2017-04-22 64 views
0

我決定用C++編寫一個簡單的Brainfu * k IDE,使用Borland的CppBuilder6。我已經把我的RichEdit放在了一起,使它看起來有點像記事本。然後我添加了TEdit輸入和TMemo輸出。經過一些測試,我認爲RichEdit在我的情況下是不好的組件,我將它改爲TMemo。Brainf * ck解釋器奇怪的輸出

在我的code input = Edit2,code = Memo2,output = 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,空第三個。我在代碼中犯了什麼錯誤?也許我錯過了一些東西。

+2

還有,你迄今所做的這個調試自己? StackOverflow不是一個調試服務。你有一個預期的結果,所以用調試程序遍歷你的代碼,直到它偏離了期望值,然後你可以找出它偏離的原因。但是我現在可以告訴你,你過度使用'Text.c_str()'是非常錯誤的,但特別是第一個:'char * pf = Memo2-> Lines-> Text.c_str(); char * p =(char *)malloc(strlen(pf)+1); strcpy(p,pf);'。你爲什麼認爲這是錯的?我會給你一個提示 - 它有未定義的行爲! –

+0

@RemyLebeau你有沒有使用過C++ builder6調試器? –

+0

所有的時間。 BCB6是我必須在我的日常工作中使用的編譯器:-(但是你描述的問題並不僅限於BCB6,你的代碼有錯誤,所以在任何編譯器版本中都會出現錯誤 –

回答

2

代碼中存在與內存相關的錯誤。 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); 
} 
+0

我不知道GetTextLen(),你的代碼是確定的。 非常感謝你。 –