首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

C++带语法检查的数学算式计算器

后端 12.97KB 17 需要积分: 1
立即下载

资源介绍:

适合初学C++的同学看一看,具体可参见博客https://blog.csdn.net/qq_42593411/article/details/136180857?spm=1001.2014.3001.5502
#include"BaseOperatorPro.h" #include"brackCheck.h" //去除字符串末端多余的空格符和制表符并对括号合法性进行判断 bool Readformulaline(std::string& line) { if (!line.empty()) { //去除末尾多余的空格或制表符 int _index = line.size() - 1; while (_index >= 0 && (line[_index] == ' ' || line[_index] == '\t')) --_index; line.erase(line.begin() + (_index + 1), line.end()); //对括号合法性进行判断 return brace_brack_paren_legitmate(line); } else return false; return true; } //根据s返回相应的计算方式标记 int mathfunc(std::string s) { if (s.compare("sin") == 0) return SIN; else if (s.compare("cos") == 0) return COS; else if (s.compare("exp") == 0) return EXP; else if (s.compare("tan") == 0) return TAN; else if (s.compare("pow") == 0) return POW; else if (s.compare("sqrt") == 0) return SQRT; else if (s.compare("arcsin") == 0) return ARCSIN; else if (s.compare("arccos") == 0) return ARCCOS; else if (s.compare("arctan") == 0) return ARCTAN; else if (s.compare("ln") == 0) return LN; else if (s.compare("lg") == 0) return LG; else if (s.compare("abs") == 0) return ABS; else return NOTFUNC; } /** @brief 对运算符容器进行位置检查,如果出现位置相邻的运算符则报错 @param loperators: 解析计算式获得的std::vector&. @note 只对双元运算符进行位置限制 */ bool check_Oper_position(std::vector& loperators) { //如果运算符容器中出现连续位置的运算符,返回错误 for (int i = 1; i < loperators.size(); ++i) { if (loperators[i].PriorityLevel != 3 && loperators[i - 1].PriorityLevel != 3) //只对双元运算符进行位置限制 { if (loperators[i].pos_InString - loperators[i - 1].pos_InString <= 1) return false; } } return true; } /** @brief 传入将计算式解析后的数值容器和运算符容器,根据运算规则计算出结果,如果正确则返回true,错误返回false @param lvalues: 解析计算式获得的std::vector&. @param loperators: 解析计算式获得的std::vector&. @param result: inputOutput the calculate result. @note 主要的报错类型有两种: 1.如果运算符找不到相应的计算数值,计算失败返回错误. 2.运算符遍历完毕,数值容器中只能 有一个未处理数据,如果多余或者少于则计算失败返回错误 */ bool calculateBaseline(std::vector& lvalues, std::vector& loperators, double& result) { //先对传入容器的位置情况进行检查 if (check_Oper_position(loperators) == false) { std::cerr << "error: two operators found adjacent in position!" << std::endl; result = ERROR; return false; } //根据运算符优先级对loperators进行排序 std::sort(loperators.begin(), loperators.end(), cmp_operatorPriority); for (auto operIt = loperators.begin(); operIt != loperators.end(); ++operIt) { //priority level = 3 代表只需要向上寻找一个操作数即可 if ((*operIt).PriorityLevel == 3) { //从当前操作符开始向上找第一个为处理的数字 int operPos = (*operIt).pos_InString; auto Upper_valuePos_it = std::find_if(lvalues.begin(), lvalues.end(), [operPos](const ValueMap& vp) { return (vp.pos_InString > operPos && vp.IsProcess == false); }); //错误检查:如果未找到或者,数字位置和运算符位置差大于1,则报错 if (Upper_valuePos_it == lvalues.end() || (*Upper_valuePos_it).pos_InString - (*operIt).pos_InString > 1) { std::cerr << "error: not exist number to cooperate with current operator: " << (*operIt).getStringFuncName() << std::endl; result = ERROR; return false; } //没有发生错误进行数值运算 double temp = (*Upper_valuePos_it).value; (*Upper_valuePos_it).value = (*operIt).singleCalculate(temp); } else { //priority level = 4,2,1 代表只需要向上向下寻找两个操作数 //从当前操作数位置向上向下找未处理的数字 int operPos = (*operIt).pos_InString; auto Upper_valuePos_it = std::find_if(lvalues.begin(), lvalues.end(), [operPos](const ValueMap& vp) { return (vp.pos_InString > operPos && vp.IsProcess == false); }); //找到了上未处理数字,从上未处理寻找下未处理数字 auto lower_valuePos_it = Upper_valuePos_it; //错误检查,并开启向下寻找数字的通道: 如果二元运算符却只有一个数字报错 if (Upper_valuePos_it == lvalues.end() || Upper_valuePos_it == lvalues.begin()) { std::cerr << "error: not exist number to cooperate with current operator: " << (*operIt).getStringFuncName() << std::endl; result = ERROR; return false; } else { int i = lower_valuePos_it - lvalues.begin(); //为了防止迭代器越界,利用一个变量定义循环范围 while (i > 0) { --lower_valuePos_it; if ((*lower_valuePos_it).IsProcess == false) //向下找到了未处理数 break; --i; } //当i == 0时代表向下未找到 if (i == 0) { std::cerr << "error: not exist number to cooperate with current operator: " << (*operIt).getStringFuncName() << std::endl; result = ERROR; return false; } } //已经找到了运算符左右未处理数 double temp = (*Upper_valuePos_it).value; (*lower_valuePos_it).IsProcess = true; //将左边的数字置为已处理 (*Upper_valuePos_it).value = (*operIt).dualCalculate((*lower_valuePos_it).value, temp); } } //遍历整个数组,如果存在2个以上未处理元素则报错,则当_Not_Process_Count = 1时,程序正确 int _Not_Process_Count = 0; for (auto vit = lvalues.begin(); vit != lvalues.end(); ++vit) { if ((*vit).IsProcess == false) { _Not_Process_Count++; if (_Not_Process_Count < 2) result = (*vit).value; } } if (_Not_Process_Count > 1) { std::cerr << "error: the valueContainer include too many value!" << std::endl; result = ERROR; return false; } else if (_Not_Process_Count == 0) { std::cerr << "error: not include enough operators!" << std::endl; result = ERROR; return false; } return true; } int getop(const std::string& Subline, int& index, char s[], int& pos) { int c, i; if (index >= Subline.size()) //字符串已经遍历完毕 return EOF return EOF; // remove black space while ((s[0] = c = Subline[index++]) == ' ' || c == '\t') ; s[1] = '\0'; i = 0; if (islower(c)) //command or NAME { while (islower(s[++i] = c = Subline[index++])) ; pos++; index--; s[i] = '\0'; if (strlen(s) > 1) return NAME; else return c; //unknown name } if (!isdigit(c) && c != '.' && c != '-') //判断排除空格后获取的第一个字符是否是运算符 { pos++; return c; } if (c == '-') //处理负数情况 { if (isdigit(c = Subline[index++]) || c == '.') s[++i] = c; else { index--; pos++; return '-'; } } if (isdigit(c)) while (isdigit(s[++i] = c = Subline[index++])) ; if (c == '.') while (isdigit(s[++i] = c = Subline[index++])) ; s[i] = '\0'; pos++; index--; //必须自减一次,因为超前赋值了 return NUMBER; } bool SubStringProcess(std::string& Subline, double& result) { //如果子串(括号中内容)是空的,则返回错误 if (Readformulaline(Subline) == false || Subline.empty()) { std::cerr << "error: the subline is empty!" << std::endl; result = ERROR; return false; } //定义一行数据中的数值、操作符容器 !!!!! std::vector lineOperators; std::vector lineValues; //初始化 int type; char s[MAXOP]; int pos = 0; int index = 0; //计算过程是否出错标志位 bool isgood = true; while ((type = getop(Subline, index, s, pos)) != EOF) { if (type == '{' || type == '[' || type == '(') { if (type == '{') { int index1 = Subline.find('}', (size_t)index); //从subline中index处开始查找第一次出现的下标 std::string Subsubstring = Subline.substr(index, (index1 - index)); //index自动指向括号下一个字符 index = index1 + 1; //将index更新指向反括号下一个位置 double value = 0.0; if (SubStringProcess(Subsubstring, value) == true) lineValues

