tom1990
tom1990

Reputation: 642

C: Clearing stdin input buffer not working as expected with fgets()

I am using the following method clear the input buffer:

void dump_line(FILE *fp) {
    int ch;    
    while ( (ch = fgetc(fp)) != EOF && ch != '\n');
}

This works fine if I read from stdin using scanf():

char string[51];
...
scanf("%50[^\n]", string);
dump_line(stdin);

However, if I use fgets() instead, as in the following code:

char string[52];
...
fgets(string, 52, stdin);
dump_line(stdin);

// Since fgets() reads in the '\n', trim the end of the string:
string[strlen(string)-1] = 0;

Since fgets() reads in the '\n' character I found the need to allocate a buffer one char larger and trim the string back one character. This works fine but there is a problem with the dump_line function. When using the scanf() version, it works as expected since there will always be a '\n' left in the input buffer due to the use of [^\n]. So even if that is the only char left in the buffer, in dump_line() the fgetc() reads the char and since it is a '\n' the while loop is broken.

In the fgets() version, the '\n' is read in if it will fit in the string buffer, leaving stdin empty. This is causing the program to wait on the fgetc(), requiring the user to hit the enter key to progress any further, which is obviously not what I am after. On the other hand, if the user enters a string too long for the buffer, the dump_line() is working fine!

Im guessing the problem is something to do with EOF, but I cannot seem to get this to work as intended! Any help would greatly be appreciated.

If it is any help the platform I am working on is Mac OSX, just in case this is some kind of platform-specific quirk.

Upvotes: 1

Views: 3437

Answers (2)

Daniel Fischer
Daniel Fischer

Reputation: 183873

Check whether you need to clear the buffer,

fgets(string, 52, stdin);
size_t len = strlen(string);
if (string[len-1] == '\n') {
    // read in whole line, no need to clear buffer
    string[len-1] = 0;
} else {
    // junk left in buffer, clear it
    dump_line(stdin);
}

Upvotes: 5

Some programmer dude
Some programmer dude

Reputation: 409136

You could use ungetc to put the newline back into the stream.

Upvotes: 1

Related Questions