基于堆栈的计算器

简单的基于堆栈的计算器

**(1)**接受用户的输入,输入形式有两种:数字、运算符。
**(2)**数字保存在堆栈中(LIFO类型内存),将数字推入堆栈。
**(3)**对堆栈顶端的两个数字出栈,应用运算符,若堆栈只有一个数字,将它重复,应用运算符。将计算结果,压入堆栈。
**(4)**使用逆波兰表示法(后缀法),例:“4+5”等价于“4 5 +”、“4+5-2”等价于“4 5 + 2 -
**(5)**实现4种运算”+ - * /“

设计(自顶向下)
(1)计算器对象为顶层对象。
(2)计算器使用堆栈保存了输入的数字,并对这些数字应用运算符。
(3)每次输入后,使用堆栈序列生成器,显示此时堆栈的内容。
(4)使用输入对象进行一些预处理(判别数字、运算符、非法输入),将用户输入的内容传递给计算器对象
(5)输入对象从标准输入获得一个字符串,区别是数字还是运算符。如果是数字,将字符串转为数字,交给计算器对象压入堆栈。如果是运算符,交给计算器对象,实现此运算。
(6)计算器对象对堆栈每次操作后,使用堆栈序列生成器,输入堆栈当前内容。

具体实现
main.cpp

#include<iostream>
#include"calc.h"
int main()
{
	//计算器对象
	Calculator TheCalculator;
	//迭代状态
	bool status;
	do
	{
		std::cout << "> ";
		//输入对象
		Input input;
		status = TheCalculator.Execute(input);
		if (status)
		{
			for (StackSeq seq(TheCalculator.GetStack());//堆栈序列对象
				!seq.AtEnd();
				seq.Advance())
			{
				//输入堆栈内容
				std::cout << " " << seq.GetNum() << std::endl;
			}
		}
	} while (status);
}

计算器类
calc.h

#ifndef CALC_H
#define CALC_H
#include<iostream>
#include<cassert>
#include"input.h"
#include"stack.h"
class Calculator
{
public:
    //int const 等价于 const int
	bool Execute(Input const & input);
	//堆栈常量的引用(只读)
	IStack const & GetStack()
	{
		return _stack;
	}
private:
	//堆栈(嵌入对象)
	IStack _stack;
	//计算函数
	int Calculate(int num1, int num2, int token)const;
};
#endif

calc.cpp

#include"calc.h"

bool Calculator::Execute(Input const &input)
{
	//获得input对象的输入
	int token = input.Token();
	//初始时假定失败
	bool status = false;

	//错误
	if (token == tokError)
	{
		std::cout << "Unknown token\n";
	}
	//输入为数字
	else if (token == tokNumber)
	{
		if (_stack.IsFull())
		{
			std::cout << "Stack is full";
		}
		else
		{
			_stack.Push(input.Number());
			status = true;
		}
	}
	//输入为运算符号
	else
	{
		//契约:input不能产生任何其他字符
		assert(token == '+' || token == '-' || token == '*'
			|| token == '/');
		//堆栈空
		if(_stack.IsEmpty())
		{
			std::cout << "Stack is empty" << std::endl;
		}
		else
		{
			int num2 = _stack.Pop();
			int num1;
			//当堆栈只有一个数
			if (_stack.IsEmpty())
			{
				num1 = num2;
			}
			else
			{
				num1 = _stack.Pop();
			}
			//结果Push堆栈
			_stack.Push(Calculate(num1, num2, token));
			status = true;
		}
	}
	return status;
}
int Calculator::Calculate(int num1, int num2, int token) const
{
	int result;
	if (token == '+')
		result = num1 + num2;
	else if (token == '-')
		result = num1 - num2;
	else if (token == '*')
		result = num1 * num2;
	else if (token == '/')
	{
		if (num2 == 0)
		{
			std::cout << "Division by zero" << std::endl;
			result = 0;
		}
		else
			result = num1/num2;
	}
	return result;
}

堆栈与堆栈序列生成器
stack.h

#ifndef STACK_H
#define STACK_H
#include<iostream>
#include<cassert>
const int maxStack = 16;
//堆栈类
class IStack
{
	friend class StackSeq;
public:
	IStack() :_top(0){}
	void Push(int i);
	int Pop();
	//堆栈满
	bool IsFull();
	//堆栈空
	bool IsEmpty();
private:
	//实际数据类型 整型数组
	int _arr[maxStack];
	int _top;
};
//堆栈序列生成器类
class StackSeq
{
public:
	StackSeq(IStack const & stack) :_stack(stack), _iCur(0){}
	//是否到达堆栈尾端
	bool AtEnd();
	//堆栈当前索引内容
	int GetNum();
	//下一个索引
	void Advance();
private:
	//堆栈常量的引用
	IStack const & _stack;
	int _iCur;
};

#endif

stack.cpp

#include"stack.h"


void IStack::Push(int i)
{
	assert(_top < maxStack);
	_arr[_top] = i;
	_top++;
}
int IStack::Pop()
{
	assert(_top>0);
	--_top;
	return _arr[_top];
}
bool IStack::IsFull()
{
	if (_top < maxStack)
	{
		return false;
	}
	else
	{
		return true;
	}
}
bool IStack::IsEmpty()
{
	if (_top > 0)
	{
		return false;
	}
	else
	{
		return true;
	}
}
bool StackSeq::AtEnd()  
{
	return  _iCur==_stack._top;
}
void StackSeq::Advance()
{
	assert(!AtEnd());
	++_iCur;
}
int StackSeq::GetNum() 
{
	assert(!AtEnd());
	return _stack._arr[_iCur];
}

输入类
input.h

#ifndef INPUT_H
#define INPUT_H
#include<iostream>
#include<cctype>
#include<cassert>
#include<cstdlib>
const int maxBuf = 100;
const int tokNumber = 1;
const int tokError = 2;

class Input
{
public:
	Input();
	//将输入返回给计算器对象
	int Token()const{ return _token; }
	//字符串转数字
	int Number()const;
private:
	int _token;
	char _buf[maxBuf];
};
#endif


input.cpp


#include"input.h"

Input::Input()
{
	std::cin >> _buf;
	int c = _buf[0];
	if (std::isdigit(c))
		_token = tokNumber;
	else if (c == '+' || c == '*' || c == '/')
		_token = c;
	//允许输入负数
	else if (c == '-')
	{
		if (std::isdigit(_buf[1]))
			_token = tokNumber;
		else
			_token = c;
	}
	else
		_token = tokError;
}
int Input::Number()const
{
	assert(_token == tokNumber);
	return std::atoi(_buf);
}

运行效果
这里写图片描述

相关系列

小型计算器A small software project

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林多

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值