Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

fwrite de structure contenant une std::string

7 réponses
Avatar
Alexplose
Bonjour,

g un petit probleme en essayant d'ecrire une structure dans un fichier

ex:

struct toto
{
int test;
std::string data;
};

le champ data n'est pas ecrit dans le fichier si il est trop long.
je comprend pas trop en fait.
Ce serait pour faire un fichier binaire avec une suite de structure.

Merci d'avance

7 réponses

Avatar
Fabien SK
Alexplose wrote:
struct toto
{
int test;
std::string data;
};

le champ data n'est pas ecrit dans le fichier si il est trop long.
je comprend pas trop en fait.
Ce serait pour faire un fichier binaire avec une suite de structure.



Tu ne peux pas. Quand tu fais un "fwrite" d'une structure, tu sauves
l'image binaire de la structure. Si un membre est un pointeur sur
quelque chose, tu vas sauver le pointeur (ça te fait une belle jambe de
sauver dans ton fichier comme quoi des données se trouvaient à l'adresse
0x12ab014). Ce que tu dois faire est une fonction membre qui va écrire
dans le fichier tous les membres, et une autre qui va lire créer un
objet à partir du fichier.
Avatar
Thierry
Bonjour,

Alexplose a écrit :

struct toto
{
int test;
std::string data;
};



Quitte a utiliser la STL, autant faire du C++ propre :
(code approximatif)

fstream f("fichier.dat", ios::out | ios::binary);
f << toto.test << toto.data;

--
"MOI JE VEUX JOUER DE L'HELICON (PON PON PON PON)"
Avatar
Arnaud Debaene
Alexplose wrote:
Bonjour,

g un petit probleme en essayant d'ecrire une structure dans un fichier

ex:

struct toto
{
int test;
std::string data;
};

le champ data n'est pas ecrit dans le fichier si il est trop long.
je comprend pas trop en fait.



Tu essaies de sauver la représentation binaire en mémoire de ta structure.
Hors, cette représentation binaire est choisie et gérée par le compilateur
et tu n'as pas à la connaitre ni à t'en soucier : elle peut varier d'un
compilateur à l'autre, d'une version à l'autre du même compilateur ou même
avec le même compilateur selon que tu est en mode debug ou release.
Conclusion : tu ne peux pas te fier à cette représentation pour ta
sauvegarde. A la place, tu dois définir une représentation "sauvegardée" de
tes données et écrire des fonctions de conversion entre les 2
représentations. On appelle ça la sérialisation. En C++, les deux méthodes
de sérialisation sont généralement operator<< et operator>> quand on veut
faire unez représentation "texte" dans le fichier.

Arnaud
Avatar
flush+blood
A ce sujet, le manque d'une sérialisation XML dans la bibliothèque standard
pour le stockage sur disque ou la communication par sockets commence à faire
vraiment défaut au C++. Je ne parle pas des librairies existantes de XML,
mais de la possibilité de transformer le contenu d'une classe en XML comme
le permet C#.
Avatar
Arnaud Debaene
flush+blood wrote:
A ce sujet, le manque d'une sérialisation XML dans la bibliothèque
standard pour le stockage sur disque ou la communication par sockets
commence à faire vraiment défaut au C++. Je ne parle pas des
librairies existantes de XML, mais de la possibilité de transformer
le contenu d'une classe en XML comme le permet C#.



C'est en effet embêtant mais impossible en C++ pour une raison fondamentale
: il n' y a pas de metadata, et les types ne sont pas des "first-class
objects" en C++, donc on ne peut pas manipuler à l'exécution le type d'un
objet, ce qui est nécessaire pour l'introspection et ensuite la
serialisation / déserialisation automatique. C'est pour ca que le C++ est
dit un langage à typage statique.

Les quelques éléments de typage dynamique qui ont été introduits
relativement tardivement en C++ (dynamic_cast et typeid) sont inutilisables
pour la sérialisation du fait du peu de contraintes qu'ils imposent :
grosso-modo, l'identificateur de type (classe type_info) est spécifique au
compilateur et n'est même pas nécessairement le même d'une exécution à
l'autre du programme, sans parler du fait qu'elle ne décrit pas le contenu
de la classe. Je me demande bien d'ailleurs pourquoi avoir rendu typeid
aussi inutile (la méthode before, à quoi elle peut bien servir ????)... Je
me trompe peut-être, mais ca sent la guerre entre fabricants de compilateurs
au sein du comité C++.
Je cross-post sur fclc++ où quelqu'un pourra sans doute nous éclairer sur le
pourquoi du comment de l'état de la norme C++ sur ce sujet.

