• 计算器软件表达式求值


    学完栈写了一个计算器小程序,
    基本功能如下:
    1.支持基本的+ - * / % 运算
    2.支持sin、cos、tan、ln、log、乘方(^)、开方(sqrt)、指数(exp) 求值
    3.支持括号及括号嵌套
    4.支持由以上运算符组和成的长表达式求值
    5.支持小数及负数
    6.支持多位数运算
    7.支持省略最右边的")":例如“2*(1+2/(1+2”可补全")"并正确求值
    8.支持省略"*",例如(1+2)(3+4) 、10sin30、sin30cos60可以正确求值
    9.满足各种用户的操作习惯:空格在任何位置都可以出现,,出现个数任意,也可以不出现,,如"sin30",,,"sin 30",,"1  + 2  "
    10.如果表达式错误不能求值会给出提示而不是退出程序,例如“2-sin*7/+”不能计算会给出提示
    11.如果除数为0或者被开方数小于零或者ln,log,tan等的操作数不合理会给出相应错误提示
    12.如果结果为整数就用整数表示,,如果有小数就保留6为有效数字
    13.支持连续计算,即算完后接着进行下一次计算
    14.支持用户输入pi代替3.1415926
    15.三角函数用角度不用弧度
    16.输入"q或Q"键退出

    代码公开,欢迎指正

    View Code
    /**************************************** 
    *******模拟计算器||表达式求值*********
    **********designed by ma6174**********
    ************************************
    */
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include<math.h>
    typedef struct s
    {//操作数栈
    float data;
    struct s *next;
    }NUM;
    typedef struct ss
    {//运算符栈
    char data;
    struct ss *next;
    }OPRT;
    //声明main(),以便在出现错误表达式后调用main()而不退出函数
    int main();
    //操作数进栈
    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;
    }
    //操作数出栈
    float Pop_Num(NUM *l)
    {
    float a;
    NUM *p;
    /*当栈为空时即运算符个数与数字个数相等
    或者运算符个数比数字个数多,
    肯定是表达式错误
    */
    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;
    }
    //将运算符转换为对应的优先级
    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转换为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;
    //各种错误标志
    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]=='-')//第一个字符为‘-’时默认为负号
    {
    i=0;
    while(a[i]=='-')//删除所有多余前导负号
    i++;
    float s=atof(&a[i]);
    if(i%2==1)//奇数个负号
    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')
    {//操作数直接进栈
    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转换为3.1415926再进栈
    Push_Num(num,3.1415926);
    i++;
    continue;
    }
    //‘-’前面不是数字时肯定是负号而不是运算符 ,‘-’为负号时单独计算
    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)))
    {//表达式中优先级高的运算符进栈
    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)//除数为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;
    }
    //栈里的优先级高的运算符出栈
    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的数值不合法!!!!!!\n\n");
    else if(ln_tag)
    printf("\nln的数值不合法!!!!\n\n");
    else if(log_tag)
    printf("\nlog的数值不合法!!!!\n\n");
    else if(sqrt_tag)
    printf("\nsqrt的数值不合法!!!!!\n\n");
    else{
    float ans=Pop_Num(num);//结果在栈底
    if(ans-(int)ans==0)
    printf("计算结果: %d\n\n",(int)ans);
    else
    printf("计算结果: %f\n\n",ans);
    }
    printf("请输入表达式: "); //继续计算
    }
    return 0;
    }


     

  • 相关阅读:
    封装cookie
    敏感词过滤
    面向对象改成选项卡
    正则表达式
    cookie
    DOM
    系统对象
    cookie记录用户名
    6个原则
    23中设计模式
  • 原文地址:https://www.cnblogs.com/ma6174/p/2278028.html
Copyright © 2020-2023  润新知