Why is the first string ignored when reading with

2019-07-24 18:53发布

问题:

Possible Duplicate:
Dev-C++ Input skipped

I am trying to read an array of character strings from stdin using fgets, but the first string I want to read is always ignored. What is causing this issue?

#include <stdio.h>

int main()
{
    int i;
    struct material
    {
        char name[30];
        float price, kg;
    };
    unsigned m,nr;
    printf("Lorry capacity=");
    scanf("%u", &m);
    printf("Number of materials=");
    putchar('\n');
    scanf("%u", &nr);
    struct material list[nr];
    for (i=0; i<nr; i++)
    {
        printf("Name=");
        fgets(list[i].name, 30, stdin);
    }
    putchar('\n');
    for (i=0; i<nr; i++)
    {
        printf("%s ", list[i].name);
    }
    return 0;
}

回答1:

scanf("%u", &nr);
struct material list[nr];
for (i=0; i<nr; i++)
{
    printf("Name=");
    fgets(list[i].name, 30, stdin);

The scanf("%u", &nr); leaves the newline in the input buffer, so fgets finds an empty line without requiring further input to be entered.

It is generally a bad idea to mix (f)scanf and fgets, for that reason (among others).

As a quick fix, empty the input buffer before the first fgets,

int ch;
while((ch = getchar()) != EOF && ch != '\n');
if (ch == EOF) {
    // oops
}

A more principled fix would be to read in the values before using fgets to get an entire line including the newline, and decode the numbers with strtoul or maybe sscanf.



回答2:

This is a very common error. After reading a number with scanf, the newline you typed by pressing ENTER is left in the input buffer, so the first call to fgets reads the (very short) line that consists of only that newline.



回答3:

I noticed that I can get rid of the newline left in the input buffer, by reading it with getchar().

Also, I had to use the following code to remove the trailing newline character from fgets() input:

char *pos;
if ((pos=strchr(Name, '\n')) != NULL)
    *pos = '\0';


回答4:

One of the things that's generally misunderstood is that when you ask for input from the user, you get freebies.

When the computer ask for the amount of materials:

Number of materials=
51

And you enter "51" you're really getting three characters: '5', '1', and '\n'. Everything comes with a newline character when you hit the enter key.

Different utilities that get input from the user handle this different. fgets() will read the newline and then it stores the input as "51\n". If you read it as a string using scanf()'s string format specificer "%s" you'll get only the digits "51" and the newline character is left on the stdin buffer.

So in your case you read a number via scanf:

scanf("%u", &nr);

Which leaves the newline, then when you try to do the next read:

fgets(list[i].name, 30, stdin);

fgets picks up that newline and stores it.

So there's a bunch of fixes possible here, one is to just use fgets() only, another is to consume the newlines with getchar() after each scanf, choice is up to you.

BTW: You can insert a newline in your printfs: printf("Number of materials=\n");



回答5:

You can just do a fgets after each scanf, which will then eat the pending newline:

char dummy[10];
...
scanf (...);
fgets (dummy, 1, stdin);


标签: c stdin fgets