共有回帖数 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 回复
Copyright © 2010~2015 直线网 版权所有,All Rights Reserved.沪ICP备10039589号
意见反馈 |
关于直线 |
版权声明 |
会员须知