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!

 

你可能感兴趣的:(表达式)