数据结构课后的实验作业
主要模块为:
转换模块:将中缀表达式转换为后缀表达式;
运算模块:对后缀表达式进行运算,得到最终运算结果。
运行环境为Ubuntu,g++版本为9.3.0
运算范围只限在32位整形以内
运算符包括了加减乘除、取余和幂次
可以进一步扩展的有:增加实数范围的运算;扩展运算符,例如根号等;实现图形操作界面
使用了GNU的开源readline库来实现比较人性化的行编辑器功能,具体的操作在这篇博客中
源码:
#include#include #include #include #include #include #include #include #include #include using namespace std; bool Error(false); //全局变量判断表达式是否非法 void Execute(void); string Transform(const string&); int weight(const char); //判断算符的权重 int calculate(const string&); void calculate_operater(const string&, stack &); int main(void) { Execute(); return 0; } void Execute(void) { string Aline; int num; //命令行历史功能初始化 using_history(); while(true) { //读取一行中缀表达式 Aline = readline("enter expression, or q to quit: "); //转化为后缀表达式 Aline = Transform(Aline); if(Aline == "exit") { cout << "invalid charactor or syntax error!" << endl; continue; } if(Aline == "") { continue; } //处理后缀表达式,得到最终运算结果 num = calculate(Aline); if(Error) { cout << "invalid charactor or syntax error!" << endl; Error = false; continue; } cout << num << endl; } return; } string Transform(const string& line) { if(line == "q") { exit(1); } //将这个字符串添加到命令行历史中 add_history(line.c_str()); stack Stack_charactors; string ret; string num; string Aline; bool flag(true); if(line[0] == '-') { Aline += '0'; } Aline += line + "#"; //cout << Aline << endl; //解析字符串 for(auto itc = Aline.cbegin(), ite = Aline.cend(); ite!=itc; ++itc) { //空格直接跳过 if(*itc == ' ') { continue; } //如果是数字 else if(*itc >= '0' && *itc <= '9') { num += *itc; flag = true; } else { if(weight(*itc) == -1) { return "exit"; } if(flag == true) { ret = ret + num + " "; num = ""; } if(Stack_charactors.empty() || (*itc == '(')) { Stack_charactors.push(*itc); } else if(*itc == ')') { while(Stack_charactors.top() != '(') { ret = ret + Stack_charactors.top() + " "; Stack_charactors.pop(); if(Stack_charactors.empty()) { return "exit"; } } Stack_charactors.pop(); } else { while((!Stack_charactors.empty()) && (weight(*itc) <= weight(Stack_charactors.top()))) { ret = ret + Stack_charactors.top() + " "; Stack_charactors.pop(); } Stack_charactors.push(*itc); } flag = false; } } ret.resize(ret.size()-1); return ret; } int weight(const char sign) { switch(sign) { case '#': { return 0; } case '+': { return 1; } case '-': { return 1; } case '*': { return 2; } case '/': { return 2; } case '%': { return 2; } case '^': { return 3; } case '(': { return 0; } case ')': { return 0; } default: { return -1; } } } int calculate(const string& expression) { int ret; istringstream is(expression); string item; stack Stack_nums; while(is >> item) { if((item=="+") || (item=="-") || (item=="*") || (item=="/") || (item=="%") || (item=="^")) { calculate_operater(item, Stack_nums); if(Error) { return 0; } } else { Stack_nums.push(atoi(item.c_str())); } } return Stack_nums.top(); } void calculate_operater(const string& sign, stack & Stack_nums) { int t1, t2; if(sign == "+") { if(Stack_nums.size() < 2) { Error = true; return; } t2 = Stack_nums.top(); Stack_nums.pop(); t1 = Stack_nums.top(); Stack_nums.pop(); Stack_nums.push(t1 + t2); } else if(sign == "-") { if(Stack_nums.size() < 2) { Error = true; return; } t2 = Stack_nums.top(); Stack_nums.pop(); t1 = Stack_nums.top(); Stack_nums.pop(); Stack_nums.push(t1 - t2); } else if(sign == "*") { if(Stack_nums.size() < 2) { Error = true; return; } t2 = Stack_nums.top(); Stack_nums.pop(); t1 = Stack_nums.top(); Stack_nums.pop(); Stack_nums.push(t1 * t2); } else if(sign == "/") { if(Stack_nums.size() < 2) { Error = true; return; } t2 = Stack_nums.top(); Stack_nums.pop(); t1 = Stack_nums.top(); Stack_nums.pop(); Stack_nums.push(t1 / t2); } else if(sign == "%") { if(Stack_nums.size() < 2) { Error = true; return; } t2 = Stack_nums.top(); Stack_nums.pop(); t1 = Stack_nums.top(); Stack_nums.pop(); Stack_nums.push(t1 % t2); } else if(sign == "^") { if(Stack_nums.size() < 2) { Error = true; return; } t2 = Stack_nums.top(); Stack_nums.pop(); t1 = Stack_nums.top(); Stack_nums.pop(); Stack_nums.push(pow(t1, t2)); } return; }



