Un interpréteur brainfuck

a marqué ce sujet comme résolu.
Auteur du sujet

Bonsoir à tous, J'ai écris un interpréteur brainfuck en C++ dans le but de m'entraîner et de pratiquer. Seulement j'ai un gros gros problème d'optimisation: mon interpréteur ne fait marcher que le "hello word" :/. Je pense que cela vient notamment de mes deux boucles for, mais je ne vois pas comment supprimer une des boucles. Je vous demande donc vos yeux avisés en C++ pour m'aiguiller et me conseiller sur ce code:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/* **************************** */
/* interpreteur brainfuck C++   */
/*                              */
/*   main.cpp                   */
/*                              */
/* ******************************/
#include <iostream>
#include <algorithm>
#include <stack>

const std::string instructions = {"<>-+[]-.,;"};

using namespace std;


int main()
{
  string c;
  char input;
  cout << "interpreteur brainFuck" << endl;
  cout << "----------------------" << endl;
  cout << "----------------------" << endl;
  cout << "instruction: >";

  //on verifie que l'instruction est valable

  do
  {
    cin >> input;

    //si l'instruction n'existe pas on quitte le programme(pour le moment :p)
    auto it = find(instructions.cbegin(),instructions.cend(), input);

    if(it == instructions.cend()){
        cout << "probleme de compilation" << endl;
        break;
    }

    //on ajoute l'instruction a la ligne du programme
    c+=input;

  }while(!(input == ';'));// ';' est l'instruction de fin

  vector<char> memory;//tableau des octets du programme
  vector<char> ::iterator memoryPtr = memory.begin();
  vector<int> brackets(c.length());
  stack<char, vector<char>> bracketStack;

  memory.push_back(0);
  memoryPtr = memory.begin();

  for(int i(0); i < c.length(); i++)
  {
    if(c[i] == '[') {//si on rencontre un crochet on l'ajoute au stack de crochets existants
      bracketStack.push(i);
    }
    if(c[i] == ']')
    {
      if(bracketStack.empty())//si on rencontre un ] alors que le stack est vide, il y a une erreur de syntaxe
      {
        cerr << "probleme de ] à la position " << i << endl;
        return 404;
      }else
      {
        int pos = bracketStack.top();
        bracketStack.pop();//on retire la [ du dessus
        brackets[i] = pos;
        brackets[pos] = i;
      }
    }

  }
  if(!bracketStack.empty())
  {
    cerr << "[ non fermé a la position " << bracketStack.size() << endl;
    return 404;
  }
  for(int i(0); i < c.length(); i++)
  {
    switch (c[i])
    {
      case '<':
        if(memoryPtr != memory.begin())
          memoryPtr--;
            break;
      case '>':
        if(memoryPtr == memory.end() - 1)
        {
          memory.push_back(0);
          memoryPtr = memory.end() - 1;
        }else{
          memoryPtr++;
        }
            break;
      case '+':
        (*memoryPtr) ++;
            break;
      case '-':
        (*memoryPtr) --;
            break;
      case '.':
          putchar(*memoryPtr);
            break;
      case ',':
        *memoryPtr = cin.get();
            break;
      case '[':
        if(!(*memoryPtr)) i  = brackets[i];
            break;
      case ']':
        if(*memoryPtr) i = brackets[i];
            break;

    }
  }
  //on quitte le programme
  cout << "-----logs de sortie----" << endl;
  cout << c<< endl;
  cout << "fin du programme";
  //fin
}

voila mon code que j'ai essayé de rendre le plus propre possible avec les règles d'indentation et de const-correctness au mieux. Merci de vos conseils et vos critiques ^^

+0 -0

Il y a moyen de pas mal simplifier. Tu devrais plutôt lire le programme Brainfuck sans te soucier de la syntaxe et au lieu d'attendre un ";" attendre la fin du fichier (EOF, c'est Ctrl-D sous Unixoïde). Sous Windows ça marche aussi. Donc la stratégie c'est de lire un fichier et virer tous les retours à la ligne et tous les caractères d'espacement possibles. Je sais pas comment tu ferais ça en C++ mais c'est très probablement possible.

Ensuite,tu n'as pas besoin de séparer vérification de la syntaxe et exécution. Il faut donc enlever ta boucle de vérification syntaxique. Dans ta boucle d'exécution, quand tu lis un [ tu mets l'indice sur la pile et alors il y a deux cas: ou bien la case mémoire courante est nulle et alors tu sautes juste après le ] correspondant, ou bien elle est pas nulle et tu continues normalement l'exécution.

Si tu tombes sur un ] tu peux gérer ça de deux façons: ou bien tu fais le test de la case mémoire puis tu décides si tu sautes après l'instruction [ ou non, ou bien tu sautes toujours à l'instruction [ qui elle va déterminer quoi faire. Je prendrais la deuxième solution, c'est plus simple.

Lors de l'exécution, si tu tombes sur un caractère inconnu tu peux arrêter là.

D'ailleurs, un mot sur la gestion des erreurs. Je ne sais pas sous quel OS tu travailles, mais quand on a un programme qui renvoie un code particulier selon l'erreur rencontrée on ne renvoie pas n'importe quoi comme 404 qui est un code d'erreur HTTP qui ne veut rien dire dans le cas présent. Ça m'a fait sourire mais autant apprendre à faire ça correctement. Utilise ceci, c'est la manière propre de gérer ton cas.

Sur le C++ je n'ai pas de commentaire à te faire, je n'en fais pas.

+0 -0
Ce sujet est verrouillé.