NYOJ 305 表达式求值

 法一:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<stdlib.h>
 4 //这个表达式求值,要先算最小单元的数值,可以采用递归方式
 5 char str[350];//使用全局数据保存字符串
 6 int first;//字符当前位置
 7 int min(int x,int y)
 8 {
 9     return x>y ? y:x;//返回比较小的数
10 }
11 int max(int x,int y)
12 {
13     return x>y ? x:y;//返回比较大的数
14 }
15 int fun()  //函数,分析字符
16 {
17     int v,n;//保存数字及数字的位数 
18     switch(str[first])  //分析字符串的开头字符
19     {
20     case 'm':  //有可能是max,min
21        first+=3;//指向 指向括号
22        if(str[first-2]=='i') //对于min
23            return min(fun(),fun()); //如min(3,5),递归时就会分别返回3和5,然后当成min的参数
24        else
25            return max(fun(),fun());
26        break;
27     case 'a':  //是add
28        first+=3;
29        return fun()+fun(); //如add(3,5),递归时就会返回3和5
30        break;
31     case ',':  //分隔符
32     case '(':
33     case ')':
34        first++;//跳过不处理
35        return fun();//继续递归
36        break;
37     default: //数字
38        sscanf(str+first,"%d%n",&v,&n);//从字符str+first开始将数字读入v,数字位数为n,此处的%n含义是返回从调用开始到此读了多少个字节 
39        first+=n;//走过数字
40        return v;
41        break; 
42     }
43 }
44 int main()
45 {
46     int n,m;
47     scanf("%d",&n);//n组测试数据
48     while(n--)
49     {
50         scanf("%s",str);//字符数据
51         m=fun();
52         printf("%d\n",m);
53         first=0;//每次测试完要使first归零
54     }
55     return 0;
56 } 

  法二:

 1 #include<stdio.h>
 2  char s[301],cstack[120];
 3  int dstack[80];
 4  int i,ctop,dtop;
 5  int Operate(int a,char theta,int b)
 6  {
 7      switch(theta){
 8          case 'd': return a+b;
 9          case 'n': return a>b?b:a;
10          case 'x': return a>b?a:b;
11      }
12  }
13  int EvaluateExpression()
14  {
15      char theta;
16      int a,b,k;
17      do{    
18          if(s[i]>'9'||s[i]<'0'){
19              if(s[i]=='a'||s[i]=='m') i+=2;
20              if(s[i]==')'){
21                  --ctop;
22                  theta=cstack[--ctop];
23                  a=dstack[--dtop];
24                  b=dstack[--dtop];
25                  dstack[dtop++]=Operate(a,theta,b);
26              }else if(s[i]!=',') cstack[ctop++]=s[i];
27              ++i;
28          }
29          while(s[i]<='9'&&s[i]>='0'){
30              for(k=0;s[i]!=','&&s[i]!=')'&&s[i]<='9'&&s[i]>='0';++i)
31                  k=10*k+s[i]-'0';
32              dstack[dtop++]=k;
33              if(s[i]==',') ++i;
34          }
35      }while(ctop);
36      return dstack[0];
37  }
38  int main()
39  {
40      int N;
41      scanf("%d",&N);
42      while(N--){
43          i=ctop=dtop=0;
44          scanf("%s",s);
45          printf("%d\n",EvaluateExpression());
46      }
47      return 0;
48  }

解题思路:这是道表达式求值问题,只需考虑加法(add)、求最大值(max)以及最小值(min),可以用递归简单实现。注意括号和逗号的处理。

一道简单的模拟题,但是就是读入数据很麻烦,对于字符串的处理的能力还是太弱,以后得多练这类题目。。。。。

重新学习了一下sscanf的在字符串中读取正数的方法。

这道题用递归写会比较简单点。

1. C 语言中的输出函数printf中的%n格式的含义

可以将所输出字符串的长度值赋绐一个变量。

如下代码:

#include<stdio.h>

void main()

{

  int slen;

  printf("hello world%n", &slen);

  printf("\n");              //换行

  printf("%d",slen);         //输出slen的值

  printf("\n");              //换行

}

 

2. %n与其他格式说明符号不同。%n不向printf传递格式化信息,而是令printf把自己到该点已打出的字符总数放到相应变元指向的整形变量中。因此%n对于的变元必须是整形指针。

对printf调用返回之后,%n对于变元指向的变量中将包含有一个整数值,表示出现%n时已经由该次printf调用输出的字符数。

printf("this%n is a test\n",&count);//调用后count为4

 

3. sscanf的功能和scanf差不多,只是多了一个参数,该参数放于第一个,用来标识要被解析的字符串,相对于scanf来说,他其实就是你输入的字符串。懂了不

char szText[1024] = "123 34.4";

sscanf(szText, "%d %f", &a, &f);

a 就等于123,f就是34.4f

scanf 系列中有个函数 sscanf,可能有人用过,它的普通用法

gnu c 实现了 C 标准的 format specify 的 %n,它的含义是返回从该次 XXscanf 调用开始到此读了多少个字节,我们可以利用这一点,来实现不需要内存分配的%s:

 

4:switch的执行是按照从小到大的顺序执行的,最后执行default语句,如果default后面带有break,那么程序就会正常跳出switch,否则,程序会继续向后执行switch语句!也就是说,不管default放在什么位置,它总是在最后一个处理,然后继续向下处理!所以,最后的处理办法,避免出现以外结果的最好办法就是每一个case以及default语句都要加一个break!

 

posted on 2012-08-03 16:38  mycapple  阅读(430)  评论(0编辑  收藏  举报

导航