基于堆栈的计算器
2016-12-21 10:39
344 查看
简单的基于堆栈的计算器
(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
计算器类
calc.h
calc.cpp
堆栈与堆栈序列生成器
stack.h
stack.cpp
输入类
input.h
input.cpp
运行效果
(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); }
运行效果
相关文章推荐
- PHP栈的定义、入栈出栈方法及基于堆栈实现的计算器完整实例
- 使用递归下降算法分析数学表达式 -- 基于堆栈的计算器实现算法
- PHP基于堆栈实现的高级计算器功能示例
- 基于堆栈的计算器代码
- 基于堆栈的计算器实现算法
- 基于堆栈的计算器实现算法
- QT 基于QMainWindow的堆栈窗体设计
- 基于ARM的硬件启动程序设计-初始化堆栈
- JS基于递归实现网页版计算器的方法分析
- 基于at89s52和lcd1602的可以进行混合运算的计算器程序
- 基于java.util.logging实现轻量级日志记录库(增加根据当前类class初始化,修复线程池模型(javaEE)下的堆栈轨迹顺序与当前调用方法不一致问题)
- 基于JavaScript的网页版【定期存款计算器 - DepositCaculator v1.0】
- 基于数组或链表的堆栈实现
- 基于android平台开发的计算器
- 基于线性表的堆栈
- 基于对话框的计算器(加减乘除)
- 基于VS2010平台的MFC入门编程——简易加法计算器
- PHP基于数组实现的堆栈和队列功能示例
- 基于JavaScript的网页版【定期存款计算器 - DepositCaculator v1.0】
- 基于js白色简洁样式计算器