计算器程序设计实战

计算器程序设计实战


程序功能说明:

用到的头文件和main.cpp函数见上一篇博客:
头文件和main.cpp的传送门

  • 正确输入一个“+”,“-”,“*”,“/”,“%”混合运算式会进行运算,并且输出正确的结果
  • 输入的运算表达式可以支持带括号“(” “)”
  • 输入的运算表达式支持负数运算
  • 如果输入的表达式不规范会报相应的错误,比如“primary expected”、“bad token”。
  • 如·果每一个运算表达式都正确输入的话,可以继续输入表达式计算。
  • 正确输入表达式计算后,如果要退出程序,可以输入“q”退出,输入错误表达式报错误之后,可以输入“hpb”退出。

程序思路说明

实现这个计算器计算的功能,大概需要以下几步:
计算器程序设计实战_第1张图片

下面就逐个介绍各个模块:

  1. Token的实现:
    定义Token的目的主要是用于保存运算符的类别以及数值,比如符号“+”,数字20等的保存。根据上述,那么Token可以用一个类来实现:
class Token{
	public:
 	   char kind;
 	   double value;
           Token(char ch)
             :kind(ch), value(0){}
           Token(char ch, double val)
             :kind(ch), value(val){}
            };

在使用Token变量时,只需在程序中把读入的字符存到Token变量中。

  1. 文法的实现
    有了Token可以进行存储用户输入的表达式,但是此时需要解析表达式的含义,比如加减乘除的含义、运算优先级等。所以此时我们就需要定义一个文法,来规定这些含义以及运算规则。
    在这个程序中总共有三个函数来处理文法:expression()、term()、primary()。它们实现的伪代码如下:
Expression:
	Term
	Expression "+" Term
	Expression "-" Term

Term:
	Primary
	Term "*" Primary
	Term "/" Primary
	Term "%" Primary
Primary:
	Number
	"("Expression")"	

跟据伪代码可以看出来,我们实现的程序中,expression()函数主要处理“+”和“-”号;term()函数主要处理乘、除、取余;primary()函数主要处理括号和数字。

当然我们可以增加计算器计算的范围,比如我们可以计算乘方,这时候只需要在对应文法规则里面加入乘方符号“^”,实现规则即可。

  1. 单词流的实现
    计算器程序的输入是一个单词序列,我们需要从标准输入cin中读入字符,并且能够向程序提供运行时需要的下一个单词。此时用一个“流”比较方便,当我们需要一个单词时,可以调用get()函数从流中产生一个单词,并且可以利用putback()函数把单词放回流中。所以这里我们可以定义一个Token_stream类型。
class Token_stream{
	public:
	   Token_stream();
	   Token get();
 	   void putback(Token t);
	private:
   	   bool full;
	   Token buffer;
	};

4.错误/异常处理
对于错误,有输入的计算式错误、或者运算规则错误(比如0不能做除数等),我们只需要在可能出错的地方抛出错误,然后再进行捕捉程序即可。捕捉错误的主要代码如下:

catch (runtime_error& e){
  	cerr << e.what() << endl;
  	keep_window_open("hpb");
  	return 1;
 }
catch (...){
  	cerr << "exception\n";
  	keep_window_open();
  	return 2;
 }

5.主函数
主函数调用相关模块,然后打印输出、如有错误捕捉错误即可。代码如下:

int main(){
 	try{
 	   while (cin){
   		cout << ">";
   		Token t = ts.get();
   		while (t.kind == ';')t = ts.get();//eat ;
   			if (t.kind == 'q'){
    				keep_window_open();
    				return 0;
   			}
    		ts.putback(t);
    		cout << "=" << expression() << endl;
  	}
  	keep_window_open();
  	return 0;
}
 	catch (runtime_error& e){
 		cerr << e.what() << endl;
  		keep_window_open("hpb");
  		return 1;
 	}
 	catch (...){
  		cerr << "exception\n";
  		keep_window_open();
  		return 2;
 	}
}
  1. 整个程序的结构
#include “std_lib_facilities.h”

class Token{/*…*/};
class Token_stream{/*…*/};

Token_stream::Token_stream():full(false),buffer(0){/*…*/};
void Token_stream::putback(Token t) {/*…*/};
Token Token_stream::get(){/*…*/};

double primary(){/*…*/};
double term(){/*…*/};
double expression(){/*…*/};

int main(){/*…*/};

运行结果计算器程序设计实战_第2张图片

总结

计算器程序还可以通过其他方式实现,比如可以用数据结构里面的中缀表达式。

你可能感兴趣的:(C++,c++,计算机科学,计算器,程序设计)