1. Temel Bilgiler
Brainfuck'ı anlamak için, 0
her biri tarafından başlatılan sonsuz hücre dizisi hayal etmelisiniz .
...[0][0][0][0][0]...
Brainfuck programı başladığında herhangi bir hücreyi işaret eder.
...[0][0][*0*][0][0]...
İşaretçiyi sağa >
hareket ettirirseniz, işaretçiyi X hücresinden X + 1 hücresine hareket ettirirsiniz.
...[0][0][0][*0*][0]...
Hücre değerini artırırsanız +
şunları elde edersiniz:
...[0][0][0][*1*][0]...
Hücre değerini tekrar artırırsanız, +
şunları elde edersiniz:
...[0][0][0][*2*][0]...
Hücre değerini düşürürseniz -
şunları elde edersiniz:
...[0][0][0][*1*][0]...
İşaretçiyi sola <
hareket ettirirseniz, işaretçiyi X hücresinden X-1 hücresine taşırsınız
...[0][0][*0*][1][0]...
2. Giriş
Karakteri okumak için virgül kullanırsınız ,
. Yaptığı şey şudur: Standart girdiden karakteri okuyun ve ondalık ASCII kodunu gerçek hücreye yazın.
ASCII tablosuna bir göz atın . Örneğin, ondalık kodu !
is 33
, while a
is 97
.
Peki, BF program belleğinizin şöyle göründüğünü hayal edelim:
...[0][0][*0*][0][0]...
Standart girdinin yerini varsayarsak a
, virgül ,
operatörü kullanırsanız , BF'nin yaptığı şey, a
ondalık ASCII kodunu 97
belleğe okumaktır :
...[0][0][*97*][0][0]...
Genelde böyle düşünmek istersiniz, ancak gerçek biraz daha karmaşıktır. Gerçek şu ki, BF bir karakter değil, bir bayt (o bayt ne olursa olsun) okur. Size örnek göstereyim:
Linux'ta
$ printf ł
baskılar:
ł
belirli bir cila karakteri. Bu karakter ASCII kodlamasıyla kodlanmamıştır. Bu durumda, UTF-8 kodlamasıdır, bu nedenle bilgisayar belleğinde birden fazla bayt alırdı. Onaltılık bir döküm yaparak bunu kanıtlayabiliriz:
$ printf ł | hd
hangi gösterir:
00000000 c5 82 |..|
Sıfırlar ofsettir. 82
birinci ve c5
temsil eden ikinci bayttır ł
(sırayla onları okuyacağız). |..|
bu durumda mümkün olmayan grafik gösterimdir.
Peki, ł
tek bayt okuyan BF programınıza girdi olarak geçerseniz , program belleği şöyle görünecektir:
...[0][0][*197*][0][0]...
Neden 197
? Eh 197
ondalık sayıdır c5
onaltılık. Tanıdık geliyor mu? Elbette. İlk baytı ł
!
3. Çıktı
Karakteri yazdırmak için nokta kullanırsınız .
Ne yapar: Gerçek hücre değerini ondalık ASCII kodu gibi ele aldığımızı varsayarsak, karşılık gelen karakteri standart çıktıya yazdırın.
Peki, BF program belleğinizin şöyle göründüğünü hayal edelim:
...[0][0][*97*][0][0]...
Şimdi nokta (.) Operatörünü kullanırsanız, BF'nin yaptığı şey yazdırmaktır:
bir
Çünkü a
ASCII'deki ondalık kod 97
.
Örneğin, bunun gibi BF programı (97 artı 2 nokta):
++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++++ ..
Gösterdiği hücrenin değerini 97'ye çıkaracak ve 2 kez basacaktır.
aa
4. Döngüler
BF döngüde döngü başlangıcı [
ve döngü bitiminden oluşur ]
. Koşulun gerçek hücre değeri olduğu C / C ++ 'da olduğu gibi düşünebilirsiniz.
Aşağıdaki BF programına bir göz atın:
++[]
++
gerçek hücre değerini iki kez artırır:
...[0][0][*2*][0][0]...
Ve []
sanki while(2) {}
sonsuz döngüdür.
Diyelim ki bu döngünün sonsuz olmasını istemiyoruz. Örneğin şunları yapabiliriz:
++[-]
Dolayısıyla, bir döngü her döngüde gerçek hücre değerini azaltır. Gerçek hücre değeri 0
döngü bittiğinde:
...[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)
Başka bir sonlu döngü örneğini ele alalım:
++[>]
Bu örnek, döngünün başladığı hücrede döngüyü bitirmemiz gerektiğini gösterir:
...[0][0][*2*][0][0]... loop starts
...[0][0][2][*0*][0]... after first iteration (loop ends)
Ancak başladığımız yerde bitirmek iyi bir uygulamadır. Neden ? Çünkü döngü başladığı başka bir hücreyi bitirirse, hücre işaretçisinin nerede olacağını varsayamayız. Dürüst olmak gerekirse, bu uygulama beyni daha az beyinsiz yapar.