Notes au passage que cette "faiblesse" du C++ a au moins 2 avantages :
- vitesse (relativement) plus importante à l'exécution, même si c'est
compensé par la complexité de la syntaxe C++qui rend certaines optimisations
impossibles pour le compilateur (les alias de variables).
- quasi-impossibilité de décompiler un programme C++, alors que pour les
langages autorisant l'introspection, il faut recourir à des obfuscateurs
plus ou moins efficace pour protéger la structure de son programme. Est-ce
que c'est un avantage réel, on pourrait en discuter...

Arnaud
Avatar
Sébastien V.
"Arnaud Debaene" a écrit dans le message news:
3fc67658$0$26803$
flush+blood wrote:
> A ce sujet, le manque d'une sérialisation XML dans la bibliothèque
> standard pour le stockage sur disque ou la communication par sockets
> commence à faire vraiment défaut au C++. Je ne parle pas des
> librairies existantes de XML, mais de la possibilité de transformer
> le contenu d'une classe en XML comme le permet C#.

C'est en effet embêtant mais impossible en C++ pour une raison


fondamentale
: il n' y a pas de metadata, et les types ne sont pas des "first-class
objects" en C++, donc on ne peut pas manipuler à l'exécution le type d'un
objet, ce qui est nécessaire pour l'introspection et ensuite la
serialisation / déserialisation automatique. C'est pour ca que le C++ est
dit un langage à typage statique.

Les quelques éléments de typage dynamique qui ont été introduits
relativement tardivement en C++ (dynamic_cast et typeid) sont


inutilisables
pour la sérialisation du fait du peu de contraintes qu'ils imposent :
grosso-modo, l'identificateur de type (classe type_info) est spécifique au
compilateur et n'est même pas nécessairement le même d'une exécution à
l'autre du programme, sans parler du fait qu'elle ne décrit pas le contenu
de la classe. Je me demande bien d'ailleurs pourquoi avoir rendu typeid
aussi inutile (la méthode before, à quoi elle peut bien servir ????)... Je
me trompe peut-être, mais ca sent la guerre entre fabricants de


compilateurs
au sein du comité C++.
Je cross-post sur fclc++ où quelqu'un pourra sans doute nous éclairer sur


le
pourquoi du comment de l'état de la norme C++ sur ce sujet.

Notes au passage que cette "faiblesse" du C++ a au moins 2 avantages :
- vitesse (relativement) plus importante à l'exécution, même si c'est
compensé par la complexité de la syntaxe C++qui rend certaines


optimisations
impossibles pour le compilateur (les alias de variables).
- quasi-impossibilité de décompiler un programme C++, alors que pour les
langages autorisant l'introspection, il faut recourir à des obfuscateurs
plus ou moins efficace pour protéger la structure de son programme. Est-ce
que c'est un avantage réel, on pourrait en discuter...

Arnaud




Salut,

Si on souhaite sérialiser une série d'objets, il me semble qu'il est
nécessaire d'écrire un minimum de code pour sauvegarder les objets non ?
Si oui, alors pourquoi ne pas regrouper cela dans une classe A et faire une
dérivation multiple en surchargeant la méthode dans A qui permet de faire
cette sauvegarde ?
Je suis rapide parce que je ne suis pas certain d'avoir toutes les cartes en
main (je ne connais pas le C#).

Sébastien
Avatar
Ambassadeur Kosh
> Salut,

Si on souhaite sérialiser une série d'objets, il me semble qu'il est
nécessaire d'écrire un minimum de code pour sauvegarder les objets non ?
Si oui, alors pourquoi ne pas regrouper cela dans une classe A et faire


une
dérivation multiple en surchargeant la méthode dans A qui permet de faire
cette sauvegarde ?
Je suis rapide parce que je ne suis pas certain d'avoir toutes les cartes


en
main (je ne connais pas le C#).



bof. ça ne change presque rien. il faudra se palucher le code pour chaque
classe. en BCB, la VCL offre un moyen : TObject est munie de static TClass
*Class() et de const char* ClassName(). mais c'est spécifique à la VCL. et
encore faut il que tes objets heritent de TObject, ce qui n'est pas le cas
des double et autres... bref, en C++, à part utiliser un parser qui va te
generer tes classes de serialisation...