Exikle
Exikle

Reputation: 1165

fgets()'s first instance is being skipped

So I'm practicing c and am getting this this bug when I use fgets(). The first instance of the code gets skipped and goes to the next line.

CODE

for(g = 0;g<numStudents;g++)
  {
    array->firstName = malloc(sizeof(char)*BUFSIZE);
    array->lastName = malloc(sizeof(char)*BUFSIZE);

    printf("Student %d\n", g+1);
    printf("First Name:");
    fgets(array->firstName, BUFSIZE, stdin);
    printf("Last Name:");
    fgets(array->lastName, BUFSIZE, stdin);
    printf("\n\n");
  }

I am using scanf() before this section, so I found out that I have to flush the buffer. However that is not working.

The output would usually be:

Student 0
First Name:Last Name:(Cursor)

Upvotes: 1

Views: 139

Answers (1)

paxdiablo
paxdiablo

Reputation: 881103

You have to be careful mixing different input methods like scanf and fgets. If you scanf("%d") and enter a single integer followed by a newline, the pointer will be left at the newline (the first character not valid for constructing an integer), so that's what a following fgets will pick up, as you can see.

For example, consider the following small program:

#include <stdio.h>
int main (void) {
    int val;
    char buffer[100];
    scanf ("%d", &val);
    fgets (buffer, sizeof(buffer), stdin);
    printf ("%d[%s]\n", val, buffer);
    return 0;
}

If you compile/run that, then enter 123 456, the output you'll see is:

123[ 456
]

There you can see that the fgets has picked up the rest of the line after the scanned integer, from the first non-digit space to the newline at the end.

If you use scanf alone, it's usually okay since most (but not quite all) format specifiers will skip leading whitespace before they read their item.

There are also ways to allow mixing of the different input methods, such as reading characters after the scanf until you get a newline, effectively throwing away the rest of the line (including the newline character).

But perhaps the easiest way is to use a custom-made, proven line-input function to get lines, and then sscanf the lines to get what you want, such as this one.

That way, all input is line-based and you still get the power of scanf to extract data from the line.

Upvotes: 6

Related Questions