Bonjour,
J'ai une série de données en lignes, séparées par des virgules, dans un
fichier texte. J'arrive à saisir mes données (fscanf("%lf,",&variable);)
mais je ne sais pas comment arreter mon acquisition (ie quand je suis au
bout de la ligne). Mon nombre de données n'est pas fixe!
J'aimerais éviter l'acquisition par une chaine, qui nécessiterait la
déclaration d'un tableau de caractères trop grand.
Merci d'avance pour votre aide et vos suggestions.
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Michaël Monerau
Antoine ALBERT wrote:
Bonjour, J'ai une série de données en lignes, séparées par des virgules, dans un fichier texte. J'arrive à saisir mes données (fscanf("%lf,",&variable);) mais je ne sais pas comment arreter mon acquisition (ie quand je suis au bout de la ligne). Mon nombre de données n'est pas fixe! J'aimerais éviter l'acquisition par une chaine, qui nécessiterait la déclaration d'un tableau de caractères trop grand.
Aïe... Ce que tu proposes là est du C (alors : news:fr.comp.lang.c). Sinon, si tu veux vraiment faire du C++, on utilise les flux plus simplement :
int i; vector<int> MesInts;
while (cin >> i) MesInts.push_back (i);
C'est plus `safe', et plus pratique aussi.
Ca s'arrêtera tout seul au bout de la ligne. Il y a d'autres moyens avec un back_inserter mais je ne connais pas bien ce côté-là, mais je préfère te donner des pistes que je connais ;-) -- <=- Michaël "Cortex" Monerau -=>
Antoine ALBERT wrote:
Bonjour,
J'ai une série de données en lignes, séparées par des virgules, dans
un fichier texte. J'arrive à saisir mes données
(fscanf("%lf,",&variable);) mais je ne sais pas comment arreter mon
acquisition (ie quand je suis au bout de la ligne). Mon nombre de
données n'est pas fixe!
J'aimerais éviter l'acquisition par une chaine, qui nécessiterait la
déclaration d'un tableau de caractères trop grand.
Aïe... Ce que tu proposes là est du C (alors : news:fr.comp.lang.c). Sinon,
si tu veux vraiment faire du C++, on utilise les flux plus simplement :
int i;
vector<int> MesInts;
while (cin >> i)
MesInts.push_back (i);
C'est plus `safe', et plus pratique aussi.
Ca s'arrêtera tout seul au bout de la ligne. Il y a d'autres moyens avec un
back_inserter mais je ne connais pas bien ce côté-là, mais je préfère te
donner des pistes que je connais ;-)
--
<=- Michaël "Cortex" Monerau -=>
Bonjour, J'ai une série de données en lignes, séparées par des virgules, dans un fichier texte. J'arrive à saisir mes données (fscanf("%lf,",&variable);) mais je ne sais pas comment arreter mon acquisition (ie quand je suis au bout de la ligne). Mon nombre de données n'est pas fixe! J'aimerais éviter l'acquisition par une chaine, qui nécessiterait la déclaration d'un tableau de caractères trop grand.
Aïe... Ce que tu proposes là est du C (alors : news:fr.comp.lang.c). Sinon, si tu veux vraiment faire du C++, on utilise les flux plus simplement :
int i; vector<int> MesInts;
while (cin >> i) MesInts.push_back (i);
C'est plus `safe', et plus pratique aussi.
Ca s'arrêtera tout seul au bout de la ligne. Il y a d'autres moyens avec un back_inserter mais je ne connais pas bien ce côté-là, mais je préfère te donner des pistes que je connais ;-) -- <=- Michaël "Cortex" Monerau -=>
Jonathan Mcdougall
int i; vector<int> MesInts;
while (cin >> i) MesInts.push_back (i);
Ca s'arrêtera tout seul au bout de la ligne. Il y a d'autres moyens avec un
back_inserter mais je ne connais pas bien ce côté-là, mais je préfère te donner des pistes que je connais ;-)
"Michaël Monerau" wrote in message news:<OMieb.201192$...
Antoine ALBERT wrote:
J'ai une série de données en lignes, séparées par des virgules, dans un fichier texte. J'arrive à saisir mes données (fscanf("%lf,",&variable);) mais je ne sais pas comment arreter mon acquisition (ie quand je suis au bout de la ligne). Mon nombre de données n'est pas fixe! J'aimerais éviter l'acquisition par une chaine, qui nécessiterait la déclaration d'un tableau de caractères trop grand.
Aïe... Ce que tu proposes là est du C (alors : news:fr.comp.lang.c). Sinon, si tu veux vraiment faire du C++, on utilise les flux plus simplement :
int i; vector<int> MesInts;
while (cin >> i) MesInts.push_back (i);
C'est plus `safe', et plus pratique aussi.
Ca s'arrêtera tout seul au bout de la ligne.
Non, ça ne s'arrêtera pas au bout de la ligne. Ça ne s'arrêtera qu'à la fin du fichier.
La façon habituelle de traiter une seule ligne, c'est :
std::string ligne ; if ( ! std::getline( std::cin, ligne ) ) { // Erreur... } else { std::istringstream s( ligne ) ; // ... Parser la ligne... }
Dans son cas, c'est encore plus complexe, parce que le séparateur, c'est une virgule, et non des espaces. Alors, il n'y a pas de support direct ; il faut vraiment parser. Quelque chose du genre :
bool getValue( std::istream& s, std::vector< double >& v ) { double tmp ; s >> tmp ; if ( s ) { v.push_back( tmp ) ; } return s ; }
bool checkSeparator( s ) { char ch ; return s >> ch && ch == ',' ; }
std::vector< double > result ; std::string ligne ; if ( std::getline( std::cin, ligne ) ) { std::istringstream s( ligne ) ; while ( getValue( s, result ) && checkSeparator( s ) ) { } }
Même là, il manque bien de traitement des erreurs.
Il y a d'autres moyens avec un back_inserter mais je ne connais pas bien ce côté-là, mais je préfère te donner des pistes que je connais ;-)
Je ne vois pas l'avantage que tu donnera un back_iterator ici.
-- 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
"Michaël Monerau" <cort@meloo.com> wrote in message
news:<OMieb.201192$hd6.2622240@news.chello.at>...
Antoine ALBERT wrote:
J'ai une série de données en lignes, séparées par des virgules, dans
un fichier texte. J'arrive à saisir mes données
(fscanf("%lf,",&variable);) mais je ne sais pas comment arreter mon
acquisition (ie quand je suis au bout de la ligne). Mon nombre de
données n'est pas fixe! J'aimerais éviter l'acquisition par une
chaine, qui nécessiterait la déclaration d'un tableau de caractères
trop grand.
Aïe... Ce que tu proposes là est du C (alors : news:fr.comp.lang.c).
Sinon, si tu veux vraiment faire du C++, on utilise les flux plus
simplement :
int i;
vector<int> MesInts;
while (cin >> i)
MesInts.push_back (i);
C'est plus `safe', et plus pratique aussi.
Ca s'arrêtera tout seul au bout de la ligne.
Non, ça ne s'arrêtera pas au bout de la ligne. Ça ne s'arrêtera qu'à la
fin du fichier.
La façon habituelle de traiter une seule ligne, c'est :
std::string ligne ;
if ( ! std::getline( std::cin, ligne ) ) {
// Erreur...
} else {
std::istringstream s( ligne ) ;
// ...
Parser la ligne...
}
Dans son cas, c'est encore plus complexe, parce que le séparateur, c'est
une virgule, et non des espaces. Alors, il n'y a pas de support direct ;
il faut vraiment parser. Quelque chose du genre :
bool
getValue( std::istream& s, std::vector< double >& v )
{
double tmp ;
s >> tmp ;
if ( s ) {
v.push_back( tmp ) ;
}
return s ;
}
bool
checkSeparator( s )
{
char ch ;
return s >> ch && ch == ',' ;
}
std::vector< double > result ;
std::string ligne ;
if ( std::getline( std::cin, ligne ) ) {
std::istringstream s( ligne ) ;
while ( getValue( s, result ) && checkSeparator( s ) ) {
}
}
Même là, il manque bien de traitement des erreurs.
Il y a d'autres moyens avec un back_inserter mais je ne connais pas
bien ce côté-là, mais je préfère te donner des pistes que je connais
;-)
Je ne vois pas l'avantage que tu donnera un back_iterator ici.
--
James Kanze GABI Software mailto:kanze@gabi-soft.fr
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
"Michaël Monerau" wrote in message news:<OMieb.201192$...
Antoine ALBERT wrote:
J'ai une série de données en lignes, séparées par des virgules, dans un fichier texte. J'arrive à saisir mes données (fscanf("%lf,",&variable);) mais je ne sais pas comment arreter mon acquisition (ie quand je suis au bout de la ligne). Mon nombre de données n'est pas fixe! J'aimerais éviter l'acquisition par une chaine, qui nécessiterait la déclaration d'un tableau de caractères trop grand.
Aïe... Ce que tu proposes là est du C (alors : news:fr.comp.lang.c). Sinon, si tu veux vraiment faire du C++, on utilise les flux plus simplement :
int i; vector<int> MesInts;
while (cin >> i) MesInts.push_back (i);
C'est plus `safe', et plus pratique aussi.
Ca s'arrêtera tout seul au bout de la ligne.
Non, ça ne s'arrêtera pas au bout de la ligne. Ça ne s'arrêtera qu'à la fin du fichier.
La façon habituelle de traiter une seule ligne, c'est :
std::string ligne ; if ( ! std::getline( std::cin, ligne ) ) { // Erreur... } else { std::istringstream s( ligne ) ; // ... Parser la ligne... }
Dans son cas, c'est encore plus complexe, parce que le séparateur, c'est une virgule, et non des espaces. Alors, il n'y a pas de support direct ; il faut vraiment parser. Quelque chose du genre :
bool getValue( std::istream& s, std::vector< double >& v ) { double tmp ; s >> tmp ; if ( s ) { v.push_back( tmp ) ; } return s ; }
bool checkSeparator( s ) { char ch ; return s >> ch && ch == ',' ; }
std::vector< double > result ; std::string ligne ; if ( std::getline( std::cin, ligne ) ) { std::istringstream s( ligne ) ; while ( getValue( s, result ) && checkSeparator( s ) ) { } }
Même là, il manque bien de traitement des erreurs.
Il y a d'autres moyens avec un back_inserter mais je ne connais pas bien ce côté-là, mais je préfère te donner des pistes que je connais ;-)
Je ne vois pas l'avantage que tu donnera un back_iterator ici.
-- 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
kanze
"Jonathan Mcdougall" wrote in message news:<%Yjeb.68765$...
int i; vector<int> MesInts;
while (cin >> i) MesInts.push_back (i);
Ca s'arrêtera tout seul au bout de la ligne. Il y a d'autres moyens avec un back_inserter mais je ne connais pas bien ce côté-là, mais je préfère te donner des pistes que je connais ;-)
Ce qui correspond bien à son code, mais qui ne résoud pas le problème initial non plus.
Le problème initial avait deux aspects importants à tenir en considération.
D'abord, il ne devait lire qu'une seule ligne. La solution la plus facile, c'est d'utiliser getline pour lire la ligne entièrement d'un coup, puis l'utiliser la ligne pour initialiser un istringstream d'où on lit les valeurs. Si pour une raison quelconque, one ne peut pas adopter cette solution (chose qui m'étonnerait), il faudrait pratiquement scanner la source caractère par caractère, au moyen de istream::get, parce que quand on lit avec les <<, le 'n' est considéré comme un espace blanc, et on le saute.
Le deuxième problème, c'est que les valeurs sont séparées par des virgules, et non simplement des espaces. Et les solutions proposées ci-dessus s'arrêtera avec une erreur à la première virgule. Il faut donc lire les caractères entre les valeurs, et vérifier qu'il y a une virgule.
En fait, ça doit donner quelque chose du genre :
std::istream& sautVirgule( std::istream& s ) { char tmp ; s >> tmp ; if ( s && tmp != ',' ) { s.setstate( std::ios::failbit ) ; } return s ; }
std::istream& lireLigneDeDoubles( std::istream& source, std::vector< double >& dest ) { std::string ligne ; if ( std::getline( source, ligne ) ) { std::istringstream s( ligne ) ; double tmp ; s >> tmp ; while ( s ) { dest.push_back( tmp ) ; sautVirgule( s ) ; } if ( ! s.eof() ) { dest.setstate( std::ios::failbit ) ; } } return source ; }
Après appel de la fonction, il faudrait évidemment tester l'état du flux. Comme d'habitude.
-- 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
"Jonathan Mcdougall" <jonathanmcdougall@DELyahoo.ca> wrote in message
news:<%Yjeb.68765$Wk2.1263031@weber.videotron.net>...
int i;
vector<int> MesInts;
while (cin >> i)
MesInts.push_back (i);
Ca s'arrêtera tout seul au bout de la ligne. Il y a d'autres moyens
avec un back_inserter mais je ne connais pas bien ce côté-là, mais
je préfère te donner des pistes que je connais ;-)
Ce qui correspond bien à son code, mais qui ne résoud pas le problème
initial non plus.
Le problème initial avait deux aspects importants à tenir en
considération.
D'abord, il ne devait lire qu'une seule ligne. La solution la plus
facile, c'est d'utiliser getline pour lire la ligne entièrement d'un
coup, puis l'utiliser la ligne pour initialiser un istringstream d'où on
lit les valeurs. Si pour une raison quelconque, one ne peut pas adopter
cette solution (chose qui m'étonnerait), il faudrait pratiquement
scanner la source caractère par caractère, au moyen de istream::get,
parce que quand on lit avec les <<, le 'n' est considéré comme un
espace blanc, et on le saute.
Le deuxième problème, c'est que les valeurs sont séparées par des
virgules, et non simplement des espaces. Et les solutions proposées
ci-dessus s'arrêtera avec une erreur à la première virgule. Il faut donc
lire les caractères entre les valeurs, et vérifier qu'il y a une
virgule.
En fait, ça doit donner quelque chose du genre :
std::istream&
sautVirgule( std::istream& s )
{
char tmp ;
s >> tmp ;
if ( s && tmp != ',' ) {
s.setstate( std::ios::failbit ) ;
}
return s ;
}
std::istream&
lireLigneDeDoubles(
std::istream& source,
std::vector< double >& dest )
{
std::string ligne ;
if ( std::getline( source, ligne ) ) {
std::istringstream s( ligne ) ;
double tmp ;
s >> tmp ;
while ( s ) {
dest.push_back( tmp ) ;
sautVirgule( s ) ;
}
if ( ! s.eof() ) {
dest.setstate( std::ios::failbit ) ;
}
}
return source ;
}
Après appel de la fonction, il faudrait évidemment tester l'état du
flux. Comme d'habitude.
--
James Kanze GABI Software mailto:kanze@gabi-soft.fr
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
"Jonathan Mcdougall" wrote in message news:<%Yjeb.68765$...
int i; vector<int> MesInts;
while (cin >> i) MesInts.push_back (i);
Ca s'arrêtera tout seul au bout de la ligne. Il y a d'autres moyens avec un back_inserter mais je ne connais pas bien ce côté-là, mais je préfère te donner des pistes que je connais ;-)
Ce qui correspond bien à son code, mais qui ne résoud pas le problème initial non plus.
Le problème initial avait deux aspects importants à tenir en considération.
D'abord, il ne devait lire qu'une seule ligne. La solution la plus facile, c'est d'utiliser getline pour lire la ligne entièrement d'un coup, puis l'utiliser la ligne pour initialiser un istringstream d'où on lit les valeurs. Si pour une raison quelconque, one ne peut pas adopter cette solution (chose qui m'étonnerait), il faudrait pratiquement scanner la source caractère par caractère, au moyen de istream::get, parce que quand on lit avec les <<, le 'n' est considéré comme un espace blanc, et on le saute.
Le deuxième problème, c'est que les valeurs sont séparées par des virgules, et non simplement des espaces. Et les solutions proposées ci-dessus s'arrêtera avec une erreur à la première virgule. Il faut donc lire les caractères entre les valeurs, et vérifier qu'il y a une virgule.
En fait, ça doit donner quelque chose du genre :
std::istream& sautVirgule( std::istream& s ) { char tmp ; s >> tmp ; if ( s && tmp != ',' ) { s.setstate( std::ios::failbit ) ; } return s ; }
std::istream& lireLigneDeDoubles( std::istream& source, std::vector< double >& dest ) { std::string ligne ; if ( std::getline( source, ligne ) ) { std::istringstream s( ligne ) ; double tmp ; s >> tmp ; while ( s ) { dest.push_back( tmp ) ; sautVirgule( s ) ; } if ( ! s.eof() ) { dest.setstate( std::ios::failbit ) ; } } return source ; }
Après appel de la fonction, il faudrait évidemment tester l'état du flux. Comme d'habitude.
-- 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
Michel Michaud
Dans news:,
Dans son cas, c'est encore plus complexe, parce que le séparateur, c'est une virgule, et non des espaces. Alors, il n'y a pas de support direct ; il faut vraiment parser. Quelque chose du genre :
Pourquoi pas getline(flux, valeur, ',') ?
-- Michel Michaud http://www.gdzid.com FAQ de fr.comp.lang.c++ : http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
Dans news:d6652001.0309302343.165e0d9c@posting.google.com,
Dans son cas, c'est encore plus complexe, parce que le séparateur,
c'est une virgule, et non des espaces. Alors, il n'y a pas de
support direct ; il faut vraiment parser. Quelque chose du genre :
Pourquoi pas getline(flux, valeur, ',') ?
--
Michel Michaud mm@gdzid.com
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
Dans son cas, c'est encore plus complexe, parce que le séparateur, c'est une virgule, et non des espaces. Alors, il n'y a pas de support direct ; il faut vraiment parser. Quelque chose du genre :
Pourquoi pas getline(flux, valeur, ',') ?
-- Michel Michaud http://www.gdzid.com FAQ de fr.comp.lang.c++ : http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
kanze
"Michel Michaud" wrote in message news:<dsKeb.5106$...
Dans news:,
Dans son cas, c'est encore plus complexe, parce que le séparateur, c'est une virgule, et non des espaces. Alors, il n'y a pas de support direct ; il faut vraiment parser. Quelque chose du genre :
Pourquoi pas getline(flux, valeur, ',') ?
Parce que le nom de la fonction ne dit pas ce qu'il fait:-).
Sérieusement, j'ai supposé que les virgules étaient des séparateurs, et non des terminateurs. C'est donc que la dernière valeur ne serait pas suivie d'une virgule. Et qu'on ne sait que c'est la dernière valeur qu'après l'avoir lu et avoir vu un 'n' à la place de la virgule.
C'est un problème assez fréquent dont on n'a pas vraiment une bonne solution tout faite dans la bibliothèque standard. On pourrait, par exemple, utiliser mes FieldArray pour la résoudre, mais au moins de les avoir sous la main, et de les connaître aussi bien qu'on connaît la bibliothèque standard, je ne crois pas que ça donnerait une solution plus simple que celui que j'ai posté. (En revanche, je verrais bien un manipulateur qui faisait à peu près ce que j'ai fait dans ma fonction sautVirgule.)
-- 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
"Michel Michaud" <mm@gdzid.com> wrote in message
news:<dsKeb.5106$op2.605805@news20.bellglobal.com>...
Dans news:d6652001.0309302343.165e0d9c@posting.google.com,
Dans son cas, c'est encore plus complexe, parce que le séparateur,
c'est une virgule, et non des espaces. Alors, il n'y a pas de
support direct ; il faut vraiment parser. Quelque chose du genre :
Pourquoi pas getline(flux, valeur, ',') ?
Parce que le nom de la fonction ne dit pas ce qu'il fait:-).
Sérieusement, j'ai supposé que les virgules étaient des séparateurs, et
non des terminateurs. C'est donc que la dernière valeur ne serait pas
suivie d'une virgule. Et qu'on ne sait que c'est la dernière valeur
qu'après l'avoir lu et avoir vu un 'n' à la place de la virgule.
C'est un problème assez fréquent dont on n'a pas vraiment une bonne
solution tout faite dans la bibliothèque standard. On pourrait, par
exemple, utiliser mes FieldArray pour la résoudre, mais au moins de les
avoir sous la main, et de les connaître aussi bien qu'on connaît la
bibliothèque standard, je ne crois pas que ça donnerait une solution
plus simple que celui que j'ai posté. (En revanche, je verrais bien un
manipulateur qui faisait à peu près ce que j'ai fait dans ma fonction
sautVirgule.)
--
James Kanze GABI Software mailto:kanze@gabi-soft.fr
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
"Michel Michaud" wrote in message news:<dsKeb.5106$...
Dans news:,
Dans son cas, c'est encore plus complexe, parce que le séparateur, c'est une virgule, et non des espaces. Alors, il n'y a pas de support direct ; il faut vraiment parser. Quelque chose du genre :
Pourquoi pas getline(flux, valeur, ',') ?
Parce que le nom de la fonction ne dit pas ce qu'il fait:-).
Sérieusement, j'ai supposé que les virgules étaient des séparateurs, et non des terminateurs. C'est donc que la dernière valeur ne serait pas suivie d'une virgule. Et qu'on ne sait que c'est la dernière valeur qu'après l'avoir lu et avoir vu un 'n' à la place de la virgule.
C'est un problème assez fréquent dont on n'a pas vraiment une bonne solution tout faite dans la bibliothèque standard. On pourrait, par exemple, utiliser mes FieldArray pour la résoudre, mais au moins de les avoir sous la main, et de les connaître aussi bien qu'on connaît la bibliothèque standard, je ne crois pas que ça donnerait une solution plus simple que celui que j'ai posté. (En revanche, je verrais bien un manipulateur qui faisait à peu près ce que j'ai fait dans ma fonction sautVirgule.)
-- 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