OVH Cloud OVH Cloud

istream_iterator

12 réponses
Avatar
Stan
bonjour,

j'aimerai écrire un truc du genre :

istream_iterator<string> in( cin );
istream_iterator<string> inend;

vector<string> lg(in, inend);
//...

sauf que je ne souhaite pas de l'espace comme séquence de fin mais un '\n'.
Quel est le moyen le plus simple pour stoker directement les lignes
provenant de cin ?
Merci.

--
-Stan

10 réponses

1 2
Avatar
Fabien LE LEZ
On Thu, 28 Jul 2005 12:27:31 +0200, "Stan" (
remove the dots )>:

Quel est le moyen le plus simple pour stoker directement les lignes
provenant de cin ?


std::vector <std::string> les_lignes;
std::string ligne;
while (std::getline (cin, ligne))
{
les_lignes.push_back (ligne);
}

Avatar
Stan
"Fabien LE LEZ" a écrit dans le message de news:

On Thu, 28 Jul 2005 12:27:31 +0200, "Stan" (
remove the dots )>:

Quel est le moyen le plus simple pour stoker directement les lignes
provenant de cin ?


std::vector <std::string> les_lignes;
std::string ligne;
while (std::getline (cin, ligne))
{
les_lignes.push_back (ligne);
}



Oui, mais mis a part cette écriture que j'utilise déja, je souhaiterais
utiliser l'idiome suivant :
//..
istream_iterator<string> in( cin );
istream_iterator<string> inend;

vector<string> lg(in, inend);
//..

Ma question était de savoir si on pouvait obtenir le même résultat avec le
style ci-dessus.

--
-Stan


Avatar
Loïc Joly

Oui, mais mis a part cette écriture que j'utilise déja, je souhaiterais
utiliser l'idiome suivant :
//..
istream_iterator<string> in( cin );
istream_iterator<string> inend;

vector<string> lg(in, inend);
//..

Ma question était de savoir si on pouvait obtenir le même résultat avec le
style ci-dessus.


Pour de la sortie, un ostream_iterator peut prendre un délimiteur en
paramètre de constructeur, pour l'entrée, je ne sais pas trop. Ca doit
pouvoir être possible de construire un istream_iterator<istream, char,
modifiedCharTrait>, avec modifiedCharTrait une classe qui va bien.

Perso, j'utiliserais la solution de Fabien.

--
Loïc

Avatar
Jean-Marc Bourguet
"Stan" ( remove the dots )> writes:

istream_iterator<string> in( cin );
istream_iterator<string> inend;

vector<string> lg(in, inend);
//..

Ma question était de savoir si on pouvait obtenir le même résultat avec le
style ci-dessus.


Tu te définis un line_iterator qui fait ce que tu veux. Il
y a aussi moyen en imbuant un locale dont le isspace fait ce
que tu veux mais c'est vraiment de l'abus.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Stan
"Jean-Marc Bourguet" a écrit dans le message de news:

"Stan" ( remove the dots )> writes:

istream_iterator<string> in( cin );
istream_iterator<string> inend;

vector<string> lg(in, inend);
//..

Ma question était de savoir si on pouvait obtenir le même résultat avec
le
style ci-dessus.


Tu te définis un line_iterator qui fait ce que tu veux. Il
y a aussi moyen en imbuant un locale dont le isspace fait ce
que tu veux mais c'est vraiment de l'abus.



Je suis un peu déçu que l'universalité n'inclut jamais le cas que
je touve le plus utile ;-)
Ou en d'autre termes, que ce qui m'interresse le plus fasse partie des
exceptions.


--
-Stan


Avatar
Fabien LE LEZ
On Thu, 28 Jul 2005 12:48:26 +0200, "Stan" :

Oui, mais mis a part cette écriture que j'utilise déja, je souhaiterais
utiliser l'idiome suivant :


Tu as demandé :
Quel est le moyen le plus simple pour stoker directement les lignes
provenant de cin ?



Je t'ai répondu en te donnant effectivement le moyen le plus simple.


Avatar
Falk Tannhäuser
Stan wrote:
j'aimerai écrire un truc du genre :

istream_iterator<string> in( cin );
istream_iterator<string> inend;

vector<string> lg(in, inend);
//...

sauf que je ne souhaite pas de l'espace comme séquence de fin mais un 'n'.


Tu peux définir une classe qui encapsule et qui est automatiquement
convertible vers std::string, et dont la lecture par operator>> se
passe comme tu veux :

#include <iostream>
#include <istream>
#include <ostream>
#include <string>
#include <iterator>
#include <vector>

struct line_string
{
std::string s;
operator std::string() const { return s; }
};

std::istream& operator>>(std::istream& in, line_string& ls)
{ return std::getline(in, ls.s); }

// ...
std::vector<std::string> lg((std::istream_iterator<line_string>(std: :cin)),
(std::istream_iterator<line_string>()));

Falk

Avatar
Stan
"Fabien LE LEZ" a écrit dans le message de news:

On Thu, 28 Jul 2005 12:48:26 +0200, "Stan" :

Oui, mais mis a part cette écriture que j'utilise déja, je souhaiterais
utiliser l'idiome suivant :


Tu as demandé :
Quel est le moyen le plus simple pour stoker directement les lignes
provenant de cin ?



Je t'ai répondu en te donnant effectivement le moyen le plus simple.



La question est en relation avec l'exemple que j'ai donné, sinon je ne
l'aurait pas mentionné.
Si tu isoles la question de son contexte...

