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 :

malloc/realloc sur des structures ? methode ?


Sujet :

C

  1. #1
    Expert éminent sénior Avatar de frp31
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Juillet 2006
    Messages
    5 196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juillet 2006
    Messages : 5 196
    Points : 12 264
    Points
    12 264
    Par défaut malloc/realloc sur des structures ? methode ?
    Bonjour tous,

    avant de commencer
    j'ai des structures de type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    typedef struct
    {
      short x;
      short y;
      short z;
    } point;
    point *p ;
    point liste[NPI];
    NPI vaut 64 au début du programme

    le programme sera porté sur des bécanes antiques (1973 à 1990) donc je dois
    tester si la mémoire est suffisante au début du programme
    je pensais à quelque chose du style :
    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
    int main(void)
    {
      if((p=malloc(sizeof(struc point) * NPI)) == NULL)
      {
         /* ne pas lancer */
         fprintf(stderr,"\\nn\t%s\n\n", message(memoire));
         exit(1);
      }
      /* sinon effectuer la reservation */
      p=malloc(sizeof(struc point) * NPI);
      /* ici les traitements */
      /* dont une boucle pour remplir les coordonnees*/
        if (scanf(" %d %d %d", &p[i].x, &p[i].y, &p[i].z) == 3)
        {
            /* traitement normal */
            scanf(" %d %d %d", &p[i].x, &p[i].y, &p[i].z);
            liste[i]=p;
        }
        else
        {
            /* erreur ! */
            fprintf(stderr,"\\nn\t%s\n\n", message(saisie));
        }
     
      /* fin de boucle des saisies*/
    déjà est ce que je commets des erreurs à ce niveau ?

    et surtout je compte proposer à l'utilisateur de traiter des coordonnées supplémentaires donc je devrai agrandir la liste[]

    quelle est la syntaxe pour realloc sur la struct list[NPI] ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    liste[] = ralloc (liste[], ((sizeof(strcut point) * nvl_taille));
    devrai ne pas marcher je suppose ? alors comment le faire ?

    merci
    désolé pour les questions qui peuvent paraitre bêtes mais j'ai du mal à m'y remettre au C et les docs ne sont pas très claires voire existantes sur ce point précis.

  2. #2
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Salut,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
      if((p=malloc(sizeof(struc point) * NPI)) == NULL)
      {
         /* ne pas lancer */
         fprintf(stderr,"\\nn\t%s\n\n", message(memoire));
         exit(1);
      }
      /* sinon effectuer la reservation */
      p=malloc(sizeof(struc point) * NPI);
    Ici, tu fais deux allocations et tu perds l'adresse du premier bloc alloué (fuite de mémoire).

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  3. #3
    Expert éminent sénior Avatar de frp31
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Juillet 2006
    Messages
    5 196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juillet 2006
    Messages : 5 196
    Points : 12 264
    Points
    12 264
    Par défaut
    ah ? et zut ...


    alors comment le faire proprement ?

  4. #4
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    A part cela ton programme a peu de chance de compiler tel quel:
    1. Il manque les fichiers d'en-tête
    2. liste n'est pas déclaré, comme p d'ailleurs (si tu définit main, autant écrire un code qui compile...)
    3. fuite de mémoire suite à deux appels à malloc
    4. Quelle utilité d'appeler deux fois scanf comme tu le fais

    D'ailleurs scanf n'est pas le choix le plus judicieux pour les entrées utilisateur. En tous les cas, c'est une fonction réservée aux spécialistes, et le commun des mortels comme moi utilises fgets, éventuellement avec sscanf ou une analyse à la main.

    En ce qui concerne ton utilisation de realloc:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    liste[] = realloc (liste[], ((sizeof(strcut point) * nvl_taille));
    liste[] n'est pas une syntaxe correcte en C et ne peut être utiliser que comme paramètre formel d'une fonction où la notation type liste[] est équivalente à type *liste. En ce qui concerne realloc, je procéderais de la manière suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct point *list;
    /*...*/
    {
        struct point *tmp;
        tmp = realloc(list, sizeof(*tmp) * nvl_taille);
        if (tmp == NULL)
        {
            /*réaction au cas où la réallocation échoue */
        }
        list = tmp;
    }
    Pour tout savoir et même plus sur l'allocation dynamique en C:
    http://rperrot.developpez.com/articles/c/allocationC/

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  5. #5
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par frp31
    ah ? et zut ...


    alors comment le faire proprement ?
    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
    #include <stdio.h>
    #include <stdlib.h>
     
    struct point {
        int x;
        int y;
        int z;
    };
     
    int main(void)
    {
        struct point *p;
        char s_buffer[20];
     
        p = malloc(NPI * sizeof(*p));
        if (p == NULL)
        {
            fprintf(stderr, "L'allocation a malheureusement échoué...\n");
            exit(EXIT_FAILURE);
        }
        /*...*/
        fgets(s_buffer, sizeof s_buffer, stdin);
        /* analyse du contenu de s_buffer et appel de sscanf, ou travail à la main
            avec appels à strtol, strtoul ou strtod */
        /*...*/
        return EXIT_SUCCESS;
    }
    Pour l'utilisation de realloc(), voir mes posts précédents et l'excellent tutoriel dont je t'ai donné le pointeur.

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  6. #6
    Expert éminent sénior Avatar de frp31
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Juillet 2006
    Messages
    5 196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juillet 2006
    Messages : 5 196
    Points : 12 264
    Points
    12 264
    Par défaut
    A part cela ton programme a peu de chance de compiler tel quel:
    1. Il manque les fichiers d'en-tête
    non mais je les affiche pas sur le forum c'est pour pas faire un message trop long et peu lisible
    2. liste n'est pas déclaré, comme p d'ailleurs (si tu définit main, autant écrire un code qui compile...)
    meme raison
    3. fuite de mémoire suite à deux appels à malloc
    là ok et je te remercie
    4. Quelle utilité d'appeler deux fois scanf comme tu le fais
    hé bien je cite le conseil qu'on m'a donné sur d'autres progs :

    scanf dans une boucle attention :
    L'utilisation "propre" de scanf est très difficile, car les traitements d'erreur ne sont pas simples. Si une entrée ne respecte pas le bon format, alors scanf s'arrête sans "consommer" l'entrée standard. Si tu boucles sans vérifier le bon fonctionnement de scanf, et sans "consommer" toi-même l'entrée standard quand il y a une erreur, tu causes une boucle infinie de tout programme.


    d'où cette protection envers le scanf. mais bon avec fgets ce problème n'existera plus.

    je sais je suis casse pied à poser des questions qui semblent évidentes à des experts, mais c'est justement parce que je ne suis pas expert et que j'ai accès à peu de doc efficaces que j'ai des requetes...

    en tout cas merci avec tout tes conseils je crois que je vais y arriver.
    même si comme je le rappelle je compile sur des rognes avec des vieilles versions de gcc ce qui pose aussi certains problèmes... mais ça c'est un faut problème puisque je peux utiliser la cross compilation si necéssaire.

  7. #7
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par frp31
    non mais je les affiche pas sur le forum c'est pour pas faire un message trop long et peu lisible
    Dans ce cas pourquoi définir la fonction main...
    Citation Envoyé par frp31
    hé bien je cite le conseil qu'on m'a donné sur d'autres progs :

    scanf dans une boucle attention :
    L'utilisation "propre" de scanf est très difficile, car les traitements d'erreur ne sont pas simples. Si une entrée ne respecte pas le bon format, alors scanf s'arrête sans "consommer" l'entrée standard. Si tu boucles sans vérifier le bon fonctionnement de scanf, et sans "consommer" toi-même l'entrée standard quand il y a une erreur, tu causes une boucle infinie de tout programme.
    Dans ton cas, tu ne protèges rien du tout:
    Citation Envoyé par frp31
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    if (scanf(" %d %d %d", &p[i].x, &p[i].y, &p[i].z) == 3)
        {
            /* traitement normal */
            scanf(" %d %d %d", &p[i].x, &p[i].y, &p[i].z);
            liste[i]=p;
        }
    Lors de ton 1er appel à scanf, tu vas devoir entrer 3 entiers. Si l'entrée est ok, scanf va lire ces 3 valeurs, les convertir en int et stocker le résultat dans les variable correspondantes. Si tout se passe bien, scanf retourne 3 et tu rendres dans le corps de if.

    Là, un nouvel appel à scanf va faire que le système va à nouveau attendre que tu entres 3 entiers au clavier et que tu valides ton entrée. Seulement, cette fois, tu ne contrôles pas la valeur de retour de scanf...

    Citation Envoyé par frp31
    d'où cette protection envers le scanf. mais bon avec fgets ce problème n'existera plus.

    je sais je suis casse pied à poser des questions qui semblent évidentes à des experts, mais c'est justement parce que je ne suis pas expert et que j'ai accès à peu de doc efficaces que j'ai des requetes...
    fgets est effectivement plus facile d'utilisation et te permet de valider l'entrée de l'utilisateur avant de faire éventuellement appel à sscanf. Pour tout savoir sur la fonction scanf: http://xrenault.developpez.com/tutoriels/c/scanf/ (excellent, mais trop fort pour moi).

    Tu n'est pas casse-pieds, je suis débutant moi-aussi...

    Citation Envoyé par frp31
    en tout cas merci avec tout tes conseils je crois que je vais y arriver.
    même si comme je le rappelle je compile sur des rognes avec des vieilles versions de gcc ce qui pose aussi certains problèmes... mais ça c'est un faut problème puisque je peux utiliser la cross compilation si necéssaire.
    Je n'ai aucune expérience des vieilles architectures. C89 est bien supporté sur un très grand nombre d'architectures matérielles (même certaines rognes dont tu parles). Si tu appliques scupuleusement la norme, tu devrais t'économiser certains soucis (bien sûr, il y a des fois ou ce n'est pas possible). Je ne connais aucun langage qui soit aussi portable que le C...

    Bonne chance

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

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

Discussions similaires

  1. tableau de pointeur pointant sur des structures.
    Par sandball22 dans le forum C
    Réponses: 10
    Dernier message: 19/08/2009, 20h15
  2. des difficultés sur des methodes
    Par bambi98 dans le forum UML
    Réponses: 4
    Dernier message: 12/12/2006, 09h32
  3. Débutant: Question sur l'utilisation des structures
    Par pdgnr dans le forum C++Builder
    Réponses: 5
    Dernier message: 26/10/2006, 13h03
  4. Operations bit à bit sur des structures
    Par DarkNagash dans le forum C
    Réponses: 4
    Dernier message: 16/03/2006, 13h59
  5. Methode de programmation sur des gros projets
    Par dynobremo dans le forum EDI
    Réponses: 10
    Dernier message: 08/06/2004, 02h59

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