签到

05月06日
尚未签到

共有回帖数 0

    幻梦如戏

    等级:


    本版新特性:
    1.纠正了几个BUG
    2.新增Debug功能,可以即时跟踪查错(主要是EC计算器本身),也可以查看运行情况,深层了解本算法原理
    3.命令行处理:
    (1)没有参数,进入界面并可选择进入Debug模式
    (2)合法文件名时,读入文件中一批表达式计算并输出到文件
    (3)参数是一条表达式,计算并打印结果

    本计算器分两部分,词法分析和计算,词法分析仅仅为计算读入表达式的各个元素
    计算为一次描述,以高优先级压栈,低优先级出栈为原理分析求解表达式.

    昨天灌水太多被管理员XX了~~~^_^希望这次不要了~~~
    还是强烈要求大家帮我查错~~~
    #include stdio.h
    #include stdlib.h
    #include math.h
    #define VER        "0.8.5"

    #define STACK_SIZE    100
    #define UNIT_TYPE_NUM    0    /* 数字*/
    #define UNIT_TYPE_ADD    1    /* '+' */
    #define UNIT_TYPE_SUB    2    /* '-' */
    #define UNIT_TYPE_MUL    3    /* '*' */
    #define UNIT_TYPE_DIV    4    /* '/' */
    #define UNIT_TYPE_LC     5    /* '(' */
    #define UNIT_TYPE_RC     6    /* ')' */
    #define UNIT_TYPE_POW    7    /* '^' */
    #define UNIT_TYPE_ERR    8    /* 错误*/
    #define BLANK           10    /* 空白*/

    typedef float        STACK_TYPE;

    typedef struct{
       int sp;
       STACK_TYPE stack[STACK_SIZE];
    }Stack;

    typedef struct{
       char type;       /*类型*/
       STACK_TYPE num;  /*类型为数字时有效*/
    }Unit;

    /*****************************
    *函数列表
    ****************************/
     
    int initStack(Stack *s);   /*初始化一个堆栈*/
    int push(Stack *s,STACK_TYPE num);   /*压栈*/
    int checkStack(Stack *s);  /*检查是否到栈底*/
    STACK_TYPE pop(Stack *s);  /*从堆栈中弹出*/
    int gettype(char a);       /*返回字符类型,本程序中有点混乱~~*/
    int unitRead(char *es,Unit *ret,int flag); /*从表达式中读出一个元素*/
    int getPRI(char a);        /*得到字符(符号)的优先级*/
    int proc(STACK_TYPE a,STACK_TYPE b,STACK_TYPE opr,STACK_TYPE *resu);
                     /*计算 a opr b*/
    float calcu(char *es);     /*计算es表达式*/
    int checkExp(char *s);     /*检查表达式s*/
    void showHelp(int flag);   /*显示帮助信息*/
    int main();                /*主函数*/

    /*****************************
    *堆栈及其基本操作函数
    ****************************/


    int initStack(Stack *s){    /*初始化堆栈*/
       s-sp=0;
       return 1;
    }

    int push(Stack *s,STACK_TYPE num){    /*将一个数压入堆栈S*/
       if(s-sp=STACK_SIZE||s-sp0) return 0;
       s-stack[s-sp]=num;
       s-sp++;
       return 1;
    }

    STACK_TYPE pop(Stack *s){        
    /*出栈,由于只是读取而已,所以不进行SP检查*/
       s-sp--;
       return(s-stack[s-sp]);
    }
    int checkStack(Stack *s){
       return(s-sp);
    }

    /*****************************
    *调试专用函数
    ****************************/

    int debug=0;
    extern Stack sign,num;
    void printSign(char t){        /*转换为直观符号*/
       if(t==UNIT_TYPE_ADD) printf("+");
       else if(t==UNIT_TYPE_SUB) printf("-");
       else if(t==UNIT_TYPE_MUL) printf("*");
       else if(t==UNIT_TYPE_DIV) printf("/");
       else if(t==UNIT_TYPE_LC) printf("(");
       else if(t==UNIT_TYPE_RC) printf(")");
       else if(t==UNIT_TYPE_POW) printf("^");
       else printf("Unit Error");
    }

    void printUnit(Unit t){        /*打印读入单元*/
       if(t.type==UNIT_TYPE_NUM) printf("Num : %f",t.num);
       else{
           printf("Sign: ");
           printSign(t.type);
       }
    }
    void debugkey(int flag,Unit t,char *s,int ggflag){
            /*调试关键函数,由一全极变量,控制是否执行*/
       int i;
       char input;
       static int gg=0;       /*直接执行标志*/
       char buf[100];
       if(debug==0) return;
       if(ggflag==0){
           gg=0;   /*假如ggflag为1,即初始化gg*/
           return;
       }
       printf("Exp: "%s"n",s);
       if(flag==1){
           printf(" Next  ");
           printUnit(t);
           printf("n");
       }
       printf("Number Stack(SP: %d):    ",num.sp);
       for(i=0;inum.sp;i++)
           printf("%.1f, ",num.stack);
       printf("nOperator Stack(SP: %d):  ",sign.sp);
       for(i=0;isign.sp;i++){
           printSign((char)sign.stack);
           printf(", ");
       }
       printf("n");
       if(gg==0){
           for(;;){
               printf("-");
               gets(buf);
               if((buf[0]=='g'||buf[0]=='G')&&buf[1]==0){
                   gg=1;
                   break;
               }
               else if((buf[0]=='t'||buf[0]=='T')&&buf[1]==0) break;
               else if((buf[0]=='q'||buf[0]=='Q')&&buf[1]==0){
                   debug=0;
                   break;
               }
               else if(buf[0]!=0) printf("Bad command.n");
           }
       }
    }




    /*****************************  *语法分析和计算等函数  ****************************/ Stack sign,num;           /*须要两个堆栈,声明为公用*/
    int gettype(char a){     if(a='0'&&a='9'||a=='.')         return UNIT_TYPE_NUM;     switch(a){     case '+':         return UNIT_TYPE_ADD;     case '-':         return UNIT_TYPE_SUB;     case '*':         return UNIT_TYPE_MUL;     case '/':         return UNIT_TYPE_DIV;     case '(':         return UNIT_TYPE_LC;     case ')':         return UNIT_TYPE_RC;     case '^':         return UNIT_TYPE_POW;     case ' ':     case 't':         return BLANK;     default:         return UNIT_TYPE_ERR;     } }          int unitRead(char *es,Unit *ret,int flag){     /*从表达式ES中读入一个元素到ret*/     static int curpos=0;/*记录当前位置*//*flag==1 时从头重新分析*/     char tbuf[50];     int ibuf;     char ttype;     if(flag==1){         curpos=0;         return 0;     }     if(es[curpos]==0)         return 0;     while((ttype=gettype(es[curpos]))==BLANK) curpos++; /*忽略空格*/     if(ttype==UNIT_TYPE_ERR)         return 2;     if(ttype!=UNIT_TYPE_NUM){    /*读入的是一个符号*/         ret-type=ttype;         ret-num=0;         curpos++;         return 1;     }     else{                /*为数字情况*/         ret-type=UNIT_TYPE_NUM;         ibuf=0;         while((ttype=gettype(es[curpos]))==UNIT_TYPE_NUM){                             /*读入字串,组成数字*/             tbuf[ibuf++]=es[curpos];             curpos++;         }         tbuf[ibuf]=0;         ret-num=(float) atof(tbuf);         return 1;     } }
    int getPRI(char a){     switch(a){         case UNIT_TYPE_ADD:         case UNIT_TYPE_SUB:             return 1;         case UNIT_TYPE_MUL:         case UNIT_TYPE_DIV:             return 2;         case UNIT_TYPE_POW:             return 3;         case UNIT_TYPE_LC:         case UNIT_TYPE_RC:             return 4;         default:             return 0;     } }
    int proc(STACK_TYPE a,STACK_TYPE b,STACK_TYPE opr,STACK_TYPE *resu){
    /*由于返回值用来作错误标识*/
       switch(opr){                            /*结果只能由指针传入*/
           case UNIT_TYPE_ADD:
               *resu=(a+b);
               return 1;
           case UNIT_TYPE_SUB:
               *resu=(a-b);
               return 1;
           case UNIT_TYPE_MUL:
               *resu=(a*b);
               return 1;
           case UNIT_TYPE_DIV:
               if(b==0){
                   printf("Divided by 0.n");
                   return 0;
               }
               *resu=(a/b);
               return 1;
           case UNIT_TYPE_POW:
               *resu=pow(a,b);
               return 1;
           default:
               printf("Unknow Error.n");
               return 0;
       }
    }

    float calcu(char *es){/*被抽像的函数,入口参数为一字符串,*/
    /*返回计算结果,错误不返回值,但会在错误设备上输出信息*/
       Unit t;
       /*int ret,procret;*/
       int lastPRI=0,curPRI;   /*记录上一个符号的优先级*/
       STACK_TYPE trc,proctemp,poptemp;
       unitRead(es,&t,1);       /*初始化单元读*/
       initStack(&sign);       /*初始化堆栈*/
       initStack(&num);
       debugkey(1,t,es,0);       /*初始化调试器内部变量*/
       
       push(&num,0);

    push(&sign,UNIT_TYPE_ADD);
       push(&num,0);
       push(&sign,UNIT_TYPE_ADD);
       /*上上计啊!先预定压入两个0+,防止堆栈出栈越界*/
       while(unitRead(es,&t,0)==1){    /*读入返回值为1时才有效*/
           switch(t.type){
           case UNIT_TYPE_NUM:
               push(&num,t.num);       /*数字总是压栈*/
               break;
           default:                /*符号*/
               if(t.type==UNIT_TYPE_RC){
                   /*遇到右括号将一直计算到左括号为止*/
                   while((trc=pop(&sign))!=UNIT_TYPE_LC){
                       if(!proc(pop(&num),pop(&num),trc,&proctemp))
                           return 0.0;
                       push(&num,proctemp);
                   }
                   lastPRI=getPRI(poptemp=pop(&sign));
                   if(poptemp==UNIT_TYPE_LC) lastPRI=0;
                     /*取出的是(则继续要压栈*/
                   push(&sign,poptemp);/*取上一次("("之前)的优先级*/
                   break;
               }
               curPRI=getPRI(t.type);
               if(curPRIlastPRI){
                   /*当读入符号优先级大于上一个时,将其压栈*/
                   push(&sign,t.type);
                   lastPRI=curPRI;

           if(t.type==UNIT_TYPE_LC)
                   /*为左括号将直接导致下一个符号压栈*/
                       lastPRI=0;
               }
               else{
                   while(getPRI(trc=pop(&sign))=curPRI&&trc!=
                       UNIT_TYPE_LC&&checkStack(&sign)){
                       if(!proc(pop(&num),pop(&num),trc,&proctemp))
                           return 0.0;
                       push(&num,proctemp);
                   }
                   push(&sign,trc);
                   /*最外面两个数字出栈,与符号出栈计算再将结果压入*/
                   push(&sign,t.type);
                   lastPRI=curPRI;
               }
               break;
           }
           debugkey(1,t,es,1);
       }
       while(checkStack(&sign)){
           if(!proc(pop(&num),pop(&num),pop(&sign),&proctemp))
               return 0.0;
           push(&num,proctemp);
           debugkey(0,t,es,1);
       }
       
       return pop(&num);
    }
    nt checkExp(char *s){
       Unit r;
       int ret,LCc=0,RCc=0;
       char lastType;
       
       unitRead(s,&r,1);
       /*初始化,指向第一位*//*这函数不用实在可惜*/
       
       if((ret=unitRead(s,&r,0))!=1){
           /*检查之前检查第一个单元*/
           printf("Illegal Expression or Command.n");
           printf(" Type your expression then press ");
           printf("ENTER.n");
           printf(" Type Q to quit,H for Help.n");
           return 0;
       }
       lastType=r.type;
       if(lastType!=UNIT_TYPE_NUM&&lastType!=UNIT_TYPE_LC){
           printf("Illegal entry.n");
           return 0;
       }
       if(lastType==UNIT_TYPE_LC) LCc++;
       while((ret=unitRead(s,&r,0))==1){/*读入返回值为1时才有效*/
           switch(r.type){
           case UNIT_TYPE_NUM:
               if(lastType==UNIT_TYPE_NUM){/*数字前不能为数字*/
                   printf("No operator between 2 numbers.n");
                   return 0;
               }
               break;
           case UNIT_TYPE_LC:    /*为左括号,前不能有数字*/
               if(lastType==UNIT_TYPE_NUM){
                   printf("No operator in front of '('.n");
                   return 0;
               }
               LCc++;
               break;
           case UNIT_TYPE_RC:    /*为右括号,前只能有数字或本身*/
               if(lastType!=UNIT_TYPE_NUM&&lastType!=UNIT_TYPE_RC){

                printf("Illegal operator in front of ')'.n");
                   return 0;
               }
               RCc++;
               break;
           default:            /*为运算符情况,运算符前只能有数字和)*/
               if(lastType!=UNIT_TYPE_NUM&&lastType!=UNIT_TYPE_RC){
                   printf("Double oprator detected.n");
                   return 0;
               }
               break;
           }
           lastType=r.type;
       }
       if(ret==2){
           printf("Illegal char detected!n");
           return 0;
       }
       if(lastType!=UNIT_TYPE_NUM&&lastType!=UNIT_TYPE_RC){
           /*最后一个单元不是数字或)*/
           printf("Illegal operator at the end of expression.n");
           return 0;
       }
       if(LCc!=RCc){
           printf("'(' and ')' not match.");
           return 0;
       }
       return 1;
    }

    void showHelp(int flag){
       clrscr();
       printf("Expression Calculater v %s",VER);
       printf("ntcopyright© 2005 Wuxiao@Cbarnntlicense:nn");
       printf(" This program is free software;you can redistrib");
       printf("ute it and/or modifyn");
       printf(" it under the terms of the GNU General Public Li");
       printf("cense as published byn");
       printf(" the Free Software Foundation;either version 2 o");
       printf("f the License,orn");

            else printf("nEC:");
               gets(exp);
               if(exp[0]=='Q'||exp[0]=='q'){
                   if(debug==1){
                       debug=0;
                       continue;
                   }
                   break;
               }
               if(exp[0]=='h'||exp[0]=='H'){
                   showHelp(1);
                   continue;
               }
               if((exp[0]=='D'||exp[0]=='d')&&exp[1]==0){
                   debug=1;
                   continue;
               }
               if(checkExp(exp))
                   printf("t= %fn",calcu(exp));
           }
           printf("Thanks for using...n");
           return 1;
       }
       else{        /*非命令行模式*/
           if((sFile=fopen(argv[1],"r"))!=NULL){
               /*打开文件成功,真是少见~~*/
               for(i=2;iargc;i++){
                   if(argv[0]=='-'||argv[0]=='/'){
                       if(argv[1]=='o'||argv[1]=='O'){
                           oFileName=argv;
                           oFileName += 2;



                      }
                   }                /*重定位输出文件*/
               }
               if((oFile=fopen(oFileName,"w"))==NULL){
                   printf("Open File for output Error!n");
                   return 0;
               }
               while(!feof(sFile)){        /*检查输入文件*/
                   inchar=fgetc(sFile);
                   if(inchar=='n') chkkey=0;
                   chkkey++;
                   if(chkkey99){
                       printf("Line is two long.n");
                       return 0;
                   }
               }
               rewind(sFile);
               while(!feof(sFile)){
                   fscanf(sFile,"%s",exp);
                   fputs(exp,oFile);
                   if(checkExp(exp))
                       fprintf(oFile,"nt= %fn",calcu(exp));
               }
               fclose(sFile);
               fclose(oFile);
           }
           else{            /*打开文件失败,试图解释成一个算式*/
               exp[0]=0;
               for(i=1;iargc;i++)
                   strcat   (exp,argv);
               if(checkExp(exp))
                   printf("t= %fn",calcu(exp));
               else{        /*无法识别的句式,打印帮助*/
                   showHelp(0);
                   printf("nUsage EC [File][-oOutfile]n");
                   printf("            EC [expression]n");
               }
           }
       }
       
    }


    写一下操作指南:
    直接运行时进入提示符
    EC 这时可用的命令是:
    Q - 退出EC
    H - 显示帮助
    D - 进入Debug模式
    表达式 - 直接计算

    Debug 模式:
    EC-Debug 这时可用的命令是:
    Q - 退出Debug模式
    H - 显示帮助
    表达式 - 计算并调试

    运行调试一条时:(以调试模式运行会发单步形式出现)
    提示符为"-",可用的命令为:
    G - 直接运行,并显示过程
    T - 单步下一个操作
    Q - 无条件返回正常模式,会计算并显示结果,但没有过程

    希望大家喜欢

    读入外部文件进行批处理
    EC srcfile [-o输出文件名] 默认为result.dat
    注意 srcfile里面各个表达式用回车或空格分开

    读入命令行进行计算
    EC expression  
    expression 中可以有空格,EC会忽略

    EC首先尝试用文件名解释,如不行,试用表达式解释,再不行,则打印帮助并退出,这是指命令行带参数的情况下

    如果要完整无损的源码,可以到
    http://post.baidu.com/f?kz=24588719
    与我机子里的原汁原味,(没有被百度的JacaScript处理过的) ^_^

    楼主 2016-03-09 13:47 回复

共有回帖数 0
  • 回 帖
  • 表情 图片 视频
  • 发表

登录直线网账号

Copyright © 2010~2015 直线网 版权所有,All Rights Reserved.沪ICP备10039589号 意见反馈 | 关于直线 | 版权声明 | 会员须知