Reputation:
I wrote a solution to an exercise that asks to write a program that acts as a simple "printing" calculator, and also detects division by zero and checks for unknown operators.
The program works as intended when expected operators are entered. For example:
"100 S" prints "= 100.000000"
"2 /" prints "= 50.000000"
"10 *" prints "= 500.000000"
It also detects division by zero and unknown operators.
However, when I enter operators in wrong order, like this: "/ 2" or "* 10", the program is stuck in a loop.
How do I fix this bug so that when the operators are entered in wrong order, it just prints "Unknown operator"?
// Write a program that acts as a simple "printing" calculator
#include <stdio.h>
int main (void)
{
float acc, b;
char operator;
printf ("Begin Calculations\n");
while ( operator != 'E') {
scanf ("%f %c", &b, &operator);
switch (operator)
{
case 'S': // set accumulator
case 's':
acc = b;
printf ("= %f\n", acc);
break;
case 'E': // end program
case 'e':
printf ("= %f\nEnd of Calculations.\n", acc);
break;
case '+':
printf ("= %f\n", acc += b);
break;
case '-':
printf ("= %f\n", acc -= b);
break;
case '*':
printf ("= %f\n", acc *= b);
break;
case '/':
if ( b == 0 )
printf ("Can't divide by zero.\n");
else
printf ("= %f\n", acc /= b);
break;
default:
printf ("Unknown operator.\n");
break;
}
}
return 0;
}
Update: I've found a solution
while ( operator != 'E' && operator != 'e' ) {
if ( scanf ("%f %c", &b, &operator ) < 2 ) {
printf ("Error. You need to enter a number.\n");
break;
}
else {
switch (operator)...
Upvotes: 0
Views: 1281
Reputation: 5187
However, when I enter operators in wrong order, like this: "/ 2" or "* 10", the program is stuck in a loop.
How do I fix this bug so that when the operators are entered in wrong order, it just prints "Unknown operator"?
You might want to read the entire expression and then parse it for correctness. There are various expression notation methods (infix, postfix (also known as reverse polish notation) and prefix (otherwise known as polish notation)) which makes the task of validating and evaluating them easier.
Also if you have or can get hold of the "The C Programming Language" book written by Dennis Ritchie and Brian Kernighan, turn to chapter 4 and read the section that walks you through the design and implementation of a calculator program.
Upvotes: 0
Reputation: 54634
The result of scanf
is the number of fields assigned. If scanf
returns 0, it will return 0
for the same format string every time you call it. Because scanf
pushes back the last character it read that does not match the input sequence (%f
), it will repeatedly try to convert the same string over and over.
That's why you loop infinitely. You might want to check the result of scanf
. If it's less than 2, error out.
Upvotes: 1
Reputation: 10392
The problem is that scanf() is trying to read what you told it to, that is, a floating point number and a character. When you type the other way around scanf returns because its not the format you told it too, but unfortunately it WONT flush the buffer, so the while would go again and scanf tries to read again, and so on.
Drop scanf, although if this is only for a homework you may try doing:
if (!scanf ("%f %c", &b, &operator)) {
scanf ("%*[^\n]"); /* TRY to flush stdin */
printf("Incorrect input!");
incorrect_input++;
continue;
} else {
incorrect_input = 0;
}
if (incorrect_input > 5) {
break; /* Very simple measure to avoid getting stuck in the loop */
}
Upvotes: 0
Reputation: 183544
It's not "stuck in a loop", it's waiting for the operator that this line:
scanf ("%f %c", &b, &operator);
promises. That line reads until it receives a floating-point number, and then it reads an operator. If you give it an operator first, it will simply ignore it.
(By the way, you should initialize operator
to something specific before getting to the line while ( operator != 'E') {
, because for all you know, operator
might happen to start out as 'E'
. Also, as Mysticial says, operator
isn't a great name for a C identifier, because of its uses in C++.)
Upvotes: 0
Reputation: 20818
I guess that to exit you need to enter a float + 'E' (0.0 E) and not just 'E'. Would that be what you're asking about?
Ah! I see you mentioned placing things backward. Yes. scanf() is never going to detect that.
If you're under Linux, check out lex and yacc (or flex and bison to be precise.) To do things like these, it's a lot better and you can make things a lot better (support parenthesis, minus and plus operator, instead of just add and subtract, etc.)
Upvotes: 0
Reputation: 1432
scanf is reading until it can parse a floating point number. Try using gets to read in a string and then parse that string from there.
http://www.cplusplus.com/reference/clibrary/cstdio/gets/
Upvotes: 0
Reputation: 49921
I think you would need to make your input routine more robust than scanf (apparently) is. For example, if you read your input in whole lines, you can parse them (say, using sscanf) to get the components w/o mucking up the input stream.
Upvotes: 0