Reputation: 10875
Well i have this code to find the paint quality of a room.
void get_room_size(char room_id, int * length, int * width) {
while (*length <= 0 && *width <= 0) {
printf("Enter length and width of room %c in feet: ", room_id);
if (scanf("%d,%d", length, width)) {
if (*length <= 0) {
printf("###Error! Length must be a positive value!\n");
}
if (*width <= 0) {
printf("###Error! Width must be a positive value!\n");
}
printf("\n");
} else {
printf("bad data");
*length = 0;
*width = 0;
}
}
}
Basically, if i enter
a,1
It will go crazy and keep looping. Whats the problem?
Upvotes: 1
Views: 2174
Reputation: 121609
Try this:
...
if (scanf("%d,%d", length, width) == 2) {
if (*length <= 0) {
printf("###Error! Length must be a positive value!\n");
}
if (*width <= 0) {
printf("###Error! Width must be a positive value!\n");
}
printf("\n");
} else {
printf("bad data");
*length = -1;
*width = -1;
}
Upvotes: 0
Reputation: 6023
You dont put & in scanf()
statement so how its read
if (scanf("%d,%d", &length, &width))
Upvotes: -1
Reputation: 881113
The reason it's going "crazy" is as follows. When scanf
fails to read in a
as a number (because it's not numeric, obviously), it won't advance the file pointer.
This is one reason why you shouldn't generally use scanf
operations, a failure can leave the file pointer in an indeterminate position (such as if you only scan in 3 of 12 items).
The other reason is that
scanf
means "scan formatted" and you would be hard pressed finding anything more unformatted than user input.
Anyway, back to the failure. Because the file pointer isn't advanced, the next time you come back to do fscanf
, it will try to read that a
again (and again and again).
If you want a decent function for handling user input, look no further than here:
#include <stdio.h>
#include <string.h>
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
This will input a line from the user, with overflow protection (unlike gets
or scanf
with unbounded "%s"
).
It also flushes to end of line if the input was too long, which will stop the remainder of the line from affecting the next input operation.
You can then sscanf
the buffer to your heart's content without any concerns re the file pointer.
The following test program shows how to use this:
int main (void) {
int rc;
char buff[10];
rc = getLine ("Enter string> ", buff, sizeof(buff));
if (rc == NO_INPUT) {
// Extra NL since my system doesn't output that on EOF.
printf ("\nNo input\n");
return 1;
}
if (rc == TOO_LONG) {
printf ("Input too long [%s]\n", buff);
return 1;
}
printf ("OK [%s]\n", buff);
return 0;
}
As an aside, you may want to re-examine your logic for a valid sized room. What you currently have would allow a room to be entered as 7 by -42 feet :-)
It's also not usually good form to rely on the output values being set to specific values on entry. If length and width are (for example) 3 and 4 on entry, this function will exit straight away without asking the user for input.
The first problem can be fixed by using ||
instead of &&
. The second by initialising the variables to 0 at the start of the function so that the loop is entered.
For completeness, if you combine that original snippet above (the include
statements and the getLine()
function) with the following slightly modified get_room_size()
function:
static void get_room_size(char room_id, int * length, int * width) {
char buff[100];
*length = *width = 0;
while ((*length <= 0) || (*width <= 0)) {
printf("Enter length and width of room %c in feet: ", room_id);
int rc = getLine (NULL, buff, sizeof (buff));
if (rc == NO_INPUT) {
printf ("\nEnd of file encountered.\n");
return;
}
if (rc == TOO_LONG) {
printf ("\nInput too long, please retry.\n");
continue;
}
if (sscanf(buff, "%d,%d", length, width) != 2) {
*length = *width = 0;
printf ("\nInput not in desired form (<number>,<number>), "
"please retry.\n");
continue;
}
if ((*length <=0) || (*width <= 0)) {
*length = *width = 0;
printf ("\nBoth length and width must be greater than zero, "
"please retry.\n");
}
}
}
and the very simple test main()
, you'll see a complete program showing how to do it.
int main (void) {
int len, wid;
get_room_size ('x', &len, &wid);
printf ("Length is %d, width is %d.\n", len, wid);
return 0;
}
Upvotes: 6
Reputation: 9
your scanf is taking in two integer. A is a character, think you want to scanf("%c", *room_id); scanf("%d", length);
I reccommend you do them separately
Upvotes: 0