题解 P2027 【bf】

Sweetlemon

2017-02-03 10:51:56

Solution

这题是编写BrainF**k的解释器,我的程序把这个过程分为三部分:读入代码和输入缓冲——预处理代码(主要是循环)——逐字符解释(执行)代码。 读入没什么可说的,但是要注意忽略"$"前/后的空格。 预处理主要是为了提高执行效率,方便循环的快速跳转。我的上一次提交就是没有用预处理,结果TLE了。因此,避免重复工作是很必要的。 有了预处理的基础,逐字符解释代码也就不难了。只要根据题目的资料(当然,也可以结合Wikipedia上的说明,下面我会发一个Wiki的截图,方便无法访问Wiki的朋友们),写出适当的代码,就好了。 下面发送一下Wiki对BrainF**k的解释(为了避免洛谷的水印影响阅读,稍微调整了版式): ![](https://cdn.luogu.com.cn/upload/pic/4178.png) 最后是AC(6ms,8515kb)的代码: ```cpp #include <stdio.h> #include <string.h> int main(void){ char codes[30001];//代码 char inputs[30001];//输入缓冲区 signed char data[30000]={0};//程序数据,需要初始化为零 int down[30001],up[30001],tstack[15000];//down为左中括号到右中括号的索引,up为右中括号到左中括号的索引,tstack为预处理时的括号栈 char t;//读取时用 signed char * pdata;//数据指针 int i=0,j=0,k=0,ncodes,ninputs; //i记录codes的索引,j记录inputs的索引,k记录tstack的索引 while ((t=getchar())!='$') if (strchr("><.,+-[]",t)) //只记录代码的字符 codes[i++]=t; ncodes=i; //为代码的总字符数 codes[ncodes]='\0'; getchar();//跳过'$'后的空格 while ((t=getchar())!='$') inputs[j++]=t; ninputs=j-1;//为输入的总字符数 inputs[ninputs]='\0'; //读入完成,开始预处理 for (i=0;i<ncodes;i++){ switch (codes[i]){ case '[': tstack[k++]=i;//入栈 break; case ']': down[tstack[--k]]=i;//出栈、记录 up[i]=tstack[k]; break; } } //预处理完成,开始解释 i=0,j=0,pdata=data; //索引、数据指针归零 while (i<ncodes){//遍历代码 switch (codes[i]){ case '<': pdata--; break; case '>': pdata++; break; case '.': putchar(*pdata); break; case ',': if (j<ninputs) *pdata=inputs[j++]; else *pdata=-1;//此时已读完输入缓冲,置为-1 break; case '+': (*pdata)++; break; case '-': (*pdata)--; break; case '[': if (!(*pdata))//如果不执行循环,直接跳到对应]处 i=down[i]; break; case ']': if (*pdata){//如果继续执行循环,跳到[处 i=up[i]; } break; } i++;//执行下一行代码 } return 0; } ```