C++ 计算器Calculator类实现

来源:互联网 发布:没谈过恋爱的女生知乎 编辑:程序博客网 时间:2024/05/22 12:15

首先祝贺我会插入源代码了。。汗。。原来都不知道还有这个功能。。尴尬

然后是我今天实现的Calculator类。。分享一下,基于C++程序设计语言第六章的计算器程序。计算器使用“递归下降”的算法(一种流行的直截了当的自顶向下技术),按照表达式-》子表达式-》项 这一顺序递归向下求值。然后首先项会返回这个项的类型,为数字、符号、变量等(枚举Token_value描述项的类型),接着将项向上返回给字表达式求值,最后字表达式的求值结果被用于整个表达式的最终结果求值中。除了核心算法的实现,我还添加了一个输入流指针istream*和输入和输出函数,使计算器可以分别从cin、命令行参数或程序里的字符串输入,以及输出到文件中。这里,字符串和命参数将被保存至一个istringstream流,该类是istream的派生类,将用输入流指针指向这个字符串输入流,读取输入。添加了一个异常类error,继承自标准库logic_error类(其实就是用logic_error实现的),以抛出计算过程中的逻辑错误。至此,这个计算器类已经相当完整了。

Calculator.h

#ifndef CALCULATOR_H#define CALCULATOR_H#include <iostream>#include <sstream>#include <string>#include <cctype>#include <map>#include <stdexcept>class Calculator{public:class error:public std::logic_error{public:    error(const std::string& s):    std::logic_error(s){}};enum Token_value{NUMBER,NAME,END,PLUS='+',MINUS='-',MUL='*',DIV='/',PRINT=';',ASSIGN='=',LP='(',RP=')'};    Calculator(const std::string& s):    input(new std::istringstream(s)),curr_tok(PRINT){    table["pi"]=3.1415926;    table["e"]=2.718218;}    Calculator(std::istream& is):input(&is),curr_tok(PRINT)    {    table["pi"]=3.1415926;    table["e"]=2.718218;}    void output(std::ostream&);private:    double expr(bool);    double term(bool);    double prim(bool);    Token_value get_token();    std::istream* input;std::map<std::string,double> table;Token_value curr_tok;double number_value;std::string string_value;};void Calculator::output(std::ostream& os){while(*input){get_token();if(curr_tok==END) break;if(curr_tok==PRINT) continue;os<<expr(false)<<std::endl;}}double Calculator::expr(bool get){double left=term(get);while(true)    switch(curr_tok){    case PLUS:        left+=term(true);        break;        case MINUS:            left-=term(true);            break;        default:            return left;    }}double Calculator::term(bool get){double left=prim(get);while(true)    switch(curr_tok){    case MUL:        left*=prim(true);        break;        case DIV:            if(double d=prim(true)){                left/=d;                break;            }            throw error("divide by 0");        default:            return left;    }}double Calculator::prim(bool get){if(get) get_token();switch(curr_tok){case NUMBER:{    double v=number_value;    get_token();    return v;}    case NAME:{        double &v=table[string_value];        if(get_token()==ASSIGN) v=expr(true);        return v;    }    case MINUS:        return -prim(true);    case LP:        double e=expr(true);        if(curr_tok!=RP) throw error(") expected");        get_token();//吃掉 )return e;default:    throw error("primary expected");}}Calculator::Token_value Calculator::get_token(){char ch;do{if(!input->get(ch)) return curr_tok=END;}while(ch!='\n'&&isspace(ch));switch(ch){case ';':case '\n':    return curr_tok=PRINT;    case '*':    case '/':    case '+':    case '-':    case '(':    case ')':    case '=':        return curr_tok=Token_value(ch);    case '0':case '1':case '2':case '3':case '4':    case '5':case '6':case '7':case '8':case '9':    case '.':        input->putback(ch);        input->operator>>(number_value);        return curr_tok=NUMBER;    default:        if(isalpha(ch)){        string_value=ch;        while(input->get(ch)&&isalnum(ch))            string_value.push_back(ch);        input->putback(ch);        return curr_tok=NAME;        }        curr_tok=PRINT;        throw error("bad token");}}#endif

main.cpp

//10.16 定义Calculator类#include <iostream>#include <fstream>#include "Calculator.h"int main(int argc,char* argv[]){Calculator calc(std::cin);try{calc.output(std::cout);}catch(Calculator::error e){std::cout<<e.what()<<std::endl;return -1;}    return 0;}


原创粉丝点击