IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
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 :

realloc par blocs


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Février 2007
    Messages
    106
    Détails du profil
    Informations personnelles :
    Âge : 43

    Informations forums :
    Inscription : Février 2007
    Messages : 106
    Par défaut realloc par blocs
    Salut a tous,

    Voila, je lis un fichier texte ligne par ligne dont je connais pas le nombre de ligne. Je pourrais lire le fichier une 1ere fois pour determiner le nombre de ligne et faire un malloc ensuite. mais pour de gros fichier, ce la peut etre lourd (je parle de fichiers de + de 2 milions de lignes)

    Une autre solution est d'utiliser un malloc initial suivit de realloc a chaque ligne. Mais cela peut etre aussi lourd (voire meme plus que lire le fichier 2 fois)
    Une solution serait de faire ca par bloque de N (avec N=1 milion par example)
    Si on atteint la fin du 1er bloque, on aggrandit la table de N.

    ci-joint un code qui simule une lecture de fichier par une boucle for de i=0 a 45 en remplissant des tables avec tab[i]=1.5*i et name[i]="blabla"
    (la je connais la longueur pour debuger plus facilement). ca fonctionne bien avec ma table de double, mais pas avec ma table de *char

    je ne pense que je ne fais pas les realloc correctement...

    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int main()
    {
     
    double *tab;
    char **name;
     
    int N=10;
    int j=0,ii=0,i=0,k=1;
     
    tab = (double*)malloc((N*k) * sizeof (double));
     
    name = (char**)malloc((N*k) * sizeof (*name));
    for(i=0;i<(N*k);i++){name[i] = (char*)malloc(10 * sizeof (**name));}
     
    for(i=0;i<45;i++){  /*loop starts*/
     
        tab[i] = 1.5*i;
        name[i] = "blabla";
     
        if((i+1)%(N)==0){  /*if initial allocation filled up*/
     
           /*realloc some more memory */                 
           k++;
           printf("realloc at %d \n",N*k); 
     
           tab = (double*)realloc(tab,(N*k) * sizeof (double));
     
           name = (char**)realloc(name,(N*k) * sizeof (*name));
           for(ii=0;ii<(N*k);ii++){name[ii] = (char*)realloc(name[ii],10 * sizeof (**name));}
     
        }
     
    j++;
     
    }  /*loop ends*/
     
     
    if(N*k>j){ /*if realloced too much memory*/ 
     
       /*realloc down to the right value*/                 
       printf("final realloc at %d",j); 
     
       tab = (double*)realloc(tab,j * sizeof (double));
     
       name = (char**)realloc(name,(j+1) * sizeof (*name));
       for(ii=0;ii<(j+1);ii++){name[ii] = (char*)realloc(name[ii],10 * sizeof (**name));}
     
    }
     
    /*
    printf("\n\n");   
    for(i=0;i<j;i++){
    printf("tab[%d]=%f\n",i,tab[i]);                 
    //printf("name[%d]=%s\n",i,name[i]);                            
    }  
    */ 
     
    return 0;
    }
    J'esperes que j'etais clair...

    merci d'avance

    Dave

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    Déjà, il y a beaucoup plus de casts qu'il n'est censé y en avoir dans un programme C.
    Commence par supprimer les casts des retours de malloc(), on y verra plus clair.

    Ensuite, pour le fonctionnement du realloc(), tu t'en sers mal en effet: En cas d'échec, la mémoire existante est leakée...
    Tu peux t'inspirer de ce que j'ai posté dans ce thread:
    http://www.developpez.net/forums/sho...d.php?t=248441

    PS: Tu devrais donner des noms plus explicites à tes variables.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre confirmé
    Inscrit en
    Février 2007
    Messages
    106
    Détails du profil
    Informations personnelles :
    Âge : 43

    Informations forums :
    Inscription : Février 2007
    Messages : 106
    Par défaut
    qu'est que tu veux dire par casts ?

  4. #4
    Membre émérite
    Avatar de Freed0
    Profil pro
    Étudiant
    Inscrit en
    Mars 2005
    Messages
    635
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2005
    Messages : 635
    Par défaut
    Le cast est une conversion de type

    Dans ton cas ce sont par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    name = (char**)malloc((N*k) * sizeof (*name));
    qui peut être simplifié en :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    /* L'opérateur sizeof ne peut être appliqué à un pointeur je pense...
        du moins le résultat n'est ss doute pas celui auquel tu t'attends */
    name = malloc (N * k * (strlen (name) + 1));

  5. #5
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tab = (double*)malloc((N*k) * sizeof (double));
    Le cast en (double*) est inutile en C.
    Si ça ne compile pas sans, c'est que tu compiles en C++.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Membre confirmé
    Inscrit en
    Février 2007
    Messages
    106
    Détails du profil
    Informations personnelles :
    Âge : 43

    Informations forums :
    Inscription : Février 2007
    Messages : 106
    Par défaut
    Citation Envoyé par Médinoc
    Tu peux t'inspirer de ce que j'ai posté dans ce thread:
    http://www.developpez.net/forums/sho...d.php?t=248441
    ok je verais ca demain

  7. #7
    Membre confirmé
    Inscrit en
    Février 2007
    Messages
    106
    Détails du profil
    Informations personnelles :
    Âge : 43

    Informations forums :
    Inscription : Février 2007
    Messages : 106
    Par défaut
    voila, j'ai modifier ce p'tit bout de code mais j'ai simplement pris en compte un pointer simple de double. (On verra plus tard avec le char **name...).

    J'ai rajouter des verifications pour les retours de malloc() et realloc(). J'ai aussi utilise un pointer temporaire (double *tmp) pour eviter de perdre le pointer principal en cas d'erreur.

    Qu'en pensez-vous ?

    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    #define oops(s)          { perror((s)); exit(1); }
     
    int main()
    {
     
    double *tab;
    double *tmp;
     
     
    int i;
    int n = 10;
    int increment = 5;
    int current_size=0;
    int isecret;
     
    /*initial dynamic allocation*/
    tab=malloc(sizeof(double)*n);
    if(tab==NULL){oops("Error: malloc()");} 
     
     
    /*----loop starts----*/
     
    isecret  = rand() % 100 + 1;
    for(i=0;i<isecret;i++){ 
     
        tab[i] = rand() % 10;
     
        printf("current_size=%d  n=%d\n",current_size,n);
     
        if(current_size>=(n-1)){ /*if initial allocation filled up*/
     
            printf("realloc at %d\n",n+increment);               
     
            tmp=realloc(tab,sizeof(double)*(n+increment));
            if(tmp==NULL){oops("Error: realloc()");}           
     
            n += increment;                   
            tab = tmp;
     
        }
     
    current_size++;
    } 
    /*----loop ends----*/
     
     
    /*if realloc'ed too much memory*/ 
    if(n>current_size){ 
     
       /*realloc down to the right value*/                 
       printf("final realloc at %d\n",current_size); 
     
       tmp = (double*)realloc(tab,sizeof (double) * current_size);
       if(tmp==NULL){oops("reallocc() error");}
       tab = tmp;
     
    }
     
    for(i=0;i<current_size;i++){printf("tab[%d]=%1.1f\n",i,tab[i]);}
     
    free(tab);
    free(tmp);
     
    return 0;
    }/*end main*/
    Dois-je faire un free(tmp) avant chaque tmp=realloc(tab,sizeof(double)*(n+increment)) ??

    merci

  8. #8
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    Non, pas de free(tmp). Jamais.
    Par contre, tu pourrais rajouter un free(tab) juste avant le oops() en cas d'échec de realloc().

    Et aussi, je pense que dans la boucle i et current_size pourraient être la même variable. Mais surtout, tu devrais réallouer AVANT de modifier tab[i].

    L'algorithme devrait être:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    BOUCLE
       SI tableau trop petit pour la valeur actuelle de i
       ALORS
          on agrandit
       FIN SI
       enregistrer tableau[i]
    FIN BOUCLE
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  9. #9
    Membre confirmé
    Inscrit en
    Février 2007
    Messages
    106
    Détails du profil
    Informations personnelles :
    Âge : 43

    Informations forums :
    Inscription : Février 2007
    Messages : 106
    Par défaut
    Je suis d'accord mais comme je verifie avec n-1 dans
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if(current_size>=(n-1)){}
    il ne devrait pas y avoir de problemes, non ?
    Quand i=n-1, on a atteint la derniere valeur de tab possible et j'ai aggrandit donc pour la prochaine valeur.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Lire un fichier par bloc de n*m bytes
    Par chaka_zulu dans le forum Langage
    Réponses: 1
    Dernier message: 24/05/2007, 07h26
  2. Réponses: 1
    Dernier message: 06/05/2007, 11h10
  3. Réponses: 9
    Dernier message: 21/11/2006, 11h16
  4. Lecture de fichier par blocs
    Par nicolas66 dans le forum C++
    Réponses: 12
    Dernier message: 11/11/2006, 20h36
  5. lecture par blocs dans un fichier avec marqueur
    Par cheikh_tk dans le forum C
    Réponses: 3
    Dernier message: 06/06/2006, 16h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo