0
votes

Below is the program that I wrote.

/*******************************************************************************
 * This program reads EOF from standard input stream to store in an integer 
 * variable and in a character variable. Both values are then output to see the
 * stored value as integer.
*******************************************************************************/
#include<stdio.h>

int main (void)
{
    /* Local Declarations */
    int        num;
    char       ch;

    /* Read EOF as character & integer and display values stored */
    printf("\nPlease only input EOF for all input prompts below");
    printf("\nNumber? ");
    scanf("%d", &num);
    printf("\nThat integer input converts to %d", num);
    printf("\nCharacter? ");
    scanf(" %c", &ch);
    printf("\nThat character input converts to %d", ch);

    /* Check if any of the stored values are recognized as EOF */
    if(num == EOF)
        printf("\nNumber is an EOF");
    if(ch == EOF)
        printf("\nCharacter is an EOF");

    /* Exit Program */
    printf("\n");
    return 0;
}// main()

I compiled using gcc on Ubuntu 11.10. It does not recognize Ctrl-D for EOF in the program and outputs 0 when trying to print its value. The output for the above program on my terminal is below.

Please only input EOF for all input prompts below
Number? 
That integer input converts to 0
Character? 
That character input converts to 0

NOTE: CTRL-D is not echoed by the terminal when I press it for the two inputs, hence not visible in the above program execution.

I have read that EOF is defined as an integer in stdio.h and stdlib.h and is traditionally defined as -1. Also, I understand that Ctrl-D simulates EOF for standard input. Then why does it not translate to -1 when storing it to an integer variable?

2
Your program should call fflush and have the \n at the end of printf format strings! - Basile Starynkevitch
@BasileStarynkevitch Thank you for pointing that out. I must flush the stream for reading an int value before starting to read a character value. But why do you suggest putting \n at the end of printf format strings rather than beginning? I have seen this convention in the book I am using to learn C and found it a bit odd. - Harsh Vardhan
Because many implementations of printf are flushing the output buffer on \n newline characters. So your book is wrong in that aspect, you really should take the habit of putting it at the end of your format strings. And this is what most Linux utilities (e.g. shells, make, or gcc itself) are doing. - Basile Starynkevitch
@BasileStarynkevitch Flushing the output buffer on EOL? I thought the output stream is flushed when the file marker is placed on EOF. Please tell us more (I see you are a GCC developer:-). - Harsh Vardhan
Learn more about the setlinebuf function. On Linux (and probably on Posix systems), when stdout is a terminal, it usually is line buffered. - Basile Starynkevitch

2 Answers

4
votes

Because scanf("%d") will attempt to read characters representing a number and then store that into the given variable.

It does not store EOF into the number if you close the stream. Otherwise how would you tell the difference between end of file and entering the numeric value of EOF (-1).

The scanf will return the number of items scanned (which will be zero if format was wrong, or EOF if the stream closed or certain errors occurred). It returns this as the return code from the scanf function, not via the pointer variable you passed to it.

You should only assume the variables (that you pass in the addresses for) are populated if the return value from scanf tells you so.

In other words, you're looking for something like:

int rc = scanf ("%d", &num);
switch (rc) {
    case EOF: {
        printf ("EOF returned\n");
        break;
    }
    case 0: {
        printf ("No items scanned\n");
        break;
    }
    default: {
        printf ("Scanned %d\n", num);
        break;
    }
}
2
votes

From the docs:

"If the input ends before the first matching failure or conversion, EOF shall be returned. If a read error occurs, the error indicator for the stream is set, EOF shall be returned"

Note that it is returned, rather than being read into the pointer you pass.

To distinguish between an error and EOF you can use feof.