138

誰かが私にこれを送ってきて、Brainfuck の Hello World だと主張しました (そう願っています...)

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

ポインターを移動し、インクリメントとデクリメントを行うことで機能するという基本を知っています...

それでも知りたいのですが、実際にどのように機能しますか?そもそも画面に何かをどのように印刷しますか? テキストはどのようにエンコードされますか? 全然わからない…

4

6 に答える 6

280

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.入力

文字を読み取るには、コンマを使用します,標準入力から文字を読み取り、その 10 進 ASCII コードを実際のセルに書き込みます

ASCII テーブルを見てください。たとえば、 の 10 進コードは!ですが33aは です97

さて、BF プログラムのメモリが次のようになっていると想像してみましょう。

...[0][0][*0*][0][0]...

標準入力が を表すと仮定するとa、コンマ,演算子を使用すると、BF はa10 進 ASCII コード97をメモリに読み込みます。

...[0][0][*97*][0][0]...

一般的にはそのように考えたいと思うでしょうが、実際はもう少し複雑です。真実は、BF は文字ではなくバイト (そのバイトが何であれ) を読み取るということです。例を示しましょう:

Linux では

$ printf ł

プリント:

ł

これは特定のポーランド文字です。この文字は ASCII エンコーディングではエンコードされません。この場合は UTF-8 エンコーディングであるため、以前はコンピューターのメモリで 1 バイト以上を使用していました。16 進数のダンプを作成することでそれを証明できます。

$ printf ł | hd

これは以下を示します:

00000000  c5 82                                             |..|

ゼロはオフセットされます。82は 1 番目、c5は 2 番目のバイトを表しますł(順番に読み取ります)。|..|この場合は不可能なグラフ表現です。

ł1 バイトを読み取る BF プログラムに入力として渡すと、プログラム メモリは次のようになります。

...[0][0][*197*][0][0]...

なぜ197ですか?10進197数はc516 進数です。おなじみのようですか?もちろん。ł!の最初のバイトです。

3.出力

.文字を表示するには、ドットを使用します。実際のセル値を 10 進 ASCII コードのように扱うと仮定して、対応する文字を標準出力に出力します。

さて、BF プログラムのメモリが次のようになっていると想像してみましょう。

...[0][0][*97*][0][0]...

ここでドット (.) 演算子を使用すると、BF は次のように出力します。

a

ASCIIaの 10 進コードは97.

たとえば、次のような BF プログラム (97 プラス 2 ドット):

++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++++++..

ポイントするセルの値を最大 97 まで増やし、2 回出力します。

ああ

4.ループ

BF では、ループは loop begin[と loop endで構成されます]。条件が実際のセル値である C/C++ のようなものだと考えることができます。

以下の BF プログラムをご覧ください。

++[]

++実際のセル値を 2 回インクリメントします。

...[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)

ただし、開始した時点で終了することをお勧めします。なんで ?ループが開始された別のセルを終了する場合、セルポインターがどこにあるかを推測できないためです。正直なところ、この練習により、ブレインファックはブレインファックが少なくなります。

于 2013-11-08T22:27:38.143 に答える
4

すべての答えは徹底的ですが、1 つの小さな詳細が欠けています: 印刷です。ブレインファック トランスレータを構築する際には、キャラクターも考慮します.。これは、実際にブレーンファックでの印刷ステートメントの外観です。したがって、頭のおかしい翻訳者がすべきことは、.文字に遭遇するたびに、現在ポイントされているバイトを出力することです。

例:

あなたが持っていると仮定します --> char *ptr = [0] [0] [0] [97] [0]... これが頭がおかしいステートメントの場合: >>>.ポインターを 3 スペース移動して右のランディング at: に移動する必要が[97]あります *ptr = 97.

write(1, ptr, 1)

または同等の印刷ステートメントを使用して、現在ポイントされているバイトを印刷します。これには値97があり、文字aが に印刷されますstd_output

于 2016-07-18T10:00:21.503 に答える