stackmachine.cpp

来自「这是在wince下面可以跑的一个画函数的软件」· C++ 代码 · 共 316 行

CPP
316
字号
//////////////////////////////////////////////////////////////////////
//
//	Graphite For WinCE(Pocket PC)
//  Initially Written By Hyouck "Hawk" Kim, peakhunt@yahoo.com
//	2002, All Rights Reserved
//
//	This is GPLed, open source based, software development project.
//	For more question about GPL,
//	visit http://www.gnu.org/licenses/gpl.txt
//
//	
//	Revision History
//	Nov/30/2002,		Initial Release		hkim	
//
//
//
//
//
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
//
// This is implementation of a simple calculator based on POSTFIX
// stack machine.
//
// Several Classes are here.
// First of all, a simple stack and linked list are here.
// The reason those classes are written is STL is not available
// on WinCE as of Nov/2002.
//
// The implementation is awkward and not so serious.
//
// Second of all, 
// POSTFIX calculator implementation is provided here.
// The idea is really simple.
// First, by parser, which is implemented as CMathParser,
// all the infix tokens are converted to postfix linked list.
// The Stack Machine calculates some arithmetic with the postfix
// linked list and a stack, which is quite traditional and not
// so much interesting.
//
// Right now, only a limited set of operators and mathematical functions
// are provided. But to extend the set should be a trivila task.
// H.Kim
//////////////////////////////////////////////////////////////////////

// StackMachine.cpp: implementation of the CStackMachine class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "graphite.h"
#include "StackMachine.h"
#include "mathlex.h"
#include <math.h>
#include <stdlib.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSimpleStack::CSimpleStack()
{
	m_top = NULL;
}

CSimpleStack::~CSimpleStack()
{
	while(!isEmpty())
	{
		pop();
	}
}

void CSimpleStack::push(double val)
{
	struct CStackElement* elem = NULL;
	elem = new struct CStackElement;

	elem->val = val;
	elem->next = m_top;

	m_top = elem;
}

double CSimpleStack::pop(void)
{
	struct CStackElement* elem;
	double val;

	elem = m_top;
	if(elem == NULL)
		return 0;

	m_top = m_top->next;

	val = elem->val;
	delete elem;
	return val;
}

bool CSimpleStack::isEmpty(void)
{
	return m_top == NULL ? true : false;
}

CStackMachine::CStackMachine()
{
	m_list = NULL;
	m_valid = false;
}

CStackMachine::~CStackMachine()
{
	if(m_list != NULL)
		delete m_list;
}

//
// this is postfix calculator without stack
//
double CStackMachine::execute(double x)
{
	CListElement* elem;
	CSimpleStack stack;
	double v[2], result, numb;

	elem = m_list->m_head;
	while(elem != NULL)
	{
		switch(elem->token->m_type)
		{
		case MATH_TOKEN_TYPE_OP:
			if(stack.isEmpty())
			{
				TRACE(L"BUG op, stack is empty\n");
				return 0;
			}
			v[1] = stack.pop();

			if(stack.isEmpty())
			{
				TRACE(L"BUG op 2, stack is empty\n");
				return 0;
			}
			v[0] = stack.pop();
			result = mathOP(v, 2, elem->token->m_str);
			stack.push(result);
			break;
		case MATH_TOKEN_TYPE_VAR:
			// FIXME : variable substitution is not yet implemened
			stack.push(x);
			break;
		case MATH_TOKEN_TYPE_NUM:
			{
				char buffer[512];
				WideCharToMultiByte(CP_ACP, NULL, elem->token->m_str, -1,
					buffer,512, NULL, NULL);
				numb = atof(buffer);
				stack.push(numb);
			}
			break;

		case MATH_TOKEN_TYPE_FUNC:
			if(stack.isEmpty())
			{
				TRACE(L"(BUG func, stack is empty\n");
				return 0;
			}
			v[0] = stack.pop();
			result = mathFunc(v, 1, elem->token->m_str);
			stack.push(result);
			break;
		}
		elem = elem->next;
	}

	if(stack.isEmpty())
	{
		TRACE(L"BUG: returning stack is empty\n");
		return 0;
	}
	return stack.pop();
}

void CStackMachine::changeFormula(CTokenList* list)
{
	if(m_list != NULL)
		delete m_list;
	m_list = list;
	m_valid = true;
}

double CStackMachine::mathOP(double variable[], int len, CString &op)
{
	double result;

	if(len != 2)
	{
		TRACE(L"PANIC : BUG\n");
		return 0;
	}

	if(op.Compare(L"+") == 0)
	{
		result = variable[0] + variable[1];
	}
	else if(op.Compare(L"-") == 0)
	{
		result = variable[0] - variable[1];
	}
	else if(op.Compare(L"*") == 0)
	{
		result = variable[0] * variable[1];
	}
	else if(op.Compare(L"/") == 0)
	{
		result = variable[0] / variable[1];
	}
	else if(op.Compare(L"^") == 0)
	{
		result = pow(variable[0], variable[1]);
	}
	else
	{
		TRACE(L"PANIC : BUG unrecognized op\n");
		return 0;
	}
	return result;
}

double CStackMachine::mathFunc(double variable[], int len, CString func)
{
	if(len != 1)
	{
		TRACE(L"PANIC : BUG VAR!= 1\n");
		return 0;
	}

	double result;

	if(func.Compare(L"sin") == 0)
	{
		result = sin(variable[0]);
	}
	else if(func.Compare(L"cos") == 0)
	{
		result = cos(variable[0]);
	}
	else if(func.Compare(L"tan") == 0)
	{
		result = tan(variable[0]);
	}
	else if(func.Compare(L"sqrt") == 0)
	{
		result = sqrt(variable[0]);
	}
	else if(func.Compare(L"abs") == 0)
	{
		result = variable[0];
		if(result < 0)
			result = -1*result;
	}
	else if(func.Compare(L"neg") == 0)
	{
		result = -1*variable[0];
	}
	else
	{
		TRACE(L"PANIC : BUG unrecognized function\n");
	}

	return result;
}


CTokenList::CTokenList()
{
	m_head = m_tail = NULL;
}

CTokenList::~CTokenList()
{
	CListElement* elem, *tmp;
	elem = m_head;
	while(elem != NULL)
	{
		tmp = elem;
		delete tmp->token;
		delete tmp;
		elem = elem->next;
	}
}

void CTokenList::addTail(CMathToken* elem)
{
	CListElement* newElem = new CListElement;

	newElem->token = elem;
	newElem->next = NULL;

	if(m_head == NULL)
	{
		m_head = m_tail = newElem;
	}
	else
	{
		m_tail->next = newElem;
		m_tail = newElem;
	}
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?