Je peux reformuler :
Quel est le moyen le plus simple pour stoker directement les lignes
provenant de cin en utilisant "istream_iterator<string> in( cin )" ?

mais il me semblait que s'était implicite.
--
-Stan



Avatar
James Kanze
Stan wrote:
"Jean-Marc Bourguet" a écrit dans le message
de news:


"Stan" ( remove the dots )> writes:



istream_iterator<string> in( cin );
istream_iterator<string> inend;




vector<string> lg(in, inend);
//..




Ma question était de savoir si on pouvait obtenir le même
résultat avec le style ci-dessus.




Tu te définis un line_iterator qui fait ce que tu veux. Il y a
aussi moyen en imbuant un locale dont le isspace fait ce que
tu veux mais c'est vraiment de l'abus.



Je suis un peu déçu que l'universalité n'inclut jamais le cas
que je touve le plus utile ;-) Ou en d'autre termes, que ce
qui m'interresse le plus fasse partie des exceptions.


L'universalité n'inclut jamais tout.

Ici, j'aime plutôt la réponse de Falk ; s'il n'avait pas répondu
d'abord, j'aurais répondu avec exactement la même chose. Le
problème, ici, c'est que std::string, ce n'est pas une
abstraction assez concrète pour qu'on puisse réelement définir
un opérateur <<. On le fait, en partie pour des raisons
historiques, et la définition en tient surtout compte des
critères historiques (et les habitudes du milieu où C est né,
celui de Unix). Mais dans la pratique, ce qu'il faut lire, ce
sont des lignes, ou des mots, ou qui sait quoi d'autre.

Note bien que les opérateurs >> et << de la norme ne sont que
des outils d'assez bas niveau. Dans la pratique, je m'en sers
prèsqu'exclusivement dans des opérateurs >> et << de mes propres
types. Aussi : il ne faut pas perdre de vue qu'ils ne supportent
pas directement un aller-retour ; pour lire correctement ce que
tu as écrit, il faut systèmatiquement insérer un séparateur, et
le système est organisé de façon à ce qu'espace blanc soit le
séparateur de choix. Mais dans le cas des std::string (et des
char*, évidemment), même ça ne suffit pas, parce que la
représentation peut, elle aussi, contenir des blancs.

Le résultat, c'est qu'effectivement, je n'utilise jamais >>
directement sur une chaîne. Pour la plupart des cas simples,
j'itère directement avec getline, pour parser chaque ligne en ce
dont j'ai besoin. Sinon, j'utilise une classe Line (mais souvent
avec des attributes en plus de simplement le text -- il m'est
arrivé, par exemple, d'enlever des blancs en tête, et de
maintenir une « indentation », et j'ai même un cas où la ligne
se décompose en quatre parties) ou une class ParsableString qui
fait partie de ma boîte à outils : à l'écriture, s'il y a du
blanc, un ''' ou un '"', ou des caractères non imprimables, il
met la chaîne en "...", avec des échappements nécessaires à
l'intérieur, et à la lecture, évidemment, il reconnaît et traite
les ", les ', et les échappements comme il faut. J'ai aussi des
classes qui découpent une chaîne selon un caractère séparateur
fixe, ou selon une expression rationnelle.

Sans parler, évidemment, des cas où je traite tout le fichier
comme une seule chaîne.

Juste pour dire : quel doit être la solution « universelle »
pour std::string ? Je ne trouve pas celui de la norme
particulièrement utile dans mon travail, mais je vois mal une
autre définition qui serait universellement applicable non plus.
(On pourrait prèsque faire le même argument pour les nombres,
étant donné qu'une langue comme l'arabe utilise d'autres
chiffres, et surtout, mes les chiffres dans l'ordre inverse, les
poids faibles avant les poids forts. Mais la représentation d'un
nombre est quand même un peu plus universel que ce que constitue
une « chaîne ».)

--
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
James Kanze
Stan wrote:
"Fabien LE LEZ" a écrit dans le message de news:



On Thu, 28 Jul 2005 12:48:26 +0200, "Stan" :



Oui, mais mis a part cette écriture que j'utilise déja, je
souhaiterais utiliser l'idiome suivant :




Tu as demandé :



Quel est le moyen le plus simple pour stoker directement les
lignes provenant de cin ?





Je t'ai répondu en te donnant effectivement le moyen le plus
simple.



La question est en relation avec l'exemple que j'ai donné,
sinon je ne l'aurait pas mentionné. Si tu isoles la question
de son contexte...


Je peux reformuler :


Quel est le moyen le plus simple pour stoker directement les
lignes provenant de cin en utilisant "istream_iterator<string>
in( cin )" ?


mais il me semblait que s'était implicite.


Pourquoi pas démander alors quelle est la façon la plus simple
de lire des doubles avec un istream_iterator<int>. Si tu veux
les lignes, ça me semble évident qu'il faut utiliser un
istream_iterator<Line>, et non un istream_iterator<string>.

Le seul problème particulier, c'est que >> sur une chaîne a
priori ne veut rien dire, et que donc, pour diverses raisons (en
partie historique) on lui a donné une définition un peu
arbitraire. (Si on en prenait la définition littéralement, il
lirait jusqu'au premier caractère qui ne peut pas faire partie
d'une chaîne. C-à-d jusqu'à la fin du fichier. Pas très utile
non plus, à mon avis.)

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




1 2