1. 程式人生 > >中綴表示式轉字尾並求值C++(括號,小數點,負數)

中綴表示式轉字尾並求值C++(括號,小數點,負數)

題目內容:

通過把“中綴轉字尾”和“字尾求值”兩個演算法功能整合在一起(非簡單的順序呼叫),

實現對中綴表示式直接求值,新演算法還是從左到右掃描中綴表示式,

但同時使用兩個棧,一個暫存操作符,一個暫存運算元,來進行求值。

(支援 + - * / ^ 五種運算)

輸入格式:

共1行,為1個字串,即一箇中綴表示式,

其中每個數字或符號間由一個空格隔開。

輸出格式:

共1行,為一個整數,即求值的結果。

輸入樣例:

( 2 + 3 ) * 6 + 4 / 2

輸出樣例:

32

思路

  1. 首先將中綴轉換為字尾表示式。 (a ).對於形如(-1+1)的計算。 (b )使用一個棧來暫存操作符。將結果直接輸出到一個字串。 (c ).對符號設立優先順序,^ > / * > + - 。 (d ).括號的匹配與優先順序問題。’( '直接進棧,遇 ‘ )’彈出直至上一個‘( ’之間的所有運算子,括號不輸出到字尾表示式中。
  2. 字尾表示式的計算。 (a ).乘方運算函式 pow(int _left, int _right); (b ).空格符的處理:(a+b)與 ( a + b ):加入一個case ‘ ’:break;即可。

函式

void IntoPost(string inStr); //字首轉字尾 bool isPush(char pre, char late); //優先順序比較 void Calculate(char np); //彈出兩個棧內數運算後再壓進棧 void CalFix(); //字尾表示式計算 void pushChar(char np); //運算子出棧 string format(string str) ; //解決(-1+2)負數報錯問題

一些關鍵點

解決負數問題思路: 即在 -1 前面加一個0 變成 0-1 即可

string format(string str) {					//解決(-1+2)負數報錯問題 
	for (int i = 0; i < str.length(); i++)	//即在 -1 前面加一個0 變成  0-1 即可
		if (str[i] == '-')
			if (i == 0)
				str.insert(0, 1, '0');
			else if (str[i - 1] == '(')
				str.insert(i, 1, '0');
	return str;
}

優先順序比較(其實有更簡單一點的操作,我做複雜了)

void pushChar(char np) {					//運算子出棧		
	if (!CharStack.empty()){
		while (!CharStack.empty() && isPush(CharStack.top(), np)) {
			fixStr += CharStack.top();		//判斷優先順序
			CharStack.pop();
		}
		CharStack.push(np);
	}
	else 
		CharStack.push(np);
}	

bool isPush(char pre, char late) {			//優先順序比較
	if (late == '^')
		if (pre == '^') return true;
		else return false;
	if (late == '*' || late == '/')
		if (pre == '^' || pre == '*' || pre == '/') return true;
		else return false;
	if (late == '+' || late == '-')
		if (pre == '(') return false;
		else return true;
	return false;
}

程式碼

/* Author : YaaaZa! ?
*  Time	  : 2018.10.20
*  中綴轉字尾求值 
*/
#include "stdafx.h"
#include<iostream>
#include<stack>
#include<string>

using namespace std;
stack<int> MoveIn;
stack<char> CharStack;
string fixStr = "";

void IntoPost(string inStr);
bool isPush(char pre, char late);
void Calculate(char np);
void CalFix();
void pushChar(char np);
string format(string str) {					//解決(-1+2)負數報錯問題 
	for (int i = 0; i < str.length(); i++)	//即在 -1 前面加一個0 變成  0-1 即可
		if (str[i] == '-')
			if (i == 0)
				str.insert(0, 1, '0');
			else if (str[i - 1] == '(')
				str.insert(i, 1, '0');
	return str;
}
int main(){
	string inStr;
	getline(cin, inStr);					//使用getline 解決字串錄入遇空格結束的問題  類似 ( a + b ) 只寫入了 ( 的
	inStr = format(inStr); 
	IntoPost(inStr);
	CalFix();
    return 0;
}
void IntoPost(string inStr) {				//字首轉字尾
	for (int i = 0; i < inStr.length(); i++) {
		switch (inStr[i]) {
		case ' ': break;
		case '+':pushChar('+'); break;
		case '(':CharStack.push('('); break;//遇前括號直接入棧 
		case ')':							//遇後括號彈出所有至上一個括號
			while (CharStack.top() != '(') {
				fixStr += CharStack.top();
				CharStack.pop();
			}
			CharStack.pop();
			break;
		case '/':pushChar('/'); break;
		case '*':pushChar('*'); break;
		case '-':pushChar('-'); break;
		case '^':pushChar('^'); break;
		default:
			fixStr += inStr[i]; break;		//數字直接輸出
		}
	}
	while (!CharStack.empty()) {			//整式尾部時彈出所有站內符號
		fixStr += CharStack.top();
		CharStack.pop();
	}
}
void pushChar(char np) {					//運算子出棧		
	if (!CharStack.empty()){
		while (!CharStack.empty() && isPush(CharStack.top(), np)) {
			fixStr += CharStack.top();		//判斷優先順序
			CharStack.pop();
		}
		CharStack.push(np);
	}
	else 
		CharStack.push(np);
}				
bool isPush(char pre, char late) {			//優先順序比較
	if (late == '^')
		if (pre == '^') return true;
		else return false;
	if (late == '*' || late == '/')
		if (pre == '^' || pre == '*' || pre == '/') return true;
		else return false;
	if (late == '+' || late == '-')
		if (pre == '(') return false;
		else return true;
	return false;
}
void CalFix() {								//字尾表示式計算
	for (int i = 0; i < fixStr.length(); i++) {
		switch (fixStr[i]) {
		case '+':Calculate('+'); break;
		case '/':Calculate('/'); break;
		case '*':Calculate('*'); break;
		case '-':Calculate('-'); break;
		case '^':Calculate('^'); break;
		case ' ': break;
		default:
			int a;
			a = (int)(fixStr[i] - 48);
			MoveIn.push(a);
			break;
		}
	}
	cout << MoveIn.top();
}
void Calculate(char np) {					//彈出兩個棧內數運算後再壓進棧
	int pre, late;
	late = MoveIn.top();
	MoveIn.pop();
	pre = MoveIn.top();
	MoveIn.pop();
	switch (np) {
	case '+':MoveIn.push(pre + late); break;
	case '/':MoveIn.push(pre / late); break;
	case '*':MoveIn.push(pre * late); break;
	case '-':MoveIn.push(pre - late); break;
	case '^':MoveIn.push(pow(pre,late)); break;
	default:
		break;
	}
}