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 :

Réallocation en boucle


Sujet :

C

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2010
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2010
    Messages : 21
    Points : 21
    Points
    21
    Par défaut Réallocation en boucle
    Mon soucis dans ma ré-allocation dans cet exemple est qu'elle est impossible au delà du deuxième tour. Donc j'en déduis à une erreur de logique de ma part.

    Nous devons utiliser deux styles d'écritures des pointeurs.

    La première version avec laquelle j'ai des soucis.

    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
     
     
    void exo391b2()
    {
        /* déclaration de variable*/
        int n,i = 0;
        int *leptrnumber = NULL, *leptrfirst = NULL;
        int *test = NULL;
        int new_taille;
     
        system("cls");
     
        leptrnumber = malloc(sizeof(int));
        leptrfirst = leptrnumber;
        printf("\nIntroduire une serie de nombre - 0 est la condition d'arret\n");
        do
        {
            printf("Le nombre n %2d : ", i + 1); scanf("%d", &n);
            if (n != 0)
            {
                new_taille = (i + 1) * sizeof(int);
                test = realloc(leptrnumber, new_taille);
     
                if (test != NULL)
                {
                    leptrnumber = test;
                    *leptrnumber = n;
                    leptrnumber = leptrnumber + 1;
                    i++;
                }
                else
                {
                    fprintf(stderr,"Allocation impossible");
                    exit(EXIT_FAILURE);
                }
            }
     
        }while(n != 0);
     
        leptrnumber = leptrfirst;
        for(n = 0; n < i; n ++)
        {
            printf("\nLe numero %2d introduit est : %d", n + 1, *leptrnumber);
            leptrnumber = leptrnumber + 1;
        }
     
        leptrnumber = NULL;
        test = NULL;
        free(leptrfirst) ;
     
        printf("\n\n");
        system("pause");
        system("cls");
    }
    Et l'écriture qui semble fonctionner et que je comprends mieux

    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
     
    void exo391b1()
    {
        /* déclaration de variable*/
        int n, i = 0;
        int *leptrnumber = NULL;
        int *test = NULL;
     
        system("cls");
     
        leptrnumber = malloc(sizeof(int));
        printf("\nIntroduire une serie de nombre - 0 est la condition d'arret\n");
        do
        {
            printf("Le nombre n %2d : ", i + 1); scanf("%d", &n);
            if (n != 0)
            {
                test = realloc(leptrnumber, (i + 1) * sizeof(int));
                if (test != NULL)
                {
                    leptrnumber = test ;
                    leptrnumber[i] = n;
                    i = i + 1;
                }
                else
                {
                    fprintf(stderr,"Allocation impossible");
                    exit(EXIT_FAILURE);
                }
     
     
            }
     
        }while(n != 0);
     
        for(n = 0; n < i; n ++)
        {
            printf("\nLe numero %2d introduit est : %d", n + 1, leptrnumber[n]);
        }
     
     
        printf("\n\n");
        system("pause");
        system("cls");
    }
    Donc si vous pouviez m'aiguillez à résoudre la première. Je me doute que d'utiliser une boucle à chaque traitement est une méthode fastidieuse mais comme on ne connait pas le nombre de chiffre que l'utilisateur va introduire. Et qu'on sort de notre boucle d'insertion par la valeur introduite 0.

  2. #2
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2011
    Messages
    1 186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2011
    Messages : 1 186
    Points : 2 502
    Points
    2 502
    Par défaut
    Bonsoir,

    Le problème vient du fait qu'à la 2ème boucle, la fonction realloc est appelée sur un pointeur qui a été déplacé sur une mémoire pas encore allouée...

    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
    void exo391b2()
    {
        //...
        do
        {  
            //....
            if (n != 0)
            {
                //alloue de la mémoire à partir de leptrnumber
                test = realloc(leptrnumber, new_taille);
     
                if (test != NULL)
                {
                    //...
                    //déplace le pointeur un int plus loin, sur mémoire non allouée
                    leptrnumber = leptrnumber + 1; 
                    
                    //...
                }
                //...
            } 
        }while(n != 0);
    Solution possible : utiliser leptrfirst (pointeur sur le premier mot du tableau) au lieu de leptrnumber qui se déplace sur le tableau.

    Attention : realloc peut déplacer le bloc mémoire , s'il ne trouve plus de mémoire contigue.
    Pense à mettre à jour leptrfirst et leptrnumber en conséquence.

  3. #3
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2010
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2010
    Messages : 21
    Points : 21
    Points
    21
    Par défaut
    Merci je vais regarder à cela. Je vous tiendrai au courant de l'évolution.
    Et j'ajouterais résolu dés que je l'aurais corrigé.

    EDIT :

    J'ai encore du mal à tout bien saisir, si tu as le temps de m'expliquer avec un exemple. Surtout comme tu dis je dois faire attention donc à la possibilité de changement "déplacement" de zone mémoire.

  4. #4
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2011
    Messages
    1 186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2011
    Messages : 1 186
    Points : 2 502
    Points
    2 502
    Par défaut
    Bonjour,

    J'ai encore du mal à tout bien saisir ...
    En précisant qu'elle partie n'est pas claire, ça aidera à expliquer ce qui n'est pas clair, en éviterait un post à rallonge.

    1) Explication pour ça ne marche pas :


    Les variables leptrnumber et leptrfirst sont des pointeurs sur des entiers.
    Le tableau d'entier sur lequel ils pointent est alloué dynamiquement. (malloc, realloc).

    Dans l'exemple qui fonctionne void exo391b1(), les pointeurs ne sont pas déplacés à l'intérieur de la zone allouée.
    Ils pointent toujours sur le début du tableau obtenue par le malloc ou le realloc.
    Pour accéder aux éléments de ce tableau, on utilise les indices :
    leptrnumber[0] // premier élément du tableau
    leptrnumber[1] // deuxième élément du tableau ...

    Dans l'exemple qui ne fonctionne pas void exo391b2(), le pointeur leptrnumber se déplace sur la mémoire allouée avec l'instruction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    leptrnumber = leptrnumber +1;
    La première fois qu'on exécute cette instruction, le pointeur pointe sur un entiers après le début du tableau,
    la deuxième fois, sur le 2ème entier du tableau ....
    Donc pour écrire dans le tableau, il ne suffit plus que de déréférencer le pointeur *leptrnumber = <un nombre>;
    Comme le pointeur se déplace sur la zone allouée, plus besoin d'utiliser d'indice leptrnumber[<i ème entier du tableau].
    Par contre l'instruction realloc, re-alloue de la mémoire à partir d'une position mémoire (indiquée par un pointeur). Comme leptrnumber se déplace sur la zone mémoire (et donc ne pointe plus sur le début du tableau), on ne peut pas l'utiliser pour ré-allouer de la mémoire.
    Il faut en effet un pointeur sur le début du tableau à déplacer.



    2) Pourquoi il faut faire attention au déplacement de la mémoire :


    La fonction realloc redimensionne la mémoire allouée pour un tableau.
    Si elle trouve assez de mémoire de façon contigue à la mémoire actuellement utilisée, la d'adresse de début de tableau ne change pas.
    Donc la valeur stocké dans le pointeur leptrnumber ne change pas (comme l'adresse mémoire n'a pas changée).
    Mais si elle ne trouve pas assez de mémoire contigue, elle désalloue la mémoire, et déplace le tableau dans une autre zone mémoire plus grande. Dans ce cas l'adresse stockée dans le pointeur leptrnumber doit être actualisée. (puisque la zone mémoire n'est plus au même endroit).
    D'où le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
       test = realloc(leptrnumber, new_taille);
       if (test != NULL)
       {
          leptrnumber = test;
       }

  5. #5
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2010
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2010
    Messages : 21
    Points : 21
    Points
    21
    Par défaut
    Ok je vois un peu plus clair.

    Donc si je te comprends

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    leptrnumber = leptrnumber + 1;
    n'est pas nécessaire ?

    Dés lors pour réactualiser la bonne adresse, dans quelle partie de mon code je dois faire attention.
    Pour le moment j'ai encore un peu de mal à le résoudre( j'ai tellement de projet en C que je suis un peu brouillon devant l'écran).

    Car actuellement ma correction ne retient que le dernier chiffre introduit. Le reste affiche des adresses d'autres sections mémoires.

    Donc je vais encore relire plusieurs fois ton message.

  6. #6
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2011
    Messages
    1 186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2011
    Messages : 1 186
    Points : 2 502
    Points
    2 502
    Par défaut
    Bonjour,

    Donc si je te comprends leptrnumber = leptrnumber + 1; n'est pas nécessaire ?

    Si j'ai bien compris, le but de l'exercice void exo391b2() est d'utiliser une autre méthode pour écrire dans un tableau que d'utiliser un indice. (avec leptrnumber[i])

    Une des ces autres solutions est de déplacer un tableau (leptrnumber = leptrnumber + 1;) ou plus communément écrit leptrnumber++; )
    Puis pour écrire à cet emplacement (qui se déplace au fur et à mesure) avec *leptrnumber = <valeur>;.

    Donc si, déplacer le pointeur sur le tableau est nécessaire pour montrer une autre méthode d'écriture dans un tableau.
    Mais en même temps, il faut donner à la fonction realloc, un pointeur qui contient toujours l'adresse du début du tableau.
    Donc on le lui donnera pas leptrnumber directement.

  7. #7
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2010
    Messages
    21
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2010
    Messages : 21
    Points : 21
    Points
    21
    Par défaut
    Excuse moi de t'avoir fait répondre à une idiotie de ma part. Bien que je n'ai pas encore trouvé la solution. Je vais marqué le sujet résolu, j'ai suffisamment d'explication pour le résoudre.

  8. #8
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2011
    Messages
    1 186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2011
    Messages : 1 186
    Points : 2 502
    Points
    2 502
    Par défaut
    Y pas de problème.

    Bon courage pour l'exercice,
    et Bonnes Fêtes de fin d'année.

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

Discussions similaires

  1. [XSLT] Faire une boucle sur une variable [i]
    Par PoT_de_NuTeLLa dans le forum XSL/XSLT/XPATH
    Réponses: 8
    Dernier message: 07/06/2010, 12h45
  2. [langage] if et boucle { ..}
    Par kacedda dans le forum Langage
    Réponses: 15
    Dernier message: 28/04/2003, 17h25
  3. [directsound] boucle de traitement de son
    Par gargle dans le forum DirectX
    Réponses: 5
    Dernier message: 24/03/2003, 10h47
  4. Sortir d'un progamme qui boucle ou qui refresh
    Par mikevador02 dans le forum C
    Réponses: 12
    Dernier message: 14/12/2002, 09h38
  5. Réponses: 2
    Dernier message: 29/05/2002, 20h43

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