精华内容
下载资源
问答
  • c++桌面计算器
    千次阅读
    2014-05-22 16:24:25

    思路:输入一个字符串,首先找到等号将其分为左右两部分,左部分为变量,右部分为运算式,分别处理。

               对于左边部分,直接记录下来变量名最后输出即可。

               右边部分,是一个算术表达式。首先将其由中缀表达式变为后缀表达式,然后对后缀表达式求值即可。在求值过程中会有一些变量,我们利用map保存变量名对应的值即可。

    参考资料:解析算术表达式[1]后缀式(逆波兰式)   http://blueve.me/archives/318

                      调度场算法(中缀变后缀)  http://zh.wikipedia.org/wiki/Shunting_yard%E7%AE%97%E6%B3%95

                      map的有关用法

    存在问题:1.不能处理浮点数

                      2.不能处理负数

    附上源码:

    #include<iostream>
    #include<string>
    #include<map>
    #include<cstdio>
    using namespace std;
    
    bool compare(char a,char b)//比较a与b的优先级
    {
        int preference[100];
        preference['+'] = 1;
        preference['-'] = 1;
        preference['*'] = 2;
        preference['/'] = 2;
        preference['('] = 3;
        if(preference[a] > preference[b])
            return true;
        return false;
    }
    
    int operation(int x,int y,char z)
    {
        switch(z)
            {
                case '+':
                    return x+y;
                case '-':
                    return x-y;
                case '*':
                    return x*y;
                case '/':
                    return x/y;
            }
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        int i,j,k;
        map <char,int>my_map;
        string whole_string;
        while(cin >> whole_string)
        {
            int split;
            for(i=0;i<whole_string.size();i++)
                if(whole_string[i] == '=')
                {
                    split = i;
                    break;
                }
            //从split+1到最后都为算术表达式
    
            int length = whole_string.size()-split-1;//length即为之后算式的长度
    
            bool ok=true;//判断是否仅为赋值语句
            for(i=2;i<=2+length-1;i++)
                if(whole_string[i]<'0'||whole_string[i]>'9')
                    ok = false;
    
            if(ok)//仅为赋值语句直接赋值即可
            {
                int tem_number = 0;
                for(i=2;i<=2+length-1;i++)
                    tem_number = tem_number*10 + whole_string[i] - '0';
                my_map[whole_string[0]] = tem_number;
            }
            else//将中值式变为后缀式
            {
                int top_output=0,top_sign=0;//两个栈顶指针(数组模拟栈)
                char output[1000][1000];
                char sign[1000];
                char str[1000];
                for(i=0;i<length;i++)
                    str[i] = whole_string[split+1+i];//将整个运算式复制到str中
                //cout << str << endl;
                for(i=0;i<length;i++)
                {
                    if(str[i]>='0'&&str[i]<='9')//是数字压入输出栈
                    {
                        for(j=i+1;j<length;j++)
                            if(str[j]<'0'||str[j]>'9')
                                break;
                        for(k=0;k<j-i;k++)
                            output[top_output][k] = str[i+k];
                        output[top_output++][k] = '\0';
                        i = j-1;
                    }
                    else if((str[i]>='a'&&str[i]<='z')||str[i]>='A'&&str[i]<='Z')//是字母将其对应的数字压入栈
                    {
                        char tem_char[1000];
                        int tem_count = 0;
                        int tem_number = my_map[str[i]];
                        //cout << "tem:" << tem_number << endl;
                        while(tem_number)//将数字转成char存入output栈
                        {
                            tem_char[tem_count++] = tem_number%10 + '0';
                            tem_number/=10;
                        }
                        for(j=0;j<tem_count;j++)
                        {
                            output[top_output][j] = tem_char[tem_count-j-1];
                        }
    
                        output[top_output++][j] = '\0';
    
                    }
                    else               //字符对其进行操作
                    {
                        if(top_output==0)
                            sign[top_sign++] = str[i];
                        else
                        {
                            if(str[i] == ')')//当为右括号将符号弹入输出栈直至左括号
                            {
    
                                while(sign[top_sign-1]!='(')
                                {
                                    output[top_output][0] = sign[top_sign-1];
                                    output[top_output++][1] = '\0';
                                    top_sign--;
                                }
                                top_sign--;
                            }
                            else
                            {
                                if(top_sign==0)
                                    sign[top_sign++] = str[i];
                                else
                                {
                                    //读入符号优先级大于栈顶元素优先级将其压入符号栈
                                    if(compare(str[i],sign[top_sign-1])||sign[top_sign-1]=='(')
                                        sign[top_sign++] = str[i];
                                    //若读入符号优先级小于栈顶元素则将栈顶元素弹出到输出栈并将符号压入符号栈
                                    else
                                    {
                                        output[top_output][0] = sign[top_sign-1];
                                        output[top_output++][1] = '\0';
                                        top_sign--;
                                        sign[top_sign++] = str[i];
                                    }
                                }
                            }
                        }
                    }
                }
    
                while(top_sign)//符号栈不为空
                {
                    output[top_output][0] = sign[top_sign-1];
                    output[top_output++][1] = '\0';
                    top_sign--;
                }
    
                //开始对后缀表达式求值(栈)
                int top_ans=0;
                int ans[1000];
    
                for(i=0;i<top_output;i++)
                {
                    if(output[i][0]>='0'&&output[i][0]<='9')//若为数字存入栈
                    {
                        int tem = 0;
                        //从0到k-1为一个数
                        for(k=1;;k++)
                            if(output[i][k]=='\0')
                                break;
                        for(j=0;j<=k-1;j++)
                            tem = tem*10 + output[i][j] - '0';
    
                        ans[top_ans++] = tem;
    
                    }//ans[top_ans++] = output[i]-'0';
    
                    else                              //若为操作符进行操作
                    {
                        ans[top_ans-2] = operation(ans[top_ans-2],ans[top_ans-1],output[i][0]);
                        top_ans--;
                    }
                }
                my_map[whole_string[0]] = ans[0];
                //cout << ans[0] << endl;
            }
            cout << whole_string[0] << "=" << my_map[whole_string[0]] << endl ;
        }
        return 0;
    }
    


    更多相关内容
  • 桌面计算器支持,命令、文件输入,也支持多文件输入,但是有些Bug,希望那个大佬看到了,能帮改一下,里面还有需求文档。望大佬不吝赐教。
  • 编译原理——C++桌面计算器 系统描述 设计并实现一个桌面计算器,支持基本四则运算,关系运算,可编程运算 基本功能 (1)以命令行方式解析用户输入的表达式,计算并显示结果; (2)支持基本的整型和浮点类型数值...

    编译原理——C++版桌面计算器

    系统描述

    设计并实现一个桌面计算器,支持基本四则运算,关系运算,可编程运算

    基本功能

    (1)以命令行方式解析用户输入的表达式,计算并显示结果;
    (2)支持基本的整型和浮点类型数值计算;
    (3)支持用变量和存储计算结果、变量引用,变量类型需声明,可根据保存的数据变化;

    扩展功能

    (1)支持输出变量类型
    (2)支持输出推导产生式
    (3)支持输出符号表
    (4)支持输出语法分析动作表
    (5)支持输出所有产生式
    (6)支持输出文法first集
    (7)支持输出文法follow集

    实现语言和平台

    实现语言:C++
    实现平台:Visual Stdio2019

    系统分析与设计

    桌面计算器概述

    通常来说编译器应具有词法分析,语法分析,语义分析,中间代码生成,代码优化,目标代码生成,符号表,错误处理器,这7个部分组成,由于本次实践目标是一个简单可编程桌面计算器,所以省去了中间代码生成,代码优化,目标代码生成,三个部分,并将语法分析与语义分析作为一个整体进行编程。
    使用技术:上下文无关文法,自底向上的语法分析,与LR语法分析器结合的SDT

    词法分析

    词法分析是编译器的第一部分,词法分析器读入字符流并将它们组织成为有意义的lexeme序列。对于每个词素,词法分析器产生词法单元作为输出,词法单元格式为:
    <token-name,attribute-value>
    本编辑器的词法分析器输出存储在out.xml中
    本编辑器词法分析器可识别词素如下表:

    可识别符号表与运算符优先级表

    Type Attribute-value Token-name
    常量 Id 1
    常量 True 2
    常量 False 3
    常量 Number 4
    数据类型 Integer 5
    数据类型 Decimal 6
    数据类型 Bool 7
    非关键字 8
    运算符 ( 10
    运算符 ) 11
    运算符 ! 21
    运算符 ++ 22
    运算符 – 23
    运算符 * 31
    运算符 / 32
    运算符 % 33
    运算符 + 41
    运算符 - 42
    运算符 < 51
    运算符 <= 52
    运算符 > 53
    运算符 >= 54
    运算符 == 61
    运算符 != 62
    运算符 && 71
    运算符 || 81
    运算符 = 91
    注释 /**/ 999
    结束 ## 1000

    1运算符和常量 id,true,false,number,decimal
    2括号 ()
    3一元运算 +, - !
    4算术运算 *,/,%
    5算术运算 +,-
    6关系运算 <, <=, >, >=
    7关系运算 ==, !=
    8逻辑与 &&
    9逻辑或 ||
    10赋值/存储 =

    语法分析

    语法分析为编译器的第二步,语法分析器使用由词法分析器生成的各个Token结合给定文法进行语法分析,目的是成功由文法推导出可能的句子,常用方法为语法分析树,
    本次实践中使用方法为与LR语法分析器结合的SDT,基本思路为,程序先读入给定文法,求出LR分析表,根据分析表和词法分析器给的Token,构造语法分析动作表,并将移入规约动作存入Reduce.xml。(程序中$list命令可以输出语法分析动作表)

    CFG

    S->L
    L->L=H
    L->H
    H->H||G
    H->G
    G->G&&F
    G->F
    F->F!=E
    F->F==E
    F->E
    E->EE<=D
    E->E>D
    E->E>=D
    E->D
    D->D-C
    D->D+C
    D->C
    C->C*B
    C->C/B
    C->C%B
    C->B
    B->B++
    B->B–
    B->!B
    B->A
    A->(H)
    A->id
    A->true
    A->false
    A->var

    语义分析

    语义分析为编译器的第三步,语义分析器使用语法分析树和符号表中的信息来检查源程序是否和语言定义的语义一致。
    根据移入规约动作与Token序列进行求结果,若有变量则去符号表中寻找值

    符号表

    程序中提供了符号表查看命令$symbols,符号表由语法分析过程中建立,当程序读入decimal或integer时进行符号表写入,初始值设定为0,可以在后续输入中进行变量赋值

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cctype>
    #include <vector>
    #include <string>
    #include <queue>
    #include <map>
    #include <set>
    #include <sstream>
    #include <fstream>
    #include <cstring>
    #include <cstdlib>
    #include <stack>
    #define _KEY_WORDEND "waiting for your expanding"
    #define MAX 507
    #define DEBUG
    using namespace std;
    
    typedef struct //词的结构,二元组形式(单词种别,单词自身的值)
    {
        int typenum; //单词种别
        char* word;
    }WORD;
    char input[255];
    char token[255] = "";
    int p_input; //指针
    int p_token;
    char ch;
    char* rwtab[] = { "id","true","false","number","integer","decimal","bool",_KEY_WORDEND };//关键字
    int var_list_symbol[50] = {};//变量类型表
    string var_list_name[50] = {};//变量名字表
    double var_list_value[50] = {};//变量值
    int var_list_size = 0;
    bool cout_type = false;
    bool cout_induction = false;
    bool cout_action = false;
    bool cout_list = false;
    bool cout_first = false;
    bool cout_follow = false;
    bool cout_itemset = false;
    bool cout_ERROR = false;
    
    WORD* scanner();//扫描
    
    int words(string input_str)
    {
        ofstream outfile("out.xml", ios::trunc);
        int over = 1;
        memset(input, 0, sizeof(input) / sizeof(char));
        WORD* oneword = new WORD;
        for (int i = 0; i < input_str.length(); i++) {
            input[i] = input_str[i];
        }
        p_input = 0;
        memset(token, 0, sizeof(token) / sizeof(char));
        p_token = 0;
        ch = 0;
        //printf("your words:  %s\n", input);
        while (over < 1000 && over != -1)
        {
            oneword = scanner();
            if (oneword->typenum < 1000)
            {
                if (oneword->typenum != 999)
                    outfile << oneword->typenum << " " << oneword->word << endl;
            }
            over = oneword->typenum;
        }
        outfile.close();
        return 0;
    }
    
    //从输入缓冲区读取一个字符到ch中
    char m_getch()
    {
        ch = input[p_input];
        p_input++;
        return ch;
    }
    
    //去掉空白符号
    void getbc()
    {
        while (ch == ' ' || ch == 10)
        {
            ch = input[p_input];
            p_input++;
        }
    }
    
    //拼接单词
    void concat()
    {
        token[p_token] = ch;
        p_token++;
        token[p_token] = '\0';
    }
    
    //判断是否字母
    int letter()
    {
        if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z')
            return 1;
        else
            return 0;
    }
    
    //判断是否数字
    int digit()
    {
        if (ch >= '0' && ch <= '9')
            return 1;
        else if (ch == '.')
            return 2;
        else
            return 0;
    }
    
    //检索关键字表格
    int reserve()
    {
        int i = 0;
        while (strcmp(rwtab[i], _KEY_WORDEND))
        {
            if (!strcmp(rwtab[i], token))
                return i + 1;
            i++;
        }
        return 8;//如果不是关键字,则返回种别码8
    }
    
    //回退一个字符
    void retract()
    {
        p_input--;
    }
    
    //词法扫描程序
    WORD* scanner()
    {
        WORD* myword = new WORD;
        myword->typenum = 10;  //初始值
        myword->word = "";
        p_token = 0;   //单词缓冲区指针
        m_getch();
        getbc();//去掉空白
    
        if (letter())//判断读取到的首字母是字母
        {
            //如int
            while (letter() || digit())
            {
                concat(); //连接
                m_getch();
            }
            retract(); //回退一个字符
            myword->typenum = reserve();//判断是否为关键字,返回种别码
            myword->word = token;
            return myword;
        }
        else if (digit())  //判断读取到的单词首字符是数字
        {
            while (digit()) //所有数字连接起来
            {
                concat();
                m_getch();
            }
            retract();
            //数字单词种别码统一为1,单词自身的值为数字本身
            myword->typenum = 1;
            myword->word = token;
            return(myword);
        }
        else switch (ch)
        {
        case '=':
            m_getch();//首字符为=,再读取下一个字符判断
            if (ch == '=')
            {
                myword->typenum = 61;
                myword->word = "==";
                return(myword);
            }
            retract();//读取到的下个字符不是=,则要回退,直接输出=
            myword->typenum = 91;
            myword->word = "=";
            return(myword);
            break;
        case '+':
            m_getch();//首字符为+,再读取下一个字符判断
            if (ch == '+')
            {
                myword->typenum = 22;
                myword->word = "++";
                return(myword);
            }
            retract();//读取到的下个字符不是+,则要回退,直接输出+
            myword->typenum = 41;
            myword->word = "+";
            return(myword);
            break;
        case '-':
            m_getch();//首字符为+,再读取下一个字符判断
            if (ch == '-')
            {
                myword->typenum = 23;
                myword->word = "--";
                return(myword);
            }
            retract();//读取到的下个字符不是+,则要回退,直接输出+
            myword->typenum = 42;
            myword->word = "-";
            return(myword);
            break;
        case '/'://读取到该符号之后,要判断下一个字符是什么符号,判断是否为注释
            m_getch();//首字符为/,再读取下一个字符判断
            if (ch == '*') // 说明读取到的是注释
            {
                m_getch();
    
                while (ch != '*')
                {
                    m_getch();//注释没结束之前一直读取注释,但不输出
                    if (ch == '*')
                    {
                        m_getch();
                        if (ch == '/')//注释结束
                        {
                            myword->typenum = 999;
                            myword->word = "注释";
                            return (myword);
                            break;
                        }
                    }
                }
            }
            else
            {
                retract();//读取到的下个字符不是*,即不是注释,则要回退,直接输出/
    
                myword->typenum = 32;
                myword->word = "/";
                return (myword);
                break;
            }
        case '*':
            myword->typenum = 31;
            myword->word = "*";
            return(myword);
            break;
        case '(':
            myword->typenum = 10;
            myword->word = "(";
            return(myword);
            break;
        case ')':
            myword->typenum = 11;
            myword->word = ")";
            return(myword);
            break;
        case '%':
            myword->typenum = 33;
            myword->word = "%";
            return(myword);
            break;
        case '>':
            m_getch();
            if (ch == '=')
            {
                myword->typenum = 54;
                myword->word = ">=";
                return(myword);
                break;
            }
            retract();
            myword->typenum = 53;
            myword->word = ">";
            return(myword);
            break;
        case '<':
            m_getch();
            if (ch == '=')
            {
                myword->typenum = 52;
                myword->word = "<=";
                return(myword);
                break;
            }
            else
            {
                retract();
                myword->typenum = 51;
                myword->word = "<";
                return (myword);
            }
        case '\0':
            myword->typenum = 1000;
            myword->word = "OVER";
            return(myword);
            break;
        case '&':
            m_getch();
            if (ch == '&')
            {
                myword->typenum = 71;
                myword->word = "&&";
                return(myword);
                break;
            }
            retract();
            myword->typenum = -1;
            myword->word = "ERROR";
            return(myword);
            break;
        case '|':
            m_getch();
            if (ch == '|')
            {
                myword->typenum = 81;
                myword->word = "||";
                return(myword);
                break;
            }
            retract();
            myword->typenum = -1;
            myword->word = "ERROR";
            return(myword);
            break;
        case '!':
            m_getch();
            if (ch == '=')
            {
                myword->typenum = 62;
                myword->word = "!=";
                return(myword);
                break;
            }
            else
            {
                retract();
                myword->typenum = 21;
                myword->word = "!";
                return (myword);
            }
        case '$':
            myword->typenum = 1000;
            myword->word = "OVER";
            return(myword);
            break;
        default:
            myword->typenum = -1;
            myword->word = "ERROR";
            return(myword);
            break;
        }
    }
    
    class WF
    {
    public:
        string left, right;
        int back;
        int id;
        WF(char s1[], char s2[], int x, int y)
        {
            left = s1;
            right = s2;
            back = x;
            id = y;
        }
        WF(const string& s1, const string& s2, int x, int y)
        {
            left = s1;
            right = s2;
            back = x;
            id = y;
        }
        bool operator < (const WF& a) const
        {
            if (left == a.left)
                return right < a.right;
            return left < a.left;
        }
        bool operator == (const WF& a) const
        {
            return (left == a.left) && (right == a.right);
        }
        void print()
        {
            if (cout_itemset)printf("%s->%s\n", left.c_str(), right.c_str());
        }
    };
    
    class Closure
    {
    public:
        vector<WF> element;
        void print(string str)
        {
            //项集族
            if (cout_itemset)
                printf("%-15s%-15s\n", "", str.c_str());
            for (int i = 0; i < element.size(); i++)
                element[i].print();
        }
        bool operator == (const Closure& a) const
        {
            if (a.element.size() != element.size()) return false;
            for (int i = 0; i < a.element.size(); i++)
                if (element[i] == a.element[i]) continue;
                else return false;
            return true;
        }
    };
    
    struct Content
    {
        int type;
        int num;
        string out;
        Content() { type = -1; }
        Content(int a, int b)
            :type(a), num(b) {}
    };
    
    vector<WF> wf;
    map<string, vector<int> > dic;
    map<string, vector<int> > VN_set;
    map<string, bool>  vis;
    string start = "S";
    vector<Closure> collection;
    vector<WF> items;
    char CH = '$';
    int go[MAX][MAX];
    int to[MAX];
    vector<char> V;
    bool used[MAX];
    Content action[MAX][MAX];
    int Goto[MAX][MAX];
    map<string, set<char> > first;
    map<string, set<char> > follow;
    
    void make_item()
    {
        memset(to, -1, sizeof(-1));
        for (int i = 0; i < wf.size(); i++)
            VN_set[wf[i].left].push_back(i);
        for (int i = 0; i < wf.size(); i++)
            for (int j = 0; j <= wf[i].right.length(); j++)
            {
                string temp = wf[i].right;
                temp.insert(temp.begin() + j, CH);
                dic[wf[i].left].push_back(items.size());
                if (j)
                    to[items.size() - 1] = items.size();
                items.push_back(WF(wf[i].left, temp, i, items.size()));
            }
    #ifdef DEBUG
        //puts("-------------------------项目表-------------------------");
        //for (int i = 0; i < items.size(); i++)
            //printf("%s->%s back:%d id:%d\n", items[i].left.c_str(), items[i].right.c_str(), items[i].back, items[i].id);
        //puts("--------------------------------------------------------");
    #endif
    }
    
    void dfs(const string& x)
    {
        if (vis[x]) return;
        vis[x] = 1;
        vector<int>& id = VN_set[x];
        for (int i = 0; i < id.size(); i++)
        {
            string& left = wf[id[i]].left;
            string& right = wf[id[i]].right;
            for (int j = 0; j < right.length(); j++)
                if (isupper(right[j]))
                {
                    dfs(right.substr(j, 1));
                    set<char>& temp = first[right.substr(j, 1)];
                    set<char>::iterator it = temp.begin();
                    bool flag = true;
                    for (; it != temp.end(); it++)
                    {
                        if (*it == '~') flag = false;
                        first[left].insert(*it);
                    }
                    if (flag) break;
                }
                else
                {
                    first[left].insert(right[j]);
                    break;
                }
        }
    }
    
    void make_first()
    {
        vis.clear();
        map<string, vector<int> >::iterator it2 = dic.begin();
        for (; it2 != dic.end(); it2++)
            if (vis[it2->first]) continue;
            else dfs(it2->first);
    #ifdef DEBUG
        if (cout_first)
            puts("****************FIRST集***************************");
        map<string, set<char> >::iterator it = first.begin();
        for (; it != first.end(); it++)
        {
            if (cout_first)
                printf("FIRST(%s)={", it->first.c_str());
            set<char>& temp = it->second;
            set<char>::iterator it1 = temp.begin();
            bool flag = false;
            for (; it1 != temp.end(); it1++)
            {
                if (flag)
                    if (cout_first)
                        printf(",");
                if (cout_first) printf("%c", *it1);
                flag = true;
            }
            if (cout_first) puts("}");
        }
    #endif 
    }
    
    void append(const string& str1, const string& str2)
    {
        set<char>& from = follow[str1];
        set<char>& to = follow[str2];
        set<char>::iterator it = from.begin();
        for (; it != from.end(); it++)
            to.insert(*it);
    }
    
    bool _check(const vector<int>& id, const string str)
    {
        for (int i = 0; i < id.size(); i++)
        {
            int x = id[i];
            if (wf[x].right == str) return true;
        }
        return false;
    }
    
    void make_follow()
    {
        while (true)
        {
            bool goon = false;
            map<string, vector<int> >::iterator it2 = VN_set.begin();
            for (; it2 != VN_set.end(); it2++)
            {
                vector<int>& id = it2->second;
                for (int i = 0; i < id.size(); i++)
                {
                    bool flag = true;
                    WF& tt = wf[id[i]];
                    string& left = tt.left;
                    const string& right = tt.right;
                    for (int j = right.length() - 1; j >= 0; j--)
                        if (isupper(right[j]))
                        {
                            if (flag)
                            {
                                int tx = follow[right.substr(j, 1)].size();
                                append(left, right.substr(j, 1));
                                int tx1 = follow[right.substr(j, 1)].size();
                                if (tx1 > tx) goon = true;
                                if (_check(id, "~"))
                                    flag = false;
                            }
                            for (int k = j + 1; k < right.length(); k++)
                                if (isupper(right[k]))
                                {
                                    string idd = right.substr(k, 1);
                                    set<char>& from = first[idd];
                                    set<char>& to = follow[right.substr(j, 1)];
                                    set<char>::iterator it1 = from.begin();
                                    int tx = follow[right.substr(j, 1)].size();
                                    for (; it1 != from.end(); it1++)
                                        if (*it1 != '~')
                                            to.insert(*it1);
                                    int tx1 = follow[right.substr(j, 1)].size();
                                    if (tx1 > tx) goon = true;
                                    if (_check(id, "~"))
                                        break;
                                }
                                else
                                {
                                    int tx = follow[right.substr(j, 1)].size();
                                    follow[right.substr(j, 1)].insert(right[k]);
                                    int tx1 = follow[right.substr(j, 1)].size();
                                    if (tx1 > tx) goon = true;
                                    break;
                                }
                        }
                        else flag = false;
                }
            }
            if (!goon) break;
        }
    #ifdef DEBUG
        if (cout_follow)
            puts("***************FOLLOW集*******************");
        map<string, set<char> >::iterator it = follow.begin();
        for (; it != follow.end(); it++)
        {
            if (cout_follow)printf("FOLLOW(%s)={", it->first.c_str());
            set<char>& temp = it->second;
            //if ( it->first[0] == 'S' )
            temp.insert('#');
            set<char>::iterator it1 = temp.begin();
            bool flag = false;
            for (; it1 != temp.end(); it1++)
            {
                if (flag) if (cout_follow)printf(",");
                if (cout_follow)printf("%c", *it1);
                flag = true;
            }
            if (cout_follow)puts("}");
        }
    #endif
    }
    
    void make_set()
    {
        bool has[MAX];
        for (int i = 0; i < items.size(); i++)
            if (items[i].left[0] == 'S' && items[i].right[0] == CH)
            {
                Closure temp;
                string& str = items[i].right;
                vector<WF>& element = temp.element;
                element.push_back(items[i]);
                int x = 0;
                for (x = 0; x < str.length(); x++)
                    if (str[x] == CH)
                        break;
                memset(has, 0, sizeof(has));
                has[i] = 1;
                if (x != str.length() - 1)
                {
                    queue<string> q;
                    q.push(str.substr(x + 1, 1));
                    while (!q.empty())
                    {
                        string u = q.front();
                        q.pop();
                        vector<int>& id = dic[u];
                        for (int j = 0; j < id.size(); j++)
                        {
                            int tx = id[j];
                            if (items[tx].right[0] == CH)
                            {
                                if (has[tx]) continue;
                                has[tx] = 1;
                                if (isupper(items[tx].right[1]))
                                    q.push(items[tx].right.substr(1, 1));
                                element.push_back(items[tx]);
                            }
                        }
                    }
                }
                collection.push_back(temp);
            }
        for (int i = 0; i < collection.size(); i++)
        {
            map<int, Closure> temp;
            for (int j = 0; j < collection[i].element.size(); j++)
            {
                string str = collection[i].element[j].right;
                int x = 0;
                for (; x < str.length(); x++)
                    if (str[x] == CH) break;
                if (x == str.length() - 1)
                    continue;
                int y = str[x + 1];
                int ii;
                //cout << i << "previous: " << str << endl;
                str.erase(str.begin() + x);
                str.insert(str.begin() + x + 1, CH);
                //cout << i <<"after: " << str << endl;
                WF cmp = WF(collection[i].element[j].left, str, -1, -1);
                for (int k = 0; k < items.size(); k++)
                    if (items[k] == cmp)
                    {
                        ii = k;
                        break;
                    }
                //string& str1 = items[ii].right;
                memset(has, 0, sizeof(has));
                vector<WF>& element = temp[y].element;
                element.push_back(items[ii]);
                has[ii] = 1;
                x++;
                if (x != str.length() - 1)
                {
                    queue<string> q;
                    q.push(str.substr(x + 1, 1));
                    while (!q.empty())
                    {
                        string u = q.front();
                        q.pop();
                        vector<int>& id = dic[u];
                        for (int j = 0; j < id.size(); j++)
                        {
                            int tx = id[j];
                            if (items[tx].right[0] == CH)
                            {
                                if (has[tx]) continue;
                                has[tx] = 1;
                                if (isupper(items[tx].right[1]))
                                    q.push(items[tx].right.substr(1, 1));
                                element.push_back(items[tx]);
                            }
                        }
                    }
                }
            }
            map<int, Closure>::iterator it = temp.begin();
            for (; it != temp.end(); it++)
                collection.push_back(it->second);
            for (int i = 0; i < collection.size(); i++)
                sort(collection[i].element.begin(), collection[i].element.end());
            for (int i = 0; i < collection.size(); i++)
                for (int j = i + 1; j < collection.size(); j++)
                    if (collection[i] == collection[j])
                        collection.erase(collection.begin() + j);
        }
    #ifdef DEBUG
        //puts("-------------CLOSURE---------------------");
        stringstream sin;
        for (int i = 0; i < collection.size(); i++)
        {
            sin.clear();
            string out;
            sin << "closure-I" << i;
            sin >> out;
            collection[i].print(out);
        }
        //puts("");
    #endif  
    }
    
    void make_V()
    {
        memset(used, 0, sizeof(used));
        for (int i = 0; i < wf.size(); i++)
        {
            string& str = wf[i].left;
            for (int j = 0; j < str.length(); j++)
            {
                if (used[str[j]]) continue;
                used[str[j]] = 1;
                V.push_back(str[j]);
            }
            string& str1 = wf[i].right;
            for (int j = 0; j < str1.length(); j++)
            {
                if (used[str1[j]]) continue;
                used[str1[j]] = 1;
                V.push_back(str1[j]);
            }
        }
        sort(V.begin(), V.end());
        V.push_back('#');
    }
    
    void make_cmp(vector<WF>& cmp1, int i, char ch)
    {
        for (int j = 0; j < collection[i].element.size(); j++)
        {
            string str = collection[i].element[j].right;
            int k;
            for (k = 0; k < str.length(); k++)
                if (str[k] == CH)
                    break;
            if (k != str.length() - 1 && str[k + 1] == ch)
            {
                str.erase(str.begin() + k);
                str.insert(str.begin() + k + 1, CH);
                cmp1.push_back(WF(collection[i].element[j].left, str, -1, -1));
            }
        }
        sort(cmp1.begin(), cmp1.end());
    }
    
    void make_go()
    {
        memset(go, -1, sizeof(go));
        int m = collection.size();
        for (int t = 0; t < V.size(); t++)
        {
            char ch = V[t];
            for (int i = 0; i < m; i++)
            {
                vector<WF> cmp1;
                make_cmp(cmp1, i, ch);
                //cout << cmp1.size() << endl;
                if (cmp1.size() == 0) continue;
                for (int j = 0; j < m; j++)
                {
                    vector<WF> cmp2;
                    for (int k = 0; k < collection[j].element.size(); k++)
                    {
                        string& str = collection[j].element[k].right;
                        int x;
                        for (x = 0; x < str.length(); x++)
                            if (str[x] == CH)
                                break;
                        if (x && str[x - 1] == ch)
                            cmp2.push_back(WF(collection[j].element[k].left, str, -1, -1));
                    }
                    sort(cmp2.begin(), cmp2.end());
                    //cout << cmp2.size() << endl;
                    bool flag = true;
                    if (cmp2.size() != cmp1.size()) continue;
                    //cout << cmp1.size() << endl;
                    for (int k = 0; k < cmp1.size(); k++)
                        if (cmp1[k] == cmp2[k]) continue;
                        else flag = false;
                    //cout << "out " << endl;
                    if (flag)
                        go[i][ch] = j;
                }
                //cout << "YES" << endl;
            }
        }
    #ifdef DEBUG
        //puts("---------------EDGE----------------------");
        stringstream sin;
        string out;
        for (int i = 0; i < m; i++)
            for (int j = 0; j < m; j++)
                for (int k = 0; k < MAX; k++)
                    if (go[i][k] == j)
                    {
                        sin.clear();
                        sin << "I" << i << "--" << (char)(k) << "--I" << j;
                        sin >> out;
                        //printf("%s\n", out.c_str());
                    }
    #endif
    }
    
    void make_table()
    {
        memset(Goto, -1, sizeof(Goto));
        //write s to the table 
        for (int i = 0; i < collection.size(); i++)
            for (int j = 0; j < V.size(); j++)
            {
                char ch = V[j];
                int x = go[i][ch];
                if (x == -1) continue;
                if (!isupper(ch))
                    action[i][ch] = Content(0, x);
                else
                    Goto[i][ch] = x;
            }
        //write r and acc to the table 
        for (int i = 0; i < collection.size(); i++)
            for (int j = 0; j < collection[i].element.size(); j++)
            {
                WF& tt = collection[i].element[j];
                if (tt.right[tt.right.length() - 1] == CH)
                {
                    if (tt.left[0] == 'S')
                        action[i]['#'] = Content(2, -1);
                    else
                        for (int k = 0; k < V.size(); k++)
                        {
                            int y = V[k];
                            //cout << "YES " << endl;
                            //cout << tt.left << "->" << tt.right << " " << tt.back << endl;
                            if (!follow[tt.left].count(V[k])) continue;
                            //cout <<tt.left << "->" << tt.right << " " <<  i << " " << V[k] << " " << tt.back << endl;
                            action[i][y] = Content(1, tt.back);
                        }
                }
            }
    #ifdef DEBUG
        if (cout_action) {
            puts("------------------------------------------LR(0)分析表--------------------------------------------------------");
            printf("%10s%5c%5s", "|", V[0], "|");
            for (int i = 1; i < V.size(); i++)
                printf("%5c%5s", V[i], "|");
            puts("");
            for (int i = 0; i < (V.size() + 1) * 10; i++)
                printf("-");
            puts("");
        }
        stringstream sin;
        for (int i = 0; i < collection.size(); i++)
        {
            if (cout_action)printf("%5d%5s", i, "|");
            for (int j = 0; j < V.size(); j++)
            {
                char ch = V[j];
                if (isupper(ch))
                {
                    if (cout_action) {
                        if (Goto[i][ch] == -1)
                            printf("%10s", "|");
                        else
                            printf("%5d%5s", Goto[i][ch], "|");
                    }
                }
                else
                {
                    sin.clear();
                    if (action[i][ch].type == -1);
                    if (cout_action)printf("%10s", "|");
                    else
                    {
                        Content& temp = action[i][ch];
                        if (temp.type == 0)
                            sin << "S";
                        if (temp.type == 1)
                            sin << "R";
                        if (temp.type == 2)
                            sin << "acc";
                        if (temp.num != -1)
                            sin << temp.num;
                        sin >> temp.out;
                        if (cout_action)printf("%7s%3s", temp.out.c_str(), "|");
                    }
                }
            }
            if (cout_action)puts("");
        }
        if (cout_action) {
            for (int i = 0; i < (V.size() + 1) * 10; i++)
                printf("-");
            puts("");
        }
    #endif
    }
    
    void print(string s1, string s2, string s3, string s4, string s5, string s6, string s7)
    {
        printf("%-15s|%-15s%-15s%-20s|%-15s%-15s%-15s\n", s1.c_str(), s2.c_str(), s3.c_str(), s4.c_str(), s5.c_str(),
            s6.c_str(), s7.c_str());
    }
    
    string get_steps(int x)
    {
        stringstream sin;
        sin << x;
        string ret;
        sin >> ret;
        return ret;
    }
    
    template<class T>
    string get_stk(vector<T> stk)
    {
        stringstream sin;
        for (int i = 0; i < stk.size(); i++)
            sin << stk[i];
        string ret;
        sin >> ret;
        return ret;
    }
    
    string get_shift(WF& temp)
    {
        stringstream sin;
        sin << "reduce(" << temp.left << "->" << temp.right << ")";//推导过程
        string out;
        sin >> out;
        return out;
    }
    
    void analyse(string src)
    {
        ofstream reduce_file("reduce.xml", ios::trunc);
        if (cout_list)print("steps", "op-stack", "input", "operation", "state-stack", "ACTION", "GOTO");
        vector<char> op_stack;
        vector<int> st_stack;
        src += "#";
        op_stack.push_back('#');
        st_stack.push_back(0);
        int steps = 1;
        for (int i = 0; i < src.length(); i++)
        {
            char u = src[i];
            int top = st_stack[st_stack.size() - 1];
            Content& act = action[top][u];
            //cout << "YES : " << i << " " << u << " " << top << " " << act.type << endl;
            if (act.type == 0)
            {
                if (cout_list)print(get_steps(steps++), get_stk(op_stack), src.substr(i), "shift", get_stk(st_stack), act.out, "");
                op_stack.push_back(u);
                st_stack.push_back(act.num);
            }
            else if (act.type == 1)
            {
                WF& tt = wf[act.num];
                int y = st_stack[st_stack.size() - tt.right.length() - 1];
                int x = Goto[y][tt.left[0]];
                //cout << y << " " << tt.left[0] << " " << x << endl;
                if (cout_induction)
                    cout << get_shift(tt) << endl;
                reduce_file << act.out << endl;
                if (cout_list)print(get_steps(steps++), get_stk(op_stack), src.substr(i), get_shift(tt), get_stk(st_stack), act.out, get_steps(x));
                for (int j = 0; j < tt.right.length(); j++)
                {
                    st_stack.pop_back();
                    op_stack.pop_back();
                }
                op_stack.push_back(tt.left[0]);
                st_stack.push_back(x);
                i--;
            }
            else if (act.type == 2)
            {
                if (cout_list)
                    print(get_steps(steps++), get_stk(op_stack), src.substr(i), "Accept", get_stk(st_stack), act.out, "");
                //i--;
            }
            else continue;
        }
        if (op_stack.size() > 2) {
            cout << "Error [error:#]" << endl;
            cout_ERROR = true;
        }
        else
            cout_ERROR = false;
        reduce_file.close();
    }
    
    void cout_varlist() {
        cout << "符号表" << endl;
        for (int i = 0; i < var_list_size; i++) {
            if (var_list_symbol[i] == 5)
                cout << "[ " << "integer" << " " << var_list_name[i] << " ]" << endl;
            else
                cout << "[ " << "decimal" << " " << var_list_name[i] << " ]" << endl;
        }
    }
    
    void add_symbols_txt() {
        ofstream outfile("symbols.xml", ios::trunc);
        for (int i = 0; i < var_list_size; i++)
            outfile << "[ " << var_list_symbol[i] << " " << var_list_name[i] << " " << var_list_value[i] << " ]" << endl;
        outfile.close();
        return;
    }
    
    void add_var(int n, string token_str) {//添加符号表
        token_str = token_str.substr(2, token_str.length());
        for (int i = 0; i < var_list_size; i++) {
            if (var_list_name[i] == token_str)
                return;
        }
        var_list_symbol[var_list_size] = n;
        var_list_name[var_list_size] = token_str;
        var_list_size++;
        add_symbols_txt();
    }
    
    string get_tokens() {
        string token_temp = "";
        string token_temp1 = "";
        ifstream file("out.xml");
        while (getline(file, token_temp1)) {
            int num_token = atoi(token_temp1.c_str());
            switch (num_token) {
            case 1:token_temp.append("id"); break;
            case 2:token_temp.append("true"); break;
            case 3:token_temp.append("false"); break;
            case 4:token_temp.append("number"); break;
            case 5:
                getline(file, token_temp1);
                if (atoi(token_temp1.c_str()) == 8)
                    add_var(5, token_temp1);
                break;
            case 6:
                getline(file, token_temp1);
                if (atoi(token_temp1.c_str()) == 8)
                    add_var(6, token_temp1);
                break;
            case 7:token_temp.append("bool"); break;
            case 8:token_temp.append("var"); break;
            case 10:token_temp.append("("); break;
            case 11:token_temp.append(")"); break;
            case 21:token_temp.append("!"); break;
            case 22:token_temp.append("++"); break;
            case 23:token_temp.append("--"); break;
            case 31:token_temp.append("*"); break;
            case 32:token_temp.append("/"); break;
            case 33:token_temp.append("%"); break;
            case 41:token_temp.append("+"); break;
            case 42:token_temp.append("-"); break;
            case 51:token_temp.append("<"); break;
            case 52:token_temp.append("<="); break;
            case 53:token_temp.append(">"); break;
            case 54:token_temp.append(">="); break;
            case 61:token_temp.append("=="); break;
            case 62:token_temp.append("!="); break;
            case 71:token_temp.append("&&"); break;
            case 81:token_temp.append("||"); break;
            case 91:token_temp.append("="); break;
            case 999:token_temp.append(""); break;
            case 1000:token_temp.append(""); break;
            }
        }
        file.close();
        return token_temp;
    }
    
    void init() {
        int n;
        char s[MAX];
        ifstream myfile("production.xml");
        string temp;
        getline(myfile, temp);
        n = atoi(temp.c_str());
        for (int i = 0; i < n; i++)
        {
            getline(myfile, temp);
            int k = 0;
            for (k = 0; k < temp.length(); k++) {
                s[k] = temp[k];
            }
            s[k] = '\0';
            int len = strlen(s), j;
            for (j = 0; j < len; j++)
                if (s[j] == '-') break;
            s[j] = 0;
            wf.push_back(WF(s, s + j + 2, -1, -1));
    #ifdef DEBUG
            wf[wf.size() - 1].print();
    #endif
        }
        make_item();
        make_first();
        make_follow();
        make_set();
        make_V();
        make_go();
        make_table();
    }
    
    void rush_var_list() {
        for (int i = 0; i < var_list_size; i++) {
            if (var_list_symbol[i] == 5)
                var_list_value[i] = int(var_list_value[i]);
        }
    }
    
    void make_production() {
        ifstream production_file("production.xml");
        string str;
        getline(production_file, str);
        while (getline(production_file, str)) {
            cout << str << endl;
        }
    }
    
    void result() {
        rush_var_list();
        stack<double> result_stack;
        ifstream production_file("production.xml");
        ifstream token_file("out.xml");
        ifstream reduce_file("reduce.xml");
        string reduce_str;
        string token_str, t;
        double num[50];
        string str[50];
        int _str_size = 0;//非关键字指针
        int _str_size_now = 0;
        int num_ptr = 0;//num最大指针
        int reduce_ptr = 0;//reduce栈用到的num当前指针
        while (getline(token_file, token_str)) {//token提取数字
            stringstream linestream;
            linestream.str(token_str);
            string first = token_str.substr(0, 1);
            int n = atoi(token_str.c_str());
            if (n == 1) {
                token_str = token_str.substr(1, token_str.length());
                double num1 = atof(token_str.c_str());
                num[num_ptr] = num1;
                num_ptr++;
            }
        }
        token_file.clear();//读文件指针回到起始
        token_file.seekg(ios_base::beg);
        while (getline(token_file, token_str)) {//token提取非关键字
            stringstream linestream;
            linestream.str(token_str);
            linestream >> t;
            char c = t[0];
            int num1 = atoi(t.c_str());
            if (num1 == 8) {
                str[_str_size] = token_str.substr(2, token_str.length());
                _str_size++;
            }
        }
        while (getline(reduce_file, reduce_str)) {
            reduce_str = reduce_str.substr(1, reduce_str.length());
            int n = atoi(reduce_str.c_str());
            n = n + 2;
            double a, b;
            bool not_found_flag = true;
            string symbols_str, symbols_str1;
            switch (n) {
                //32 寻找符号表中值
            case 32:
                token_file.clear();//读文件指针回到起始
                token_file.seekg(ios_base::beg);
                getline(token_file, symbols_str);
                if (!getline(token_file, symbols_str1)) {
                    symbols_str = symbols_str.substr(2, symbols_str.length());
                    for (int i = 0; i < var_list_size; i++) {
                        if (var_list_name[i] == symbols_str) {
                            if (cout_type) {
                                if (var_list_symbol[i] == 6)
                                    cout << "[Decimal, " << var_list_value[i] << "]" << endl;
                                else if (var_list_symbol[i] == 5)
                                    cout << "[Integer, " << var_list_value[i] << "]" << endl;
                            }
                            else
                                cout << var_list_value[i] << endl;
                            not_found_flag = false;
                        }
                    }
                    if (not_found_flag)
                        cout << "Error [undefined identifier:" << symbols_str << "]" << endl;
                }
                else {
                    string str_now = str[_str_size_now];
                    for (int i = 0; i < var_list_size; i++) {
                        if (var_list_name[i] == str_now) {
                            result_stack.push(var_list_value[i]);
                            _str_size_now++;
                        }
                    }
                }
                break;
            case 31: result_stack.push(0); break;
            case 30: result_stack.push(1); break;
            case 29: result_stack.push(num[reduce_ptr]); reduce_ptr++; break;
            case 28:break;
            case 27:break;
            case 26:
                a = result_stack.top();
                result_stack.pop();
                if (a != 0)result_stack.push(0);
                else result_stack.push(1);
                break;
            case 25:
                a = result_stack.top();
                result_stack.pop();
                result_stack.push(a--);
                break;
            case 24:
                a = result_stack.top();
                result_stack.pop();
                result_stack.push(a++);
                break;
            case 23:break;
            case 22:
                a = result_stack.top();
                result_stack.pop();
                b = result_stack.top();
                result_stack.pop();
                result_stack.push(int(b) % int(a));
                break;
            case 21:
                a = result_stack.top();
                result_stack.pop();
                b = result_stack.top();
                result_stack.pop();
                if (a == 0)result_stack.push(b);
                else result_stack.push(b / a);
                break;
            case 20:
                a = result_stack.top();
                result_stack.pop();
                b = result_stack.top();
                result_stack.pop();
                result_stack.push(b * a);
                break;
            case 19:break;
            case 18:
                a = result_stack.top();
                result_stack.pop();
                b = result_stack.top();
                result_stack.pop();
                result_stack.push(a + b);
                break;
            case 17:
                a = result_stack.top();
                result_stack.pop();
                b = result_stack.top();
                result_stack.pop();
                result_stack.push(b - a); break;
            case 16:break;
            case 15:
                a = result_stack.top();
                result_stack.pop();
                b = result_stack.top();
                result_stack.pop();
                if (b >= a) result_stack.push(1);
                else result_stack.push(0); break;
            case 14:
                a = result_stack.top();
                result_stack.pop();
                b = result_stack.top();
                result_stack.pop();
                if (b > a) result_stack.push(1);
                else result_stack.push(0); break;
            case 13:
                a = result_stack.top();
                result_stack.pop();
                b = result_stack.top();
                result_stack.pop();
                if (b <= a) result_stack.push(1);
                else result_stack.push(0); break;
            case 12:
                a = result_stack.top();
                result_stack.pop();
                b = result_stack.top();
                result_stack.pop();
                if (b < a) result_stack.push(1);
                else result_stack.push(0); break;
            case 11:break;
            case 10:
                a = result_stack.top();
                result_stack.pop();
                b = result_stack.top();
                result_stack.pop();
                if (b == a) result_stack.push(1);
                else result_stack.push(0); break;
            case 9:
                a = result_stack.top();
                result_stack.pop();
                b = result_stack.top();
                result_stack.pop();
                if (b != a) result_stack.push(1);
                else result_stack.push(0); break;
            case 8:break;
            case 7:
                a = result_stack.top();
                result_stack.pop();
                b = result_stack.top();
                result_stack.pop();
                if (b && a) result_stack.push(1);
                else result_stack.push(0); break;
            case 6:break;
            case 5:
                a = result_stack.top();
                result_stack.pop();
                b = result_stack.top();
                result_stack.pop();
                if (b || a) result_stack.push(1);
                else result_stack.push(0); break;
            case 4:break;
            case 3:
                token_file.clear();//读文件指针回到起始
                token_file.seekg(ios_base::beg);
                getline(token_file, symbols_str);
                symbols_str = symbols_str.substr(2, symbols_str.length());
                for (int i = 0; i < var_list_size; i++) {
                    if (var_list_name[i] == symbols_str) {
                        var_list_value[i] = result_stack.top();
                        not_found_flag = false;
                    }
                }
                if (not_found_flag)
                    cout << "not found " << symbols_str << endl;
                break;
            case 2:break;
            }
        }
        if (!result_stack.empty() && !cout_ERROR) {
            double result = result_stack.top();
            if (result == 1) {
                if (cout_type)
                    cout << "[Bool, true]" << endl;
                else
                    cout << "true" << endl;
            }
            else if (result == 0) {
                if (cout_type)
                    cout << "[Bool, false]" << endl;
                else
                    cout << "false" << endl;
            }
            else {
                ifstream file1("reduce.xml");
                string temp1, temp2;
                while (getline(file1, temp1))
                    temp2 = temp1;
                file1.close();
                bool flag = true;
                if (temp2 == "R1") {//=产生式
                    flag = false;
                }
                if (cout_type) {
                    int result1 = result;
                    float temp = result1 - result;
                    if (fabs(temp) < 1e-6) {
                        if (flag)cout << "[Integer, " << result << "]" << endl;
                    }
                    else
                        if (flag)cout << "[decimal, " << result << "]" << endl;
                }
                else
                    if (flag)cout << result << endl;
            }
        }
        production_file.close();
        token_file.close();
        reduce_file.close();
    }
    
    void cout_help() {
        cout << "---------------------------------" << endl;
        cout << "编辑器中所有变量都需要定义才可使用,数据类型有integer和decimal" << endl;
        cout << "可输入命令如下:默认只输出值 " << endl;
        cout << "    $type(输出类型和值)" << endl;
        cout << "    $induction(输出推到产生式)" << endl;
        cout << "    $symbols(输出符号表)" << endl;
        cout << "    $default(恢复默认值)" << endl;
        cout << "    $first(输出文法first集)" << endl;
        cout << "    $follow(输出文法follow集)" << endl;
        cout << "    $production(输出所有产生式)" << endl;
        cout << "    $help(输出帮助)" << endl;
        cout << "    $list(输出语法分析动作表)" << endl;
        cout << "    ##(退出)" << endl;
        cout << "---------------------------------" << endl;
    }
    
    int main()
    {
        init();
        string input_str;
        bool flag = true;
        cout_help();
        while (flag) {
            cout << ">>>";
            getline(cin, input_str);
            if (input_str == "##") {
                cout << "quit" << endl;
                return 0;
            }
            else if (input_str == "$symbols") {
                cout_varlist();
            }
            else if (input_str == "$first") {
                cout_first = !cout_first;
                make_first();
                cout_first = !cout_first;
            }
            else if (input_str == "$follow") {
                cout_follow = !cout_follow;
                make_follow();
                cout_follow = !cout_follow;
            }
            else if (input_str == "$production") {
                make_production();
            }
            else if (input_str == "$type") {
                cout_type = !cout_type;
                cout << "$type=" << cout_type << endl;
            }
            else if (input_str == "$induction") {
                cout_induction = !cout_induction;
                cout << "$induction=" << cout_induction << endl;
            }
            else if (input_str == "$default") {
                bool cout_type = false;
                bool cout_induction = false;
                bool cout_action = false;
                bool cout_list = false;
                bool cout_first = false;
                bool cout_follow = false;
                bool cout_itemset = false;
                bool cout_ERROR = false;
                cout << "init" << endl;
            }
            else if (input_str == "$list") {
                cout_list = !cout_list;
                cout << "$list=" << cout_list << endl;
            }
            else if (input_str == "$help") {
                cout_help();
            }
            else {
                words(input_str);
                analyse(get_tokens());
                result();
            }
        }
        return 0;
    }
    

    github地址

    项目地址

    展开全文
  • C++桌面计算器(第一版)

    千次阅读 2018-10-08 17:51:31
    (此版本为过程式,对应于《The C++ Programming Language 3rd》第六章) 表达式语法分析如下(递归定义): ***************** * program: * END //END is end-of-input * expr_list END * expr_list:...

    (此版本为过程式,对应于《The C++ Programming Language 3rd》第六章)

    表达式语法分析如下(递归定义):

     *****************
     * program:
     *     END					//END is end-of-input
     *     expr_list END
     * expr_list:
     *     expression PRINT     // PRINT is semicolon
     *     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 ) 
     * *****************
    

    完整文件(不包括Makefile)

    • calc.h
    • calc.cpp
    • main.cpp

    calc.h

    /**
     * calc.h
     *****************
     * program:
     *     END                  //END is end-of-input
     *     expr_list END
     * expr_list:
     *     expression PRINT     // PRINT is semicolon
     *     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 PROGRAM
    extern Token_value curr_tok;
    extern map<string, double> table;   // var table
    extern int no_of_errors;
    
    extern double expr(bool get);
    extern Token_value get_token();
    extern double error(const string& s);
    // END for DRIVER PROGRAM
    
    extern double term(bool get);
    extern double prim(bool get);
    
    #endif
    

    calc.cpp

    // calc.cpp
    #include "calc.h"
    
    #include <cctype>
    
    #include <iostream>
    #include <map>
    #include <string>
    
    using namespace std;
    
    // error function
    int no_of_errors;
    
    double error(const string& s)
    {
        no_of_errors++;
        cerr << "error: " << s << '\n';
        return 1;
    }
    // END error function
    
    Token_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 table
    
    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(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
    
    

    main.cpp

    /**
     * main.cpp
     *
     * 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 DRIVER
    istream* 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;
    
    }
    

    程序结构如下:

    程序结构图

    展开全文
  • c++实现计算器文件

    2019-12-10 23:26:27
    使用c++语言完成的计算器模拟操作,除了基本四则运算操作意外,还可以实现括号添加,优先运算括号内的表达式。
  • 桌面计算器解析 1.1自定义类型分析 1.1.1 枚举类型 enum Token_value { NAME, NUMBER, END, PLUS='+', MINUS='-', MUL='*', DIV='/', PRINT=';', ASSIGN='=', LP='(', RP=')' }; ​ 首先我们可以看到程序维护了...

    桌面计算器解析

    1.1自定义类型分析

    1.1.1 枚举类型

    enum Token_value {
        NAME,       NUMBER,       END,
        PLUS='+',   MINUS='-',    MUL='*',      DIV='/',
        PRINT=';',  ASSIGN='=',   LP='(',       RP=')'
    };
    

    ​ 首先我们可以看到程序维护了一个枚举类型Token_value,并且实例化了一个变量:curr_tok,用来存储由控制台读入的用户输入的类型。大部分名字都采取见名知意的风格,可直观了解到符号要表达的意思,下面做一些细节的解释:
    $$
    \begin{cases}
    NAME:代表常量,PI和自然对数e或者用户自己输入的变量的名称\
    NUMBER:浮点数\
    END:字符串的结束标志:\text{\0}\

    \end{cases}
    $$
    ​ 其他的符号意思都很明显,不做赘述。

    1.1.2 全局变量

    extern Token_value curr_tok;
    extern map<string, double> table;   // var table
    extern int no_of_errors;
    

    整个程序中存在三个全局变量:

    • curr_tok

      作用已在上一小节中予以描述,被初始化为PRINT状态。

    • table

      table是一个map集合,将从控制台读入的pi,e字符(串)转化称为对应的值,同时假如读入的是table中的元素,那么curr_tok也会将状态标记为NAME,及上述的代表常量的符号。

    • no_of_errors

      报错的个数

    1.2 输入分析

    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;
        }
    ......
    }
    

    这部分不是我们要分析的重点,所以只做简单说明。

    程序的输入主要时针对了两种情况:

    • 一种是直接有输入dc和要执行的指令的,比如:dc 1+3;,这种在我们直接在IDE中run的情况下不存在,在命令行输入才需要输入dc。
    • 一种时只有输入1+3,即是我们在IDE中run的过程。

    我们针对这两种情况,根据参数的个数进行判别,以便使指针指向正确的流的位置。

    1.3 程序流程分析

    ​ 在这部分,我们将以完整的输入:3+2*3;为例进行一个流程的简短说明,以说明函数之间的调用关系和流程。随后再分别对各个调用的函数的功能和相互关系进行分析。

    1.3.1 举例分析流程

    ​ 我们首先进入main函数,忽略掉前面的输入部分,函数体写得很精简:

    while (*input) {
            get_token();
            if (curr_tok == END) break;
            if (curr_tok == PRINT) continue;
            cout << expr(false) << '\n';
        }
    

    ​ 循环体的循环条件是输入的指针无异常,要是输入异常则会跳出循环。

    ​ 首先进行的get_token函数的调用:

    ​ 通读代码,大致可以得到结论:get_token调用目的是不断更新curr_tok变量的状态,也就是当前的输入所代表的状态,并且通过这个状态来判断下一步应该执行什么样的操作。

    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;
        }
    }
    

    字符ch是一个临时变量,用来记录从控制台输入的数字,字符等。这个变量在switch中会因变量的类型不同而进行不同而进入到不同的归宿:

    • 若读入结束标志,那么更新curr_tok标志为END,整个程序会返回到mian函数跳出循环体并结束

    • 若读入的是运算符,那么在枚举类型中找到对应的枚举量,用枚举类型值更新curr_tok

    • 若读入的是数字,则更新curr_tok,即当前输入状态为NUMBER

      并且这里作者有一个特别的操作,为了避免输入123,在一个字符一个字符读入的情况下只拿出来一个ch=1,这里将字符putback,放回流中,再一把将读入的数拿出来,放到number_value中。

    • 如读入的是字符,那么会进行是否是常量e和pi的判断或者进一步判断是否是用户自己定义的变量的名称:进行类似于上面读取整个number_value的操作,将后续要读入的字符也都进来。最后更新curr_tok状态为NAME。

    • 假如都不满足上面的情况,那么只能说明输入出现了错误,通过标准错误流报错,并且将状态更新为PRINT.

    ​ 对于我们举出的例子,自然满足第三种情况,我们保存了现在的curr_tok的状态:NUMBER,返回到main函数中,进入expr函数的调用。我们先给出上述状态的流程图(由于main函数其实大程度上起到的是调节下一次的输入和非法输入的状态,在我们举例说明的时候并没有反复使用,此外由于调用的过程较为复杂,所以这之后的流程图,main和星形的get_token将不会画出):

    image-20210329192937500

    1.3.1.1进行运算的函数expr(),trem(),prim()

    expr()函数主要的功能是及逆行加减运算和将最后结果返回到main中进行打印到控制台的操作。

    可以看到:double left = term(get);我们传入的参数为false,程序首先会进行又一层的函数调用:调用term来进行乘法的操作。而进入term函数之后,我们发现函数的第一行又是对下一个函数的调用:我们接着不得不进入prim函数。层层递归以达到取得最后的left值的结果。

    所以这里我们先进入递归的最底层:prim()函数,对其进行说明,稍后再以返回的顺序对expr()函数进行说明。

    prim()函数处理最基础的,也是级别最高的状态:

    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(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");
        }
    }
    

    调用到这层时,由于传入的get值时false,所以这里不会在对get_token函数进行调用,直接进入switch分支中,根据当前的NUMBER状态,进入相应的分支中。首先用临时变量记下当前的number_value值,即之前输入的3。接着prim再进行一次get_token的调用,此时在get_token函数中读入新的字符:+,并且此时把我们的输入状态改变为PLUS,最后这次get_token调用结束,返回到prim函数中。此时prim调用也随即结束,返回到调用的term函数处,并带回临时变量的值v:赋予term中的变量left。

    至此我们进行的流程为:

    image-20210329185749809

    我们来到term函数:

    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;
        }
    }
    

    ​ 在term中,我们进入循环,根据现在的curr_tok的状态,进入switch分支:default 。下面也将得到结论,这个函数只是处理乘除法,并不对加法进行处理。不管怎样,left值:3,被带回到了expr函数中。

    ​ 带着left = 3的结果,我们来着这个整个函数体类似trem的函数expr中。至此,我们终于结束了上图中描述的调用,进入了循环中,根据当前的PLUS状态,我们发现函数继续向下调用了term函数,而trem函数向下调用prim,prim从get_token中读入数字2,更新curr_tok状态为NUMBER,接着不断地返回到上次的调用处……在term函数中接着调用get_token,得到 乘法的状态,饥渴的term函数终于得到了一个属于他自己专属的乘法运算,他迫不及待想知道要相乘的对象是什么,故而再次call了prim函数,希望得到一个number与left值2相乘,prim带着3与2相乘,最后得到left值:6。term函数break,返回到上次调用它的地方。这次我们调用的完整过程为:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7mDKmEnq-1620315125756)(C:/Users/%E5%AD%99%E8%95%B4%E7%90%A6/AppData/Roaming/Typora/typora-user-images/image-20210329190029463.png)]

    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;
            }
        }
    }
    

    ​ 经过这次的递归下降,读者可能已经不记得了上次我们调用term是在哪里了,不妨看一下上上个段落——上次调用是在expr函数中,我们想要知道PLUS的操作对象,所以向下调用的term,而term最后是获得了一个left值的:6,把它返回expr函数中,经过PLUS操作,最终left值更新为3+6,即9。

    ​ 跳出expr,根据上面的流程图,我们是回到了main函数。最终将结果6进行了输出,并等待下一次的循环……

    1.3.1.2 完整流程图

    ​ 为了方便梳理整个流程,我们再次做出一个更完整的流程图,方便对着流程图进行梳理。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yeVq3MDy-1620315125761)(C:/Users/%E5%AD%99%E8%95%B4%E7%90%A6/AppData/Roaming/Typora/typora-user-images/image-20210329185242321.png)]

    1.3.2 函数功能及关系

    1.3.2.1 函数功能

    ​ 经过上面流程的大概分析,我们已经差不多把主要的代码阅读了一遍。可以对相应的函数进行细节功能进行细节性的分析了:

    • get_token()
      • 整个程序的获得输入的唯一入口就是get_token函数,不论从何处要获得下一个输入的字符,就需要调用curr_token函数
      • get_token整个程序的状态解析器也是该函数。get_token会根据输入对curr_tok进行修改,从该全局变量的状态会直接决定程序下一步应该调用哪个函数,进行哪个运算。
      • 其实整个递归下降的编程风格中,每一次调用向下的过程不论是小的分支,还是大的流程的调用,get_token函数都是我们递归的的终点,开始返回调用处的起点。
    • expr()
      • expr函数所能处理就是基本的加减运算,这也说明这是一个优先级最低的运算。
      • 优先级最低决定了该函数需要不断地向下调用别的函数,获得下一个运算法,以判断有无更高级的运算。在高级的运算算完之后返回结果,再对结果进行加减运算。所以expr函数的出现常常的递归的起点。
    • term()
      • term函数常是由expr函数调用的,他会根据现在的状态来判断是否要进行乘法除法运算。
      • term函数不是运算优先级最高的函数,所以常常会继续向下调用最基础的prim()函数。
    • prim()
      • prim()是最基础的字符和常量的处理,也是整个函数中直接调用get_token的唯二函数(main也调用)。
      • 常常是通过prim()对当前状态的分析来获得下一次的输入或者是返回负数的值等。

    1.3.2.3 函数间的关系

    ​ 在上面的论述中我们其实已经对各个函数之间的协作关系进行了详细的分析和总结,所以这里只以树状图的形式进行图示说明:

    image-20210329194127791

    ​ 此外,由于计算器的功能比较强大,调用关系也很复杂,所以仅仅根据我们举出的3+2*3的例子只能大概了解函数的功能,更加复杂的调用和函数间关系根据这幅图也能得到一些启示。

    1.4 程序中的错误管理

    ​ 这是一个需要直接跟用户进行输入上交互的程序,所以面对用户的输入状态,不合法的输入必然要进行适当的处理。所以程序实际上维护一个错误管理函数,对可能出现的错误,比如除数是0,输入的符号不合法等进行处理。一些函数会对其进行调用,将错误的情况打印在控制台,供用户检查。

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

    2.1 小结

    ​ 较之前阅读和自己写的的面向过程的程序或者一些大项目来说,该桌面计算器无疑是调用关系最为复杂的一个,同时也是最为精巧的一个:每个函数都像面向对象的开发中的一个小组件,各个函数之间任务不重叠,只是实现自己的一部分功能,复杂的调用关系也反映了每个部分的复用性是非常之高的,任务分配也是十分准确的。

    ​ 这样的程序可能在接触面向对象的思想之前会觉得没有比这更好的程序了,接触过Java后觉得这样递归下降的程序风格让人又爱又恨了,写的精妙,阅读起来确实也是难度攀升。经过debug调试和一些资料查找才明白了其中的一些细节的设计和整个程序在给出样例的情况下的流程。

    ​ 桌面计算器面对更加复杂的输入必然会有更加复杂的调用,但函数之间的关系却是万变不离其宗。(希望下一次阅读这个程序的面向对象的版本时能轻松些(逃))

    精巧的一个:每个函数都像面向对象的开发中的一个小组件,各个函数之间任务不重叠,只是实现自己的一部分功能,复杂的调用关系也反映了每个部分的复用性是非常之高的,任务分配也是十分准确的。

    ​ 这样的程序可能在接触面向对象的思想之前会觉得没有比这更好的程序了,接触过Java后觉得这样递归下降的程序风格让人又爱又恨了,写的精妙,阅读起来确实也是难度攀升。经过debug调试和一些资料查找才明白了其中的一些细节的设计和整个程序在给出样例的情况下的流程。

    ​ 桌面计算器面对更加复杂的输入必然会有更加复杂的调用,但函数之间的关系却是万变不离其宗。(希望下一次阅读这个程序的面向对象的版本时能轻松些(逃))

    展开全文
  • C++实现桌面计算器

    2014-05-05 16:05:01
    C++实现桌面计算器,以等号结束,Devc中直接使用
  • 桌面计算器C++代码

    2012-05-05 23:57:30
    大学课堂作业,用C++编写桌面计算器的源程序。实现计算器的基本功能,作业的标准模板。
  • 桌面计算器

    2018-10-21 22:23:18
    C++程序设计语言6.1节计算器。 命令行计算器,可以进行加减乘除运算,支持变量定义。 有单文件和多文件两种
  • 编译原理_计算器_C++实现 编译原理_计算器_C++实现 编译原理_计算器_C++实现 编译原理_计算器_C++实现
  • 桌面计算器改进版

    2019-04-15 00:53:43
    桌面计算器,实现了普常见的桌面计算器的功能,可计算加减乘除,可处理括号符号
  • 这里要介绍各种语句和表达式,将通过一个桌面计算器的程序做些事情,该计算器提供四种座位浮点数的中缀运算符的标准算术运算。这个计算器由四个部分组成:一个分析器,一个输入函数,一个符号表和一个驱动程序。 ...
  • 本程序具有类似编译器计算等式的功能比如输入算式: 40-(5.2*2.1-10)-5/i-25/5+9= 然后按enter键,就会计算出结果,也就是说只要你输入任意合法的算式,就能计算出结果
  • 如何开始对解析器进行编程。
  • C++程序设计特别版中的桌面计算器源码。
  • C++面向对象程序设计-桌面计算器实现 源代码 /** ***************** * program: * END //END is end-of-input * expr_list END * expr_list: * expression PRINT // PRINT is semicolon * expre...
  • 这里写自定义目录标题C++程序设计语言——一个桌面计算器示例程序代码 C++程序设计语言——一个桌面计算器示例 C++程序设计语言一书中第10章 10.2节的桌面计算器示例。 程序代码 #include <ctype.h> #include ...
  • 在 Visual Studio 中安装“使用 C++桌面开发”工作负载并在计算机上运行 。 如果尚未安装,请参阅在 Visual Studio 中安装 C++ 支持。 创建应用项目 Visual Studio 使用项目来组织应用的代码,使用解决方案来...
  • 一、Visual Studio Installer 安装 C++ 桌面开发库、 二、Visual Studio 2019 创建 Windows 桌面程序
  • 问题介绍:今天突然看到一个问题看起来蛮有趣的,跟大家分享一下. 给定任意日期对该日期进行加减天数,最后得出加减后出现的日期.以及给两个日期你可以得出他们两个之间相隔多少天.(需要考虑闰年,每个月天数不同,...
  • 一个简单的计算器类(类型),要求: (1) 从键盘读入算式。 (2) 可以进行加、减、乘、除运算。 (3) 运算要有优先级。 (4) 用户可以按任何的运算符出现顺序进行输入。 (5) 不限定用户输入的计算式的长度。 ...
  • 一、打开记事本、计算器 #include &lt;stdlib.h&gt; void main(){ system("notepad");//打开记事本 system("pause"); system("calc");//打开计算器 system("pause&...
  • 现在给大家介绍一下使用VS2019创建第一个C++项目,进而熟悉下VS2019。一、启动界面二、启动后进入VS2019的项目主界面1.打开最近项:会展示近期打开的项目、文件夹、文件,最后一次打开的在最上面,方便快速启动之前...
  • python妙用桌面计算器

    2021-02-21 13:37:09
    python当计算器——不是玩笑 python是一个好东西 度娘说: Python由荷兰数学和计算机科学研究学会的Guido van Rossum 于1990 年代初设计,作为一门叫做ABC语言的替代品。 Python提供了高效的高级数据结构,还能...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,074
精华内容 1,229
关键字:

c++桌面计算器

c++ 订阅