(请看下一篇改进版)
本来是想写一个逆波兰的,写着写着就写歪了,写成了直接处理表达式字符串并输出结果,写的差不多了才发现逆波兰
比这样写应该要简单,也可能是我的思路有问题吧,还有一些需要优化的地方以后再说吧。
主要的思路是这样的,先处理括号,把一个带括号的表达式分解成前段,括号内的内容为中段,括号后面的内容分为
后段,递归处理中段括号内的字符串,因为这样可以完美的处理好括号的问题,然后把不带括号的表达式传递给计算不带
括号的表达式的函数,先扫描一遍字符串的高阶运算*和/,同理把字符串分成前段,2个操作数和中间的符号,还有后面的
内容,当字符串的所有高阶运算处理完成之后,就传递给下一个只处理+和-运算的函数,因为还没有写负负得正这些规则
,所以目前只能处理2个(包括2个)以下的负号,处理+-运算的时候也是用的和上述方法同样的原理,把表达式分割成一
个带一个操作符号和2个操作数的字符串和后面的字符串,这样递归了3层之后,就得到了最终的结果了.
#include "reverse_polish.h"
void reverse_polish()
{
string st;
cout << "输入一个表达式" << endl;
cin >> st;
cout<<main_logic(st);
}
//处理括号
string main_logic(string st)
{
if (0 == check_parentheses(st))
{
return calculate(st);
}
else
{
string start = "", mid = "", end = "";//将字符串分割成第一个正括号前面,第一个反括号后面,还有中间,中间的递归
int count = check_parentheses(st);
auto it = st.begin(), mid_s = it, mid_e = it, temp = it;
while (it != st.end())
{
if (*it == ')')
{
break;
}
++count;
++it;
}
mid_e = it;
while (it != st.begin())
{
if (*it == '(')
{
break;
}
--count;
--it;
}
mid_s = it;
if (mid_s != st.begin())
{
temp = st.begin();
while (temp != mid_s)
{
start += *temp;
++temp;
}
}
if (mid_s != mid_e)
{
temp = mid_s + 1;
while (temp != mid_e)
{
mid += *temp;
++temp;
}
}
if (mid_e != st.end())
{
temp = mid_e + 1;
while (temp != st.end())
{
end += *temp;
++temp;
}
}
return main_logic(start + main_logic(mid) + end);
}
}
int check_parentheses(string st)
{
int count = 0;
for (auto it : st)
{
if (it == '(')
{
++count;
}
}
return count;
}
//处理不带括号的表达式并把结果转换成string输出
string calculate(string st)
{
if (0 == check_high(st))
{
return calculate_low(st);
}
else
{
string start = "", mid = "", end = "", temp = "";//处理字符串中的高阶乘除法
auto it = st.begin(), start_m = it, end_m = it, point= st.begin();
while (*it != '*'&&*it != '/')
{
++it;
}
point = it + 1;
while (point != st.end())
{
if (*point == '+' || *point == '-' || *point == '*' || *point == '/')
{
if (point != it + 1)
{
break;
}
}
++point;
}
end_m = point;//确定乘除号后面的操作数
point = it;
while (point != st.begin())
{
if (*point == '+' || *point == '-'&&*(point - 1) != '+'&&*(point - 1) != '-')
{
break;
}
--point;
}
start_m = point;//确定乘除号前面的操作数
if (start_m != st.begin())
{
point = st.begin();
while (point != start_m + 1)
{
start += *point;
++point;
}
}
if (end_m != st.end() - 1)
{
point = end_m;
while (point != st.end())
{
end += *point;
++point;
}
}
if (start_m != st.begin())
{
point = start_m + 1;
}
else
{
point = start_m;
}
while (point != end_m)
{
mid += *point;
++point;
}
return calculate(start + calculate_high(mid) + end);
}
}
string calculate_low(string st)
{
if (0 == check_low(st))
{
return st;
}
else
{
string next;
double total = atof(st.c_str());
int count = 0;
auto it = st.begin();
if (*it == '-' || *it == '+')
{
if (*(it + 1) != '+'&&*(it + 1) != '-')
{
++count;
++it;
}
}
while (*it != '+' && *it != '-')
{
++count;
++it;
}
if (*it == '+')
{
total += atof(st.c_str() + count + 1);
}
else
{
total -= atof(st.c_str() + count + 1);
}
while (*it < '0' || *it > '9')
{
++count;
++it;
}
while (*it != '+' && *it != '-')
{
++count;
++it;
if (it == st.end())
{
break;
}
}
if (it != st.end())
{
while (it != st.end())
{
next += *it;
++it;
}
}
return calculate_low(to_string(total) + next);
}
}
string calculate_high(string st)
{
int count = 0;
auto it = st.begin();
double total = atof(st.c_str());
string temp;
while (*it != '*'&&*it != '/')
{
++count;
++it;
}
if (*it == '*')
{
total *= atof(st.c_str() + count + 1);
}
else
{
total /= atof(st.c_str() + count + 1);
}
temp = to_string(total);
return temp;
}
int check_high(string st)
{
int count = 0;
for (auto it : st)
{
if (it == '*' || '/' == it)
{
++count;
}
}
return count;
}
int check_low(string st)
{
int count = 0;
auto it = st.begin();
if (*it == '+' || *it == '-')
{
++it;
}
for (; it != st.end(); ++it)
{
if (*it == '+' || '-' == *it)
{
++count;
}
}
return count;
}
因为本人比较懒,就没怎么写注释,见谅.
头文件和main文件
#include <iostream>
#include <string>
#include <stack>
using namespace std;
void reverse_polish();
string main_logic(string st);
int check_parentheses(string st);
string calculate(string st);
string calculate_high(string st);
string calculate_low(string st);
int check_high(string st);
int check_low(string st);
#include "reverse_polish.h"
int main()
{
reverse_polish();
system("pause");
return 0;
}
其实写到了这里就差不多实现了我想要的功能了,可能会改进处理多个无意义的运算符号的功能。
几经修改,修正了大概10个左右的bug,现在应该问题很小了.