C++表达式求值
表达式求值问题:
完成类似如下界面所示的表达式求值软件,输入包含加﹑减﹑乘﹑除﹑括号等运算符和0-9数字的表达式,输出表达式计算结果。
扩展要求(选作):
(1)表达式包含多位整数甚至是小数,如(2.5+3.15)/0.69;
(2)表达式包含特定函数,如: 1+sin(5+2/3)*3;
提交:
程序源代码(含注释)﹑程序报告文档,打包成压缩文件在课程网站上按规定时间提交。
功能要求:
- 编程语言:C/C++
- 支持的特定函数:sin、cos、tan等
- 实现含括号优先级、四则混合运算、数值可以是负数的表达式求值
C++实现表达式求值
- 支持运算符:加、减、乘、除、左括号、右括号
- 支持操作数:多位数值、负数、小数
- 支持函数:sin、cos、tan
- 当发生除0、括号不匹配,或运算符、操作数不合法将给出错误提示
如有需要,程序可方便扩展对如sqrt、pow、log等其他函数的支持。
算法原理
采用数据结构的栈特性,将中缀表达式转换成后缀表达式(逆波兰表达式)再进行计算求值。
表达式求值类源码(部分)
/**********************************
* 表达式求值
*
* - 支持运算符:+、-、*、/、(、)
* - 支持操作数:多位数值、负数、小数
* - 支持函数:sin、cos、tan
*
**********************************/
#include <iostream>
#include <vector>
#include <stack>
#include <string>
#include <sstream>
#include <cmath>
#include <cctype>
//表达式求值类
class ExpCalculation {
private:
using TokenList = std::vector<std::string>;
using TokenStack = std::stack<std::string>;
using ValueStack = std::stack<double>;
public:
ExpCalculation() {
}
public:
//传入表达式,求值成功返回true,否则返回false,可通过error获取错误原因
bool evaluate(const std::string& expression, double& result) {
TokenList token_list;
TokenList postfix_list;
if (!parseToken(expression, token_list, error_)) return false;
if (!postfixToken(token_list, postfix_list, error_)) return false;
convertTokenListToString(postfix_list, postfix_);
if (!evaluateToken(postfix_list, result, error_)) return false;
return true;
}
//获取表达式转换的后缀表达式文本串
const std::string& postfix() const {
return postfix_;
}
//获取求值错误原因
const std::string& error() const {
return error_;
}
命令行版本的测试案例
//测试表达式求值
void testing(const std::string& expression) {
double result;
std::string error;
ExpCalculation exp;
std::cout << "----------------------" << std::endl;
std::cout << expression << std::endl;
if (exp.evaluate(expression, result)) {
std::cout << "postfix: " << exp.postfix() << std::endl;
std::cout << "result = " << result << std::endl;
} else {
std::cout << "error: " << exp.error() << std::endl;
}
}
int main() {
system("title 表达式求值 (源码联系作者小企鹅 1561968262)");
std::cout << "# 表达式求值程序 #" << std::endl;
std::cout << "- 支持运算符:+、-、*、/、(、)" << std::endl;
std::cout << "- 支持操作数:多位数值、负数、小数" << std::endl;
std::cout << "- 支持函数:sin、cos、tan" << std::endl;
//案例测试
testing("(5+55.55)*(666/3.2+67)-4");
testing("sin(56 * cos(7 * 3.14159) / (tan(66 - 52 * 0.7)) - (52*6))");
testing("(2.5+3.15)/0.69");
testing("1+sin(5+2/3)*3");
testing("-3.14+cos(-75+-2*63)/-5");
return 0;
}
命令行版本的测试输出(错误版本)
因我直接使用的cmath中的sin、cos、tan函数,这类函数的参数是弧度而非角度,所以需要做转换,以下符合c语言中表达式的求值结果:
命令行版本的测试输出(正确版本)
将cmath中的sin、cos、tan参数由角度转换成弧度后再计算,以下符合数学表达式的求值结果:
MFC版本的实现(错误版本)
用MFC给程序做一个简单的窗口界面
因我直接使用的cmath中的sin、cos、tan函数,这类函数的参数是弧度而非角度,所以需要做转换,以下符合c语言中表达式的求值结果:
MFC版本的实现(正确版本)
用MFC给程序做一个简单的窗口界面
将cmath中的sin、cos、tan参数由角度转换成弧度后再计算,以下符合数学表达式的求值结果:
源码下载
链接:https://pan.baidu.com/s/18FVCtzM1CCDfeS9Atv4SwQ
提取码:1111