Why the unexpected behaviour for scanf(" %f "... " %f "..." %c ")? - c

I am trying build a simple calculator. But whenever I input both the numbers, it skips straight to the default case and doesn't take in the input of operator. Here is my code -:
#include <stdio.h>
int main()
{
float num1, num2, result;
char opr;
printf("Enter the first number : ");
scanf(" %f ", &num1);
printf("\nEnter the second number : ");
scanf(" %f ", &num2);
printf("\nEnter the operation to be performed (+, -, *, /) : ");
scanf(" %c ", &opr);
switch (opr)
{
case '+' :
result = num1 + num2;
break;
case '-' :
result = num1 - num2;
break;
case '*' :
result = num1 * num2;
break;
case '/' :
result = num1/num2;
break;
default :
printf("\nWrong input.");
break;
}
printf("\nThe result is : %f", result);
return 0;
}
I tried to take the operator input twice and even left a space before "%c" so that it doesn't take newline as input. It skips straight to "Wrong input." section. Any help would be great.
Thank You.

The solution (as provided by Some programmer dude in comments here) is:
don't have trailing (or for almost all formats, leading) spaces in a scanf
Your comments indicate that you aready tried and verified that solution,
but have trouble understanding why it helps.
For visualisation, I modified your code without applying the solution, but with adding some helpful output.
#include <stdio.h>
int main()
{
float num1, num2, result;
char opr;
printf("Enter the first number : ");
scanf(" %f ", &num1);
printf("Got %f.\n", num1);
printf("\nEnter the second number : ");
scanf(" %f ", &num2);
printf("Got %f.\n", num2);
printf("\nEnter the operation to be performed (+, -, *, /) : ");
scanf(" %c ", &opr);
printf("Got %c.\n", opr);
switch (opr)
{
case '+' :
result = num1 + num2;
break;
case '-' :
result = num1 - num2;
break;
case '*' :
result = num1 * num2;
break;
case '/' :
result = num1/num2;
break;
default :
printf("\nWrong input.");
break;
}
printf("\nThe result is : %f", result);
return 0;
}
Try that code with the following input:
1.1<return>
1.2<return>
+<return>
*<return>
And you get the output (with input inbetween):
Enter the first number : 1.1
1.2
Got 1.100000.
Enter the second number : +
Got 1.200000.
Enter the operation to be performed (+, -, *, /) : *
Got +.
The result is : 2.300000
This is because:
1.1 gets scanned into num1, but not before a white space and a non-whitespace is found in input. This only happens with the first <return> and the first part of the second number 1.2. So you have to already enter the second number to make the first scanning work, because of the trailing whitespace in its format string. You have to do that before the prompt for the second number, because the prompt only gets to output after the fist scanning is done.
1.2 gets scanned into num2, but with the same problem, this time satisfied by the second <return> and the operator +. So you have to enter the operator before being prompted to.
+ gets scanned into opr, again with the same problem. It is already need before being prompted for, in order to satisfy the second scanning. It is not yet scanned, it just stops the scanning for a non-whitespace.
Then the prompt for the operator is in output, but at that point it was already required in input, though not being scanned yet.
Then the operator gets scanned into opr, but only if it is again followed by whitespace (the third <return>) and some non-whitespace (the *).
You can see that your program otherwise does as you programmed, yielding 1.1+1.2 being 2.3.

Related

When I add two integers it says invalid although supposedly it's for characters and symbols. Am I missing something?

