OVH Cloud OVH Cloud

Visual C++ 6.0 ; debug ; fichier

29 réponses
Avatar
Laurent
c'est simple, ce programme fonctionne normallement sans debug, et en debug,
il me trouve un eof() des le premier input.read()


JE NE COMPRENDS PAS !!!!!!!!!!!

merci.


#include <iostream.h>
#include <fstream.h>
#include <stdio.h>

void main(void)
{

ifstream input;
char Carac[1];
int Taille;

input.open("fichier.txt",ios::in);

do
{
input.read(Carac, sizeof(Carac));
if(input.good())
{
Taille++;
}
}
while(!input.eof());

cout << "Taille : " << Taille << " octets.";


}

10 réponses

1 2 3
Avatar
Michel Michaud
Dans news:btm5nt$if1$, Thomas
donc

if( input ) {
while ( input.good() ) { // tt que eof non atteinte


Moi, je réagis fortement (et négativement) quand mes
élèves prennent la peine d'écrire un commentaire et qu'il
ne correspond pas à ce qu'il commente !!! Le if est
par ailleurs inutile...

--
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 news:,
Sauf qu'en général, la taille d'un fichier ne tient pas sur un int.
Si le fseek est assez sûr, le ftell pourrait renvoyer n'importe
quoi. Pour déterminer la position dans un fichier, la fonction


Est-ce que ça a changé récemment ? Je lis ceci dans la norme C89
(la seule norme C que j'ai et il me semble celle sur laquelle est
basé C++) :

The ftell function obtains the current value of the file position
indicator [...]. For a binary stream, the value is the number of
characters from the beginning of the file. [...]

Il me semble donc qu'avec un stream en mode binaire, ça fonctionne
pas si mal. Et ftell renvoie un long par ailleur...

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

Avatar
kanze
"Régis Troadec" wrote in message
news:<btkri2$3g5$...

"Laurent" a écrit dans le message de news:
btk39j$l34$
c'est simple, ce programme fonctionne normallement sans debug, et en
debug, il me trouve un eof() des le premier input.read()

JE NE COMPRENDS PAS !!!!!!!!!!!


le "ça marche pas en debug mais autrement oui" sous Visual reste vague
dans ton post : qu'entends-tu par là ?


Qu'il trouve un eof() dès le premier input.read(), j'imagine. C'est ce
qu'il a dit, de toute façon.

Lances-tu l'exécutable du dossier de la version debug (par rapport à
celui de la release), auquel cas "fichier.txt" n'y est peut-être pas
présent ?


Je suppose qu'il a assez de bon sens pour d'abord vérifier qu'il a
lancé les deux versions depuis le même répertoire, et que le fichier à
ouvrir était bien présent.

#include <iostream.h>
#include <fstream.h>
#include <stdio.h>


headers superflus :
#include <iostream.h> => inclus avec fstream


Peut-être. En fait, je vois mal comment on pourrait implémenter
fstream.h sans inclure iostream.h, mais formellement, il n'y a aucune
garantie. En tout cas, c'est en général considéré une bonne pratique
d'include tout ce dont on a besoin, même quand on le sait inclu
indirectement.

#include <stdio.h> => bon pour les E/S C, pas ici


En général (et ici), oui, mais il ne faut pas oublier que c'est toujours
dans <stdio.h> (ou <cstdio>) que sont définis remove et rename.

void main(void)
{
ifstream input;
char Carac[1];
int Taille;


Taille non initialisée => int Taille = 0;


Pas du tout. Taille non initialisée implique Taille non initialisée. La
première lecture en donne un comportement indéfini. Typiquement, tu as
simplement une valeur au hazard. En mode debug, un bon compilateur
pourrait l'initialiser avec quelque chose de marquant (0xdeadbeef a une
certaine popularité). Voire même y associer un flag caché qu'il teste
avant la lecture, pour générer une erreur (échec d'assertion) dans le
cas d'un accès sans écriture préalable.

Dans un cas aussi simple que ceci, j'imagine que la plupart des
compilateur donnerait un avertissement, au moins si on a activé
l'optimisation (pour qu'ils fassent l'analyse de flux nécessaire).

char Carac[1] pas très élégant => char Carac; // voir plus loin


Tout à fait d'accord. J'ai supposé (peut-être à tort, mais je donne
toujours la bénéfice de la doute) qu'il avait commencé avec quelque
chose de plus compliqué, avec peut-être un buffer plus grand, et que le
[1] était le résultat d'avoir simplifier.

ouverture de flux plus simple (ios::in est par defaut) => ifstream
input("fichier.txt"); // open à virer en dessous


En somme, tu sais qu'il y a des choses qui se passe derrier ton dos,
mais tu ne veux surtout pas que le lecteur le sache. Dans ce cas-ci, on
peut supposer évidemment que le lecteur sache aussi ce que fait
ifstream, et donc, qu'il n'y a pas vraiment dissimilation. Bien que, vue
la question, et ta réponse...

input.open("fichier.txt",ios::in);

do
{
input.read(Carac, sizeof(Carac));
if(input.good())
{
Taille++;
}
}
while(!input.eof());


=> Tester si flux bien ouvert avant et prevoir une gestion sinon:


Il n'y a pas de sinon. Le traitement d'un fichier qu'on ne peut pas
ouvrir n'est pas le même que le traitement d'un fichier vide.

=> get (lit 1 caractère) plus facile que read (utilisé plutôt pour flux
binaire), sinon => input.read(&Carac, sizeof(Carac));


Moi, aussi, si on lit caractère par caractère, j'utiliserais get.

Quant à binary, il faudrait d'abord savoir ce qu'il veut faire.

=> test dans boucle peu élégant


Mais fréquent. Il n'y a pas de solution élégante, en fait. C'est
pourquoi la question se trouve discutée si souvent.

Je te propose :

if( input ) {
while ( input.good() ) { // tt que eof non atteinte ou pas
d'erreur


Comme j'ai indiqué par ailleurs, ios::good() est une fonction sans la
moindre utilité.

input.get( Carac ); // lit 1 caractere
Taille++; // incr


Et si la lecture échoue ? Ce qui va arriver forcement à la fin. Tu
compte un de trop.

}
}
else {
cout << "blabla..." << endl;
}


cout << "Taille : " << Taille << " octets.";

}


Et voilà.


Tu l'as testé ? Y compris vérifié que le résultat était juste ?

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16


Avatar
Régis Troadec
a écrit dans le message de news:

"Régis Troadec" wrote in message
news:<btkri2$3g5$...

"Laurent" a écrit dans le message de news:
btk39j$l34$
c'est simple, ce programme fonctionne normallement sans debug, et en
debug, il me trouve un eof() des le premier input.read()

JE NE COMPRENDS PAS !!!!!!!!!!!


le "ça marche pas en debug mais autrement oui" sous Visual reste vague
dans ton post : qu'entends-tu par là ?


Qu'il trouve un eof() dès le premier input.read(), j'imagine. C'est ce
qu'il a dit, de toute façon.

Lances-tu l'exécutable du dossier de la version debug (par rapport à
celui de la release), auquel cas "fichier.txt" n'y est peut-être pas
présent ?


