Brainfuck переводчик странный вывод

Я решил написать простую среду разработки Brainfuck на C ++ с использованием Borland CppBuilder6. Я надел свой RichEdit и сделал его похожим на блокнот. Затем я добавил TEdit для ввода и TMemo для вывода. После некоторых тестов я подумал, что RichEdit — плохой компонент для использования в моем случае, и я изменил его на TMemo.

В моем коде ввод = Edit2, код = Memo2, вывод = Memo1. Я переписал это два раза, и эта версия кажется наиболее правильной; Я решил не использовать указатели (я думал об этом и даже написал версию указателя, к сожалению, это не сработало, поэтому для упрощения я удалил указатели).

char *cells = (char*)calloc(65536,1); //Should i use malloc?
int cellp = 0;
void __fastcall BFIde::interpret() {
char* pf = Memo2->Lines->Text.c_str(); //Weird output
char* p = (char*)malloc(strlen(pf)+1);
strcpy(p, pf); //Because pf is constant, i need to copy it into not constant string.
int pp = 0;

MessageBox(NULL,p,NULL,MB_OK); //To ensure that program is correct, but it ain't.

while(p[pp]){
switch(p[pp]){
case '>':
cellp++;
break;
case '<':
cellp--;
break;
case '+':
MessageBox(NULL, "Plus", NULL, MB_OK); //When executing test code, never gets shown.
cells[cellp]++;
break;
case '-':
cells[cellp]--;
break;
case '.':{ //It should look other, but I've replaced it to ensure that output is correct.
char arr[2]={cells[cellp],0};MessageBox(NULL, arr, NULL, MB_OK);}
break;
case ',': //Remove first character and pass it to program
if(Edit2->Text == "")cells[cellp] = 0;
else {cells[cellp] = Edit2->Text.c_str()[0];char* str;strcpy(str, Edit2->Text.c_str());Edit2->Text=str++;}
break;
case '[':{ //Propably works.
int bal = 1;
if (cells[cellp] == '\0') {
do {
pp++;
if      (p[pp] == '[') bal++;
else if (p[pp] == ']') bal--;
} while ( bal != 0 );
}
break;
}
case ']':
int bal2 = 0;
do {
if      (p[pp] == '[') bal2++;
else if (p[pp] == ']') bal2--;
pp--;
} while ( bal2 != 0 );
break;
}
pp++;
}
MessageBox(NULL, IntToStr(cellp).c_str(), NULL, MB_OK); //To check that something was parsed. Shows 0 everytime (not expected).
}

Когда я ввожу некоторый код, например. «+». и выполнить эту функцию (с помощью кнопки), это показывает серию сообщений. Первый: (строка 8), вторая: 0 (строка 55), и больше ничего не показывает. Ожидаемый результат должен был написать: сначала +.второй Plusи пустой 3-й. Что я сделал неправильно в своем коде? Может быть, я что-то пропустил.

0

Решение

В вашем коде есть ошибки, связанные с памятью. Самая первая строчка interpret() принимает указатель на временный AnsiString это освобождается сразу после этого, поэтому последующие строки кода работают с висящим указателем на недопустимую память. Точно так же в вашем ',' обработчик, вы пытаетесь скопировать данные в неинициализированный указатель, который не указывает на допустимую память. И вы не делаете никаких проверок границ при доступе к cells[] массив.

Есть также логические ошибки в вашем ']' обработчик. Вы не проверяете текущие данные ячейки на 0, чтобы решить, к какой инструкции перейти к следующей, и вы не ищете правильный обратный поиск при поиске открытия '[',

Попробуйте что-то более похожее на это:

static const int maxCells = 65536;

class BFIde : public TForm
{
__published:
TEdit *Edit2;
TMemo *Memo1;
TMemo *Memo2;
TButton *Button1;
void __fastcall Button1(TObject *Sender);
private:
char cells[maxCells];
int cellp;
char& cellData();
void __fastcall interpret(const AnsiString &commands, AnsiString input);
public:
__fastcall BFIde(TComponent *Owner);
};

__fastcall BFIde::BFIde(TComponent *Owner)
: TForm(Owner)
{
}

char& __fastcall BFIde::cellData()
{
if ((cellp < 0) or (cellp >= maxCells))
throw Exception("Accessing cells out of bounds");
return cells[cellp];
}

void __fastcall BFIde::interpret(const AnsiString &commands, AnsiString input)
{
Memo1->Clear();

memset(cells, 0, maxCells);
cellp = 0;

const char* start = commands.c_str();
const char* p = start;

while (*p)
{
switch (*p)
{
case '>':
++cellp;
break;

case '<':
--cellp;
break;

case '+':
cellData()++;
break;

case '-':
cellData()--;
break;

case '.':
{
char ch = cellData();
Memo1->SelStart = Memo1->GetTextLen();
Memo1->SelLength = 0;
Memo1->SelText = ch;
break;
}

case ',':
{
char ch;
if (input.Length() == 0) {
ch = '\0';
}
else {
ch = input[1];
input.Delete(1, 1);
}
cellData() = ch;
break;
}

case '[':
{
if (cellData() == '\0')
{
int bal = 1;
while (*++p)
{
if (*p == '[') {
++bal;
}
else if (*p == ']')
{
if (--bal == 0)
break;
}
}
if (bal != 0)
throw Exception("Unbalanced loop");
}
break;
}

case ']':
{
if (cellData() != '\0')
{
int bal = 1;
while (p > start)
{
--p;
if (*p == ']') {
++bal;
}
else if (*p == '[')
{
if (--bal == 0)
break;
}
}
if (bal != 0)
throw Exception("Unbalanced loop");
}
break;
}
}

++p;
}

ShowMessage(cellp);
}

void __fastcall BFIde::Button1(TObject *Sender)
{
interpret(Memo2->Lines->Text,  Edit2->Text);
}
2

Другие решения

Других решений пока нет …