Programming in Brainfuck

Processing Input

Now we're going to play with processing input. Brainfuck allows you to read a byte as input and store it in the byte at the pointer. This means that entering 123 will be read as the byte-values 49, 50 & 51.

"Well that's really convienent..."

Hey, I didn't design the language.

Let's write a program which reads in three characters and writes them out

,.,.,.
This is a no-brainer: read a character, then write a character. Now something a bit more 'robust':
>+[>,] <[<] >>[.>]
Which is equivalent to:
p++;
a[p]++;
while (a[p]) {
    p++;
    a[p] = getchar();
}
p--;
while (a[p]) {
    p--;
}
p += 2;
while (a[p]) {
    putchar(a[p]);
    p++;
}
Let's break it down. First:
>+[>,]
This increments p, leaving a[0] equal to zero. it then increments a[1] and enters a loop. a[1] has to be non-zero in order for the loop to execute. Within the loop, we increment p and read and store a byte in a[p]. This loop continues until we read in a null leaving a[p] equal to zero after the read. The result is consecutive entries in a[] for each character read. This of course limits what we can read in to the maximum array size of 30000 characters. Next:
<[<]
This 'rewinds' back to the beginning, stopping when p equals zero. This is why a[0] was left equal to zero. And finally:
>>[.>]
p gets incremented twice to skip a[p] which equals zero and a[1] which equals one from our input loop. We enter a loop, outputting a character and incrementing p until a[p] equals zero.

Now, this can be done in a simpler way which is not contstrained by the maximum array size:

+[,.]
The logic here is pretty simple: increment a[0] so we can enter a loop. Once in the loop, read a character and write it out.

Now, all the above work fine for redirecting input from a file: when the end of file is reached, the , instruction reads a null, storing a zero in the byte under the pointer. This is not the case with reading input from he keyboard. Most Brainfuck implementations use some form a getchar() to implement the , instruction. This means that at the first , the program will wait for you to type in some characters follower by 'enter'. Each , will fetch a character from the string entered, including the 'enter' you pressed (which it reads as an ASCII 13). If your program is going to process keyboard input, you need to take this into consideration.

Here is an example which reads a string from the keyboard and prints it out in reverse order:

+[->,----------]<[+++++++++++.<]
Which is equivalent to:
p++;
while (a[p]) {
    a[p]--;
    p++;
    a[p] = getchar();
    a[p] -= 10;
}
p--;
while (a[p]) {
    a[p] += 11;
    putchar(a[p]);
    p--;
}
We prime the read loop (+[->,----------]) as in the previous example. Once in the loop, we decrement a[p] (on the first pass of the loop, this resets a[0] to zero, providing the stop condition for the output loop), increment p and read and store a byte at a[p]. We then subtract ten: if a[p] equals zero after this, then we have read a carrage return and we exit the read loop. If not, we loop back around and do it all over again.

The output loop (<[+++++++++++.<]) is pretty straight forward. We got to this point because the last character read in had a value of ten and after subtracting ten from it, left the byte at the pointer equal to zero, thus breaking out of the read loop. So, we decrement p to get us back to the last character and enter a loop. We add eleven to the byte at the pointer (ten from the carrage-return check plus one for the decrement when the read loop starts again), print out the character and decrement p, moving us back down the array until we hit a[0] which equals zero and drops us out of the loop.

"Tell me again why I'm doing this?"

Why, for the sheer joy one gets from the challenge!

Click here and we'll look at some ways of doing things in Brainfuck.


Home | Introduction | First Program | Input Processing | Building Blocks | Resources | bf2pl

cydathria dot com