题解 P3695 【CYaRon!语】
wjyyy
2019-02-15 07:40:33
## 题解:
模拟即可。
---
再有其他内容就是字符串的读入了吧。
下了三组数据才AC,不得不说#10很强。
在这个题中,函数思想很重要。因为有很多地方会调用相同的内容,甚至有时候有大篇幅相似的两部分可以合在一个函数里再加`if`判断。
循环的嵌套是最麻烦的内容,其次是变量求值。还好没有数组套数组(大不了多几个递归),字符串长度开得比较小。变量可以用`std::map`映射,然后用编号统一存起来。
对于变量求值而言,一个是**单项式求值**,一个是**多项式(仅加减)求值**,其中又要考虑是否是数组的情况。我写了一个`getnext(int &i)`函数,用来获取从$i$开始的第一个**可求的**式子。如果`a`是一个数组,那么`a[7]`是一个可求的式子而`a`不是。然后用字符串处理依次考虑正负即可。
如果经常使用gdb或某些IDE的自带debug器的话,循环嵌套的思路比较容易联想,实现起来比较麻烦~~废话~~。使用一个变量tot存储当前做到**循环的**第几行了,带入内层循环tot不变,循环结束时置tot为en+2(en指循环结束的}字符所在行的前一行)。
还有一个地方是**循环中**语句会被使用多遍,这时不能直接通过标准读入,而要把这些语句全部存起来。读一行(空格也读)用到的是`gets(char *s)`,当读到EOF时返回NULL。
注意这个题的缩进和空格都不确定。所以需要写一个`jump()`,就是使$i$跳过前面所有的连续空格。还有其他字符的跳过额外写一点也不怎么麻烦。
感谢自己的坚持。
## Code:
```cpp
#include<cstdio>
#include<cstring>
#include<iostream>
#include<map>
#define jump() do{while(s[i]==' ')++i;}while(0)
using namespace std;
map<string,int> mp;
int a[55][1010];
int cnt;
int st[55],len[55];
char s[1000];
int getnext(int &i)//获得从i开始接下来一段式子的值 i被置为最后一个下标+1
{
jump();
int x=0;
if(s[i]>='0'&&s[i]<='9')
{
for(;s[i]>='0'&&s[i]<='9';++i)
x=x*10+s[i]-'0';
return x;
}
string ss="";
for(;s[i]>='a'&&s[i]<='z';++i)
ss+=s[i];
int t=mp[ss];
if(len[t]==1)
return a[t][0];
jump();
++i;
int ans=a[t][getnext(i)-st[t]];
++i;
return ans;
}
int getstring(int &i)//获得从i开始的一个多项式的值
{
int ans=0,flag=1;
jump();
while((s[i]>='0'&&s[i]<='9')||(s[i]>='a'&&s[i]<='z')||s[i]=='+'||s[i]=='-')
{
flag=(s[i]=='-')?-1:1;
while(s[i]==' '||s[i]=='+'||s[i]=='-')
++i;
ans+=flag*getnext(i);
jump();
}
return ans;
}
void Set()//赋值
{
int i=0;
jump();
i+=4;
jump();
string ss="";
for(;s[i]>='a'&&s[i]<='z';++i)
ss+=s[i];
int t=mp[ss],u=0,v=0;
if(len[t]==1)
{
while(s[i]==' '||s[i]==',')
++i;
a[t][0]=getstring(i);
}
else
{
++i;
u=getstring(i);
//i是']'
++i;
while(s[i]==' '||s[i]==',')
++i;
a[t][u-st[t]]=getstring(i);
}
}
void print()
{
int i=0;
jump();
i+=7;
jump();
while(s[i]==' '||s[i]==',')
++i;
printf("%d ",getstring(i));
}
void qaq();
bool ihu(int ty);
void hor();
void whi();
char F[500][100];
int tot=0;
bool isend()//是否结尾 判断ihu、hor和while是否结束
{
if(!tot)
gets(s);
else
{
int i=0;
for(;F[tot][i]!='\0';++i)
s[i]=F[tot][i];
s[i]='\0';
++tot;
}
int i=0;
jump();
return (s[i]=='}');
}
int main()
{
gets(s);
int i=1,flag=0;
jump();
if(s[i]=='v')//如果没有定义就要跳过
{
gets(s);
while(s[0]!='}')
{
string ss="";
int i=0;
jump();
for(;s[i]>='a'&&s[i]<='z';++i)
ss+=s[i];
mp[ss]=++cnt;
jump();
if(s[i+1]=='i')
st[cnt]=len[cnt]=1;
else
{
i+=10;
while(s[i]==' '||s[i]==',')
++i;
//逗号前后的空格
st[cnt]=getnext(i);
while(s[i]==' '||s[i]=='.')
++i;
len[cnt]=getnext(i);
len[cnt]-=st[cnt]-1;
}
gets(s);
}
}
else
flag=1;
while(flag||gets(s)!=NULL)
{
flag=0;
if(!strlen(s))
continue;
qaq();
tot=0;
}
return 0;
}
void qaq()//执行语句
{
int i=0;
jump();
if(s[i]=='{')
{
++i;
jump();
if(s[i]=='i')
ihu(0);
else if(s[i]=='w')
whi();
else
hor();
}
else if(s[i+1]=='s')
Set();
else
print();
}
bool ihu(int ty)
{
int i=0;
jump();
++i;
jump();
i+=3+ty*2;
jump();
char tmp[2]={s[i],s[i+1]};
i+=2;
if(tmp[0]=='n')
++i;
while(s[i]==' '||s[i]==',')
++i;
int x=getstring(i);
while(s[i]==' '||s[i]==',')
++i;
int y=getstring(i);
bool sat;
if(tmp[0]=='e')
sat=(x==y);
else if(tmp[0]=='l')
{
if(tmp[1]=='t')
sat=(x<y);
else
sat=(x<=y);
}
else if(tmp[0]=='n')
sat=(x!=y);
else
{
if(tmp[1]=='t')
sat=(x>y);
else
sat=(x>=y);
}
if(ty)
return sat;
int br=1;
if(!sat)
while(1)
{
if(isend()&&br==1)
return 0;
i=0;
jump();
if(s[i]=='{')
++br;
if(s[i]=='}')
--br;
}
else
{
while(1)
{
if(isend()&&br==1)
return 0;
if(!strlen(s))
continue;
qaq();
}
}
}
void hor()
{
int i=0;
jump();
++i;
jump();
i+=3;
jump();
string ss="";
for(;s[i]>='a'&&s[i]<='z';++i)
ss+=s[i];
int t=mp[ss];
int *ii,u;//用指针引用值更加方便
if(len[t]==1)
ii=&a[t][0];
else
{
++i;
u=getstring(i);
ii=&a[t][u-st[t]];
}
while(s[i]==' '||s[i]==',')
++i;
int from=getstring(i);
while(s[i]==' '||s[i]==',')
++i;
int to=getstring(i);
int st=1,en=0,l=0;
if(tot)
st=tot;
int br=1;
while(1)
{
if(isend()&&br==1)//注意不要找到别人的右括号了 下同
{
if(tot)
en=tot-2;//en是右括号上面一行相对st(1)的编号
else
en=l;
break;
}
if(!strlen(s))//注意空串如果跳过会方便一些
continue;
++l;
i=0;
jump();
if(s[i]=='{')
++br;
if(s[i]=='}')
--br;
if(!tot)
{
i=0;
for(;s[i]!='\0';++i)
F[l][i]=s[i];
F[l][i]='\0';
}
}
for(*ii=from;*ii<=to;++(*ii))
{
tot=st;
while(tot<=en)
{
i=0;
for(;F[tot][i]!='\0';++i)
s[i]=F[tot][i];
s[i]='\0';
++tot;
qaq();
}
}
tot=en+2;
}
void whi()
{
int i=0;
char p[1000];
for(;s[i]!='\0';++i)
p[i]=s[i];
p[i]='\0';
int st=0,en=0,l=0;
if(tot)//最外层不需要处理这里
{
st=tot-1;
++tot;
}
int br=1;
while(1)
{
if(isend()&&br==1)
{
if(tot)
en=tot-2;
else
en=l;
break;
}
if(!strlen(s))
continue;
i=0;
++l;
jump();
if(s[i]=='{')
++br;
if(s[i]=='}')
--br;
if(!tot)
{
i=0;
for(;s[i]!='\0';++i)
F[l][i]=s[i];
F[l][i]='\0';
}
}
while(1)
{
tot=st+1;
i=0;
for(;p[i]!='\0';++i)
s[i]=p[i];
s[i]='\0';
if(!ihu(1))
{
tot=en+2;
return;
}
while(tot<=en)
{
i=0;
for(;F[tot][i]!='\0';++i)
s[i]=F[tot][i];
s[i]='\0';
++tot;
qaq();
}
}
}
```