Je suppose qu'il a assez de bon sens pour d'abord vérifier qu'il a
lancé les deux versions depuis le même répertoire, et que le fichier à
ouvrir était bien présent.

#include <iostream.h>
#include <fstream.h>
#include <stdio.h>


headers superflus :
#include <iostream.h> => inclus avec fstream


Peut-être. En fait, je vois mal comment on pourrait implémenter
fstream.h sans inclure iostream.h, mais formellement, il n'y a aucune
garantie. En tout cas, c'est en général considéré une bonne pratique
d'include tout ce dont on a besoin, même quand on le sait inclu
indirectement.

#include <stdio.h> => bon pour les E/S C, pas ici


En général (et ici), oui, mais il ne faut pas oublier que c'est toujours
dans <stdio.h> (ou <cstdio>) que sont définis remove et rename.

void main(void)
{
ifstream input;
char Carac[1];
int Taille;


Taille non initialisée => int Taille = 0;


Pas du tout. Taille non initialisée implique Taille non initialisée. La
première lecture en donne un comportement indéfini. Typiquement, tu as
simplement une valeur au hazard. En mode debug, un bon compilateur
pourrait l'initialiser avec quelque chose de marquant (0xdeadbeef a une
certaine popularité). Voire même y associer un flag caché qu'il teste
avant la lecture, pour générer une erreur (échec d'assertion) dans le
cas d'un accès sans écriture préalable.


Oui, d'accord car de toute façon, il s'agit d'une déclaration ET d'une
définition, mais en affectant une valeur dès le départ, la recherche
d'erreurs s'en trouve facilitée


Dans un cas aussi simple que ceci, j'imagine que la plupart des
compilateur donnerait un avertissement, au moins si on a activé
l'optimisation (pour qu'ils fassent l'analyse de flux nécessaire).

char Carac[1] pas très élégant => char Carac; // voir plus loin


Tout à fait d'accord. J'ai supposé (peut-être à tort, mais je donne
toujours la bénéfice de la doute) qu'il avait commencé avec quelque
chose de plus compliqué, avec peut-être un buffer plus grand, et que le
[1] était le résultat d'avoir simplifier.

ouverture de flux plus simple (ios::in est par defaut) => ifstream
input("fichier.txt"); // open à virer en dessous


En somme, tu sais qu'il y a des choses qui se passe derrier ton dos,
mais tu ne veux surtout pas que le lecteur le sache. Dans ce cas-ci, on
peut supposer évidemment que le lecteur sache aussi ce que fait
ifstream, et donc, qu'il n'y a pas vraiment dissimilation. Bien que, vue
la question, et ta réponse...

input.open("fichier.txt",ios::in);

do
{
input.read(Carac, sizeof(Carac));
if(input.good())
{
Taille++;
}
}
while(!input.eof());


=> Tester si flux bien ouvert avant et prevoir une gestion sinon:


Il n'y a pas de sinon. Le traitement d'un fichier qu'on ne peut pas
ouvrir n'est pas le même que le traitement d'un fichier vide.

=> get (lit 1 caractère) plus facile que read (utilisé plutôt pour flux
binaire), sinon => input.read(&Carac, sizeof(Carac));


Moi, aussi, si on lit caractère par caractère, j'utiliserais get.

Quant à binary, il faudrait d'abord savoir ce qu'il veut faire.

=> test dans boucle peu élégant


Mais fréquent. Il n'y a pas de solution élégante, en fait. C'est
pourquoi la question se trouve discutée si souvent.

Je te propose :

if( input ) {
while ( input.good() ) { // tt que eof non atteinte ou pas
d'erreur


Comme j'ai indiqué par ailleurs, ios::good() est une fonction sans la
moindre utilité.

input.get( Carac ); // lit 1 caractere
Taille++; // incr


Et si la lecture échoue ? Ce qui va arriver forcement à la fin. Tu
compte un de trop.

}
}
else {
cout << "blabla..." << endl;
}


cout << "Taille : " << Taille << " octets.";

}


