1.基礎
要了解Brainfuck你必須想象每個0
初始化細胞的無限陣列。
...[0][0][0][0][0]...
當brainfuck程序啓動時,它指向任何單元格。
...[0][0][*0*][0][0]...
如果移動指針向右>
你是從小區X移動指針到單元X + 1
...[0][0][0][*0*][0]...
如果您增加單元格值+
你:
...[0][0][0][*1*][0]...
如果您再次提高單元格價格+
即可獲得:
...[0][0][0][*2*][0]...
如果減少細胞值-
你:
...[0][0][0][*1*][0]...
如果移動指針離開<
你是從小區X移動指針小區X-1
...[0][0][*0*][1][0]...
2.輸入
要閱讀字符,請使用逗號,
。它的作用是:從標準輸入讀取字符並將其十進制ASCII碼寫入實際單元。
看看ASCII table。例如,!
的十進制代碼是33
,而a
是97
。
好吧,讓我們來想象你的BF程序存儲器的樣子:
...[0][0][*0*][0][0]...
假設標準輸入代表a
,如果使用逗號,
運營商,什麼BF不讀a
進制ASCII碼97
內存:
...[0][0][*97*][0][0]...
你一般都想這樣想,但事實有點複雜。事實是,BF不會讀取字符,而是讀取一個字節(無論該字節是什麼)。讓我告訴你例子:
在linux下
$ printf ł
打印:
ł
這是具體的拋光特性。該字符不是由ASCII編碼編碼的。在這種情況下,它是UTF-8編碼,所以它在計算機內存中佔用了多個字節。我們可以做一個十六進制轉儲證明這一點:
$ printf ł | hd
表示:
00000000 c5 82 |..|
零被抵消。82
是第一個,並且c5
是代表ł
的第二個字節(爲了我們將讀取它們)。 |..|
是在這種情況下不可能的圖形表示。
好吧,如果你通過ł
輸入到你的BF程序,讀取單字節,程序存儲器將看起來像:
...[0][0][*197*][0][0]...
爲什麼197
?那麼197
十進制是c5
十六進制。似乎很熟悉?當然。它是ł
的第一個字節!
3.輸出
要打印字符使用點.
它所做的是:假設我們像對待進制ASCII代碼的實際單元格的值,打印對應的字符到標準輸出。
好吧,讓我們來想象你的BF程序存儲器的樣子:(。)
...[0][0][*97*][0][0]...
如果你現在使用點操作,所做的BF是打印:
一個
因爲a
ASCII中的十進制代碼是97
。
因此,例如BF程序是這樣的(97個加號2點):
++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++ ..
將增加它指向的單元格的值爲97並將其打印出來2次。
AA
4.循環
在BF循環由循環的開始和[
循環結束]
。你可以認爲它就像在C/C++中那樣,條件是實際的單元格值。
看看BF程序如下:
++[]
++
增量實際單元格值的兩倍:
...[0][0][*2*][0][0]...
而且[]
就像while(2) {}
,所以它的無限循環。
假設我們不希望這個循環是無限的。例如我們可以這樣做:
++[-]
所以每次循環循環它都會減少實際的單元格值。一旦實際單元格的值是0
循環結束:
...[0][0][*2*][0][0]... loop starts
...[0][0][*1*][0][0]... after first iteration
...[0][0][*0*][0][0]... after second iteration (loop ends)
讓我們考慮有限循環的另一個例子:
++[>]
這個例子說明,我們沒有在這個循環開始對細胞完成循環:
...[0][0][*2*][0][0]... loop starts
...[0][0][2][*0*][0]... after first iteration (loop ends)
但是,最好結束我們開始的地方。爲什麼?因爲如果循環結束了它啓動的另一個單元格,我們不能假定單元格指針將在哪裏。說實話,這種做法使得brainfuck減少brainfuck。
一定很難保持用這種語言編寫的應用程序。 –
@ ring0:不,這是一種只寫語言。 – LetMeSOThat4U
它有什麼實際用途? –