算术表达式的计算(基于逆波兰表达式)的c++实现

来源:互联网 发布:网络摄像头平台 编辑:程序博客网 时间:2024/06/07 04:50

        以字符串的形式输入一个算术表达式,如何对其进行识别并计算出结果呢?

        如果按照普通的算术表达式计算,由于需要考虑到操作符和括号的优先级,实现起来十分麻烦。但是基于逆波兰表达式(也称后缀表达式)来计算的话,可以忽略其优先级顺序进行计算,十分简便。

        逆波兰表达式的定义及算法可以很方便的查询到,这里不再赘述。

        程序的说明如下:

        输入一个算术表达式,将其转换成为后缀表达式并输出计算结果。算术表达式中只能识别“+”、“-”、“*”、“/”四种运算符,负数需要用括号表示:如“(-1)”。对于除了操作数和运算符之外的字符自动忽略。

        首先是栈的定义以及字符串转换为长整形long的函数:

<span style="font-size:14px;">template<typename T>class Stack {public:void pop() {if (empty())return ;data.pop_back();--topstack;}const T& top() {return data[topstack];}void push(const T& item) {data.push_back(item);++topstack;}bool empty() {return topstack == -1 ? true : false;}private:std::vector<T> data;int topstack = -1;};long str_to_num(const std::string& s) {  //字符串转长整形std::istringstream str(s);long num;str >> num;return num;}</span>


        程序实现的思路及代码如下:

        1.读取表达式,构造vector<string>储存成为普通的中缀表达式。忽略无意义字符,对于负数,去除括号保存。

<span style="font-size:14px;">void expression(std::vector<std::string> &vec ,const std::string& s){   std::string num;bool neg = false;               //判定是否负数for (auto iter = s.begin(); iter != s.end();/*空*/) {if (*iter >= 48 && 57 >= *iter) {num += *iter;++iter;}else if (*iter == '+' || *iter == '-' || *iter == '*' || *iter == '/') {if (num.size() != 0)vec.push_back(num);num = *iter;vec.push_back(num);num = "";++iter;}else if (*iter == '(') {                  //处理负数情况if (num.size() != 0) {vec.push_back(num);num = "";}if (*(++iter) == '-') {neg = true;num += '-';++iter;}else vec.push_back("(");}else if (*iter == ')') {if (num.size() != 0) {vec.push_back(num);if (!neg)vec.push_back(")");num = "";++iter;}}else ++iter;}if (num.size() != 0)vec.push_back(num);}</span>


        2.历遍中缀vector<string>,利用栈构造后缀vector<string>:

                  (1)对于操作数和左括号“(”,直接放入栈中。

                  (2)对于操作符“+”、“-”,弹出栈内元素直至栈为空或者遇到“(”,将操作符放入栈中。

            (3)对于操作符“*”、“/”,弹出栈内元素直至栈为空或者遇到“+”、“-”、“(”,将操作符放入栈中。
            (4)对于右括号“)”,弹出栈内元素直至遇到左括号“(”。
            (5)历遍结束后,弹出栈内所有元素。
<span style="font-size:14px;">void postfix_exp(std::vector<std::string> &p_vec, std::vector<std::string> &vec) {   Stack<std::string> sta;for (auto &oper : vec) {if (oper == "+" || oper == "-") {                    //对于加号和减号while (true) {if (sta.empty() || sta.top() == "(")break;p_vec.push_back(sta.top());sta.pop();}sta.push(oper);}else if (oper == "*" || oper == "/") {                //对于乘号和除号while (true) {if (sta.empty() || sta.top() == "+" ||sta.top() == "-" || sta.top() == "(")break;p_vec.push_back(sta.top());sta.pop();}    sta.push(oper);}else if (oper == ")") {                                  //对于右括号while (true) {if (sta.top() == "(") {sta.pop();break;}p_vec.push_back(sta.top());sta.pop();}}else sta.push(oper);}while (!sta.empty()) {p_vec.push_back(sta.top());sta.pop();}std::cout << "The postfix-expression is : ";for (auto &row : p_vec)std::cout << row<<" ";std::cout << std::endl;}</span>


 3.历遍后缀vector<string>。对于操作数转换成为长整形long放入栈中;对于运算符则弹出两个操作数进行计算,然后将结果放入栈中。栈中剩余的最后一项便是计算的最终结果。
<span style="font-size:14px;">const long count(std::vector<std::string> &vec) {            Stack<long> sta;for (auto &oper : vec) {long lhs = 0, rhs = 0;if (oper=="+") {rhs = sta.top();sta.pop();lhs = sta.top();sta.pop();sta.push(lhs + rhs);}else if (oper == "-") {rhs = sta.top();sta.pop();lhs = sta.top();sta.pop();sta.push(lhs - rhs);}else if (oper == "*") {rhs = sta.top();sta.pop();lhs = sta.top();sta.pop();sta.push(lhs * rhs);}else if (oper == "/") {rhs = sta.top();sta.pop();lhs = sta.top();sta.pop();sta.push(lhs / rhs);}elsesta.push(str_to_num(oper));}if (!sta.empty())return sta.top();elsereturn 0;}</span>

         最后则是main()函数的代码:
<span style="font-size:14px;">int main() {while (true) {std::string str;std::cout << "Enter the expression,or q for quit : ";std::cin >> str;if (str == "q")break;std::vector<std::string> exp;std::vector<std::string> p_exp;expression(exp, str);postfix_exp(p_exp, exp);std::cout << "The result is : " << count(p_exp) <<"."<< std::endl<<std::endl;}}</span>
   新手一枚,欢迎大大们的建议和指导!



0 0
原创粉丝点击