用计算器比较麻烦,因为它不按计算顺序来,需要按很多次(加之平时用得少,又掺进来负数,按上十来次就按错了)。出于统计方便,写了个程序专门算数。
效果如下(格式不作要求,只要输对就行):
主要代码:
/*/////////////////////////////////////// 带括号的四则运算: ------------------------------------- 1、中序转为后序表达式 顺序读取,对不同对象按不同情况处理: 1)运算数:直接输出 2)左括号:压入堆栈 3)右括号:将栈的运算符弹出并输出,直到遇到左括号(弹出,不输出) 4)运算符: 若优先级大于栈顶运算符,则把它压栈 若优先级小于等于栈顶运算符,将栈顶运算符弹出并输出,再比较新的栈顶运算符, 直到该运算符优先级大于栈顶运算符为止,然后将该运算符压栈 5)若所有对象处理完毕,则把堆栈中残留的运算符一并输出 -------------------------------------- 2、计算后序表达式 每遇到运算符则对它之前的两个数计算 -------------------------------------- 程序支持形如 -0.3 + 4 * (-1.5 + -6.4 / -2) * -4 形式的算式 ////////////////////////////////////////*/ #include "LinkedStack.h" #include <string> #include <sstream> #include <iostream> using namespace std; string Calculate(char oper, double a, double b) { switch(oper) { case '+':a += b; break; case '-':a -= b; break; case '*':a *= b; break; case '/': if(b != 0) a /= b; else throw BadInput(); } stringstream stream; stream << a; string str; stream >> str; return str; } // 删除字符串中空格 void trim(string &str, string::size_type pos = 0) { static const string delim = " \t"; //删除空格或者tab字符 pos = str.find_first_of(delim, pos); if(pos == string::npos) return; trim(str.erase(pos, 1)); } // 从某处起略过数字添加右括号 void AddRight(string& line, int i) { int len = line.length(); ++i; while(i < len && (line[i] == '0' || line[i] == '1' || line[i] == '2' || line[i] == '3' || line[i] == '4' || line[i] == '5' || line[i] == '6' || line[i] == '7' || line[i] == '8' || line[i] == '9' || line[i] == '.')) ++i; line.insert(i, ")"); } // 处理负数和正号 string& HandleExp(string& line) { trim(line); if(line[0] == '-' || line[0] == '+') { AddRight(line, 0); // 先补右括号 line = "(0" + line; // 再补左括号 } // 需用 line.length(),因为长度不断在变化 for(unsigned i = 1; i < line.length(); ++i) { if(( line[i] == '-' || line[i] == '+') && ( line[i - 1] == '+' || line[i - 1] == '-' || line[i - 1] == '*' || line[i - 1] == '/' || line[i - 1] == '(' )) { AddRight(line, i); // 先补右括号 line = line.insert(i, "(0"); } } return line; } // 处理表达式,并将中序转后序表达式,并进行计算 string InToPost(string& line) { line = HandleExp(line); LinkedStack<string>num; LinkedStack<char>symb; char op; double a,b; int size = line.length(), i; string item(""); for(i = 0; i < size; ++i) { if(line[i] == '(') { symb.Add('('); continue; } if(line[i] == '*' || line[i] == '/') { if(item != "") { num.Add(item); item = ""; } if( !symb.IsEmpty() && symb.Top() != '(' &&(symb.Top() == '*' || symb.Top() == '/')) { symb.Delete(op); num.Delete(item); b = strtod(item.c_str(), NULL); num.Delete(item); a = strtod(item.c_str(), NULL); num.Add( Calculate(op, a, b) ); item = ""; } symb.Add(line[i]); continue; } if(line[i] == '+' || line[i] == '-') { if(item != "") { num.Add(item); item = ""; } if(!symb.IsEmpty() && symb.Top() != '(' ) { symb.Delete(op); num.Delete(item); b = strtod(item.c_str(), NULL); num.Delete(item); a = strtod(item.c_str(), NULL); num.Add(Calculate(op, a, b)); item = ""; } symb.Add(line[i]); continue; } if(line[i] == ')') { if(item != "") { num.Add(item); item = ""; } while(!symb.IsEmpty() && symb.Top() != '(') { symb.Delete(op); num.Delete(item); b = strtod(item.c_str(), NULL); num.Delete(item); a = strtod(item.c_str(), NULL); num.Add(Calculate(op, a, b)); } symb.Delete(op); // 删除 ( item = ""; continue; } else { item += line[i]; } } // 最后一个数字 if(item != "") { num.Add(item); item = ""; } while(!symb.IsEmpty()) { symb.Delete(op); num.Delete(item); b = strtod(item.c_str(), NULL); num.Delete(item); a = strtod(item.c_str(), NULL); num.Add(Calculate(op, a, b)); } return num.Top(); }
时间: 2024-10-08 16:46:28