浙大复试机试之表达式求值

题目描述

    读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。

输入描述:

    测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。没有非法表达式。当一行中只有0时输入结束,相应的结果不要输出。

输出描述:

    对每个测试用例输出1行,即该表达式的值,精确到小数点后2位。

示例1

输入

1 + 2
4 + 2 * 5 - 7 / 11
0

输出

3.00
13.36

对于题目本身而言,学过数据结构的大体思路应该都能想到,但是具体实现会有各类问题,本题是我在复试过程中使用的《王道机试指南》一书中做到的,该题涉及到了所学到的栈以及优先级判别,字符串输入输出和相关处理等问题,涉及范围较广,个人认为自己实现还是难度挺大的,特将调试过程中的问题和注意点记下来,当作笔记,大神看到莫当真。

#include<iostream>
#include<cstdio>
#include<stack>
#include<cctype>
//isdigit()函数要用到
#include<string>
using namespace std;
int Priority(char c){ //优先级依次排序
    if(c=='#')
        return 0;
    else if(c=='$')
        return 1;
    else if(c=='+'||c=='-')
        return 2;
    else if(c=='*'||c=='/')
        return 3;
}
double GetNumber(string str,int &index){
    //获得下个数字
    double number = 0;
    while(isdigit(str[index])){
       //该函数在头文件cctype中,该函数能够用来检查字符是否为十进制数字自符
        //本题为过滤到空格以及运算符
        number = number*10+str[index]-'0';
        index++;
    }
    return number;  //返回的是对应的操作数
}
double Calculate(double x,double y,char op){
    double result = 0;
    if(op =='+')
        result = x+y;
    else if(op=='-')
        result = x-y;
    else if(op =='*')
        result = x*y;
    else if(op == '/')
        result = x/y;
    return result;
}
int main(){
    string str;
    while(getline(cin,str)){
        if(str=="0")
            break;  //终止条件
    
    int index = 0;        //字符串下标
    stack<char> oper;     //运算符栈
    stack<double>data;    //运算数栈
    str+='$';  //字符串尾部添加$
    oper.push('#');       //运算符栈底添加#
    while(index<str.size()){
        if(str[index]==' ') index++;           //略过空格
        else if(isdigit(str[index]))
            data.push(GetNumber(str,index));   //将对应的数字入栈
        else {  
       //比较运算符栈的栈顶元素与当前字符串中操作符的优先级高低
            if(Priority(oper.top())<Priority(str[index])){
                //优先级不如当前操作符的优先级高,因此入栈,字符串指针index后移
                oper.push(str[index]);
                index++;
            }
            else{ 
          //栈顶的操作符优先级更高,需要将放入运算数栈中的栈顶和次栈顶元素进行运算
                double y = data.top();
                data.pop();  //移除栈顶元素
                double x=data.top();
                data.pop(); //注意是x?y进行运算,注意前后顺序
                data.push(Calculate(x,y,oper.top()));
                //注意还要将运算符栈的栈顶元素移除
                oper.pop();
            }
        }
    }printf("%.2f\n",data.top());  //保留到后几位的方式要学会
  }
    return 0;
    
    
}

对于学习本题的一些总结:

1.对于栈的定义可以使用STL(标准数据库),简单明了,不需要将重心放在如何定义栈上

    固定格式问 stack <数据类型> 栈名 (运算符名可以定为 oper,运算数名可以定为 data)

    而相关的操作为 .push() 为入栈,.top()为取出栈顶元素,.pop()为移除栈顶元素 (注意这里的top操作之后常常跟着pop操作,下一次用来访问新栈顶元素)

2.对于优先级排序的Priority()函数可以适当移植到其他类似问题中,只要是涉及优先级或是表达式求值均可适当运用

3.对于将输入的字符串中的数字提取出来的GetNumber()函数是十分有效的,此函数可以用在类似与输入一个字符串提取所有数字等相关要求中,务必记住

4.此程序的作者运用两个例外的符号表示栈的结束(#) 和($)表示表达式的结束

下附该题目对应的牛客网OJ网址

https://www.nowcoder.com/practice/5759c29a28cb4361bc3605979d5a6130?tpId=63&tqId=29576&tPage=1&ru=/kaoyan/retest/9001&qru=/ta/zju-kaoyan/question-ranking

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值