-2
#include <stdio.h>

int main() {
    for (int i = 0; i < 10; i++) {
        printf("0");
        char a[0];
        scanf("%c", a);
    }
}

I write this code and for every char in input, it loops an extra time without scanning again. So bash shows:

0 [i input '1', then:]
0011
000111
0000

Then loop terminates. It is like it saves the chars in scanf buffer and removes one by one each loop, rereading them extra. But why?

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • 4
    How much memory do you think is reserved by `char a[0];` (even if the compiler allows it)? Following from that, where do you think the input from `scanf("%c", a);` will be stored? – Weather Vane Jan 07 '22 at 00:34
  • Do please learn to use spaces and (especially) indentation to improve your code's readability. I've helped you out this time. – John Bollinger Jan 07 '22 at 00:38
  • Please see [What happens if I define a 0-size array?](https://stackoverflow.com/questions/9722632/what-happens-if-i-define-a-0-size-array-in-c-c) – Weather Vane Jan 07 '22 at 00:41
  • 1
    Think about it: when you "input '1'", what are your exact keypresses? – John Bollinger Jan 07 '22 at 00:41

1 Answers1

2

First of all, your code has the following serious problem:

You are not allocating sufficient space for scanf to write a character. Passing an insufficiently large memory buffer to scanf causes undefined behavior.

You should change char a[0]; to char a[1];, or better: Simply write char a; and change scanf("%c", a); to scanf("%c", &a);.

Now, to answer your actual question:

You are not taking into account that the newline character '\n' is also part of the input. It is this character that you are registering as an additional character.

If you want the newline character to be discarded, then you could change

scanf( "%c", &a );

to:

scanf( " %c", &a );

This will cause scanf to discard all whitespace characters (i.e. spaces, tabs, newlines, etc.) before attempting to match a character. That way, scanf will never match a newline character (or any other whitespace character).

If you only want newline characters to be discarded, but not spaces and other whitespace characters, then you can use these lines instead:

//discard any newline characters
scanf( "%*[\n]" );

//read the actual input
scanf( "%c", &a );

Note that in the code above, it is necessary to have two separate scanf function calls. You cannot combine them like this:

//read the actual input
scanf( "%*[\n]%c", &a );

The reason why you cannot do this is that the %[] conversion format specifier will only match a non-empty character sequence. Therefore, matching will fail if there are no newline characters. In the line scanf( "%*[\n]" );, it does not matter whether matching succeeds or fails, but in the line scanf( "%*[\n]%c", &a );, it does matter, because scanf won't attempt to match the second conversion format specifier if matching the first one fails.

See the documentation for the function scanf for further information.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39