Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Problème d'allocation dynamique


Sujet :

C

  1. #1
    Candidat au Club
    Problème d'allocation dynamique
    Bonjour,
    Je commence le C et je travaille sur un exercice d'allocation dynamique dont le but est d'afficher les mots contenu dans fichier ("strings.txt"). Ces mots seront contenus dans une structure composé d'un tableau dynamique et d'une valeur qui correspond à la longueur du mot.

    Voici le programme :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    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
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
     
     
    #define STR_MAX 100
     
     
    void* malloc(size_t nombreOctetsNecessaires);
     
     
    struct string
    {
        char str[STR_MAX] ;
        int len ;
    } ;
     
     
    struct string * lit_fichier(char *nom_fichier, int *nb)
    {
        FILE *f ;
        int i = 0 ;
        int j = 0 ;
        char *chaine = NULL ;
        struct string *tab = NULL ;
     
        f = fopen(nom_fichier,"r") ;
     
        printf("avant comptage %d %d \n", i, *nb) ;
        /* On compte le nombre de mots */
        fgets(chaine, 20, f) ;
        printf("%s ",chaine) ;
        while ( (i<*nb) && ( fgets(chaine, 20, f) ) != NULL) {
            printf("pendant comptage %d \n", i) ;
            i++ ;
        }
     
        *nb = i ;
        printf("apres comptage %d \n", *nb) ;
     
        /* Retour au début du fichier */
        fseek(f, 0, SEEK_SET) ;
     
        /* Allocation dynamique et vérification */
        tab = malloc(*nb * sizeof(char*)) ;
     
        if (tab == NULL ){
            fprintf(stderr,"Allocation impossible \n");
            exit(EXIT_FAILURE);
        }
        printf("avant lecture dans lecture %d \n", *nb) ;
        /* Lecture du fichier */
        while  ( (j < *nb) && ( fgets(chaine, 20, f) != NULL ) ){
            strcpy(tab[j].str, chaine) ;
            tab[j].len = strlen(tab[j].str - 1) ;
            j++ ;
        }
        printf("apres lecture dans lecture %d \n", j) ;
     
     
        fclose(f) ;
        return tab ;
    }
     
     
    void affichage(struct string tab[], int longueur)
    {
        int i ;
     
        for ( i = 0 ; i < longueur ; i++ ) {
            printf("%s   (%d) \n" , tab[i].str, tab[i].len) ;
        }
    }
     
     
    int main(int argc, char *argv[])
    {
        FILE *f ;
        struct string *tableau ;
        int nb = 10 ;
     
        /* Ouverture du fichier */
        if ( argc == 1 ) {
            fprintf(stderr, "Il me faudrait un nom de fichier ...\n") ;
            return 1 ;
        }
     
        f = fopen(argv[1], "r") ;
     
        if ( f == NULL ) {
            fprintf(stderr, "Impossible de lire le fichier [%s].\n", argv[1]) ;
            return 2 ;
        }
     
        fclose(f) ;
     
        printf("avant lecture %d \n", 1);
        tableau = lit_fichier(argv[1], &nb) ;
        printf("après lecture %d \n", 2);
        affichage(tableau, nb) ;
        printf("après affichage %d \n",3) ;
     
        /* Libération de la mémoire */
        free(tableau) ;
        tableau = NULL ;
    }



    Je n'ai pas d'erreur à la compilation, mais pourtant en l'exécutant, j'obtiens ceci :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    avant lecture 1 
    avant comptage 0 10 
    Segmentation fault: 11


    Le programme ne rentre pas dans la 1ère boucle de "lit_fichier" alors que la condition sur i est bonne et qu'il y a des choses à lire dans le fichier.
    Je ne comprends pas d'où vient mon erreur
    Une explication ?

    Merci d'avance !

  2. #2
    Expert confirmé
    Bonjour,

    ligne 24, on voit bien que chaine vaut NULL.
    ligne 31, on passe chaine à la fonction fgets en lui disant que c'est un buffer capable de recevoir au moins 20 caractères.
    Boom

  3. #3
    Candidat au Club
    Mais je ne vois pas comment "initialiser" chaine autrement qu'en lui donnant la valeur NULL. Comment est-ce que je pourrais m'en sortir ?

  4. #4
    Responsable Systèmes

    Mais je ne vois pas comment "initialiser" chaine autrement qu'en lui donnant la valeur NULL. Comment est-ce que je pourrais m'en sortir ?
    Avec malloc. Ou initialiser chaine comme ceci :
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur la création d'un système : http://chrtophe.developpez.com/tutor...s/minisysteme/
    Mon article sur le P2V : http://chrtophe.developpez.com/tutoriels/p2v/
    Consultez nos FAQ : Windows, Linux, Virtualisation

  5. #5
    Candidat au Club
    Ça marche, merci beaucoup !

  6. #6
    Expert éminent sénior
    Bonjour
    Citation Envoyé par AuBar Voir le message
    Mais je ne vois pas comment "initialiser" chaine autrement qu'en lui donnant la valeur NULL. Comment est-ce que je pourrais m'en sortir ?
    Ton souci c'est que tu n'as pas bien compris la façon de faire. On ne te demande pas d'initialiser chaine (d'ailleurs pourquoi initialiser un truc qui va être rempli 3 lignes plus bas), on te demande de garantir que chaine aura bien la place pour stocker 20 caractères.
    D'où la solution de chrtophe qui te propose d'utiliser malloc (allocation mémoire) ou bien de définir chaine comme un tableau tout prêt (et non plus un pointeur pointant sur rien).
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  7. #7
    Candidat au Club
    J'avais aussi mal compris l'exercice : il était uniquement nécessaire que le tableau soit alloué dynamiquement et non chaine.
    Donc la bonne réponse était que chaine devait être un tableau de taille fixe !

  8. #8
    Responsable Systèmes

    Je rajouterais qu'en C, une chaine de caractères est en fait un tableau de char devant ce terminer par \0. Si on y accède via un pointeur, celui-ci pointera sur le premier élément de ce tableau. Pas sûr que tu es déjà vu les pointeurs.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur la création d'un système : http://chrtophe.developpez.com/tutor...s/minisysteme/
    Mon article sur le P2V : http://chrtophe.developpez.com/tutoriels/p2v/
    Consultez nos FAQ : Windows, Linux, Virtualisation