Thread: Trouble with a simple calculator

  1. #1
    Registered User
    Join Date
    Oct 2012
    Posts
    4

    Question Trouble with a simple calculator

    Hello all,

    I have very recently started basic C-Programming and have decided to teach myself by trying to make a very basic calculator.

    The only issue I'm having is with validating that the input is in the form (Number) (operator) (Number).

    My operator validation works fine but if I type an invalid character for either of the numbers, I get an infinite loop of prinft("").

    If anyone could try and see what the problem is I would be much obliged.

    Thanks,

    Sam.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    int main(void)
    {
        /* Define variables and assign inital values for validation*/
        
        int        invalid_operator = 0, invalid_number = 0;
        char    operator;
        float    n1, n2, result, valid_input;
        
        /* Ask user for input and validate*/
        
        printf("Please enter two numbers and your operation in the format:\n (Number 1) (operator) (Number2)\n");
        if(3!=scanf("%f %c %f", &n1, &operator, &n2))
            invalid_number = 1;
            
        /* If input is not valid, start while loop - ask user to input values until correct format is obtained*/    
            
        while(invalid_number == 1)
        {
            printf("One or more of your inputs are invalid. Please enter your two numbers along with a valid operator (+, -, * or /) in the format:\n (Number 1) (operator) (Number2)\n");
            
            if(3!=scanf("%f %c %f", &n1, &operator, &n2))
                invalid_number = 1;
            else
                invalid_number = 0;
        }
                
        /* Once input is validated, attempt to perform operation requested*/
    
    
        if(operator == '+')
            result = n1 + n2;
        else if(operator == '-')
            result = n1 - n2;
        else if(operator == '*')
            result = n1 * n2;
        else if(operator == '/')
            result = n1 / n2;
        else
            invalid_operator = 1;
        
        /* If operator is not defined, start while loop - ask user to input values until valid operator is obtained*/
        
        while(invalid_operator == 1)
        {
            printf("Your operator is invalid. Please enter your two numbers along with a valid operator (+, -, * or /) in the format:\n (Number 1) (operator) (Number2)\n");
            scanf("%f %c %f", &n1, &operator, &n2);
            
            valid_input = (operator == '+') || (operator == '-') || (operator == '*') || (operator == '/');
                
            if(!valid_input)
                invalid_operator = 1;
            else
                invalid_operator = 0;
        }
        
        if(operator == '+')
            result = n1 + n2;
        else if(operator == '-')
            result = n1 - n2;
        else if(operator == '*')
            result = n1 * n2;
        else if(operator == '/')
            result = n1 / n2;
        
        /* Print result*/
        
        printf("The result of %f %c %f is: %f\n", n1, operator, n2, result);
        
        exit (EXIT_SUCCESS);
    }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    The problem is, scanf() does NOT discard any input if it can't make any sense of it.

    So if the next character is 'a', and you're trying %f, then scanf will get no further and just keep returning zero (no conversion made this time).

    To get back to a known state, read this FAQ
    FAQ > Flush the input buffer - Cprogramming.com

    > if(3!=scanf("%f %c %f", &n1, &operator, &n2))
    Operand reversal only ever made any sense when compilers were stupid, the operator was ==, and the natural left hand side was an l-value.
    Question 17.4

    Since two of these things are already false, and if you're using a modern compiler like GCC, then there isn't really any point to it.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Oct 2012
    Posts
    4
    Wow, thanks for the quick reply.

    Okay, so the scanf is always returning 0 for an invalid input, so why doesn't it return 0 and then repeat the while loop and ask for the user to input values again?

    Sorry if these questions are really bad =(.

    Thanks for the buffer suggestion, is there any way to do it without clearing the buffer?

    Am I right in assuming that the validation for the operators works because it also registers numbers as characters so the scanf still returns 3?

    I was under the impression also that the scanf function returned the number of values it successfully scanned :S? So if the user enters "a * 3" why does it return 0 and not 2?

    Thanks for the help!

    Edit: I am indeed using the GCC compiler by the way.
    Last edited by Impulse; 10-23-2012 at 12:11 PM.

  4. #4
    Registered User
    Join Date
    Sep 2012
    Posts
    357
    Quote Originally Posted by Impulse View Post
    ... so the scanf is always returning 0 for an invalid input, so why doesn't it return 0 and then repeat the while loop and ask for the user to input values again?
    Because it doesn't remove the character that originated the error from the input stream.
    Next time through the loop it reads the same character again, and, of course, gives the same error as before.

    Imagine you've asked for an integer (with "%d") but typed "boo".
    As soon as scanf() sees the 'b', it stops, puts the 'b' back in the input stream and returns an error.
    The next time a scanf() happens, the first thing it sees is that same 'b'.

    The safest way to get user input is with fgets() followed by a parsing of the input.

  5. #5
    Registered User
    Join Date
    Oct 2012
    Posts
    4
    OH I see! Thank you very much. I understand what you mean.

    I have heard fgets is much safer, I shall try this.

    Thank you to the both of you for your replies.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Simple Calculator
    By mmario10 in forum C Programming
    Replies: 19
    Last Post: 04-05-2012, 11:59 PM
  2. Simple Calculator By C
    By husam_elmutasim in forum C Programming
    Replies: 2
    Last Post: 06-28-2011, 05:58 PM
  3. simple calculator
    By symcy in forum C Programming
    Replies: 2
    Last Post: 02-05-2011, 12:04 PM
  4. simple calculator
    By symcy in forum C Programming
    Replies: 0
    Last Post: 02-05-2011, 11:21 AM
  5. very simple calculator
    By N_D_E in forum C Programming
    Replies: 4
    Last Post: 03-22-2010, 07:18 PM