1

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)
Exikle
  • 1,155
  • 2
  • 18
  • 42
  • `sizeof(char) == 1` and is mandatory, can you please post your input? Also using `malloc()` for a fixed size is not really necessary. – Iharob Al Asimi Feb 11 '15 at 01:46
  • 1
    At the very least, the answer to [Does `scanf()` take `'\n'` as input left over from previous `scanf()`](http://stackoverflow.com/questions/1815986/does-scanf-take-n-as-input-leftover-from-previous-scanf) applies to your situation. The `scanf()` probably leaves a newline in the input stream which `fgets()` reads as the first input 'line'. I would close this as a duplicate, but I'd rather have some consensus before wielding Mjolnir. – Jonathan Leffler Feb 11 '15 at 01:59
  • How are you flushing the buffer after `scanf`? – R Sahu Feb 11 '15 at 02:00
  • 1
    Use `while((int c=getchar())!='\n' && c!=EOF);` before the loop. – Spikatrix Feb 11 '15 at 02:16

1 Answers1

6

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.

Community
  • 1
  • 1
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953