Comment lire jusqu’à EOF à partir de cin en C ++

Je code 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. cin.get( input, '\0' ) 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 est-ce que l’utilisation de boucles est la seule façon de le faire? Si oui, quelle est la meilleure façon?

La seule façon de lire une quantité variable de données à partir de stdin consiste à utiliser des boucles. J’ai toujours trouvé que la fonction std::getline() fonctionne très bien:

 std::ssortingng 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 lui-même un caractère, vous ne pouvez donc pas appeler un seul appel à getline ().

Vous pouvez le faire sans boucles explicites en utilisant des iterators de stream. Je suis sûr qu’il utilise une sorte de boucle en interne.

 #include  #include  #include  #include  #include  int main() { // don't skip the whitespace while reading std::cin >> std::noskipws; // use stream iterators to copy the stream to a ssortingng std::istream_iterator it(std::cin); std::istream_iterator end; std::ssortingng results(it, end); std::cout < < results; } 

Utiliser des boucles:

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

Ressource

Après avoir recherché la solution de KeithB en utilisant std::istream_iterator , j’ai découvert le std:istreambuf_iterator .

Programme de test pour lire toutes les entrées de canalisation dans une chaîne, puis réécrire:

 #include  #include  #include  int main() { std::istreambuf_iterator begin(std::cin), end; std::ssortingng s(begin, end); std::cout < < s; } 

Probablement le plus simple et généralement efficace:

 #include  int main() { std::cout < < std::cin.rdbuf(); } 

Si nécessaire, utilisez le stream d'autres types comme std::ossortingngstream tant que tampon au lieu du stream de sortie standard ici.

Vous pouvez utiliser la fonction std :: istream :: getline () (ou de préférence la version qui fonctionne sur std :: ssortingng ) pour obtenir une ligne entière. Les deux ont des versions qui vous permettent de spécifier le délimiteur (caractère de fin de ligne). La valeur par défaut pour la version de chaîne est ‘\ n’.

Note sortingste: j’ai décidé d’utiliser C ++ IO pour être compatible avec le code basé sur le boost. De 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 Mo / s. Microsoft Visual C ++ 2010 (/ O2) en fait 40 Mo / s pour le même code.

Après avoir réécrit l’IO en C pure while (fgets(buf, 100, stdin)) le débit a grimpé à 90 Mo / s dans les deux compilateurs testés. Cela fait une différence pour toute entrée supérieure à 10 Mo …

 while(std::cin) { // do something } 

Attends, je te comprends bien? Vous utilisez cin pour l’entrée du clavier et vous souhaitez arrêter de lire l’entrée lorsque l’utilisateur entre le caractère EOF? Pourquoi l’utilisateur taperait-il jamais le caractère EOF? Ou voulez-vous dire que vous voulez arrêter de lire un fichier à l’EOF?

Si vous essayez d’utiliser cin pour lire un caractère EOF, alors pourquoi ne pas simplement spécifier l’EOF comme délimiteur?

 // Needed headers: iostream char buffer[256]; cin.get( buffer, '\x1A' ); 

Si vous voulez arrêter de lire un fichier au niveau du fichier EOF, utilisez simplement getline et spécifiez à nouveau le fichier EOF comme délimiteur.

 // Needed headers: iostream, ssortingng, and fstream ssortingng buffer; ifstream fin; fin.open("test.txt"); if(fin.is_open()) { getline(fin,buffer,'\x1A'); fin.close(); } 

Une option consiste à utiliser un conteneur, par exemple

 std::vector data; 

et redirect toutes les entrées dans cette collection jusqu’à ce que EOF soit reçu, c.-à-d.

 std::copy(std::istream_iterator(std::cin), std::istream_iterator(), std::back_inserter(data)); 

Cependant, le conteneur utilisé peut avoir besoin de réaffecter la mémoire trop souvent, ou vous allez vous retrouver avec une exception std::bad_alloc lorsque votre système manque de mémoire. Pour résoudre ces problèmes, vous pouvez réserver un nombre fixe d’éléments N et traiter ces quantités d’éléments isolément, c.-à-d.

 data.reserve(N); while (/*some condition is met*/) { std::copy_n(std::istream_iterator(std::cin), N, std::back_inserter(data)); /* process data */ data.clear(); }