4

我正在尝试编写一个笨拙的解释器,但我缺少一些上下文或其他东西。应该调用来处理“ +><>”等转换的函数应该是:

std::vector<int> Interpreter::interpret(const std::string &src_,
    const std::vector<int> & input_)

程序测试如下:

    int main()
{
std::vector<int> res;
// output: 1
res = interpret("+.");
for (auto i : res)
std::cout << i << " ";
2
// output: 2
res = interpret(",.", {2});
for (auto i : res)
std::cout << i << " ";
return 0;
}

http://www.muppetlabs.com/~breadbox/bf/

我真的不明白这是在做什么。我看过其他视频,但它只是没有意义。有人可以解释目标吗?

如果给函数一个要翻译的数组,那么 30000 字节数组的意义何在?

编辑:我应该编写 C++ 代码,将字符转换为 Brainfuck 命令的字符,并且他们应该在某个 30000 字节的数组上执行相应的命令,以及这意味着什么。

编辑:提供说明

摘要 为 Brainfk 编写一个简单的解释器。1 简介

Brainfk 程序有一个隐含的字节指针,称为指针,它可以在 30000 字节的数组中自由移动,最初全部设置为零。指针本身被初始化为指向该数组的开头。Brainfuck 编程语言由八个命令组成,每个命令都表示为一个字符。

>增加指针。
<减少指针。
+增加指针处的字节。
-减少指针处的字节。
.一个点,输出指针处的字节。
,逗号,输入一个字节并将其存储在指针处的字节中。
[如果指针处的字节为零,则向前跳过匹配的]。
]向后跳转到匹配的 [ 除非指针处的字节为零。

例如,“Hello, World!”的一个版本。Brainfk 中的程序是

++++++++++[>+++++++>++++++++++>+++>+<<<<-]
>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.
+++.------.--------.>+.>.

2 要求

2.1 测试程序
我将使用程序对您的代码进行批量测试和评分。因此,请仔细检查您的函数签名。未能正常运行可能会影响您的项目成绩。入口函数都将具有名称interpret。您可以根据需要实现任意数量的其他辅助函数。以下部分详细介绍了这些规范。

2.1.1 C++ 我会使用 C++11 ( g++ -std=c++11 ...) 来测试你的程序。因此,请随意使用一些最近添加到 C++ 中的好东西,例如 lambda 函数、数组初始化等。为方便起见,请将您的声明和实现代码分隔在bf.h和中bf.cpp。函数签名是std::vector<int> interpret(const std::string &src, const std::vector<int> &input = {});

我的测试程序看起来像

int main()  
{  
std::vector<int> res;  
// output: 1  
res = interpret("+.");  
for (auto i : res)  
    std::cout << i << " ";  

// output: 2  
res = interpret(",.", {2});  
for (auto i : res)  
    std::cout << i << " ";  
return 0;  
}  

编辑:到目前为止我所拥有的:

BFK.h

#pragma once
#include <vector>
#include <iostream>

using namespace std;


char arr[30000];
char* p = arr;

void incPtr();

void decPtr();

void incByte();

void decByte();

void printByte();

void setByte();

void jumpF();

void jumpB();

std::vector<int> interpret(const std::string &src,
    const std::vector<int> & input = {});

BFK.cpp

#include "BFK.h"

void incPtr() {
    p++;
}

void decPtr() {
    p--;
}

void incByte() {
    (*p)++;
}

void decByte() {
    (*p)--;
}

void printByte() {
    std::cout << *p;
}

void setByte() {
    std::cin >> *p;
}

void jumpF() {
    if (*p == 0) {

    }
}

void jumpB() {

}


std::vector<int> interpret(const std::string &src_,
    const std::vector<int> & input_){
    int i = 0;
    int max = src_.size();
    while (i < max) {
        switch (src_[i]) {
        case '>':
            incPtr();
            break;
        case '<':
            decPtr();
            break;
        case '+':
            incByte();
            break;
        case '-':
            decByte();
            break;
        case '.':
            printByte();
            break;
        case ',':
            setByte();
            break;
        case '[':
            jumpF();
            break;
        case ']':
            jumpB();
            break;
        }
    }

    return input_;
}

你应该能够在不实例化任何东西的情况下调用解释,所以我不知道另一种方法来把它放在一起。我还没有实现跳转功能。

4

1 回答 1

1

如果给函数一个要翻译的数组,那么 30000 字节数组的意义何在?

想象一下,你得到两个数字——2 和 5——并希望你的 Brainfuck 程序打印它们的总和。

当您所能做的就是操纵当前单元格中的值并“选择”哪个单元格是当前单元格时,您会怎么做?当然,在某些时候你会需要一些临时记忆。

为了在两个单独的单元格中有两个值,为添加做准备,您可以这样做:

,>,

如果用户输入2and 3(十进制,而不是 ascii),那么 Brainfuck 程序存储器或磁带的前两个字节将如下所示:

[2, 3, 0, 0, ...]
//  ^ This is where our tape pointer is now. We incremented it with `>`

很好,现在添加呢?一个解决方案是使用 Brainfuck 循环。

让我们添加两个自然整数,除了递增和递减值之外什么都不做:

int a = 2, b = 3

while (a != 0)
{
    b += 1
    a -= 1
}

基本上,我们将第一个值递减直到它达到零,并且随着它的减少,我们正在递增第二个值。随着时间的推移,这将显示:

a = 2, b = 3
a = 1, b = 4
a = 0, b = 5
a == 0, break

因此,我们确实得到了2 + 3 = 5. 这很简单,可以在 Brainfuck 中实现。

,  Get value for first cell (a)
>, Get value for second cell (b)
<  Move back to a
[  Loop until a == 0
    >+ Decrement b
    <- Increment a
    We are still at a at this point, so everything is alright
]  Loop again if a != 0
>. Print the final result (sum of a plus b)

...所有这些都是为了演示如何使用 Brainfuck 的磁带记忆来做实际的事情。

我相信很多 Brainfuck 程序将磁带作为堆栈来操作。有趣的是,您实际上并不需要了解 Brainfuck 程序用来以可用方式临时存储值的技术。

让我们看看 Brainfuck 解释器将如何粗略地与上述程序一起工作,一个接一个的指令。

*在堆栈中的值之后意味着它是堆栈指针现在指向的位置。

我会将其中一些分组,以免时间过长。

  1. ,- tape[index] = input(),堆栈现在[2*, 0, 0, ...]
  2. >- index += 1,堆栈现在[2, 0*, 0, ...]
  3. ,- tape[index] = input(),堆栈现在[2, 3*, 0, ...]
  4. <- index -= 1,堆栈现在[2*, 3, 0, ...]
  5. [- if (tape[index] == 0) { skipToLoopEnd(); },不跳转(2 == 0为假),堆栈保持不变
  6. >+- 堆栈现在[2, 4*, 0, ...]
  7. <-- 堆栈现在[1*, 4, 0, ...]
  8. ]- if (tape[index] != 0) { skipToLoopBegin(); },跳转(1 != 0为真),栈左同
  9. >+- 堆栈现在[1, 5*, 0, ...]
  10. <-- 堆栈现在[0*, 5, 0, ...]
  11. ]- if (tape[index] != 0) { skipToLoopBegin(); }不跳转0 != 0为假),堆栈保持不变
  12. >- index += 1,堆栈现在[0, 5*, 0, ...]
  13. .- print(tape[index]),打印5

不用说,我没有意识到这个问题来自 2015 年!(耶!)至少有人会在未来发现这很有用...... :^)

于 2018-11-22T20:41:25.243 回答