Partage
  • Partager sur Facebook
  • Partager sur Twitter

[C] Fonction retournant un tableau de strings

Sujet résolu
    3 juin 2022 à 19:44:08

    Bonjour,

    Je suis en train d'essayer de faire une fonction qui doit manipuler un tableau de strings :

    char **guesses(Arbre *arbre_racine){
     
        String_list *liste_mots = arbre_to_list(arbre_racine) ;
        String *actuel = liste_mots->tete ;
        table_hash_frequence *table_freq_norm = subtable(liste_mots, table_freq) ;
     
        list_f *list_freq_norm = sublist_f(table_freq_norm, liste_mots) ;
        element_f *actuel_p_word = list_freq_norm->head ;
     
        double entro ;
        double score_actuel ;
        double scores[5] = {-1, -1, -1, -1, -1} ;
        char *guess = (char*)malloc(sizeof(actuel->string)) ;
     
        char **guess_array = malloc(sizeof(char*) * 5) ;
        for(int i = 0; i < 5; i++)
            guess_array[i] = malloc(27 * sizeof(char)) ;
     
        int i = 0 ;
        int index = min_double_array_index(scores) ;
     
        while (actuel != NULL) {
     
            i++ ;
            printf("Boucle : %d\n", i) ;
     
            entro = entropie(actuel->string, arbre_racine, liste_mots) ;
            score_actuel = entro + actuel_p_word->frequence ;
             
            if (score_actuel > scores[index]){
                scores[index] = score_actuel ;
                strncpy(guess, actuel->string, strlen(actuel->string) + 1) ;
                strcpy(guess_array[index], guess) ;
                index = min_double_array_index(scores) ;
            }
     
            actuel_p_word = actuel_p_word->next ;
            actuel = actuel->suivant ;
     
        }
     
        list_f_destroy(list_freq_norm) ;
        destroy_string_list(liste_mots) ;
        table_freq_destroy(table_freq_norm) ;
     
        return guess_array ;
     
    }

    Et pour le main :

                char **tmp1 = guesses(arbre) ;
                char *guess = "zionfzoijnfzou" ;
    
                for(int i = 0; i < 5 ;i++)
                    free(tmp1[i]) ;
                free(tmp1) ;

    Le but de la fonction est de stocker les 5 réponses qui ont les meilleures scores et de renvoyer ce tableau, mais je me retrouve avec des problèmes de memory leak. Avant d'avoir essayé de faire cela, j'ai fais une fonction qui retourne seulement le guess avec le score le plus haut comme ça :

        String_list *liste_mots = arbre_to_list(arbre_racine);
        String *actuel = liste_mots->tete;
        // p(word)
        table_hash_frequence *table_freq_norm = subtable(liste_mots, table_freq);
    
        list_f *list_freq_norm = sublist_f(table_freq_norm, liste_mots);
        element_f *actuel_p_word = list_freq_norm->head;
    
        double entro;
        double score_actuel;
        double score = 0.0;
        char *guess = (char*)malloc(sizeof(actuel->string));
        int i = 0;
        while (actuel != NULL){
            i++;
            printf("Boucle : %d\n", i);
            entro = entropie(actuel->string, arbre_racine, liste_mots);
            score_actuel = entro + actuel_p_word->frequence;
    
            if (score_actuel >= score){
                score = score_actuel;
                strncpy(guess, actuel->string, strlen(actuel->string) + 1);
            }
    
            actuel_p_word = actuel_p_word->next;
            actuel = actuel->suivant;
        }
    
        list_f_destroy(list_freq_norm);
        destroy_string_list(liste_mots);
        table_freq_destroy(table_freq_norm);
    
        return guess;

    Et elle fonctionnait. Le problème vient donc bien de l'implémentation d'un tableau de strings mais je ne vois pas trop comment modifier ce que j'ai fais... Auriez-vous une idée ?

    Merci d'avance pour votre réponse !

    PS : Le programme affiche juste le premier mot en faisant un for (int i = 0 ; i < 5 ; i++) printf("%s", tmp1[i]) ;

    -
    Edité par TheArcturus 3 juin 2022 à 20:21:43

    • Partager sur Facebook
    • Partager sur Twitter
      4 juin 2022 à 12:54:15

      Bonjour ! Je ne peux pas t'aider car je ne maîtrise pas trop les pointeurs (en tout cas pas au point de manipuler des pointeurs de pointeurs comme tu le fais).

      Mais au cas où, je voulais t'indiquer comment je m'y serais pris (je ne maîtrise pas les pointeurs, mais j'arrive à faire des choses quand même). Le principe : j'utilise toujours des tableaux 1-D (sauf pour une matrice, allez). Un tableau de chaîne de caractères, c'est donc un tableau de 'chaine' où je définis le type 'chaine'. Quelque chose comme :

      typedef char* chaine;    // type destiné à recevoir des chaînes de caractères

      Et je crée un tableau de 5 'chaine' :

      #define NB_REPONSES 5
      chaine tableau[NB_REPONSES];

      De mon point de vue d'être humain, 'tableau' est un bête tableau (déclaré avec [], pas avec * : c'est plus lisible), pas un pointeur de pointeur (ça, c'est du point de vue du compilateur). En fait il faut quand même se souvenir que c'est un tableau de pointeurs (pointeurs de 'char') si on veut le remplir correctement.

      Voilà, c'est au cas où ça t'apporterait quelque chose de simplifier un peu...

      -
      Edité par robun 4 juin 2022 à 15:22:27

      • Partager sur Facebook
      • Partager sur Twitter
        4 juin 2022 à 13:54:18

        Il y a beaucoup de choses qui peuvent provoquer un plantage !

        si actuel->string est un pointeur la taille allouée ne sera pas correcte.

        si min_double_array_index(scores) renvoi un nombre supérieur ou égal à 5.

        etc...  tu utilises des fonction que l'on ne sait pas ce qu'elle font.

        Il faut utiliser un débogueur. 

        • Partager sur Facebook
        • Partager sur Twitter
        ...
          4 juin 2022 à 14:14:30

          Et surtout pour t'aider à débusquer tes erreurs de gestion de mémoire il faut utiliser un memory profiler comme valgrind par exemple.

          La démarche est simple :

          • installer valgrind si ce n'est pas déjà fait ;
          • compiler ton projet avec les infos de debug (option -g avec clang et/ou gcc) ;
          • lancer ton exécutable avec valgrind en indiquant les options : --leak-check=full --track-origins=yes --show-reachable=yes ;
          • décortiquer le log pour non seulement trouver l'endroit (et tu en auras sans doute plus d'un) où le segfault est lancé mais également pour avoir le call stack qui aboutit à l'erreur et celui qui est à l'origine de l'allocation ;
          • étape finale corriger les erreurs et éventuellement utiliser un debuger pour les comprendre.
          Voilà, savoir programmer est une chose, savoir coder une autre, trouver les bugs encore une autre ; mais à chaque moment il est important de savoir utiliser des outils qui nous simplifient la vie et nous permettent de trouver des solutions bien plus rapidement qu'en ayant recours à un débogage assisté par forum.
          • Partager sur Facebook
          • Partager sur Twitter
            4 juin 2022 à 14:47:13

            Merci beaucoup pour vos réponses !
            Je vais regarder tout ça
            • Partager sur Facebook
            • Partager sur Twitter

            [C] Fonction retournant un tableau de strings

            × 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