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 :

Tableau de chaînes de caractères


Sujet :

C++

  1. #1
    Membre à l'essai
    Inscrit en
    Mars 2007
    Messages
    43
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 43
    Points : 20
    Points
    20
    Par défaut Tableau de chaînes de caractères
    Bonjour,

    Je manipule des tableau de chaînes de caractères. Voici mon code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    char * Nomatt[SHE_TAILLE_NOMATT];
       char * Valatt[SHE_TAILLE_VALLAT];
     
       for (int i=0; i< NB_MAX_EXTRAS; i++)
       {
          Nomatt[i] = (char *)fde_evt.get_nomatt(i).c_str();
          Valatt[i] = (char *)fde_evt.get_valatt(i).c_str();
       }
    Pourtant, à la sortie de la boucle for, les chaînes de caractères dans les tableaux Nomatt et Valatt ne sont pas du tout celles retournées par les get_nomatt et get_valatt, mais ce sont des chaînes incompréhensibles.

    Qu'est ce que je fais de pas bien ?

  2. #2
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 61
    Points : 30
    Points
    30
    Par défaut
    tu finis bien tes chaines avec des \0 ?

  3. #3
    Membre à l'essai
    Inscrit en
    Mars 2007
    Messages
    43
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 43
    Points : 20
    Points
    20
    Par défaut
    Oui, puisque c_str() rajoute tout seul le caractère \0.

  4. #4
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    fde_evt.get_nomatt(i) retourne peut-être un objet temporaire, qui est détruit à la prochaine itération...
    Boost ftw

  5. #5
    Membre à l'essai
    Inscrit en
    Mars 2007
    Messages
    43
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 43
    Points : 20
    Points
    20
    Par défaut
    loufoque, c'était exactement ca. Ce qui est étrange, c'est que ce code fonctionnait sous Visual 6, mais plus sous Visual 8. J'ai corrigé ca en faisant des allocations dynamiques :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    char * Nomatt[SHE_TAILLE_NOMATT];
    char * Valatt[SHE_TAILLE_VALLAT];
     
    for (int i=0; i< NB_MAX_EXTRAS; i++)
    {
       Nomatt[i] = new char[TAILLE_MAX];
       Valatt[i] = new char[TAILLE_MAX];
       strcpy(Nomatt[i], fde_evt.get_nomatt(i).c_str());
       strcpy(Valatt[i], fde_evt.get_valatt(i).c_str());
    }
    Sans bien sûr oublier les delete[].

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 61
    Points : 30
    Points
    30
    Par défaut
    Attend j'avais pas vu le cast.
    Tu veux que le compilo cast un CString dans un char * ???
    Ca n'ettonerais que ca se fasse comme ca ... si ?

  7. #7
    Membre à l'essai
    Inscrit en
    Mars 2007
    Messages
    43
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 43
    Points : 20
    Points
    20
    Par défaut
    c_str() renvoie un (const char *). Je le cast en (char *) pour le mettre dans mon tableau. Mais de toute facon, je ne fais plus ce cast avec la solution que j'ai trouvé.

  8. #8
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Ton code est non exception-safe et comporte fort probablement des fuites.
    Fais un tableau de std::string, tout simplement....
    Boost ftw

  9. #9
    Membre à l'essai
    Inscrit en
    Mars 2007
    Messages
    43
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 43
    Points : 20
    Points
    20
    Par défaut
    Si ca ne tenait qu'a moi, j'aurai bien évidemment utilisé un tableau de string. Mais malheureusement, après je fais appel à une fonction qui attend un tableau de type (char **), et ca je ne peux pas le modifier... :/

  10. #10
    Membre à l'essai
    Inscrit en
    Mars 2007
    Messages
    43
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 43
    Points : 20
    Points
    20
    Par défaut
    Aussi, si à la fin de ma méthode, je fais un :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    for(int j = 0; j < NB_MAX_EXTRAS; j++)
       {
          delete[] Nomatt[j];
          delete[] Valatt[j];
       }
    pourquoi penses tu que j'aurai probablement des fuites mémoire ?

  11. #11
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Exemple simplifié :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    T* a = new T;
    T* b = new T;
    delete b;
    delete a;
    Si le deuxième "new T" lève une exception, la mémoire ne sera jamais libérée.
    Boost ftw

  12. #12
    Membre à l'essai
    Inscrit en
    Mars 2007
    Messages
    43
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 43
    Points : 20
    Points
    20
    Par défaut
    Ok je vois, il faudrait donc que j'entoure les allocations de try/catch, avec des delete[] dans le catch, c'est ca ?

  13. #13
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Le mieux est, toujours, de laisser la gestion dynamique de la mémoire à des éléments dont on sait qu'ils ont été créés, justement, pour la prendre en charge de manière cohérente et sécurisée.

    Ainsi, il n'y a rien à faire, la classe vector (ou toute autre classe de conteneur de ton choix parmi ceux de la STL) est à préférer de manière systématique aux différents tableaux "C style", surtout si tu envisage d'en gérer la taille de manière dynamique.

    De la même manière la classe string est à préférer aux chaines de caractères "C style", qui ne vont pas sans poser certains problèmes.

    Au final, ton code pourrait très bien ressembler à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    std::vector<std::string> Nomatt;
    std::vector<std::string> Valatt;
    for(int i=0; i< NB_MAX_EXTRAS; i++)
    {
        std::string nom=fde_evt.get_nomatt(i).c_str();
        std::string val=fde_evt.get_valatt(i).c_str();
        Nomatt.push_back(nom);
        Valatt.push_back(val);
    }
    et tous tes problèmes seraient résolus (nécessite l'inclusion des fichiers d'en-têtes <string> et <vector> )
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  14. #14
    Membre à l'essai
    Inscrit en
    Mars 2007
    Messages
    43
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 43
    Points : 20
    Points
    20
    Par défaut
    Bonjour koala,

    Comme je disais dans un post plus haut :

    Si ca ne tenait qu'a moi, j'aurai bien évidemment utilisé un tableau de string. Mais malheureusement, après je fais appel à une fonction qui attend un tableau de type (char **), et ca je ne peux pas le modifier... :/
    Je n'ai malheureusement pas trouvé une méthode simple pour transformer un std::vector<std::string> en (char **).

  15. #15
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Les blocs try/catch pour faire du clean-up ça pue.

    Voici une solution simple et portable, bien qu'un peu sous-optimale
    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
    boost::scoped_array<char> Nomatt[SHE_TAILLE_NOMATT];
    boost::scoped_array<char> Valatt[SHE_TAILLE_NOMATT];
     
    for (int i=0; i< NB_MAX_EXTRAS; i++)
    {
       const std::string& nom = fde_evt.get_nomatt(i).
       const std::string& val = fde_evt.get_valatt(i);
     
       Nomatt[i] = boost::scoped_array<char>(new char[nom.size()+1]);
       Valatt[i] = boost::scoped_array<char>(new char[val.size()+1]);
     
       memcpy(Nomatt[i].get(), nom.c_str(), nom.size()+1);
       memcpy(Valatt[i].get(), val.c_str(), val.size()+1);
    }
     
    char* Nomatt2[SHE_TAILLE_NOMATT];
    char* Valatt2[SHE_TAILLE_VALATT];
     
    for (int i=0; i< NB_MAX_EXTRAS; i++)
    {
        Nomatt2[i] = Nomatt[i].get();
        Valatt2[i] = Valatt[i].get();
    }
    J'ai aussi corrigé cette histoire de TAILLE_MAX.

    Pour que le code soit valide, il faut bien évidemment que NB_MAX_EXTRAS soit inférieur ou égal à SHE_TAILLE_*. (du coup, pourquoi ne pas utiliser directement NB_MAX_EXTRAS ?)

    Pour aller plus vite tu peux
    - Ne pas utiliser new[] qui initialise la mémoire à 0 mais un allocateur mémoire
    - Supposer que scoped_array<char> et char* sont compatibles binairement.
    Boost ftw

  16. #16
    Membre à l'essai
    Inscrit en
    Mars 2007
    Messages
    43
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 43
    Points : 20
    Points
    20
    Par défaut
    Merci pour toutes ces précisions !

Discussions similaires

  1. Réponses: 11
    Dernier message: 15/04/2008, 20h48
  2. Réponses: 13
    Dernier message: 18/07/2007, 09h01
  3. Tableau de chaînes de caractères
    Par sone47 dans le forum MATLAB
    Réponses: 2
    Dernier message: 27/02/2007, 14h54
  4. tableau de chaîne de caractères
    Par salseropom dans le forum C
    Réponses: 6
    Dernier message: 11/09/2006, 17h23
  5. Tableau de chaînes de caractères
    Par mac1 dans le forum Langage
    Réponses: 3
    Dernier message: 15/01/2006, 13h18

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