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>