又一篇四则运算代码
代码分为两段
一段为将输入分解为TOKEN : 0-9 ( ) + _ * /
一段为根据输入进行计算
第一段

#include <iostream> #include <string> #include <vector> #include <deque> #include <tuple> #include <assert.h> using namespace std; enum CALC_STATUS{ InitStatus = 0, InNumberStatus, InIdentStatus, EndLineStatus, BadStatus }; enum Token_Type{ NumberTokenType, LparamTokenType, RparamTokenType, AddTokenType, SubTokenType, MulTokenType, DivTokenType, BadTokenType }; typedef struct TOKEN_TUPLE{ TOKEN_TUPLE(const std::string& token,const Token_Type& type){ s = token; t = type; } TOKEN_TUPLE(){}; TOKEN_TUPLE(const TOKEN_TUPLE& tt){ s = tt.s; t = tt.t; } std::string s; Token_Type t; }; std::deque<TOKEN_TUPLE> tokenDeque; void InsertToken(const std::string& token,const Token_Type& type){ tokenDeque.push_front(TOKEN_TUPLE(token,type)); } bool IsIdent(const char cc){ return ( cc == '+' || cc == '-' || cc == '*' || cc == '/' || cc == '(' || cc == ')' ); } void InsertIdentToken(const std::string& token) { Token_Type tokenType = BadTokenType; if(token.size() != 1 || !IsIdent(token[0])) return; if(token[0] == '+'){ tokenType = AddTokenType; }else if(token[0] == '-'){ tokenType = SubTokenType; }else if(token[0] == '*'){ tokenType = MulTokenType; }else if(token[0] == '/'){ tokenType = DivTokenType; }else if(token[0] == '('){ tokenType = LparamTokenType; }else if(token[0] == ')'){ tokenType = RparamTokenType; } InsertToken(token,tokenType); } bool ParseInput(const std::string& input) { bool bRet = false; CALC_STATUS status = InitStatus; size_t begPos , endPos ; bool foundPoint = false; tokenDeque.clear(); for(size_t index= 0;index < input.size();++index){ switch(status){ case InitStatus: if(isspace(input[index])){ continue; }else if(isdigit(input[index])){ status = InNumberStatus; begPos = index; continue; }else if( IsIdent(input[index]) ){ status = InIdentStatus; begPos = index; continue; }else{ status = BadStatus; //std::cout << "parse bad input,index is " << index << std::endl; break; } break; case InNumberStatus: if(isdigit(input[index])){ status = InNumberStatus; continue; }else if(input[index]=='.'){ if(foundPoint){ status = BadStatus; //std::cout << "parse bad input,index is " << index << std::endl; break; } status = InNumberStatus; foundPoint = true; continue; }else if( IsIdent(input[index])){ endPos = index; InsertToken(input.substr(begPos,endPos-begPos),NumberTokenType); begPos = index; status = InIdentStatus; foundPoint = false; continue; }else if(isspace(input[index])){ endPos = index; InsertToken(input.substr(begPos,endPos-begPos),NumberTokenType); status = InitStatus; foundPoint = false; continue; } else{ status = BadStatus; break; } case InIdentStatus: endPos = index; InsertIdentToken(input.substr(begPos,endPos-begPos)); status = InitStatus; --index; continue; default: status = BadStatus; break; }//switch(status) }//for(size_t index= 0;index < input.size();++index) if(status != BadStatus && status != InitStatus){ endPos = std::string::npos; if(status == InNumberStatus) { InsertToken(input.substr(begPos,endPos-begPos),NumberTokenType); }else if(status == InIdentStatus){ InsertIdentToken(input.substr(begPos,endPos-begPos)); } bRet = true; }else if(status == InitStatus){ bRet = true; } if(!bRet) tokenDeque.clear(); return bRet; } void PrintErrorMsg(const string& input){ std::cout << std::endl << "test error!!" << std::endl; std::cout << "input is " << input << "."<< std::endl; } void TestInput(const string& input,bool result,size_t tokenCount){ static int i = 1; if( ParseInput(input) != result) { PrintErrorMsg(input); std::cout << "result is not " << result << std::endl<< std::endl; }else if( tokenDeque.size() != tokenCount ){ PrintErrorMsg(input); std::cout <<"tokenCount is " <<tokenDeque.size() << " not " << tokenCount << std::endl <<std::endl; }else{ std::cout << i << "\ttimes test pass!" << std::endl; } i++; } bool GetNextToken(TOKEN_TUPLE& tokenTuple) { if(tokenDeque.empty()){ tokenTuple.t = BadTokenType; return false; } tokenTuple = tokenDeque.back(); tokenDeque.pop_back(); return true; } void UngetToken(const TOKEN_TUPLE& tokenTuple){ tokenDeque.push_back(tokenTuple); } bool ParsePression(double& value); bool ParsePrimaryExpression(double& value) { bool ret = false; bool minusFlag = false; TOKEN_TUPLE tt; GetNextToken(tt); if (tt.t == SubTokenType) { minusFlag = true; } else { UngetToken(tt); } GetNextToken(tt); if(tt.t == NumberTokenType){ value = std::stod(tt.s); }else if(tt.t == LparamTokenType){ if(!ParsePression(value)) return false; GetNextToken(tt); if(tt.t != RparamTokenType){ return false; } }else{ UngetToken(tt);//?? } if(minusFlag) value = -value; ret =true; return ret; } bool ParseTerm(double& value){ bool ret = false; double v1; double v2; TOKEN_TUPLE tt; if(!ParsePrimaryExpression(v1) ) return ret; for(;;){ GetNextToken(tt); if(tt.t != MulTokenType && tt.t != DivTokenType&&ret){ UngetToken(tt); break; } ParsePrimaryExpression(v2); if(tt.t == MulTokenType){ v1 = v1*v2; }else if(tt.t == DivTokenType){ if(v2 ==0.0) return ret; v1 = v1/v2; } } value = v1; ret = true; return ret; } bool ParsePression(double& value){ bool ret = false; double v1; double v2; TOKEN_TUPLE tt; if(tokenDeque.empty()) return ret; if(!ParseTerm(v1)) return ret; for(;;){ GetNextToken(tt); if(tt.t != AddTokenType && tt.t != SubTokenType){ UngetToken(tt); break; } ParseTerm(v2); if(tt.t == AddTokenType){ v1 = v1+v2; }else if(tt.t == SubTokenType){ v1 = v1-v2; }else{ UngetToken(tt); } } value = v1; ret = true; return ret; } int main(int argc, char *argv[]) { // std::string input; // cin >> input; // cout << input << endl; // TestInput("2",true,1); // TestInput("0.2",true,1); // TestInput("2 3",true,2); TestInput("2.467 + 3",true,3); double d; bool ret = ParsePression(d); // TestInput("()2.467 + 3",true,5); // TestInput("3.14 + ( 2.43-1) /3 *(2*6)",true,15); // TestInput(".()2.467 + 3",false,0); // TestInput("aas+2()2.467 + 3",false,0); // TestInput("2.46.7 + 3",false,0); // TestInput("2.4(6.7 + 3",true,5); return 0; }
显示结果
第二段

