Search code examples
cscanf

Why doesn't scanf with character set format read input in a for loop?


While trying to get newline character as input using scanf and display it as output as this discussion suggests, I tried the following code,

#include <stdio.h>
void main()
{
    int n;
    printf("Loop:\n");

    scanf("%d",&n);
    for (int i = 0; i < n; ++i)
    {
        char in[28];
        scanf("%27[^\n]%*c",&in);
        printf("%s\n",in);
    }
}

During execution, inside the for loop the input stream doesn't accept any inputs and instead displays n smiley faces. Is this because of the trailing newline character after reading n?


Solution

  • Beyond the type mismatch, the reason scanf("%27[^\n]%*c",&in); does not read extra input from the user is there is a pending newline left by scanf("%d",&n);. scanf() fails because there is no match for the character set and the newline is not consumed by %*c because the previous mismatch stops the scan.

    Here is a modified version:

    #include <stdio.h>
    
    int flush_input(void) {
        int c;
        while ((c = getchar()) != EOF && c != '\n')
            continue;
        return c;
    }
    
    int main() {
        int n;
        printf("Loop:\n");
    
        if (scanf("%d", &n) != 1)
            return 1;
    
        flush_input();
        for (int i = 0; i < n; ++i) {
            char in[28];
            if (scanf("%27[^\n]", in) != 1) {
                // blank line or EOF
                *in = '\0';
            }
            printf("%s\n", in);
            if (flush_input() == EOF)
                break;
        }
        return 0;
    }