fgets instructions gets skipped.Why?
Asked Answered
L

3

5

Whenever I do a scanf before a fgets the fgets instruction gets skipped. I have come accross this issue in C++ and I remember I had to had some instrcution that would clear the stdin buffer or something like that. I suppose there's an equivalent for C. What is it?

Thanks.

Labor answered 25/5, 2010 at 17:44 Comment(3)
Code, please .. ?Reaper
You might find it easier to use fgets for all your input and then use sscanf when you want to parse values from a line.Otherness
@Tim Post: I thought this would be so straitforward for most of the users, that didn't find it necessary. I think the question is detailed enough.Labor
S
5

I'll bet it's because of the \n stuck in the input stream.

See one of these questions:

I am not able to flush stdin.
How do I go about Flushing STDIN here?
scanf() causing infinite loop

or this answer.

Also: Why not to use scanf().

P.S. fgets() is a function, not an instruction.

Spark answered 25/5, 2010 at 17:49 Comment(0)
T
3

The fgets() function following the call to scanf() is probably1 not getting skipped. It is probably1 returning immediately having found a newline in the input stream.

Calling scanf() before fgets() almost always results in scanf() leaving an unused newline ('\n') in the input stream, which is exactly what fgets() is looking out for.

In order to mix scanf() and fgets(), you need to remove the newline left behind by the call to scanf() from the input stream.

One solution for flushing stdin (including the newline) would be something along the lines of the following:

int c;
/* discard all characters up to and including newline */
while ((c = getchar()) != '\n' && c != EOF); 

1 - It is difficult to be certain without seeing the actual code.


Or, as Jerry Coffin suggested in his comment below, you could use scanf("%*[^\n]");. The "%*[^\n]" directive instructs scanf() to match things that are not newlines and suppress assignment of the result of the conversion.

/* match up to newline */
scanf("%*[^\n]"); 
/* discard the newline */
scanf("%*c"); 

From http://c-faq.com/stdio/gets_flush1.html:

An initial scanf() with “%*[^\n]” will either eat everything up to but not including a newline, or fail. A subsequent “%*c” (or plain old getchar()) will consume the newline, if there was one.

That last “if” matters too: perhaps the user signalled EOF. In this case, the getchar() or scanf("%*c") might -- this decision is left to the people who write your compiler -- either immediately return EOF, or go back to the user for more input. If the implementors choose the latter, the user might have to click on “end this thing” (^D, ^Z, mouse button, front panel switch, or whatever) one extra time. This is annoying, if nothing else.


Or, as Chris Dodd suggested in his comment below, you could use scanf("%*[^\n]%*1[\n]");. The "%*[^\n]%*1[\n]" directive instructs scanf() to match things that are not newlines and then match one newline and suppress assignment of the results of the conversion.

/* match and discard all characters up to and including newline */
scanf("%*[^\n]%*1[\n]");
Techno answered 25/5, 2010 at 17:59 Comment(2)
You can flush the input buffer (i.e., discard until newline is reached) a little more easily with: scanf("%*[^\n]");Ruy
You can flush up to and including the newline with scanf("%*[^\n]%*1[\n]")Defluxion
C
1

You can just put this line before your fgets() call and that'll get the trailing '\n' generated when you pressed enter

scanf("%c", (char *) stdin);
Cydnus answered 28/8, 2021 at 9:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.