In my calculator I tried firstly to make one operation functioning to have integers be displayed properly and when someone inputted a character it would say invalid.
When I input two integers it say's invalid. Not the actual sum of it.
#include <stdio.h>
#include <conio.h>
int main(){
char op;
int num1, num2;
int result;
printf("Enter (+, -, /, *): ");
scanf("%c", &op);
printf("Enter Two Integers: \n");
scanf("%d %d", &num1, &num2);
switch (op){
case '+':
result = num1+num2;
if(!(num1 == '+' && num2 == '+')){
printf("Invalid");
}
else{
printf("Sum: %d ", result);
}
break;
case '-':
result = num1-num2;
printf("Difference: %d ", result);
break;
case '/':
result = num1/num2;
printf("Quotient: %d ", result);
break;
case '*':
result = num1*num2;
printf("Product: %d ", result);
break;
default:
break;
}
getch();
return 0;
}
I expected that with that new line of condition it will make characters and symbols print "Invalid"
if(!(num1 == '+' && num2 == '+'))
This doesn't make any sense for several reasons. First of all De Morgan's laws and boolean algebra is often considered a prerequisite before studying any form of programming. By applying De Morgan/common sense, then we can tell that the opposite to "if num1 is + and num2 is +" is "if num1 isn't + OR num2 isn't +". That is:
if(num1 != '+' || num2 != '+') or if you will if(!(num1 == '+' || num2 == '+')).
With that logic flaw out of the way, this is the wrong solution to the the actual problem anyway. You simply want to prevent the user from entering a character - any character not just '+' - when expecting a number. The easiest way of doing that is to check the result of scanf - it returns a number corresponding to the number of arguments successfully read. For example:
int result;
do
{
result = scanf("%d %d", &num1, &num2);
if(result != 2)
{
printf("You must enter two numbers!\n");
}
}
while(result != 2);
Another option is to read the input as a string with fgets and then parse that string afterwards.
As a side note, please note that <conio.h> has been obsolete for well over 20 years and if someone taught you to use it, you need a more updated source of learning. The future for freshly graduated MS DOS programmers isn't very promising...
Be sure to check the return value of scanf to ensure it read the number of values you expected.
num1 and num2 are int variables and you are reading into them using the %d specifier. If you type in + or other symbols, scanf("%d %d", &num1, &num2) will return 0. A simple demonstration:
$ cat > testing.c
#include <stdio.h>
int main(void) {
int op;
int result = scanf("%d", &op);
printf("%d\n", result);
}
$ gcc testing.c
$ ./a.out
+
0
$ ./a.out
67
1
The odds that num1 and num2 uninitialized both contain the value '+' are not impossible but highly unlikely, so the most likely outcome is that "Invalid." is printed.
As noted in comments, 43 is the ASCII code for '+' so if these specific numbers are input, both num1 and num2 will test as equal to 43 and their sum (86) will be printed.

How to make this program ask for input again if invalid input is entered (in C programming)? [duplicate]

