为什么 C 中的 brainfuck 解释器在执行带有循环的程序时可能无法工作?
Why the brainfuck interpreter in C may not work when executing a program with loops?
我决定按照个人发展的顺序再写一个 BF 解释器,尽管这是他从头开始编写的第二个版本,但无论如何它不能正确地与循环一起工作。请告诉我如何重写,或者逻辑问题是什么。下面是BF中的代码和程序示例。
#include <stdio.h>
void brainfuck(char* str, int length)
{
char arr[30000] = { 0 };
int ptr = 0, i = 0;
int **brackets = { 0 };
int br_len = 0;
while (i < length)
{
if (str[i] == '[')
{
brackets = (int **)realloc(brackets, (br_len + 1) * sizeof(int *));
brackets[br_len] = (int *)malloc(2 * sizeof(int));
brackets[br_len][0] = '[';
brackets[br_len][1] = i;
br_len++;
}
else if (str[i] == ']')
{
brackets = (int **)realloc(brackets, (br_len + 1) * sizeof(int *));
brackets[br_len] = (int *)malloc(2 * sizeof(int));
brackets[br_len][0] = ']';
brackets[br_len][1] = i;
br_len++;
}
i++;
}
int counter, pos, j; i = 0;
while (i < length)
{
switch (str[i])
{
case '>': ptr++; break;
case '<': ptr--; break;
case '+': arr[ptr]++; break;
case '-': arr[ptr]--; break;
case '.': putchar(arr[ptr]); break;
case ',': arr[ptr] = getchar(); break;
case '[':
if (arr[ptr] == 0)
{
j = 0;
pos = 0;
do
{
pos = j;
j++;
}
while (brackets[j - 1][1] != i);
j = pos + 1;
counter = 1;
while (j < br_len)
{
if (brackets[j][0] == '[')
counter++;
else if (brackets[j][0] == ']')
{
counter--;
if (counter == 0)
break;
}
j++;
}
i = brackets[j][1];
}
break;
case ']':
if (arr[ptr] == 0)
{
j = br_len - 1;
pos = br_len - 1;
do
{
pos = j;
j--;
} while (brackets[j + 1][1] != i);
j = pos - 1;
counter = -1;
while (j >= 0)
{
if (brackets[j][0] == '[')
{
counter++;
if (counter == 0)
break;
}
else if (brackets[j][0] == ']')
counter--;
j--;
}
i = brackets[j][1] - 1;
}
break;
default: break;
}
i++;
}
free(brackets);
}
void main()
{
FILE* fr;
int length;
char* str;
fr = fopen("input.txt", "r");
fseek(fr, 0, SEEK_END);
length = ftell(fr);
rewind(fr);
str = (char*)malloc(length * sizeof(char));
fread(str, 1, length, fr);
brainfuck(str, length);
free(str);
fclose(fr);
}
“你好,世界!”一个循环
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++
.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.
------.--------.>+.>.
“你好,世界!”嵌套循环
++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
']' 如果单元格为 非 零
则应跳回
非常复杂的方法;你想把匹配项放在方括号数组中,就像
case '[':
if (arr[ptr] == 0)
i = brackets[i];
break;
为什么 i = 括号[j][1] - 1;而不仅仅是 i = brackets[j][1]; (额外的速度成本)
让 j 和 pos 费力地关联是一个危险信号
忘记释放所有那些小的 2-int 数组
我决定按照个人发展的顺序再写一个 BF 解释器,尽管这是他从头开始编写的第二个版本,但无论如何它不能正确地与循环一起工作。请告诉我如何重写,或者逻辑问题是什么。下面是BF中的代码和程序示例。
#include <stdio.h>
void brainfuck(char* str, int length)
{
char arr[30000] = { 0 };
int ptr = 0, i = 0;
int **brackets = { 0 };
int br_len = 0;
while (i < length)
{
if (str[i] == '[')
{
brackets = (int **)realloc(brackets, (br_len + 1) * sizeof(int *));
brackets[br_len] = (int *)malloc(2 * sizeof(int));
brackets[br_len][0] = '[';
brackets[br_len][1] = i;
br_len++;
}
else if (str[i] == ']')
{
brackets = (int **)realloc(brackets, (br_len + 1) * sizeof(int *));
brackets[br_len] = (int *)malloc(2 * sizeof(int));
brackets[br_len][0] = ']';
brackets[br_len][1] = i;
br_len++;
}
i++;
}
int counter, pos, j; i = 0;
while (i < length)
{
switch (str[i])
{
case '>': ptr++; break;
case '<': ptr--; break;
case '+': arr[ptr]++; break;
case '-': arr[ptr]--; break;
case '.': putchar(arr[ptr]); break;
case ',': arr[ptr] = getchar(); break;
case '[':
if (arr[ptr] == 0)
{
j = 0;
pos = 0;
do
{
pos = j;
j++;
}
while (brackets[j - 1][1] != i);
j = pos + 1;
counter = 1;
while (j < br_len)
{
if (brackets[j][0] == '[')
counter++;
else if (brackets[j][0] == ']')
{
counter--;
if (counter == 0)
break;
}
j++;
}
i = brackets[j][1];
}
break;
case ']':
if (arr[ptr] == 0)
{
j = br_len - 1;
pos = br_len - 1;
do
{
pos = j;
j--;
} while (brackets[j + 1][1] != i);
j = pos - 1;
counter = -1;
while (j >= 0)
{
if (brackets[j][0] == '[')
{
counter++;
if (counter == 0)
break;
}
else if (brackets[j][0] == ']')
counter--;
j--;
}
i = brackets[j][1] - 1;
}
break;
default: break;
}
i++;
}
free(brackets);
}
void main()
{
FILE* fr;
int length;
char* str;
fr = fopen("input.txt", "r");
fseek(fr, 0, SEEK_END);
length = ftell(fr);
rewind(fr);
str = (char*)malloc(length * sizeof(char));
fread(str, 1, length, fr);
brainfuck(str, length);
free(str);
fclose(fr);
}
“你好,世界!”一个循环
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++
.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.
------.--------.>+.>.
“你好,世界!”嵌套循环
++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
']' 如果单元格为 非 零
则应跳回非常复杂的方法;你想把匹配项放在方括号数组中,就像
case '[':
if (arr[ptr] == 0)
i = brackets[i];
break;
为什么 i = 括号[j][1] - 1;而不仅仅是 i = brackets[j][1]; (额外的速度成本)
让 j 和 pos 费力地关联是一个危险信号
忘记释放所有那些小的 2-int 数组