Et voilà.


Tu l'as testé ? Y compris vérifié que le résultat était juste ?
--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16




Avatar
James Kanze
"Michel Michaud" writes:

|> Dans news:,
|> > Sauf qu'en général, la taille d'un fichier ne tient pas sur
|> > un int. Si le fseek est assez sûr, le ftell pourrait renvoyer
|> > n'importe quoi. Pour déterminer la position dans un fichier, la
|> > fonction

|> Est-ce que ça a changé récemment ?

Pas depuis C90, à ce que je sache. C'était bien une innovation du
comité de normalisation de C, en revanche.

|> Je lis ceci dans la norme C89 (la seule norme C que j'ai et il me
|> semble celle sur laquelle est basé C++) :

|> The ftell function obtains the current value of the file position
|> indicator [...]. For a binary stream, the value is the number of
|> characters from the beginning of the file. [...]

|> Il me semble donc qu'avec un stream en mode binaire, ça
|> fonctionne pas si mal. Et ftell renvoie un long par ailleur...

Et voilà le problème. Sur pas mal de systèmes, encore
aujourd'hui, un long, ça n'a que 32 bits. Or qu'un système
aujourd'hui qui limite la taille d'un fichier à 2^32, c'est vraiment
taré (et je n'en connais pas). Alors, quoiqu'en dit la norme...

En fait, déjà avant la norme C90, le problème était connu.
C'est pour ça que C90 a introduit fpos_t et fgetpos/fsetpos. Les
veilles fonctions, fseek et ftell, continuent à fonctionner comme
avant dans les cas où elles peuvent marcher (ce qui devient assez
rare de nos jours), mais le code nouveau doit se servir des nouvelles.

--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France +33 1 41 89 80 93
Avatar
James Kanze
Jean-Marc Bourguet writes:

|> "Régis Troadec" writes:

|> > C'est vrai et ta solution est plus commode.

|> > Mais pourquoi donc le fait d'utiliser ios_base::good() ne
|> > garantirait pas que l'opération suivante soit réussie ? (De
|> > même, ios_base::fail() ne garantirait-il pas que l'opération
|> > suivante échoue ?)

