当前位置: 代码迷 >> C语言 >> 请同时具有耐心和热心的版主进来看一下!!!
  详细解决方案

请同时具有耐心和热心的版主进来看一下!!!

热度:222   发布时间:2004-11-04 20:57:00.0
请同时具有耐心和热心的版主进来看一下!!!

我写了个计算器的程序(还未完善所有功能!),遇到点问题,主要是计算结果(有时对有时错)

我查了很久,也未果!故请版主们来看一下,谢啦!

程序如下:

#define MAX 100 #include<stdio.h> #include<stdlib.h> #include<math.h> typedef struct { float value;//数值 char charc[5];//运算符 }link;//结构体用于存放处理后的表达式(即是数值与运算符的集合) float operS(float c)//求一个数的开方 { float temp; temp=sqrt(c); return(temp); }

int operA(int a,int b)//求排列 { int i,sn; sn=1; for(i=a;i>=a-b+1;i--) sn=sn*i; return(sn); }

int operC(int a,int b)//求组合 { int temp,i,sn,tn; sn=1; for(i=a;i>=a-b+1;i--) sn=sn*i; tn=1; for(i=b;i>0;i--) tn=tn*i; temp=sn/tn; return(temp); }

int operX(int a,int b)//求a的b次方 { int i,sn=1; for(i=1;i<=b;i++) sn=sn*a; return(sn); }

int operN(int a)//求阶乘 { int i,sn; sn=1; for(i=a;i>0;i--) sn=sn*i; return(sn); }

calculation(link exp[],int k)//计算求值 { int i,j,t; for(i=1;i<=k;i++) for(j=1;exp[i].charc[j]!='#';j++)//即是后缀表达式中数值后面跟有运算符的就求值 switch(exp[i].charc[j]) { case'+':for(t=i-1;exp[t].value!=0&&t>0;t--)//向前看第一个exp[t].value不为0的值 { exp[i].value=exp[t].value+exp[i].value; exp[t].value=0;//计算之后便把它置0,新值保留在exp[i].value中 break; } case'-':for(t=i-1;exp[t].value!=0&&t>0;t--)//四则计算 { exp[i].value=exp[t].value-exp[i].value; exp[t].value=0; break; } case'*':for(t=i-1;exp[t].value!=0&&t>0;t--) { exp[i].value=exp[t].value*exp[i].value; exp[t].value=0; break; } case'/':for(t=i-1;exp[t].value!=0&&t>0;t--) { exp[i].value=exp[t].value/exp[i].value; exp[t].value=0; break; } } printf("表达式的值为:\n"); printf("%f",exp[k].value); }

void turn()//将表达式转换成后缀表达式,在这一过程中还求出了S(),A(),C()等的值 { int i,j,k,t,top,num,temp,sum1,sum2; float sum,su,tem; char expr[MAX],stack[MAX];//expr[]内放初始表达式,stack[]用作符号栈 link exp[MAX]; i=0;k=0;t=0;top=1;//k为表达式所含数值个数 printf("请输入要求值的表达式:\n"); do { i++; scanf("%c",&expr[i]); }while(expr[i]!='#'&&i<=MAX);//输入表达式 num=i; printf("原表达式为:\n"); for(i=1;i<=num;i++) printf("%c",expr[i]); printf("\n"); i=1; while(expr[i]!='#') { switch(expr[i]) { case'S':sum=0.0;su=0.0;tem=0.1;//是求S()的 i=i+2; while(expr[i]>='0'&&expr[i]<='9')//可能是小数 { sum=sum*10+expr[i]-48; i++; } if(expr[i]=='.') { i++; while(expr[i]>='0'&&expr[i]<='9') { su=su+(expr[i]-48)*tem; tem=tem*(0.1); i++; } } i++; sum=sum+su; exp[++k].value =operS(sum);//放入exp[]中 sum=0.0;su=0.0;//重新置0 break; case'A':sum1=0;sum2=0;t1=0;t2=0;//是求排列的 for(i=i+2;expr[i]!=',';i++)//前一个数 { t1++; sum1=sum1*10+expr[i]-48;; } for(i=i+1;expr[i]!=')';i++)//后一个数 { t2++; sum2=sum2*10+expr[i]-48; } i++; exp[++k].value=operA(sum1,sum2);//求值并保存 break; case'C':sum1=0;sum2=0;t1=0;t2=0;//求组合 for(i=i+2;expr[i]!=',';i++)//前一个数 { t1++; sum1=sum1*10+expr[i]-48; } for(i=i+1;expr[i]!=')';i++)//后一个数 { t2++; sum2=sum2*10+expr[i]-48; } i++; exp[++k].value=operC(sum1,sum2); break; case'^':sum1=0;sum2=0;t1=0;t2=0;temp=1;//求次方 for(j=i-1;expr[j]>='0'&&expr[j]<='9';j--)//基数 { t1++; sum1=sum1+(expr[j]-48)*temp; temp=temp*10; } for(i=i+1;expr[i]>='0'&&expr[i]<='9';i++)//幂 { t2++; sum2=sum2*10+expr[i]-48; } k--; exp[++k].value=operX(sum1,sum2); break; case'!':sum1=0;t1=0;temp=1;//阶乘 for(j=i-1;expr[j]>'0'&&expr[j]<'9';j--) { t1++; sum1=sum1+(expr[j]-48)*temp; temp=temp*10; } i++; k--; exp[++k].value=operN(sum1); break; case'(':stack[++top]=expr[i++];//当前是左括号便进栈 break; case')':while(stack[top]!='('&&top!=1)//当前是右括号则把栈内所有运算符出栈 exp[k].charc[++t]=stack[top--]; top--;//左括号也出栈 i++; break; case'*': case'/':while(stack[top]=='*'||stack[top]=='/')//当前是*或/,如果栈顶是*或/则把栈顶出栈 exp[k].charc[++t]=stack[top--]; stack[++top]=expr[i++]; break; case'+': case'-':while(stack[top]!='('&&top!=1)//当前是+或-则把比它优先级高的运算符(既*或/)出栈 exp[k].charc[++t]=stack[top--]; stack[++top]=expr[i++]; break; default:sum=0.0;su=0.0;tem=0.1;//当前是数字则直接进栈 while(expr[i]>='0'&&expr[i]<='9') { sum=sum*10+expr[i]-48;//整数部分 i++; } if(expr[i]=='.')//小数部分 { i++; while(expr[i]>='0'&&expr[i]<='9') { su=su+(expr[i]-48)*tem; tem=tem*(0.1); i++; } } exp[++k].value=sum; exp[k].charc[++t]='#';//后缀表达式中数字后面没有运算符的话便把#放到exp[].charc[1]中 t=0; break; } } while(top!=1)//把栈内剩下的运算符出栈 exp[k].charc[++t]=stack[top--]; exp[k].charc[++t]='#'; printf("转换成后缀表达式并放入表后的分布:\n"); for(i=1;i<=k;i++) printf("%10f",exp[i].value); printf("\n"); for(i=1;i<=k;i++) for(j=1;exp[i].charc[j]!='#'&&j<5;j++) if(exp[i].charc[j]=='+'||exp[i].charc[j]=='-'||exp[i].charc[j]=='*'||exp[i].charc[j]=='/') printf("%3c",exp[i].charc[j]); printf("%c%c",exp[1].charc[1],exp[2].charc[1]);//输出后缀表达式中数值和运算符 printf("\n"); calculation(exp,k);//调用子函数进行计算求值 }

