OVH Cloud OVH Cloud

redirection de flux dans une application C++

47 réponses
Avatar
Sid Touati
Bonjour à tous,
j'ai cherché sur plusieurs documents et ouvrages de référence la
possibilité ou pas de programmer des redirections de flux localement à
une application C++. Je ne souhaite pas le faire via le shell, car de
telle redirections sont globales à toute l'application.

Je veux faire quelque chose du genre :

ifstream ofile("Toto.txt")

if (!ofile) {
cerr<<"Zut. Pas pu ouvrir. Je lis à partir de stdin à partir de
maintenant.\n";

// ofile=cin ; <===== Je veux implémenter cela. A savoir que
ofile devienne un alias de cin

}

Est-ce possible de faire cela ?

Je sais qu'on peut toujours remplacer ofile par cin dans le reste de
l'application, mais je préfère d'abord voir si on peut aliaser cin avec
un autre ifstream. Cela simplifierait le code.

Je remercie d'avance tout gourou de C++.

S

10 réponses

1 2 3 4 5
Avatar
Gabriel Dos Reis
Sid Touati writes:

| > oui.
| > // includes
| > std::ifstream ifile("Toto.txt");
| > std::istream& input = ifile ? static_cast<std::istream&>(ifile) : cin;
| > Utilisez "input" à la place de "ifile". Si possible, il est
| > préférable
| > de manipuler les flux en termes de "std::istream&" et "std::ostream&".
| > Manuel
| Bravo, cette solution me paraît plus élégante et plus compacte. Je la

Voilà bien une notion d'élégance assez particulière.

-- gaby
Avatar
Pierre Barbier de Reuille
Sid Touati wrote:

oui.

// includes

std::ifstream ifile("Toto.txt");
std::istream& input = ifile ? static_cast<std::istream&>(ifile) : cin;

Utilisez "input" à la place de "ifile". Si possible, il est préférable
de manipuler les flux en termes de "std::istream&" et "std::ostream&".


Manuel

Bravo, cette solution me paraît plus élégante et plus compacte. Je la

teste...
Merci

S


Attention tout de même au couplage de input et de ifile ...
En gros, si ifile est détruit avant input, ça va faire des choses
bizarres ... (genre si input est renvoyé par une fonction)

Pierre


Avatar
Sid Touati
At après les deux objets écrivent au même endroit ?


Oui exactement, pourquoi pas. N'est ce pas le comportement attendue
d'une redirection ? On fait bien cela en C en une seule instruction, non ?


| Je ne comprends pas pourquoi ce comité a rejeté cette solution.

Probablement sur la base de longues années d'expérience avec cette
histoire de copie de flux.


Parfait, mais cela ne réponds pas à la question : pourquoi la copie de
flux n'est elle pas une solution retenue ? Dire que les sages et les
mandarins l'ont décidé pour le bienfait du C++, c'est un peu limite.

S

Avatar
Marc Boyer
Le 19-07-2006, Sid Touati a écrit :
At après les deux objets écrivent au même endroit ?


Oui exactement, pourquoi pas. N'est ce pas le comportement attendue
d'une redirection ? On fait bien cela en C en une seule instruction, non ?


Oui, mais, par exemple, C n'a pas d'appel automatique au destructeur.
Donc, l'ambiguïté est laissée à la charge du programmeur.

Je cite cet aspect puisque c'est le seul que j'ai compris
sur le problème avec rdbuf, et je crois que tu as le même
dans la solution que tu trouvais 'élégante'.

| Je ne comprends pas pourquoi ce comité a rejeté cette solution.

Probablement sur la base de longues années d'expérience avec cette
histoire de copie de flux.


Parfait, mais cela ne réponds pas à la question : pourquoi la copie de
flux n'est elle pas une solution retenue ? Dire que les sages et les
mandarins l'ont décidé pour le bienfait du C++, c'est un peu limite.


Gabriel apporte des informations vraies sur le C++.
Après, son sens de la pédagogie et de la répartie est assez
inhabituel. Mais bon, évitons de parler à sa place...

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exciter des sots
IF -- Rudyard Kipling (Trad. Paul Éluard)


Avatar
kanze
Sid Touati wrote:

Ça a été rejeté par le comité, exprès. Ça veut dire quoi,
l'affectation d'un flux ? Copie des états d'erreur ? Copie
des options de formattage ?


