C語言 表達式轉換 中綴表達式轉後綴表達式

算術表達式有前綴表示法、中綴表示法和後綴表示法等形式。日常使用的算術表達式是採用中綴表示法,即二元運算符位於兩個運算數中間。請設計程序將中綴表達式轉換爲後綴表達式。

輸入格式:

輸入在一行中給出不含空格的中綴表達式,可包含+-*\以及左右括號(),表達式不超過20個字符。

輸出格式:

在一行中輸出轉換後的後綴表達式,要求不同對象(運算數、運算符號)之間以空格分隔,但結尾不得有多餘空格。

輸入樣例:

2+3*(7-4)+8/4

輸出樣例:

2 3 7 4 - * + 8 4 / +

解題思路:

這道題比較混蛋,很混蛋,他也咩有告訴你到底是什麼數字,而且還把“/”給打反了打成了“\”,其次呢,對於數字的輸入不只是一位整數,而是:正負都有的多位小數輸入 。騙子,曰噢。

我的處理辦法是用string::iterator來記錄當前掃描到的位置,然後用這個iterator來進行數字的單獨識別,其他情況按照逆波蘭算法處理就好,其他博主的文章寫的已經很多了,原理就不再贅述了,此處留下博主的一種實現方案。

代碼:

#include <iostream>
#include <map>
#include <stack>
#include <vector>

using namespace std;

typedef map<char, int> TokenLevel;

vector<string> reversePolishNotation(const string& expression, const TokenLevel& tokenLevel);
string readNumber(string::const_iterator& it, const string& expression);
int main() {
	const TokenLevel tokenLevel{
		{'+', 1},{'-', 1},
		{'*', 2},{'/', 2},
		{'(', 0},{')', 0}
	};

	string inputExpression;
	cin >> inputExpression;

	auto res = reversePolishNotation(inputExpression, tokenLevel);
	cout << res[0];
	for (int i = 1; i < res.size(); i++) {
		cout << " " << res[i];
	}

	return 0;
}

inline bool checkNumber(string::const_iterator& it, const string& expression) {
	return isdigit(*it) ||
		(it == expression.begin() || *(it - 1) == '(') && (*it == '-' || *it == '+') ||
		*it == '.' && isdigit(*(it + 1));
}
string readNumber(string::const_iterator& it, const string& expression) {
	string rtn;
	while (it != expression.end() && checkNumber(it, expression))
		if (*it != '+') rtn += *it++; else ++it;
	return rtn;
}

vector<string> reversePolishNotation(const string& expression, const TokenLevel& tokenLevel) {
	vector<string> result;
	vector<char> buffer;
	for (auto it = expression.begin(); it != expression.end();) {
		auto ch = *it;
		if (!checkNumber(it, expression)) {
			if (ch == '(' || buffer.empty()) {
				buffer.push_back(ch);
			} else if (ch == ')') {
				while (buffer.back() != '(') {
					result.push_back(string{ buffer.back() });
					buffer.pop_back();
				}
				buffer.pop_back();
			} else {
				if (tokenLevel.at(ch) <= tokenLevel.at(buffer.back())) {
					while (!buffer.empty() && tokenLevel.at(ch) <= tokenLevel.at(buffer.back())) {
						result.push_back(string{ buffer.back() });
						buffer.pop_back();
					}
				}
				buffer.push_back(ch);
			}++it;
		} else result.push_back(readNumber(it, expression));
	}

	while (!buffer.empty()) {
		result.push_back(string{ buffer.back() });
		buffer.pop_back();
	}
	return result;
}

當然,博主爲什麼這麼寫呢,當然是爲了可讀性可維護性還有可擴展性啦。

舉個🌰

inline bool checkNumber(string::const_iterator& it, const string& expression);

中的isdigit數字判定改爲isalnum之後,就可以解析單詞啦o(* ̄▽ ̄*)ブ

inline bool checkNumber(string::const_iterator& it, const string& expression) {
	return isalnum(*it) ||
		(it == expression.begin() || *(it - 1) == '(') && (*it == '-' || *it == '+') ||
		*it == '.' && isalnum(*(it + 1));
}

測試

結尾:

(´▽`ʃ♡ƪ) over~

就這。

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