In this code, scanf
works only once. What am I doing wrong?
#include <stdio.h>
#include <unistd.h>
int main()
{
int i = 1;
if (! fork())
{
while(i)
{
printf("Enter i");
scanf("%d", &i);
fflush(stdin);
fflush(stdout);
}
}
else
{
printf("Parent\n");
}
return(0);
}
It has already been recommended that you not use
scanf
. If you feel you must usescanf
, you really should be checking the return value to determine if an input error occurred prior to the conversion.It has also been noted that you should not be flushing
stdin
viafflush
as it invokes undefined behavior. If you feel that you must flushstdin
, you may want to refer to the answers to this question.If an invalid value such as "1,234" is entered,
scanf
will accept the '1' and the ",234/n" will be left in the input stream. Sincefflush(stdin)
is not guaranteed to work, subsequent calls toscanf
will keep rejecting the same ',' over and over again, never making any progress. If the return value is checked for zero (indicating an early matching failure), this infinite loop can be avoided. It is also necessary to remove the invalid character(s) from the input stream prior to another call toscanf
.See scanf() causing infinite loop as well.
First I tried to extract the simplest code that gives the problem (not used C/scanf for a long time). The code without the
fork
works fine. A little google search "fork scanf" gave me the answer.After the fork, the input stream is closed. So the scanf gets into a bad state. The following program is a slight modification of yours. It prints "stream closed".
It's a bit hard to say without seeing what input you're providing. If it works without
fork
then it might be a clash as Amit described. Two other things, though:Don't use
scanf
.fflush(stdin)
is undefined behavior. Don't do it.From the comp.lang.c FAQ:
try to check if i>0.
After the parent process returns, it hands control back to the shell, which is free to close its
stdin
. Even ifstdin
remained valid and active, the user would receive a confusing shell prompt.To retain the child's access to stdin/out, you need to stall the parent from terminating until the child is done. Use
wait
or a related function.…
This fixes your bug on my machine. I'm not an expert on Unix file descriptor semantics, but it appears the resulting program might be portable. Why you want to do this is another matter…