使用C語言寫的科學計算器,可以實現四則運算、三角函數運算、指對數運算;優先級正確;能智能屏蔽空格,能識別輸入錯誤和運算錯誤,能實現繼續運算、清空運算結果和有效退出的功能
#include#include #include #define INPUT_MAX 1000 #define NODE_MAX 500 #define NUM_OPT 20 #define LEN_OPT 6 #define NUM_OPS 200 typedef enum{ Opd=0, Opt=1 }Type; typedef struct{ int opt; double opd; Type tp; }Node; //括號棧,檢測括號是否匹配 char brackets[NUM_OPS]; int bb=0; int input(Node *in); int translate(char *p,Node *re,int *len); double translateopd(char *p,int *len); int translateopt(char *p,int *len); int cmp(const char *s,const char *d); int calculate(Node *n,double *r); int sclt(int opr,double *opd); int dclt(int opr,double *opd1,double opd2); int prid(int c); /*功能:表達式輸入和轉換 * 接收輸入並翻譯為操作符和操作數存入表達式鏈 *輸入:表達式鏈的地址 *輸出:執行狀態,正確返回1,錯誤返回0 */ int input(Node *in) { //input->string char ins[INPUT_MAX]={0}; int insi=0; char temp_in=0; int len=0; //檢測開頭的空格 while(' '==(ins[0]=getchar())); //檢測是不是直接輸入了一個回車 if(ins[0]!='\n') { do{ temp_in=getchar(); //只能忽略多余空格 if(ins[insi]==' '&&temp_in==' ') continue; ins[++insi]=temp_in; }while(temp_in!='\n'); ins[insi]=0; } insi=0; //輸入回車直接輸出0 if(ins[0]=='\n') in->tp=Opd,in->opd=0.0,in++; else //壓入表達式鏈 while(ins[insi]) { if(translate(ins+insi,in++,&len)) insi+=len; else return 0; } //自動添加等號 if((in-1)->opt!='=') in->opt='=',in->tp=Opt,in++; in->opt=-1,in->tp=Opt; return 1; } /*功能:翻譯字符串為操作數或操作符 *輸入:字符串地址,翻譯返回節點,操作數和操作符長度返回地址 *輸出:翻譯結果狀態 */ int translate(char *p,Node *re,int *len) { if(*p>='0'&&*p<='9') { re->tp=Opd; re->opd=translateopd(p,len); return 1; } else if(*p=='e'||*p=='p') { if(*p=='e') { re->tp=Opd; re->opd=M_E; *len=1; if(p[1]==' ') (*len)++; //十分重要,此處必須加括號 return 1; } else { if(p[1]=='i') { re->tp=Opd; re->opd=M_PI; *len=2; if(p[2]==' ') (*len)++; return 1; } else return 0; } } else { re->tp=Opt; re->opt=translateopt(p,len); if(re->opt) return 1; else return 0; } } /*功能:翻譯操作數 */ double translateopd(char *p,int *len) { int flag=0; int pointnum=1; double temp=0; int i=0; do{ if(!flag&&p[i]!='.') temp=temp*10+p[i++]-'0'; else if(!flag&&p[i]=='.') flag=1,i++; else temp+=(p[i++]-'0')*pow(0.1,pointnum),pointnum++; }while((p[i]>='0'&&p[i]<='9')||p[i]=='.'); if(p[i]==' ') i++; *len=i; return temp; } /*功能:翻譯操作數 * 如果運算符非法,則返回0,合法則返回非零標志 */ int translateopt(char *p,int *len) { char fu[NUM_OPT][LEN_OPT]={"+","-","*","/","^","(",")","sin","cos","tan","asin","acos","atan","ln","lg","="}; int fu_int[NUM_OPT]={'+','-','*','/','^','(',')','s','c','t','s'+'a','c'+'a','t'+'a','n','g','='}; int i=0; for(i=0;i tp==Opt&&n->opt=='-') OPRD[db]=0.0,db++; //Push(&OPRD,0.0); while(1) { //判斷前面有沒有負號 if(n->tp==Opd) { OPRD[db]=n->opd,db++,n++; //Push(&OPRD,n->opd),n++; } else { //雙目運算符 if(prid(n->opt)) { //if(!GetTop(OPRT,&top)) if(tb) top=OPRT[tb-1]; if(!tb) { if(n->opt=='='||n->opt==')') { if(n->opt==')') { bb--; //if(!Pop(&brackets,&temp)) if(bb<0) { printf("Bracket does not match!"); return 0; } } break; } else OPRT[tb]=n->opt,tb++,n++; //Push(&OPRT,n->opt),n++; continue; } if(prid(top)==0) { //Pop(&OPRD,&a); //Pop(&OPRT,&o); db--; a=OPRD[db]; tb--; o=OPRT[tb]; if(sclt(o,&a)) { OPRD[db]=a,db++; //Push(&OPRD,a); continue; } else return 0; } if(prid(top)>=prid(n->opt)) { //Pop(&OPRD,&b); //Pop(&OPRD,&a); //Pop(&OPRT,&o); db--; b=OPRD[db]; db--; a=OPRD[db]; tb--; o=OPRT[tb]; if(dclt(o,&a,b)) { OPRD[db]=a,db++; //Push(&OPRD,a); } else return 0; } else { OPRT[tb]=n->opt,tb++,n++; //Push(&OPRT,n->opt),n++; } } else { //單目運算符和括號 double x=0.0; if(n->opt=='(') { brackets[bb]='(',bb++; //Push(&brackets,'('); if(len=calculate(n+1,&x)) { OPRD[db]=x,db++; //Push(&OPRD,x); n+=len,n++; if(n->tp==Opt&&n->opt==-1) { printf("Bracket does not match!"); return 0; } } else return 0; } else { OPRT[tb]=n->opt,tb++; //Push(&OPRT,n->opt); n++; } } } } *r=OPRD[db-1]; return n-nb+1; } /*功能:單目運算 */ int sclt(int opr,double *opd) { switch(opr) { case 's': *opd=sin(*opd); break; case 'c': *opd=cos(*opd); break; case 't': *opd=tan(*opd); break; case 'a'+'s': if(*opd<-1||*opd>1) { printf("Beyond asin()!"); return 0; } else *opd=asin(*opd); break; case 'a'+'c': if(*opd<-1||*opd>1) { printf("Beyond acos()!"); return 0; } else *opd=acos(*opd); break; case 'a'+'t': if(*opd>-3.141592654/2&&*opd<3.141592654/2) *opd=atan(*opd); else { printf("Beyond atan()!"); return 0; } break; case 'n': if(*opd>0) *opd=log(*opd); else { printf("Beyond ln()!"); return 0; } break; case 'g': if(*opd>0) *opd=log10(*opd); else { printf("Beyond lg()!"); return 0; } break; } return 1; } /*功能:雙目運算 */ int dclt(int opr,double *opd1,double opd2) { switch(opr) { case '+': *opd1 = *opd1+opd2;break; case '-': *opd1 = *opd1-opd2;break; case '*': *opd1 = (*opd1)*opd2;break; case '/': if(opd2>pow(0.1,8)||opd2<0-pow(0.1,8)) *opd1 = (*opd1)/opd2; else { printf("Error 1/0 !"); return 0; } break; case '^': *opd1 = pow(*opd1,opd2);break; } return 1; } /*功能:判斷優先級 */ int prid(int c) { switch(c) { case '+': case '-': case '=': case ')': return 1;break; case '*': case '/': return 2;break; case '^': return 3;break; default :return 0;break; } } int main() { int c=0; while(1) { Node nodes[NODE_MAX]={0}; double r=0.0; //清空括號棧 bb=0; //InitStack(&brackets); printf("Enter: "); //輸入 if(!input(nodes)) { printf("Input Error!"); continue; } //計算 if(calculate(nodes,&r)) { if(bb) { printf("Bracket does not match!"); continue; } if(floor(r)==r) printf("%d",(int)r); else printf("%.4f",r); } c=getchar(); if(c=='q') //退出 break; else if(c=='c') //清屏 system("clear"); if(c!='\n') getchar(); } printf("Quit...\n"); return 0; }