This question already has an answer here:
Flushing buffers in C
(1 answer)
Closed 1 year ago.
I know about fflush(stdin) that it is undefined behavior according to standard. But when it comes to stdout, there is no such restriction. I did google to get the concept of using stdout as a parameter of fflush, but I couldn't get it.
Can someone elaborate the fflush function having stdout as a parameter with an easy example?
When printing (e.g. printf), the output is put into a buffer and may not be written to the console until a newline character is displayed. To ensure that everything in the buffer is written to the console, fflush(stdout) may be used.
One example is displaying the progress of some process:
for(int i = 0; i < 100; i++)
{
<...calculation...>
printf("."); // Print a dot after each iteration to show progress
fflush(stdout); // The dot may be buffered. This ensures that it is displayed immediately
}
Related
I am aware that most terminals are by default in line buffer mode. i.e. output is buffered and not directed to stdout until a new-line character is encountered.
So I would expect this to print nothing (at least before the buffer is filled up):
int main() {
while(1) {
printf("Haha");
sleep(1);
}
return 0;
}
It indeed prints nothing for a short period of time.
If I want to print "Haha" every second, I can either printf("Haha\n") or do fflush(stdout) after printf. (I know this is not so portable, but it's a solution nonetheless)
Now I recall the very classic scanf program (with my addition to while(1) loop to prevent buffer flushing on program exit):
int main() {
char char_in;
while(1) {
printf("Haha. Input sth here: ");
scanf("%c", &char_in);
}
return 0;
}
Now the program prints Haha. Input sth here: (and wait for my input). It is not here if I remove the scanf statement. Why is that so?
Thanks.
Now the program prints Haha. Input sth here: (and wait for my input). It is not here if I remove the scanf statement. Why is that so?
Because the standard (N1570 .. "almost C11") says so, §5.1.2.3/6 (emphasis mine):
The least requirements on a conforming implementation are:
[..]
The input and output dynamics of interactive devices shall take place as specified in 7.21.3. The intent of these requirements is that unbuffered or line-buffered output appear as soon as possible, to ensure that prompting messages actually appear prior to a program waiting for input.
[..]
Even though your output does not contain a newline and is send to a line buffered stdout, it has to appear before your program is allowed to wait for input. This is because stdout and stdin are connected to a terminal and thus are (Attention: This is implementation defined!) what the standard calls "interactive devices".
This question already has answers here:
if my scanf variable is a float and a user inputs a character how can i prompt them to input a number? assuming the scanf is inside a do while loop
(2 answers)
Why is scanf() causing infinite loop in this code?
(16 answers)
I am not able to flush stdin. How can I flush stdin in C?
(8 answers)
Closed 3 years ago.
i have a function that ask to the user to enter a value to calculate its square root, however when i try to validate that the number of the input must be a number and not a char, it makes an infinite loop
void opcion1(void){
float A, K, i, aux;
int awnser;
ask:
fflush( stdin );
printf("enter the value for A: ");
sleep(1);
awnser = scanf("%f", &A);
if(awnser < 1){ // not a number
fputs("\nA is not a number\n", stderr);
goto ask;
}
if(A < 0 ){
aux = -A;
i = sqrt(aux);
if(A == (int)A) printf("\nthe square root of %.0f, is%.0fi", A, i);
else printf("the square root of %.3f, is %.4fi", A, i);
}else{
K = sqrt(A);
printf("the square root of A is %.2f", K);
}
}
output:
enter the value for A:
k
A is not a number
enter the value for A:
A is not a number
enter the value for A:
A is not a number
enter the value for A:
A is not a number
enter the value for A:
The main issue is that its hard to understand all these concepts when you are just starting with the language. Like where the hell does scanf take the input? What is buffering?
I won't talk about technical terms, you can always google them if you want to go deep, will try to keep it simple. Also I am just talking from unix side and donno anything about windows.
scanf(3) calls read(2) internally and printf(3) calls write(2). So why don't we use read(2) and write(2) directly? The issue is that read(2)/write(2) are slow because for them a switch needs to be made to from user mode to kernel mode and this is a time taking process. What scanf() and printf() do is that they stay in user mode and collect the information there and read/write it in one go i.e. they store it in a buffer for time being.
Now this makes some more things possible. As the input hasn't reached your variable yet and is in the buffer, scanf() can do additional checks. Like in your case, check if the input is as per your format specifier. If not it won't assign it to your variable and return. But scanf won't clear that buffer where it received input. In your case in scanf(), when your input is not as per %f, it returns 0 and your if condition makes it go up and input again. But it never cleared the buffer. So the buffer contains the same input as from before and it acts again on it causing the same problem again. This continues infinitely.
Now to the solution:
This is a little confusing due to "standards" issue.
When you see the manpage of fflush(3),
It states:
For input streams, fflush() discards any buffered data that has been fetched from the underlying file, but has not been consumed by the application.
But then at the bottom of the page,
The standards do not specify the behavior for input streams. Most other implementations behave the same as Linux.
So fflush(stdin) doesn't seem to work like that on your system. (just as it doesn't on mine)
Best ways to achieve this have already been discussed in many questions:
How to solve your problem:
Scanf skips every other while loop in C
Better way:
Using fscanf() vs. fgets() and sscanf()
Another way is to change fflush(stdin) to fpurge(stdin)(ITS NOT PORTABLE AND NOT STANDARD).
From the manpage of fpurge(3) which I don't see being discussed anywhere:
The function fpurge() clears the buffers of the given stream. For
output streams this discards any unwritten output. For input streams
this discards any input read from the underlying object but not yet
obtained via getc(3); this includes any text pushed back via
ungetc(3).
Also have a look at why its not a good idea to use goto in such scenarios. What is wrong with using goto?
I am aware that most terminals are by default in line buffer mode. i.e. output is buffered and not directed to stdout until a new-line character is encountered.
So I would expect this to print nothing (at least before the buffer is filled up):
int main() {
while(1) {
printf("Haha");
sleep(1);
}
return 0;
}
It indeed prints nothing for a short period of time.
If I want to print "Haha" every second, I can either printf("Haha\n") or do fflush(stdout) after printf. (I know this is not so portable, but it's a solution nonetheless)
Now I recall the very classic scanf program (with my addition to while(1) loop to prevent buffer flushing on program exit):
int main() {
char char_in;
while(1) {
printf("Haha. Input sth here: ");
scanf("%c", &char_in);
}
return 0;
}
Now the program prints Haha. Input sth here: (and wait for my input). It is not here if I remove the scanf statement. Why is that so?
Thanks.
Now the program prints Haha. Input sth here: (and wait for my input). It is not here if I remove the scanf statement. Why is that so?
Because the standard (N1570 .. "almost C11") says so, §5.1.2.3/6 (emphasis mine):
The least requirements on a conforming implementation are:
[..]
The input and output dynamics of interactive devices shall take place as specified in 7.21.3. The intent of these requirements is that unbuffered or line-buffered output appear as soon as possible, to ensure that prompting messages actually appear prior to a program waiting for input.
[..]
Even though your output does not contain a newline and is send to a line buffered stdout, it has to appear before your program is allowed to wait for input. This is because stdout and stdin are connected to a terminal and thus are (Attention: This is implementation defined!) what the standard calls "interactive devices".
This question already has an answer here:
C's printf and fprintf(stdout,) are not printing
(1 answer)
Closed 6 years ago.
Just see the below program,
#include <stdio.h>
int main()
{
printf("hai");
while(1);
}
The above code is not printing hai and its just waitinG. But if I add
printf("hai\n");
its working.
Can I know what happening internally?
Writing printf("hai\n"); instead will cause, due to the newline character, the output buffer to be flushed, so you'll see the output before entering the infinite loop. There are other ways of flushing the output buffer, but appending the newline character is particularly simple.
Technically the behaviour of a tight loop like while(1); is undefined in C, but that is unlikely to be the cause of your problem.
printf("hai"); won't show something immediateley, you need to flush stdout's buffer with either printf("\n"); or fflush(stdout);
Your standart output stream (stdout) is buffered, so it will only flush (and display what is in it) when it is either manually forced or when it recieves a newline character ('\n').
You can change this behavior with the library function setbuf()
You can also manually flush the buffer (force it to immideatly display whats currently in it) by using fflush(stdout);
This question already has answers here:
Is there any way to peek at the stdin buffer?
(3 answers)
Closed 9 years ago.
I want to write a function that would tell me if stdin buffer is empty.
So, here's the code:
int buff_empty()
{
char buffer[3];
fgets(buffer, 3, stdin);
if(strlen(buffer) > 1) return 0;
return 1;
}
but the problem is - I don't want fgets() to wait for my input. I'm using my own function to read, for example, an integer, and then check with this func is buffer empty (was more than one number put) or not.
Function works well, but when I read a number (read function reads just to white space, just like scanf()), it waits for one breakline(Enter?) more. Is there any way to solve it?
Thanks in advance!
Part of the problem is that you are kind of asking the program to read your mind. When it reads (or tries to read) from the input, and there's nothing there, how does it tell the difference between there being no more input and the input just hasn't been entered yet?
The normal solution is to put the input into a separate file, and look for the end-of-file to tell when there is no more input. So when the program tries to read the next number, it hits the end of file and knows that there isn't any more input.
Try reading up on the feof() function, or the possible return values of fgets().