简体   繁体   中英

C++ Infix to Postfix Conversion and Calculator

I'm new to stackoverflow, and have final project for my Data Structures class in college. For my project, I am creating a calculator that takes a mathematical expression from input, such as (11-2)/3*(15+2/1)-6, and does two things:

1) Converts the expression from infix notation to postfix notation 2) Uses the postfix notation to evaluate the value of the expression

I have gotten fairly close to a final product, but my issue is that the program can only take numbers 0-9, as the way I currently have the code is that the conversion function evaluates the input as a string, and thus numbers greater than 9 (ie, double/triple digit numbers) will trip up the evaluation function. How can I detect these numbers as ints (or floats/doubles) and put them in a format (with the operators) that the evaluation function can deal with?

Additionally, I need to create exception class (incorrect parenthesis, division by zero, letters/non-operands/non-operators, etc). I have not learned much about what exception classes even are, so I'm not sure how I write these. I know it has to do with throw/catch functions, but any input is appreciated (or direction towards where I can find a simple explanation). I have pasted my code below:

#include <iostream>
#include <ctype.h>
#include <stack>
#include <ItemType.h>
using namespace std;

string getPostfix( string str );

double evaluate( string str );

bool hasPrecedence( char a, char b );

int main()
{
    cout << "Welcome to the calculator!" << endl;
    string infixString; 
    string postFixString;
    bool valid = false;
    cout << "Enter the expression you would like to evaluate: ";
    getline( cin, infixString );    // get expression as string
    postFixString = getPostfix( infixString ); // convert to postfix
    cout << postFixString << endl;
    cout << "The value of the given expression is: " << evaluate( postFixString ) << endl; // output evaluated expression

    return 0;
}

string getPostfix( string str ) // function to convert infix to postfix
{
    string postFixStr;  // converted string
    stack<char> stack;  // stack for operators
    for ( int i = 0; i < str.length(); i++ )
    {
        if ( isdigit( str[i] ) )    // if str[i] is a digit (0-9), add to postfix string
            postFixStr += str[i];

        else if ( str[i] == '(' )   // if str[i] is an opening parenthesis, push to stack
            stack.push( str[i] );

        else if ( str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/' )    // if an operator...
        {
            if ( stack.empty() || stack.top() == '(' ) // ... push to stack if stack is empty or top of stack is opening parenthesis
            {
                stack.push( str[i] );
            }

            else if ( hasPrecedence( str[i], stack.top() ) ) // ... if the operator has higher precedence, push to stack
            {
                stack.push( str[i] );
            }

            else // ... if neither of the above cases, add operator already in stack to string, pop it, and push the new operator to stack
            {
                postFixStr += stack.top();
                stack.pop();
                stack.push( str[i] );
            }
        }

        else if ( str[i] == ')' ) // ... if str[i] is closing parenthesis, add to string and pop until opening parenthesis is reached
        {
            while ( stack.top() != '(' )
            {
                postFixStr += stack.top();
                stack.pop();
            }
            if ( stack.top() == '(' )
                stack.pop();
        }
    }
    while ( ! stack.empty() ) // after string has been iterated, add the remainder of the stack to the string
    {
        postFixStr += stack.top();
        stack.pop();
    }
    return postFixStr;
} 

double evaluate( string str ) // function to evaluate postfix expression
{
    int op1, op2;
    stack<int> stack;
    for ( int i = 0; i < str.length(); i++ ) // iterate through postfix string
    {
        if ( isdigit( str[i] ) ) // if a digit, push to stack as int value
            stack.push( str[i] - 48 );
        else if ( str[i] == '+' ) // cases for different operators
        {
            op1 = stack.top(); // assign top int to op1
            stack.pop();       // pop top
            op2 = stack.top(); // assign next into to op2
            stack.pop();       // pop top
            stack.push( op1 + op2 ); // add op1 and op2, push result to stack
        }
        else if ( str[i] == '-' )
        {
            op1 = stack.top();
            stack.pop();
            op2 = stack.top();
            stack.pop();
            stack.push( op1 - op2 );
        }
        else if ( str[i] == '*' )
        {
            op1 = stack.top();
            stack.pop();
            op2 = stack.top();
            stack.pop();
            stack.push( op1 * op2 );
        }
        else if ( str[i] == '-' )
        {
            op1 = stack.top();
            stack.pop();
            op2 = stack.top();
            stack.pop();
            stack.push( op1 / op2 );
        }
    }
    return stack.top(); // return final value
}

bool hasPrecedence( char a, char b ) // function to determine operator precedence
{
    int aWeight, bWeight = 2;
    if ( a == '*' || a == '/' )
        aWeight = 2;
    else
        aWeight = 1;
    return aWeight >= bWeight;
}

Thanks everyone for the replies. After looking into the solutions you all posted and gathering ideas from them, I found a very simple solution to my specific case.

In my getPostFix function, I added spaces after every character inserted into the postFixStr, and then using these spaces as delimiters, I was able to add this to the first "if" statement in my evaluate function:

if ( isdigit( str[i] ) )
{
    double value = 0;
    while ( i < str.length() && isdigit( str[i] ) ) // if a digit, push to stack as double value
    {
        value = ( value * 10 ) + ( str[i] - '0' );
        i++;    
    }
    stack.push(value);
}

Note, the * 10 is to move the previous value in as the 10's place (or 100's+ place), and the -'0' is a slightly clearer version of the -49 that I had before to change the ascii value to the arithmetic value.

I hope this helps someone in the future!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM