简体   繁体   中英

Accessing data in a nested structure using pointers

I am doing an assignment which requires me to write a code that contains a nested structure. The problem is actually pretty simple. Just to obtain coordinates of the corners of a rectangle. I have been researching online but most examples are without the typedef structure. My problem is mainly being unsure of what is the correct syntax to access and store the data. I have the structure templates as follows:

typedef struct
{
    double x;
    double y;
} Point; // Create a Point datatype;
typedef struct // nested structure
{
    Point topLeft; // topLeft is the variable name for "Point" structure with x&y property
    Point botRight; // botRight is the variable name for "Point" structure with x&y property
} Rectangle; // Create a Rectangle datatype with Point structure within
void getRect(Rectangle *r); // function prototype
int main()
{
Rectangle r; // initializing rectangle;
getRect(&r); // call function to get inputs using call by reference
}

void getRect(Rectangle *r)
{
    printf("Enter top left points:\n");
    scanf("%lf %lf", r->topLeft.x,r->topLeft.y); // Not sure if this is correct as my program can compile and run up till this point and crashes.
    printf("Enter bottom right points:\n");
    scanf("%lf %lf", r->botRight.x,r->botRight.y);
}

Seeking everyone's kind guidance on this matter!

The problem is that the arguments of the calls of scanf shall be pointers. For example

scanf("%lf %lf", &r->topLeft.x, &r->topLeft.y);

and

scanf("%lf %lf", &r->botRight.x, &r->botRight.y);

That is you need to pass objects x and y by reference that the function scanf could deal with the original objects instead of copies of their values.

In C passing by reference means passing objects indirectly through pointers to them. In this case the called function can get a direct access to the objects by using the dereferencing operation of the pointers.

scanf() does not allocate memory so you have always to pass addresses where the function can place the data for each specifier, those things like %d or %lf . So in your case you must pass the address of each double field using, well, the address of operator, &

Always test the return of scanf() . There is no reason to continue on reading data if you could not get one of the points

Avoiid this type of comment:

    void getRect(Rectangle *r); // function prototype

Is is fairly obvious that this is a prototype. There a few of these comments in your code. Prefer to use comments that describe uses, parameters, arguments, algorithms...

an example

The small program below declares your structures in some usual ways, including a function to return a Rectangle for each call and one to print the data out. It is usual for testing. It is just an example. I am not telling it is good or best or anything.

for the SO Police : I always cast the pointer to malloc() because, well, I do.

#include    <stdio.h>
#include    <stdlib.h>

typedef struct
{
    double x;
    double y;

}   Point;


typedef struct
{
    Point tL; // top left
    Point bR; // bottom right

}   Rectangle;

Rectangle*  rFactory();
int         showR(Rectangle*);

int         main(void)
{
    Point   A = { 2., 3. };

    Point   B = 
    {
        .y = 3.4,
        .x = 0.
    };

    Point*  pP = &A;
    printf( "Point is (%lf,%lf)\n", pP->x, pP->y ); // using pointer
    printf( "Point is (%lf,%lf)\n", A.x, A.y ); // using data directly

    Rectangle   R0 = { A,B };

    Rectangle   R1 =
    {
        {
            .x = 0.,
            .y = 2.
        },  // tL

        {  3.,4. } // bR
    };

    Rectangle   R2 = 
    {
        .bR = { 1.,2. },
        .tL = { -4.,-5 }
    };

    Rectangle*  pR = &R0;
    pR = &R1;
    pR = &R2; // :) just to get rid of the unused-var warnings 
    printf( "(via pointer) Rectangle is [(%lf,%lf), (%lf,%lf)]\n",
        pR->tL.x, pR->tL.y,
        pR->bR.x, pR->bR.y ); // using pointer
    printf( "(via data) Rectangle is [(%lf,%lf), (%lf,%lf)]\n",
        R2.tL.x, R2.tL.y,
        R2.bR.x, R2.bR.y ); // using data directly

    R2.bR.x = 0.;
    R2.bR.y = 0.;
    printf( "(Changed bR) Rectangle is [(%lf,%lf), (%lf,%lf)]\n",
        pR->tL.x, pR->tL.y,
        pR->bR.x, pR->bR.y ); // using pointer

    printf( "(Using function)\n\n");
    showR( &R2);

    // using a 'factory function gets a new one
    printf( "\n\n(Using factory function)\n\n");
    Rectangle*  other = rFactory();
    showR( other );
    free(other); // this one was allocated

    return 0;

}


Rectangle*  rFactory()
{
    Rectangle* one = (Rectangle*) malloc(sizeof(Rectangle));
    if ( one == NULL ) return NULL; // could not alloc
    int res = 0;

    printf("\
\tEnter points like '3., -2.3' separated by at least one space\
\n\tTop Left point: ");
    res = scanf("%lf %lf", &one->tL.x,&one->tL.y);
    if ( res != 2 )
    {
        free(one);
        return NULL;
    };  // if()

    printf("\
\n\tBottom Right point: ");
    res = scanf("%lf %lf", &one->bR.x,&one->bR.y);
    if ( res != 2 )
    {
        free(one);
        return NULL;
    };  // if()
    
    return one;
};


int     showR( Rectangle* pR)
{
    if ( pR == NULL ) return -1;
    printf( "\n\t[using showR()] Rectangle is [(%lf,%lf), (%lf,%lf)]\n",
        pR->tL.x, pR->tL.y,
        pR->bR.x, pR->bR.y ); // using pointer
    return 0;
}

the output

PS C:\src\bases> gcc -o tst -std=c17 -Wall sh.c
PS C:\src\bases> ./tst
Point is (2.000000,3.000000)
Point is (2.000000,3.000000)
(via pointer) Rectangle is [(-4.000000,-5.000000), (1.000000,2.000000)]
(via data) Rectangle is [(-4.000000,-5.000000), (1.000000,2.000000)]
(Changed bR) Rectangle is [(-4.000000,-5.000000), (0.000000,0.000000)]
(Using function)


        [using showR()] Rectangle is [(-4.000000,-5.000000), (0.000000,0.000000)]


(Using factory function)

        Enter points like '3., -2.3' separated by at least one space
        Top Left point: 1. 2.

        Bottom Right point: 3. 4.

        [using showR()] Rectangle is [(1.000000,2.000000), (3.000000,4.000000)]
PS C:\src\bases>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM