为什么 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 数组