题意:给出一个C表达式,计算其值。其中操作数只有26个字母,从a到z依次初始值为1到26;操作符有二位的 + 和二位的 - ,和正常意思一样,然后还有一位的自增 ++ 和一位的自减 - - ,都有前缀和后缀两种,都和正常理解的一样。然后计算表达式值,并给出式子中的各变量最后的值。对了,每个变量在表达式中最多只出现一次。
思路:题目最后也有给出思路,就是将所有一位操作符即自增和自减操作符去掉,再将有前缀操作符的变量自增或自减了,然后计算表达式的值,最后将有后缀操作符的变量自增或自减。这里只要在输入串中查找自增和自减操作符就行了,遇到的是前缀的就直接修改相应变量值,遇到后缀的进行标记下。由于题目没有提到空格的情况,开始用gets输入,结果WA了,说明自增或自减操作符自己中间可能有空格,然后自增或自减操作符与修饰的那个变量之间可能有空格。(可能是前者,可能后者,也可能两者都有)所以直接getchar过滤掉空格。但又要原样输入表达式,只好另存了一下。
注意:空格的情况。多处都有可能有空格。
吐槽:这题好像也挺简单的哈,但是在白书的那个专题里,8道题目中这道UVa通过率好像最低,还以为多难的~~~~唉,数据不可信~~不可吓自己~~
晚上还是要及时睡觉啊~就算偶尔看个精彩的比赛到一两点,结束后就睡了吧,别破罐子破摔,搞到四五点再睡的话,休息到十二点也休息不过来了啊~~ 睡不好,干什么都不行,什么都不相干,甚至连电影都懒得看,生活就会变糟~
Code:
#include<stdio.h>
#include<string.h>
#define MAXN 120
char exp[MAXN];
char ysexp[MAXN];
int zm[30];
int hz[30];
bool flag[30];
int main()
{
//while(fgets(exp,MAXN-1,stdin)!=NULL)
//while(gets(exp)!=NULL)
char ch;
while((ch=getchar())!=EOF)
{
int cnt=0;
int yscnt=0;
do
{
ysexp[yscnt++]=ch;
if(ch!=' ') exp[cnt++]=ch;
}while((ch=getchar())!='\n');
ysexp[yscnt]='\0';
exp[cnt]='\0';
printf("Expression: %s\n",ysexp);
for(int i=0;i<26;++i)
{ zm[i]=i+1; hz[i]=0; flag[i]=0;}
char *s=exp;
while((s=strstr(s,"++"))!=NULL)
{
if(*(s+2)=='\0' || *(s+2)=='-' || *(s+2)==' ')
{//后缀
hz[*(s-1)-'a']++;
*s=' '; *(s+1)=' ';
}
else
{//前缀
zm[*(s+2)-'a']++;
*s=' '; *(s+1)=' ';
}
//s++;
}
s=exp;
while((s=strstr(s,"--"))!=NULL)
{
if(*(s+2)=='\0' || *(s+2)=='+' || *(s+2)==' ')
{
hz[*(s-1)-'a']--;
*s=' '; *(s+1)=' ';
}
else
{
zm[*(s+2)-'a']--;
*s=' '; *(s+1)=' ';
}
//s++;
}
//计算
s=exp;
while(*s<'a' || *s>'z') s++;//直到*exp为小写字母
int val=zm[*s-'a'];
flag[*s-'a']=1;
char c;
while((c=*s)!='\0')
{
if(c=='+')
{
while(*s<'a' || *s>'z') s++;//直到*exp为小写字母
val+=zm[*s-'a'];
flag[*s-'a']=1;
}
else if(c=='-')
{
while(*s<'a' || *s>'z') s++;
val-=zm[*s-'a'];
flag[*s-'a']=1;
}
s++;
}
printf(" value = %d\n",val);
for(int i=0;i<26;++i)
if(flag[i])
{
zm[i]+=hz[i];
printf(" %c = %d\n",'a'+i,zm[i]);
}
}
return 0;
}