31

I am using the following C code to take input from user until EOF occurs, but problem is this code is not working, it terminates after taking first input. What's wrong with this code?

float input;
 
printf("Input No: ");
scanf("%f", &input);
    
while(!EOF)
{
    printf("Output: %f", input);
    printf("Input No: ");
    scanf("%f", &input);
}
starball
  • 20,030
  • 7
  • 43
  • 238
itsaboutcode
  • 24,525
  • 45
  • 110
  • 156
  • 4
    Note: Assuming the user input is not piped, checking for EOF is probably not ideal, since IIRC usually that means the user must hit ctrl+D to quit, which is non-obvious – Brian Sep 15 '09 at 18:41

6 Answers6

53

EOF is just a macro with a value (usually -1). You have to test something against EOF, such as the result of a getchar() call.

One way to test for the end of a stream is with the feof function.

if (feof(stdin))

Note, that the 'end of stream' state will only be set after a failed read.

In your example you should probably check the return value of scanf and if this indicates that no fields were read, then check for end-of-file.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • 3
    And note Brian's comment: stdin doesn't normally register EOF, since there's always more the user can type. On a Unixy system, that usually means control-D. – David Thornley Sep 15 '09 at 19:08
  • It depends what you mean my 'normally'. If you've redirected stdin (file or pipe, unix or windows), EOF is usually signalled correctly. In an interactive unix terminal ^D usually works, in windows text mode, ^Z at the start of a line works. – CB Bailey Sep 15 '09 at 19:12
  • How can you tell where it failed? like If I ask it to read 4 bytes, and it encounters EOF at 2 bytes, how will it tell me that the request was partially fulfilled? – MarcusJ Jul 13 '15 at 07:40
9

EOF is a constant in C. You are not checking the actual file for EOF. You need to do something like this

while(!feof(stdin))

Here is the documentation to feof. You can also check the return value of scanf. It returns the number of successfully converted items, or EOF if it reaches the end of the file.

A. Levy
  • 29,056
  • 6
  • 39
  • 56
  • does the FILE function contain a variable that would be better to test than using EOF? it just seems like it'd be better to check a status on the actual file pointer, than using some strange function that only works half the time. – MarcusJ Jul 13 '15 at 07:42
4

Another issue is that you're reading with scanf("%f", &input); only. If the user types something that can't be interpreted as a C floating-point number, like "pi", the scanf() call will not assign anything to input, and won't progress from there. This means it would attempt to keep reading "pi", and failing.

Given the change to while(!feof(stdin)) which other posters are correctly recommending, if you typed "pi" in there would be an endless loop of printing out the former value of input and printing the prompt, but the program would never process any new input.

scanf() returns the number of assignments to input variables it made. If it made no assignment, that means it didn't find a floating-point number, and you should read through more input with something like char string[100];scanf("%99s", string);. This will remove the next string from the input stream (up to 99 characters, anyway - the extra char is for the null terminator on the string).

You know, this is reminding me of all the reasons I hate scanf(), and why I use fgets() instead and then maybe parse it using sscanf().

David Thornley
  • 56,304
  • 9
  • 91
  • 158
-1

as a starting point you could try replacing

while(!EOF)

with

while(!feof(stdin))
Craig
  • 4,750
  • 22
  • 21
-1

You want to check the result of scanf() to make sure there was a successful conversion; if there wasn't, then one of three things is true:

  1. scanf() is choking on a character that isn't valid for the %f conversion specifier (i.e., something that isn't a digit, dot, 'e', or 'E');
  2. scanf() has detected EOF;
  3. scanf() has detected an error on reading stdin.

Example:

int moreData = 1;
...
printf("Input no: ");
fflush(stdout);
/**
 * Loop while moreData is true
 */
while (moreData)
{
  errno = 0;
  int itemsRead = scanf("%f", &input);
  if (itemsRead == 1)
  {
    printf("Output: %f\n", input);
    printf("Input no: ");
    fflush(stdout);
  }
  else
  {
    if (feof(stdin))
    {
      printf("Hit EOF on stdin; exiting\n");
      moreData = 0;
    }
    else if (ferror(stdin))
    {
      /**
       * I *think* scanf() sets errno; if not, replace
       * the line below with a regular printf() and
       * a generic "read error" message.
       */
      perror("error during read");
      moreData = 0;
    }
    else
    {
      printf("Bad character stuck in input stream; clearing to end of line\n");
      while (getchar() != '\n')
        ; /* empty loop */
      printf("Input no: ");
      fflush(stdout);
    }
 }
John Bode
  • 119,563
  • 19
  • 122
  • 198
  • 1
    possible infinite loop when clearing to end of line. I suggest ``while (((ch = getchar()) != EOF) && (ch != '\n')) /* void */;`` ad then checking (again) for EOF and setting ``moredata = 0;`` – pmg Sep 15 '09 at 19:58
  • Please open a new question. – andig Jan 22 '18 at 07:46
-1
while(scanf("%d %d",a,b)!=EOF)
{

//do .....
}
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129