92 votes

Comment lire jusqu'à EOF à partir de cin en C++.

Je suis en train de coder un programme qui lit les données directement à partir de l'entrée de l'utilisateur et je me demandais comment je pourrais (sans boucles) lire toutes les données jusqu'à EOF à partir de l'entrée standard. J'ai envisagé d'utiliser cin.get( input, '\0' ) mais '\0' n'est pas vraiment le caractère EOF, qui lit simplement jusqu'à EOF ou '\0' selon la première éventualité.

Ou bien l'utilisation de boucles est-elle le seul moyen de le faire ? Si oui, quel est le meilleur moyen ?

88voto

trotterdylan Points 279

Le seul moyen de lire une quantité variable de données à partir de stdin est d'utiliser des boucles. J'ai toujours trouvé que les std::getline() fonctionne très bien :

std::string line;
while (std::getline(std::cin, line))
{
    std::cout << line << std::endl;
}

Par défaut getline() lit jusqu'à une nouvelle ligne. Vous pouvez spécifier un autre caractère de terminaison, mais EOF n'est pas un caractère en soi, donc vous ne pouvez pas simplement faire un appel à getline() .

8 votes

Une chose à laquelle il faut faire attention ici, c'est que lorsque vous lisez des fichiers qui ont été transmis par stdin, cette boucle et la plupart des réponses données ajouteront un saut de ligne supplémentaire à la fin de votre entrée. Tous les fichiers ne se terminent pas par un saut de ligne, mais chaque itération de la boucle ajoute "std::endl" au flux. Ce n'est pas un problème dans la plupart des cas, mais si l'intégrité du fichier est un problème, cela peut vous retomber dessus.

1 votes

Ce ne devrait pas être la réponse la plus votée. Voir la réponse du wiki communautaire ci-dessous. Vous pouvez également consulter cette question : stackoverflow.com/questions/3203452/

65voto

Degvik Points 794

Utilisation des boucles :

#include <iostream>
using namespace std;
...
// numbers
int n;
while (cin >> n)
{
   ...
}
// lines
string line;
while (getline(cin, line))
{
   ...
}
// characters
char c;
while (cin.get(c))
{
   ...
}

ressource

52voto

KeithB Points 9459

Vous pouvez le faire sans boucles explicites en utilisant des itérateurs de flux. Je suis sûr qu'il utilise une sorte de boucle en interne.

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

int main()
{
// don't skip the whitespace while reading
  std::cin >> std::noskipws;

// use stream iterators to copy the stream to a string
  std::istream_iterator<char> it(std::cin);
  std::istream_iterator<char> end;
  std::string results(it, end);

  std::cout << results;
}

3 votes

Joli. Quant à "Je suis sûr qu'il utilise une sorte de boucle en interne" - n'importe quelle solution le ferait.

0 votes

Cela semble supprimer les caractères de nouvelle ligne de l'entrée, même s'ils se trouvent en plein milieu.

3voto

liborm Points 58

Triste parenthèse : j'ai décidé d'utiliser C++ IO pour être cohérent avec le code basé sur boost. Parmi les réponses à cette question, j'ai choisi while (std::getline(std::cin, line)) . En utilisant g++ version 4.5.3 (-O3) dans cygwin (mintty) j'ai obtenu un débit de 2 MB/s. Avec Microsoft Visual C++ 2010 (/O2), le débit est de 40 Mo/s pour le même code.

Après avoir réécrit l'OI en pur C while (fgets(buf, 100, stdin)) le débit est passé à 90 Mo/s dans les deux compilateurs testés. Cela fait une différence pour toute entrée supérieure à 10 Mo...

0 votes

Il n'est pas nécessaire de réécrire votre code en C pur, il suffit d'ajouter une fonction std::ios::sync_with_stdio(false); avant votre boucle "while". cin.tie(NULL); Il peut également être utile d'entrecouper la lecture et l'écriture.

0voto

Bryan Points 1
while(std::cin) {
 // do something
}

10 votes

C'est une réponse terriblement désastreuse, car il est pratiquement garanti qu'elle aboutira à un code erroné.

0 votes

@KerrekSB pourquoi c'est pratiquement garanti d'aboutir à un mauvais code ?

1 votes

@MatúšFerech : Parce que cela suggère fortement que // do something ne contient pas de vérification supplémentaire des valeurs de retour des opérations d'E/S, et la vérification qu'il contient n'a pas de sens.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X