📄 exp19_1.cpp
字号:
/*为模拟简单计算器程序添加异常处理(参见教材【例7.7】)。包括被零除、整型数溢出和输入非法字符。
[提示]首先定义四种异常,尽管没有数据域,为通用还是定义为模板。被零除、整型数溢出两个异常在
Calculator::Compute()函数中抛出。将Calculator::Cal()中的读入开关语句定义为try块,输入非法字
符异常放开关语句中,栈空在栈模板中。四个catch子句排在try块外,子句中包括清栈命令。
*/
//测试用:6/0=;65535*65535=;4+6*3+k=;6+6+=;
#include<iostream.h>
#include<math.h>
#include<stdlib.h>
#include<limits.h>
#include"Exp19_1.h" //链栈模板定义文件
template<typename T>class divided_by_zero{
public:
divided_by_zero(){}
void print(){cerr<<"因被零除,发生算术溢出,跳过"<<endl;}
};
template<typename T>class intoverflow{
public:
intoverflow(){}
void print(){cerr<<"因整型数溢出,跳过"<<endl;}
};
template<typename T>class invalid_letter{
public:
invalid_letter(){}
void print(){cerr<<"因输入非法字母,跳过"<<endl;}
};
class Calculator{ //简易计算器类
Stack<int> Nstack;
Stack<char> Ostack;
public:
Calculator(void){};
void Cal(void); //计算器运算程序
void GetTwoNum(int &Num1,int &Num2);
void Compute(char Opr);
void Clear(void);
};
void Calculator::Clear(){
Nstack.MakeEmpty();
Ostack.MakeEmpty();
}
void Calculator::GetTwoNum(int &Num1,int &Num2){
Num1=Nstack.Pop();
Num2=Nstack.Pop();
}
void Calculator::Compute(char Opr){
int Num1,Num2;
double a;
if(Opr!='=') GetTwoNum(Num1,Num2);
switch(Opr){
case '+':a=double(Num2)+double(Num1);
if(a<INT_MAX&&a>INT_MIN) Nstack.Push(Num2+Num1);//结果压栈
else throw intoverflow<int>();
break;
case '-':a=double(Num2)-double(Num1);
if(a<INT_MAX&&a>INT_MIN) Nstack.Push(Num2-Num1);//结果压栈
else throw intoverflow<int>();
break;
case '*':a=double(Num2)*double(Num1);
if(a<INT_MAX&&a>INT_MIN) Nstack.Push(Num2*Num1);//结果压栈
else throw intoverflow<int>();
break;
case '/':if(Num1!=0) Nstack.Push(Num2/Num1);
else throw divided_by_zero<int>();
break;
case '=':cout<<Nstack.Pop()<<endl; //输出结果
}
}
void Calculator::Cal(){
bool b1=true,b2=true;
char ch1,ch2,str[50];
int k=-1;
while(b2){
cin>>ch1;
if(ch1>='0'&&ch1<='9'){
k++;
str[k]=ch1; //数字字符添入串中
}
else{
if(k>=0){
str[k+1]='\0'; //数字串生成
Nstack.Push(atoi(str)); //数字串转换为整数后压栈
k=-1;
}
try{//try块的位置很重要,否则会出错
switch(ch1){
case 'c':
Clear();
break;
case '+':
case '-':
while(!Ostack.IsEmpty()){
ch2=Ostack.Pop(); //不会有比'+' '-'优先级低的
Compute(ch2);
}
Ostack.Push(ch1);
break;
case '*':
case '/':
while(!Ostack.IsEmpty()&&b1){
ch2=Ostack.Pop(); //把栈顶运算符弹出
if(ch2=='*'||ch2=='/') //比较优先级
Compute(ch2); //新的优先级并不高
else{ //新的优先级高
Ostack.Push(ch2); //先把原栈中的运算符压回去
b1=false;
}
}
Ostack.Push(ch1); //再把新的运算符压栈
b1=true; //此句保证乘除从左倒右进行
break;
case '=':
while(!Ostack.IsEmpty()){
ch2=Ostack.Pop();
Compute(ch2);
}
Compute(ch1);
break;
case 'z':
b2=false;
break;
default:throw invalid_letter<int>();
}
}
catch(divided_by_zero<int> &eObj){Clear();eObj.print();}
catch(intoverflow<int> &eObj){Clear();eObj.print();}
catch(invalid_letter<int> &eObj){Clear();eObj.print();}
catch(stack_is_empty<int> &eObj){Clear();eObj.print();}
}
}
}
void main(){
Calculator Calcul;
Calcul.Cal();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -