Partage
  • Partager sur Facebook
  • Partager sur Twitter

interpreteur brainfuck

Sujet résolu
    14 août 2021 à 10:28:41

    Bonjour à tous !

    Voilà je viens vers vous car je n'arrive pas à comprendre quelque chose.

    J'ai fait un programme qui permet d'interpréter du code brainfuck le voici :

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    
    /*          PROTOTYPES         */
    int read_file(char *file_name, char **buffer, int **saveLoop);
    int brainfuck(char *file_name);
    /*******************************/
    
    int read_file(char *file_name, char **buffer, int **saveLoop) {
        FILE *file = NULL;
        int sizeBuffer = 0;
        int sizeLoop = 0;
        int tmp = 0;
    
        file = fopen(file_name, "r");
        if (file == NULL) {
            printf("probleme d'ouverture du fichier");
            return (1);
        }
    
        while (!feof(file)) {
            tmp = fgetc(file);
            sizeBuffer++;
            if (tmp == '[') {
                sizeLoop++;
            }
        }
        rewind(file);
        (*buffer) = malloc(sizeof(char) * sizeBuffer + 1);
        (*saveLoop) = malloc(sizeof(int) * sizeLoop);
    
        fread((*buffer), sizeBuffer, 1, file);
        (*buffer)[sizeBuffer] = '\0';
    
        fclose(file);
        
        return (0);
    }
    
    
    int brainfuck(char *file_name) {
        int memory[30000] = {0};    //stock les valeurs
        int *ptr = memory;          //se promène dans le tableau memory
        char *buffer = NULL;        //stock ce qu'il y a dans le fichier
        int *saveLoop = NULL;       //stock les entrées de boucles
        int iLoop = -1;             //se promène dans saveLoop
        int i = 0;                  //Se promène dans buffer
    
        if (read_file(file_name, &buffer, &saveLoop) == 1) {
            return (1);
        }
        printf("%s\n", buffer);
        while (buffer[i] != '\0') {
            switch(buffer[i]) {
                case '+':   if ((*ptr) < 128) {
                                (*ptr)++;
                            }
                            break;
    
                case '-':   if ((*ptr) > 0) {
                                (*ptr)--;
                            }
                            break;
    
                case '>':   if (ptr < &memory[30000]) {
                                ptr++;
                            }
                            break;
    
                case '<':   if (ptr > &memory[0]) {
                                ptr--;
                            }
                            break;
    
                case '.':   putchar((*ptr));
                            break;
    
                case ',':   (*ptr) = getchar();
                            break;
    
                case '[':   iLoop++;
                            saveLoop[iLoop] = i;
                            break;
    
                case ']':   if ((*ptr) == 0) {
                                iLoop--;
                            } else {
                                i = saveLoop[iLoop];
                            }
                            break;
    
                default :   break;
            }
            i++;
        }
        printf("\n");
        return (0);
    }
    
    int main(int argc, char **argv) {
        if (argc != 2) {
            return (EXIT_FAILURE);
        } else {
            if (brainfuck(argv[1]) == 1) {
                return (EXIT_FAILURE);
            }
        }
        return (EXIT_SUCCESS);
    }

    En faisant des tests avec des fichiers brainfuck ça marche :

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

    ou encore pour l'imbrication de boucles comme pour :

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

    petit souci c'est qu'avec ce code brainfuck suivant il m'affiche 9) et les autres interpreteurs en ligne affichent :) :

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

    pourtant en faisant ce brainfuck sur papier je trouve aussi "9)" car dans le [[]<->] il y le moins qui retire de un. Alors je me pose la question pourquoi j'obtiens la même chose que mon code sur papier et pourquoi je n'ai pas le même resultat que les autres.

    Ensuite il déconne pour le mandelbolt, il tourne en continu sans rien faire.

    Pourtant il me semble que j'ai bien malloc, j'emêche les sorties mémoires de ptr, je malloc mon buffer à la bonne taille et je malloc mon tableau qui stocke les debuts de boucles à la bonne taille également.

    Si vous avez des indices alors je suis preneur à 100% :D !

    En cas d'incompréhension, je peux aider si besoin !

    Merci




    • Partager sur Facebook
    • Partager sur Twitter
      14 août 2021 à 10:33:31

      Bonjour,

      c'est le moment d'apprendre à utiliser un debuger …

      • Partager sur Facebook
      • Partager sur Twitter
        14 août 2021 à 11:00:22

        Effectivement j'ai bien 2 erreurs mémoires comme me le dit valgrind

        La première erreur vient du printf

        La seconde vient de la condition de la boucle

        mais ligne 57 "while (buffer[i] != '\0')" mais pourtant j'ai bien malloc mon buffer et le fread est correct ?

        vu que je récupère tous les éléments du fichier puis à la fin je mets bien un \0 au dernier élément de mon tableau.

        EDIT : J'ai modifié le code en

        (*buffer) = malloc(sizeof(char) * sizeBuffer);
        fread((*buffer), sizeBuffer-1, 1, file);
        buffer[sizeBuffer-1] = '\0';

        par exemple :

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


        il y a 22 éléments et mon sizeBuffer est égal à 23 donc je malloc bien à la taille de sizeBuffer et je dois bien mettre le '\0' à la position 22 du buffer car c'est le dernier en réservant à 23 adresses mémoires.

        mais j'ai toujours 2 problèmes

        -
        Edité par Van3ll0pe 14 août 2021 à 11:15:40

        • Partager sur Facebook
        • Partager sur Twitter
          14 août 2021 à 12:00:50

          bon j'ai un peu lu ton code et je me suis arrêté directement en ligne 23 → Why is “while ( !feof (file) )” always wrong?
          • Partager sur Facebook
          • Partager sur Twitter
            14 août 2021 à 13:06:48

            White Crow a écrit:

            bon j'ai un peu lu ton code et je me suis arrêté directement en ligne 23 → Why is “while ( !feof (file) )” always wrong?


            Merci pour ton aide !

            Je ne savais pas bien le comportement de FEOF.

            Pour remplacer ça j'ai utilisé la structure stat et j'ai récupéré st_size pour connaître la taille du fichier.

            Ensuite je fopen->fread->fclose sans problème.

            J'ai 0 problème mémoire comme me l'indique valgrind.

            par contre j'ai toujours cette incomprinéhension sur :

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

            qui m'affiche "9)", j'ai retranscrit sur papier et je trouve aussi "9)" mais les interpreteurs de brainfuck en ligne me donne ":)".

            voici le nouveau code que j'ai fait :

            #include <stdio.h>
            #include <stdlib.h>
            #include <unistd.h>
            #include <string.h>
            #include <sys/types.h>
            #include <sys/stat.h>
            #include <fcntl.h>
            
            /*          PROTOTYPES         */
            int read_file(char *file_name, char **buffer);
            int brainfuck(char *file_name);
            int count_loop(char *buffer, int **saveLoop);
            /*******************************/
            
            int read_file(char *file_name, char **buffer) {
                FILE *file = NULL;
                struct stat info_file;
                int sizeBuffer = 0;
            
                stat(file_name, &info_file);
                sizeBuffer = info_file.st_size;
                (*buffer) = malloc(sizeof(char) * (sizeBuffer)+1);
                if (*buffer == NULL) {
                    return (1);
                }
                file = fopen(file_name, "r");
                if (file == NULL) {
                    return (1);
                }
                fread((*buffer),sizeBuffer,1, file);
                (*buffer)[sizeBuffer] = '\0';
                fclose(file);
                
                return (0);
            }
            
            int count_loop(char *buffer, int **saveLoop) {
                int sizeLoop = 0;
                for (int i = 0; buffer[i]; i++) {
                    if (buffer[i] == '[') {
                        sizeLoop++;
                    }
                }
            
                (*saveLoop) = malloc(sizeof(int) * sizeLoop);
                if (*saveLoop == NULL) {
                    return (1);
                }
                return (0);
            }
            
            int brainfuck(char *file_name) {
                int memory[30000] = {0};    //stock les valeurs
                int *ptr = memory;          //se promène dans le tableau memory
                char *buffer = NULL;        //stock ce qu'il y a dans le fichier
                int *saveLoop = NULL;       //stock les entrées de boucles
                int iLoop = -1;             //se promène dans saveLoop
                int i = 0;                  //Se promène dans buffer
            
                if (read_file(file_name, &buffer) == 1) {
                    return (1);
                }
                count_loop(buffer, &saveLoop);
                printf("%s\n", buffer);
            
                while (buffer[i] != '\0') {
                    switch(buffer[i]) {
                        case '+':   if ((*ptr) < 128) {
                                        (*ptr)++;
                                    }
                                    break;
            
                        case '-':   if ((*ptr) > 0) {
                                        (*ptr)--;
                                    }
                                    break;
            
                        case '>':   if (ptr < &memory[30000]) {
                                        ptr++;
                                    }
                                    break;
            
                        case '<':   if (ptr > &memory[0]) {
                                        ptr--;
                                    }
                                    break;
            
                        case '.':   putchar((*ptr));
                                    break;
            
                        case ',':   (*ptr) = getchar();
                                    break;
            
                        case '[':   iLoop++;
                                    saveLoop[iLoop] = i;
                                    break;
            
                        case ']':   if ((*ptr) == 0) {
                                        iLoop--;
                                    } else {
                                        i = saveLoop[iLoop];
                                    }
                                    break;
            
                        default :   break;
                    }
                    i++;
                }
                printf("\n");
                
                free(saveLoop);
                free(buffer);
                return (0);
            }
            
            int main(int argc, char **argv) {
                if (argc != 2) {
                    return (EXIT_FAILURE);
                } else {
                    if (brainfuck(argv[1]) == 1) {
                        return (EXIT_FAILURE);
                    }
                }
                return (EXIT_SUCCESS);
            }

            de plus dans cet exemple du brainfuck que j'ai trouvé il y a des boucles inutiles mais là n'est pas le problème


            • Partager sur Facebook
            • Partager sur Twitter
              14 août 2021 à 13:30:01

              il faut utiliser un debuger … valgrind c'est bien mais c'est un memory profiler …

              Un debuger c'est par exemple gdb, ou nemiver/DDD pour un gui, ou intégré à ton ide …

              Sinon en passant … [ saute à l'instruction après le ] correspondant si l'octet pointé est à 0, je ne vois pas où tu fais ça.

              • Partager sur Facebook
              • Partager sur Twitter
                15 août 2021 à 0:53:17

                White Crow a écrit:

                il faut utiliser un debuger … valgrind c'est bien mais c'est un memory profiler …

                Un debuger c'est par exemple gdb, ou nemiver/DDD pour un gui, ou intégré à ton ide …

                Sinon en passant … [ saute à l'instruction après le ] correspondant si l'octet pointé est à 0, je ne vois pas où tu fais ça.


                j'utilise un tout petit peu GDB mais sans plus.

                Je vais me mettre à apprendre GDB sans plus tarder.

                J'ai réussi mon code, tout fonctionne !:D merci encore pour ton aide WhiteCrow.

                • Partager sur Facebook
                • Partager sur Twitter

                interpreteur brainfuck

                × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                • Editeur
                • Markdown