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,現在應該問題很小了.



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章