计算机软件技术基础实习day01

今天的主要内容是学会了如何使用双栈法实现四则运算,原理是
1、初始化两个栈,运算符栈s1和存储中间结果的栈s2
2、从左至右扫描中缀表达式
3、遇到操作数时,将其压入s2
4、遇到运算符时,将其与s1栈顶运算符的优先级进行比较:
如果s1为空,或栈顶运算符为左括号"(",则直接将此运算符入栈
否则,若优先级比栈顶运算符的高,也将运算符压入s1
否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4.1)与s1中的栈顶运算符相比较
5、遇到括号时:
如果是左括号"(",则直接压入s1
如果是右括号")",则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃
6、重复步骤2至5,知道表达式最右边
7、将s1中剩余的运算符以此弹出并压入s2
8、依次弹出s2中的元素并输入,结果的逆序即为中缀表达式对应的后缀表达式。

算法如下

#include<iostream>  
#include<string>  
#include<stack>  
#include<sstream>  
using namespace std;  
  
int getP(char ch)  
{  
    //获取优先级  
    if (ch == '(') return 1;  
    else if (ch == '+' || ch == '-') return 2;  
    else if (ch == '*' || ch == '/') return 3;  
    else return 4;  
}  
  
void calculate(stack<double> &opnd, char op)  
//参数1:当前操作数栈  
//参数2:运算符
{  
    double num1, num2, num3;  
    num2 = opnd.top();  
    opnd.pop();  
    num1 = opnd.top();  
    opnd.pop();
 
    if (op == '+') {  
        num3 = num1 + num2;  
    }  
    else if (op == '-') {  
        num3 = num1 - num2;  
    }  
    else if (op == '*') {  
        num3 = num1 * num2;  
    }  
    else if (op == '/') {  
        num3 = num1 / num2;  
    }  
    //思考1:计算过程输出显示
    cout<<num1<<op<<num2<<"="<<num3<<endl;
    opnd.push(num3);  
}  
  
double work(string str)  
{  
    //计算中缀表达式,默认输入是合法的  
    stack<double> OPND;//操作数栈 类型为double的栈 
    stack<char> OPTR;  //运算符栈 类型为char的栈,存char类型的字符 
    int i = 0, j;  
    int sz = str.size();//算式长度  
    char tmp_op; //存放临时存储操作符的变量 
    string tmp_num; //存放操作数的临时变量 
    while (i < sz) {  
        if (str[i] >= '0' && str[i] <= '9') {//是操作数  
            j = i;  
            while (j < sz && ((str[j] >= '0' && str[j] <= '9')||str[j]=='.')) { j++; }//可能是多位数 
            tmp_num = str.substr(i, j - i);  //字符串截取
            //double t=atoi(tmp_num.c_str());
            double t;
            stringstream ss;
            ss<<tmp_num;
            ss>>t; // 要把字符串转变为数字,并且入操作数栈
            OPND.push(t);
            //cout<<t<<endl;
            i = j;  
        }  
        else if (str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/') {//是运算符  
            if (OPTR.empty()) {//运算符栈为空 ,此时没有必要比较 
                OPTR.push(str[i]);  //直接入栈
            }  
            else {  //不为空,需要对比优先级
                while (!OPTR.empty()) {  
                    tmp_op = OPTR.top();//栈顶操作符(最近一次入栈的操作符)  
                    if (getP(tmp_op) >= getP(str[i])) { //如果栈顶运算符优先级大于当前运算符优先级,比如 * > + 
                        //计算  
                        calculate(OPND, tmp_op);//此时需要把前面的高优先级运算符[例如乘法]先计算 【必须先乘法再加法,不能拆开算】 
                        OPTR.pop();//这个运算符用过了,可以删掉了  
                    }  //开始下一次循环,继续对比
                    else break;  //如果栈顶运算符优先级小于当前运算符优先级,那么直接退出,因为:当前运算符优先级高,所以他先计算,他需要的操作数还没有进来。
                }  
                OPTR.push(str[i]);//当前运算符入栈  
            }  
            i++;  
        }  
    
        else {  //是括号
            if (str[i] == '(') OPTR.push(str[i]); //左括号直接入栈 
            else {  //是右括号
                while (OPTR.top() != '(') {//当没有遇到配对的左括号时  
                    tmp_op = OPTR.top();  //取栈顶的操作符
                    //计算  
                    calculate(OPND, tmp_op); //括号内计算 
                    OPTR.pop();  //计算完一次就删掉(出栈)一个运算符
                }  
                OPTR.pop(); //把最后的左括号也删掉(出栈) 
            }  
            i++;  
        }  
 
    }  
    //遍历完后,若栈非空,弹出所有元素  
    while (!OPTR.empty()) { 
        tmp_op = OPTR.top();  
        //计算  
        calculate(OPND, tmp_op);  
        OPTR.pop(); //每计算完一个二元操作符,则弹出该操作符 
    }  
    return OPND.top();  
}  
  
int main()  
{  
    string str;
    cout<<"请输入字符串:"<<endl;
    cin>>str;    
    double num_res = work(str);  
    cout << "计算结果:" << endl << num_res << endl;  
    system("pause");  
    return 0;  
}  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值