计算器软件----表达式求值
學(xué)完棧寫了一個計算器小程序,
基本功能如下:
1.支持基本的+ - * / % 運算
2.支持sin、cos、tan、ln、log、乘方(^)、開方(sqrt)、指數(shù)(exp) 求值
3.支持括號及括號嵌套
4.支持由以上運算符組和成的長表達式求值
5.支持小數(shù)及負數(shù)
6.支持多位數(shù)運算
7.支持省略最右邊的")":例如“2*(1+2/(1+2”可補全")"并正確求值
8.支持省略"*",例如(1+2)(3+4) 、10sin30、sin30cos60可以正確求值
9.滿足各種用戶的操作習(xí)慣:空格在任何位置都可以出現(xiàn),,出現(xiàn)個數(shù)任意,也可以不出現(xiàn),,如"sin30",,,"sin 30",,"1??+ 2??"
10.如果表達式錯誤不能求值會給出提示而不是退出程序,例如“2-sin*7/+”不能計算會給出提示
11.如果除數(shù)為0或者被開方數(shù)小于零或者ln,log,tan等的操作數(shù)不合理會給出相應(yīng)錯誤提示
12.如果結(jié)果為整數(shù)就用整數(shù)表示,,如果有小數(shù)就保留6為有效數(shù)字
13.支持連續(xù)計算,即算完后接著進行下一次計算
14.支持用戶輸入pi代替3.1415926
15.三角函數(shù)用角度不用弧度
16.輸入"q或Q"鍵退出
代碼公開,歡迎指正
*******模擬計算器||表達式求值*********
**********designed by ma6174**********
*************************************/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
typedef struct s
{//操作數(shù)棧
float data;
struct s *next;
}NUM;
typedef struct ss
{//運算符棧
char data;
struct ss *next;
}OPRT;
//聲明main(),以便在出現(xiàn)錯誤表達式后調(diào)用main()而不退出函數(shù)
int main();
//操作數(shù)進棧
void Push_Num(NUM *l,float n)
{
// printf("Push_Num %f\n",n);
NUM *p;
p=(NUM *)malloc(sizeof(NUM));
p->data=n;
p->next=l->next;
l->next=p;
}
//運算符進棧
void Push_Oprt(OPRT *l,char n)
{
// printf("Push_Oprt %c\n",n);
OPRT *p;
p=(OPRT *)malloc(sizeof(OPRT));
p->data=n;
p->next=l->next;
l->next=p;
}
//操作數(shù)出棧
float Pop_Num(NUM *l)
{
float a;
NUM *p;
/*當(dāng)棧為空時即運算符個數(shù)與數(shù)字個數(shù)相等
或者運算符個數(shù)比數(shù)字個數(shù)多,
肯定是表達式錯誤*/
if(l->next==NULL)
{
printf("\n表達式錯誤!!!\n\n");
int i=300000000;
while(i--);
main();
}
a=l->next->data;
p=l->next;
l->next=p->next;
free(p);
// printf("Pop_Num %f\n",a);
return a;
}
//運算符出棧
void Pop_Oprt(OPRT *l)
{
OPRT *p;
p=l->next;
l->next=p->next;
// printf("Pop_Oprt %c\n",p->data);
free(p);
}
//取得棧頂運算符
char Get_Top_Oprt(OPRT *l)
{
// printf("Get_Top_Oprt %c\n",l->next->data);
return l->next->data;
}
//將運算符轉(zhuǎn)換為對應(yīng)的優(yōu)先級
int change(char c)
{
if(c=='(')return 1;
if(c=='+'||c=='-')return 2;
if(c=='*'||c=='/'||c=='%')return 3;
//S=sin,C=cos,T=tan,L=ln,G=log,@=sqrt,E=exp
if(c=='S'||c=='C'||c=='T'||c=='L'||c=='G'||c=='@'||c=='E')return 4;
if(c=='^')return 5;
return 0;
}
//將原串處理,例如sin ->S
int deal(char *a)
{
int i,len=strlen(a),l=0,r=0;
for(i=0;i<len;i++)
{
//刪除表達式中的空格
if(a[i]==' ')
{
int j=i+1;
for(;j<len;j++)
a[j-1]=a[j];
a[len-1]='#';
len--;
i--;
}
//sin
if(a[i]=='s'&&a[i+1]=='i'&&a[i+2]=='n')
{//將sin轉(zhuǎn)換為S
a[i]='S';
int j=i+3;
for(;j<len;j++)
a[j-2]=a[j];
a[len-1]=a[len-2]='#';//防止最后atof誤判
len-=2;
}
//cos
if(a[i]=='c'&&a[i+1]=='o'&&a[i+2]=='s')
{
a[i]='C';
int j=i+3;
for(;j<len;j++)
a[j-2]=a[j];
a[len-1]=a[len-2]='#';
len-=2;
}
//tan
if(a[i]=='t'&&a[i+1]=='a'&&a[i+2]=='n')
{
a[i]='T';
int j=i+3;
for(;j<len;j++)
a[j-2]=a[j];
a[len-1]=a[len-2]='#';
len-=2;
}
//ln
if(a[i]=='l'&&a[i+1]=='n')
{
a[i]='L';
int j=i+2;
for(;j<len;j++)
a[j-1]=a[j];
a[len-1]='#';
len-=1;
}
//log
if(a[i]=='l'&&a[i+1]=='o'&&a[i+2]=='g')
{
a[i]='G';
int j=i+3;
for(;j<len;j++)
a[j-2]=a[j];
a[len-1]=a[len-2]='#';
len-=2;
}
//sqrt
if(a[i]=='s'&&a[i+1]=='q'&&a[i+2]=='r'&&a[i+3]=='t')
{
a[i]='@';
int j=i+4;
for(;j<len;j++)
a[j-3]=a[j];
a[len-1]=a[len-2]=a[len-3]='#';
len-=3;
}
//exp
if(a[i]=='e'&&a[i+1]=='x'&&a[i+2]=='p')
{
a[i]='E';
int j=i+3;
for(;j<len;j++)
a[j-2]=a[j];
a[len-1]=a[len-2]='#';
len-=2;
}
//在sin30sin30,,,,(1+2)sin30,,,,sin30(1+2),,,,(1+2)(1+2)這樣的表達式之間添加 "*"
if(((a[i-1]>='0'&&a[i-1]<='9')||a[i-1]==')')&&
(a[i]=='S'||a[i]=='C'||a[i]=='T'||a[i]=='L'||a[i]=='G'||a[i]=='@'||a[i]=='E'||a[i]=='('))
{
int j=len;
for(;j>i;j--)
a[j]=a[j-1];
a[i]='*';
len++;
}
if(a[i]=='(')l++;
if(a[i]==')')r++;
}
//在表達式右邊加 ")"來使括號匹配
if(l-r>0)
{
int n=l-r;
while(n--)
{
a[len]=')';
len++;
}
}
return len;
}
int main()
{
char a[1000];
int n,i,len;
system("cls");//清屏
printf("\t\t\t模擬計算器&&表達式求值\n\n");
printf("\t\t支持 + - * / % ^ sqrt log ln sin cos tan exp ()\n\n");
printf("請輸入表達式: ");
while(gets(a)!=NULL)
{
len=deal(a);
// printf("%s\n",a);
int i=0;
//各種錯誤標(biāo)志
int zero_tag=0,tan_tag=0,sqrt_tag=0,ln_tag=0,log_tag=0;
NUM *num;
num=(NUM *)malloc(sizeof(NUM));
num->next=NULL;
OPRT *oprt;
oprt=(OPRT *)malloc(sizeof(OPRT));
oprt->next=NULL;
if(len==0)
{
printf("請輸入表達式: ");
continue;
}
if(len==1&&(a[i]=='q'||a[i]=='Q'))
exit(0);
Push_Oprt(oprt,'#');//作為棧底運算符
if(a[0]=='-')//第一個字符為‘-’時默認(rèn)為負號
{
i=0;
while(a[i]=='-')//刪除所有多余前導(dǎo)負號
i++;
float s=atof(&a[i]);
if(i%2==1)//奇數(shù)個負號
s=-s;
Push_Num(num,s);
i++;
while(a[i]>='0'&&a[i]<='9'||a[i]=='.')
i++;
}
if(a[0]=='+')
{//前面多余的加號(正號)全部忽略
i=0;
while(a[i]=='+')
i++;
}
//開始處理表達式
for(;i<len;i++)
{
if(a[i]>='0'&&a[i]<='9')
{//操作數(shù)直接進棧
Push_Num(num,atof(&a[i]));
while(a[i]>='0'&&a[i]<='9'||a[i]=='.')//尋找下一個運算符
i++;
i--;
continue;
}
if(a[i]=='p'&&a[i+1]=='i')
{//pi轉(zhuǎn)換為3.1415926再進棧
Push_Num(num,3.1415926);
i++;
continue;
}
//‘-’前面不是數(shù)字時肯定是負號而不是運算符 ,‘-’為負號時單獨計算
if(a[i]=='-'&&(a[i-1]>'9'||a[i-1]<'0'))
{
float s=atof(&a[i+1]);
s=-s;
Push_Num(num,s);
i++;
while(a[i]>='0'&&a[i]<='9'||a[i]=='.')
i++;
i--;
continue;
}
// “+”直接忽視
if(a[i]=='+'&&(a[i-1]>'9'||a[i-1]<'0'))
{
i++;
continue;
}
if(change(a[i])>change(Get_Top_Oprt(oprt)))
{//表達式中優(yōu)先級高的運算符進棧
Push_Oprt(oprt,a[i]);
continue;
}
else{
if(a[i]=='('){// '('直接進棧
Push_Oprt(oprt,'(');
continue;
}
if(a[i]==')'){//無條件出棧
while(Get_Top_Oprt(oprt)!='(')
{
float s,aa,b;
aa=Pop_Num(num);
char c;
c=Get_Top_Oprt(oprt);
if(c!='S'&&c!='C'&&c!='T'&&c!='L'&&c!='G'&&c!='@'&&c!='E')
b=Pop_Num(num);
switch(Get_Top_Oprt(oprt)){
case '+':s=aa+b;break;
case '-':s=b-aa;break;
case '*':s=aa*b;break;
case '/':{
if(aa==0)//除數(shù)為0
zero_tag=1;
else
s=b/aa;
break;
}
case '%':s=(int)b%(int)aa;break;
case '^':s=pow(b,aa);break;
case 'S':{
s=sin(aa/180*3.1415926);
break;
}
case 'C':{
s=cos(aa/180*3.1415926);
break;
}
case 'T':{
s=tan(aa/180*3.1415926);
break;
}
case 'L':{
if(aa<=0)
ln_tag=1;
else
s=log(aa);
break;
}
case 'G':{
s=log10(aa);
if(aa<=0)
log_tag=1;
else
break;
}
case '@':{
if(aa<0)
sqrt_tag=1;
else
s=sqrt(aa);
break;
}
case 'E':{
s=exp(aa);
break;
}
}
Pop_Oprt(oprt);
Push_Num(num,s);
}
Pop_Oprt(oprt);
continue;
}
//棧里的優(yōu)先級高的運算符出棧
float s,aa,b;
aa=Pop_Num(num);
char c;
c=Get_Top_Oprt(oprt);
if(c!='S'&&c!='C'&&c!='T'&&c!='L'&&c!='G'&&c!='@'&&c!='E')
b=Pop_Num(num);
switch(Get_Top_Oprt(oprt)){
case '+':s=aa+b;break;
case '-':s=b-aa;break;
case '*':s=aa*b;break;
case '/':{
if(aa==0)
zero_tag=1;
else
s=b/aa;
break;
}
case '%':s=(int)b%(int)aa;break;
case '^':s=pow(b,aa);break;
case 'S':{
s=sin(aa/180*3.1415926);
break;
}
case 'C':{
s=cos(aa/180*3.1415926);
break;
}
case 'T':{
s=tan(aa/180*3.1415926);
break;
}
case 'L':{
if(aa<=0)
ln_tag=1;
else
s=log(aa);
break;
}
case 'G':{
if(aa<=0)
log_tag=1;
else
s=log10(aa);
break;
}
case '@':{
if(aa<0)
sqrt_tag=1;
else
s=sqrt(aa);
break;
}
case 'E':{
s=exp(aa);
break;
}
}
c=Get_Top_Oprt(oprt);
Push_Num(num,s);
Pop_Oprt(oprt);
Push_Oprt(oprt,a[i]);
}
}
//表達式遍歷完畢,棧里的運算符依次出棧
while(Get_Top_Oprt(oprt)!='#')
{
float s,aa,b;
aa=Pop_Num(num);
char c;
c=Get_Top_Oprt(oprt);
if(c!='S'&&c!='C'&&c!='T'&&c!='L'&&c!='G'&&c!='@'&&c!='E')
b=Pop_Num(num);
switch(Get_Top_Oprt(oprt)){
case '+':s=aa+b;break;
case '-':s=b-aa;break;
case '*':s=aa*b;break;
case '/':{
if(aa==0)
zero_tag=1;
else
s=b/aa;
break;
}
case '%':s=(int)b%(int)aa;break;
case '^':s=pow(b,aa);break;
case 'S':{
s=sin(aa/180*3.1415926);
break;
}
case 'C':{
s=cos(aa/180*3.1415926);
break;
}
case 'T':{
if(cos(aa/180*3.1415926)<=0.000001)
tan_tag=1;
s=tan(aa/180*3.1415926);
break;
}
case 'L':{
if(aa<=0)
ln_tag=1;
else
s=log(aa);
break;
}
case 'G':{
if(aa<=0)
log_tag=1;
else
s=log10(aa);
break;
}
case '@':{
if(aa<0)
sqrt_tag=1;
else
s=sqrt(aa);
break;
}
case 'E':{
s=exp(aa);
break;
}
}
Pop_Oprt(oprt);
Push_Num(num,s);
}
if(zero_tag)
printf("\n除以0!!!\n\n");
else if(tan_tag)
printf("\ntan的數(shù)值不合法!!!!!!\n\n");
else if(ln_tag)
printf("\nln的數(shù)值不合法!!!!\n\n");
else if(log_tag)
printf("\nlog的數(shù)值不合法!!!!\n\n");
else if(sqrt_tag)
printf("\nsqrt的數(shù)值不合法!!!!!\n\n");
else{
float ans=Pop_Num(num);//結(jié)果在棧底
if(ans-(int)ans==0)
printf("計算結(jié)果: %d\n\n",(int)ans);
else
printf("計算結(jié)果: %f\n\n",ans);
}
printf("請輸入表達式: "); //繼續(xù)計算
}
return 0;
}
?
?
總結(jié)
以上是生活随笔為你收集整理的计算器软件----表达式求值的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Struts2+JSON特别让人恶心的一
- 下一篇: ubuntu 11.10上安装osdly