51

How do you get to see the last print? In other words what to put in for EOF? I checked the definitions and it says EOF is -1.

And if you enter Ctrl-D you won't see anything.

#include <stdio.h>

int main() {
 int c;
 while((c = getchar() != EOF)) {
  printf("%d\n", c);
 }
 printf("%d - at EOF\n", c);
}
Undo
  • 25,519
  • 37
  • 106
  • 129
Chris_45
  • 8,769
  • 16
  • 62
  • 73

10 Answers10

56

On Linux systems and OS X, the character to input to cause an EOF is Ctrl-D. For Windows, it's Ctrl-Z.

Depending on the operating system, this character will only work if it's the first character on a line, i.e. the first character after an Enter. Since console input is often line-oriented, the system may also not recognize the EOF character until after you've followed it up with an Enter.

And yes, if that character is recognized as an EOF, then your program will never see the actual character. Instead, a C program will get a -1 from getchar().

Carl Smotricz
  • 66,391
  • 18
  • 125
  • 167
  • Ok but what's the difference between Ctrl-z and Ctrl-D on Windows? Ctrl-z = EFO Ctrl-D = kill? – Chris_45 Nov 23 '09 at 10:14
  • @Chris_45: On Windows, Ctrl-Z marks EOF, Ctrl-D is just Ctrl-D (or character 04). @gotch4: It's standard (but little used) HTML: < kbd >. – Carl Smotricz Nov 23 '09 at 11:50
  • 1
    @Chris_45: Ctrl-D corresponds to ASCII EOT (end-of-transmission), MS-DOS however used Ctrl-Z (ASCII SUB) for compatibility with CP/M, and Windows inherits that. In CP/M the EOF character was actually a character in the file, because all files had to be multiples of 128 characters. The character used to signal EOF is specific to the OS not the programming language. http://en.wikipedia.org/wiki/End-of-file – Clifford Nov 23 '09 at 14:15
  • Well I meant the difference between Ctrl-Z and Ctrl-C? not Ctrl-d – Chris_45 Nov 23 '09 at 14:34
  • 4
    Then say so! :) Ctrl-C will usually kill a program that's accepting input from the console. Ctrl-D will mark the end of input but the program could continue running after that. – Carl Smotricz Nov 23 '09 at 19:07
  • On Mac, what is `EOF`? – diguage Mar 07 '15 at 05:43
  • @diguage: These days, Macs run OS X, which is a Mac-i-fied BSD Unix dialect, so as for other (all?) Unixes, the EOF character is Ctrl-D. – Carl Smotricz Mar 09 '15 at 16:19
  • A more precise description of the behavior of control-D is [here](https://stackoverflow.com/a/21365313/298225). By itself, control-D only means “send all bytes in input buffer to process.” When it is pressed when there are no byte in the input buffer, the routine attempting to read data from the device interrupts that as an EOF indicator. This is why EOF is caused when control-D is pressed at the beginning of a line (with the default line discipline), and why it is also caused when control-D is pressed twice. – Eric Postpischil Aug 10 '21 at 02:26
  • You can see this in action by writing a loop that calls `getchar` and prints the result. Generally, if you type a line, the results will be printed only when Enter is pressed, sending the typed characters to the process. But results will also appear when you type control-D after typing some other characters, because they are sent to the process immediately. Also, since the EOF is only a “soft” EOF indicated inside the C library, you can call `clearerr(stdin)` and resume characters with `getchar`. – Eric Postpischil Aug 10 '21 at 02:28
32

You should change your parenthesis to

while((c = getchar()) != EOF)

Because the "=" operator has a lower precedence than the "!=" operator. Then you will get the expected results. Your expression is equal to

while (c = (getchar()!= EOF))

You are getting the two 1's as output, because you are making the comparison "c!=EOF". This will always become one for the character you entered and then the "\n" that follows by hitting return. Except for the last comparison where c really is EOF it will give you a 0.

EDIT about EOF: EOF is typically -1, but this is not guaranteed by the standard. The standard only defines about EOF in section 7.19.1:

EOF which expands to an integer constant expression, with type int and a negative value, that is returned by several functions to indicate end-of-file, that is, no more input from a stream;

It is reasonable to assume that EOF equals -1, but when using EOF you should not test against the specific value, but rather use the macro.

Lucas
  • 13,679
  • 13
  • 62
  • 94
  • "EOF which expands to an integer constant expression, with type int and a negative value" `Int` is 32 bits and EOF signals success typically on the wchar_t value of -1 (or 65535) or the char value -1 with an extraneous *ÿ*. – Laurie Stearn Jan 23 '16 at 04:25
  • @LaurieStearn: In C, EOF is really just a macro that expands to a constant integer expression (typically defined in some header as something like: `#define EOF (-1)`) and is therefore typically 4 bytes wide. The EOF macro doesn't signal anything, since it is just a value. `getchar` - as defined in the standard library - always returns an integer value and when it returns a value equivalent to EOF (typically -1) indicates that it has reached the end of the file. The underlying mechanism is obviously dependent on your C-runtime and you can't really make any generalizing statements. – Lucas Jan 23 '16 at 13:30
  • @Lucas: Forgive my necro rant, Agreed. In VS10, the 65535 isn't strictly an *int*, but there's something going on with the 2's complement and the sign bit to make it so it seems. – Laurie Stearn Jan 23 '16 at 13:54
  • Gah, Didn't know there was a wide version of EOF, as explained [here](http://stackoverflow.com/questions/34964197/fgetwc-eof-loop-test-fails-but-65535-ok). – Laurie Stearn Jan 24 '16 at 06:50
11

The value of EOF is a negative integer to distinguish it from "char" values that are in the range 0 to 255. It is typically -1, but it could be any other negative number ... according to the POSIX specs, so you should not assume it is -1.

The ^D character is what you type at a console stream on UNIX/Linux to tell it to logically end an input stream. But in other contexts (like when you are reading from a file) it is just another data character. Either way, the ^D character (meaning end of input) never makes it to application code.

As @Bastien says, EOF is also returned if getchar() fails. Strictly speaking, you should call ferror or feof to see whether the EOF represents an error or an end of stream. But in most cases your application will do the same thing in either case.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • So you can never make the EOF on win32 make it to the appcode and see the last print? – Chris_45 Nov 23 '09 at 09:53
  • @Chris_45 - I'm talking about the meaning of EOF. The root cause of the bug in your "appcode" is something completely different -- see @Lucas's answer, – Stephen C Nov 23 '09 at 21:33
4

Couple of typos:

while((c = getchar())!= EOF)

in place of:

while((c = getchar() != EOF))

Also getchar() treats a return key as a valid input, so you need to buffer it too.EOF is a marker to indicate end of input. Generally it is an int with all bits set.


#include <stdio.h>
int main()
{
 int c;
 while((c = getchar())!= EOF)
 {
  if( getchar() == EOF )
    break;
  printf(" %d\n", c);
 }
  printf("%d %u %x- at EOF\n", c , c, c);
}

prints:

49
50
-1 4294967295 ffffffff- at EOF

for input:

1
2
<ctrl-d>
Heinzi
  • 167,459
  • 57
  • 363
  • 519
sud03r
  • 19,109
  • 16
  • 77
  • 96
  • 2
    Isn't there a bug in your code as well? You call `getchar()` twice (once in the while loop and once in the if), so very second input will be lost... – Heinzi Nov 23 '09 at 10:48
  • It works because the second getchar() gets the '\n' from hitting return. – Lucas Nov 23 '09 at 11:11
  • @Heinzi the second getchar() is used to capture the "\n" from return. This was done to explain the behavior OP got in hi code.. – sud03r Nov 23 '09 at 11:44
3

EOF means end of file. It's a sign that the end of a file is reached, and that there will be no data anymore.

Edit:

I stand corrected. In this case it's not an end of file. As mentioned, it is passed when CTRL+d (linux) or CTRL+z (windows) is passed.

Ikke
  • 99,403
  • 23
  • 97
  • 120
  • The edit is incorrect. The phrase "it is passed when CTRL+d...is [pressed]" is nonsense. When the user types ctrl-D, the input file is closed and `getchar` returns EOF to indicate that the end of file has been reached. There is no EOF character that is sent to the process. – William Pursell Jan 09 '13 at 22:47
  • What do you mean it is a sign? Is it a specific bit pattern? – Koray Tugay Jan 11 '15 at 12:09
  • He means sign in the normal (non-IT, non-mathematical) sense; i.e. an indication. At dog wags its tail as a sign that it is happy. – Stephen C Apr 16 '20 at 06:03
3

nput from a terminal never really "ends" (unless the device is disconnected), but it is useful to enter more than one "file" into a terminal, so a key sequence is reserved to indicate end of input. In UNIX the translation of the keystroke to EOF is performed by the terminal driver, so a program does not need to distinguish terminals from other input files. By default, the driver converts a Control-D character at the start of a line into an end-of-file indicator. To insert an actual Control-D (ASCII 04) character into the input stream, the user precedes it with a "quote" command character (usually Control-V). AmigaDOS is similar but uses Control-\ instead of Control-D.

In Microsoft's DOS and Windows (and in CP/M and many DEC operating systems), reading from the terminal will never produce an EOF. Instead, programs recognize that the source is a terminal (or other "character device") and interpret a given reserved character or sequence as an end-of-file indicator; most commonly this is an ASCII Control-Z, code 26. Some MS-DOS programs, including parts of the Microsoft MS-DOS shell (COMMAND.COM) and operating-system utility programs (such as EDLIN), treat a Control-Z in a text file as marking the end of meaningful data, and/or append a Control-Z to the end when writing a text file. This was done for two reasons:

  1. Backward compatibility with CP/M. The CP/M file system only recorded the lengths of files in multiples of 128-byte "records", so by convention a Control-Z character was used to mark the end of meaningful data if it ended in the middle of a record. The MS-DOS filesystem has always recorded the exact byte-length of files, so this was never necessary on MS-DOS.

  2. It allows programs to use the same code to read input from both a terminal and a text file.

user2864740
  • 60,010
  • 15
  • 145
  • 220
redtone
  • 31
  • 1
1
#include <stdio.h>

int main() {
    int c;
    while((c = getchar()) != EOF) { //precedence of != is greater than =, so use braces
        printf("%d\n", c);
    }
    printf("%d - at EOF\n", c);
}

I think this is right way to check value of EOF. And I checked the output.

For INPUT: abc and Enter I got OUTPUT: 97 98 99 10. ( the ASCII values)

For INPUT Ctrl-D I got OUTPUT: -1 - at EOF. So I think -1 is the value for EOF.

Try other inputs instead of Ctrl-D, like Ctrl-Z. I think it varies from compiler to compiler.

Heinzi
  • 167,459
  • 57
  • 363
  • 519
srikanth rongali
  • 1,463
  • 4
  • 28
  • 53
  • 1
    Sure, `stdio.h` defines `EOF` as `-1`. But that shouldn't interest you, nor do you need to look at it or print it out. Just check for EOF in your code and let the compiler worry about the details. – Carl Smotricz Nov 23 '09 at 11:57
0

to keep it simple: EOF is an integer type with value -1. Therefore, we must use an integer variable to test EOF.

Jency
  • 269
  • 1
  • 13
-1
#include <stdio.h>

int main() {
    int c;
    while((c = getchar()) != EOF) { 
        putchar(c);
    }    
    printf("%d  at EOF\n", c);
}

modified the above code to give more clarity on EOF, Press Ctrl+d and putchar is used to print the char avoid using printf within while loop.

-3
int c;

while((c = getchar())!= 10)
{
    if( getchar() == EOF )
        break;

     printf(" %d\n", c);
}
Pang
  • 9,564
  • 146
  • 81
  • 122
  • 1
    Not sure what the purpose of this answer is (or why some people dump blocks of code on SO with no explanation), but note the bug here: every second character is discarded due to the faulty EOF checking logic. – Username Obfuscation Sep 08 '20 at 07:39