0

I was going through some program when i came across this.

#include<stdio.h>
void main()
{
char z;
do
{
    printf("1st line\n");
    printf("2nd line\n");
            scanf("%c",&z);

    switch(z)
    {
        case 'a':printf("this is case a\n");
            break;
        case 'b':printf("this is case b\n");
            break;
        case 'c':printf("Exit\n");
            return;
            break;
        default:
            printf("this is default\n");
            break;
    }
}while(1);

}

1st time i give an input, the output is proper. But after the first input is given and the loop starts for the second time, scanf statement isn't executed at all. The printf statements get executed though and also the default case.

1st line
2nd line
b
this is case b
1st line
2nd line
this is default
1st line
2nd line

nj-ath
  • 3,028
  • 2
  • 25
  • 41

3 Answers3

6

When you entered b for the first scanf call, you also hit . When scanf("%c", &z) processed this input, it left the newline character in the input stream.

The second set of output is due to the scanf reading the newline character that followed b. Since \n is neither a, nor b, nor c, it hits the default case.

You can fix the behavior to be more like what you expect by modifying your scanf string:

scanf(" %c", &z);

Note the space character before the %c. This will cause scanf to skip whitespace characters (including the newline) before processing the input.

jxh
  • 69,070
  • 8
  • 110
  • 193
4
  1. int main().

  2. No undefined behavior here. It's just that scanf() doesn't work how you think it does. %c consumes a character. A character. One. And it doesn't consume the newline that's left in the buffer of stdin after you hit Enter. (So "the second scanf isn't executed" is not true - it's executed and it processes whatever is left for it.) Now, the newline character isn't either one of a, b or c, so the switch statement continues execution at the default: label.


If you want to read a character from the standard input, a reliable way is:

char buf[LINE_MAX];
fgets(buf, sizeof buf, stdin);
switch (buf[0]) {
    // etc.
}

alternative:

int c = fgetc(stdin);
while (fgetc(stdin) == '\n')
    ;

Don't use scanf(). (At least not until you understand what it does.) It's evil.

  • 2
    +1, I agree that `scanf()` should generally be avoided. – jxh Jul 14 '13 at 06:42
  • 1
    @H2CO3, I tested this sample with Eclipse and gcc, and it behaves as the OP expected. Does this mean that eclipse doesn't put the `\n` in the stream? I also thought that the return key would be the problem, so I was surprised that it works. – Devolus Jul 14 '13 at 06:45
  • When running it on the console, it is as you described, so it seems that Eclipse is indeed swallowing the `\n` itself. – Devolus Jul 14 '13 at 06:47
  • @Devolus I think in this case it does. (Thanks for giving me another reason to hate IDEs, I collect those!) –  Jul 14 '13 at 06:47
1

No big problem, you just ignore to handle the '\n' input after each character, you may do it this way:

scanf("%c\n",&z);

So that you can avoid handling '\n'.

lulyon
  • 6,707
  • 7
  • 32
  • 49