Heu ... je pense que tout copier ferait bien l'affaire,
d'autant plus que c'est le comportement attendu pour un
opérateur d'affectation '='.


Tout copier, ça veut dire quoi ? Il y a des états implicits,
par exemple ; un ofstream est propriétaire de son streambuf, et
le delete dans son constructeur.

Dans la pratique, l'affectation ne marche pas pour des classes
du genre [io]stream. D'abord, parce que l'affectation ne marche
pas bien avec l'héritage ; tu affectes un ofstream à un
ostream, et le résultat est toujours un ostream, jamais un
ofstream. (Les deux objets ne sont donc pas égaux.)
Deuxièmement, évidemment, parce que la sémantique des flux
ressemble à une sémantique d'un objet d'entité. Pas dans tous
les détails, mais à la fin, ils représentent bien quelque chose
d'externe au programme, et modifier (c-à-d lire OU écrire) un
flux modifierait l'état de l'autre. Ou non, selon les cas.

Note qu'il y a des représentations des flux qui sont copiable :
les [io]stream_iterator, par exemple. Mais du coup, ils ont une
sémantique d'affectation et de copie assez particulière, et dans
la pratique, une fois qu'on a fait a = b, on ne se sert plus de
b.

Je ne comprends pas pourquoi ce comité a rejeté cette
solution.


Parce que personne dans le comité a pû lui donner un sens.

streambuf*
getStreambuf( std::string const& filename )
{
std::auto_ptr< std::streambuf >
file( std::new filebuf ) ;
return file->open( filename.c_str(), std::in )
? file.release()
: std::cin.rdbuf() ;
}

et ensuite :

std::istream input( getStreambuf( filename ) ) ;
// ...
if ( input.rdbuf() != std::cin.rdbuf() ) {
delete input.rdbuf() ;
}


Disons que... d'habitude en C++, une ligne de code vaut
plusieurs lignes en C. Dans ce cas précis, une ligne en C vaut
plusieurs en C++. Cela n'est pas top. On a l'impression
d'utiliser un canon pour abattre une mouche : aller si loin
dans le C++ rien que pour redirriger un flux, y a de quoi
démotiver.


Je ne comprends pas. Ici, on fait quelque chose qui n'est même
pas possible en C. Et question de propreté et de lisabilité,
c'est quand même préférable de mettre la logique de décision
dans sa propre fonction, non ?

Heureusement, Manuel Zaccaria donne une solution qui semble
plus compacte. Je ne l'ai pas encore testé.


Il doit marcher. C'est en effet une bonne solution aussi. Dans
la mesure où le critère de choix se limite effectivement à
« est-ce qu'on peut ouvrir le fichier ? ». L'avantage de ma
solution, c'est qu'elle isole ce choix, ce qui permet à le
modifier et le comprendre plus facilement. S'il n'y a pas de
question de modification, la condition actuelle est assez simple
que sa mise en ligne ne pose pas de problèmes de
compréhension ; alors, la solution spécifique (et simple) de
Manuel est probablement préférable. Les principes que montre ma
solution, en revanche, sont généralement applicable, et je crois
qu'il vaut la peine de le comprendre. (J'utilise quelque chose
de semblable, par exemple, quand je dois utiliser le premier
fichier que je trouve dans une liste.)

--
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


Avatar
Sid Touati


Tout copier, ça veut dire quoi ? Il y a des états implicits,
par exemple ; un ofstream est propriétaire de son streambuf, et
le delete dans son constructeur.


Bonjour James,
ces questions, on se les pose à chaque fois qu'on surcharge un opérateur
d'affectation entre classes différentes. On arrive bien à trouver une
sémantique pour des cas plus compliqués que les flux standards...


Dans la pratique, l'affectation ne marche pas pour des classes
du genre [io]stream. D'abord, parce que l'affectation ne marche
pas bien avec l'héritage ; tu affectes un ofstream à un
ostream, et le résultat est toujours un ostream, jamais un
ofstream. (Les deux objets ne sont donc pas égaux.)


Oui, en effet. Pour me reprendre, cette remarque est vraie dans un cas
plus général, i.e., entre les classes ascendantes et descendantes.


Je ne comprends pas pourquoi ce comité a rejeté cette
solution.


Parce que personne dans le comité a pû lui donner un sens.


Ou peut être qu'il y a eu plusieurs "sens" proposés mais aucun n'a fait
consensus chez les mandarins.
Il me paraît naturel, et peut être suffisant, de simplement proposer le
sens de l'affectation entre flux comme étant une redirection classique.

