string类型的数学表达式处理

(请看下一篇改进版)

  本来是想写一个逆波兰的,写着写着就写歪了,写成了直接处理表达式字符串并输出结果,写的差不多了才发现逆波

比这样写应该要简单,也可能是我的思路有问题吧,还有一些需要优化的地方以后再说吧。

  主要的思路是这样的,先处理括号,把一个带括号的表达式分解成前段,括号内的内容为中段,括号后面的内容分为

后段,递归处理中段括号内的字符串,因为这样可以完美的处理好括号的问题,然后把不带括号的表达式传递给计算不带

括号的表达式的函数,先扫描一遍字符串的高阶运算*和/,同理把字符串分成前段,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,现在应该问题很小了.



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值