务必请哪为好心的版主花点时间看一下,给我指出错误在哪???(程序可运行,主函数很简单,就是调用子函数turn())

衷心感谢!!!

搜索更多相关的解决方案: 版主  热心  耐心  

----------------解决方案--------------------------------------------------------

如果是结果不对,就应该是你算法的问题了,仔细看看!!!


----------------解决方案--------------------------------------------------------

若是算法问题,那就只可能出现在计算求值函数calculation里,因为前面的中缀表达式转换成后缀表达式的结果总是正确的,

但我都看了几次了,还是没发现哪出了问题!

版主啊,你若是有空的话,就帮我看一下喽!


----------------解决方案--------------------------------------------------------
简化你的程式,只把主函数与错误的部分贴上来,运行正确的部分删去,再一个,子函数从简,要让人一眼就能看明白。不然,谁有那么多精力来查看你那上百行的程式?
----------------解决方案--------------------------------------------------------
晕晕的……
----------------解决方案--------------------------------------------------------

我重新看了一遍,在calculation函数里面出了点问题,但也只是解决了一部分!

calculation函数如下:

calculation(link exp[],int k) { int i,j,t=0; i=1; while(i<=k) { if(exp[i].charc[1]!='#') { for(j=1;exp[i].charc[j]!='#';j++) switch(exp[i].charc[j]) { case'+':t=i-1; while(t>0) { if(exp[t].value==0) t--; else { exp[i].value=exp[t].value+exp[i].value; exp[t].value=0; break; } }//while end case'-':t=i-1; while(t>0) { if(exp[t].value==0) t--; else { exp[i].value=exp[t].value-exp[i].value; exp[t].value=0; break; } }//while end case'*':t=i-1; while(t>0) { if(exp[t].value==0) t--; else { exp[i].value=exp[t].value*exp[i].value; exp[t].value=0; break; } }//while end case'/':t=i-1; while(t>0) { if(exp[t].value==0) t--; else { exp[i].value=exp[t].value/exp[i].value; exp[t].value=0; break; } }//while end }//switch end i++; }//if end else i++; }//while end printf("表达式的值为:\n"); printf("%f",exp[k].value); }

虽然turn函数总是能得到正确的结果,但我总觉得它有问题!

它里面的变量k的值一直在变化,每执行一条语句就加1,但最后却又是正确的个数!我跟踪了几遍都没弄明白

turn函数已经在上面有了,我就不贴了,免得...

总之谢谢以上几位,因为总还有人看了偶的!谢啦!

如果下一贴有谁能跟我指出哪里错了...那就太....好了!

合乎!


----------------解决方案--------------------------------------------------------
  相关解决方案