在某些应用中,为了支持灵活性,往往用到自定义的公式。
比如,有如下的原始公式集合:
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='\n';
while(ch=='\n'){
str="";
while(~scanf("%c",&ch)&&ch!='\n')
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!='\n')
if(ch!=' ')
str+=ch;
cout<<count(str);
return 0;
}
浙公网安备 33010602011771号