标签:
四则运算栈实现,支持小数、负数,经过测试,暂时没发现错误!
思路:
1、去掉字符串中的空格,将字符串按照运算符和数字保存到vector<string>中;
2、判断字符串是否符合四则运算的表达式;
3、栈实现:数字栈、运算符栈,从左到右扫描中缀表达式;
数字:直接入栈;运算符:
(1)”(“:直接入栈;
(2)”)“:弹出()之间的运算符,进行运算;
(3)”+-*/“:如果当前运算符优先级<栈顶运算符优先级,则数字栈弹出两个数和栈顶运算符进行运算,并将结果存入数字运算符,再将当前运算符入栈;否则直接入栈。
扫描结束后,如果运算符栈还有元素,则出栈运算。
负数:支持5+-3这样的写法,扫描到”-“,判断”-“是减号还是负号;
”-“前面一个字符是数字或者”)“,则认为是减号;否则是负号;
如果当前字符是负号,将标志isNeg=true,则下一个数字存入vector<string>中时,加上负号。
小数:支持.1这样的写法,小数点”.“与数字字符的处理方式相同。
#include <iostream> #include <string> #include <stack> #include <vector> #include <algorithm> using namespace std; //打印输出容器 template <typename T> void print(const T& v) { for(size_t i = 0; i < v.size(); ++i) { cout << v[i] << " "; } cout << endl; } //运算符优先级 int getPriority(const string& op) { int priority; if (op == "#") priority = 3; else if (op == "*" || op == "/") priority = 2; else if (op == "+" || op == "-") priority = 1; else priority = -1; return priority; } //将字符串表达式分开 vector<string> preParse(const char* str) { vector<string> tokens; int len = strlen(str); char *p = (char*)malloc((len+1)*sizeof(char)); int i = 0, j = 0; //去掉空格 while(i < len) { if(str[i] == ‘ ‘) { ++i; continue; } p[j++] = str[i++]; } p[j] = ‘\0‘; j = 0; len = strlen(p); bool isNeg = false; while (j < len) { char temp[2]; string token; switch(p[j]) { case ‘+‘: case ‘*‘: case ‘/‘: case ‘(‘: case ‘)‘: temp[0] = p[j]; temp[1] = ‘\0‘; token = temp; tokens.push_back(token); break; case ‘-‘: if(j == 0) { //tokens.push_back("#"); isNeg = true; } else if (p[j-1] == ‘)‘ || isdigit(p[j-1])) { tokens.push_back("-"); } else { //tokens.push_back("#"); isNeg = true; } break; default: i = j; while ( ( isdigit(p[i]) || p[i] ==‘.‘ ) && i < len) { i++; } char *num = (char*)malloc(i-j+2); strncpy(num, p+j, i-j+1); num[i-j] = ‘\0‘; if (isNeg) { char *temp = (char*)malloc(i-j+3); temp[0] = ‘-‘; strcpy(temp+1, num); tokens.push_back(temp); isNeg = false; } else { tokens.push_back(num); } j = i - 1; free(num); break; } j++; } free(p); //print(tokens); return tokens; } //两个数运算 void calculate(stack<double> & opdStack, string opt) { if(opt == "#") { double opd = opdStack.top(); double result = 0 - opd; opdStack.pop(); opdStack.push(result); } else { double rOpd = opdStack.top(); opdStack.pop(); double lOpd = opdStack.top(); opdStack.pop(); double result; if(opt == "+") result = lOpd + rOpd; else if(opt == "-") result = lOpd - rOpd; else if(opt == "*") result = lOpd * rOpd; else if(opt == "/") result = lOpd / rOpd; opdStack.push(result); } } //计算 double process(string &str) { char *s = (char *)malloc(str.size()); strcpy(s, str.c_str()); vector<string> tokens = preParse(s); int i = 0; int size = tokens.size(); stack<double> opdStack; //num stack<string> optStack; //op for(i = 0; i < size; ++i) { string token = tokens[i]; if(token=="#"||token=="+"||token=="-"||token=="*"||token=="/") { if(optStack.size() == 0) { optStack.push(token); } else { int tokenPriority = getPriority(token); string topOpt = optStack.top(); int topOptPritority = getPriority(topOpt); if(tokenPriority > topOptPritority) { optStack.push(token); } else { while(tokenPriority <= topOptPritority) { optStack.pop(); calculate(opdStack, topOpt); if(optStack.size()>0) { topOpt = optStack.top(); topOptPritority = getPriority(topOpt); } else { break; } } optStack.push(token); } } } else if(token == "(") { optStack.push(token); } else if(token == ")") { while(optStack.top() != "(") { string topOpt = optStack.top(); calculate(opdStack,topOpt); optStack.pop(); } optStack.pop(); } else { opdStack.push(stod(token)); } } while(optStack.size() != 0) { string topOpt = optStack.top(); calculate(opdStack,topOpt); optStack.pop(); } return opdStack.top(); } //判读是否错误 //1 有除数字、+-*/()外的字符 //2 首字符是+*/ //3 括号不匹配 //4 除数为0 bool isRight(const string &str) { string c1 = "0123456789+-*/()."; string c2 = "0123456789"; if (str.find_first_of(c2) == string::npos) { cout << "表达式中没有可计算的数字!" << endl; return false; } if (str.find_first_not_of(c1) != string::npos) { cout << "表达式中有除数字、+-*/()外的非法字符!" << endl; return false; } if (str[0] == ‘+‘ || str[0] == ‘/‘ || str[0] == ‘*‘) { cout << "表达式中首字符错误!" << endl; return false; } if ( count(str.cbegin(),str.cend(),‘(‘) != count(str.cbegin(),str.cend(),‘)‘) ) { cout << "表达式中括号不匹配!" << endl; return false; } char *s = (char *)malloc(str.size()); strcpy(s, str.c_str()); vector<string> tokens = preParse(s); for (auto it = tokens.cbegin(); it != tokens.cend(); ++it) { if (*it == "/") { ++it; if(*it == "0") { cout << "除数不能为0!" << endl; return false; } } if(*it == "/" || *it == "*"|| *it == "+" || *it == "-" ) { ++it; if(*it == "/" || *it == "*"|| *it == "+" || *it == "-" ) { cout << "运算符相邻无法计算!" << endl; return false; } } } return true; } int main() { while (1) { string str; cout << "input:"; cin >> str; if( isRight(str) ) { cout << "result:"<<process(str) << endl; } } }
程序参考了某些博客的文章,但是难以找到原地址,如需注明,请练习本人!
标签:
原文地址:http://www.cnblogs.com/pukaifei/p/5346463.html