数据结构(3)

题目描述

计算非负整常数四则运算表达式,可用的运算符有:+ - * / ( ) 。

输入格式

一组非负整常数四则运算表达式,每个表达式输入一行,长度不超过1024个字符,每对括号内一定包含数字。

输出格式

每个表达式的计算结果输出一行,错误的表达式输出error。

输入样例 

12+5
-4-7
3-*5
((12-3)/2)+5
3+7/(2-2)

输出样例 

17
error
error
9
error

数据范围与提示

算法流程:

E1:设立运算符栈和操作数栈;

E2:开始运算符#入栈,向表达式串尾添加结束运算符#;

E3:逐词读入表达式,并处理:

    E31:若读入为操作数,则入栈;

    E32:若读入为运算符,则与栈顶运算符相比较:

        E321:若栈顶运算符优先级高于读入运算符:
                     弹出栈顶运算符和两个操作数,计算并将结果入栈,执行步骤E32;

        E322:若栈顶运算符优先级低于读入运算符:
                     则将读入运算符入栈,执行步骤E3;

        E323:若栈顶运算符优先级等于读入运算符:
                     若为#,计算结束,若为括号,则弹出运算符,执行步骤E3。

E4:检查栈状态,得到计算结果; 

#include<iostream>
#include<string>
#include<stack>
#include<cctype>

using namespace std;
int func(string org)
{
    int temp=0;
    stack<char> test;
    int num[1024]={0};
    int index=0;
    char op[1024];
    stack<int> number;

    int flag=0;
    for(int i=0;i<org.length();i++)
    {
        char tp=org[i];
        if(isdigit(org[i]))
        {
            temp*=10;
            temp+=org[i]-'0';
            flag=1;
        }
        else
        {
            if(flag){
                num[index]=temp;
                op[index]='!';
                index++;
                flag=0;
                temp=0;
            }
            if(org[i]=='#'){
                while(!test.empty())
                {
                    op[index++]=test.top();
                    test.pop();
                }
                break;
            }
            else{
                if(test.empty()||org[i]=='(')
                {
                    test.push(org[i]);
                }
                else if(org[i]==')'){
                    while(!test.empty()&&test.top()!='(')
                    {
                        op[index++]=test.top();
                        test.pop();
                    }
                    if(!test.empty())  test.pop();
                    else return -1;
                }
                else if(org[i]=='*'||org[i]=='/'){
                    while(!test.empty()&&(test.top()=='*'||test.top()=='/'))
                    {
                        op[index++]=test.top();
                        test.pop();
                    }
                    test.push(org[i]);
                }
                else{
                    while(!test.empty()&&test.top()!='(')
                    {
                        op[index++]=test.top();
                        test.pop();
                    }
                    test.push(org[i]);
                }
            }
        }
    }
    int temp1=0,temp2=0;
    for(int i=0;i<index;i++)
    {
        if(op[i]=='!')
        {
            number.push(num[i]);
        }
        else
        {
            temp1=number.top();
            number.pop();
            if(number.empty()) return -1;
            temp2=number.top();
            number.pop();
            switch(op[i])
            {
                case '+':
                    number.push(temp2+temp1);
                    break;
                case '-':
                    number.push(temp2-temp1);
                    break;
                case '*':
                    number.push(temp2*temp1);
                    break;
                case '/':
                    if(temp1==0) return -1;
                    number.push(temp2/temp1);
                    break;
            }
        }
    }
    return number.top();
}
int brackets(string org)
{
    int mark=0;
    for(int i=0;i<org.length();i++)
    {
        if(org[i]=='(') mark++;
        if(org[i]==')') mark--;
    }
    return mark;
}
int main()
{
    string org;
    while(cin>>org)
    {        
        if(brackets(org))
        {
            cout<<"error"<<endl;
        }
        else
        {
            org+='#';
            int result;
            result=func(org);
            if(result==-1)
            {
                cout<<"error"<<endl;
            }
            else cout<<result<<endl;
        }
    }
    return 0;
}

 写了半天,最后借鉴了大佬的代码。

  • 头文件和命名空间

    • 引入了 <iostream>, <string>, <stack>, 和 <cctype>,用于输入输出、字符串处理、栈操作及字符判断。

  • func 函数

    • 负责将输入字符串(表达式)转换为后缀表达式,并计算其值。

    • 使用两个栈:一个字符栈 test 用于存储运算符,另一个整型栈 number 用于存储操作数。

    • 循环遍历输入字符串,处理数字、运算符和括号:

      • 当遇到数字时,将其拼接成完整的数字。

      • 遇到运算符时,根据优先级进行处理,并将结果存入 op 数组。

      • 遇到括号时,按照括号的规则进行入栈和出栈。

  • brackets 函数

    • 检查表达式中的括号是否匹配,通过计数左括号和右括号的数量来实现。

  • main 函数

    • 循环读取用户输入的表达式,检查括号匹配,若不匹配则输出“error”。

    • 将表达式末尾添加 # 作为结束标志,调用 func 计算结果,若结果为 -1,则输出“error”;否则输出计算结果。

对func函数详细分析

        temp: 用于临时存储当前读取的数字。

        test: 一个字符栈,用于存储操作符。
        num: 存储读取到的数字。
        index: 数组 num 和 op 的索引,用于记录操作数和操作符的数量。
        op: 存储操作符(如 +、-、*、/)。
        number: 一个整数栈,用于存储操作数。
        flag: 标记当前是否正在读取一个数字。

        负责将输入字符串(表达式)转换为后缀表达式,并计算其值。

1. 操作符的处理

操作符的处理分为两部分:处理栈的逻辑和操作符的优先级。

2. 处理括号的逻辑

  • 左括号 (:

    • 如果栈为空或当前字符是 (,则直接将其推入栈中。

    • 这表明我们遇到了一个新的子表达式。

  • 右括号 ):

    • 当遇到右括号 ) 时,程序需要将栈中操作符弹出直到遇到左括号 (

    • 弹出过程中,将操作符存入 op 数组。

    • 如果没有找到对应的左括号,返回错误 -1。

  • 处理乘法和除法操作符

    • 对于乘法 * 和除法 /,由于它们的优先级较高,程序需要在推入当前操作符之前,检查栈中是否已经有相同或更高优先级的操作符。

    • 如果有,则将它们弹出并存入 op 数组。

  • 处理加法和减法操作符

    • 对于加法 + 和减法 -,处理逻辑类似于乘法和除法,但需要注意的是,加法和减法的优先级较低。

    • 只要遇到操作符,就弹出所有在栈中的操作符,直到遇到左括号为止。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值