Par contre, je n'ai pas la moindre idée de ce qu'il fait réellement. Pour moi, un booléen, c'est un seul bit (à 1 pour true, à 0 pour false). Donc, le "forcer" dans un octet donne un résultat qui m'échappe un peu.
On Mon, 03 Oct 2005 22:56:21 +0200, Alain Cabiran
<pasdespam@club-internet.fr>:
bool a;
ostream s;
Invalide. On ne peut pas créer un ostream "dans le vide".
write<bool>(s, a);
Pourquoi expliciter le "<bool>" ?
Le code suivant compile sans souci avec Comeau :
#include <iostream>
#include <fstream>
template<class A> std::ostream& write
(std::ostream & s, const A & valeur)
{
s.write(reinterpret_cast<const char *>(&valeur), sizeof valeur);
return s;
}
Par contre, je n'ai pas la moindre idée de ce qu'il fait réellement.
Pour moi, un booléen, c'est un seul bit (à 1 pour true, à 0 pour
false). Donc, le "forcer" dans un octet donne un résultat qui
m'échappe un peu.
Par contre, je n'ai pas la moindre idée de ce qu'il fait réellement. Pour moi, un booléen, c'est un seul bit (à 1 pour true, à 0 pour false). Donc, le "forcer" dans un octet donne un résultat qui m'échappe un peu.
Alain Cabiran
On Mon, 03 Oct 2005 21:56:59 +0200, Alain Cabiran :
template<class A> std::ostream write (...
Ça y est, j'ai compris : tu as oublié un "&" ici.
template<class A> std::ostream& write (...
j'avais essayé :)
en fait si je remplace : s.write(static_cast<const char *>(&valeur), sizeof(valeur)); par : s.write((const char *)&valeur, sizeof(valeur));
ça compile sans erreur. Mais je ne comprends pas la différence entre static_cast<type>(valeur) et (type)valeur
en tout cas sous g++ 3.3 ... (j'ai pas essayé d'autre compilateur)
Alain C.
On Mon, 03 Oct 2005 21:56:59 +0200, Alain Cabiran
<pasdespam@club-internet.fr>:
template<class A> std::ostream write (...
Ça y est, j'ai compris : tu as oublié un "&" ici.
template<class A> std::ostream& write (...
j'avais essayé :)
en fait si je remplace :
s.write(static_cast<const char *>(&valeur), sizeof(valeur));
par :
s.write((const char *)&valeur, sizeof(valeur));
ça compile sans erreur. Mais je ne comprends pas la différence
entre static_cast<type>(valeur) et (type)valeur
en tout cas sous g++ 3.3 ... (j'ai pas essayé d'autre compilateur)
On Mon, 03 Oct 2005 21:56:59 +0200, Alain Cabiran :
template<class A> std::ostream write (...
Ça y est, j'ai compris : tu as oublié un "&" ici.
template<class A> std::ostream& write (...
j'avais essayé :)
en fait si je remplace : s.write(static_cast<const char *>(&valeur), sizeof(valeur)); par : s.write((const char *)&valeur, sizeof(valeur));
ça compile sans erreur. Mais je ne comprends pas la différence entre static_cast<type>(valeur) et (type)valeur
en tout cas sous g++ 3.3 ... (j'ai pas essayé d'autre compilateur)
Alain C.
Fabien LE LEZ
On Mon, 03 Oct 2005 23:16:27 +0200, Alain Cabiran :
en fait si je remplace : s.write(static_cast<const char *>(&valeur), sizeof(valeur)); par : s.write((const char *)&valeur, sizeof(valeur));
Ici, le cast consiste à ignorer le type de la variable, et à ne s'intéresser qu'à l'arrangement des bits en mémoire. Donc, logiquement, on devrait écrire reinterpret_cast<>.
On Mon, 03 Oct 2005 23:16:27 +0200, Alain Cabiran
<pasdespam@club-internet.fr>:
en fait si je remplace :
s.write(static_cast<const char *>(&valeur), sizeof(valeur));
par :
s.write((const char *)&valeur, sizeof(valeur));
Ici, le cast consiste à ignorer le type de la variable, et à ne
s'intéresser qu'à l'arrangement des bits en mémoire. Donc,
logiquement, on devrait écrire reinterpret_cast<>.
On Mon, 03 Oct 2005 23:16:27 +0200, Alain Cabiran :
en fait si je remplace : s.write(static_cast<const char *>(&valeur), sizeof(valeur)); par : s.write((const char *)&valeur, sizeof(valeur));
Ici, le cast consiste à ignorer le type de la variable, et à ne s'intéresser qu'à l'arrangement des bits en mémoire. Donc, logiquement, on devrait écrire reinterpret_cast<>.
Fabien LE LEZ
On Mon, 03 Oct 2005 21:56:59 +0200, Alain Cabiran :
template<class A> std::ostream write(std::ostream & s, const A & valeur) { 1) s.write(static_cast<const char *>(&valeur), sizeof(A));
Au fait, ne perds pas de vue que tout ça est assez proche de l'alchimie : on ne peut pas vraiment prévoir ce qui va se passer.
Si A == int, on peut raisonnablement supposer que le code va "découper" le "int" en morceaux de CHAR_BIT bits, et les enregistrer dans un ordre qui dépend du système.
Si A == std::string, le code ci-dessus va prendre la représentation mémoire de la variable, quelle qu'elle soit, et la "loger" dans des octets. Le résultat sera un fichier contenant des octets a priori sans signification.
Si A == bool, j'avoue que je ne sais pas. Je sais ce que donnent les opérateurs sur un booléen, mais je n'ai pas vraiment idée de sa représentation en mémoire. La seule chose dont je puisse être sûr, c'est que si deux "bool" se suivent en mémoire, il y a un nombre entier non nul d'octets entre l'adresse du premier et l'adresse du second. C'est valable pour tous les types, d'ailleurs.
On Mon, 03 Oct 2005 21:56:59 +0200, Alain Cabiran
<pasdespam@club-internet.fr>:
template<class A> std::ostream write(std::ostream & s, const A & valeur)
{
1) s.write(static_cast<const char *>(&valeur), sizeof(A));
Au fait, ne perds pas de vue que tout ça est assez proche de
l'alchimie : on ne peut pas vraiment prévoir ce qui va se passer.
Si A == int, on peut raisonnablement supposer que le code va
"découper" le "int" en morceaux de CHAR_BIT bits, et les enregistrer
dans un ordre qui dépend du système.
Si A == std::string, le code ci-dessus va prendre la représentation
mémoire de la variable, quelle qu'elle soit, et la "loger" dans des
octets. Le résultat sera un fichier contenant des octets a priori sans
signification.
Si A == bool, j'avoue que je ne sais pas. Je sais ce que donnent les
opérateurs sur un booléen, mais je n'ai pas vraiment idée de sa
représentation en mémoire. La seule chose dont je puisse être sûr,
c'est que si deux "bool" se suivent en mémoire, il y a un nombre
entier non nul d'octets entre l'adresse du premier et l'adresse du
second. C'est valable pour tous les types, d'ailleurs.
On Mon, 03 Oct 2005 21:56:59 +0200, Alain Cabiran :
template<class A> std::ostream write(std::ostream & s, const A & valeur) { 1) s.write(static_cast<const char *>(&valeur), sizeof(A));
Au fait, ne perds pas de vue que tout ça est assez proche de l'alchimie : on ne peut pas vraiment prévoir ce qui va se passer.
Si A == int, on peut raisonnablement supposer que le code va "découper" le "int" en morceaux de CHAR_BIT bits, et les enregistrer dans un ordre qui dépend du système.
Si A == std::string, le code ci-dessus va prendre la représentation mémoire de la variable, quelle qu'elle soit, et la "loger" dans des octets. Le résultat sera un fichier contenant des octets a priori sans signification.
Si A == bool, j'avoue que je ne sais pas. Je sais ce que donnent les opérateurs sur un booléen, mais je n'ai pas vraiment idée de sa représentation en mémoire. La seule chose dont je puisse être sûr, c'est que si deux "bool" se suivent en mémoire, il y a un nombre entier non nul d'octets entre l'adresse du premier et l'adresse du second. C'est valable pour tous les types, d'ailleurs.
On Mon, 03 Oct 2005 21:56:59 +0200, Alain Cabiran :
template<class A> std::ostream write (...
Ça y est, j'ai compris : tu as oublié un "&" ici.
template<class A> std::ostream& write (...
j'avais essayé :)
en fait si je remplace : s.write(static_cast<const char *>(&valeur), sizeof(valeur)); par : s.write((const char *)&valeur, sizeof(valeur));
ça compile sans erreur. Mais je ne comprends pas la différence entre static_cast<type>(valeur) et (type)valeur
Ici, le cast de type C correspond à un reinterpret_cast, non un static_cast. Si tu utilises reinterpret_cast, ça doit marcher.
Évidemment, ici comme ailleurs, reinterpret_cast est un signal que le code n'est probablement pas portable, et qu'il ne risque de marcher que si tu connais bien les détails de la machine et de l'implémentation. Copier les octets bruts d'une variable ne sert en général pas à grand chose.
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Alain Cabiran wrote:
On Mon, 03 Oct 2005 21:56:59 +0200, Alain Cabiran
<pasdespam@club-internet.fr>:
template<class A> std::ostream write (...
Ça y est, j'ai compris : tu as oublié un "&" ici.
template<class A> std::ostream& write (...
j'avais essayé :)
en fait si je remplace :
s.write(static_cast<const char *>(&valeur), sizeof(valeur));
par :
s.write((const char *)&valeur, sizeof(valeur));
ça compile sans erreur. Mais je ne comprends pas la différence
entre static_cast<type>(valeur) et (type)valeur
Ici, le cast de type C correspond à un reinterpret_cast, non un
static_cast. Si tu utilises reinterpret_cast, ça doit marcher.
Évidemment, ici comme ailleurs, reinterpret_cast est un signal
que le code n'est probablement pas portable, et qu'il ne risque
de marcher que si tu connais bien les détails de la machine et
de l'implémentation. Copier les octets bruts d'une variable ne
sert en général pas à grand chose.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
On Mon, 03 Oct 2005 21:56:59 +0200, Alain Cabiran :
template<class A> std::ostream write (...
Ça y est, j'ai compris : tu as oublié un "&" ici.
template<class A> std::ostream& write (...
j'avais essayé :)
en fait si je remplace : s.write(static_cast<const char *>(&valeur), sizeof(valeur)); par : s.write((const char *)&valeur, sizeof(valeur));
ça compile sans erreur. Mais je ne comprends pas la différence entre static_cast<type>(valeur) et (type)valeur
Ici, le cast de type C correspond à un reinterpret_cast, non un static_cast. Si tu utilises reinterpret_cast, ça doit marcher.
Évidemment, ici comme ailleurs, reinterpret_cast est un signal que le code n'est probablement pas portable, et qu'il ne risque de marcher que si tu connais bien les détails de la machine et de l'implémentation. Copier les octets bruts d'une variable ne sert en général pas à grand chose.
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Alain Cabiran
Alain Cabiran wrote:
On Mon, 03 Oct 2005 21:56:59 +0200, Alain Cabiran :
template<class A> std::ostream write (...
Ça y est, j'ai compris : tu as oublié un "&" ici.
template<class A> std::ostream& write (...
j'avais essayé :)
en fait si je remplace : s.write(static_cast<const char *>(&valeur), sizeof(valeur)); par : s.write((const char *)&valeur, sizeof(valeur));
ça compile sans erreur. Mais je ne comprends pas la différence entre static_cast<type>(valeur) et (type)valeur
Ici, le cast de type C correspond à un reinterpret_cast, non un static_cast. Si tu utilises reinterpret_cast, ça doit marcher.
Évidemment, ici comme ailleurs, reinterpret_cast est un signal que le code n'est probablement pas portable, et qu'il ne risque de marcher que si tu connais bien les détails de la machine et de l'implémentation. Copier les octets bruts d'une variable ne sert en général pas à grand chose.
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Je répond à ce message ci pour l'ensemble :
merci à tous ! j'avais complètement oublié cet opérateur, et c'est effectivement ce qui se passe :
J'en suis arrivé à la même conclusion : les données stockées ne seront pas portables d'une plateforme à une autre. j'en suis malheureusement arrivé à utiliser le stockage binaire parce que je n'ai pas trouvé comment stocker et relire 2 chaines de caractères consécutives de façon simple avec iostream en "mode texte".
exemple :
1 5 chaine n°1 45 chaine 2 3 1 c1 5 d, e 3 f codé en réalité comme ceci : 1 5 "chaine n°1" 45 "chaine 2" 2 3 1 "c1" 5 "d, e" 3 "f"
j'ai mis des guillemets juste pour séparer les chaines. mais du fait qu'elles n'ont pas de contraintes de caractères, je ne vois pas quoi utiliser comme séparateur...
j'ai jeté un coup d'oeil à qt, gtk, wxwindows, mysql, gdbm mais en suis revenu, beaucoup de boulot pour un si petit programme, je me suis rabattu vers ncurses, simple et suffisant pour l'instant. "Malheureusement" contrairement aux autres libs citées, la gestion des entrées/sorties disque se fait par la stl qui ne propose rien de portable.
voilà,
encore merci à tous
Alain C.
Alain Cabiran wrote:
On Mon, 03 Oct 2005 21:56:59 +0200, Alain Cabiran
<pasdespam@club-internet.fr>:
template<class A> std::ostream write (...
Ça y est, j'ai compris : tu as oublié un "&" ici.
template<class A> std::ostream& write (...
j'avais essayé :)
en fait si je remplace :
s.write(static_cast<const char *>(&valeur), sizeof(valeur));
par :
s.write((const char *)&valeur, sizeof(valeur));
ça compile sans erreur. Mais je ne comprends pas la différence
entre static_cast<type>(valeur) et (type)valeur
Ici, le cast de type C correspond à un reinterpret_cast, non un
static_cast. Si tu utilises reinterpret_cast, ça doit marcher.
Évidemment, ici comme ailleurs, reinterpret_cast est un signal
que le code n'est probablement pas portable, et qu'il ne risque
de marcher que si tu connais bien les détails de la machine et
de l'implémentation. Copier les octets bruts d'une variable ne
sert en général pas à grand chose.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Je répond à ce message ci pour l'ensemble :
merci à tous ! j'avais complètement oublié cet opérateur,
et c'est effectivement ce qui se passe :
J'en suis arrivé à la même conclusion : les données stockées ne seront
pas portables d'une plateforme à une autre. j'en suis malheureusement
arrivé à utiliser le stockage binaire parce que je n'ai pas trouvé
comment stocker et relire 2 chaines de caractères consécutives de façon
simple avec iostream en "mode texte".
exemple :
1 5 chaine n°1 45 chaine 2 3 1 c1 5 d, e 3 f
codé en réalité comme ceci :
1 5 "chaine n°1" 45 "chaine 2" 2 3 1 "c1" 5 "d, e" 3 "f"
j'ai mis des guillemets juste pour séparer les chaines.
mais du fait qu'elles n'ont pas de contraintes de caractères,
je ne vois pas quoi utiliser comme séparateur...
j'ai jeté un coup d'oeil à qt, gtk, wxwindows, mysql, gdbm
mais en suis revenu, beaucoup de boulot pour un si petit programme,
je me suis rabattu vers ncurses, simple et suffisant pour l'instant.
"Malheureusement" contrairement aux autres libs citées, la gestion
des entrées/sorties disque se fait par la stl qui ne propose rien de
portable.
On Mon, 03 Oct 2005 21:56:59 +0200, Alain Cabiran :
template<class A> std::ostream write (...
Ça y est, j'ai compris : tu as oublié un "&" ici.
template<class A> std::ostream& write (...
j'avais essayé :)
en fait si je remplace : s.write(static_cast<const char *>(&valeur), sizeof(valeur)); par : s.write((const char *)&valeur, sizeof(valeur));
ça compile sans erreur. Mais je ne comprends pas la différence entre static_cast<type>(valeur) et (type)valeur
Ici, le cast de type C correspond à un reinterpret_cast, non un static_cast. Si tu utilises reinterpret_cast, ça doit marcher.
Évidemment, ici comme ailleurs, reinterpret_cast est un signal que le code n'est probablement pas portable, et qu'il ne risque de marcher que si tu connais bien les détails de la machine et de l'implémentation. Copier les octets bruts d'une variable ne sert en général pas à grand chose.
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Je répond à ce message ci pour l'ensemble :
merci à tous ! j'avais complètement oublié cet opérateur, et c'est effectivement ce qui se passe :
J'en suis arrivé à la même conclusion : les données stockées ne seront pas portables d'une plateforme à une autre. j'en suis malheureusement arrivé à utiliser le stockage binaire parce que je n'ai pas trouvé comment stocker et relire 2 chaines de caractères consécutives de façon simple avec iostream en "mode texte".
exemple :
1 5 chaine n°1 45 chaine 2 3 1 c1 5 d, e 3 f codé en réalité comme ceci : 1 5 "chaine n°1" 45 "chaine 2" 2 3 1 "c1" 5 "d, e" 3 "f"
j'ai mis des guillemets juste pour séparer les chaines. mais du fait qu'elles n'ont pas de contraintes de caractères, je ne vois pas quoi utiliser comme séparateur...
j'ai jeté un coup d'oeil à qt, gtk, wxwindows, mysql, gdbm mais en suis revenu, beaucoup de boulot pour un si petit programme, je me suis rabattu vers ncurses, simple et suffisant pour l'instant. "Malheureusement" contrairement aux autres libs citées, la gestion des entrées/sorties disque se fait par la stl qui ne propose rien de portable.