1

Here's a small program:

#include <stdio.h>

int main() {
  char str[21], choice[21]; int size;
  while(1){
    printf("$ ");
    fgets(str, 20, stdin);
    printf("Entered string: %s", str);
    if(str[0] == 'q') {
      printf("You sure? (y/n) ");
      scanf("%s", choice);
      if(choice[0] == 'y' || choice[0] == 'Y')
        break;
    }
  }
  return 0;
}

It reads a string using fgets(). If the string starts with a q, it confirms if the user wants to quit, and exits if the user types y.

When I run it and type q, this happens:

$ q
Entered string: q
You sure? (y/n) n
$ Entered string: 
$ 

Note the $ Entered string:. Clearly, fgets() got an empty character or something as input, even though I didn't type anything.

What's going on?

Anubhav C
  • 2,631
  • 2
  • 18
  • 23

3 Answers3

2

It because the scanf call reads a character, but leaves the newline in the buffer. So when you next time call fgets is finds that one newline character and reads it resulting in an empty line being read.

The solution is deceptively simple: Put a space after the format in the scanf call:

scanf("%s ", choice);
/*       ^    */
/*       |    */
/* Note space */

This will cause scanf to read and discard all training whitespace, including newlines.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • That can't happen for input `q`. fgets() would read the newline as well. – P.P Jul 12 '13 at 12:26
  • @KingsIndian Yes, but the question is about the case when the programs continues after the `scanf` call, which *does* leave the newline. – Some programmer dude Jul 12 '13 at 12:28
  • The explanation sounds right (why didn't I notice the newline? *facepalm*), but the solution doesn't work. After I add that space, the `scanf()` call doesn't terminate. I tried adding using `"%s\n"` too, but that doesn't terminate either. – Anubhav C Jul 12 '13 at 12:33
  • OP's question and example specifically talk about input `q`. I think the issue is elsewhere. – P.P Jul 12 '13 at 12:35
  • @Anubhav Since you are are only interested in a single character, why not scan for a single character? Try e.g. `scanf("%c ", &char_choice);`. Might work better. – Some programmer dude Jul 12 '13 at 12:35
  • @KingsIndian Yes, the question mentions `q`, but it's what happens *after* the the `q` is read that is the problem. – Some programmer dude Jul 12 '13 at 12:36
  • @JoachimPileborg: Using a char has the same problem. `scanf` doesn't terminate if I add the space, and leaves a newline in the buffer if I don't. – Anubhav C Jul 12 '13 at 12:38
  • Right. I see the mix up now. Ironically Anubhav claims this still doesn't fix the issue. That's strange. – P.P Jul 12 '13 at 12:42
  • @Anubhav That is *really* weird. It shouldn't do that in either case. – Some programmer dude Jul 12 '13 at 12:42
  • Using `getchar()` does work, though. (See other answer.) Maybe the extra character is something other than `\n`? EDIT: Nope, printing out the ASCII value shows that it's '\n' (ASCII 10). – Anubhav C Jul 12 '13 at 12:46
  • The space in the `scanf` format consumes all whitespace after the "%s" conversion succeeded. So `scanf` doesn't return before it encounters the next non-whitespace character, @Anubhav. – Daniel Fischer Jul 12 '13 at 13:57
2

As described in other answer scanf call leaves the newline in the input buffer you can also use getchar() after scanf like this :

scanf("%20s", choice);// always remember( & good) to include field width 
                      // in scanf while reading

Strings otherwise it will overwrite buffer in case of large strings `

getchar();  //this will eat up the newline 

Besides , you should also use fgets like this :

fgets(str,sizeof str, stdin); //Its better 
Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
0decimal0
  • 3,884
  • 2
  • 24
  • 39
0

Use a 'char' of a specific size char choice [1]

OR

char c[1];
c = getchar();
if(c[0] == 'y' || c[1] == 'y'){
 // DO SOMETHING
}
jackotonye
  • 3,537
  • 23
  • 31