逆波蘭運算器浮點求值(c++版本)

//--calculator_of_double.h   //----頭文件

/*----------浮點求值運算器-----------*/

/*-------框架--------*/
/*
1.判斷匹配
	a.搞個臨時棧tmpS存所有()
	b.判斷tmpS的匹配
		遇到(進
		遇到)
			若空,則假
			若非空,即是(,則彈(;ch++
		返回tmpS空即是匹配真
2.總函數
	1.若數字則s++,並後續,轉double,push
	2.若字符switch優先級,分別處理
		A.<,push
		B.=,pop,s++
		C,>,雙目運算,push
		
*/
#ifndef Calculator_of_double_
#define Calculator_of_double_

#include<stack>
using namespace std;

class CalculatorOD{
	const char * ExpArray;		//----輸入的表達式s.assign(cp)用c指針串替換
	stack<double> TmpDoubS;		//----double臨時變動棧
	stack<char> TmpSymbolS;		//----臨時運算符棧;
public:
	CalculatorOD(const char*);
	bool JudgeMarray();						//----檢測括號配對情況
	void Calculat();
	char OrderBetween(char, char);			<span style="white-space:pre">		</span>//----求優先級
	double GetResult(double, char, double);	<span style="white-space:pre">			</span>//----雙目求值
	int factorial(int);						//----單目階乘
};
#endif // !Calculator_of_double_



//----calculator_of_double.cpp  //----定義文件

#include"calculator_of_double.h"
#include<iostream>
#include<stack>
#include<ctype.h>
#include<stdlib.h>
#include<math.h>
#include<stdio.h>

CalculatorOD::CalculatorOD(const char *chPtr){
	ExpArray = chPtr;
	printf("\n輸入的是:	%s\n", ExpArray);
	Calculat();
}

bool CalculatorOD::JudgeMarray(){
	stack<char> TmpS;

	for (int i = 0; ExpArray[i] != '\0'; i++){
		if (ExpArray[i] == '(')
			TmpS.push(ExpArray[i]);
		else if (ExpArray[i] == ')'){
			if (!TmpS.empty())
				TmpS.pop();
			else
				return false;
		}
	}

	return TmpS.empty();
}

void CalculatorOD::Calculat(){
	if (!JudgeMarray()){
		cout << "輸入不配對!\n"<<endl;
		return;
	}

	TmpSymbolS.push('\0');

	for (int i = 0, j = 0; !TmpSymbolS.empty();)
	{
		char TmpStr[100/*sizeof(ExpArray) / sizeof(ExpArray[0])*/];					//----存儲浮點字符串;

		if (!isdigit(ExpArray[i])){			//----跳過非浮點
			switch (OrderBetween(TmpSymbolS.top(), ExpArray[i]))
			{
			case '<':
				TmpSymbolS.push(ExpArray[i++]); 
				break;
			case '=':
				TmpSymbolS.pop();
				i++;
				break;
			case '>':
				double TemD1 = TmpDoubS.top(); TmpDoubS.pop();
				char TemSbl = TmpSymbolS.top(); TmpSymbolS.pop();

				if (TemSbl == '!')
					TmpDoubS.push(factorial(static_cast<int>(TemD1)));
				else{
					double TemD2 = TmpDoubS.top(); TmpDoubS.pop();
					TmpDoubS.push(GetResult(TemD1, TemSbl, TemD2));
				}
				break;
			}
			
		}

		while (isdigit(ExpArray[i]) || ExpArray[i] == '.')
		{
			TmpStr[j++] = ExpArray[i++];	<span style="white-space:pre">		</span>//----複製
			TmpStr[j] = '\0';				//----每個字符後添加'\0'

			if (!isdigit(ExpArray[i]) && ExpArray[i] != '.'){
				TmpDoubS.push(atof(TmpStr));<span style="white-space:pre">		</span>//----轉化爲浮點存棧裏,atof(char*p以空NULL結尾)
				j = 0;					//----繼續沒串頭0索引開始
				//printf("%15.5lf", TmpDoubS.top());
			}
		}
	}
	int ival = 5;
	printf("求得的結果是:%15.8lf\n\n", TmpDoubS.top());
}

char CalculatorOD::OrderBetween(char chStack, char chNew){
	const char SymbolSheet[10][10] =   // 運算符優先等級 [棧頂][ 當前]
		//  |--------------- 當前運算符--------------|		
	{ '+', '-', '*', '/', '^', '!', '(', ')', '\0', '0'
	, '>', '>', '<', '<', '<', '<', '<', '>', '>', '+'	// + -
	, '>', '>', '<', '<', '<', '<', '<', '>', '>', '-'	// - |
	, '>', '>', '>', '>', '<', '<', '<', '>', '>', '*'	// * 棧
	, '>', '>', '>', '>', '<', '<', '<', '>', '>', '/'	// / 頂
	, '>', '>', '>', '>', '>', '<', '<', '>', '>', '^'	// ^ 運
	, '>', '>', '>', '>', '>', '>', '<', '>', '>', '!'	// ! 算
	, '<', '<', '<', '<', '<', '<', '<', '=', ' ', '('	// ( 符
	, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ')'	// ) |
	, '<', '<', '<', '<', '<', '<', '<', ' ', '=', '\0'	// \0--
	};

	char chS = chStack;//'(';//----棧
	char chCur = chNew;// ')';//----當前
	int X, Y;

	for (int i = 0; i <= 9; i++)
	if (SymbolSheet[i][9] == chS){
		X = i; break;
	}
	for (int i = 0; i <= 9; i++)
	if (SymbolSheet[0][i] == chCur){
		Y = i; break;
	}

	/*cout << endl << X << ',' << Y << endl;
	cout << SymbolSheet[X][Y] << endl;*/			//----測試用
	return SymbolSheet[X][Y];
}

double CalculatorOD::GetResult(double D2, char Syb, double D1){
	switch (Syb)
	{
	case'+':
		return D1 + D2;
	case'-':
		return D1 - D2;
	case'/':
		return D1 / D2;
	case'*':
		return D1 * D2;
	case'^':
		return pow(D1, D2);
	/*default:
		return 0;*/
	}
	return 0;//----無意義的,防止編譯警告無全部return
}

int CalculatorOD::factorial(int ival){
	if (ival == 0)
		return 1;
	return ival*factorial(ival - 1);
}

//----main.cpp--//----程序入口文件

#include<conio.h>
#include"calculator_of_double.h"
#include<iostream>
using namespace std;

int main(){
	CalculatorOD calA("32^(1/5)^(1/2)");
	CalculatorOD calB("(1*(3+2)-3)/2)");
	CalculatorOD calC("32.1^(1/5.09)^(1.19/2.13)");
	CalculatorOD calD("(1+2^3!-4)*(5!-(6-(7-(89-0!))))");

	return _getch();
}/*--------以下可實現---------
 "32^(1/5)^(1/2)"			得到1.41
 "(1+2^3!-4)*(5!-(6-(7-(89-0!))))"  <span style="white-space:pre">	</span>得到2013
 "32.1^(1/5.09)^(1.19/2.13)"		得到1.46338

 ------以下風格不可實現-------
 32^(-5)
 -3+1
 */







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