zoukankan      html  css  js  c++  java
  • NYOJ 35 表达式求值 (字符串处理)

    题目链接

    描述

    ACM队的mdd想做一个计算器,但是,他要做的不仅仅是一计算一个A+B的计算器,他想实现随便输入一个表达式都能求出它的值的计算器,现在请你帮助他来实现这个计算器吧。

    比如输入:“1+2/4=”,程序就输出1.50(结果保留两位小数)

    • 输入
      第一行输入一个整数n,共有n组测试数据(n<10)。每组测试数据只有一行,是一个长度不超过1000的字符串,表示这个运算式,每个运算式都是以“=”结束。这个表达式里只包含+-*/与小括号这几种符号。其中小括号可以嵌套使用。数据保证输入的操作数中不会出现负数。数据保证除数不会为0
    • 输出
      每组都输出该组运算式的运算结果,输出结果保留两位小数。
    • 样例输入
      21.000+2/4=((1+2)*5+1)/4=
    • 样例输出
      1.504.00

    分析:

    数据结构栈的应用,对于一个中缀表达式,我们如果想要计算这个表达式的值的话,可以先将这个中缀表达式转换为后缀形式,然后再用后缀表达式进行计算。

    中缀转后缀,定义一个栈存放操作符,一个字符数组存储转换后的后缀形式,转换满足

    如果是数字或者'.'的话直接放到后缀表达式中(存点是因为可能有小数),

    如果是操作符'('的话就将该操作符直接入栈,如果是操作符')'的话,就将栈顶操作符依次放到后缀表达式中,直到栈顶元素为'('为止,

    如果说其他操作符的话,就将该操作符与栈顶操作符的优先级进行比较,当栈顶元素的优先级比该操作符大,就将栈顶元素放到后缀表达式中,当前的操作符入栈

    后缀表达式的计算,定义一个操作数栈,存放后缀中取得的操作数,遇到操作符的话,就将栈中的两个元素出栈计算后在讲结果入栈。

    代码:

        #include<stdio.h>
        #include<iostream>
        #include<stack>
        #include<string.h>
        #include<stdlib.h>
        using namespace std;
        char zhong[1000];///存储输入进去的中缀表达式
        char hou[1000];///中缀转换后的后缀表达式
        int pri[300];///定义相关操作符的优先级
        void tran(char zhong[],char hou[])///中缀转后缀
        {
            stack<char>flag;///定义一个栈,存储操作符
            int k=0;
            flag.push('=');///首先把'='加入到栈中,起到一个压栈的作用,是为了即使是第一个操作符进栈的话,也比栈顶元素的优先级高,可以直接入栈
            for(int i=0; zhong[i]!='='; i++)
            {
                if(zhong[i]>='0'&&zhong[i]<='9'||zhong[i]=='.')///可能有小数的情况
                {
                    hou[k++]=zhong[i];
                }
                else
                {
                    hou[k++]='#';///起到将操作数与运算符相分离的作用
                    if(zhong[i]=='(')///左括号直接入栈
                        flag.push(zhong[i]);
                    else if(zhong[i]==')')///如果是右括号的话
                    {
                        while(flag.top()!='(')///就一直找到与他相匹配的左括号
                        {
                            hou[k++]=flag.top();
                            flag.pop();
                        }
                        flag.pop();
                    }
                    else
                    {
                        while(pri[flag.top()]>=pri[zhong[i]])///比较当前操作符与栈顶操作符的优先级,栈顶元素的优先级比较大的话,就出栈
                        {
                            hou[k++]=flag.top();
                            flag.pop();
                        }
                        flag.push(zhong[i]);///然后把当前的操作符入栈
                    }
        
                }
            }
            while(flag.top()!='=')///最后栈中的所有操作符都入后缀序列
            {
                hou[k++]=flag.top();
                flag.pop();
            }
            hou[k]='';
        }
        
        double Suan(char hou[])///计算后缀
        {
            stack<double>shu;///存放操作数
            char chun[50];
            //  memset(chun,'',sizeof(chun));
            int k=0;
            for(int i=0; hou[i]!=''; i++)
            {
                if(hou[i]>='0'&&hou[i]<='9'||hou[i]=='.')
                {
                    chun[k++]=hou[i];
                }///将当前这个数取出来
                else
                {
                    if(k!=0)
                    {
                        shu.push(atof(chun));///将这个字符串类型的数转换为double类型,并入栈 
                        memset(chun,'',sizeof(chun));
                        k=0;
                    }
                    if(hou[i]!='#')///如果是操作符的话,就将栈中的两个操作数出栈再将计算后的结果入栈
                    {
                        double a,b,c;
                        a=shu.top();
                        shu.pop();
                        b=shu.top();
                        shu.pop();
                        switch(hou[i])
                        {
                        case '+':
                            c=a+b;
                            shu.push(c);
                            break;
                        case '-':
                            c=b-a;
                            shu.push(c);
                            break;
                        case '*':
                            c=a*b;
                            shu.push(c);
                            break;
                        case '/':
                            c=b/a;
                            shu.push(c);
                            break;
                        }
                    }
        
                }
            }
            return shu.top();
        }
        int main()
        {
            int n;
            scanf("%d",&n);
            pri['=']=-1;///定义优先级最低,只是起到一个压栈的作用
            pri['(']=0;
            pri['+']=1;
            pri['-']=1;
            pri['*']=2;
            pri['/']=2;
            pri[')']=3;
            while(n--)
            {
                scanf(" %s",zhong);
                tran(zhong ,hou);
               // cout<<hou<<endl;
                printf("%.2lf
    ",Suan(hou));
            }
        
            return 0;
        }
    
  • 相关阅读:
    Windows Azure Storage (17) Azure Storage读取访问地域冗余(Read Access – Geo Redundant Storage, RA-GRS)
    SQL Azure (15) SQL Azure 新的规格
    Azure China (5) 管理Azure China Powershell
    Azure China (4) 管理Azure China Storage Account
    Azure China (3) 使用Visual Studio 2013证书发布Cloud Service至Azure China
    Azure China (2) Azure China管理界面初探
    Azure China (1) Azure公有云落地中国
    SQL Azure (14) 将云端SQL Azure中的数据库备份到本地SQL Server
    [New Portal]Windows Azure Virtual Machine (23) 使用Storage Space,提高Virtual Machine磁盘的IOPS
    Android数据库升级、降级、创建(onCreate() onUpgrade() onDowngrade())的注意点
  • 原文地址:https://www.cnblogs.com/cmmdc/p/6729598.html
Copyright © 2011-2022 走看看