1

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?

  • 2
    You must check return value of `scanf`. I assume it returns `0` because there is a pending `\n` in the input buffer from first `scanf` that does not match your format specifier. As a result `in` is not filled with any new input. – Gerhardh Jun 22 '22 at 10:25
  • 5
    Please stop trying to kludge away trailing newlines: deal with them as they arrive. With `%d` and `%f` and `%s` you don't need to. With `%c` and `%[]` just place a space before: such as `" %27[^\n]"` This will also deal the the newline from the previous scanf before the loop. Please see [scanf() leaves the newline char in the buffer](https://stackoverflow.com/questions/5240789/scanf-leaves-the-new-line-char-in-the-buffer). – Weather Vane Jun 22 '22 at 10:26
  • 2
    What is the input you are giving it, and what is the expected output? – Weather Vane Jun 22 '22 at 10:28
  • 4
    Remove the ampersand at `in` in `scanf()`. – the busybee Jun 22 '22 at 10:28
  • 3
    If you want to write portable C programs, don't make `main` "return" `void`. Make it `int main` – Ted Lyngmo Jun 22 '22 at 10:34

2 Answers2

3

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;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
2

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("%27[^\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("%27[^\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.

Lundin
  • 195,001
  • 40
  • 254
  • 396