OVH Cloud OVH Cloud

lecture d'un fichier

5 réponses
Avatar
fanny Chevalier
Bonjour,

Je dispose d'un fichier contenant des données utilisateur sur chaque ligne.
Pour lire ce fichier, j'ouvre un flux ifstream et récupère chaque champ
selon son type (entier, chaine, ...)
Cependant, certaines lignes ne respectent pas le meme format que les
autres en ce qui concerne les champs.
Autrement dit je dispose de ces deux types de formats :

entier entier caractere entier date(format aaaa-jj-mm)
entier entier caractere date(format aaaa-jj-mm)

Comment puis-je faire pour identifier les lignes qui contiennent
l'entier supplémentaire ?

Je recupère une ligne ainsi (cas de la ligne sans l'entier
supplémentaire) :

ifstream input;
// ouverture fichier

int entier1, entier2, annee, jour, mois;
char caratere, c_temp;

input >> entier1 >> entier2 >> caractere >> annee >> c_temp >> jour >>
c_temp >> mois;

Peut-etre je peux pré-traiter mon fichier en ajoutant en debut de ligne
le nombre de mots qu'elle contient ?

Merci par avance pour vos réponses.

F.C.

5 réponses

Avatar
Michel Decima
In news:e669pm$4o2$,
fanny Chevalier typed:
Bonjour,

Je dispose d'un fichier contenant des données utilisateur sur chaque
ligne. Pour lire ce fichier, j'ouvre un flux ifstream et récupère
chaque champ selon son type (entier, chaine, ...)
Cependant, certaines lignes ne respectent pas le meme format que les
autres en ce qui concerne les champs.
Autrement dit je dispose de ces deux types de formats :

entier entier caractere entier date(format aaaa-jj-mm)
entier entier caractere date(format aaaa-jj-mm)

Comment puis-je faire pour identifier les lignes qui contiennent
l'entier supplémentaire ?


Lire les lignes une par une dans une chaine de caracteres, et ensuite
traiter le contenu de la chaine avec un istringstream

std::ifstream input("data.txt");
std::string line;
while (getline(input, line)) {
std::istringstream parser(line);

parser >> entier1 >> entier2 >> caractere >> annee >> c_temp
jour >> c_temp >> mois;



if (parser >> entier_supplementaire) {
...
}
}


Avatar
Fabien LE LEZ
On Wed, 7 Jun 2006 13:21:07 +0200, "Michel Decima"
:

Lire les lignes une par une dans une chaine de caracteres,


Oui.

et ensuite
traiter le contenu de la chaine avec un istringstream


Y'a pas à dire, les istream ne m'ont jamais inspiré.

En PHP, j'utiliserais les regex sans hésiter une seconde ; en C++,
j'ai moins ce réflexe, mais ça peut tout de même être une bonne idée.

Avatar
Michel Decima
In news:,
Fabien LE LEZ typed:
On Wed, 7 Jun 2006 13:21:07 +0200, "Michel Decima"
:

Lire les lignes une par une dans une chaine de caracteres,


Oui.

et ensuite
traiter le contenu de la chaine avec un istringstream


Y'a pas à dire, les istream ne m'ont jamais inspiré.

En PHP, j'utiliserais les regex sans hésiter une seconde ; en C++,
j'ai moins ce réflexe, mais ça peut tout de même être une bonne idée.


J'ai propose istringstream pour rester standard et ne pas trop 'perturber'
le code original. Apres, c'est la complexite de traitement et la
disponibilite
des outils qui determine le choix (si on va jusqu'a Boost.Spirit, il faut
aussi
ajouter les competences du programmeur...)


Avatar
fanny Chevalier
Michel Decima wrote:
In news:,
Fabien LE LEZ typed:

On Wed, 7 Jun 2006 13:21:07 +0200, "Michel Decima"
:


Lire les lignes une par une dans une chaine de caracteres,


Oui.


et ensuite
traiter le contenu de la chaine avec un istringstream


Y'a pas à dire, les istream ne m'ont jamais inspiré.

En PHP, j'utiliserais les regex sans hésiter une seconde ; en C++,
j'ai moins ce réflexe, mais ça peut tout de même être une bonne idée.



J'ai propose istringstream pour rester standard et ne pas trop 'perturber'
le code original. Apres, c'est la complexite de traitement et la
disponibilite
des outils qui determine le choix (si on va jusqu'a Boost.Spirit, il faut
aussi
ajouter les competences du programmeur...)


Merci pour votre aide, mais j'ai opté pour awk qui me rajoute le nombre
de champs de chaque ligne en début de ligne
Ainis, en testant cette valeur, je sais si la ligne comporte l'entier
supplémentaire ou non.

awk '{print NF " " $0}' monFichier > copieFichier

Merci encore



Avatar
kanze
Fabien LE LEZ wrote:
On Wed, 7 Jun 2006 13:21:07 +0200, "Michel Decima"
:

Lire les lignes une par une dans une chaine de caracteres,


Oui.

et ensuite traiter le contenu de la chaine avec un
istringstream


Y'a pas à dire, les istream ne m'ont jamais inspiré.


Tout dépend de ce qu'il y a à faire, mais en général, si le
nombre de champs varie, je crois que tu as raison. On peut le
faire, ici, avec quelque chose du genre :

std::string line ;
while ( std::getline( source, line ) ) {
std::istringstream s( line ) ;
std::vector< std::string >
fields(
(std::istream_iterator< std::string >( s )),
(std::istream_iterator< std::string >()),
std::back_inserter( fields ) ;
switch ( fields.size() ) {
case 4 :
// Quatre champs ...
break ;

case 5 :
// Cinq champs ...
break ;

default :
// Erreur...
break ;
}
}

Mais j'aurais plutôt tendance à utiliser ma classe FieldArray (à
http://kanze.james.neuf.fr, j'espère).

En PHP, j'utiliserais les regex sans hésiter une seconde ; en
C++, j'ai moins ce réflexe, mais ça peut tout de même être une
bonne idée.


C'est aussi une solution. Moi-même, j'ai énormement l'habitude
de AWK pour ce genre de chose. Au point que les toutes premières
classes que j'ai écrites en C++, c'était pour faire des choses
qu'on fait naturellement en AWK : String (naturellement, à
l'époque), AssocArray (un tableau haché indexé par des String --
aujourd'hui avec le type d'index comme paramètre du template
aussi), et FieldArray, qui découpe une chaîne en champs, selon
un critère donné. Pendant longtemps, je me servais du modèle
template et l'héritage pour choisir le critère ; aujourd'hui,
c'est le modèle stratégie, mais dans les utilisations typiques,
il n'y a pas de différence. Quelque chose comme ci-dessus

std::string line ;
while ( std::getline( source, line ) ) {
Gabi::BlankSeparatedFields
fields( line ) ;
// ...
}

La véritable avantage, par rapport à la solution purement
standard ci-dessus, c'est que par la suite, tu peux changer la
définition de ce que c'est qu'un champ simplement en changeant
le type de fields (ou en se servant de la classe de base,
Gabi::FieldArray, et en fournissant toi-même le Splitter (le
délégué qui fait le travail).

Sinon aussi, boost::regex offre pas mal de possibilités.

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