字符串表达式求值(支持多种类型运算符)
时间:2020-07-14
本文章向大家介绍字符串表达式求值(支持多种类型运算符),主要包括字符串表达式求值(支持多种类型运算符)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
一、说明
1. 输入字符串为中缀表达式,无需转为后缀表达式
2. 支持的运算符包括:
算术运算符:"+,-,*,/"
关系运算符:">,<,>=,<=,=,!="(注意等于运算符采用的是一个等号)
逻辑运算符:"&&,||"
3. 支持大于10的数字,不支持负数操作数,但支持中间结果和返回值为负数
二、算法原理&步骤
本文算法对中缀表达式形式字符串进行求值,同时支持与或运算和逻辑运算(若含有关系运算符或者逻辑运算符,则输出为1或者0)。类似于加减乘除,将关系运算符和逻辑运算符看作优先级低的运算符进行处理,优先级:算术运算符>关系运算符>逻辑运算符。
步骤:
1. 初始化两个空堆栈,一个存放操作数,一个存放运算符。
2. 从左至右扫描输入字符串,依次读取。
- 2.1 若为操作数,则压入操作数栈;
- 2.2 若为运算符,判断其优先级是否大于运算符栈栈顶元素优先级。若大于栈顶元素优先级,则直接压栈;否则,弹出栈顶元素operator,同时依次从操作数栈中弹出两个元素number1,number2,计算表达式(number2 operator number1)的值value,并将值value压入操作数栈。重复上述过程直至当前扫描的操作符优先级大于栈顶元素,然后将当前运算符压栈。
3. 弹出运算符栈顶元素operator,同时依次从操作数栈中弹出两个元素number1,number2,计算表达式(number2 operator number1)的值value,并将值value压入操作数栈。重复上述过程直至运算符栈为空。
4. 此时操作数栈应该只有一个元素,即为表达式的值。
三、代码&测试
求值函数:
1 /* 字符串表达式求值 2 * @param input: 输入的字符串 3 * @param output: 表达式的值,若含有关系运算符则为1或者0 4 * return 计算过程是否正常 5 */ 6 bool ExpValue(string input,int& output) 7 { 8 stack<int> operand_stack; 9 stack<string> operator_stack; 10 11 char prev = 0; // 上一个属于运算符的字符 12 for (int i = 0; i < input.size(); i++) 13 { 14 char c = input[i]; 15 // prev是否是一个完整运算符 16 if (!isOperator(c) && prev) 17 { 18 string new_op = string("").append(1, prev); 19 addNewOperator(new_op, operand_stack, operator_stack); 20 prev = 0; 21 } 22 23 // 数字 24 if (isdigit(c)) 25 { 26 int val_c = c - '0'; 27 if (i > 0 && isdigit(input[i - 1])) 28 { 29 int top_num = operand_stack.top(); 30 top_num = top_num * 10 + val_c; 31 operand_stack.pop(); 32 operand_stack.push(top_num); 33 } 34 else 35 operand_stack.push(val_c); 36 } 37 // 运算符字符 38 else if (isOperator(c)) 39 { 40 // 处理两字符运算符 41 if (prev) 42 { 43 string new_op = string("").append(1, prev).append(1, c); 44 addNewOperator(new_op, operand_stack, operator_stack); 45 prev = 0; 46 } 47 else 48 prev = c; 49 } 50 else if (c == '(') 51 operator_stack.push("("); 52 else if (c == ')') 53 { 54 // 处理括号内的运算符 55 while (operator_stack.top()!="(") 56 { 57 int num1 = operand_stack.top(); 58 operand_stack.pop(); 59 int num2 = operand_stack.top(); 60 operand_stack.pop(); 61 string op = operator_stack.top(); 62 operator_stack.pop(); 63 64 int val = Calculate(num2, num1, op); 65 operand_stack.push(val); 66 } 67 operator_stack.pop(); // 弹出"(" 68 } 69 } 70 assert(operand_stack.size() == operator_stack.size() + 1); 71 // 弹出所有运算符 72 while(!operator_stack.empty()) 73 { 74 int num2 = operand_stack.top(); 75 operand_stack.pop(); 76 int num1 = operand_stack.top(); 77 operand_stack.pop(); 78 string op = operator_stack.top(); 79 operator_stack.pop(); 80 81 int val = Calculate(num1, num2, op); 82 operand_stack.push(val); 83 } 84 85 if (operand_stack.size() == 1) { 86 output = operand_stack.top(); 87 return true; 88 } 89 return false; 90 }
其中用到的子函数有:
/* 判断字符是否属于运算符 */ bool isOperator(char c) { switch (c) { case '-': case '+': case '*': case '/': case '%': case '<': case '>': case '=': case '!': case '&': case '|': return true; default: return false; } } /* 获取运算符优先级 */ int getPriority(string op) { int temp = 0; if (op == "*" || op == "/" || op == "%") temp = 4; else if (op == "+" || op == "-") temp = 3; else if (op == ">" || op == "<" || op == ">=" || op == "<=" || op == "=" || op == "!=") temp = 2; else if (op == "&&" || op == "||") temp = 1; return temp; } /* * 返回一个两元中缀表达式的值 * syntax: num_front op num_back * @param num_front: 前操作数 * @param num_back: 后操作数 * @param op: 运算符 */ int Calculate(int num_front, int num_back, string op) { if (op == "+") return num_front + num_back; else if (op == "-") return num_front - num_back; else if (op == "*") return num_front * num_back; else if (op == "/") return num_front / num_back; else if (op == "%") return num_front % num_back; else if (op == "!=") return num_front != num_back; else if (op == ">=") return num_front >= num_back; else if (op == "<=") return num_front <= num_back; else if (op == "=") return num_front == num_back; else if (op == ">") return num_front > num_back; else if (op == "<") return num_front < num_back; else if (op == "&&") return num_front && num_back; else if (op == "||") return num_front || num_back; return 0; } /* 新运算符入栈操作 */ void addNewOperator(string new_op, stack<int>& operand_stack, stack<string>& operator_stack) { while (!operator_stack.empty() && getPriority(operator_stack.top()) >= getPriority(new_op)) { int num2 = operand_stack.top(); operand_stack.pop(); int num1 = operand_stack.top(); operand_stack.pop(); string op = operator_stack.top(); operator_stack.pop(); int val = Calculate(num1, num2, op); operand_stack.push(val); } operator_stack.push(new_op); }
测试结果:
int main() { string s0 = "10-1*10+3%2"; string s1 = "100 + (3-33)*2"; string s2 = "20+1 >= 20 && 20+1 < 20"; string s3 = "10>20 || 10/1>=5"; int ret = -1; if (ExpValue(s0, ret)) cout << s0 << "的值: " << ret << endl; if (ExpValue(s1, ret)) cout << s1 << "的值: " << ret << endl; if (ExpValue(s2, ret)) cout << s2 << "的值: " << ret << endl; if (ExpValue(s3, ret)) cout << s3 << "的值: " << ret << endl; return 0; }
上述代码的执行结果为:
原文地址:https://www.cnblogs.com/irvingluo/p/13301157.html
- mysql创建数据表时如何判断是否已经存在?
- 温故知新:接口的隐式实现与显式实现
- 也谈枚举ToString()性能的改进
- silverlight:利用telerik中的zip类对字符串进行压缩、解压
- 索引,视图,存储过程和触发器文档
- 重点解读:用小程序给公众号涨粉10w的7大行业案例
- 网络域名与注册商标冲突的解决途径
- 网站代码优化我们必须要做的那些事
- 真是热闹! Slade.com等多个域名被曝交易
- python编码问题之"encode"&"decode"
- python3编码问题终结者--还搞不懂你来找我
- Pycharm集成PyQt4并使用
- python遍历一个目录,输出所有文件名
- pyqt4实现tab界面切换
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python读取Excel数据并生成图表过程解析
- 解决keras模型保存h5文件提示无此目录问题
- 如何基于Python代码实现高精度免费OCR工具
- python怎么调用自己的函数
- Python datetime模块使用方法小结
- PHP hebrev()函数用法讲解
- PHP hex2bin()函数用法讲解
- PHP+jQuery实现即点即改功能示例
- PHP html_entity_decode()函数讲解
- PHP下载大文件失败并限制下载速度的实例代码
- thinkphp5框架实现的自定义扩展类操作示例
- python导入库的具体方法
- PHP+jQuery实现双击修改table表格功能示例
- 基于ThinkPHP5框架使用QueryList爬取并存入mysql数据库操作示例
- Laravel推荐使用的十个辅助函数