I am writing an application with a menu and I am asking the user to provide an integer representing an option from the menu
1. Option 1
2. Option 2
3. Option 3
...
This option is stored in a variable called
option
I want to avoid wrong input such as "12a", "1a2", "anyString" and I've read that this can be achieved by storing return value of scanf_s() function.
So I stored it in a variable called
ret
and now I want that every time user provides wrong input to prompt them to enter a new value.
So I wrote something like this:
int ret = scanf_s("%d", &option);
while (!ret)
{
cout << "Provide an integer, not a string! :)\n";
ret = scanf_s("%d", &option);
}
The problem is when it enters the while it is not allowing user to enter a new value and hence the value of ret
never changes, making it run endlessly.
How can I achieve what I am looking for?
CodePudding user response:
When scanf_s
fails to convert an integer, the offending input stays in the input stream. Calling scanf_s("%d", &option)
again will produce the same result until some characters are removed from the input stream. Note also that using scanf_s
or scanf
directly from stdin
is error prone: the newline entered by the user stays in the input stream and will be read by a subsequent call to getchar()
or fgets()
, potentially causing unexpected behavior.
To avoid these pitfalls, it is recommended to read one line at a time with fgets()
and convert it with sscanf()
this way:
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
int main() {
char buf[80];
int option;
char cc;
for (;;) {
print_menu(); // output the menu options
if (!fgets(buf, sizeof buf, stdin)) {
/* end of file reached: break from the loop */
break;
}
/* parse exactly one integer with optional leading and trailing whitespace */
if (sscanf(buf, "%d %c", &option, &cc) != 1) {
printf("invalid input: %s", buf);
printf("enter one integer exactly\n");
continue;
}
printf("option is %d\n", option);
// handle option
}
return 0;
}