This question already has answers here:
Why is my c != 'o' || c != 'x' condition always true? [duplicate]
(5 answers)
Closed 6 years ago.
Does anybody have any idea why this always loops for values different than 1 or 0,and also how can i avoid the endless loop in case of giving a character as input?
#include <stdio.h>
int a;
main()
{
do
{
puts("Give 1 or 0 for input:");
scanf("%d",&a);
} while(a!=0 || a!=1);
printf("\n%d",a);
return 0;
}
The only way for the loop to terminate is if both a!=0 and a!=1 are false. Or in other words: it can only end when a == 0 and a == 1 at the same time. That is of course impossible, so the loop never terminates.
If you want to loop to terminate when the user inputs 1 or 0, then you need a logical and operator there:
do
{
puts("Give 1 or 0 for input:");
scanf("%d",&a);
} while(a!=0 && a!=1);
Aside from that, you really must check the return value of scanf, and purge the input stream in case of failure. If you input a character, then scanf will signify it failed, but leave the character in the input stream. The subsequent iterations will just get stuck on trying to read that character.
One way to do so is with scanf itself and the %*s format specifier.
do
{
puts("Give 1 or 0 for input:");
int read_res = scanf(" %d",&a);
if (read_res != 1)
scanf("%*s");
} while(a != 0 && a != 1);
The asterisk in the format string means scanf will still match any non white-space character and purge them from the stream, but will not attempt to assign them into anything (so no extra parameter is required). I also added a leading white-space to %d in order to disregard any leading white-spaces before the number.
Related
This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
scanf Getting Skipped [duplicate]
(1 answer)
Why is adding a leading space in a scanf format string recommended?
(2 answers)
Closed 1 year ago.
I have an assignment in which I have to input dimensions of the first matrix, then which operation i would like to perform('-', '+' or '*'; subtraction, addition and multiplying respectively), and after that dimensions of the second matrix. But after entering first dimensions, I receive error message related to char. I cannot figure it out, even after reading a lot about whitespaces and errors related to scanf. Please help. Thank you
int main(void){
int rows_1 = 0, columns_1 = 0; //MATRIX_1 DIM
int rows_2 = 0, columns_2 = 0; //MATRIX_2 DIM
char c = ' ';
if(scanf("%d %d", &rows_1, &columns_1)!=2) //input first size
{
fprintf(stderr, "Error!\n");
return 100;
}
scanf("%c", &c);
if( c!='*' || c!='-' || c!='+' ) //error handling for char
{
fprintf(stderr, "Error!\n");
return 100;
}
if(scanf("%d%d", &rows_2, &columns_2)!=2) //input second size
{
fprintf(stderr, "Error!\n");
return 100;
}
return 0;
}
You have two problems:
The first is that c will contain the newline you pressed after the input for rows_1 and columns_1. Add a single leading space in the format string: " %c" to skip leading white-space (like newlines).
The second issue is that the logical condition is wrong and will always be true, no matter the input for c.
You probably want the opposite of c=='*' || c=='-' || c=='+', which according to De Morgan's laws is c!='*' && c!='-' && c!='+' (but you can also use the logical negation operator ! as in !(c=='*' || c=='-' || c=='+')).
This is rather easy to figure out if you think about it for a little. Lets say that c is a newline '\n'. Then c!='*' is true and due to the short-circuit evaluation of the logical operators, the remaining condition will not be evaluated. The same happens for any other character, including the ones you check for (exchange the newline for e.g. '-' and c!='*' will still be true; also try with '*' and then c!='*' will be false but c!='-' will be true).
This question already has answers here:
What is the effect of trailing white space in a scanf() format string?
(4 answers)
Closed 4 years ago.
Why it is asking for 4 input instead of 3 ?
I have used only 3 scanf in my program.
This is a program about finding smallest and largest number among 3 variables.
Please Help...
#include <stdio.h>
int main()
{
int first, second, third;
printf("Enter 3 integers for compare:");
scanf("%d\n",&first);
scanf("%d\n",&second);
scanf("%d\n",&third);
if((first>second) && (first>third))
printf("First number is the largest\n");
else if((second>first) && (second>third))
printf("Second number is the largest\n");
else if((third>second) && (third>first))
printf("\nThird number is the largest\n");
if((first<second) && (first<third))
printf("First number is smallest\n");
else if((second<first) && (second<third))
printf("Second number is smallest\n");
else if((third<second) && (third<first))
printf("Third number is smallest\n");
return 0;
}
Lets take your last call to scanf:
scanf("%d\n",&third);
The "\n" at the end of the format string means the scanf function will read and discard any white-space after the input, but it can't know when the white-space ends until there is something which is not a white-space character. That means you need to enter some extra input for scanf to be satisfied.
So the simple solution is to just don't have the newlines in your scanf format strings.
This question already has answers here:
What is the effect of trailing white space in a scanf() format string?
(4 answers)
Simple C scanf does not work? [duplicate]
(5 answers)
Closed 4 years ago.
I wrote this code for a school project and I have the following problem.
When I choose 1 at the first time, my program runs fine but as I choose w or r the second time, something goes wrong. None of the 2 ifs is running. I printed usr_ans2 to see the result of scanf and usr_ans2 variable is a weird question mark in a box and not a w or r character as I typed. Also I tried scanf(" %c", usr_ans2) . The question marks do not appear but the if commands are still not running.
int main(){
int usr_ans1;
char usr_ans2;
while(1){
printf("\nSelect action: (1-3)\n");
scanf("%d", &usr_ans1);
if(usr_ans1 == 1){
printf("Select to write or read from a file the text: (w/r) ");
usr_ans2 = scanf("%c", &usr_ans2);
if(usr_ans2 == 'w')
printf("You selected to write");
else if(usr_ans2 == 'r')
printf("You selected to read");
}
else if(usr_ans1 == 2){
printf("Example1");
}
else if(usr_ans1 == 3){
printf("Example2");
}
return 0;
}
scanf() in usr_ans2 = scanf("%c", &usr_ans2); will return 1 (the numbers of successfully converted specifiers) or EOF (some negative value like -1 when end-of-file or error occurs). if(usr_ans2 == 'w') will never be true.
Try
// usr_ans2 = scanf("%c", &usr_ans2);
scanf(" %c", &usr_ans2); // add the space too to skip leading white-space
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);
This question already has answers here:
Why is scanf() causing infinite loop in this code?
(16 answers)
Closed 9 years ago.
In line 5 I read an integer and isint is getting 1 if it reads an integer or 0 if it's not an integer. If isint is 0 I have a loop asking user to give an integer and I read until the user gives an integer. I try this code giving a character instead of an integer but I have an infinite loop. The program just doesn't wait to give a new input. What's wrong with my code?
#include <stdio.h>
int main(void) {
int arg1;
//int arg2;
int attacknum = 1;
int isint = 1;
//printf("Insert argument attacks and press 0 when you have done this.\n");
printf("Attack %d\n", attacknum);
attacknum++;
printf("Give attacking argument:");
isint = scanf("%d", &arg1); //line 5
while(isint == 0){
printf("You did not enter a number. Please enter an argument's number\n");
isint = scanf("%d", &arg1);
printf("is int is %d\n", isint);
}
return 0;
}
As others have mentioned, if scanf can't parse the input, it leaves it unscanned.
Generally scanf is a poor choice for interactive input because of this kind of behavior, and because it doesn't match the line-at-a-time interface experienced by the user.
You are better off reading one line into a buffer using fgets. Then parse that line using sscanf. If you don't like the input, throw the whole line away and read another one.
Something like this:
#include <stdio.h>
int main(void)
{
char line[256];
int arg1;
int isint;
while (1) {
printf("Give attacking argument:");
fgets(line, sizeof line, stdin);
isint = sscanf(line, "%d",&arg1);
if (isint) break;
printf("You did not enter a number.Please enter an argument's number\n");
}
printf("Thanks for entering %d\n", arg1);
return 0;
}
(For production code you'll want to handle long lines, check return codes, also check for trailing garbage after the number, etc.)
Actually, an even better approach would be to not use scanf if you just want to read an integer, and instead use strtol. That gives you a handy pointer to the character just after the number, and you can check that it's whitespace or nul.
When scanf is confronted with a non-digit it will not consume any input and return that zero integers were read. The non-digit will stay in the input for the next call to scanf that will behave the same as the first call, etc.
In answer to your question below. You could use fgetc to parse at least one character, but this will give the error messages for every character already typed. Typically I think you want to skip until a newline. To this end you could use fgets as suggested by poolie. Or you could add the following after scanf.
int ch;
if (isint == 0)
while ((ch = fgetc(stdin)) != EOF && ch != '\n')
{
/* Skip characters */
}
P.S: In your case it is probably better to put it just before the first printf in the loop.