Facet pour changer std::endl

Le
Michael DOUBEZ
Bonjour,

Est ce que quelqu'un saurait comment modifier une facet pour que
std::endl envoie au lieu de ?

Baisquement, j'ai un code existant qui communiquait par une stream sur
port série avec endl (alias ) en tant que fin de ligne mais
maintenant, je dois utiliser à la place.

Michael
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
James Kanze
Le #312402
On Oct 25, 6:50 pm, Michael DOUBEZ
Est ce que quelqu'un saurait comment modifier une facet pour que
std::endl envoie r au lieu de n ?


Je ne crois pas que ce soit le bon chemin. La fonction
std::endl elle-même ne prend pas en compte le locale, et
insérerait toujours 'n'. On pourrait s'arranger pour remapper
le 'n' en 'r' (ou plutôt en 0x0D) dans un codecvt, qui
servira alors dans le filebuf, mais selon le cas, ça pourrait
être considéré comme un abus -- surtout, il ne marcherait
qu'avec des std::filebuf (ifstream et ofstream), et non avec des
autres streambuf. (Remarque, selon le cas, ça pourrait être un
avantage, et non un défaut.)

Baisquement, j'ai un code existant qui communiquait par une
stream sur port série avec endl (alias n) en tant que fin de
ligne mais maintenant, je dois utiliser r à la place.


Je me démande : pour la communication à un port série, est-ce
que tu te sers d'un streambuf sur mesure, ou est-ce que tu
passes par un filebuf et le système ? Dans le premier cas,
c'est évident que la transformation doit avoir lieu dans le
streambuf. Dans le deuxième, l'utilisation d'un codecvt pourrait
exceptionnellement se justifier : c'est bien l'encodage de ton
« fichier » qui est en question.

--
James Kanze (GABI Software) email:
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

Michael DOUBEZ
Le #312401
On Oct 25, 6:50 pm, Michael DOUBEZ
Est ce que quelqu'un saurait comment modifier une facet pour que
std::endl envoie r au lieu de n ?


Je ne crois pas que ce soit le bon chemin. La fonction
std::endl elle-même ne prend pas en compte le locale, et
insérerait toujours 'n'. On pourrait s'arranger pour remapper
le 'n' en 'r' (ou plutôt en 0x0D) dans un codecvt, qui
servira alors dans le filebuf, mais selon le cas, ça pourrait
être considéré comme un abus -- surtout, il ne marcherait
qu'avec des std::filebuf (ifstream et ofstream), et non avec des
autres streambuf. (Remarque, selon le cas, ça pourrait être un
avantage, et non un défaut.)

Baisquement, j'ai un code existant qui communiquait par une
stream sur port série avec endl (alias n) en tant que fin de
ligne mais maintenant, je dois utiliser r à la place.


Je me démande : pour la communication à un port série, est-ce
que tu te sers d'un streambuf sur mesure, ou est-ce que tu
passes par un filebuf et le système ?


J'ai refais un streambuf.

Dans le premier cas,
c'est évident que la transformation doit avoir lieu dans le
streambuf. Dans le deuxième, l'utilisation d'un codecvt pourrait
exceptionnellement se justifier : c'est bien l'encodage de ton
« fichier » qui est en question.


Oui, je pourrait effectivement filter dans le sreambuf. J'aurais préféré
une modification moins intrusive: ça me parraissait plus adapté de ne
pas propager la contrainte du format de communication jusque là (i.e. en
étendant la fonctionalité de serialbuf).
Comme endl est rn sous windows par exemple, je me dit que ça doit être
trivial avec un codecvt custom.

Michael


James Kanze
Le #312399
On Oct 26, 10:08 am, Michael DOUBEZ
Oui, je pourrait effectivement filter dans le sreambuf.


C'est l'endroit désigné par la conception pour des transcodages.

J'aurais préféré une modification moins intrusive: ça me
parraissait plus adapté de ne pas propager la contrainte du
format de communication jusque là (i.e. en étendant la
fonctionalité de serialbuf).


La question, c'est conceptuellement, à quel niveau veux-tu
placer la conversion. Si tu la conçois comme un transcodage, que
ta destination se sert d'un encodage particulier, alors, sa
place est dans le streambuf (et c'est bien l'impression que j'ai
d'après ta description), selon la conception des iostream, en
tout cas.

Comme endl est rn sous windows par exemple, je me dit que ça doit ê tre
trivial avec un codecvt custom.


Ce n'est pas tout à fait vrai. La spécification d'endl, c'est
d'insérer un 'n' dans le flux, puis de faire un flush. Et c'est
tout ce qu'il fait, quelque soit le système. (Essaie-le, par
exemple, sur un ostringstream, ou un ofstream ouvert en mode
binaire.)

C'est justement que dans les iostream, il y a trois couches de
conversion :

le formattage :
C'est le rôle de ostream (de même que le rôle d'istream est
de parser en entrée). Avec un ostream, on peut soit
formatté (les opérateurs >>), soit sortir des données
« pré-formattées » (les fonctions genre write ou put). (Le
modèle de base est un flux de texte, mais c'est assez
courant---bien qu'à mon avis pas très propre---de se
servir des fonctions put et write aussi pour l'écriture des
formats binaires, éventuellement moyenement des
reinterpret_cast.)

le transcodage :
C'est le rôle du locale imbué dans le filebuf (et ne se fait
que dans filebuf, non dans les autres streambuf). Si tu ne
veux pas de transcodage, il faut imbuer le filebuf avec le
locale "C". (La bonne gestion des locales dans les flux
n'est pas toujours évidente.)

la conversion en format externe :
Encore, il n'y a que le filebuf qui est concerné, et pas les
stringbuf, etc. Grosso modo, donné un flux de texte en
format interne (avec par exemple 'n' comme fin de ligne),
on convertit en format externe, selon la mode. Il y a deux
modes, text et binary, avec text comme défaut ; dans le cas
de text, la conversion concerne à la fois les fins de lignes
(conversion de 'n' en CRLF sous Windows, ou en écriture
dans un enrégistrement différent sous des OS des mainframes)
et la fin de fichier (reconnaissance du caractère 0x1A comme
fin de fichier en entrée sous Windows, bien que Windows n'a
pas réelement besoin d'un caractère de fin de fichier) ; en
mode binaire, il n'y a que la fin de fichier qui est touchée
(et qui n'exige pas de considérations spéciales sous la
plupart des systèmes).

Note qu'à part le premier, les conversions s'effectuent dans le
streambuf, et non dans ostream, et qu'elles dépendent du type de
streambuf -- parmi les streambuf standard, il n'y a que filebuf
qui en est concerné, mais évidemment, tu es libre d'établir tes
propres conventions dans tes propres streambufs. Note aussi
qu'il n'y a pas de streambuf standard qui lit des fichiers sans
appliquer les deux dernières conversions -- en sortie mode
binaire, la dernière est un no-op sous Windows ou sous Unix,
mais ce n'est pas le cas partout. Et si tu veux être certain que
le deuxième est un no-op, il faut prendre soins que le filebuf
soit imbué du locale "C". (Dans mes flux UTF-8, par exemple, je
travaille directement sur le streambuf, et je l'imbue bien avec
le locale "C" avant de lire quoique ce soit. Malheureusement,
s'il s'agit d'un fichier déjà ouvert, je ne peux pas changer le
mode, ce qui peut poser des problèmes.)

--
James Kanze (GABI Software) email:
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

Publicité
Poster une réponse
Anonyme