When I run the first code and press ctrl-c immediately there will be no 45 written out to the file. But when I run the second code, I do get 45.
I couldn't come to the reason why this behavior happens in the below code? If stdout is line buffered shouldn't output come after I enter a character? What am I missing?
First code:
#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE *fp=stdout;
fp=fopen("myfile","w");
fprintf(fp,"%d",45);
getchar();
// return 0;
}
Second code:
#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE *fp=stdout;
fprintf(fp,"%d",45);
getchar();
// return 0;
}
PS: I'm using GCC and the platform is Linux.
I dont think getchar has anything to do with the buffering you are observing in the first code. If you dont press any character and wait for a while ( ie stay inside getchar() ), you'll most probably see an empty file. This happens irrespective of whether you've stalled the program with getchar, sleep or a while(1).
Now you press Ctrl-C for which your program has no handler registered and hence your program terminates abruptly. Whether buffers/streams are flushed on abrupt program termination is implementation defined. Read the full story here
Why is data not being flushed to file on process exit?
For example, on my system ( Windows 7, Code Blocks which uses gcc and mingw framework internally ), I can see 45 indeed being flushed into the file irrespective of using getchar or anything when I terminate it abruptly. ie on my system, the implementation is flushing data to the file on abrupt program termination.
So, the bottom line is, what happens when you do things in a non-normal fashion is implementation defined!
But the second case is indeed a curious one where getchar seems to be flushing the stdout buffer. I shall update on that as soon as I find the exact cause of why getchar is/seems-to-be flushing stdout buffer
Whats causing confusion is getchar(), seems like when it is called it is flushing stdout.
If you replace getchar() with something like sleep(10) then you 45 won't be printed.
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
FILE *fp=stdout;
//fp=fopen("myfile","w");
fprintf(fp,"%d",45);
sleep(10);
//getchar();
// return 0;
}
The first case you are writing to a physical file. fopen, fclose are buffered I/O depends on the implementation, data may not be committed immediately until the buffer is full. Calling fclose() will cause the buffer to be written to disk.
The second case you are writing to STDIO and data written to STDIO normally show up immediately.
Related
#include <stdio.h>
int main(){
char a[2] = {0};
a[0] = 't';
printf("%s", a);
scanf("%c", a);
return 0;
}
scanf here will cause an automatic flush of stdout.
Running a.out will print t on the terminal before running scanf, more info: How is printf getting flushed before scanf is executed?
However, doing a.out > out.txt and terminating it with ^C does not print anything inside out.txt yet the output still appeared on the screen without redirecting stdout with >.
If stdout is being flushed then why out.txt is still empty?
If it's not being flushed then how did t appear on the screen in the first example?
(I know using \n or a manual fflush or properly terminating the program will fix the issue, i'm just curious about this behaviour).
The key is the word interactive:
The input and output dynamics of interactive devices shall take place as specified in 7.21.3.
As soon as you redirect the standard output to a file, it is no longer interactive.
For example the Linux C standard library actually executes the analogue of the isatty library call to figure this out. If it figures out that standard output is not directed to file it will also break this relationship. It will also increase the I/O performance of programs that work as part of a command pipeline.
You can yourself test whether stdout is connected to a terminal by executing
#include <unistd.h>
printf("stdout is connected to a terminal: %d\n", isatty(fileno(stdout)));
When you read from stdin using getchar, fgets or some similar function, if you type some text and then put an eof (control+d in linux) you cannot delete the previous text. For example, if I type 'program' and then enter eof by pressing control+d, I can't delete what I typed before, i.e. program.
#include<string.h>
#include<stdlib.h>
int main() {
char buffer[1024] = "";
printf("> ");
if(fgets(buffer,sizeof(buffer),stdin) == NULL){
puts("eof");
}
else{
puts(buffer);
}
return 0;
}
How can this be avoided?
The readline function of The GNU Readline Library I think is my best option to do the job. It's pretty simple to use but it uses dynamic memory to host the string so you have to use the free function to free up the memory. You can find more information by opening a terminal and typing 'man readline'.
The code would look like this:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <readline/readline.h>
int main() {
char *ptr = readline("> ");
if(!ptr){
puts("eof");
}
else{
puts(ptr);
}
free(ptr);
return 0;
}
To be able to use readline with gcc you must pass it -lreadline
When fgets reads a line, what will happen is that it will read characters from the specified stream until it encounters a '\n' or EOF, until it has read the specified maximum size to read or a read error occurs. It does not see what you are doing on your keyboard at all. It only sees the stream, but it is the terminal that sends the data to the stream.
What's happening when you are editing the input has absolutely nothing to do with fgets. That's the terminals job.
As Eric Postpischil wrote in the comments:
Pressing control-D in Linux does not signal EOF. It actually means “Complete the current read operation.” At that point, if characters have been typed, they are immediately sent to the program, whereas the system would usually wait until Enter is pressed. If no characters have been typed, the read operation completes with zero characters read, which some I/O routines treat as an EOF, and that is why programs may seem to receive an EOF when control-D is pressed at the start of a line of input. Since the data is sent to the program, of course there is no way to undo it—it has already been sent.
I guess there is some way to alter the behavior of pressing C-d, but then you need to decide what it should do instead. If you want it to do "nothing" instead of sending the data to stdin I cannot really see what you have won. The only use case I can see with this is if you for some reason are having a problem with accidentally pressing C-d from time to time.
One thing you could do is to take complete control of every keystroke. Then you would have to write code to move the cursor every time the user presses a key, and also write code to remove characters when the user is pressing backspace. You can use a library like ncurses for this.
It can't be avoided. Simply put, Ctrl+D ends the current read operation.
If you want to ignore this, make your own fgets based on fgetc and have it ignore end-of-file.
#include <stdio.h>
#include <unistd.h>
int main()
{
while(1)
{
fprintf(stdout,"hello-out");
fprintf(stderr,"hello-err");
sleep(1);
}
return 0;
}
The output of above on my machine is
hello-errhello-errhello-errhello-errhello-errhello-errhello-errhello-errhello-errhello-errhello-errhello-errhello-errhello-err
I had to kill the program to stop it.
Is it the correct and expected behavior.
Or it is wrong.This was an interview question hence I am posting here.
This is the expected output:
The program loops forever because of the while (1) loop.
stdout is line-buffered (by default), so it only flushes to the console when a new-line character ('\n') is printed. As you aren't printing any new-line characters, you never see any of the hello-out text.
However stderr is not line-buffered (by default), so it updates the console on every new fprintf() call.
stdout is buffered on most machines. You won't see any output from any fprintf calls to stdout unless you print a newline or call fflush().
So yes, it's expected behaviour, most of the time.
While everyone is right that you have an infinite loop, stderr is not buffered so you get it immediately, stdout is line buffered so it is deferred until you get a newline, they do not mention that stdout does not have infinite storage. I think the buffers are 1k or so by default (see setbuf). If you wait long enough you will get a very long burst of hello-out sequences. It is entirely possible that the last hello-out might be truncated part of the way through the string "hello-out".
[...]hello-outhello-outhellhello-errhello-err
^^^^
I am confused about getchar()'s role in the following code. I mean I know it's helping me see the output window which will only be closed when I press the Enter key.
So getchar() is basically waiting for me to press enter and then reads a single character.
What is that single character this function is reading? I did not press any key from the keyboard for it to read.
Now when it's not reading anything, why does it not give an error saying "hey, you didn't enter anything for me to read"?
#include <stdio.h>
int main()
{
printf( "blah \n" );
getchar();
return 0;
}
That's because getchar() is a blocking function.
You should read about blocking functions, which basically make the process wait for something to happen.
The implementation of this waiting behavior depends on the function, but usually it's a loop that waits for some event to happen.
For the case of the getchar() function, this probably is implemented as a loop that constantly reads a file (stdin for this case) and checks weather the file is modified. If the file is modified, the loop behaves by doing something else.
The getchar() function will simply wait until it receives a character, holding the program up until it does.
A character is sent when you hit the enter key; under a Windows OS, it will send a carriage return (CR) and a line-feed (LF).
See this CodingHorror post for a nicely put explanation.
(...the explanation of the CR+LF part, not the getchar() blocking part)
Try this:
#include <stdio.h>
int main(int argc, char *argv[])
{
char ch;
printf("I'm now going to block until you press something and then return... ");
ch = getchar();
if (ch >= 0)
printf("\nYou pressed %c\n", ch);
else
printf("\nAliens have taken over standard input! Run!\n");
return 0;
}
getchar() will cause your program to go to sleep until a keyboard (or whatever is attached to stdin) interrupt is received. This means it's blocking, no additional code will execute until getchar() returns.
It's very, very helpful to look at the return value of a function in order to understand it.
Any function may block, unless it provides some mechanism to prevent blocking. For instance, open() allows a O_NONBLOCK flag which is helpful for opening slow to respond devices like modems. In short, if it gets input from a terminal or has to wait to get an answer from the kernel or some device, there's a very good chance it might block.
getchar() blocks your program's execution until a key is pressed. So, there's no error if no key is pressed, getchar() will wait for it to happen :)
You can learn more about how getchar behaves here:
http://www.cppreference.com/wiki/c/io/getchar
...this should answer your question:)
I think what confuses you is that the Enter key is needed befor the program continues. By default, the terminal will buffer all information until Enter is pressed, before even sending it to the C program.
see discussion of Enter problem here
I'm just learning C with Kernighan and Ritchie's book; I'm in the basics of the fourth chapter ("Functions and Program Structure"). The other day I became curious about the sleep() function, so tried to use it like this:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
printf(" I like cows.");
sleep(5);
return 0;
}
The problem is the output of the program, it looks like it does the sleep() first and then the printf(), in other words, it waits five seconds and then prints the string. So I thought, maybe the program gets to sleep() so fast that it doesn't let printf() have his work done like I want, that is print the string and then sleep.
How can I show the string and then put the program to sleep?
The compiler is GCC 3.3.5 (propolice) in OpenBSD 4.3.
printf() writes to stdout (the default output stream) which is usually line buffered. The buffer isn't flushed by the time sleep is called so nothing is displayed, when the program exits all streams are automatically flushed which is why it prints right before exiting. Printing a newline will usually cause the stream to be flushed, alternatively you could use the fflush function:
int main(void)
{
printf(" I like cows.\n");
sleep(5);
return 0;
}
or:
int main(void)
{
printf(" I like cows.");
fflush(stdout);
sleep(5);
return 0;
}
If you are printing to a stream that is not line buffered, as may be the case if stdout is redirected or you are writing to a file, simply printing a newline probably won't work. In such cases you should use fflush if you want the data written immediately.
Your problem is that printf (and anything else that uses the stdio library to write to stdout (standard output)) is buffered - line buffered if it goes to the console, and size buffered if it goes to a file. If you do a fflush(stdout); after the printf, it will do what you want. You could try just adding a newline ('\n') to your string, and that would do the right thing as long as you don't redirect standard output to a file.
I'm not 100% sure, but I think stderr isn't buffered, which can cause confusion because you might see output you made to stderr before output you previously made to stdout.
Buffering means that all the output is stored in a place (called buffer) and is output after a certain amount of data is present in it. This is done for efficiency reasons.
Some (most?) implementations clear the buffer after a newline when writing to the console, so you can also try
printf(" I like cows.\n");
instead of the call to fflush()
I implemented time encounter as following;
for (int i = 1; i <= 60; i++) {
printf("%02d", i);
fflush(stdout);
sleep(1);
printf("\b\b");
}