I have trouble understanding getchar() and EOF.
I was trying to run this code:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char c;
int a = 0; //no. of characters
while (1) {
c = getchar();
if (c == EOF) {
// printf("%i",c);
break;
}
putchar(c);
++a;
}
printf("%i", a);
int b;
while ((b = getchar()) != EOF) {
putchar(b);
}
printf("here"); // to check wether the code written after the loop is executed
}
I terminated the first loop by pressing Ctrl-D twice, I found many posts explaining the reason for this. But whenever I try to call the getchar() function after the first loop it keeps returning EOF, even though that would have been already read by the last call in the first loop.
Code editor - VSCode
OS - macOS
You must define c as an int to accommodate for the full range of possible return values from getchar(), namely all values of type unsigned char and the special negative value EOF (usually defined as (-1)).
On most unix systems, when Ctrl-D is typed in the terminal in canonical mode, whatever input has been buffered by the terminal is sent to the process. In your case, it causes the input to be echoed. If there is no such input pending, the terminal sends zero bytes to the process, which is interpreted by the OS as the end of file. Hitting Ctrl-D twice in a row, or more precisely at the beginning of a read request, does not enter an EOF byte, it signals the end of file to the reading process, hence any further attempt at reading from the stream will return EOF immediately without requesting more user input from the terminal.
This question already has answers here:
Difference between int and char in getchar/fgetc and putchar/fputc?
(2 answers)
Closed 3 years ago.
I'm reading through the K&R book and implemented the 'copy' example:
#include <stdio.h>
int main() {
char c;
while ((c = getchar()) != EOF) {
putchar(c);
}
return 0;
}
All normal input appears to work correctly but when an EOF (^D) is entered the program prints infinite "�" characters and I must halt the program manually.
I have tried using putchar(c); as well as printf("%c", c); to the same effect.
Does anyone know the cause of this?
Since c is of type char, an int value returned from getchar will be converted to the type char before it is compared to EOF.
Since the EOF is an in-band error mechanism, it has to be an error value that can be distinguished from all valid characters that could be returned. When you assign EOF to a char you discard information.
After executing:
char c = EOF;
the statement
c == EOF
is false.
Preserve the return type of getchar by doing:
int c;
instead of:
char c;
Using int c instead of char c should solve your issue
This question already has answers here:
What is EOF in the C programming language?
(10 answers)
Closed 5 years ago.
I am new to coding and I am learning through a book called "The C Programming Language - 2nd Edition - Ritchie Kernighan" and there is this code:
#include<stdio.h>
#include<stdlib.h>
int main(){
int c,nl;
nl =0;
while((c=getchar())!=EOF)
if(c == '\n')
++nl;
printf("%d\n",nl);
return 0;
}
After typing the code in CodeBlocks I run it and when I type in a word and press enter nothing happens. The word is not being counted and printed. I am new to all of this but if anyone has an idea feel free to share it. Thank you very much !
The issue is that you never read the EOF (End Of File); this is the end of the input data coming from the console (where you type).
Everything you type is either a letter, digit, special character, or newline, but never EOF.
To generate an EOF you need to enter a special control-key combination. On Windows this is Ctrl+Z and on UNIX/Linux/macOS this is Ctrl+D.
The book you're reading is great and written by the two creators of C. It one of my first programming books and I still have it; all worn-out.
Small piece of advice: Always put your code blocks inside { } to avoid mistakes and create more visual clarity, use spaces consistently, and add empty lines. Your code would look like this:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int c, nl;
nl = 0;
while ((c = getchar()) != EOF)
{
if (c == '\n')
{
++nl;
}
}
printf("%d\n", nl);
return 0;
}
Why should it stop? Your expectations are wrong. getchar() will go on getting characters until it encounters EOF.
How to pass that to getchar?
For Windows Ctrl+Z will do the trick. And then press Enter.
For Unix or Linux system it would be Ctrl+D
Responsive output before entering EOF
To get a more responsive output you can add this line, that will tell you the cumulative sum of \n found.
if(c == '\n'){
++nl;
printf("Till now %d newline found",nl);
fflush(stdout);
}
Further Explanation of the added code
The code segment provided above will provide you some output when you press enter. But the thing is until you enter EOF it will keep on waiting for more and more input. That's what also happened in the first case. So you have to press Ctrl+Z and press Enter. That will break the loop. And you will see the final output - the number of line count.
This question already has answers here:
Cannot figure out how to use getchar(); in C
(4 answers)
Closed 8 years ago.
I read few questions on Stack Overflow but everyone here is explaining that has already been explained in K&R. I want to ask when the below program runs. Then if I input my name in the console then it get printed in the next line. Firstly this function's name is getchar why it doesn't take just one character 'a' or any other? I get correct output irrespective of how long my input is.
I wrote 'adfsajfsjssadfsa.......up to to 100 characters and putchar copied it exactly'. Also book is using int. I know int can hold data up to 4 bytes much bigger than char but what's the use of providing data types in C if we can use any of them.
Why does putchar print it to next line? Is it built this way to always print the output in next line? I wrote adfsajfsjssadfsa.......upto to 100 characters and putchar copied it exactly when will a situation come that I would get error and integer c won't be able to hold that big data. How many characters?
#include <stdio.h>
int main()
{
int c;
c=getchar();
while(c!=EOF){
putchar(c);
c=getchar();
}
}
You are calling getchar and putchar multiple times (because they are inside a loop) so they get and print multiple characters.
You MUST use an int variable when using getchar, because getchar can return any character or EOF. EOF isn't a character, so it doesn't fit in a char, and it represents the end of the file.
Variable c will always contain just 1 character, which is int. You are overwriting previous value with return value of a function getchar in each iteration of a loop.
Also try to avoid duplicate code by rewriting the while loop. You can call function getchar and assign value to variable c inside the while condition:
while ((c = getchar()) != EOF) {
putchar(c);
}
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);
}
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().
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.
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.
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>
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.
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:
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.
It allows programs to use the same code to read input from both a terminal and a text file.
#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.
to keep it simple: EOF is an integer type with value -1. Therefore, we must use an integer variable to test EOF.
#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.
int c;
while((c = getchar())!= 10)
{
if( getchar() == EOF )
break;
printf(" %d\n", c);
}