必威电竞|足球世界杯竞猜平台

Brainfuck
來源:互聯網

Brainfuck是一種極小化的計算機語言,它是由Urban Müller在1993年創建的。由于fuck在英語中是臟話,這種語言有時被稱為brainf*ck或brainf**k,甚至被簡稱為BF。

簡介

Müller的目標是建立一種簡單的、可以用最小的編譯器來實現的、符合艾倫·麥席森·圖靈完全思想的編程語言。這種語言由八種狀態構成,為Amiga機器編寫的編譯器(第二版)只有240個字節大小!

就象它的名字所暗示的,brainfuck程序很難讀懂。盡管如此,brainfuck圖靈機一樣可以完成任何計算任務。雖然brainfuck的計算方式如此與眾不同,但它確實能夠正確運行。

這種語言基于一個簡單的機器模型,除了指令,這個機器還包括:一個以字節為單位、被初始化為零的數組、一個指向該數組的指針(初始時指向數組的第一個字節)、以及用于輸入輸出的兩個字節流。

這種語言,是一種按照“Turing complete(艾倫·圖靈完備)”思想設計的語言,它的主要設計思路是:用最小的概念實現一種“簡單”的語言,BrainF**k 語言只有八種符號,所有的操作都由這八種符號的組合來完成。

字符標識

下面是這八種狀態的描述,其中每個狀態由一個字符標識:

(按照更節省時間的簡單說法,"]"也可以說成“向后跳轉到對應的"["狀態”。這兩解釋是一樣的。)

(第三種同價的說法,"["意思是"向前跳轉到對應的"]"",]意思是"向后跳轉到對應的[指令的次一指令處,如果指針指向的字節非零。")

Brainfuck程序可以用下面的替換方法翻譯成c語言(假設ptr是char*類型):

當前位置清零

[-] 將當前指針的值歸零

之前位置清零

[[-]<] 將當前指針以及之前的指針歸零

字符i/o

,. 從鍵盤讀取一個字符并輸出到屏幕上。

簡單的循環

,[.,] 這是一個連續從鍵盤讀取字符并回顯到屏幕上的循環。注意,這里假定0表示輸入結束,事實上有些系統并非如此。以-1和"未改變"作為判斷依據的程序代碼分別是",+[-.,+]"和",[.[-],]"。

指針維護

>,[.>,] 通過移動指針保存所有的輸入,供后面的程序使用。

加法

[->+<]

把當前位置的值加到后面的單元中(破壞性的加,它導致左邊的單元被歸零)。

條件指令

,----------[----------------------.,----------]

這個程序會把從鍵盤讀來的小寫字符轉換成大寫。按回車鍵退出程序。

首先,我們通過,讀入第一個字符并把它減10(大多數情況下,brainfuck使用10作為換行符的值)。如果用戶按的是回車鍵,循環命令([)就會直接跳轉到程序的結尾:因為這時第一個字節已經被減到了零。如果輸入的字符不是換行符(假設它是一個小寫字符),程序進入循環。在這里我們再減去剩下的22,這樣總共減掉32:這是ASCⅡ碼中小寫字符和大寫字符的差值。

下面我們把它輸出到屏幕。然后接收下一個輸入字符,并減去10。如果它是換行符,退出循環;否則,再回到循環的開始,減去22并輸出……當循環退出時,因為后面已經沒有其他的指令,程序也隨之終止。

加法

,>++++++[<-------->-],,[<+>-],<.>.

這個程序對兩個一位數做加法,并輸出結果(如果結果也只有一位數的話):4+3

7 (現在程序開始有點復雜了。我們要涉及到數組中單元的內容了,比如、、之類。)

第一個輸入的數字被放在在中,從中減去48來把它從ASCⅡ碼值48到57轉換為數值0到9:這是通過在中放入6,然后按照中的次數讓一個循環從中多次減去8來完成的(當加上或減去一個大的數值時,這是常用的辦法)。下一步,加號被讀入中;然后,第二個數字被輸入,覆蓋掉加號。

下面的循環[<+>-]執行最重要的工作:通過把第二個數字移動到第一個里面讓它們相加,并把清空。這里的每次循環都把增一并從中減一;最終,在被置零的多次循環中,中的值就被轉移到了中。現在,中是我們輸入的換行符(這個程序里,我們沒有設置對輸入錯誤的檢查機制)。

然后,指針被移回到指向,并輸出它的內容(里面現在是 a + (b + 48)的值,因為我們沒有修改b的值,這等于 (a + b) + 48,也就是我們想要輸出的ASCⅡ值)。然后,把指針指向,里面保存著前面輸入的換行符;輸出換行符,程序結束。

乘法

,>,,>++++++++[<------<------>>-]<<[>[>+>+<<-]>>[<<+>>-]<<<-]>>>++++++[<++++++++>-],<.>.

和前一個程序類似,不過這次是乘法而不是加法。

第一個輸入的數字被放入,星號和第二個數字被放入,然后兩個數值都被校正:減去48。

現在,程序進入了主循環。我們的基本思想是:每次從中減去一,同時把的值加入到保存乘積的中。在實際操作中,第一個內層循環把的值同時轉移到和中,同時清零(這是我們復制數字的基該方法)。下一個內層循環把中的值重新放回到,并清零。然后從中減一,結束外層循環。在退出這個循環時,中為零,仍然是輸入的第二個數值,則是這兩個數值的和。(要是想保存第一個數,我們可以在外層循環中每次給加一,最后把移回。)在結果中加48,并把換行符讀入,輸出ASCII碼的乘積,然后輸出剛才保存的換行符。

除法

,>,>++++++[-<--------<-------->>]

從簡單儲存2個數字符到和,并各自減去48

<<[ 這是一個主循環,在被除數,也就是的值為0后循環跳出

>[->+>+<<] 從單元1中復制除數的值到和,設為0

>[-<<- 被除數減去除數,結果將儲存在,并且將歸0

[>]>>>[<[>>>-<<<[-]]>>]<<] 如果被除數為0,跳出循環

>>>+ 加1值商到

<<[-<<+>>] 從復制除數到

<<<] 移動指針到

>[-]>>>>[-<<<<<+>>>>>] 從復制商到 (這步不是必須的,但會更清楚)

<<<<++++++[-<++++++++>]<.

參考資料 >

生活家百科家居網