0

So I made a simple calculator that takes two numbers and a basic operation (+,-,*,/) and then prints out the result, and also an error message is printed when anything other than those four operators is entered. But I have these questions that I couldn't quite find the answers for:

1-How do I make a while loop that makes the program print an Error message and asks the user to enter the two numbers and the operation again when anything other than a number is entered into either %d's in the scanf?

2- Why does the program print out the error message infinitely when anything other than numbers is entered into either %d's in the scanf or when I try to enter each variable seperately (For example: 10 Enter / Enter 5 Enter, the program starts printing out the error message infinitely after I press enter after the "/").

Here is my code:

#include <math.h>
#include <stdio.h>

int main()
{
 double n1=0.0,n2=0.0,result=0.0;
 char operation=' ';

 scanf("%lf%c%lf", &n1,&operation,&n2);

 while(operation!='+' && operation!='-' && operation!='*' && operation!='/')
    {
      printf("Error! Invalid Operator.\n");
      scanf("%lf%c%lf", &n1,&operation,&n2);
    }

 if(operation=='+')
   {
     result=n1+n2;
     printf("%f",result);
   }
 else if(operation=='-')
   {
     result=n1-n2;
     printf("%f",result);
   }
 else if(operation=='*')
   {
     result=n1*n2;
     printf("%f",result);
   }
 if(operation=='/')
   {
     result=n1/n2;
     printf("%f",result);
   }

 return 0;
}

OJScofield
  • 19
  • 3
  • 1
    `scanf` is, unfortunately, just terrible for this sort of thing. – Steve Summit Jun 13 '21 at 19:39
  • 3
    1. Always check `scanf`'s return value -- if it didn't match as many inputs as requested, something is wrong. 2. When `scanf` fails to match input, it *leaves the unmatched input on the input stream*, where it typically continues to cause problems. Problem #2 is unreasonably difficult to solve. The only reasonable way to handle erroneous inut is to [not use `scanf`](https://stackoverflow.com/questions/58403537). – Steve Summit Jun 13 '21 at 19:43
  • See also [this question](https://stackoverflow.com/questions/34219549/how-to-properly-flush-stdin-in-fgets-loop) and [this related answer](https://stackoverflow.com/questions/2979209/using-fflushstdin/58884121#58884121). – Steve Summit Jun 13 '21 at 19:48
  • @SteveSummit 1-How do I check scanf's return value? 2-What would you suggest using other than scanf? Something like gets maybe? – OJScofield Jun 13 '21 at 19:50
  • 2
    1. `if(scanf("%lf%c%lf", &n1,&operation,&n2) != 3) { complain; }`. 2. Definitely not `gets`; it's even worse. See [this question](https://stackoverflow.com/questions/58403537). – Steve Summit Jun 13 '21 at 19:51
  • 1
    Your scanf() is forcing the user to not enter whitespace (e.g.: 12*12 ) ... if they use whitespace (e.g.: 12 * 12 ) then an error occurs. if this is a requirement, then checking scanf()'s return code can be used to enforce it... however things get out of sync. Perhaps a scanf like this: scanf(" %lf %c %lf", &n1, &operation, &n2) (note the single space before both %lf, and the %c) which will consume optional whitespace, may work in both circumstances. – TonyB Jun 14 '21 at 06:54

1 Answers1

0

I hope this is what you're looking for. You don't need math.h for this and I also replaced the ifs with switch statement.

#include <stdio.h>

int main()
{
 double n1=0.0,n2=0.0,result=0.0;
 char operation=' ';
 /* char buf[10]; */
 int ch;
 while(1){
 while(scanf("%lf%c%lf",&n1,&operation,&n2)!=3){
    /* scanf("%[^\n]",buf); */
    while( (ch = getchar()) != EOF && ch != '\n' ){;} //Use this as user3629249 suggested as buf might overflow
    printf("Error.\n");
}
 switch(operation){
 case '+':
 result=n1+n2;
 printf("%lf",result);
 return 0;
 case '-':
 result=n1-n2;
 printf("%lf",result);
 return 0;
 case '*':
 result=n1*n2;
 printf("%lf",result);
 return 0;
 case '/':
 result=n1/n2;
 printf("%lf",result);
 return 0;
 default:
 printf("Error! Invalid Operator.\n");
 break;
 }
}
 return 0;
}
  • regarding `scanf("%[^\n]",buf);` with this input statement, the user can easily overflow the `buf[]` resulting undefined behavior. Suggest: `int ch; while( (ch = getchar()) != EOF && ch != '\n' ){;}` – user3629249 Jun 15 '21 at 01:21