蓝桥杯---公式解析


在某些应用中,为了支持灵活性,往往用到自定义的公式。

比如,有如下的原始公式集合:

    int add(int x, int y):  返回x与y的和
    
    int add(int x, int y, int z):  返回x,y,z三个数的和
    
    int min(int x, int y):  返回x,y中较小的值
    
    int max(int x, int y):  返回x,y中较大的值

    int doubleMe(int x):  返回 x 的2倍

给出一个自定义公式串

add(min(5,3),max(2,8),add(1,doubleMe(1)))

通过手工计算可以得出结果为:14

本题的任务是:编写一个解析程序,能够对由上述原始公式任意组合出来的公式计算其结果。也就是输入一个自定义公式串,输出它的计算结果(可以不考虑输入公式本身有语法错误的情况)。

输入的公式串中可以含有多余的空格,类似:

add( min(5, 3) , max(2 , 8) )  也是合法的公式。

程序输入:公式串
程序输出:该公式的计算值




解题思路:思路相对来说比较简单,以前做过好几道这样的题目,但是这是第一次完全自己写的,其实就是用递归的思路,不过要做递归,思路一定是需要清晰的,否则在递归的时候很容易出错,并且出了错还是不好查找的,另外的一个重要的事情就是必须要设定好正确的递归出口,深切体验。。。


具体思路,在每一次的时候都是从第一个字母开始搜索,当遇到关键的字眼,也就是add、min、max、doubleMe的时候就就开始分割,直到出现的左括号‘(’的数目和右括号‘)’的数目相同,并且出现了部分的结束标志,也就是再一个’)‘或者是’,‘,这样的话就把每一部分分解开了,但是这样的话代码好像就不太美观了,有点长。。。

#include <iostream>
#include <cstdio>
#include <memory.h>
using namespace std;
int count(string str){
    int len = str.length();
	if(str[0]<='9'&&str[0]>='0'){
	  int temp=0,i=0;
	  temp=str[i++]-'0';
	  while(i<len&&str[i]<='9'&&str[i]>='0'){
	   temp=temp*10+str[i]-'0';
	   i++;
	   }
	  return temp;
	}
	if(str[0]=='a'){
	   int i=4,templ=0,tempr=0,tmp=0;
	   for(int x=1;x<=3&&i<len;x++,i++){
	   	 string s="";
	     while(   templ!=tempr|| (  str[i]!=',' && str[i]!=')'    )      ){
	   	 if(str[i]=='(') templ++;
	   	 if(str[i]==')') tempr++;
	   	 s+=str[i];
	     i++;
	   }
	   tmp+=count(s);
	   }
	  return tmp;
	}
	if(str[0]=='m'&&str[1]=='i'){
	   int i=4,templ=0,tempr=0,tmp1=0,tmp2=0;
	   for(int x=1;x<=2&&i<len;x++,i++){
	   	 string s="";
	     while(   templ!=tempr|| (  str[i]!=',' && str[i]!=')'    )      ){
	   	 if(str[i]=='(') templ++;
	   	 if(str[i]==')') tempr++;
	   	 s+=str[i];
	     i++;
	    }
	   x==1?tmp1=count(s):tmp2=count(s);
	   }
	  return tmp1<tmp2?tmp1:tmp2;
	}
	if(str[0]=='m'&&str[1]=='a'){
	   int i=4,templ=0,tempr=0,tmp1=0,tmp2=0;
	   for(int x=1;x<=2&&i<len;x++,i++){
	   	 string s="";
	     while(   templ!=tempr|| (  str[i]!=',' && str[i]!=')'    )      ){
	   	 if(str[i]=='(') templ++;
	   	 if(str[i]==')') tempr++;
	   	 s+=str[i];
	     i++;
	    }
	   x==1?tmp1=count(s):tmp2=count(s);
	   }
	  return tmp1>tmp2?tmp1:tmp2;
	}
	if(str[0]=='d'){
	   int i=9,templ=0,tempr=0;
	   	 string s="";
	     while(   templ!=tempr|| (  str[i]!=',' && str[i]!=')'    )      ){
	   	 if(str[i]=='(') templ++;
	   	 if(str[i]==')') tempr++;
	   	 s+=str[i];
	     i++;
	    }
	  return count(s)*2;
	}
return 0;
}
int main()
{
   string str;
   char ch='
';
   while(ch=='
'){
        str="";
       while(~scanf("%c",&ch)&&ch!='
')
         if(ch!=' ')
          str+=ch;
   int len = str.length();
   cout<<count(str)<<endl;
  }
return 0;
}

稍微修改了一下,这样好像美观一点,但是换汤不换药,只是函数更加明确了点。。。

#include <iostream>
#include <cstdio>
#include <memory.h>
using namespace std;
string s;//记录当前切割出的子串 
int cut(string str,int i){ //返回当前已经搜索完了的str的i的下一个位置 
	s="";
	int templ=0,tempr=0;
    while( templ!=tempr|| (  str[i]!=',' && str[i]!=')'  )  ){
	  if(str[i]=='(') templ++;
	  if(str[i]==')') tempr++;
	  s+=str[i];
	  i++;
	}
	return i+1;
}
int count(string str){
    int len = str.length();
    int  tmp1=0,tmp2=0,temp=0,tmp=0; //tmp1,tmp2比较大小时记录两个数  temp记录返回数的时候的值, tmp记录求和的时候的和 
	if(str[0]<='9'&&str[0]>='0'){
	  int i=0;  //记录遍历的起始位置 
	  temp=str[i++]-'0';
	  while(i<len&&str[i]<='9'&&str[i]>='0'){
	   temp=temp*10+str[i]-'0';
	   i++;
	   }
	  return temp;
	}
	if(str[0]=='a'){//实现add()函数 
	   int i=4;
	   for(int x=1;x<=3&&i<len;x++){//注意需要用Len来控制add()函数是双目还是三目运算符 
	   	 i=cut(str,i);
	   tmp+=count(s);
	   }
	  return tmp;
	}
	if(str[0]=='m'){//实现min()、max()函数 
	   int i=4;
	   for(int x=1;x<=2;x++){
	   	i=cut(str,i);  
	   x==1?tmp1=count(s):tmp2=count(s);
	   }
	  if(str[1]=='i')
	    return tmp1<tmp2?tmp1:tmp2;//返回最小值 
	return tmp1>tmp2?tmp1:tmp2;//返回最大值 
	}
	if(str[0]=='d'){//doubleMe()函数 
	   int i=9;
	   	i=cut(str,i);
	  return count(s)*2;
	}
  return 0;
}
int main()
{
   string str="";
   char ch;
   while(~scanf("%c",&ch)&&ch!='
')
      if(ch!=' ')
         str+=ch;
   cout<<count(str);
return 0;
}




原文地址:https://www.cnblogs.com/zswbky/p/5431986.html