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

Langage C++ Discussion :

Stockage de structures de taille aléatoire


Sujet :

Langage C++

  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2011
    Messages : 91
    Par défaut Stockage de structures de taille aléatoire
    Bonjour à tous,

    Alors voilà, j'ai une problématique touchant au langage C++ (mais j'utilise Qt)
    Voici mon cas :

    J'ai une QTableWidget et en parallèle un tableau de structures. Chaque colonne de la QTableWidget correspond à une variable de la structure et chaque ligne correspond à une structure du tableau. La QTableWidget permet de remplir mon tableau de structure.

    Mon but maintenant est de pouvoir stocker ce tableau de structure dans un fichier et de pouvoir la récupérer. Cela serait facile si dans la structure il y avait que des int, char, bool, char[x], etc.. Le problème c'est qu'il y a aussi des chaines de caractères de taille aléatoire.

    En exemple, prenons la structure suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    typedef struct s_test
    {
      int    a;
      char  b;
      char  c[10];
    }                   t_test;
    Pour la stocker (En utilisant l'objet QFile)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    t_test test;
    file.write((const char*)&test, sizeof(t_test));
    Pour la récupérer (Toujours en utilisant QFile)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    t_test test;
    file.read((char*)&test, sizeof(t_test));
    Tout cela marche parfaitement mais est ce possible de pouvoir faire de même avec une structure contenant une variable c de type char* ou char[] ou même de type QString ou *QString?

    Ou bien, autre solution, je pourrais à la place de stocker mes chaines de caractères directement dans ma structure, je pourrai y stocker un index qui représenterai une clé d'une QMap ou std::map qui serait prototypé comme cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    QMap<int; char*> map;
    ou
    QMap<int; char[]> map;
    ou
    QMap<int; QString> map;
    ou
    QMap<int; *QSrting> map;
    Reste à savoir si je pourrai la stocker ou non? Même problème..
    En espérant avoir été le plus clair possible.
    Merci d'avance.

  2. #2
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    sizeof, non, ca ne marchera pas.
    par contre, tu peux implémenter toi meme un calcul de taille.

  3. #3
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Salut

    C'est volontaire de faire du code C-like, plutôt que du C++ ? Surtout que Qt fournit pas mal d'outils pour les fichiers, c'est quand même s'embêter pour rien.

    (HS : c'est quoi ce typedef devant struct ? C'est inutile en C++)

    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
    struct s_test
    {
      qint32 a;
      char b;
      QString c;
    }
     
    QTextStream& operator << (QTextStream& stream, s_test const& t) {
        stream << t.a << t.b << t.c;
    }
     
    QTextStream& operator >> (QTextStream& stream, s_test& t) {
        stream >> t.a >> t.b >> t.c;
    }
     
    QFile file("toto.txt");
    QTextStream stream(file);
     
    s_test t;
    stream << t;
     
    QMap<int, QString> map;
    stream << map;
     
    QMap<int, s_test> map;
    stream << map;
    C'est quand même plus simple, non ?

  4. #4
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2011
    Messages : 91
    Par défaut
    Merci pour vos réponses aussi rapides.
    Par contre j'aurai du préciser que j'ai simplifié la structure à deux trois variables, la vérité c'est que dans la structure il y a d'autres structures, qui contiennent encore d'autres structures et qui contiennent des dizaines de variables donc non merci pour le QDatastream et les "<<" pour stocker et les ">>" pour récupérer

    C'est pour cela que j'aimerai bien arriver à écrire la structure d'un coup avec un write et la récupérer avec un read.. J'aimerai bien savoir ce qu'il se passe quand je fais cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    struct s_test
    {
      char *toto;
    }
     
    s_test test;
    test.toto = strdup("coucou les gens");
    QFile file("toto.txt");
    file.write((const char*)&test, sizeof(s_test));
    L'adresse de la chaine est stockée dans le fichier?

    (HS : Et désolé pour le typedef j'ai toujours fais ça en C alors j'ai continué en C++ )

  5. #5
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Bah si, il suffit d'écrire ces opérateurs pour les différentes structures.

    PS: Je me disais bien que Qt ne pouvais pas être si C-esque

  6. #6
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Citation Envoyé par DarKaa Voir le message
    Merci pour vos réponses aussi rapides.
    Par contre j'aurai du préciser que j'ai simplifier la structure à deux trois variables, la vérité c'est que dans la structure il y a d'autres structures, qui contiennent encore d'autres structures et qui contiennent des dizaines de variables donc non merci pour le QDatastream et les "<<" pour stocker et les ">>" pour récupérer

    C'est pour cela que j'aimerai bien arriver à écrire la structure d'un coup avec un write et la récupérer avec un read.. J'aimerai bien savoir ce qu'il se passe quand je fais cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    struct s_test
    {
      char *toto;
    }
     
    s_test test;
    test.toto = strdup("coucou les gens");
    QFile file("toto.txt");
    file.write((const char*)&test, sizeof(s_test));
    L'adresse de la chaine est stockée dans le fichier?

    (HS : Et désolé pour le typedef j'ai toujours fais ça en C alors j'ai continué en C++ )
    Et tu fais quoi si tu dois modifier l'une des sous-sous-sous-sous structure ? Tu réécris ton read et write, en espérant ne pas faire d'erreur ?
    En termes d'abstraction, il n'y a probablement pas plus moisi d'écrire un seul read+write pour l'ensemble des structures (et je parle même pas de conception, je ferais pas la liste des principes de POO non respectés)

    Le fait de venir du C te fait croire que le C++ n'est pas un langage différent... et c'est une grosse erreur. Apprend à écrire du code simple et correcte en C++ (chaque opérateur prend 1 ligne à écrire, c'est pas la mort), ça t'évitera de perdre du temps à débuger

  7. #7
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2011
    Messages : 91
    Par défaut
    Si les structures ne comprenaient que des structure ou éléments de tailles fixes. Pour modifier une valeur je récupère la structure globale avec un read et ensuite c'est à coup de struct1.struct2.struct3.variableAModifier = valeurSouhaitée avant de write. Je ne vois pas comment faire plus simple..

    Le gros problème est que je n'ai pas QUE des éléments de tailles fixes..

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 157
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 157
    Billets dans le blog
    4
    Par défaut
    Salut,
    Citation Envoyé par DarKaa Voir le message
    c'est à coup de struct1.struct2.struct3.variableAModifier = valeurSouhaitée avant de write.
    Comment tu accèdes à tes membres n'a rien à voir avec leur (dé)sérialisation.

    Surcharger les opérateurs est de très (trèèèèès) loin la meilleure solution.

    Tu vois pas comment faire plus simple ? J'annonce que ta "solution" est au mieux source de problème.
    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
    struct S1 {
     int i;
     char c;
     std::string s;
     
     std::ostream& operator<<(std::ostream& out) const {
      out<<i<<std::endl;
      out<<c<<std::endl;
      out<<s<<std::endl;
      return out;
     }
    };
    struct S2 {
     S1 s;
     float f;
     
     std::ostream& operator<<(std::ostream& out) const {
      out<<s<<std::endl;
      out<<f<<std::endl;
      return out;
     }
    };
     
    S2 s;
    s.f = 5.0f;
    s.s.i = 0;
    s.s.c = 'u';
    std::cout<<s;
    A quel niveau tu vois de la difficulté ?!
    Si je modifie S1, je modifie uniquement son opérateur.

    Quant au problème de la taille d'un élément, c'est un faux problème.
    C'est toi qui fais la (dé)sérialisation, tu décides de ton format. Si la taille est "inconnue", tu as plusieurs options, dont les premières qui me viennent à l'esprit
    - précéder la valeur d'un int avec la taille à lire derrière (cas typique d'une sérialisation de char*)
    - terminer les données d'un caractère spécial (ce qui est exactement ce qui est fait avec une chaîne de type char* en C !! et le \0 final)
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  9. #9
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par DarKaa Voir le message
    Si les structures ne comprenaient que des structure ou éléments de tailles fixes. Pour modifier une valeur je récupère la structure globale avec un read et ensuite c'est à coup de struct1.struct2.struct3.variableAModifier = valeurSouhaitée avant de write. Je ne vois pas comment faire plus simple..

    Le gros problème est que je n'ai pas QUE des éléments de tailles fixes..
    Salut,

    A part si tu décide d'écrire un fichier binaire en utilisant des tailles arbitraires, tu te fous pas mal du fait que les éléments de tes structures n'aient pas une taille fixe

    La première chose à faire, comme l'a si bien fait remarqué gbdivers, c'est, bien sur, d'utiliser les opportunités fournies par le langage et ou par Qt et par "jeter à la poubelle" tes vieilles habitudes issues du C (ou, du moins, de les classer dans un tiroir pour le cas où tu devras coder en C )

    La deuxième chose à faire, spécifique à la sérialisation / désérialisation , c'est de surcharger, pour chaque structure, les opérateur << et >>, respectivement pour les ostream et les istream.

    Ainsi, tu pourrais avoir une structure (la plus petite qui soit utilisée) qui n'utiliserait que des types primitifs ou apparentés (comprends: des types pour lesquels il existe déjà des surcharge de ces opérateurs, comme std::string, par exemple), et te contenter de fonctions libres proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    std::ostream & operator << (std::ostream & ofs, PetiteStructure const & s)
    {
        ofs<< s.membre1<<" "<<s.membre2<<" "<<s.membre3;
    }
    std::istream & operator >> (std::istream & ifs, PetiteStructure & s)
    {
        ifs>> s.membre1>>s.membre2>>s.membre3;
    }
    Puis, il y aurait bien sur une structure qui l'utilise, entre autres choses, pourquoi pas, sous la forme d'un tableau :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    struct UtilisePetiteStructure
    {
        int x;
        std::string y;
        std::vector<PetiteStructure> allStructs;
    };
    Comme tu as déjà fourni une surcharge des opérateur << et >> pour PetiteStructure, tu peux te contenter d'un
    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
    std::ostream & operator << (std::ostream & ofs, PetiteStructure const & s)
    {
        ofs<< s.x<<" "<<s.y<<" "<<allStruct.size();
        for (size_t i = 0; i<allStructs.size();++i)
        {
            ofs<<allStruct[i];
        }
    }
    std::istream & operator >> (std::istream & ifs, UtilisePetiteStructure& s)
    {
        size_t size;
        ifs>> s.x>>s.y>>size;
        for (size_t i = 0; i<size;++i)
        {
            PetiteStructure temp;
            ifs>>temp;
            s.allStruct.push_back(temp);
        }
    }
    et tu pourrais continuer comme cela avec un nombre à peu près illimité de sous structures

    Ce qui importe, c'est, surtout, qu'il existe une surcharge des deux opérateurs pour chaque structure que tu veux lire ou écrire

    La seule chose à laquelle il faille penser c'est, si tu manipule des éléments de taille variable, à bien lire et / ou écrire la taille de ces éléments, de préférence avant d'essayer de lire et / ou d'écrire les éléments en question (simplement pour qu'il te soit possible de t'arrêter quand le compte est atteint)
    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

  10. #10
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2011
    Messages : 91
    Par défaut
    Citation Envoyé par koala01 Voir le message
    A part si tu décide d'écrire un fichier binaire en utilisant des tailles arbitraires, tu te fous pas mal du fait que les éléments de tes structures n'aient pas une taille fixe
    C'est exactement cela que je dois faire.. Cela change quelque chose à la solution proposée?

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par DarKaa Voir le message
    C'est exactement cela que je dois faire.. Cela change quelque chose à la solution proposée?
    Ca change surtout que tu dois, d'abord et avant tout, veiller à rester dans les limites de tes tailles arbitraires.

    Mais si tu as un problème au niveau du respect de ces tailles, lorsque tu veux lire ou écrire les données, il est déjà trop tard pour y changer quoi que ce soit
    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

  12. #12
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    91
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2011
    Messages : 91
    Par défaut
    Ok Ok. Je vais tester cela. Merci à tous !

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

Discussions similaires

  1. Réponses: 15
    Dernier message: 23/04/2013, 23h45
  2. variable de taille aléatoire
    Par syki.mail dans le forum MATLAB
    Réponses: 11
    Dernier message: 23/04/2012, 13h50
  3. Images de taille aléatoire
    Par sam01 dans le forum Mise en page CSS
    Réponses: 2
    Dernier message: 03/10/2009, 23h02
  4. Réponses: 9
    Dernier message: 21/05/2008, 15h56
  5. Réponses: 7
    Dernier message: 08/12/2005, 10h26

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