表达式求值
-
描述
-
Dr.Kong设计的机器人卡多掌握了加减法运算以后,最近又学会了一些简单的函数求值,比如,它知道函数min(20,23)的值是20 ,add(10,98) 的值是108等等。经过训练,Dr.Kong设计的机器人卡多甚至会计算一种嵌套的更复杂的表达式。
假设表达式可以简单定义为:
1. 一个正的十进制数 x 是一个表达式。
2. 如果 x 和 y 是 表达式,则 函数min(x,y )也是表达式,其值为x,y 中的最小数。
3. 如果 x 和 y 是 表达式,则 函数max(x,y )也是表达式,其值为x,y 中的最大数。
4.如果 x 和 y 是 表达式,则 函数add(x,y )也是表达式,其值为x,y 之和。
例如, 表达式 max(add(1,2),7) 的值为 7。
请你编写程序,对于给定的一组表达式,帮助 Dr.Kong 算出正确答案,以便校对卡多计算的正误。
-
输入
-
第一行: N 表示要计算的表达式个数 (1≤ N ≤ 10)
接下来有N行, 每行是一个字符串,表示待求值的表达式
(表达式中不会有多余的空格,每行不超过300个字符,表达式中出现的十进制数都不
超过1000。)
输出
- 输出有N行,每一行对应一个表达式的值。 样例输入
-
3 add(1,2) max(1,999) add(min(1,1000),add(100,99))
样例输出
-
3 999 200
-
第一行: N 表示要计算的表达式个数 (1≤ N ≤ 10)
题解:解这道题之前,我们要学一些预备知识:
sscanf()函数的应用:(这是我百度一些知识,大家也可以去百度)
看书的时候碰到sscanf函数,就上网查了很多资料,并加以自己的整理,希望对大家有所帮助。
(因为参考的博客太多太散,就不一一注明,望大神们见谅)
sscanf() :从一个字符串中读进与指定格式相符的数据.
函数原型:
Int sscanf( string str, string fmt, mixed var1, mixed var2 ... );
int scanf( const char *format [,argument]... );
sscanf与scanf类似,都是用于输入的,只是后者以屏幕(stdin)为输入源,前者以固定字符串为输入源。 简单地说就是输入的类型不同。
首先要先搞清楚,sscanf函数的返回值:(个人认为不必细究,懂用就好)
成功则返回参数数目,失败则返回-1,错误原因存于errno中。返回0表示失败,否则,表示正确格式化数据的个数
例如:sscanf(str,"%d%d%s", &i,&i2, &s); 如果三个变成都读入成功会返回3。(同scanf)
如果只读入了第一个整数到i则会返回1。证明无法从str读入第二个整数。
sscanf强大的功能体现在对format的支持上。我在这一方面重点整理了一下啊,这里作主要说明:(采用用法+例子帮助大家学习)
一、常见用法。
有点类似于scanf的使用(略有区别),有点赋值的味道。
1. char buf[512] = ;
sscanf("123456 ", "%s", buf);
printf("%s\n", buf);
结果为:123456
(注:各种的类型使用相同,都有%d,%s,%f等)
2. 取指定长度的字符串。如在下例中,取最大长度为4字节的字符串。
sscanf("123456 ", "%4s", buf);
printf("%s\n", buf);
结果为:1234
二、有关format符号上的特殊用法:
1.%[^a]:表示取到指定字符为止的字符串。
如在下例中,取遇到空格为止字符串。
sscanf("123456 abcdedf", "%[^ ]", buf); printf("%s\n", buf);
输入的结果为:123456
2.%[a-z] 表示匹配a到z中任意字符。
如在下例中,取仅包含1到9和小写字母的字符串。 sscanf("123456abcdedfBCDEF", "%[1-9a-z]", buf); printf("%s\n", buf); 结果为:123456abcdedf
(结合1.2的使用方法的例子:)
取仅包含指定字符集的字符串。如在下例中,取仅包含1到9和小写字母的字符串。 sscanf("123456abcdedfBCDEF", "%[1-9a-z]", buf); printf("%s\n", buf); 结果为:123456abcdedf 取到指定字符集为止的字符串。如在下例中,取遇到大写字母为止的字符串。 sscanf("123456abcdedfBCDEF", "%[^A-Z]", buf); printf("%s\n", buf); 结果为:123456abcdedf
3.%*[]: *亦可用于格式中, (即 %*d 和 %*s) 加了星号 (*) 表示跳过此数据不读入. (也就是不把此数据读入参数中)
结合第一点的用法:
例子:
给定一个字符串iios/12DDWDFF@122,获取 / 和 @ 之间的字符串,先将 "iios/"过滤掉,再将非'@'的一串内容送到buf中 sscanf("iios/12DDWDFF@122", "%*[^/]/%[^@]", buf); printf("%s\n", buf); 结果为:12DDWDFF
外加另一个例子:
给定一个字符串““hello, world”,仅保留world。(注意:“,”之后有一空格) sscanf(“hello, world”, "%*s%s", buf); printf("%s\n", buf); 结果为:world %*s表示第一个匹配到的%s被过滤掉,即hello被过滤了 如果没有空格则结果为NULL。
4.还有另一些不太常见的用法:
1
2
3
4
5
6
7
8
9
10
11
12
|
{a|b|c}表示a,b,c中选一
[d],表示可以有d也可以没有d。
width表示读取宽度。
{h | l | I64 | L}:参数的size,通常h表示单字节size,I表示2字节 size,L表示4字节size(
double
例外),l64表示8字节size。
特别的:%*[width] [{h | l | I64 | L}]type 表示满足该条件的被过滤掉,不会向目标参数中写入值
支持集合操作;
%[aB
'] 匹配a、B、'
中一员
|
%n的用法下面是第一种解法:(递归的调用,参考大神的代码)
%n说明符输出有效字符数量,%n在scanf和printf中都可使用。与%n相对应的形参是一个int类型的指针,%n不影响scanf和printf的返回值。例如:
scanf("%d %d%n", &i, &j, &k);
如果输入434 6434,则k等于8,而scanf的返回值仍然为2。又如:
scanf("%c%n", &ch, &k);
输入“sbcdefdg”后,k等于1,而不是8,因为%c只取一个字符,%n输出的是有效字符数量。
%n用在printf函数里,表示输出的字符数量,例如:
printf("i=%d, j=%d\n%n", i, j, &k);
在i=343、j=123的情况下,k=12,同时%n不影响printf的返回值,其返回值仍然为12,而不是14。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
char a[400];
int start;
int fun()
{
int v, n;
switch(a[start])
{
case'm':
{
start += 4;
if(a[start-2]=='n') return min(fun(), fun());
else return max(fun(), fun());
}
case'a':
{
start += 4;
return fun()+fun();
}
case',':
case')':
{
++start;
return fun();
}
default:
{
sscanf(a+start, "%d%n", &v, &n);
start += n;return v;
}
}
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%s", a);
start = 0;
printf("%d\n", fun());
}
return 0;
}
第二种方法:(栈的使用)
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<stack>
using namespace std;
char ch[400];
int fun1(char a, int b, int c)
{
if(a == '+')
return b+c;
else if(a == '>')
return b>c?b:c;
else
return b<c?b:c;
}
int fun2()
{
int len = strlen(ch);
stack<char>sting;
stack<int>num;
for(int i = 0; i < len; i++)
{
if(ch[i]=='a')
{
sting.push('+');
i += 3;
}
else if(ch[i] == 'm')
{
if(ch[i+1] == 'a')
{
sting.push('>');
i += 3;
}
else
{
sting.push('<');
i += 3;
}
}
else if(ch[i] >= '0' && ch[i] <= '9')
{
int v, n;
sscanf(ch+i, "%d%n", &v, &n);
num.push(v);
i += n-1;
}
else if(ch[i] == ')')
{
char a = sting.top(); sting.pop();
int b = num.top(); num.pop();
int c = num.top(); num.pop();
num.push(fun1(a, b, c));
}
}
return num.top();
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%s", ch);
printf("%d\n", fun2());
}
return 0;
}