数据结构 用栈实现四则混合运算

实验目的:

       利用“栈”完成一定程度的四则混合运算,四则运算表达式应以字符串形式读入。该段程序要实现的基本功能是实现“十以内的加减乘除运算”,在实现四则运算的简单功能后,可以考虑让表达式的第一项为负数,还可以考虑括号、乘方运算,同时将数值范围从十以内的整数扩展到有理数,通过该计算器程序的编写更好的理解与运用栈。

实验思路:

样例: 

① 输入:-3.14+2*15-7^2+(12*3)

     输出:13.860

输入:-77+54*3^2-(19+3*5)

    输出:375.000

输入:79/4+51*(4.5*21+14^3)

     输出:144783.250

实验代码:

/*
基础要求:以字符串形式输入一个包含加减乘除等运算符号的四则混合运算表达,
利用栈计算该表达式的值,表达式中的数值在0-9之间。 
进阶:字符串中的一个字符为负号,运算符中增加括号、乘方等运算符,
表达式中的数值大于等于10,表达式中的数值为小数 
范例:
①21*(5-17)+6^2
A:-216 
*/
#include<stdlib.h>
#include<stdio.h>
#include <iostream>
#include <string>
#include <ctype.h>
#include <set>
#include <queue>//c++队列 
#include <stack>// C++栈 
#include <map>//C++中关联容器map ,本段代码中使用insert、find、empty函数 
#include <math.h>//乘方运算中调用pow() 
using namespace std;
//判断是否为操作符,操作符——true;否则——false;
bool is_operator(char ch) {
    set<char> operator_set;
    operator_set.insert('+');
    operator_set.insert('-');
    operator_set.insert('*');
    operator_set.insert('/');
    operator_set.insert('%');
    operator_set.insert('^');
    return operator_set.find(ch) != operator_set.end();
}
// 比较两个操作符的优先级
int compare_priority(char a, char b) {
    map<char, int> operator_priority;
    operator_priority.insert(make_pair('+', 1));
    operator_priority.insert(make_pair('-', 1));
    operator_priority.insert(make_pair('*', 2));
    operator_priority.insert(make_pair('/', 2));
    operator_priority.insert(make_pair('%', 2));
    operator_priority.insert(make_pair('^', 3));
    return operator_priority[a]-operator_priority[b];
}
//处理一元操作符 '+'和'-'
string preprocess(const string infix) {
    string result = infix;
    set<char> valid_char_set;
    for(int i=0; i<=9; i++) {
        valid_char_set.insert(i+'0');
    }
    valid_char_set.insert('+');
    valid_char_set.insert('-');
    valid_char_set.insert('*');
    valid_char_set.insert('/');
    valid_char_set.insert('%');
    valid_char_set.insert('^');
    valid_char_set.insert('(');
    valid_char_set.insert(')');
    valid_char_set.insert('.');//小数点
 
    for(int i=0; i<result.size(); i++) {
        //如果字符不在valid_char_set,说明有不能处理的字符,结束程序
        if(valid_char_set.find(result[i]) == valid_char_set.end()) {
            printf("存在非法字符!!!");
            exit(-1);}
    }
    //处理一元操作符
    for(int i=0; i<result.size(); i++) {
        char temp = result[i];
        if(temp != '+' && temp != '-') {
            continue;
        }
        if(i==0) result.insert(i, 1, 0+'0');
		else if(i-1>=0 && !isdigit(result[i-1]) && result[i-1]!=')') { //一元+-,紧跟着其他符号后面
            result.insert(i, "(0");
            int j = i+3;
            int bracket_count=0;//如果有括号,应包含括号
            for(; j<result.size(); j++) {
                if(isdigit(result[j]) || result[j]=='.') continue;
               else if(result[j]=='(') ++bracket_count;
               else if(result[j]==')'){
                    if((--bracket_count) == 0)break;
                    else if(bracket_count==0)break;}
            }
            i = j;
            result.insert(j, ")");
        }
    }
    return result;
}
//中缀表达式--后缀表达式
queue<string> infix_to_post(string infix) {
    queue<string> postfix;//后缀表达式队列
    stack<char> operator_stack;//转换过程中,用来存储操作符的栈
    set<char> valid_operand_set;//操作数中的字符
    for(int i=0; i<=9; i++) {
        valid_operand_set.insert(i+'0');
    }
    valid_operand_set.insert('.');
    for(int i=0; i<infix.size(); i++) {
        char ch = infix[i];
        if(infix[i]=='(') {//左括号
            operator_stack.push(infix[i]);
        } else if(infix[i]==')') {//右括号
            while(!operator_stack.empty() && operator_stack.top()!='(') {
                postfix.push(string(1, operator_stack.top()));
                operator_stack.pop();
            }
            operator_stack.pop();//将"("出栈
        } else if(is_operator(infix[i]) == true) { //是操作符(不包含 左、右括号)
            if(operator_stack.empty()) { //操作符栈为空
                operator_stack.push(infix[i]);
                continue;
            }
            //操作符栈非空
            char top_stack = operator_stack.top();
            //将栈中'较高和相等'优先级的操作符放到 后缀表达式中。
            //终止条件为:当前操作符>栈顶操作符优先级,或优先级相等、但栈顶操作符的结合性是“从右向左”。
            while(compare_priority(infix[i], top_stack)<=0) {
                //优先级相等,但栈顶操作符结合性为从右向左,这里特指'^'
                if(compare_priority(infix[i], top_stack)==0 && infix[i]=='^') {   //因为'^'的结合性从右向左,所以单独处理
                    break;
                }
                //当前操作符<=栈顶操作符优先级,当前操作符结合性为从左到右
                postfix.push(string(1, top_stack));
                operator_stack.pop();
                if(!operator_stack.empty()) {
                    top_stack = operator_stack.top();
                } else break;
            }
            //将当前操作符入栈
            operator_stack.push(infix[i]);
        } else {//操作数
            string current_operator;
            int j=i;
            while(valid_operand_set.find(infix[j]) != valid_operand_set.end()) {
                current_operator += infix[j];
                ++j;
            }
            postfix.push(current_operator);
            i=j-1;//因为for循环,每次都会执行i++
        }
        queue<string> temp_queue = postfix;
        while(temp_queue.size()>0) {
            temp_queue.front();
            temp_queue.pop();
        }
    }
    //最后将栈中内容全部取出来
    while(!operator_stack.empty()) {
        postfix.push(string(1, operator_stack.top()));
        operator_stack.pop();
    }
    return postfix;
}
//计算两个操作数
double calculate_two(double a, double b, string operand) {
    double result;
    if(operand == "+") {
        result = a+b;
    } else if(operand == "-") {
        result = a-b;
    } else if(operand == "*") {
        result = a*b;
    } else if(operand == "/") {
        if(b==0) {
            exit(-1);
        }
        result = a/b;
    } else if(operand == "%") {
        result = (static_cast<int>(a)) % (static_cast<int>(b));
    } else if(operand == "^") {
        result = pow(a, b);
    }
    return result;
}
//对后缀表达式,进行计算
double calculate_post(queue<string>& post) {
    stack <double> result_stack;
    while(!post.empty()) {
        string temp = post.front();
        post.pop();
        if(is_operator(temp[0])) { //是操作符
            if(result_stack.size()<2) {
                exit(-1);
            }
            double operand2 = result_stack.top();//从栈中取出两个元素
            result_stack.pop();
            double operand1 = result_stack.top();
            result_stack.pop();
            double m = calculate_two(operand1, operand2, temp);//计算并将结果压入栈中
            result_stack.push(m);
        } else { //操作数
            double temp_operand = atof(temp.c_str());
            result_stack.push(temp_operand);
        }
    }
    return result_stack.top();
}
int main(int argc, char **argv) {
    string infix;
    getline(cin, infix);//输入表达式 
    string result_infix = preprocess(infix);//处理一元操作符:‘+’‘-’ 
    queue<string> result_post = infix_to_post(result_infix);//将表达式转换为计算机易于理解的后缀表达式 
    queue<string> temp = result_post;
    while(!temp.empty()) {
        temp.pop();
    }//判断是否栈空,若非空则弹出栈顶元素 
    double result = calculate_post(result_post);//对后缀表达式计算并将结果返回给result 
	printf("计算结果为:%.3f",result);//输出结果 
    return 0;
}

 

  • 4
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我可以为您解答这个问题。 首先,我们需要定义一个来存储数字和运算符。可以使用数组来实现数据结构。然后,我们需要检查输入的表达式是否符合语法规则,规则包括:表达式只包含数字、运算符和括号,括号匹配,运算符的优先级和结合性符合四则运算的规则。 在检查完语法后,我们可以开始将表达式转换成后缀表达式。后缀表达式也称为逆波兰表达式,是一种不含括号的表达式。转换过程中,我们需要遍历表达式中的每个数字和运算符,根据运算符的优先级和结合性,将它们依次压入中,直到表达式结束。 最后,我们按照后缀表达式的顺序依次弹出数字和运算符,进行计算。具体实现可以参考以下伪代码: ```python stack = [] # 检查语法 # 转换成后缀表达式 for token in expression: if token.isdigit(): stack.append(int(token)) elif token in '+-*/': while stack and stack[-1] in '*/' and token in '+-': # 弹出顶元素,进行计算 op = stack.pop() b = stack.pop() a = stack.pop() if op == '*': stack.append(a * b) elif op == '/': stack.append(a // b) elif op == '+': stack.append(a + b) elif op == '-': stack.append(a - b) stack.append(token) elif token == '(': stack.append(token) elif token == ')': while stack[-1] != '(': op = stack.pop() b = stack.pop() a = stack.pop() if op == '*': stack.append(a * b) elif op == '/': stack.append(a // b) elif op == '+': stack.append(a + b) elif op == '-': stack.append(a - b) stack.pop() # 弹出左括号 # 计算最终结果 while len(stack) > 1: op = stack.pop() b = stack.pop() a = stack.pop() if op == '*': stack.append(a * b) elif op == '/': stack.append(a // b) elif op == '+': stack.append(a + b) elif op == '-': stack.append(a - b) result = stack.pop() ``` 希望这个回答能够帮助到您。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值