This question already has answers here:
Why is scanf() causing infinite loop in this code?
(16 answers)
Closed 5 years ago.
There are two different spots where the check happens.
That is, where you enter a, s, m, d, or q and when you enter the first and second number.
At any of the checks, if the check is false, it should ask you to re-enter your input.
I'm guessing this can be done by putting a scanf statement for the numbers part inside a while loop check, but when I enter an invalid value (non-number) the loop runs infinitely.
So I must be doing something wrong. I have made the a, s, m, d, and q part work for the most part.
But the second part never seems to work. For this, I left my failed attempts at the while loops out, and instead in //comments.
Any help would be greatly appreciated!
Here is my code so far:
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char ch;
float num1,num2,answer;
printf("Enter the operation of your choice:\n");
printf("a. add s. subtract\n");
printf("m. multiply q. divide\n");
printf("q. quit\n");
while ((ch = getchar())!='q')
{
printf("Enter the operation of your choice:\n");
printf("a. add s. subtract\n");
printf("m. multiply q. divide\n");
printf("q. quit\n");
ch=tolower(ch);
if (ch=='\n')
continue;
else
{
switch(ch)
{
case 'a':
//The code below is what I have tried to make work.
//This code would also be copy pasted to the other cases,
//of course with the correct operations respectively being used.
//
//printf("Enter first number: ")
//while(scanf("%f",&num1)==0)
//{
// printf("Invalid input. Please enter a number.");
// scanf("%f",&num1);
//}
//printf("Enter second number: ")
//while(scanf("%f",&num2)==0)
//{
// printf("Invalid input. Please enter a number.");
// scanf("%f",&num2);
//}
//answer = num1 + num2;
//printf("%f + %f = %f\n",num1,num2,answer);
//break;
//
//I have also tried to make this work using do-while loops
printf("Enter first number: ");
scanf("%f",&num1);
printf("Enter second number: ");
scanf("%f",&num2);
answer = num1 + num2;
printf("%f + %f = %f\n",num1,num2,answer);
break;
case 's':
printf("Enter first number: ");
scanf("%f",&num1);
printf("Enter second number: ");
scanf("%f",&num2);
answer = num1 - num2;
printf("%f - %f = %f\n",num1,num2,answer);
break;
case 'm':
printf("Enter first number: ");
scanf("%f",&num1);
printf("Enter second number: ");
scanf("%f",&num2);
answer = num1 * num2;
printf("%f * %f = %f\n",num1,num2,answer);
break;
case 'd':
printf("Enter first number: ");
scanf("%f",&num1);
printf("Enter second number: ");
scanf("%f",&num2);
answer = num1 / num2;
printf("%f / %f = %f\n",num1,num2,answer);
break;
default:
printf("That is not a valid operation.\n");
break;
}
}
}
return 0;
}
Again, thanks for any help!
Ya'll would be a life saver!
Cheers!
-Will S.
EDIT: I got my code to work! Here is the final code...
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char ch;
float num1,num2,answer;
printf("Enter the operation of your choice:\n");
printf("a. add s. subtract\n");
printf("m. multiply q. divide\n");
printf("q. quit\n");
while ((ch = getchar())!='q')
{
ch=tolower(ch);
//Ignore whitespace
if (ch=='\n')
continue;
else
{
switch(ch)
{
//Addition part
case 'a':
//First number
printf("Enter first number: ");
//Check to see if input is a number
while (scanf("%f",&num1)==0)
{
printf("Invalid input. Please enter a number, such as 2.5, -1.78E8, or 3: ");
scanf("%*s");
}
//Second number
printf("Enter second number: ");
while (scanf("%f",&num2)==0)
{
printf("Invalid input. Please enter a number, such as 2.5, -1.78E8, or 3: ");
scanf("%*s");
}
//Do math for respective operation
answer = num1 + num2;
//Print out result
printf("%.3f + %.3f = %.3f\n", num1,num2,answer);
break;
//Subtraction part
case 's':
printf("Enter first number: ");
while (scanf("%f",&num1)==0)
{
printf("Invalid input. Please enter a number, such as 2.5, -1.78E8, or 3: ");
scanf("%*s");
}
printf("Enter second number: ");
while (scanf("%f",&num2)==0)
{
printf("Invalid input. Please enter a number, such as 2.5, -1.78E8, or 3: ");
scanf("%*s");
}
answer = num1 - num2;
printf("%.3f - %.3f = %.3f\n", num1,num2,answer);
break;
//Multiplication part
case 'm':
printf("Enter first number: ");
while (scanf("%f",&num1)==0)
{
printf("Invalid input. Please enter a number, such as 2.5, -1.78E8, or 3: ");
scanf("%*s");
}
printf("Enter second number: ");
while (scanf("%f",&num2)==0)
{
printf("Invalid input. Please enter a number, such as 2.5, -1.78E8, or 3: ");
scanf("%*s");
}
answer = num1 * num2;
printf("%.3f * %.3f = %.3f\n", num1,num2,answer);
break;
//Division part
case 'd':
printf("Enter first number: ");
while (scanf("%f",&num1)==0)
{
printf("Invalid input. Please enter a number, such as 2.5, -1.78E8, or 3: ");
scanf("%*s");
}
printf("Enter second number: ");
while (scanf("%f",&num2)==0)
{
printf("Invalid input. Please enter a number, such as 2.5, -1.78E8, or 3: ");
scanf("%*s");
}
//Check for if number is a zero
while (num2==0)
{
printf("Please enter a non-zero number, such as 2.5, -1.78E8, or 3: ");
while (scanf("%f",&num2)==0)
{
printf("Invalid input. Please enter a number, such as 2.5, -1.78E8, or 3: ");
scanf("%*s");
}
}
answer = num1 / num2;
printf("%.3f / %.3f = %.3f\n", num1,num2,answer);
break;
//For if a non-valid operation is entered
default:
printf("That is not a valid operation.\n");
break;
}
}
printf("Enter the operation of your choice:\n");
printf("a. add s. subtract\n");
printf("m. multiply q. divide\n");
printf("q. quit\n");
}
printf("Bye.\n");
return 0;
}
Looking back at it, I probably could do without the if/else statement.
There are multiple problems with your code. First of all in this loop
You are taking input two times on failure
while(scanf("%f",&num1)==0) //Taking Input Here Once
{
printf("Invalid input. Please enter a number.");
scanf("%f",&num1); //Again Taking input.
}
Instead what you wanted was to check the return value of the scanf() and if it was 0 you would execute the loop again, so this would be the way to do that:
int l = 0;
while(l==0){ //Checking l, if it is zero or not, if zero running loop again.
printf("Invalid input. Please enter a number.");
l = scanf("%f",&num1); //Storing Return Value of scanf in l
}
When the program will encounter any line with scanf("%f" , &num1) or scanf("%f" , &num2), it will skip all the white spaces and wait for next input. In the case where the input does not match the format specification, then the input isn't consumed and remains in the input buffer.
int l = 0;
while(l==0){ //Checking l
printf("Invalid input. Please enter a number.");
l = scanf("%f",&num1); //scanf will look at the buffer if the input
//does not match, it will not be consumed
//and will remain in buffer.
}
In other words, the character that doesn't match is never read. So when you type e.g. an a character, your code will loop indefinitely as scanf continues to fail on the same character.
When the program executes its last scanf("%f",&num2) call then because of the enter there is a newline \n character present in buffer and so due to ch = getchar(), new line \n gets stored in ch and the following if condition satisfies and the loop execute again.
if(ch =='\n')
continue;
while(scanf("%f",&num1)==0)
{
printf("Invalid input. Please enter a number.");
scanf("%f",&num1);
}
This loops scans two numbers per iteration. This is not what you want. Lose the second scanf.
You should also check for EOF and errors.
int result;
while((result = scanf("%f",&num1))==0)
{
printf("Invalid input. Please enter a number.");
}
if (result == EOF) .... report an error and exit ...

