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

Time:06-23

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("'[^\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?

CodePudding user response:

Beyond the type mismatch, the reason scanf("'[^\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("'[^\n]", in) != 1) {
            // blank line or EOF
            *in = '\0';
        }
        printf("%s\n", in);
        if (flush_input() == EOF)
            break;
    }
    return 0;
}

CodePudding user response:

How to compile any C program as a beginner: What compiler options are recommended for beginners learning C?

Following this advise and compiling with gcc gives 2 problems:

<source>:2:6: error: return type of 'main' is not 'int' [-Wmain]
    2 | void main()
      |      ^~~~
<source>: In function 'main':
<source>:11:21: error: format '%[^
   ' expects argument of type 'char *', but argument 2 has type 'char (*)[28]' [-Werror=format=]
   11 |         scanf("'[^\n]%*c",&in);
      |                ~~~~~^~      ~~~
      |                     |       |
      |                     char *  char (*)[28]
  • The first reported error is because void main() is an implementation-defined form of main() which isn't suitable for gcc unless you explicitly compile for embedded systems or the like. Switch to int main (void).

  • The second reported error says that the conversion %c expected a parameter of type char*. You gave it a parameter of type char (*)[28]. Huh, what is that? Well, it is a pointer to an array of 28 char. Not the same thing and not what you want, but what you get if you do &in instead of in.

Luckily, viewing multiple lines of the gcc output gives you the exact location of the bug, after which you will find the bug in seconds:

   11 |         scanf("'[^\n]%*c",&in);
      |                ~~~~~^~      ~~~
      |                     |       |
      |                     expect  BUG HERE FIX ME

Now if you follow the above guidelines, you should be able fix the next trivial bug that the compiler has already found.

  • Related