问题
I'm currently learning C and C++ on my own. In this little "program practice" I ask the user to enter either 'i' or 'd' to know whether they want to work with integers or decimal (float) numbers. I have a while loop that makes sure the user enter 'i' or 'd' by telling them if they entered the wrong char. For some reason, the prompt inside the while loop prints two times before going to the getchar(). I'm having a bit of hard time understanding what's happening under the hood in this situation. Any help is super appreciated. I'm using Xcode (don't know if it's relevant).
#include <stdio.h>
int main()
{
char action;
printf("Please enter 'i' to work with integers or 'd' to work with decimals.\n\n");
scanf("%c", &action);
while (action != 'i' || action != 'd')
{
printf("You didn't entered the right command. Please try again (i/d)\n");
action = getchar()
}
}
So what I'm getting as an output is this:
You didn't entered the right command. Please try again (i/d)
You didn't entered the right command. Please try again (i/d)
回答1:
What is happening is that when you enter a character and hit a return, you are actually entering two characters - the character and the return character ('\n'). The loop executes once for each character. Which is why you see it go through twice.
The trick is to filter out the return character explicitly, like so:
#include <stdio.h>
int main()
{
char action;
printf("Please enter 'i' to work with integers or 'd' to work with decimals.\n\n");
scanf("%c", &action);
while (action != 'i' || action != 'd')
{
if (action != '\n')
{
printf("You didn't entered the right command. Please try again (i/d)\n");
}
action = getchar();
}
}
回答2:
As correctly diagnosed by Ziffusion in his answer, you get the double prompt because you get the newline after the user's incorrect input as a separate character, and that too is neither i
nor d
.
Here is a rewrite with some improvements:
#include <stdio.h>
int main(void)
{
char action = '\0';
printf("Please enter 'i' to work with integers or 'd' to work with decimals: ");
while (scanf(" %c", &action) == 1 && action != 'i' && action != 'd')
printf("You didn't enter the right command. Please try again (i/d): ");
printf("Action selected: %d\n", action);
}
What's changed?
The prompt doesn't end with a newline, so the user's response appears immediately after it. Standard I/O normally synchronizes standard output and standard input so that the prompt will be flushed, despite not ending with a newline. If the prompt doesn't appear, you can add a
fflush(stdout);
orfflush(0);
after each of the promptingprintf()
statements.The result of
scanf()
is checked to deal with EOF.The format of
scanf()
includes a leading space. This will skip white space before the character that's returned, so you get a non-blank, non-newline character.The original condition
action != 'i' || action != 'd'
is always true; you need the&&
instead.Nitpick: improve grammar of error message.
Note that after the loop, action might not be either i
or d
if the user triggered EOF (typed Control-D or equivalent). If you get EOF (for example, the user ran the program with standard input from /dev/null
), you would not have a deterministic value in action
except for the initialization to '\0'
.
回答3:
Here I fixed you code:
#include <stdio.h>
int main()
{
char action;
printf("Please enter 'i' to work with integers or 'd' to work with decimals.\n\n");
scanf("%c", &action);
while (action != 'i' && action != 'd') // here the loop will stop if action is 'i' or 'd'
{
printf("You didn't entered the right command. Please try again (i/d)\n");
scanf("\n%c", &action);// here to deal with '\n'
}
}
来源:https://stackoverflow.com/questions/17892383/while-loops-duplicates-printf-two-times-before-getting-to-getchar