Ensuite, l'implémentation est autre chose. Le thread que j'ai lancé a
proposé certaines pistes.


Je ne comprends pas. Ici, on fait quelque chose qui n'est même
pas possible en C. Et question de propreté et de lisabilité,
c'est quand même préférable de mettre la logique de décision
dans sa propre fonction, non ?


Je parlais de "ce cas précis", ie les redirections. En C, il est plus
facile de rediriger : on écrit : ofile=stdout; et voilà.
Ensuite, il faut faire attention aux bugs.

a+
S


Avatar
Michel Decima

Je parlais de "ce cas précis", ie les redirections. En C, il est plus
facile de rediriger : on écrit : ofile=stdout; et voilà.


Si on utilise des pointeurs, tout devient plus facile.

Ensuite, il faut faire attention aux bugs.


C'est coherent avec la facilité.

Avatar
Gabriel Dos Reis
Sid Touati writes:

| > At après les deux objets écrivent au même endroit ?
|
| Oui exactement, pourquoi pas. N'est ce pas le comportement attendue
| d'une redirection ?

Ce n'est pas le comportement que j'attends d'une affectation de flux.

| On fait bien cela en C en une seule instruction, non ?

Je m'en fous royalement de ce que fait C en une seule instruction.
Si je veux une affectation de pointeur, je sais l'écrire sans avoir à
introduire une sémantique bancale.

| > | Je ne comprends pas pourquoi ce comité a rejeté cette solution.
| > Probablement sur la base de longues années d'expérience avec cette
| > histoire de copie de flux.
|
| Parfait, mais cela ne réponds pas à la question : pourquoi la copie de
| flux n'est elle pas une solution retenue ?

Encore faut-il que tu lises et comprennes les réponses.

-- Gaby
Avatar
Gabriel Dos Reis
Sid Touati writes:

|
| > Tout copier, ça veut dire quoi ? Il y a des états implicits,
| > par exemple ; un ofstream est propriétaire de son streambuf, et
| > le delete dans son constructeur.
|
| Bonjour James,
| ces questions, on se les pose à chaque fois qu'on surcharge un
| opérateur d'affectation entre classes différentes. On arrive bien à
| trouver une sémantique pour des cas plus compliqués que les flux
| standards...

Comme ?

[...]

| Ou peut être qu'il y a eu plusieurs "sens" proposés mais aucun n'a
| fait consensus chez les mandarins.
| Il me paraît naturel, et peut être suffisant, de simplement proposer
| le sens de l'affectation entre flux comme étant une redirection
| classique.

Cela *te* paraît naturel, mais il ne l'est pas pour moi.

[...]

| Je parlais de "ce cas précis", ie les redirections. En C, il est plus
| facile de rediriger : on écrit : ofile=stdout; et voilà.

Tu fais une affectation de pointeurs. Ce n'est pas le même problème.

| Ensuite, il faut faire attention aux bugs.

Aha. Yaka.

-- Gaby
Avatar
Manuel Zaccaria
Sid Touati a écrit:

std::ifstream ifile("Toto.txt");
std::istream& input = ifile ? static_cast<std::istream&>(ifile) : cin;

Utilisez "input" à la place de "ifile". Si possible, il est préférable
de manipuler les flux en termes de "std::istream&" et "std::ostream&".


Manuel
Bravo, cette solution me paraît plus élégante et plus compacte. Je la

teste...
Merci



Ce n'est pas vraiment une 'solution' comme c'est écrit.
Gabriel Dos Reis et Pierre Barbier de Reuille ont raison mais je voulais
surtout porter l'attention sur les classes istream et ostream sans avoir
à rediriger les flux standard cin et cout. La variable input ne devrait
même pas être là. J'aurais mieux fait d'écrire:

void Lecture(std::istream& input)
{
// utilise input (ici pas de souci de durée de vie de ifile vs input)
}

et utiliser avec ifile ou cin.

L'avantage de rediriger cin et/ou cout est que ça évite de modifier tout le
code mais c'est pas une panacée non plus (on n'a qu'un fichier de chaque).
L'avantage d'utiliser istream et/ou ostream (dans du nouveau code) est que,
à mon avis, c'est plus souple à utiliser. Mais je ne suis pas un expert.

Manuel


1 2 3 4 5