|> Parce que good() indique que l'operation precedente a reussit et
|> fail() qu'elle a echoue.

Si good() renvoie vrai, l'opération précédante a réussit. Si
good() renvoie faux, en revanche, on ne sait pas si l'opération
précédante a réussit ou non.

--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France +33 1 41 89 80 93
Avatar
James Kanze
"Michel Michaud" writes:

|> Dans news:btm5nt$if1$, Thomas
|> > donc

|> > if( input ) {
|> > while ( input.good() ) { // tt que eof non atteinte

|> Moi, je réagis fortement (et négativement) quand mes
|> élèves prennent la peine d'écrire un commentaire et qu'il
|> ne correspond pas à ce qu'il commente !!!

En général, les commentaires qui expliquent ce qui est évident
sont à éviter, même s'ils sont vrais. :-) Et je réagirais
aussi négativement à un élève qui utilise ios::good() sans
savoir ce qu'il fait.

|> Le if est par ailleurs inutile...

Il pourrait potentiellement permettre un message d'erreur différent
quand on n'arrive pas à ouvrir le fichier.

--
James Kanze mailto:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France +33 1 41 89 80 93
Avatar
Gabriel Dos Reis
James Kanze writes:

| Et voilà le problème. Sur pas mal de systèmes, encore
| aujourd'hui, un long, ça n'a que 32 bits. Or qu'un système
| aujourd'hui qui limite la taille d'un fichier à 2^32, c'est vraiment
| taré (et je n'en connais pas). Alors, quoiqu'en dit la norme...

Tu utilises quelle version de solaris ?

-- Gaby
Avatar
Michel Michaud
Dans news:, James
"Michel Michaud" writes:
Je lis ceci dans la norme C89 (la seule norme C que j'ai et il me
semble celle sur laquelle est basé C++) :

The ftell function obtains the current value of the file
position indicator [...]. For a binary stream, the value is
the number of characters from the beginning of the file. [...]

Il me semble donc qu'avec un stream en mode binaire, ça
fonctionne pas si mal. Et ftell renvoie un long par ailleur...



Et voilà le problème. Sur pas mal de systèmes, encore
aujourd'hui, un long, ça n'a que 32 bits. Or qu'un système
aujourd'hui qui limite la taille d'un fichier à 2^32, c'est vraiment
taré (et je n'en connais pas). Alors, quoiqu'en dit la norme...


Les fichiers de plus de 4 gigaoctets sont plutôt rares sur ma
machine (je n'en ai aucun pour le moment !). Pas sur la tienne ?


En fait, déjà avant la norme C90, le problème était connu.
C'est pour ça que C90 a introduit fpos_t et fgetpos/fsetpos. Les
veilles fonctions, fseek et ftell, continuent à fonctionner comme
avant dans les cas où elles peuvent marcher (ce qui devient assez
rare de nos jours), mais le code nouveau doit se servir des


Il me semble qu'il y a bien des cas où l'analyse nous dira que les
fichiers qu'on veut traiter auront moins de 4 gigaoctets et ce,
encore pour longtemps.

nouvelles.


Je verrais bien ftell faire exactement ce que voulait la personne
qui a posé la question originalement. Ton explication détaillée
permet de voir les limites. Dire simplement que ftell ne donne pas
ce qu'on pense est un peu différent (certains ont avancé que ça ne
renvoyait pas une valeur numérique, confondant donc fgetpos et
ftell...).


--
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 news:, James
"Michel Michaud" writes:

Dans news:btm5nt$if1$, Thomas
donc

if( input ) {
while ( input.good() ) { // tt que eof non atteinte


Moi, je réagis fortement (et négativement) quand mes
élèves prennent la peine d'écrire un commentaire et qu'il
ne correspond pas à ce qu'il commente !!!



En général, les commentaires qui expliquent ce qui est évident
sont à éviter, même s'ils sont vrais. :-)


Oui oui, j'espère que c'était assez clair par mon message (mon
« correspond » ne veut pas dire « répète »), mais il ne faut
pas qu'il contredise ce que le code fait non plus !

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




1 2 3