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...
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;
}
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.