スペースを含む式を評価する


制限時間:3000ミリ秒|メモリ制限:65535キロバイトの
難易度:4
説明
ACMチームのMDDが電卓になりたいが、何彼は唯一のA + Bの計算を計算されていない、彼はランダムに1を入力したい関係しています式でその価値を見つけることができる電卓。今度は彼がこの電卓を実現するのを手伝ってください。
次のような入力: "1 + 2/4 ="、プログラムは入力整数nの最初の行の1.50(小数点以下2桁の結果)
入力
出力します。テストデータのグループはn個あります(n <10)。
テストデータの各グループには、この式を表す1000以下の文字列である1行しかありません。各式は「=」で終わります。この式には、+-* /と括弧のみが含まれます。括弧はネストできます。データは、入力オペランドに負の数がないことを保証します。
データは、除数が0にならないことを保証します。

 

 

これは私たちのojにとって問題ですが、それは非常に制限されています。つまり、式にスペースがある場合に式の値を通常どのように計算するかです。

 

式にスペースが含まれているプログラムを克服することはできません。


#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include<stack>
#include<string.h>
using namespace std;
bool IsOperator(char ch);
char Precede(char opr1, char opr2);
double Operate(double opnd1, char op, double opnd2);
int ConvertToIndex(char opr);
/**
  这个是用来判断一个字符是不是
  操作符的
*/
bool IsOperator(char ch)
{
    if (ch == '+' || ch == '-' ||
            ch == '*' || ch == '/' ||
            ch == '(' || ch == ')' || ch == '=')
        return true;
    else
        return false;

}

//运算符的优先关系
//'+', '-', '*', '/', '(', ')', '#'
char OprRelation[7][7] = {
   
   {'>', '>', '<', '<', '<', '>', '>'}, //'+'
    {'>', '>', '<', '<', '<', '>', '>'}, //'-'
    {'>', '>', '>', '>', '<', '>', '>'}, //'*'
    {'>', '>', '>', '>', '<', '>', '>'}, //'/'
    {'<', '<', '<', '<', '<', '=', ' '}, //'('
    {'>', '>', '>', '>', ' ', '>', '>'}, //')'
    {'<', '<', '<', '<', '<', ' ', '='}
};//'#'
/**
   这个是用来获取每一个操作符的优先级
*/
int ConvertToIndex(char opr)
{
    int index;

    switch (opr)
    {
    case '+':
        index = 0;
        break;
    case '-':
        index = 1;
        break;
    case '*':
        index = 2;
        break;
    case '/':
        index = 3;
        break;
    case '(':
        index = 4;
        break;
    case ')':
        index = 5;
        break;
    case '=':
        index = 6;
        break;
    }

    return index;
}
/**
   这个是用来获取连个字符的优先级
*/
char Precede(char opr1, char opr2)
{
    int index1 = ConvertToIndex(opr1);
    int index2 = ConvertToIndex(opr2);

    return OprRelation[index1][index2];
}
/**
    这个是用来对两个数进行求值
*/
double Operate(double opnd1, char op, double opnd2)
{
    double ret;

    switch(op)
    {
    case '+':
        ret = opnd1 + opnd2;
        break;
    case '-':
        ret = opnd1 - opnd2;
        break;
    case '*':
        ret = opnd1 * opnd2;
        break;
    case '/':
        ret = opnd1 / opnd2;
        break;
    }

    return ret;
}

//算符优先算法
double CaculateExpression(string exp)
{
    stack<char> optr; //只处理+ - # / ()运算
    stack<double> opnd;  //只处理0-9的整数运算
    char ch;
    int i = 0;
    optr.push('=');
    ch = exp[i++];
    bool flag = true;
    //如果##配对,表达式求值完成
    while (flag&&(ch != '=' || optr.top() != '='))
    {
        if (!IsOperator(ch))
        {
            string f,g;
            f=exp[i-1];
            g.append(f);
            while(!IsOperator(exp[i]))
            {
                f=exp[i];
                g.append(f);
                ++i;
            }
            double value = atof(g.c_str());
            //操作数入栈
            opnd.push(value);
            ch = exp[i++];
        }
        else
        {
            //比较栈顶操作符和新取得的操作符的优先关系
            cout<<optr.top()<<"   "<<ch<<endl;
            cout<<Precede(optr.top(),ch)<<endl;
            switch (Precede(optr.top(), ch))
            {
            case '<'://栈顶优先权低
                optr.push(ch);
                ch = exp[i++];
                break;
            case '='://括号配对,栈顶括号弹出
                optr.pop();
                if(exp.length()==i)
                {
                    flag=false;
                }
                else
                {
                    ch = exp[i++];
                }
                break;
            case '>'://栈顶优先权高,先弹出,计算,结果操作数入栈
                char op = optr.top();
                optr.pop();
                double num2 = opnd.top();//第二个操作数在前
                opnd.pop();
                double num1 = opnd.top();
                opnd.pop();

                double ret = Operate(num1, op, num2);

                opnd.push(ret);
                break;
            }
        }
    }//end of while
//    cout<<ch<<"   "<<optr.top()<<endl;

    //操作数栈的唯一元素即为计算结果
    return opnd.top();
}


