The following code produces a very strange result when I run it.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
for ( ; ; )
{
char test;
printf("Please enter 'w' ");
scanf("%c", &test);
printf("%c\n", test);
if (test == 'w')
{
printf("Working\n");
}
else
{
printf("ERROR\n");
return 0;
}
}
}
What I want to happen is for the whenever I input 'w' it continues the loop so I can input 'w' again. What it does though is go to the else statement even though I input 'w'. It just seems to skip the scanf() line. I have asked everyone I know who knows C but they do not know how to solve it.
Somebody please help me out here!
This is because you type w followed by ENTER. So there are 2 characters in the input, 'w', followed by a newline (\n). The latter causes the else branch to be taken on the second iteration.
Note that standard input is line buffered when connected to a terminal. If you need to deal with characters immediately, there are ways to do that. See the comp.lang.c FAQ for details ("How can I read a single character from the keyboard without waiting for the RETURN key? How can I stop characters from being echoed on the screen as they're typed?").
Note that for robust programming it is a must to check the return value of scanf. It returns the number of successfully converted items. As shown, your code does not handle the case of end-of-file properly, i.e. when the user types Ctrl-D (assuming Unix terminal). Then scanf returns EOF and no conversion was performed, but you use test as if it contained a meaningful value.
as Jens said. you have to ignore the newline '\n'
Adding a space at the beginning of the format specifier " %c" will ignore the newline '\n'
scanf(" %c", &test);
Using " %c" will also ignore other white spaces like \t space \b \v \r
As Jens says, you must consume '\n', use getchar() after scanf()
You need to do something like
scanf("%c", &test);
while(getchar()!='\n');
scanf takes input upto space or \n (whichever comes first) and leaves the \n in the buffer
Related
This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 6 years ago.
I have this block of code (functions omitted as the logic is part of a homework assignment):
#include <stdio.h>
int main()
{
char c = 'q';
int size;
printf("\nShape (l/s/t):");
scanf("%c",&c);
printf("Length:");
scanf("%d",&size);
while(c!='q')
{
switch(c)
{
case 'l': line(size); break;
case 's': square(size); break;
case 't': triangle(size); break;
}
printf("\nShape (l/s/t):");
scanf("%c",&c);
printf("\nLength:");
scanf("%d",&size);
}
return 0;
}
The first two Scanf's work great, no problem once we get into the while loop, I have a problem where, when you are supposed to be prompted to enter a new shape char, it instead jumps down to the printf of Length and waits to take input from there for a char, then later a decimal on the next iteration of the loop.
Preloop iteration:
Scanf: Shape. Works Great
Scanf: Length. No Problem
Loop 1.
Scanf: Shape. Skips over this
Scanf: length. Problem, this scanf maps to the shape char.
Loop 2
Scanf: Shape. Skips over this
Scanf: length. Problem, this scanf maps to the size int now.
Why is it doing this?
scanf("%c") reads the newline character from the ENTER key.
When you type let's say 15, you type a 1, a 5 and then press the ENTER key. So there are now three characters in the input buffer. scanf("%d") reads the 1 and the 5, interpreting them as the number 15, but the newline character is still in the input buffer. The scanf("%c") will immediately read this newline character, and the program will then go on to the next scanf("%d"), and wait for you to enter a number.
The usual advice is to read entire lines of input with fgets, and interpret the content of each line in a separate step. A simpler solution to your immediate problem is to add a getchar() after each scanf("%d").
The basic problem is that scanf() leaves the newline after the number in the buffer, and then reads it with %c on the next pass. Actually, this is a good demonstration of why I don't use scanf(); I use a line reader (fgets(), for example) and sscanf(). It is easier to control.
You can probably rescue it by using " %c" instead of "%c" for the format string. The blank causes scanf() to skip white space (including newlines) before reading the character.
But it will be easier in the long run to give up scanf() and fscanf() and use fgets() or equivalent plus sscanf(). All else apart, error reporting is much easier when you have the whole string to work with, not the driblets left behind by scanf() after it fails.
You should also, always, check that you get a value converted from scanf(). Input fails — routinely and horribly. Don't let it wreck your program because you didn't check.
Try adding a space in the scanf.
scanf(" %d", &var);
// ^
// there
This will cause scanf() to discard all whitespace before matching an integer.
Use the function
void seek_to_next_line( void )
{
int c;
while( (c = fgetc( stdin )) != EOF && c != '\n' );
}
to clear out your input buffer.
The '\n' character is still left on the input stream after the first call to scanf is completed, so the second call to scanf() reads it in. Use getchar().
When you type the shape and ENTER, the shape is consumed by the first scanf, but the ENTER is not! The second scanf expects a number so, the ENTER is skipped because is considered a white space, and the scanf waits for a valid input ( a number) that, again, is terminated by the ENTER. Well, the number is consumed, but the ENTER is not, so the first scanf inside the while uses it and your shape prompt is skipped... this process repeats. You have to add another %c in the scanfs to deal with the ENTER key. I hope this helps!
You can also use
scanf("%c%*c", &c);
to read two characters and ignore the last one (in this case '\n')
The following code produces a very strange result when I run it.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
for ( ; ; )
{
char test;
printf("Please enter 'w' ");
scanf("%c", &test);
printf("%c\n", test);
if (test == 'w')
{
printf("Working\n");
}
else
{
printf("ERROR\n");
return 0;
}
}
}
What I want to happen is for the whenever I input 'w' it continues the loop so I can input 'w' again. What it does though is go to the else statement even though I input 'w'. It just seems to skip the scanf() line. I have asked everyone I know who knows C but they do not know how to solve it.
Somebody please help me out here!
This is because you type w followed by ENTER. So there are 2 characters in the input, 'w', followed by a newline (\n). The latter causes the else branch to be taken on the second iteration.
Note that standard input is line buffered when connected to a terminal. If you need to deal with characters immediately, there are ways to do that. See the comp.lang.c FAQ for details ("How can I read a single character from the keyboard without waiting for the RETURN key? How can I stop characters from being echoed on the screen as they're typed?").
Note that for robust programming it is a must to check the return value of scanf. It returns the number of successfully converted items. As shown, your code does not handle the case of end-of-file properly, i.e. when the user types Ctrl-D (assuming Unix terminal). Then scanf returns EOF and no conversion was performed, but you use test as if it contained a meaningful value.
as Jens said. you have to ignore the newline '\n'
Adding a space at the beginning of the format specifier " %c" will ignore the newline '\n'
scanf(" %c", &test);
Using " %c" will also ignore other white spaces like \t space \b \v \r
As Jens says, you must consume '\n', use getchar() after scanf()
You need to do something like
scanf("%c", &test);
while(getchar()!='\n');
scanf takes input upto space or \n (whichever comes first) and leaves the \n in the buffer
I'm trying to develop a simple text-based hangman game, and the main game loop starts with a prompt to enter a guess at each letter, then goes on to check if the letter is in the word and takes a life off if it isn't. However, when I run the game the prompt comes up twice each time, and the program doesn't wait for the user's input. It also takes off a life (one life if it was the right input, two if it wasn't), so whatever it's taking in isn't the same as the previous input. Here's my game loop, simplified a bit:
while (!finished)
{
printf("Guess the word '%s'\n",covered);
scanf("%c", ¤tGuess);
i=0;
while (i<=wordLength)
{
if (i == wordLength)
{
--numLives;
printf("Number of lives: %i\n", numLives);
break;
} else if (currentGuess == secretWord[i]) {
covered[i] = secretWord[i];
secretWord[i] = '*';
break;
}
++i;
}
j=0;
while (j<=wordLength)
{
if (j == (wordLength)) {
finished = 1;
printf("Congratulations! You guessed the word!\n");
break;
} else {
if (covered[j] == '-') {
break;
}
}
++j;
if (numLives == 0) {
finished = 1;
}
}
}
I assume the problem is scanf thinking it's taken something in when it hasn't, but I have no idea why. Does anyone have any idea? I'm using gcc 4.0.1 on Mac OS X 10.5.
When you read keyboard input with scanf(), the input is read after enter is pressed but the newline generated by the enter key is not consumed by the call to scanf(). That means the next time you read from standard input there will be a newline waiting for you (which will make the next scanf() call return instantly with no data).
To avoid this, you can modify your code to something like:
scanf("%c%*c", ¤tGuess);
The %*c matches a single character, but the asterisk indicates that the character will not be stored anywhere. This has the effect of consuming the newline character generated by the enter key so that the next time you call scanf() you are starting with an empty input buffer.
Caveat: If the user presses two keys and then presses enter, scanf() will return the first keystroke, eat the second, and leave the newline for the next input call. Quirks like this are one reason why scanf() and friends are avoided by many programmers.
Newlines.
The first time through the loop, scanf() reads the character.
Then it reads the newline.
Then it reads the next character; repeat.
How to fix?
I seldom use scanf(), but if you use a format string "%.1s", it should skip white space (including newlines) and then read a non-white space character. However, it will be expecting a character array rather than a single character:
char ibuff[2];
while ((scanf("%.1s", ibuff) == 1)
{
...
}
Break the problem up into smaller parts:
int main(void) {
char val;
while (1) {
printf("enter val: ");
scanf("%c", &val);
printf("got: %d\n", val);
}
}
The output here is:
enter val: g
got: 103
enter val: got: 10
Why would scanf give you another '10' in there?
Since we printed the ASCII number for our value, '10' in ASCII is "enter" so scanf must also grab the "enter" key as a character.
Sure enough, looking at your scanf string, you are asking for a single character each time through your loop. Control characters are also considered characters, and will be picked up. For example, you can press "esc" then "enter" in the above loop and get:
enter val: ^[
got: 27
enter val: got: 10
Just a guess, but you are inputting a single character with scanf, but the user must type the guess plus a newline, which is being consumed as a separate guess character.
scanf(" %c", &fooBar);
Notice the space before the %c. This is important, because it matches all preceding whitespace.
Jim and Jonathan have it right.
To get your scanf line to do what you want (consume the newline character w/o putting it in the buffer) I'd change it to
scanf("%c\n", ¤tGuess);
(note the \n)
The error handling on this is atrocious though. At the least you should check the return value from scanf against 1, and ignore the input (with a warning) if it doesn't return that.
A couple points I noticed:
scanf("%c") will read 1 character and keep the ENTER in the input buffer for next time through the loop
you're incrementing i even when the character read from the user doesn't match the character in secretWord
when does covered[j] ever get to be '-'?
I'll guess: your code is treating a newline as one of the guesses when you enter data. I've always avoided the *scanf() family due to uncontrollable error handling. Try using fgets() instead, then pulling out the first char/byte.
I see a couple of things in your code:
scanf returns the number of items it read. You will probably want to handle the cases where it returns 0 or EOF.
My guess would be that the user is hitting letter + Enter and you're getting the newline as the second character. An easy way to check would be to add a debugging printf statement to show what character was entered.
Your code will only match the first occurrence of a match letter, i.e. if the word was "test" and the user entered 't', your code would only match the first 't', not both. You need to adjust your first loop to handle this.
When you enter the character, you have to enter a whitespace character to move on. This whitespace character is present in the input buffer, stdin file, and is read by the scanf() function.
This problem can be solved by consuming this extra character. This can be done by usnig a getchar() function.
scanf("%c",¤tGuess);
getchar(); // To consume the whitespace character.
I would rather suggest you to avoid using scanf() and instead use getchar(). The scanf()requires a lot of memory space. getchar() is a light function. So you can also use-
char currentGuess;
currentGuess=getchar();
getchar(); // To consume the whitespace character.
The following code produces a very strange result when I run it.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
for ( ; ; )
{
char test;
printf("Please enter 'w' ");
scanf("%c", &test);
printf("%c\n", test);
if (test == 'w')
{
printf("Working\n");
}
else
{
printf("ERROR\n");
return 0;
}
}
}
What I want to happen is for the whenever I input 'w' it continues the loop so I can input 'w' again. What it does though is go to the else statement even though I input 'w'. It just seems to skip the scanf() line. I have asked everyone I know who knows C but they do not know how to solve it.
Somebody please help me out here!
This is because you type w followed by ENTER. So there are 2 characters in the input, 'w', followed by a newline (\n). The latter causes the else branch to be taken on the second iteration.
Note that standard input is line buffered when connected to a terminal. If you need to deal with characters immediately, there are ways to do that. See the comp.lang.c FAQ for details ("How can I read a single character from the keyboard without waiting for the RETURN key? How can I stop characters from being echoed on the screen as they're typed?").
Note that for robust programming it is a must to check the return value of scanf. It returns the number of successfully converted items. As shown, your code does not handle the case of end-of-file properly, i.e. when the user types Ctrl-D (assuming Unix terminal). Then scanf returns EOF and no conversion was performed, but you use test as if it contained a meaningful value.
as Jens said. you have to ignore the newline '\n'
Adding a space at the beginning of the format specifier " %c" will ignore the newline '\n'
scanf(" %c", &test);
Using " %c" will also ignore other white spaces like \t space \b \v \r
As Jens says, you must consume '\n', use getchar() after scanf()
You need to do something like
scanf("%c", &test);
while(getchar()!='\n');
scanf takes input upto space or \n (whichever comes first) and leaves the \n in the buffer
I'm trying to develop a simple text-based hangman game, and the main game loop starts with a prompt to enter a guess at each letter, then goes on to check if the letter is in the word and takes a life off if it isn't. However, when I run the game the prompt comes up twice each time, and the program doesn't wait for the user's input. It also takes off a life (one life if it was the right input, two if it wasn't), so whatever it's taking in isn't the same as the previous input. Here's my game loop, simplified a bit:
while (!finished)
{
printf("Guess the word '%s'\n",covered);
scanf("%c", ¤tGuess);
i=0;
while (i<=wordLength)
{
if (i == wordLength)
{
--numLives;
printf("Number of lives: %i\n", numLives);
break;
} else if (currentGuess == secretWord[i]) {
covered[i] = secretWord[i];
secretWord[i] = '*';
break;
}
++i;
}
j=0;
while (j<=wordLength)
{
if (j == (wordLength)) {
finished = 1;
printf("Congratulations! You guessed the word!\n");
break;
} else {
if (covered[j] == '-') {
break;
}
}
++j;
if (numLives == 0) {
finished = 1;
}
}
}
I assume the problem is scanf thinking it's taken something in when it hasn't, but I have no idea why. Does anyone have any idea? I'm using gcc 4.0.1 on Mac OS X 10.5.
When you read keyboard input with scanf(), the input is read after enter is pressed but the newline generated by the enter key is not consumed by the call to scanf(). That means the next time you read from standard input there will be a newline waiting for you (which will make the next scanf() call return instantly with no data).
To avoid this, you can modify your code to something like:
scanf("%c%*c", ¤tGuess);
The %*c matches a single character, but the asterisk indicates that the character will not be stored anywhere. This has the effect of consuming the newline character generated by the enter key so that the next time you call scanf() you are starting with an empty input buffer.
Caveat: If the user presses two keys and then presses enter, scanf() will return the first keystroke, eat the second, and leave the newline for the next input call. Quirks like this are one reason why scanf() and friends are avoided by many programmers.
Newlines.
The first time through the loop, scanf() reads the character.
Then it reads the newline.
Then it reads the next character; repeat.
How to fix?
I seldom use scanf(), but if you use a format string "%.1s", it should skip white space (including newlines) and then read a non-white space character. However, it will be expecting a character array rather than a single character:
char ibuff[2];
while ((scanf("%.1s", ibuff) == 1)
{
...
}
Break the problem up into smaller parts:
int main(void) {
char val;
while (1) {
printf("enter val: ");
scanf("%c", &val);
printf("got: %d\n", val);
}
}
The output here is:
enter val: g
got: 103
enter val: got: 10
Why would scanf give you another '10' in there?
Since we printed the ASCII number for our value, '10' in ASCII is "enter" so scanf must also grab the "enter" key as a character.
Sure enough, looking at your scanf string, you are asking for a single character each time through your loop. Control characters are also considered characters, and will be picked up. For example, you can press "esc" then "enter" in the above loop and get:
enter val: ^[
got: 27
enter val: got: 10
Just a guess, but you are inputting a single character with scanf, but the user must type the guess plus a newline, which is being consumed as a separate guess character.
scanf(" %c", &fooBar);
Notice the space before the %c. This is important, because it matches all preceding whitespace.
Jim and Jonathan have it right.
To get your scanf line to do what you want (consume the newline character w/o putting it in the buffer) I'd change it to
scanf("%c\n", ¤tGuess);
(note the \n)
The error handling on this is atrocious though. At the least you should check the return value from scanf against 1, and ignore the input (with a warning) if it doesn't return that.
A couple points I noticed:
scanf("%c") will read 1 character and keep the ENTER in the input buffer for next time through the loop
you're incrementing i even when the character read from the user doesn't match the character in secretWord
when does covered[j] ever get to be '-'?
I'll guess: your code is treating a newline as one of the guesses when you enter data. I've always avoided the *scanf() family due to uncontrollable error handling. Try using fgets() instead, then pulling out the first char/byte.
I see a couple of things in your code:
scanf returns the number of items it read. You will probably want to handle the cases where it returns 0 or EOF.
My guess would be that the user is hitting letter + Enter and you're getting the newline as the second character. An easy way to check would be to add a debugging printf statement to show what character was entered.
Your code will only match the first occurrence of a match letter, i.e. if the word was "test" and the user entered 't', your code would only match the first 't', not both. You need to adjust your first loop to handle this.
When you enter the character, you have to enter a whitespace character to move on. This whitespace character is present in the input buffer, stdin file, and is read by the scanf() function.
This problem can be solved by consuming this extra character. This can be done by usnig a getchar() function.
scanf("%c",¤tGuess);
getchar(); // To consume the whitespace character.
I would rather suggest you to avoid using scanf() and instead use getchar(). The scanf()requires a lot of memory space. getchar() is a light function. So you can also use-
char currentGuess;
currentGuess=getchar();
getchar(); // To consume the whitespace character.