Using switch statement to make a simple calculator

I created a program of using 'switch' statement to make a simple calculator. If I first take the integer output & then the operator output, the value of b is always shown '0'. (the code is given here) However, if I first take the operator output, the program works just fine. What may be the reason for this? Thanks.
int a;
int b;
char sign;
printf("Enter two required integers: ");
scanf("%d", &a);
scanf("%d", &b);
printf("Enter the operator(+ or - or * or /): ");
scanf(" %s", &sign);
switch(sign){
case '+': printf("The summation of %d and %d is %d", a,b, a+b);
break;
case '-': printf("The subtraction of %d and %d is %d", a,b, a-b);
break;
case '*': printf("The product of %d and %d is %d", a,b, a*b);
break;
case '/': printf("The division of %d and %d is %d", a,b, a/b);
break;
default: printf("Enter the right operator noob!");
}
return 0;
}
scanf(" %s", &sign);
this is not correct. sign is char so it can only store 1 character, but you are trying to read a string which would need more than 1 characters so that would override the memory.
Rather use
scanf(" %c", &sign);
This is a basic question. You should keep in mind that a char can contain a single character from the keyboard. On the other hand, when you do character variable input or output, you should use %c for this purpose. On the other hand, we know, a string is built with multiple character combination. String variable is declared with char
variable[size];
And for string input or output, you need to use %s. As you used no 'string' here, you need to replace %s with %c and that should solve your issue!

c - char variable proceeds without taking input

I have written a program to take input of two numbers and either add or subtract the numbers depending the operation specified.
Here is my code :
#include <stdio.h>
#include <stdlib.h>
int main()
{
float i, j, k;
char a;
printf("This is a program to add or subs two number.\n");
printf("Enter the first number : ");
scanf("%f", &i);
printf("Enter the second number : ");
scanf("%f", &j);
printf("Give your choice(+ or -): ");
scanf("%c", &a);
switch(a){
case '+' :
k = i + j;
printf("Sum = %f\n", k);
break;
case '-' :
k = i - j;
printf("Difference = %f\n", k);
break;
default:
printf("Cannot do this operation\n");
}
return 0;
}
This program takes input for the two numbers but skips input for operation and runs the default case. Please help!
(I am using gcc compiler).
The %c conversion specifier won't automatically skip any leading whitespace, so if there's a stray newline in the input stream (from a previous entry, for example) the scanf call will consume it immediately.
One way around the problem is to put a blank space before the conversion specifier in the format string:
scanf(" %c", &a);
The blank in the format string tells scanf to skip leading whitespace, and the first non-whitespace character will be read with the %c conversion specifier.
-Aditya

Switch small program does not let me see result

I am learning the switch statement of C. This is my small program and it runs and does the calculation but doesn't let me see the result of the operation. The black window shows up so that I input the numbers and the operator and then for a fraction of a second shows the result and disappears. Any help is appreciated.
#include <stdio.h>
int main(int argc, char *argv[])
{
int num1, num2, ans=0;
char ch, name;
printf("Enter a value: ");
scanf("%d", &num1);
printf("Enter a second value: ");
scanf("%d", &num2);
printf("Input * To multiply\
+ To add\
- To subtract: ");
scanf(" %c", &ch);
switch(ch)
{
case'*':
ans=num1 * num2;
printf("%d times %i equals: %i",num1,num2,ans);
break;
case'+':
ans=num1+num2;
printf("%i plus %i equals: %d",num1,num2,ans);
break;
case'-':
ans=num1-num2;
printf("%d minus %d equals: %d",num1,num2,ans);
break;
default:
printf("Range numbers");
}
getchar();
return ch;
}
Probably due to output buffering. Add newlines (\n) last in your formatting strings.
As a newbie, you should end all your printf format string with an escaped newline \n, i.e. printf("%i plus %i equals %d\n", num1, num2, ans); (or you should call fflush(stdout); just after the end of the switch before the getch and before all your scanf).

Resources