The following program shows how buffered I/O can cause problems in programs when errors like 'divide by zero' happen:
int main()
{
int a = 1, b = 0, c;
printf("Dividing...");
c = a/b;
printf("Answer is: %d\n", c);
return 0;
}
The output is Floating point exception (core dumped).
Fair enough. But surprisingly, if I changed the first printf to printf("Dividing...\n");, this text actually gets printed before the program crashes (I'm running GCC on Linux, by the way).
Am I to conclude that adding a newline is equivalent to flushing? And if so, if all my printf() strings end in \n, I'm actually depriving myself of the benefits of buffered I/O?
If your standard output is going to a terminal, yes, it's equal to flushing, as printf() will use line-based buffering.
If it's redirected to a file, then no. In this case printf() uses much bigger buffers, usually corresponding to file system block sizes or whatever, to optimize IO.
Related
I build a small program that simply copy the text from an input.txt file to an output.txt file. It works with no apparent problem with the command:
./myCopier.txt < rand.txt > randout.txt
on a GCC89 compiler, used for didactic purposes.
#include<stdio.h>
int main(void){
int c;
while ((c = getchar()) != EOF)
putchar(c);
/*The text in printf() does not appear anywhere*/
printf("My theories and toughts!\n");
}
Later, I add printf() in order to print my thoughts about how the program worked. It compiles without errors or warnings even with restrictive parameters (-Wall), but this text does not appear in any place. By any place, I mean both output.txt and the standard output.
I am thinking that:
The command ./myCopier.exe alone clearly create an endless loop. Without text input there is no EOL character, hence the print() command is never reached.
So, why when the input is provided, the printf() command has no apparent effect? I'd expect the text from printf()to appear on the standard output, just when the loop closes and output.txt is created. Why does it not occur?
My theory is that ./myCopier.txt < rand.txt > randout.txt does not allow it. For some reason, it makes the program only transfer the input to the output, "ignoring" everything does not come from the input. Am I correct? If so, why?
If you are interested in the problem with deeper detail, here is the assembly code:
http://text-share.com/view/79f31f38
Omitting the return statement in main() causes undefined behavior in C89/C90.
Normally, returning from main() forces the output buffer to be flushed. If you omit the return statement, anything can happen.
Try to add return 0 at the end of main() as was required in C90. GCC in c90/gnu90 mode will warn you otherwise: "control reaches end of non-void function".
Try to add fflush(stdout);.
I write a program to print integer values using for loop and after printing, the program should wait one second, after that those integers are overwrite with double space character in other words the purpose of the program is to erase those integer after wait for one second.
This the program:
#include <stdio.h>
#include <time.h>
int main (void) {
int i;
for(i=1;i<=5;i++){
printf("%d ",i);
}
for(;clock () < CLOCKS_PER_SEC;){} /*wait for one second*/
printf("\r"); /*move to the beginning of the line*/
for(i=1;i<=5;i++){
printf(" "); /*overwriting the integers*/
}
printf("\n");
return 0;
}
The problem is in the wait loop loop brackets `for(;clock () < CLOCKS_PER_SEC;){}' when i
remove those brackets the program work properly. but if the for loop with brackets. the program doesn't work,I mean the program still runs but it overwrite the integer instead of showing those integers first.
please someone explain what happen?
When you remove the brackets, the printf("\r") statement becomes the body of the for loop, logically equivalent to this:
for(;clock () < CLOCKS_PER_SEC;) {printf("\r");}
So the integers get overwritten right away instead of after the end of the delay period.
Of course, the real question is why you are using a busy-loop for a delay rather than just calling sleep(1), which is much more efficient (i.e. it won't pin your CPU at 100% during the delay period)
You aren't flushing stdout (the stream that printf writes to) yourself so it doesn't happen until the '\r' is written, and then you immediately clear it.
If you remove the {}, then your loop is equivalent to
for(;clock () < CLOCKS_PER_SEC;)
printf("\r");
which writes a bunch of \r, the first of which flushes the output and the rest of which are redundant. After the loop completes, you clear the line, working as you want it to.
You should call fflush(stdout) after printing the numbers. Or you could move the printf("\r") so it comes before the wait loop (the difference being where the cursor ends up).
Your loop is problematic, as there's no guarantee that clock() starts at 0, and it won't on many systems, and you shouldn't spin like that ... it slows down other programs running on your system. You could just use sleep(1), although it's not very accurate.
I suspect somehow the output buffer is being flushed differently between the two cases. You could check this by manually flushing the buffer using fflush(stdout) before the problematic loop.
Also note that the {} aren't mandatory in C, for single-line statements within the loop.
Here is the code you might want:
#include <stdio.h>
int main(int argc, char * argv[]) {
int seconds = 10;
while(seconds>0) {
printf("%10d", --seconds);
fflush(stdout);
sleep(1);
printf("\r");
}
printf("%10s\n", "time up!");
return 0;
}
(Since you ask about what fflush() acturally is, here is a little explanation base on my understanding)
It's all about io cache, 1 reason cache exists is: read/write memory could be over 1000 times quicker than hard disk.
So program should try do reduce the frequence of read/write hard disk, and use memory instead, but need a proper tradeoff for the user experience and io delay.
e.g
When read a file by lines, it could read 2kb or so at once instead a single line, then could read from the memory cache,
When write to console, the program might choose to write to the memory cache until meet a \n or \t char, and some other case.
fflush(FILE * file), is a function from stdio.h, it flush the cache of specified FILE. In your case, the file is stdout(standard output), which print to your console. When you use printf() to print a single number, it might write to cache of stdout, so you didn't see it in console, but calling fflush(stdout) flush out the cache to your console.
On the first 'for' loop you are printing values using printf. Here 'printf' uses 'stdout' which is a buffered output- meaning output will not be printed unless '\n' is provided or buffer full. so you can either uses flush(stdout) after the first loop or uses fprintf(stderr, "") to print to standard error which is not a buffered output.
I am (re-)learning programming and I started with C. My IDE (if I may say so) is cygwin (32Bit) and Visual-Studio 2010 both on Windows7.
I am always compiling the code I write with gcc (cygwin) as well as with the VS2010 compiler. I do so, I guess, because I think it is a good way of learning.
Anyway I just learned about fflush(stdin), i.e. flushing the stdin buffer. Seems a good functionality because else, using scanf appears to be a pain.
So I wrote the code below based on an example from my text book. It compiles both with gcc in cygwin as well as with VS2010. When I run the VS compiled program it works fine (s.below), when I run the gcc compiled program in cygwin the fflush(stdin) does not flush the stdin buffer (s.below).
I have read some threads about fflush(stdin) having an undefined behaviour in some cases. Whatever that may mean, I took it from the C for Linux Programming textbook. If fflush(stdin) is not a valid means to get rid of stuff in the stdin buffer, what other standard method is there?
Thanks a lot for any answers!
==Program run under Windows:
enter a long integer and a double
23.00 78.99
lint = 23
dt = 0.00
enter a five digits input
78493
u entered 78 and 493
==Program run in Cygwin:
enter a long integer and a double
23.00 78.99
lint = 23
dt = 0.00
enter a five digits input
u entered 78 and 2665720
==CODE====
long lint;
double dt;
int fp, sp;
char fn[50], ln[50];
/* using the l modifier to enter long integers and doubles */
puts ("enter a long integer and a double");
scanf("%ld %lf", &lint, &dt);
printf("lint = %d\ndt = %.2f\n", lint, dt);
fflush(stdin); /*DOES NOT WORK UNDER CYGWIN!?*/
/* use field width to split input */
puts("\nenter a five digits input");
scanf("%2d %3d", &fp, &sp);
printf("u entered %d and %d\n", fp, sp);
C11 at 7.21.5.2.2 says (emphasis mine):
If stream points to an output stream or an update stream in which the most recent
operation was not input, the fflush function causes any unwritten data for that stream
to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined.
This means that you shouldn't call fflush on an input stream (unless you are writing code for a very specific operating system and library where the behavior is defined)
There is a good reason for it! You would normally think that fflush(stdin) would flush the line you have just entered, right? Well there's more to it. Imagine running your program like this:
$ ./program < input_file
In this case, all the file is theoretically already in the buffer of stdin. Therefore, flushing that buffer equals ending your input which is quite a useless operation. For such reasons, fflush cannot have a very sensible behavior on input streams and that's why it's undefined on them.
If you want to ignore the current line, there are better ways to do it. One example is the following:
void flush_line(FILE *fin)
{
int c;
do
{
c = fgetc(fin);
} while (c != '\n' && c != EOF);
}
This reads the input character by character and stops until either end-of-file, read error or end-of-line occurs.
In the standard, fflush() is not defined for input streams. In Microsoft's documentation it is explicitly defined.
The upshot is that while you can use it with Microsoft's C library with clearly defined behaviour, such behaviour is not portable.
If you want to use GCC and have this work, then you could use MinGW/GCC since that uses Microsoft's C runtime rather than glibc.
You should not fflush an input stream. The differences you observe came from the fact that the behaviour of this operations is undefined.
From what I understand, you are writing this program for Linux and believe it or not, fflush(stdin) only works under Windows. (That's at least what I got from my C book called C for dummies). The alternative for fflush(stdin) on Linux is fpurge(stdin). Try it out and see if it works for you.
After Mark Lakata pointed out that the garbage isn't properly defined in my question I came up with this. I'll keep this updated to avoid confusions.
I am trying to get a function that I can call before a prompt for user input like printf("Enter your choice:); followed a scanf and be sure that only the things entered after the prompt would be scanned in by scanf as valid input.
As far as I can understand the function that is needed is something that flushes standard input completely. That is what I want. So for the purpose of this function the "garbage" is everything in user input i.e. the whole user input before that user prompt.
While using scanf() in C there is always the problem of extra input lying in the input buffer. So I was looking for a function that I call after every scanf call to remedy this problem. I used this, this, this and this to get these answers
//First approach
scanf("%*[^\n]\n");
//2ndapproach
scanf("%*[^\n]%*c");
//3rd approach
int c;
while((c = getchar()) != EOF)
if (c == '\n')
break;
All three are working as far as I could find by hit-and-trial and going by the references. But before using any of these in all of my codes I wanted to know whether any of these have any bugs?
EDIT:
Thanks to Mark Lakata for one bug in 3rd. I corrected it in the question.
EDIT2:
After Jerry Coffin answered I tested the 1st 2 approaches using this program in code:blocks IDE 12.11 using GNU GCC Compiler(Version not stated in the compiler settings).
#include<stdio.h>
int main()
{
int x = 3; //Some arbitrary value
//1st one
scanf("%*[^\n]\n");
scanf("%d", &x);
printf("%d\n", x);
x = 3;
//2nd one
scanf("%*[^\n]%*c");
scanf("%d", &x);
printf("%d", x);
}
I used the following 2 inputs
First Test Input (2 Newlines but no spaces in the middle of garbage input)
abhabdjasxd
23
bbhvdahdbkajdnalkalkd
46
For the first I got the following output by the printf statements
23
46
i.e. both codes worked properly.
Second Test input: (2 Newlines with spaces in the middle of garbage input)
hahasjbas asasadlk
23
manbdjas sadjadja a
46
For the second I got the following output by the printf statements
23
3
Hence I found that the second one won't be taking care of extra garbage input whitespaces. Hence, it isn't foolproof against garbage input.
I decided to try out a 3rd test case (garbage includes newline before and after the non-whitespace character)
``
hahasjbas asasadlk
23
manbdjas sadjadja a
46
The answer was
3
3
i.e. both failed in this test case.
The first two are subtly different: they both read and ignore all the characters up to a new-line. Then the first skips all consecutive white space so after it executes, the next character you read will be non-whitespace.
The second reads and ignores characters until it encounters a new-line then reads (and discards) exactly one more character.
The difference will show up if you have (for example) double-spaced text, like:
line 1
line 2
Let's assume you read to somewhere in the middle of line 1. If you then execute the first one, the next character you read in will be the 'l' on line 2. If you execute the second, the next character you read in will be the new-line between line 1 and line 2.
As for the third, if I were going to do this at all, I'd do something like:
int ch;
while ((ch=getchar()) != EOF && ch != '\n')
;
...and yes, this does work correctly -- && forces a sequence point, so its left operand is evaluated first. Then there's a sequence point. Then, if and only if the left operand evaluated to true, it evaluates its right operand.
As for performance differences: since you're dealing with I/O to start with, there's little reasonable question that all of these will always be I/O bound. Despite its apparent complexity, scanf (and company) are usually code that's been used and carefully optimized over years of use. In this case, the hand-rolled loop may be quite a bit slower (e.g., if the code for getchar doesn't get expanded inline) or it may be about the same speed. The only way it stands any chance of being significantly faster is if the person who wrote your standard library was incompetent.
As far maintainability: IMO, anybody who claims to know C should know the scan set conversion for scanf. This is neither new nor rocket science. Anybody who doesn't know it really isn't a competent C programmer.
The first 2 examples use a feature of scanf that I didn't even know existed, and I'm sure a lot of other people didn't know. Being able to support a feature in the future is important. Even if it was a well known feature, it will be less efficient and harder to read the format string than your 3rd example.
The third example looks fine.
(edit history: I made a mistake saying that ANSI-C did not guarantee left-to-right evaluation of && and proposed a change. However, ANSI-C does guarantee left-to-right evaluation of &&. I'm not sure about K&R C, but I can't find any reference to it and no one uses it anyways...)
Many other solutions have the problem that they cause the program to hang and wait for input when there is nothing left to flush. Waiting for EOF is wrong because you don't get that until the user closes the input completely!
On Linux, the following will do a non-blocking flush:
// flush any data from the internal buffers
fflush (stdin);
// read any data from the kernel buffers
char buffer[100];
while (-1 != recv (0, buffer, 100, MSG_DONTWAIT))
{
}
The Linux man page says that fflush on stdin is non-standard, but "Most other implementations behave the same as Linux."
The MSG_DONTWAIT flag is also non-standard (it causes recv to return immediately if there is no data to be delivered).
You should use getline/getchar:
#include <stdio.h>
int main()
{
int bytes_read;
int nbytes = 100;
char *my_string;
puts ("Please enter a line of text.");
/* These 2 lines are the heart of the program. */
my_string = (char *) malloc (nbytes + 1);
bytes_read = getline (&my_string, &nbytes, stdin);
if (bytes_read == -1)
{
puts ("ERROR!");
}
else
{
puts ("You typed:");
puts (my_string);
}
return 0;
I think if you see carefully at right hand side of this page you will see many questions similar to yours. You can use fflush() on windows.
I have a weird issue with printing data out. I use printf to print a char* string and then after that print another one. However part of the first string doesn't get printed and when I print the second string the missing part of the first one is prepended to that one. What is happening here?
I'm writting a simple libpcap implimentation. Here is a sample callback function that will produce the same results. I tried removing buffering and adding a putchar('\n') after printing but it didn't help.
void ParseData(u_char* useless, const struct pcap_pkthdr* pkthdr, const u_char* packet){
int packetLen, i;
packetLen = pkthdr->len;
for (i = 0; i < packetLen; i++){
putchar(packet[i]);
}
}
stdio buffers characters. Unless you tell it otherwise, usually it will only actually issue a write when it sees a newline character. If you want a different behavior, you can remedy it with some of these:
After your first printf, call fflush(stdout); to flush the buffer.
Alternatively, call setbuf(stdout, NULL); to disable buffering. Do this before you do any printfs.
Bypass stdio by coding to platform specific APIs like write (POSIX) or WriteFile (Windows). Usually I would recommend against this, especially for something like stdout..
There is a possibility that your first printf is not having a '\n' at the end. In some cases the data might be buffered and printed together when a '\n' is encountered.
But, this is just a guess. Incase if you cannot post code, try the above.
It's called file stream buffering.
You can disable it or change the size of the buffer using setvbuf(). Or just fflush() after every print. However, the stream buffer is (normally) flushed when a line terminator (\n) is present.
I have a similar experience but this has more to do with double byte. I have 2 char* define back to back. I read some char into the first string. Turns out that is was double byte, so the remaining of the string spill over to the second string.