资源文件列表:

计算器源码.zip 大约有11个文件
  1. 计算器源码/include/
  2. 计算器源码/include/BaseOperatorPro.h 2KB
  3. 计算器源码/include/brackCheck.h 1.71KB
  4. 计算器源码/include/calmath.h 4.75KB
  5. 计算器源码/include/config.h 96B
  6. 计算器源码/include/Operator_Value.h 1.75KB
  7. 计算器源码/src/
  8. 计算器源码/src/BaseOperatorPro.cpp 9.75KB
  9. 计算器源码/src/brackCheck.cpp 5.19KB
  10. 计算器源码/src/main.cpp 4.03KB
  11. 计算器源码/src/Operator_Value.cpp 3.34KB
0评论
提交 加载更多评论
其他资源 STM32单个舵机控制源码
STM32单个舵机控制源码
STM32单个舵机控制源码
51单片机单个舵机控制源码
51单片机单个舵机控制源码
51、32、arduino舵机控制代码
arduino单个舵机控制源码
51、32、arduino舵机控制代码
STM32F407控制机械手源码
STM32F407控制机械手源码
UVM验证方法学源代码压缩文件
UVM验证方法学源代码压缩文件
st7701驱动 datasheet
st7701驱动 datasheet
st7701驱动 datasheet st7701驱动 datasheet st7701驱动 datasheet
谢卓飞-1120231828.zip
谢卓飞-1120231828.zip
XMLTools-3.1.1.13-x64 安装包
XMLTools-3.1.1.13-x64 安装包