Возвращаемся к нашим баранам, в смысле к
великому и могучему языку с прикольным
названием Brainfuck. Как выводить символы мы
посмотрели в прошлый раз, а сегодня
продолжим с остальными насущеными
операциями.
Ввод
Как уже было сказано, ввод в языке
осуществляется оператором '.'. Он получает
символ и в виде десятичного ASCII кода
записывает в тот блок, на который указывает
в настоящее время указатель. Напомню
операторы:
> = увеличение указателя памяти или
смещение право на 1 блок
< = уменьшение или смещение влево на 1 блок
+ = увеличение значения в ячейке памяти, на
которую ссылается указатель
- = соответственно уменьшение на единиц
[ = аналог цикла while(cur_block_value != 0)
] = если значение в ячейке на которую
указывает указатель не равно нулю, то
переход на [
, = аналог getchar(), ввод одного символа
. = аналог putchar(), вывод одного символа на
консоль
Итак, поэкспериментируем:
,.,.,.
Такая программа прочтет три символа с
клавиатуры и тут же выведет их. Более
полноценно:
>,[>,]<[<]>[.>]
Эта программа работает как юниксовая
команда cat - читает из STDIN и выводит в STDOUT.
Разберем как она работает: >, - смещает
указатель вправо и читает код символа; [>,] -
цикл, в котором указатель смещается вправо
и читается символ до тех пор, пока строка не
закончится символом NULL (\0 или десятичный
нуль); <[<] - перемотка, смещение указателя
влево по блокам до тех пор, пока не
встретится ноль, а он у нас лежит, напомню, в
самой первой ячейке; >[.>] - соответственно
обратный процесс, смещение по блокам вправо
до нуля и вывод символов.
На С это выглядело бы так:
++p;
*p=getchar();
while(*p != 0){
++p;
*p=getchar();
}
--p;
while(*p != 0) --p;
++p;
while(*p != 0){
putchar(*p);
++p;
}
Собственно, теперь мы знаем как вводить
символы, как их выводить и как
манипулировать памятью - этого вполне
достаточно для написания программ :).
Фишки
Есть много вещей, которые сделают
программирование на Brainfuck проще. Дабы
каждый не открывал для себя Америку опишу
некоторые.
Перенос блоков памяти.
+++++[>>+<<-]
Устанавливаем в первую ячейку 5, затем
организуем цикл, в котором переносим
значение из первой ячейки в третью,
оставляя первую пустой.
Копирование из одного блока памяти в
другой.
+++++[>>+>+<<<-]>>>[<<<+>>>-]
Опять 5 в первую ячейку, копируем в третью
и четвертую, оставляя первую пустой. Затем
переносим значение из четвертой обратно в
первую. Данные скопированы!
Сложение двух ячеек памяти:
+++++>+++[<+>-]
Заносим 5 и 3, организуем цикл, в котором
добавляем к первой ячейке единицу и
вычитаем из второй единицу.
Вычитание:
+++++++>+++++[<->-]
Очевидно, что тут из 7 вычитается 5.
Умножение мы уже разбирали в примере
вывода, однако повторим еще раз:
+++[>+++++<-]
Деление делается аналогично, только на
основе вычитания 🙂
(Продолжение следует)