首先介绍一下吊炸天的语言——BrainFuck
Brainfuck是一种极小化的计算机语言,它是由Urban Müller在1993年创建的。由于fuck在英语中是脏话,这种语言有时被称为brainf*ck或brainf**k,甚至被简称为BF
这种语言基于一个简单的机器模型,除了指令,这个机器还包括:一个以字节为单位、被初始化为零的数组、一个指向该数组的指针(初始时指向数组的第一个字节)、以及用于输入输出的两个字节流。
这种语言,是一种按照“Turing complete(完整图灵机)”思想设计的语言,它的主要设计思路是:用最小的概念实现一种“简单”的语言,BrainF**k 语言只有八种符号,所有的操作都由这八种符号的组合来完成
(按照更节省时间的简单说法,"]"也可以说成“向后跳转到对应的"["状态”。这两解释是一样的。)
(第三种同价的说法,"["意思是"向前跳转到对应的"]"",]意思是"向后跳转到对应的[指令的次一指令处,如果指针指向的字节非零。")
Brainfuck程序可以用下面的替换方法翻译成C语言(假设ptr是char*类型):
当前位置清零
[-] 将当前指针的值归零
之前位置清零
[[-]<] 将当前指针以及之前的指针归零
字符I/O
,. 从键盘读取一个字符并输出到屏幕上。
简单的循环
,[.,] 这是一个连续从键盘读取字符并回显到屏幕上的循环。注意,这里假定0表示输入结束,事实上有些系统并非如此。以-1和"未改变"作为判断依据的程序代码分别是",+[-.,+]"和",[.[-],]"。
指针维护
>,[.>,] 通过移动指针保存所有的输入,供后面的程序使用。
加法
[->+<]
把当前位置的值加到后面的单元中(破坏性的加,它导致左边的单元被归零)。
为了方便我们理解BrainFuck语言,大家可以下载一个很好的编译器,里面还有很多demo
http://download.csdn.net/detail/sm9sun/9721483
下面给出两个示例:
一、程序输出hello word!
BF代码:++++++++++[>+>+++>+++++++>++++++++++<<<<-]>>>++.>+.+++++++..+++.<<++.>+++++++++++++++.>.+++.------.--------.<<+.<.
程序输出小于输入数字的所有质数
BF代码:>++++++++[<++++++++>-]<++++++++++++++++.[-]>++++++++++[<++++++++++>-]<++++++++++++++.[-]>++++++++++[<++++++++++>-]<+++++.[-]>++++++++++[<++++++++++>-]<+++++++++.[-]>++++++++++[<++++++++++>-]<+.[-]>++++++++++[<++++++++++>-]<+++++++++++++++.[-]>+++++[<+++++>-]<+++++++.[-]>++++++++++[<++++++++++>-]<+++++++++++++++++.[-]>++++++++++[<++++++++++>-]<++++++++++++.[-]>+++++[<+++++>-]<+++++++.[-]>++++++++++[<++++++++++>-]<++++++++++++++++.[-]>++++++++++[<++++++++++>-]<+++++++++++.[-]>+++++++[<+++++++>-]<+++++++++.[-]>+++++[<+++++>-]<+++++++.[-]+[->,----------[<+>-------------------------------------->[>+>+<<-]>>[<<+>>-]<>>>+++++++++[<<<[>+>+<<-]>>[<<+>>-]<[<<+>>-]>>-]<<<[-]<<[>+<-]]<]>>[<<+>>-]<<>+<-[>+[>+>+<<-]>>[<<+>>-]<>+<-->>>>>>>>+<<<<<<<<[>+<-<[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<<<>[>>+>+<<<-]>>>[<<<+>>>-]<<<<>>>[>+>+<<-]>>[<<+>>-]<<<[>>>>>+<<<[>+>+<<-]>>[<<+>>-]<[>>[-]<<-]>>[<<<<[>+>+<<-]>>[<<+>>-]<>>>-]<<<-<<-]+>>[<<[-]>>-]<<>[-]<[>>>>>>[-]<<<<<<-]<<>>[-]>[-]<<<]>>>>>>>>[-<<<<<<<[-]<<[>>+>+<<<-]>>>[<<<+>>>-]<<<>>[>+<-]>[[>+>+<<-]>>[<<+>>-]<>+++++++++<[>>>+<<[>+>[-]<<-]>[<+>-]>[<<++++++++++>>-]<<-<-]+++++++++>[<->-]<[>+<-]<[>+<-]<[>+<-]>>>[<<<+>>>-]<>+++++++++<[>>>+<<[>+>[-]<<-]>[<+>-]>[<<++++++++++>>>+<-]<<-<-]>>>>[<<<<+>>>>-]<<<<>[-]<<+>]<[[>+<-]+++++++[<+++++++>-]<-><.[-]>>[<<+>>-]<<-]>++++[<++++++++>-]<.[-]>>>>>>>]<<<<<<<<>[-]<[-]<<-]++++++++++.[-]
是不是很神奇?
下面我们具体说一下思路:
假设我们要打印一个'A' A对应的ascii码为65,当然我们也可以用65个+,不过这样比较LOW
我们先用++++++表示把第一个空间增加到6,然后以此为循环进入第二个空间
每次循环让其加10,即++++++ [ > ++++++++++ < - ] >
此时我们在后面加一个. 运行一下++++++ [ > ++++++++++ < - ] > .输出的应该是一个<,即ascii为60
然后我们再在后面加5个+就能输出A了
好了下面我们输出一个I LOVE YOU试试
还是根据上面的原理,首先I(73),我们把他当作8*9+1来处理,即:++++++++ [ > +++++++++ < - ] > +.
之后我们可以将其变成空格(32),除了直接减去差值以外我们也可以将其归零然后重新赋值,用[-]归零,再加32
即:++++++++ [ > +++++++++ < - ] > +.[-]++++ [ > ++++++++ < - ] > .
然后写L(76),注意,当前值为32,我们可以使其加到38再*2,即:++++++++ [ > +++++++++ < - ] > +.[-]++++ [ > ++++++++ < - ] >.++++++[>++<-]>.
此时你应该输出的I L,看看是不是~~
所以~BrainFuck语言实现起来非常的自由,具体怎样写最简洁最大气就要看你的智商啦~~
接着我们再完成下面的字符输出
++++++++ [ > +++++++++ < - ] > +.[-]++++ [ > ++++++++ < - ] >.++++++[>++<-]>.+++.+++++++.-----------------.[-]++++ [ > ++++++++ < - ] >. -- [ >+++ < - ] >-.----------.++++++.
C语言实现解释器代码:
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>char s[30000]={0};char code[100000];int len = 0;int stack[100];int stack_len=0;int main(int argc,char**argv){char c;int i=0,j,k,x=0;FILE* f;char* p=s+10000;f=fopen(argv[1],"r");while(fread(&code[len],1,1,f)==1) {len++;}setbuf(stdout,NULL);while(i<len) {switch(code[i]) {case '+':(*p)++;break;case '-':(*p)--;break;case '>':p++;break;case '<':p--;break;case '.':putchar((int)(*p));//printf("put:%hdn",*p);break;case ',':*p=getchar();break;case '[':if(*p) {stack[stack_len++]=i;} else {for(k=i,j=0;k<len;k++) {code[k]=='['&&j++;code[k]==']'&&j--;if(j==0)break;}if(j==0)i=k;else {fprintf(stderr,"%s:%dn",__FILE__,__LINE__);return 3;}}break;case ']':i=stack[stack_len-- - 1]-1;break;default:break;}i++;//x++;//printf("%d : i=%dn",x,i);}printf("\n"); system("pause");return 0;}
注:网上相关代码很多,但是大多数都有一个BUG,就是对于嵌套循环即[[]]这样的处理有误。
大家也可以测试输出质数的这个源码,其正好有一个嵌套循环。
然后我们也可以把BF代码保存为二进制文本,后缀名为bf(随便你啦)
再将我们的程序关联上
最后再让我们输出一下I LOVE YOU
好啦~大家现在又学会了一种语言说“我爱你”,还不赶紧去跟妹子表(zhuang)白(bi)~科科