1. 程式人生 > >四則運算的C++實現

四則運算的C++實現

一個很基本的問題,總是在重複發明輪子,為了不總討論這種月經問題,今天徹底終結這個問題吧。

大體分兩步:去掉括號,並轉化為字尾佇列,然後計算這個佇列

BaseCalc.h:

#pragma once

enum CalcType
{
	CalcType_None,
	CalcType_Number,
	CalcType_Operator_Plus,
	CalcType_Operator_Multiply,
	CalcType_Operator_Left_Parenthesis,

	CalcType_Operator_Minus = 0x80000000 + CalcType_Operator_Plus,
	CalcType_Operator_Divide = 0x80000000 + CalcType_Operator_Multiply,
};

class CBaseCalc
{
public:
	CBaseCalc(char cOpr)
	{
		m_nValue = cOpr;
		if ('+' == cOpr) m_nType = CalcType_Operator_Plus;
		else if ('*' == cOpr) m_nType = CalcType_Operator_Multiply;
		else if ('(' == cOpr) m_nType = CalcType_Operator_Left_Parenthesis;
		else if ('-' == cOpr) m_nType = CalcType_Operator_Minus;
		else if ('/' == cOpr) m_nType = CalcType_Operator_Divide;
		else m_nType = CalcType_None;
	}
	CBaseCalc(CalcType nType){ m_nType = nType; m_nValue = 0; }
	virtual ~CBaseCalc(){}

	double GetValue(){ return m_nValue; }
	void SetValue(double d){ m_nValue = d; }

	CalcType GetType(){ return m_nType; }
private:
	double m_nValue;
	CalcType m_nType;
};

double Calculate(CalcType nType,CBaseCalc& a, CBaseCalc&b)
{
	double dRet = 0;

	switch (nType)
	{
	case CalcType_None:
		break;
	case CalcType_Number:
		break;
	case CalcType_Operator_Plus:
		return a.GetValue() + b.GetValue();
		break;
	case CalcType_Operator_Multiply:
		return a.GetValue() * b.GetValue();
		break;
	case CalcType_Operator_Left_Parenthesis:
		break;
	case CalcType_Operator_Minus:
		return a.GetValue() -b.GetValue();
		break;
	case CalcType_Operator_Divide:
		return a.GetValue() /b.GetValue();
		break;
	default:
		break;
	}
	return dRet;
}

bool operator <(CBaseCalc& a, CBaseCalc& b)
{
	int nA = a.GetType() & 0x7FFFFFFF;
	int nB = b.GetType() & 0x7FFFFFFF;
	return nA<nB;
}

main.cpp
#include <string>
#include <stack>
#include <queue>
using namespace std;
#include "BaseCalc.h"

char * express = "1+2*3-(4*5+6)/7-8/9";

bool IsNum(int a)
{
	if (a>='1'&&a<='9')
	{
		return true;
	}

	return false;
}

double CalcPostFix(queue<CBaseCalc>& input_queue)
{
	stack<CBaseCalc> stackTmp;
	do
	{
		CBaseCalc a = input_queue.front();
		input_queue.pop();
		if (a.GetType() != CalcType_Number)
		{
			printf("%c ", (int)a.GetValue());
			CBaseCalc nNum1 = stackTmp.top();
			stackTmp.pop();
			CBaseCalc nNum2 = stackTmp.top();
			stackTmp.pop();

			double dRet = Calculate(a.GetType(), nNum2, nNum1);
			CBaseCalc nc(CalcType_Number);
			nc.SetValue(dRet);
			stackTmp.push(nc);
		}
		else
		{
			printf("%f ", a.GetValue());
			//NumCalc nc;
			//nc.SetValue(a.GetValue());
			stackTmp.push(a);
		}
	} while (!input_queue.empty());
	return stackTmp.top().GetValue();
}

void Fun()
{

	queue<CBaseCalc> queuePostFix;
	stack<CBaseCalc> stackOpr;

	char* pCur = express;
	int nLen = strlen(express);
	int nCur = 0;
	int nLast = 0;
	string aNum;
	char cLast = 0;
	while (nCur <= nLen)
	{
		pCur = express + nCur++;
		if (IsNum(*pCur))
		{
			aNum += *pCur;
		}
		else
		{
			if (!aNum.empty())
			{
				CBaseCalc bc(CalcType_Number);
				int nValue = atoi(aNum.c_str());
				bc.SetValue(nValue);
				queuePostFix.push(bc);
				aNum = "";
			}


			if (stackOpr.empty())
			{
				stackOpr.push(*pCur);
			}
			else
			{
				
				char cOpr = *pCur;
				cLast = cOpr;

				if ('(' == cOpr)
				{
					stackOpr.push(cOpr);
				}
				else if (')' == cOpr)
				{
					do
					{
						CBaseCalc a = stackOpr.top();
						stackOpr.pop();

						if (a.GetType() != CalcType_Operator_Left_Parenthesis)
						{
							queuePostFix.push(a);

						}
						else
						{
							break;
						}


					} while (true);
				}
				else
				{
					while (true)
					{
						CBaseCalc a = stackOpr.top();
						if (a.GetType() == CalcType_Operator_Left_Parenthesis)
						{
							stackOpr.push(cOpr);
							break;
						}
						CBaseCalc b(cOpr);
						if (a<b)
						{
							stackOpr.push(b);
							break;
						}
						else
						{
							queuePostFix.push(a);
							stackOpr.pop();
						}

						if (stackOpr.empty())
						{
							stackOpr.push(cOpr);
							break;
						}

					}



				}
			}

		}

		//nCur++;
	}
	printf("\n");
	double dRet=CalcPostFix(queuePostFix);
	printf("\n%s = %f\n", express, dRet);
}



int _tmain(int argc, _TCHAR* argv[])
{
	Fun();
	return 0;

}

本著開源精神送給後來程式設計師,沒有深度測試難免小BUG,希望學習者也是取其精華,修改別人bug也是自己提高的過程嘛。