If I understand what you are doing, and you need to determine the lower-left coordinates and the width and height of a bounding box to surround the x, y coordinates entered by the user, then you do not need an array at all. All you need do is keep track of the lower-left and lower-right coordinates and use a couple of temporary double
values to capture the max x, y coordinates entered by the user and then your width and height can be set by subtracting the lower-left coordinates from the max values.
(note: you may need to adjust your comparisons based on whether you are using a normal Cartesian coordinate system (x, y are 0 at the center) or Screen coordinates (x, y are 0 at top-left of screen). We will leave that to you)
You cannot use any input function correctly unless you check the return. scanf()
returns the number of successful conversions that take place based on the conversion-specifiers you include in the format-string. It can return less than the total if EOF
is encountered before all conversions take place or if a matching-failure occurs. (e.g. users enters "banana"
instead of a coordinate). When a matching failure occurs, character extraction from stdin
ceases and the characters causing the failure are left in stdin
unread. (just waiting to bite you on your next attempted input).
scanf()
returns EOF
on an input-failure (EOF
encountered before the first successful conversion takes place). In addition to a matching or input failure, you must also handle additional or extraneous characters entered by the user beyond what you ask for (e.g. the user enters "10.2 13.8 and other nonsense"
. Otherwise a matching failure will occur on the next input attempt.
For further detail on the conditions you must check every time scanf()
is called, the the answer to this question C For loop skips first iteration and bogus number from loop scanf.
Implementing your bounding box function along with the needed validations is fairly straight-forward. However, ending the input is a bit tricky with scanf()
. In order to avoid setting some MagicNumbers for the user to enter to signify done, the user should generate a Manual EOF
by pressing Ctrl + d (or Ctrl + z on windows). Then you can process the EOF
normally while still retaining the full range of possible inputs. (note: using the recommended method of input fgets()/sscanf()
, the user need only press Enter on an empty line to indicate they are done)
With that in mind, you can implement your function as follows:
#include <float.h> /* for `DBL_MAX` macro */
...
void readPointsFindBoundingBox (double *bottomLeftX, double *bottomLeftY,
double *widthp, double *heightp)
{
/* temp values for parameters, initialized to max/min of range */
double x = DBL_MAX, y = DBL_MAX, x_max = DBL_MIN, y_max = DBL_MIN;
*bottomLeftX = *bottomLeftY = DBL_MAX; /* initialize parameter values */
*widthp = *heightp = 0;
puts ("Press Ctrl+D (or Ctrl+z on windows twice) when done\n");
for (;;) { /* loop continually taking input */
int rtn; /* variable to save scanf() return */
fputs ("Enter coordinates (\"X Y\"): ", stdout); /* prompt for coordinates */
rtn = scanf ("%lf %lf", &x, &y); /* read input, save return */
if (rtn == EOF) { /* check if user done */
puts ("(input done)");
break;
}
/* empty remaining characters from stdin */
for (int c = getchar(); c != '\n'; c = getchar()) {}
/* validate EVERY user-input. 2 valid conversions required. */
if (rtn != 2) { /* handle matching-failure */
fputs (" error: invalid double values.\n", stderr);
continue;
}
if (x < *bottomLeftX) /* set bottomLeftX/Y as minimum coordinate */
*bottomLeftX = x; /* assumes lower-left is minimum coordinate */
if (y < *bottomLeftY) /* adjust '>' if Y increases as you go down */
*bottomLeftY = y;
if (x > x_max) /* track maximum bounding coordinates */
x_max = x; /* to calculate width, height */
if (y > y_max) /* adjust y compare if Y increases down */
y_max = y;
}
*widthp = x_max - *bottomLeftX; /* set width and height based on */
*heightp = y_max - *bottomLeftY; /* coordinates input by user */
}
(note: this presumes the pointers double *bottomLeftX, double *bottomLeftY, double *widthp, double *heightp
are all simple double
values back in the calling function for which the address has been passed to your function)
To test your function you can write a short main()
and add #include <stdio.h>
to the top, e.g.
#include <stdio.h>
/* additional include and your function go here */
int main (void) {
double bottomleft, bottomright, width, height;
readPointsFindBoundingBox (&bottomleft, &bottomright, &width, &height);
printf ("\nBounding Box\n"
" Lower Left Coordinates (x, y): (%.2lf, %.2lf)\n"
" Height, Width (height, width): (%.2lf, %.2lf)\n",
bottomleft, bottomright, width, height);
}
Example Use/Output
$ ./bin/boundingboxfn
Press Ctrl+D (or Ctrl+z on windows twice) when done
Enter coordinates ("X Y"): 5.2 3
Enter coordinates ("X Y"): 9.1 -1
Enter coordinates ("X Y"): 2.2 3.3
Enter coordinates ("X Y"): .5 -.1
Enter coordinates ("X Y"): -1.4 8.1
Enter coordinates ("X Y"): my dog has fleas
error: invalid double values.
Enter coordinates ("X Y"): 1.1 1.1
Enter coordinates ("X Y"): 4 -2
Enter coordinates ("X Y"): (input done)
Bounding Box
Lower Left Coordinates (x, y): (-1.40, -2.00)
Height, Width (height, width): (10.50, 10.10)
If you pick through the numbers, the function does provide the correct lower-left coordinates and the width and height of the bounding box required to enclose all coordinates. (recall the earlier note about adjustments needed if you are working in Screen Coordinates instead of a normal X, Y coordinate system with X and Y increasing to the right and up, respectively)
Let me know if I understood your issue correctly, and if not, drop a comment and I can help further. Let me know if you have any questions with what is done above as well.