实现《C++程序设计语言(特别版)》第6章 表达式和语句 - 桌面计算器 - Linux

来源:互联网 发布:高级安全windows防火墙 编辑:程序博客网 时间:2024/06/05 05:52

这个实现只是一个思路,需要容错和优化。表达式语法分析如下:

 *****************
 * program:
 *     END
 *     expr_list END
 * expr_list:
 *     expression PRINT     // PRINT is ;
 *     expression PRINT expr_list
 * expression:
 *     expression + term
 *     expression - term
 *     term
 * term:
 *     term / primary
 *     term * primary
 *     primary
 * primary:
 *     NUMBER
 *     NAME    // this is variable
 *     NAME = expression
 *     - primary
 *     ( expression )
 *****************

文件列表:

  • calc.cc
  • calc.h
  • main.cc
  • makefile
源码下载连接:http://download.csdn.net/detail/wxqee/4397788

用法:
xiwang@ubuntu:~/Dev/calc$ makeg++ -Wall -I. -D_DEBUG -c calc.cc -o calc.cc.og++ -Wall -I. -D_DEBUG -c main.cc -o main.cc.og++ -D_DEBUG -L. calc.cc.o main.cc.o -o calc -lpthreadxiwang@ubuntu:~/Dev/calc$ ./calcr = 2.5;2.5      //<输出>area = pi * r * r;19.635   //<输出>^C

所有代码》》》》

文件:calc.cc
// calc.cc#include "calc.h"#include <ctype.h>#include <iostream>#include <map>#include <string>using namespace std;// error functionint no_of_errors;double error(const string& s){    no_of_errors++;    cerr << "error: " << s << '\n';    return 1;}// END error functionToken_value curr_tok = PRINT;double expr(bool get){    double left = term(get);    for (;;)    {        switch (curr_tok) {            case PLUS:                left += term(true);                break;            case MINUS:                left -= term(true);                break;            default:                return left;        }    }}double term(bool get){    double left = prim(get);    for (;;)    {        switch (curr_tok) {            case MUL:                left *= prim(true);                break;            case DIV:                if (double d = prim(true)) {                    left /= d;                    break;                }                return error("divide by 0");            default:                return left;        }    }}double number_value;string string_value;map<string, double> table;   // var tabledouble 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) return error(") expected");            get_token();            return e;        }        default:            return error("primary expected");    }}// --BEGIN-- OPTIMIZE get_token function// Token_value get_token()// {//     char ch = 0;//     cin >> ch;////     switch (ch) {//         case 0://             return curr_tok = END;   // assign and return//         case ';'://         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;//     }// }Token_value get_token(){    char ch = 0;    // --BEGIN-- ignore blanks except '\n'    // do {    //     if (!cin.get(ch)) return curr_tok = END;    // } while (ch != '\n' && isspace(ch));    cin >> ch;    // ---END--- ignore blanks except '\n'    switch (ch) {        case 0:            return curr_tok = END;   // assign and return        case ';':        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)) {                // --BEGIN-- Optimize to avoid meeting blank issue                // cin.putback(ch);                // cin >> string_value;                string_value = ch;                while (cin.get(ch) && isalnum(ch)) string_value.push_back(ch);                cin.putback(ch);                // ---END_-- Optimize to avoid meeting blank issue                return curr_tok = NAME;            }            error("bad token");            return curr_tok = PRINT;    }}// ---END--- OPTIMIZE get_token function

文件:calc.h
/** * calc.h ***************** * program: *     END *     expr_list END * expr_list: *     expression PRINT     // PRINT is ; *     expression PRINT expr_list * expression: *     expression + term *     expression - term *     term * term: *     term / primary *     term * primary *     primary * primary: *     NUMBER *     NAME    // this is variable *     NAME = expression *     - primary *     ( expression ) */#ifndef CALC_H_#define CALC_H_#include <map>#include <string>using namespace std;enum Token_value {    NAME,       NUMBER,       END,    PLUS='+',   MINUS='-',    MUL='*',      DIV='/',    PRINT=';',  ASSIGN='=',   LP='(',       RP=')'};// for DRIVER PROGRAMextern Token_value curr_tok;extern map<string, double> table;   // var tableextern int no_of_errors;extern double expr(bool get);extern Token_value get_token();extern double error(const string& s);// END for DRIVER PROGRAMextern double term(bool get);extern double prim(bool get);#endif

文件:main.cc  (驱动程序)
/** * main.cc * * EAMPLE *     ./calc 'rate=1.1934;150/rate;19.75/rate;217/rate' */#include <iostream>#include <sstream>#include "calc.h"using namespace std;// --BEGIN-- COMMENT SIMPLE DRIVER// // DRIVER PROGRAM// int main(int argc, char **argv) {//   table["pi"] = 3.1415926535897932385;  // PRE-DEFINED NAMES//   table["e"]  = 2.7182818284590452354;////   while (cin) {//       get_token();//       if (curr_tok == END) break;//       if (curr_tok == PRINT) continue;//       cout << expr(false) << endl;//   }////   return no_of_errors;// }// ---END--- COMMENT SIMPLE DRIVERistream* input;int main(int argc, char * argv[]){    switch (argc) {        case 1:            input = &cin;            break;        case 2:            input = new istringstream(argv[1]);            break;        default:            error("too many arguments");            return 1;    }    table["pi"] = 3.1415926535897932385;  // PRE-DEFINED NAMES    table["e"]  = 2.7182818284590452354;    while (*input) {        get_token();        if (curr_tok == END) break;        if (curr_tok == PRINT) continue;        cout << expr(false) << '\n';    }    if (input != &cin) delete input;    return no_of_errors;}

文件:makefile
# Makefile, 2012-06-23 T1110# TODO# ----------------------------------NAME        = calcVERSION     = 1.0.0RELEASE     = 01# ----------------------------------BIN         = $(NAME)OBJS        = $(patsubst %.cpp,%.cpp.o,$(wildcard $(SRC_DIR)/*.cpp))OBJS       += $(patsubst %.cc,%.cc.o,$(wildcard $(SRC_DIR)/*.cc))OBJS       += $(patsubst %.C,%.C.o,$(wildcard $(SRC_DIR)/*.C))# TODO# BEGIN ----------------------------------# FoldersSRC_DIR     = .# FlagsCXXFLAGS    = -WallCXXFLAGS   += -I$(SRC_DIR)CPPFLAGS    = -D_DEBUGLDFLAGS     = -L$(SRC_DIR)LIBS        = -lpthread# END ----------------------------------.PHONY: all cleanall: $(BIN)$(BIN): $(OBJS)$(CXX) $(CPPFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS)# source files%.cpp.o: %.cpp$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $^ -o $@%.cc.o: %.cc$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $^ -o $@%.C.o: %.C$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $^ -o $@clean:$(RM) $(BIN) $(OBJS)



原创粉丝点击