int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        char str[1000];
        scanf("%s",str);
        // strcat(str,"#");
        string f;
        f=str;
        //cout<<atof(f.c_str())<<endl;
        printf("%.2lf\n",CaculateExpression(f));

    }
    return 0;
}

 

式にスペースを入れてプログラムを克服します。

#include<stdio.h>
#include<string>
#include<string.h>
#include<iostream>
#include<stack>
#include<stdlib.h>
using namespace std;
stack<double> num;
stack<char> optr;
//                 +   -   *   /   (   )  =
char opt[7][7]= {'>','>','<','<','<','>','>', // +
                 '>','>','<','<','<','>','>',// -
                 '>','>','>','>','<','>','>',// *
                 '>','>','>','>','<','>','>',// /
                 '<','<','<','<','<','=','>',// (
                 '>','>','>','>','>','>','>', // )   // 不可能放进去的
                 '<','<','<','<','<','<','=' // =
                };
double rel_two(double a,char b,double c)
{
    switch(b)
    {
    case '+':
        return a+c;
    case '-':
        return a-c;
    case '*':
        return a*c;
    case '/':
        return a/c;
    }
}
bool is_optr(char& ch)
{
    if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')'||ch=='=')
    {
        return true;
    }
    else
        return false;

}
int pri(char _pri)
{
    switch(_pri)
    {
    case '+':
        return 0;
    case '-':
        return 1;
    case '*':
        return 2;
    case '/':
        return 3;
    case '(':
        return 4;
    case ')':
        return 5;
    case '=':
        return 6;

    }
}
char priority(char a,char b)
{
    int a1,b1;
    a1=pri(a);
    b1=pri(b);
    return opt[a1][b1];

}
double cal(string exp)
{
    optr.push('=');
    int i=0;
    char ch=exp[i++];
    while((optr.top()!='=' || ch!='=' )&& ch!='\0')
    {
        if(ch!=' ')
        {
            if(is_optr(ch))
            {
//                cout<<ch<<endl;
 cout<<optr.top()<<"     "<<ch<<endl;
 cout<<priority(optr.top(),ch)<<endl;
                switch(priority(optr.top(),ch))
                {

                case '<':
                    optr.push(ch);
//                    cout<<optr.top()<<"     "<<ch<<endl;
                    ch=exp[i++];
                    break;
                case '=':
                    optr.pop();
                    ch=exp[i++];
                    break;
                case '>':
                    char ch1;
                    ch1=optr.top();
//                    cout<<ch1<<endl;
                    optr.pop();
                    double a,b;
                    b=num.top();
                    num.pop();
                    a=num.top();
//                    cout<<a<<b<<endl;
                    num.pop();
                    num.push(rel_two(a,ch1,b));
//                    cout<<num.top()<<endl;
//                    ch=exp[i++];  //  栈顶元素需要依次和ch比较优先级
                    break;

                }

            }
            else
            {
                string p,q;
                q=ch;
                p.append(q);
//                while(!is_optr(ch)&&ch!=' ')
                while(!is_optr(exp[i])&&exp[i]!=' ')
                {
//                    q=exp[i];               // error occur!
                    p.append(q);
                    i++;
                }
//                cout<<p<<endl;
                ch=exp[i++];
                num.push(atof(p.c_str()));
//                cout<<atof(p.c_str())<<endl;
//                cout<<p<<endl;

            }

        }
        else
        {
            ch=exp[i++];
        }
    }

    return num.top();
}
int main()
{
    int n;
    scanf("%d",&n);
    getchar();
    while(n--)
    {
        char s[100];
        gets(s);
        string s1;
        s1=s;
//        cout<<s<<endl;
//        cout<<atoi(s1.c_str())<<endl;
        cout<<cal(s1.c_str())<<endl;
    }

}


出力結果:

おすすめ

転載: blog.csdn.net/nyist_yangguang/article/details/114583819