2017-04-22 6 views
0

J'ai décidé d'écrire un simple IDE Brainfu * k en C++ en utilisant CppBuilder6 de Borland. J'ai mis sur mon pour un RichEdit et l'ai fait ressembler un peu à un bloc-notes. Ensuite, j'ai ajouté TEdit pour l'entrée et TMemo pour la sortie. Après quelques tests, j'ai pensé que RichEdit est un mauvais composant à utiliser dans mon cas et je l'ai changé en TMemo.Brainf * ck interprète étrange sortie

Dans mon code, entrez = Edit2, code = Memo2, output = Memo1. Je l'ai réécrit deux fois et cette version semble la plus correcte; J'ai décidé de ne pas utiliser de pointeurs (j'ai pensé à cela et même écrit la version du pointeur, malheureusement, cela n'a pas fonctionné, donc pour simplifier j'ai supprimé les pointeurs).

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). 
} 

Lorsque j'entre un code, par ex. "+" et exécuter cette fonction (via le bouton), cela montre des séries de messagebox. D'abord: (ligne 8), ensuite: 0 (ligne 55), et rien de plus ne se montre. Le résultat attendu était d'écrire: Premier +., deuxième Plus, et vide 3e. Ce que j'ai mal fait dans mon code? Peut-être que j'ai raté quelque chose.

+2

Et qu'avez-vous fait jusqu'à présent pour déboguer vous-même? StackOverflow n'est pas un service de débogage. Vous avez un résultat attendu, donc parcourez votre code avec le débogueur jusqu'à ce qu'il dévie de cette attente, et vous pouvez comprendre pourquoi il dévie. Mais je peux vous le dire tout de suite, votre utilisation trop zélée de 'Text.c_str()' est très fausse, mais surtout la première: 'char * pf = Memo2-> Lignes-> Text.c_str(); char * p = (char *) malloc (strlen (pf) +1); strcpy (p, pf); Pourquoi pensez-vous que c'est faux? Je vais vous donner un indice - il a UN COMPORTEMENT UNDEFINED! –

+0

@RemyLebeau Avez-vous déjà utilisé le débogueur C++ builder6? –

+0

Tout le temps. BCB6 est le compilateur que je dois utiliser à mon travail de jour :-(Mais le problème que vous décrivez ne se limite pas à BCB6 Vous avez des erreurs dans votre code, donc il serait cassé dans n'importe quelle version du compilateur –

Répondre

2

Votre code contient des erreurs liées à la mémoire. La toute première ligne interpret() prend un pointeur sur un AnsiString temporaire qui est libéré immédiatement après, de sorte que les lignes de code suivantes fonctionnent avec un pointeur suspendu à la mémoire non valide. De même, dans votre gestionnaire ',', vous essayez de copier des données vers un pointeur non initialisé qui ne pointe pas sur la mémoire valide. Et vous ne faites aucune vérification de limites lors de l'accès à votre tableau cells[].

Votre gestionnaire ']' comporte également des erreurs de logique. Vous ne vérifiez pas les données de cellule actuelles pour 0 pour décider quelle instruction passer à la suivante, et vous ne cherchez pas en arrière correctement lorsque vous recherchez l'ouverture '['.

Essayez quelque chose comme ceci:

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

Je ne savais pas à propos de GetTextLen(), votre code est ok . Merci beaucoup. –