This question already has answers here:
fflush(stdin) function does not work
(3 answers)
fflush() is not working in Linux
(9 answers)
Why fflush(stdin) does not remove buffer (stdin) [duplicate]
(2 answers)
How to clear input buffer in C?
(18 answers)
Closed 5 years ago.
This is the code which I'm trying to run on my Mac. In this the statement after fflush doesn't work. After fflush the compiler should stop and wait for the user input but it doesn't.
Can anyone tell me why this is happening or is there any other way to do it?
int main()
{
int pos,neg,zero,num;
char ans = 'y';
pos=neg=zero=0;
while(ans == 'y' || ans=='Y')
{
printf("\nEnter a number : ");
scanf("%d",&num);
if(num==0)
zero++;
if(num>0)
pos++;
if(num<0)
neg++;
fflush(stdin);
printf("\nDo you want to continue?\n\n");
scanf("%c",&ans);
}
printf("You entered %d positive numbers\n",pos);
printf("You entered %d negative numbers\n",neg);
printf("You entered %d zeros \n",zero);
return 0;
}
From standard 7.21.5.2
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.
You were having undefined behavior in your code. More clearly, fflush won't work. The most common way to do it would be something as shown below:
int c;
while ((c = getchar()) != '\n' && c != EOF){}
Another solution would be to use (much easier for you but not robust)
scanf(" %c",&ans);
^^
This will make sure all white space is being consumed. This will solve one of the problem that may arise, but not all. (The others arise due to use of scanf and wrong input).
Side note
Also another way to get rid of this problem altogether would be to use fgets or similar to read one line and then use strtol or strtod to get the desired input parsed from the inputted line. scanf is extremely useful for formatted input. The scenario which you will have - it is better to use fgets, there are too many cases with scanf that you have to deal with otherwise.
For wrong input you need to flush the standard input so that you don't have to deal with them again in the next scanf. If you use fgets then you will get the input line from the stdin and then if you can parse it and the input is correct - you go on processing it, else you discard the whole line and wait for the next fgets call.
Related
This question already has answers here:
The program doesn't stop on scanf("%c", &ch) line, why? [duplicate]
(2 answers)
Closed 1 year ago.
I'm struggling on a question proving scanf() and getchar() can both retrieve a character from the input.
However, when I try to put them inside the same program, only the first function is running properly. The latter is discarded completely.
#include <stdio.h>
char letter;
int main()
{
printf("I'm waiting for a character: ");
letter = getchar();
printf("\nNo, %c is not the character I want.\nTry again.\n\n",letter);
printf("I'm waiting for a different character: ");
scanf("%c",&letter);
printf("Yes, %c is the one I'm thinking of!\n",letter);
return(0);
}
output
I have tried switching the places of those two functions but it is of no use.
Can someone help me find the issue and provide a way to fix this? The only requirement is that the program takes input twice, once by the getchar() function and once via scanf()
The second read attempt just reads whitespace (the end of line character, since you pressed enter after the first letter). Simply replace it with this:
scanf(" %c", &letter);
The space before % will tell scanf to read the next non-whitespace character.
This question already has answers here:
fgets doesn't work after scanf [duplicate]
(7 answers)
Closed 1 year ago.
#include <stdio.h>
#include <string.h>
int main()
{
int num;
char answer[10];
char affirmation[10]="yes";
do
{
printf("Enter a number : \n");
scanf("%d",&num);
if (num % 97 == 0)
{
printf("No. is divisible by 97!\n");
}
else
{
printf("No. is not divisible by 97!\n");
}
printf("Once More ? [yes/no] \n");
fgets(answer,sizeof(answer),stdin);
}
while(strcmp(affirmation,answer) == 0);
return 0;
}
I expected from this program to check the divisibility of a provided number by 97 and then to ask if I again want it to check for another number if I input "yes". But it isn't prompting for my input .
If anybody can explain the reason behind this problem and suggest some ways to get through, it will be appreciated.The output is given below:
This output is for num = 194.
It is being executed but what it's reading is the newline character in the input stream that wasn't read when you did the scanf.
What your scanf does is to first skip any white space, then read an integer up to but not including the first non-digit character, which is probably the \n generated by the ENTER key.
Then, because fgets reads a line up to the next newline, you get an empty line.
In both the preceding two paragraphs, I'm assuming for simplicity ideal conditions such as ensuring it's a valid integer and that the line is not longer than the size you provided. Obviously, deviating from that could cause unruly behaviour.
It's generally not a good idea to mix the two input types unless you know in great detail what will be in the input stream. It's often better to just use line-based input and then sscanf that into more appropriate variables.
That way, you can be more sure about where your input stream is at any given point.
A quick fix in this particular case is simply to augment your scanf so that it skips to the start of the next line:
scanf("%d",&num);
while (getchar() != '\n') {}
The other problem you'll have after that is the fact that your fgets input will actually be "yes\n" rather than "yes", so that string comparison won't work.
If you're after a fairly robust line input function that takes care of that (and many other things), see here.
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?
This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 4 years ago.
I am implementing a Stack data structure using an array. To perform an operation on a stack like Push or Pop or Exit from Program, I am taking an input from a user in the form of an integer(Say 1 for Push).
For taking an input from a user continuously, I am running a while(1) loop and inside a loop asking a user to give an integer as an input for required operation.
Problem: during the execution, the program is not waiting for a user to give input and goes into infinite loop. I have tried to clear stdin using fflush but still not working.
Please look at the code below with given comments and help.
Thanks.
//Main function
int main(){
STACK marks, roll_number; //marks and roll_number are two stacks of type STACK
//Initialize both Stacks with required size
initStack(&marks, 10);
initStack(&roll_number, 10);
int choice, marks_data;
//Menu for user to choose from available operations
printf("1. Push\n");
printf("2. Pop\n");
printf("3. Exit\n");
//Taking user input for operations
while(1){
printf("Enter choice of Operation:\n");
//Clearing standard input. Although not a best practice but implementing to
//take user input
fflush(stdin);
// program is not stopping here and taking invalid choice
//hence executing 'default statement' of switch case
scanf("%d", &choice);
switch(choice){
case 1: printf("Enter Marks");
scanf(" %d", &marks_data);
push(&marks, marks_data);
break;
case 2: marks_data = pop(&marks);
printf("Deleted Data : %d\n", marks_data);
break;
case 3: exit(0);
default: printf("Invalid Choice of Operation !!\n");
}
//using to clear \n character from user and taking valid input
printf("Press Enter Key to continue...");
while(getchar() != '\n')
getchar();
}
return 0;
}
When you use scanf, you have to put your "account's hat" on and account for all characters either read from the input buffer, or left unread in the input buffer. This is especially true when mixing input between numeric and character input or when mixing input functions in your code.
In your case, you call scanf ("%d", ...) for choice and marks, but then attempt to control your loop execution with:
printf("Press Enter Key to continue...");
while(getchar() != '\n')
getchar();
As a good scanf accountant, you know reading using the '%d' format specifier will read digits from stdin up to the first non-digit character and terminate the read, leaving the non-digit character in stdin unread. (presuming no stray characters were entered following choice or mark), that will be the '\n' character generated by pressing Enter following your previous input.
When you test while(getchar() != '\n'), the first character read is likely the '\n' character, causing your loop to test TRUE and skip the getchar() call within the loop.
The easiest solution is just to add an additional getchar() below your current one.
Next fflush(stdin) is Undefined Behavior on just about all systems except windows. On Linux, fflush(stdin) is defined, but only for seekable streams -- which only applies to stdin if a file has been redirected to your program on stdin, e.g.
./yourexe < somefile.txt
Otherwise fflush(stdin) is not defined. So you have to ask yourself -- being non-portable on everything but windows unless stdin is seekable as the result of redirection -- "Is is really good practice to use anywhere?" and "How do I force the user to redirect a file to stdin?" (you can't). So best to avoid all the way around.
Look things over and let me know if you have further questions.
This question already has answers here:
Why does scanf appear to skip input?
(7 answers)
Closed 8 years ago.
Here i have a simplified piece of code that asks and displays a number on a loop, it works fine for all numbers i type in, But if i input a letter or a special character (!"£$%^&*-_=+ etc ) it goes mental and skips the input.
#include<stdio.h>
int number;
int main()
{
do
{
system("cls");
printf("Enter a number");
scanf("%d",&number);
}
while(1==1);
}
My question is, what can i do to stop this from happening?, is there some code that filters out this nonsense or is scanf pretty much worthless?
//Edit: This is somehow been marked as a duplicate, heh.
From here:
if the input doesn't conform to the expected format scanf() can be
impossible to recover sensibly [..] A "better" alternative here is to
use an input function like fgets() or fgetc() to read chunks of input,
then scan it with sscanf() or parse it with string handling functions
like strchr() and strtol().
scanf with %d will fail to scan an integer and returns 0 when a character was entered. So just check if it doesn't return 1. If it doesn't , a character was entered (if it returned 0) or else, an integer was entered. Note that if EOF was encountered, scanf will return -1.
if(scanf("%d", &number) != 1)//character entered
{
printf("Invalid input\n");
scanf("%*s");//clear the invalid character(s) from stdin
}
else
{
//a number was entered
}
The reason that scanf becomes "mental" and the program prints Enter a number many times when you enter a character is that when the scanf fails to scan an integer from the standard input stream(stdin), it returns 0 and the execution continues. When scanf is called the next time, it sees the characters which you had entered the last time and again fails and this process continues. To prevent it, just clear the stdin like I've done in the code above.
Another popular way of clearing the stdin is using:
int c;
while((c = getchar()) != '\n' && c != EOF);