1 // 11111.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include <string> 6 #include <iostream> 7 8 9 using namespace std; 10 11 std::string s1 = "2+3-2"; 12 std::string s2 = "2+3*3"; 13 std::string s3 = "2+(3*3)"; 14 std::string s4 = "()2+(3*3)"; 15 16 int gStringIndex = 0; 17 18 bool ParseExPression(const std::string& s, int& v); 19 20 #define ERROR_MSG \ 21 std::cerr << "Error. Func : " << __FUNCTION__ << ".\tLine : " << __LINE__ << std::endl; \ 22 std::cerr << "expression is " << s << ". error index is " << gStringIndex << std::endl; \ 23 exit(0); 24 25 26 bool ParsePrimaryExpression(const std::string& s, int& v) 27 { 28 bool minusFlag = false; 29 30 if (s[gStringIndex] == '-') { 31 minusFlag = true; 32 ++gStringIndex; 33 } 34 35 if (isdigit(s[gStringIndex])) { 36 std::string token = s.substr(gStringIndex, 1); 37 v = stoi(token); 38 gStringIndex++; 39 if (minusFlag) 40 v = -v; 41 return true; 42 } 43 else if (s[gStringIndex] == '(') 44 { 45 gStringIndex++; 46 if (!ParseExPression(s, v)) { 47 ERROR_MSG; 48 } 49 if (s[gStringIndex] == ')') { 50 gStringIndex++; 51 if (minusFlag) 52 v = -v; 53 return true; 54 } 55 } 56 else { 57 ERROR_MSG; 58 } 59 60 61 62 63 return false; 64 } 65 66 67 bool ParseTerm(const std::string& s, int& v) 68 { 69 int v1; 70 int v2; 71 char ident = 0; 72 73 if (!ParsePrimaryExpression(s, v1)) { 74 ERROR_MSG; 75 } 76 while (1) { 77 if (s[gStringIndex] != '*' && 78 s[gStringIndex] != '/') 79 { 80 break; 81 } 82 else { 83 ident = s[gStringIndex]; 84 ++gStringIndex; 85 } 86 87 if (!ParsePrimaryExpression(s, v2)) { 88 ERROR_MSG; 89 } 90 91 if (ident == '*') 92 { 93 v1 = v1*v2; 94 } 95 else if (ident == '/' && v2 != 0) { 96 v1 = v1 / v2; 97 } 98 else { 99 ERROR_MSG; 100 } 101 } 102 103 v = v1; 104 return true; 105 } 106 107 bool ParseExPression(const std::string& s, int& v) 108 { 109 int v1; 110 int v2; 111 char ident = 0; 112 113 114 if (!ParseTerm(s, v1)) { 115 ERROR_MSG; 116 } 117 118 while (1) { 119 if (s[gStringIndex] != '+' && 120 s[gStringIndex] != '-') 121 { 122 break; 123 } 124 else { 125 ident = s[gStringIndex]; 126 ++gStringIndex; 127 } 128 129 if (!ParseTerm(s, v2)) { 130 ERROR_MSG; 131 } 132 133 if (ident == '+') 134 { 135 v1 = v1+v2; 136 } 137 else if (ident == '-') { 138 v1 = v1 - v2; 139 } 140 else { 141 ERROR_MSG; 142 } 143 144 } 145 146 v = v1; 147 return true; 148 } 149 150 151 bool ParseInput(const std::string& s) 152 { 153 gStringIndex = 0; 154 int v; 155 if (!ParseExPression(s, v)) { 156 ERROR_MSG; 157 } 158 159 std::cout << s << " = " << v << endl; 160 161 162 return true; 163 } 164 165 int main() 166 { 167 ParseInput(s1); 168 std::cout << std::endl << std::endl; 169 170 ParseInput(s2); 171 std::cout << std::endl << std::endl; 172 173 ParseInput(s3); 174 std::cout << std::endl << std::endl; 175 176 ParseInput(s4); 177 std::cout << std::endl << std::endl; 178 179 return 0; 180 }
显示结果
作 者: itdef
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力
欢迎转帖 请保持文本完整并注明出处
技术博客 http://www.cnblogs.com/itdef/
B站算法视频题解
https://space.bilibili.com/18508846
qq 151435887
gitee https://gitee.com/def/
欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
如果觉得不错,欢迎点赞,你的鼓励就是我的动力


【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话