c++之父写的简单计算器程序,(看看大师的功力吧) (1/113)

< 上一篇下一篇 >
本帖地址: 复制地址

修改 回帖 引用 楼主: 小邪

用户形象图片

这是 《the c++ programming language》 第六章函数的一个例子。
例子中没有高深的算法,都是c++中最常用的语法现象
但是这150行程序里蕴含的功力极深,(至少我达不到这种水平,程序的效率,存储开销等方面做的都非常出色,甚至是天衣无缝)
今日贴出 请大家一同欣赏。
(作者在程序中因为简化程序而改写了一些更好的方法,正如作者在序言中所说,要有一种健康的怀疑态度,我之所以说它完美,并不是指我们编不出比它好的程序,而是指它清晰的结构,合理的设计,以及蕴含在这里面的编程艺术
回到帖子顶部

回帖 引用 1楼[楼主] 小邪

用户形象图片

//////////////////////////////////////////////////////////////
//以下是 c++之父写的一个简单计算器程序 包括分析器,输入,符号表,驱动程序
//计算器的输入语法:
// 1)以 ";" 号作为一行的结束
// 2)可用英文单词命名变量 (但变量后要有空格)
// 例子如下:
// 输入: r =2.5; (注意空格)
// 输出: 2.5 (记负值结果)
// 输入: area = r * r * pi ;
// 输出: 19.635
//
// 以下代码为标准c++代码,我在vc++2003.net上运行无误

#include <iostream>
#include <string>
#include <map>
#include <cctype>
using namespace std;
const ture=1;
const flase=0;

map<string,double> table;


///////////////////////////////////////////////////////////////
//计算器输入允许的词法
enum Token_value{
    NAME, NUMBER, END,
    PLUS='+', MINUS='-', MUL='*', DIV='/',
    PRINT=';', ASSIGN='=', LP='(', RP=')',
};

///////////////////////////////////////////////////////////////
//分析器 加和减
double expr(bool);

///////////////////////////////////////////////////////////////
//分析器 乘和除
double term(bool);

///////////////////////////////////////////////////////////////
//分析器 处理初等项
double prim(bool);

///////////////////////////////////////////////////////////////
//词法分析器
Token_value get_token();

///////////////////////////////////////////////////////////////
//错误处理
double error(const string &s);

///////////////////////////////////////////////////////////////
//当前词法标记
Token_value curr_tok=PRINT;

double number_value;  //存放数值
string string_value; //存放计算器变量名
int no_of_errors; //记录错误个数


double expr(bool get) {
    double left=term( get);

    for( ; ; )
        switch(curr_tok) {
        case PLUS:
            left+=term(ture);
            break;
        case MINUS:
            left-=term(ture);
            break;
        default:
            return left;
        }
}

double term(bool get) {
    double left=prim(get);

    for( ; ; )
        switch(curr_tok) {
        case MUL:
            left*=prim(ture);
            break;
        case DIV:
            if(double d=prim(ture)) {
                left/=d;
                break;
            }
return error("divide by 0");
        default:
            return left;
        }
}


double 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(ture);
            return v;
        }
    case MINUS:
        return -prim(ture);
    case LP: {
            double e=expr(ture);
            if(curr_tok!=RP)
                return error(") expected");
            get_token();
            return e;
        }
    default:
        return error("primary expected");
    }
}

Token_value get_token() {
    char ch=0;
    cin>>ch;

    switch(ch) {
    case 0:
        return curr_tok=END;
    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 '.':
        cin.putback(ch);
        cin>>number_value;
        return curr_tok=NUMBER;
    default:
        if(isalpha(ch)) {
            cin.putback(ch);
            cin>>string_value;
            return curr_tok=NAME;
        }
        error("bad token");
        return curr_tok=PRINT;
    }
}

double error(const string& s) {
    no_of_errors++;
    cerr<<"error: "<<s<<endl;
    return 1;
}

int main() {
    table["pi"]=3.1415926;
    table["e"]=2.718281828;

    while(cin) {
        get_token();
        if(curr_tok==END)
            break;
        if(curr_tok==PRINT)
            continue;
        cout<<expr(false)<<endl;
    }
    return no_of_errors;
}</CC>
回到帖子顶部
个人信息
  • 荣誉+3
  • 荣誉+2
  • 荣誉+1
  • 荣誉-1
  • 荣誉-2
  • 荣誉-3
发表留言
  • 文章不错!
  • 精华好文!
  • 支持原创文章!
  • 帖子图文并茂,好!
  • 真知灼见,说得好!
  • 恶意广告
  • 违规内容
  • 严重灌水
  • 重复发帖
  • 标题党
你确定要删除此楼层吗
扣20点经验值

快速回复进入高级回复

插入图片 选择表情

验证码 看不清?换一张(不区分大小写)

[完成后按Ctrl+Enter发表]
[回复须知]