1993年,松本行弘告诉世界可以用
puts "Hello, world!"
来打印出这条向世界问好的语句,但是,在世界的另一个角落,一位来自瑞士的大学生也打算给世界带来一点小小的震撼。
光速入门
如何判断一门语言是否会给世界带来极大的震撼?Brainf***k(下简称BF)仅用它的名字就给世人以最简解。
当然,更震撼的是,你只需要八个字符就能描绘出这个世界。
下面光速介绍一下这门语言的所有基础知识
BF所使用的所有字符
字符 | 作用 | C语言(char* ptr) |
> | 指针指向下一字节 | ++ptr |
< | 指针指向前一字节 | --ptr |
+ | 指针所指向字节的值加一 | ++*ptr |
- | 指针所指向字节的值减一 | --*ptr |
. | 打印出指针指向的字节对应内容(ASCII码) | putchar(*ptr) |
, | 输入内容到指针指向的字节(ASCII码) | getchar() |
[ | 如果指针指向的字节数值为0,则跳转去执行下一个]之后的内容 | while(*ptr){ |
] | 如果指针指向的字节数值不为0,,则跳转去执行上一个[之后的内容 | } |
可操作空间
BF为我们提供了一个以字节为单位、被初始化为0的数组(默认长度为128字节,每个字节存储的数为0-255),我们的所有操作都将围绕这个数组展开。
BF还提供过了一个指向该数组的指针(初始状态时该指针指向数组的第一个字节),其亦是极为重要的组件之一
最后,BF还为我们提供了用于输入和输出的两个字节流。
这就是使用BF之前我们所需了的所有知识,真正做到五分钟学会一门语言!
helo word
既然已经掌握了BF所需的所有知识,那就来编写每个语言上手必不可少的helo word吧!
传统守旧派
作为初学者,我认为我们应该在不使用[]循环,并且将每一个字符都存在数组对应位置的条件下来来编写这个程序,体验自然的美感(what a ugly beauty)
一张ASCLL码表
为什么这里会有一张ASCLL码表?期待你在读完下面的程序后还能够脱离他来认识这个世界
程序展示
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
. /*H*/
>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++
. /*e*/
>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++
. /*l*/
>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++
. /*l*/
>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++
. /*o*/
>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++
. /*w*/
>
++++++++++++++++++++++++++++++++
. /* */
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++
. /*w*/
>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++
. /*o*/
>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++
. /*r*/
>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++
. /*l*/
>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++
. /*d*/
>
++++++++++++++++++++++++++++++++
. /*!*/
传统中立派
我们为何不去复用同一个位置?但我仍不认为我们应该使用循环!
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
. /*H*/
>
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++
. /*e*/
+++++++
. /*l*/
. /*l*/
+++
. /*o*/
++++++++
. /*w*/
>
++++++++++++++++++++++++++++++++
. /* */
<
. /*w*/
--------
. /*o*/
+++
. /*r*/
------
. /*l*/
--------
. /*d*/
>
+
. /*!*/
上科技!
受不了了!直接上循环!
如何实现乘法?
在进入科技环节之前,我想我们应该先了解BF简单的乘法实现
思路非常简单,譬如我们要计算5*6,我们只需要告诉它在一个字符内执行五次++++++,
实现如下:
+++++/*先存储需要运算的次数*/
[ /*开始循环*/
>
++++++ /*再储存每次要加的次数*/
<
- /*完成一次循环*/
]
程序展示
++++++++++
[>+++++++>++++++++++>+++>+
<<<<-]
>++.
>+.
+++++++..
+++.
>++.
<<+++++++++++++++.
>.
+++.
------.
--------.
>+.
>.
一些小组件
下面是一些BF语言中常用的组件
加法实现
[->+<]
字符归零
[-]
大小写转换
,----------
[----------------------
.
,----------]
C语言实现简易BF编译器
#include <stdio.h>
#include <string.h>
#define MEMORY_SIZE 65535
#define DIR_LEFT (-1)
#define DIR_RIGHT 1
char CODE[] = ""; /*存放BF代码*/
int jump(int ip,int dir)
{
int depth = 0;
do {
if (CODE[ip] == '[')
depth += 1;
else if (CODE[ip] == ']')
depth -= 1;
ip += dir;
} while(depth);
return ip;
}
int main(int argc, char const *argv[])
{
char memory[MEMORY_SIZE];
int ip , p ;
ip = p =0;
memset(memory,0,MEMORY_SIZE);
while (ip < sizeof(CODE))
{
switch (CODE[ip])
{
case '+':
memory[p] += 1;
break;
case '-':
memory[p] -= 1;
break;
case '>':
p += 1;
break;
case '<':
p -= 1;
break;
case '.':
putchar(memory[p]);
break;
case ',':
memory[p] = getchar();
break;
case '[':
if (memory[p] == 0)
ip = jump(ip, DIR_RIGHT);
break;
case ']':
if (memory[p] != 0)
ip = jump(ip, DIR_LEFT);
break;
}
ip += 1;
}
return 0;
}
理论上brain与纸带机的思想几乎完全一致,所以它也一定是图灵完备的