Cómo leer hasta EOF desde cin en C ++

Estoy codificando un progtwig que lee datos directamente de la entrada del usuario y me preguntaba cómo podría (sin bucles) leer todos los datos hasta EOF desde la entrada estándar. Estaba considerando usar cin.get( input, '\0' ) pero '\0' no es realmente el carácter EOF, que solo lee hasta EOF o '\0' , lo que ocurra primero.

¿O está utilizando los bucles la única manera de hacerlo? Si es así, ¿cuál es la mejor manera?

La única manera en que puede leer una cantidad variable de datos desde stdin es usando bucles. Siempre he encontrado que la función std::getline() funciona muy bien:

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

Por defecto getline () lee hasta una nueva línea. Puede especificar un carácter de terminación alternativo, pero EOF no es en sí mismo un carácter, por lo que no puede simplemente hacer una llamada a getline ().

Puede hacerlo sin bucles explícitos mediante el uso de iteradores de flujo. Estoy seguro de que utiliza algún tipo de bucle internamente.

 #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 string std::istream_iterator it(std::cin); std::istream_iterator end; std::string results(it, end); std::cout < < results; } 

Usando loops:

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

recurso

Después de investigar la solución de KeithB usando std::istream_iterator , descubrí el std:istreambuf_iterator .

Probar el progtwig para leer toda la entrada canalizada en una cadena y luego escribirla de nuevo:

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

Probable más simple y generalmente eficiente:

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

Si es necesario, utilice stream de otros tipos como std::ostringstream como buffer en lugar de flujo de salida estándar aquí.

Puede usar la función std :: istream :: getline () (o preferiblemente la versión que funciona en std :: string ) para obtener una línea completa. Ambos tienen versiones que le permiten especificar el delimitador (carácter de fin de línea). El valor predeterminado para la versión de cadena es ‘\ n’.

Triste nota: decidí usar C ++ IO para ser consistente con el código basado en boost. De las respuestas a esta pregunta elegí while (std::getline(std::cin, line)) . Usando g ++ versión 4.5.3 (-O3) en cygwin (mintty) obtuve 2 MB / s de rendimiento. Microsoft Visual C ++ 2010 (/ O2) lo convirtió en 40 MB / s para el mismo código.

Después de volver a escribir el IO en C puro while (fgets(buf, 100, stdin)) el rendimiento saltó a 90 MB / s en ambos comstackdores probados. Eso hace una diferencia para cualquier entrada de más de 10 MB …

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

Espera, ¿te entiendo correctamente? ¿Estás utilizando cin para ingresar el teclado, y quieres dejar de leer la entrada cuando el usuario ingresa el carácter EOF? ¿Por qué el usuario alguna vez ingrese el carácter EOF? ¿O quiso decir que quiere dejar de leer un archivo en el EOF?

Si realmente está tratando de usar cin para leer un carácter EOF, ¿por qué no simplemente especifica el EOF como el delimitador?

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

Si quiere dejar de leer un archivo en el EOF, simplemente use getline y especifique de nuevo el EOF como delimitador.

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

Una opción es usar un contenedor, por ejemplo

 std::vector data; 

y redirigir toda la entrada a esta colección hasta que se reciba EOF , es decir,

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

Sin embargo, es posible que el contenedor utilizado tenga que reasignar la memoria con demasiada frecuencia o terminará con una excepción std::bad_alloc cuando el sistema se quede sin memoria. Para resolver estos problemas, puede reservar una cantidad fija N de elementos y procesar esta cantidad de elementos de forma aislada, es decir,

 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(); }