OVH Cloud OVH Cloud

[debutant] flux/fichier

24 réponses
Avatar
Bruno CAUSSE
Je lis dans la faq

bool is_readable( const std::string & file )
{
std::ifstream fichier( file.c_str() );
return fichier != 0;
}

Pourquoi on n'utilise pas return fichier.good() ?

Merci

10 réponses

1 2 3
Avatar
Cyrille
Je lis dans la faq

bool is_readable( const std::string & file )
{
std::ifstream fichier( file.c_str() );
return fichier != 0;
}

Pourquoi on n'utilise pas return fichier.good() ?


Le cast de "fichier" vers un pointeur ne donne un pointeur nul que si
fichier.fail() renvoye vrai. Or fichier.fail() n'est pas l'inverse de
fichier.good() (good() peut retourner false par exemple si on est à la
fin du fichier, alors que fail() retournera false aussi s'il n'y a pas
eu d'erreur de lecture)

Par contre, pourquoi utiliser fichier != 0 plutôt que !fichier.fail(),
je ne sais pas.

--
"A one-legged duck can only swim in circles" ~ Oscar Wilde

Avatar
James Kanze
Bruno CAUSSE wrote:
Je lis dans la faq


bool is_readable( const std::string & file )
{
std::ifstream fichier( file.c_str() );
return fichier != 0;


Drôle de façon de l'écrire. L'idiome consacré, c'est :
return fichier ;
C'est la première fois que je vois la comparaison avec 0.

}


Pourquoi on n'utilise pas return fichier.good() ?


Parce qu'il n'a pas la sémantique voulue. Si le fichier existe,
mais est vide, par exemple, sa valeur de retour n'est pas
spécifiée.

(En général, ios::good() ne sert à rien.)

--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34

Avatar
Sylvain Togni
Bruno CAUSSE wrote:
Je lis dans la faq

bool is_readable( const std::string & file )
{
std::ifstream fichier( file.c_str() );
return fichier != 0;


Drôle de façon de l'écrire. L'idiome consacré, c'est :
return fichier ;
C'est la première fois que je vois la comparaison avec 0.


La comparaison avec 0 (ou avec NULL) permet d'éviter un warning sur
certains compilateurs, dont VC++ :

warning C4800: 'void *' : forcing value to bool 'true' or 'false'
(performance warning)

J'avoue que c'est pas très joli, mais bon, pourquoi aussi ces satanés
flux ont-ils un operateur de convertion vers void* et non vers bool ?

--
Sylvain


Avatar
Michel Michaud
Dans le message 42ae0547$0$899$,
J'avoue que c'est pas très joli, mais bon, pourquoi aussi ces
satanés flux ont-ils un operateur de convertion vers void* et non
vers bool ?


Ce serait trop risqué, car bool est un type entier qui pourrait
ensuite être utilisé par accident dans des expressions où ce
n'est pas ce que l'on veut. Par exemple, comme

double d= (bool)0;

fonctionne, alors ceci fonctionnerait aussi

double d= flux; // OK si stream::operator bool()

La conversion vers void* donne moins de surprise, sauf à ceux
qui se demandent pourquoi :-)

double d= (void*)0; // ERREUR conversion impossible
double f= flux; // ERREUR avec stream::operator void*()

Ceci dit, tout ça est peut-être un peu trop subtil et on aurait
pu vivre avec l'impossibilité de faire le test « if (flux) » :
ce n'est pas difficile d'écrire if (!flux.fail()) ou autre test
du genre il me semble. Personnellement je n'écris jamais le
test if (flux)...

--
Michel Michaud
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/

Avatar
Loïc Joly
Ceci dit, tout ça est peut-être un peu trop subtil et on aurait
pu vivre avec l'impossibilité de faire le test « if (flux) » :
ce n'est pas difficile d'écrire if (!flux.fail()) ou autre test
du genre il me semble. Personnellement je n'écris jamais le
test if (flux)...


Je ne l'écris pas souvent directement, mais le test

while (flux >> valeur)

est quand même d'usage courant, et serait peu joli à écrire avec fail.

--
Loïc

Avatar
kanze
Sylvain Togni wrote:
Bruno CAUSSE wrote:
Je lis dans la faq

bool is_readable( const std::string & file )
{
std::ifstream fichier( file.c_str() );
return fichier != 0;


Drôle de façon de l'écrire. L'idiome consacré, c'est :
return fichier ;
C'est la première fois que je vois la comparaison avec 0.


La comparaison avec 0 (ou avec NULL) permet d'éviter un
warning sur certains compilateurs, dont VC++ :

warning C4800: 'void *' : forcing value to bool 'true' or 'false'
(performance warning)

J'avoue que c'est pas très joli, mais bon, pourquoi aussi ces
satanés flux ont-ils un operateur de convertion vers void* et
non vers bool ?


Pour des raisons historiques. D'abord, quand les flux ont été
inventés, il n'y avait pas de type bool. Et dans la mesure où on
utilise les opérateurs << et >> sur des flux, on a estimé qu'une
conversion implicite en int aurait été trop dangéreux : si tu
oublies de déclarer le surcharge, et le type en question a lui
aussi une conversion vers un type entier, l'expression est
toujours légale, mais fait quelque chose de bien différente que
ce auquel tu attends.

Ensuite, quand on a ajouté bool au langage, pour des raisons
historiques, on n'a pas pû le faire sans introduire des
conversions implicites, du genre entier vers bool ou pointeur
vers bool. (En gros, il fallait que « if ( p ) » continue à
marcher.) Avec toutes ces conversions, on a estîmé qu'il valait
mieux que la conversion implicite continue à renvoyer un
pointeur.

En fin de compte, c'est une convention. On peut ne pas l'aimer ;
on ne peut pas l'ignorer. Dans l'ensemble, elle fonctionne assez
bien. À condition d'y conformer -- elle forme un ensemble, et on
ne peut pas n'y adhérer que parfois.

Ceci dit, dans l'exemple précis, je crois que « return
fichier.is_open() ; » ferait bien l'affaire.

--
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
kanze
Michel Michaud wrote:
Dans le message 42ae0547$0$899$,
J'avoue que c'est pas très joli, mais bon, pourquoi aussi
ces satanés flux ont-ils un operateur de convertion vers
void* et non vers bool ?


Ce serait trop risqué, car bool est un type entier qui
pourrait ensuite être utilisé par accident dans des
expressions où ce n'est pas ce que l'on veut. Par exemple,
comme

double d= (bool)0;

fonctionne, alors ceci fonctionnerait aussi

double d= flux; // OK si stream::operator bool()

La conversion vers void* donne moins de surprise, sauf à ceux
qui se demandent pourquoi :-)

double d= (void*)0; // ERREUR conversion impossible
double f= flux; // ERREUR avec stream::operator void*()


Je crois que le véritable problème concerne les opérateurs
<<. Si MaClasse a une conversion implicite vers un type entier,
quelque chose comme : std::cout << uneMaClasse serait légale,
même si j'oublie de définir le surcharge de l'opérateur <<.

Ceci dit, tout ça est peut-être un peu trop subtil et on
aurait pu vivre avec l'impossibilité de faire le test « if
(flux) » : ce n'est pas difficile d'écrire if (!flux.fail())
ou autre test du genre il me semble.


Le problème, c'est que les tests disponibles sème la confusion.
Moi non plus, je n'aime pas réelement l'idiome, mais c'est
tellement consacré que c'est incontournable : on teste le flux
avec son opérateur de conversion ou son opérateur !. Le
problème, évidemment, c'est que logiquement, on doit écrire :
«@if ( flux.good() ) ». Sauf qu'évidemment, ça ne fait pas ce
qu'on veut. La réponse au problème : on ne se sert pas de ces
fonctions, mais on traite le flux comme un type booléen.

Je crois que tu me connais assez pour pouvoir déviner ce que je
pense d'une telle convention:-). Mais c'est la convention ;
c'est ce que les gens apprennent, et c'est ce auquel on s'attend
en lisant du code.

Personnellement je n'écris jamais le test if (flux)...


Pourquoi ? C'est toujours « while ( flux >> x ) » ou « while (
getline( flux, chaine ) » ?

J'ai joué un moment avec l'idée d'écrire :

while ( ! (flux >> x).fail() ) ...

C'est plus explicit. Mais ce n'est pas idiomatique, et je crains
que ça déroute trop.

--
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
kanze
Loïc Joly wrote:
Ceci dit, tout ça est peut-être un peu trop subtil et on
aurait pu vivre avec l'impossibilité de faire le test « if
(flux) » : ce n'est pas difficile d'écrire if (!flux.fail())
ou autre test du genre il me semble. Personnellement je
n'écris jamais le test if (flux)...


Je ne l'écris pas souvent directement, mais le test

while (flux >> valeur)

est quand même d'usage courant, et serait peu joli à écrire
avec fail.


Tu veux dire que tu n'aimes pas :
while ( ! (flux >> valeur).fail() ) ...
ou
while ( ! getline( flux, ligne ).fail() ) ...

Je vois deux problèmes avec ces utilisations de fail (y compris
celui proposée par Michel) : les programmeurs expérimentés vont
poser la question, pourquoi tu n'as pas simplement utiliser la
conversion implicite, et les programmeurs débuttants vont poser
la question, pourquoi la négation, et seront tentés à l'écrire
« if ( flux.good() ) ». C'est surtout cette dernière
considération qui me fait hésiter. (En fait, ma décision est le
résultat d'une discussion avec Steve Clamage, quand je
commençais le C++. Moi aussi, j'avais utiliser flux.good(), et
le commentaire de Steve était : traiter le flux comme ci c'était
un bool, et tu auras toujours ce que tu veux ; utiliser les
fonctions, et tu te tromperas une fois sur deux, parce que les
noms sont si mal choisis.)

Si on n'aime vraiment pas l'idée de la conversion implicite,
quelque chose comme :

inline bool
ok( std::ios& flux )
{
return ! flux.fail() ;
// ou simplement flux
}

while ( ok( flux >> valeur ) ) ...

while ( ok( getline( flux, ligne ) ) ...

etc. Mais pour moi, la convention, c'est la convention. J'ai mon
avis là-dessus en ce qui en concerne l'élégance et la beauté,
mais elle marche, elle est répandue, et elle est facile à
expliquer aux débuttants. Elle est trop omniprésente pour que je
puisse espérer à la changer, et je n'aime pas lutter contre les
moulins à vent quand ce n'est pas réelement nécessaire.

--
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
Michel Michaud
Dans le message 42ae7ce5$0$168$,
Personnellement je n'écris jamais le test if (flux)...


Je ne l'écris pas souvent directement, mais le test

while (flux >> valeur)

est quand même d'usage courant, et serait peu joli à écrire avec
fail.


J'avoue que ce cas me semble moins problématique et que je
n'y avais pas pensé. Ceci dit, voir ma réponse à James...

--
Michel Michaud
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/


Avatar
Michel Michaud
Dans le message ,
Michel Michaud wrote:
Personnellement je n'écris jamais le test if (flux)...


Pourquoi ? C'est toujours « while ( flux >> x ) » ou « while (
getline( flux, chaine ) » ?

J'ai joué un moment avec l'idée d'écrire :

while ( ! (flux >> x).fail() ) ...

C'est plus explicit. Mais ce n'est pas idiomatique, et je crains
que ça déroute trop.


Je crois que c'est idiomatique en C (pas le code exactement, mais
le style). Ça démontre une crainte de coder une vraie boucle et
demie alors que c'est bien ce qu'on fait. Et comme je suis
beaucoup moins allergique aux boucles et demie qu'aux variables
déclarées à une portée inutilement grande, je ferais souvent tout
naturellement

for(;;)
{
TypeDeX x;
flux >> x;
/***/
if (flux.fail()) break;
/***/
utilisation de x...
}

J'ai perdu depuis longtemps l'intérêt pour la combinaison des
opérations comme on le faisait en C... Je trouve le code plus
clair ainsi et le style s'applique dans bien des cas où l'on ne
pourrait pas combiner les opérations. La boucle et demie
explicite donne une uniformité qui me semble bien utile. Et,
avant que tu ne le proposes, je n'aime pas non plus l'idée
d'abuser du for en écrivant « for (TypeDeX x; flux >> x;) ».
Encore une fois, c'est une boucle et demie camouflée qui ne
peut pas toujours être appliquée...

Désolé pour ceux que ça déroute. Dans mon esprit, il est vraiment dommage
que des programmeurs soient déroutées par des boucles et
demie et du code écrit explicitement :-)

--
Michel Michaud
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/


1 2 3