user731914
user731914

Reputation:

Why is the following program stuck in a loop?

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

Answers (7)

yasouser
yasouser

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

MSN
MSN

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

Francisco Soto
Francisco Soto

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

ruakh
ruakh

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

Alexis Wilke
Alexis Wilke

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

nmjohn
nmjohn

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

Scott Hunter
Scott Hunter

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

Related Questions