优化一下上次写的代码,加上了注释,加强了可读性和封装性
#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 = "";//将字符串分割成第一个正括号前面,第一个反括号后面,还有中间,中间的递归
ite mid_s, mid_e, temp;
mid_e = find_end(st);
mid_s = find_start(st);
if (mid_s != st.begin())
{
start = get_start(st,mid_s);
}
if (mid_s != mid_e)
{
mid = get_mid(mid_s, mid_e);
}
if (mid_e != st.end())
{
end = get_end(st, mid_e);
}
return main_logic(start + main_logic(mid) + end);
}
}
//获取第一个反括号前面的第一个正括号
ite find_start(string &st)
{
auto it = st.begin();
while (it != st.end())
{
if (*it == ')')
{
while (it != st.begin())
{
if (*it == '(')
{
return it;
}
--it;
}
}
++it;
}
return it;
}
//获取第一个反括号
ite find_end(string &st)
{
auto it = st.begin();
while (it != st.end())
{
if (*it == ')')
{
break;
}
++it;
}
return it;
}
//获取括号前面的字符串
string get_start(string &st, ite it)
{
string start;
ite temp = st.begin();
while (temp != it)
{
start += *temp;
++temp;
}
return start;
}
//获取括号里面的字符串
string get_mid(ite start, ite end)
{
string mid;
ite temp;
temp = start + 1;
while (temp != end)
{
mid += *temp;
++temp;
}
return mid;
}
//获取括号后面的字符串
string get_end(string &st, ite it)
{
string end;
ite temp;
temp = it + 1;
while (temp != st.end())
{
end += *temp;
++temp;
}
return end;
}
//检查括号
int check_parentheses(string &st)
{
int count = 0;
for (auto it : st)
{
if (it == '(')
{
++count;
}
}
return count;
}
//处理不带括号的表达式分解成第一个操作数前面和2个操作数和操作符还有第二个操作数后面的一共3个字符串
string calculate(string &st)
{
if (0 == check_high(st))
{
return calculate_low(st);
}
else
{
string start = "", mid = "", end = "", temp = "";//处理字符串中的高阶乘除法
ite start_m, end_m, point;
end_m = find_calculate_end(st);
start_m = find_calculate_start(st);
if (start_m != st.begin())
{
start = get_calculate_start(st, start_m);
}
if (end_m != st.end() - 1)
{
end = get_calculate_end(st, end_m);
}
mid = get_calculate_mid(start_m + (start_m != st.begin()), end_m);
return calculate(start + calculate_high(mid) + end);
}
}
//获取第二个操作数后面的符号位置
ite find_calculate_end(string &st)
{
ite it = st.begin(), point;
while (*it != '*'&&*it != '/')
{
++it;
}
point = it + 1;
while (point != st.end())
{
if (*point == '+' || *point == '-' || *point == '*' || *point == '/')
{
if (point != it + 1)
{
break;
}
}
++point;
}
return point;
}
//获取第一个操作数前面的符号位置
ite find_calculate_start(string &st)
{
ite it = st.begin(), point;
while (*it != '*'&&*it != '/')
{
++it;
}
point = it;
while (point != st.begin())
{
if (*point == '+' || *point == '-'&&*(point - 1) != '+'&&*(point - 1) != '-')
{
break;
}
--point;
}
return point;
}
//获取无括号表达式的第一个操作数前面的字符串
string get_calculate_start(string &st, ite it)
{
string start;
ite point;
point = st.begin();
while (point != it + 1)
{
start += *point;
++point;
}
return start;
}
//获取第二个操作数后面的的字符串
string get_calculate_end(string &st, ite it)
{
string end;
ite point;
point = it;
while (point != st.end())
{
end += *point;
++point;
}
return end;
}
//获取2个操作数和操作符的字符串
string get_calculate_mid(ite start, ite end)
{
string mid;
ite point = start;
while (point != end)
{
mid += *point;
++point;
}
return mid;
}
//计算高阶计算*和/
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;
}
//计算低阶计算+和-
string calculate_low(string &st)
{
if (0 == check_low(st))
{
return st;
}
else
{
string first, next;
ite point = find_calculate_low_point(st);
first = get_low_first(st, point);
next = get_low_next(st, point);
return calculate_low(calculate_add(first) + next);
}
}
//分解得到2个操作数和一个操作符的字符串
string get_low_first(string &st, ite it)
{
string first;
ite point = st.begin();
while (point != it)
{
first += *point;
++point;
}
return first;
}
//第二个操作数后面的字符串
string get_low_next(string &st, ite it)
{
string next;
ite point = it;
while (point != st.end())
{
next += *point;
++point;
}
return next;
}
//寻找第二个低阶运算操作数后面的位置,可以是字符串结尾
ite find_calculate_low_point(string &st)
{
ite it = st.begin();
if (*it == '-' || *it == '+')
{
if (*(it + 1) != '+'&&*(it + 1) != '-')
{
++it;
}
}
while (*it != '+' && *it != '-')
{
++it;
}
while (*it < '0' || *it > '9')
{
++it;
}
while (*it != '+' && *it != '-')
{
++it;
if (it == st.end())
{
break;
}
}
return it;
}
//计算低阶运算
string calculate_add(string &st)
{
double total = atof(st.c_str());
int count = 0;
ite 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);
}
return to_string(total);
}
主函数和头文件
#include "reverse_polish.h"
int main()
{
reverse_polish();
system("pause");
return 0;
}
#include <iostream>
#include <string>
#include <stack>
#include <iterator>
using namespace std;
typedef std::_String_iterator<std::_String_val<std::_Simple_types<char>>> ite;
//获取数学表达式字符串
void reverse_polish();
/*处理括号------------------------------------*/
string main_logic(string &st);
//获取第一个反括号前面的第一个正括号
ite find_start(string &st);
//获取第一个反括号
ite find_end(string &st);
//获取括号前面的字符串
string get_start(string &st, ite it);
//获取括号里面的字符串
string get_mid(ite start, ite end);
//获取括号后面的字符串
string get_end(string &st, ite it);
//检查括号个数
int check_parentheses(string &st);
/*括号处理完毕--------------------------------*/
//处理不带括号的表达式分解成第一个操作数前面和2个操作数和操作符还有第二个操作数后面的一共3个字符串
string calculate(string &st);
//获取第二个操作数后面的符号位置
ite find_calculate_end(string &st);
//获取第一个操作数前面的符号位置
ite find_calculate_start(string &st);
//获取无括号表达式的第一个操作数前面的字符串
string get_calculate_start(string &st,ite it);
//获取第二个操作数后面的的字符串
string get_calculate_end(string &st, ite it);
//获取2个操作数和操作符的字符串
string get_calculate_mid(ite start,ite end);
//计算高阶计算*和/
string calculate_high(string &st);
//检查高阶运算符数量
int check_high(string &st);
//计算低阶计算+和-
string calculate_low(string &st);
//寻找第二个低阶运算操作数后面的位置,可以是字符串结尾
ite find_calculate_low_point(string &st);
//计算低阶运算符数量,不会把第一个数的负号当成操作符
int check_low(string &st);
//分解得到2个操作数和一个操作符的字符串
string get_low_first(string &st, ite it);
//第二个操作数后面的字符串
string get_low_next(string &st, ite it);
//计算低阶运算
string calculate_add(string &st);