I'm working on character K&R C book to try to learn the C language. I'm having a lot of issues because I'm using windows 10 OS instead of Linux. I'm using msys2 to compile and run my code. I for the longest time couldn't figure out the File copying from section 1.5.1 until asking for help from an expert in the field. He pointed out that I needed to use fflush(stdout);
{
while ((c = getchar()) != EOF) { // read buffer store in c, then check if it is EOF(ctrl+z on windows)
fflush(stdout); //flush buffer
putchar(c); // print the character retrieved
printf("%d\n",(c));
}
return(0);
}
Adding that made my program work as expected. However, Now I'm running into similar difficulty on the character counter of the next section.
long counter = 0; // initialize c variable
while (getchar() != EOF) { //check if character received is EOF(ctrl+z on windows)
fflush(stdout); //flush buffer
++counter; // incrementcounter
}
fflush(stdout);
printf("%ld\n",(counter));
return(0);
I never see the print on my counter at the end.
The attached image shows what happens when I run the file. The "Stopped" print is from when I sent EOF(ctr+Z).
I essentially have two questions:
What exactly happens when I send EOF to my kernel.
Is there a way to send EOF without immediately killing my program?
I hope that was easy to follow and thank you all in advance.
What exactly happens when i send EOF to my kernel.
The system (MSYS) tells the program that its standard input has reached EOF (end-of-file), and there'll be no more input availablr.
Is there a way to send EOF without immediately killing my program?
No. Sending an EOF never terminates a program immediately. It lets the program continue without reading input anymore. It's your program that terminates itself when it found nothing to read.
The reason you see Stopped is that you didn't send an EOF at all! Oj Unix shells (including MSYS and Cygwin), Ctrl-Z means Suspend. You can type fg to bring it to foreground again, then press Ctrl-D to send it an EOF.
Note: Ctrl-Z sends EOF only in Windows CMD, and in Windows 10 you have to uncheck a box.
Related
Following "The C Programming Language" by Kernighan and Ritchie, I am trying to enter the program described on page 18 (see below).
The only changes I made were to add "int" before "main" and "return 0;" before closing the brackets.
When I run the program in Terminal (Mac OS 10.15) I am prompted to enter an input. After I enter the input I am prompted to enter an input again - the "printf" line is apparently never reached and so the number of characters is never displayed.
Can anyone help me with the reason why EOF is never reached letting the while loop exit? I read some other answers suggesting CTRL + D or CTRL + Z, but I thought this shouldn't require extra input. (I was able to get the loop to exit with CTRL + D).
I have also pasted my code and the terminal window below.
#include <stdio.h>
int main(){
long nc;
nc = 0;
while( getchar() != EOF )
++nc;
printf("%ld\n", nc);
return 0;
}
From pg. 18 of "The C Programming Language
My screenshot
You already have the correct answer: when entering data at the terminal, Ctrl-D is the proper way to indicate "I'm done" to the terminal driver so that it sends an EOF condition to your program (Ctrl-Z on Windows). Ctrl-C breaks out of your program early.
If you ran this program with a redirect from an actual file, it would properly count the characters in the file.
EOF means end of file; newlines are not ends of files. You need to press CTRL+D to give the terminal an EOF signal, that's why you're never exiting your while loop.
If you were to give a file as input instead of through the command line, then you would not need to press CTRL+D
Adding to the two good answers I would stress that EOF does not naturally occur in stdin like in other files, a signal from the user must be sent, as you already stated in your question.
Think about it for a second, your input is a number of characters and in the end you press Enter, so the last character present in stdin is a newline character not EOF. For it to work EOF would have to be inputed, and that is precisely what Ctrl+D for Linux/Mac or Ctrl+Z for Windows, do.
As #DavidC.Rankin correctly pointed out EOF can also occur on stdin through bash piping e.g. echo "count this" | ./count or redirecting e.g. ./count < somefile, where somefile would be a text file with the contents you want to pass to stdin.
By the way Ctrl+C just ends the program, whereas Ctrl+D ends the loop and continues the program execution.
For a single line input from the command line you can use something like:
int c = 0;
while((c = getchar()) != EOF && c != '\n'){
++nc;
}
I'm making a simple program in C that reads an input. It then displays the number of characters used.
What I tried first:
#include <stdio.h>
int main(int argc, char** argv) {
int currentChar;
int charCount = 0;
while((currentChar = getchar()) != EOF) {
charCount++;
}
printf("Display char count? [y/n]");
int response = getchar();
if(response == 'y' || response == 'Y')
printf("Count: %d\n",charCount);
}
What happened:
I would enter some lines and end it with ^D (I'm on Mac). The program would not wait at int response = getchar();. I found online that this is because there is still content left in the input stream.
My first question is what content would that be? I don't enter anything after pressing ^D to input EOF and when I tried to print anything left in the stream, it would print a ?.
What I tried next:
Assuming there were characters left in the input stream, I made a function to clear the input buffer:
void clearInputBuffer() {
while(getchar() != '\n') {};
}
I called the function right after the while loop:
while((currentChar = getchar()) != EOF) {
charCount++;
}
clearInputBuffer();
Now I would assume if there is anything left after pressing ^D, it would be cleared up to the next \n.
But instead, I can't stop the input request. When I press ^D, rather than sending EOF to currentChar, a ^D is shown on the terminal.
I know there is a probably a solution to this online, but since I'm not sure what exactly my problem is, I don't really know what to look for.
Why is this happening? Can someone also explain exactly what is going on behind the scenes of this program and the Terminal?
man 3 termios - search for VEOF. That will tell you what it actually does.
If you need more explanation, I'll start by saying the ISO C stdin stream has a default buffer, so any bytes read are stored into that buffer unless this behavior is somehow overridden (e.g. setvbuf).
The getchar function will read from this default buffer unless the buffer has no characters in it left to read. In that case, it will call the read function to actually store new data into that buffer and return the number of bytes read.
However, your terminal has its own input buffer. It will wait for an input sequence recognized as an end-of-line (EOL) delimiter. This is where things get interesting. If ICANON is enabled, and you use Ctrl+D with bytes in the terminal's input buffer already, then you effectively will send all of that pending bytes to the program, as if you had entered an end-of-line delimiter. The read function will receive those bytes and store them in the input buffer used for stdin, resulting in getchar returning an appropriate value.
If Ctrl+D is pressed with no pending bytes in the terminal's input buffer, no data will be sent, read will return 0, and EOF gets returned by getchar after getchar sets the end-of-file indicator for the stdin stream.
Given the two behaviors of Ctrl+D, it follows that pressing it twice will send all pending bytes on the first key press, effectively emptying the terminal's input buffer, followed by the second key press sending 0 bytes to read, which means getchar returns EOF and the end-of-file indicator for stdin is set.
If an error occurs (e.g. stdin was closed), read itself will return -1, and getchar will return EOF after setting the error indicator for the stdin stream. The following may help to illustrate the idea of how it works, though there's likely a lot more going on behind the scenes with the TTY itself than just waiting for an EOL or VEOF and sending data after either one is detected:
Of course, if ICANON isn't set on the controlling terminal, then you will never receive EOF unless your input is not from a terminal because suddenly certain special key sequences like Ctrl+D won't be recognized as special key sequences since the feature is turned off.
For a bit more completeness, please note that the ICANON bit and termios stuff in general do not necessarily apply much on Windows. The Windows Command Prompt uses Ctrl+Z for one thing, and the Windows operating system has no concept of terminals other than things like the _isatty C runtime function that is used to detect whether a file descriptor points to a file description that involves a console handle.
Pressing Ctrl+Z with data pending will effectively cancel any remaining input that follows it, though an end-of-line character (Ctrl+M or Enter) still needs to be pressed for the data to be sent unless processed input was disabled by using the SetConsoleMode Windows API function.
If pressed with no input data pending and sent by entering an end-of-line character, it acts as EOF. For example, hello^Z1234^M results in hello^Z being read, and everything including the ^M end-of-line character is ignored. ^Z1234^M or just ^Z^M will trigger EOF.
Operating systems are weird.
Ctrl+D is a bit weird on Unix -- it's not actually an EOF character. Rather, it's a signal to the shell that stdin should be closed. As a result, the behavior can be somewhat unintuitive. Two Ctrl+Ds in a row, or a Return followed by a Ctrl+D, will give you the behavior you're looking for. I tested it with this code:
#include <stdio.h>
int main(void) {
size_t charcount = 0;
while (getchar() != EOF)
charcount++;
printf("Characters: %zu\n", charcount);
return 0;
}
Edited to include chux's format character suggestion.
You can do it (also) this way:
fseek(stdin,0,SEEK_END);
This works fine for me.
I'm working out of the K&R book, and I'm on the code example of how to count characters from a stream of text. I copied their code and tried running it, but when the command line prompts you for characters, the loop doesn't exit and thus will never print out the character count. Is there an error here I'm not catching?
#include <stdio.h>
main()
{
long nc;
nc = 0;
while(getchar() != EOF) {
++nc;
}
printf("%1d\n", nc);
}
Whenever you want to stop it just send the EOF signal to the shell.
Ctrl+d in Linux or Ctrl+z on Windows.
By the way (as additional info) Ctrl+c send SIGINT to a process in Linux and on Windows it does something similar.
Have you tried to press Ctrl+D (on Linux) or Ctrl+Z (on Windows)? If yes then It will come out of loop for sure. On pressing these keys, it will return EOF and loop will terminate.
Try ending your character stream with CNTL-Z (end of file character). Just hitting Enter results in a CR which is just another character to count
I am reading through "The C Programming Language", and working through all the exercises with CodeBlocks. But I cannot get my character counter to work, despite copying it directly from the book. The code looks like this:
#include <stdio.h>
main(){
long nc;
nc = 0;
while (getchar() != EOF)
++nc;
printf("%ld\n", nc);
}
When I run the program, it opens a window I can type in, but when I hit enter all that happens is it skips down a line and I can keep typing, but I think it's supposed to print the number of characters.
Any idea what's going wrong?
This line:
while (getchar() != EOF)
means that it keeps reading until the end of input — not until the end of a line. (EOF is a special constant meaning "end of file".) You need to end input (probably with Ctrl-D or with Ctrl-Z) to see the total number of characters that were input.
If you want to terminate on EOL (end of line), replace EOF with '\n':
#include <stdio.h>
main(){
long nc;
nc = 0;
while (getchar() != '\n')
++nc;
printf("%ld\n", nc);
}
Enter is not EOF. Depending on your OS, Ctrl-D or Ctrl-Z should act as EOF on standard input.
I ran into the problem tonight, too. Finally found out that Ctrl-D on Linux worked. You build the source file using cc, and start the program and input a word, then press Ctrl-D twice when finished typing. The number that the program countered will be printed just behind the very word you just typed, and the program terminates immediately. Just like this:
The above answer provided by nujabse is correct. But recently coming across this issue myself and researching the answer, I would like to add why.
Using Ctrl+C tells the terminal to send a SIGINT to the current foreground process, which by default translates into terminating the application.
Ctrl+D tells the terminal that it should register a EOF on standard input, which bash interprets as a desire to exit.
What's the difference between ^C and ^D
#include <stdio.h>
int main() {
char read = ' ';
while ((read = getchar()) != '\n') {
putchar(read);
}
return 0;
}
My input is f (followed by an enter, of course). I expect getchar() to ask for input again, but instead the program is terminated. How come? How can I fix this?
The Terminal can sometimes be a little bit confusing. You should change your program to:
#include <stdio.h>
int main() {
int read;
while ((read = getchar()) != EOF) {
putchar(read);
}
return 0;
}
This will read until getchar reads EOF (most of the time this macro expands to -1) from the terminal. getchar returns an int so you should make your variable 'read' into an integer, so you can check for EOF. You can send an EOF from your terminal on Linux with ^D and I think on windows with ^Z (?).
To explain a little bit what happens. In your program the expression
(read = getchar()) !='\n'
will be true as long as no '\n' is read from the buffer. The problem is, to get the buffer to your program, you have to hit enter which corresponds to '\n'.
The following steps happen when your program is invoked in the terminal:
~$\a.out
this starts your program
(empty line)
getchar() made a system call to get an input from the terminal and the terminal takes over
f
you made an input in the terminal. The 'f' is written into the buffer and echoed back on the terminal, your program has no idea about the character yet.
f
f~$
You hit enter. Your buffer contains now 'f\n'. The 'enter' also signals to the terminal, that it should return to your program. Your progam
reads the buffer and will find the f and put it onto the screen and then find an '\n' and immediatley stop the loop and end your program.
This would be standard behaviour of most terminals. You can change this behaviour, but that would depend on your OS.
getchar() returns the next character from the input stream. This includes of course also newlines etc. The fact that you don't see progress in your loop unless you press 'Enter' is caused by the fact that your file I/O (working on stdin) doesn't hand over the input buffer to getchar() unless it detects the '\n' at the end of the buffer. Your routine first blocks then handles the two keystrokes in one rush, terminating, like you specified it, with the appearance of '\n' in the input stream. Facit: getchar() will not remove the '\n' from the input stream (why should it?).
after f you are putting "enter" which is '/n'.
so the loop ends there.
if you want to take another character just keep on putting them one after the other as soon as enter is pressed the loop exits.
You've programmed it so the loop ends when you read a \n (enter), and you then return 0; from main which exits the program.
Perhaps you want something like
while ((read = getchar()) != EOF) {
putchar(read);
}
On nx terminals you can press Control-D which will tell the tty driver to return the input buffer to the app reading it. That's why ^D on a new line ends input - it causes the tty to return zero bytes, which the app interprets as end-of-file. But it also works anywhere on a line.