本例来自课本《c++语言程序设计(第4版)》第9章第9-9的案例
本例实现一个简单的整数计算器,能够进行加、减、乘、除和乘方运算。使用时算式采用后缀输入法,每个操作数、操作符之间都以空白符分隔。例如,若要计算“3+5”则输入“3 5 +”。乘方运算符用“^”表示。每次运算在前次结果基础上进行,若要将前次运算结果清除,可输入“c”。当输入“q”时程序结束
分析
本题实际上是要实现简单的表达式处理功能,可以用栈来处理表达式。对于比较复杂的表达式例如(1+5)/2-3,需要建立两个栈:操作数栈和操作符栈。但是本题的问题比较简单,每次输入的表达式只有一个操作符,因此没有操作优先级问题,也不需要操作符栈,可以只设一个操作数栈,
程序的主要思路
每当遇到操作数时,便入栈;遇到操作符时,便连续弹出两个操作数并执行运算,然后将运算结果压入栈顶。输入“c”时,清空操作数栈;输入“q”时,清空操作数栈并结束程序。
类设计的要点
建立一个计算器类,内嵌一个栈类操作对象作为操作数栈。成员函数应该包括:将操作数压入栈、连续弹出两个操作数、执行运算、对表达式的输入及计算过程的控制、清空操作数栈。
代码TIPS
tip1: 字符串输入 cin
对于cin而言,其输入结束条件为遇到enter、空格或tab键
例:
include<iostream>
include<string>
using namespace std;
int main(){
string str;
cin>>str; //输入 10 20 30
cout<<str<<endl;//输出为10
return 0;
}
代码
代码包含三个文件“Calculator.h”、“Calculator.cbp”以及“main.cbp”,是使用codeblocks软件编写的c++语言的程序,对例9-9做了微调。
- 头文件 Calculator.h
#ifndef CALCULATOR_H
#define CALCULATOR_H
#include<iostream>
#include<stack>
#include<cmath>
#include<sstream>
#include<string>
using namespace std;
class Calculator //计算器类
{
public:
void run(); //运行计算器程序
void clear(); //清空操作数栈
protected:
private:
stack<double> s; //操作数栈
void enter(double num); //将操作数num压入栈
// 连续将两个操作数弹出栈,放在opnd1和opnd2中
bool getTwoOperands(double &opnd1,double &opnd2);
void compute(char op);// 执行由操作符op指定的运算
};
#endif // CALCULATOR_H
- 头文件实现文件 Calculator.cbp
#include "Calculator.h"
using namespace std;
void Calculator::enter(double num){ //将操作数num压入栈
s.push(num);
}
//连续将两个操作数弹出栈,放在opnd1和opnd2中,
//如果栈中没有两个操作数,则返回false并输出相关信息
bool Calculator::getTwoOperands(double &opnd1,double &opnd2){
if(s.empty()){ //检查栈是否为空
cerr<<"Missing operand!"<<endl;
return false;
}
opnd1 = s.top(); //将右操作数弹出栈
s.pop();
if(s.empty()){ //检查栈是否为空
cerr<<"Missing operand!"<<endl;
return false;
}
opnd2 = s.top();
s.pop();
return true;
}
void Calculator::compute(char op){ //执行运算
double operand1,operand2;
bool result = getTwoOperands(operand1,operand2); //将两个操作数弹出栈
if(result){ //如果成功,执行运算并将运算结果压入栈
switch(op){
case '+':
s.push(operand1+operand2);
break;
case '-':
s.push(operand2-operand1);
break;
case '*':
s.push(operand2*operand1);
break;
case '/':
if(operand1==0){ //检查除数是否为0
cerr<<"Divided by 0!"<<endl;
while(!s.empty()) //除数为0时清空栈
s.pop();
}else{
s.push(operand2/operand1);
}
break;
case '^':
s.push(pow(operand2,operand1));
break;
default:
cerr<<"Unrecognized operator!"<<endl;
break;
}
cout<<" = "<<s.top()<<endl; //输出本次运算结果
}else{ //操作数不够,清空栈
while(!s.empty())
s.pop();
}
}
//工具函数,用于字符串转换为实数
inline double stringToDouble(const string &str){
istringstream stream(str); //字符串输入流
double result;
stream>>result;
return result;
}
void Calculator::run(){ //读入并处理后缀表达式
string str;
while(cin>>str,str!="q"){ //cin 遇enter,space或tab键输入结束
switch(str[0]){ //操作符
case 'c':
while(!s.empty())
s.pop();
break;
case '-': // 遇“-”需判断是减号还是负号
if(str.length()>1) //如果字符串长度大于1,是负号
{
enter(stringToDouble(str));
}else
{
compute(str[0]);
}
break;
case '+':
case '*':
case '/':
case '^':
compute(str[0]);
break;
default: //若读入的是操作数,转换为整型后压入栈
enter(stringToDouble(str));
break;
}
}
}
void Calculator::clear(){ //清空操作数栈
while(!s.empty())
s.pop();
}
- 主文件 main.cbp
#include <iostream>
#include"Calculator.h"
using namespace std;
/*
栈的应用----一个简单的整数计算器
本利实现一个简单的整数计算器,能够进行加、减、乘除运算。使用时算式采用
后缀输入法,每个操作数、运算符之间都以空白符分隔。例如,若要计算“3+5”
则输入“3 5 +”。乘法运算符用^表示。每次运算在前次结果基础上进行,若要将
前次运算结果清除,可输入‘c’,当输入“q”时,程序结束。
*/
int main()
{
Calculator c;
c.run();
return 0;
}