Estoy codificando un programa que lee datos directamente de la entrada del usuario y me preguntaba cómo podría (sin bucles) leer todos los datos hasta EOF de la entrada estándar. Estaba considerando usar, cin.get( input, '\0' )
pero '\0'
no es realmente el carácter EOF, que solo se lee hasta EOF o '\0'
, lo que ocurra primero.
¿O es el uso de bucles la única forma de hacerlo? Si es así, ¿cuál es la mejor manera?
Usando bucles:
#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)) { ... }
recurso
fuente
Puede hacerlo sin bucles explícitos utilizando iteradores de flujo. Estoy seguro de que usa algún tipo de bucle internamente.
#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; }
fuente
Después de investigar el uso de la solución de KeithB
std::istream_iterator
, descubrí elstd:istreambuf_iterator
.Pruebe el programa para leer toda la entrada canalizada en una cadena, luego escríbala nuevamente:
#include <iostream> #include <iterator> #include <string> int main() { std::istreambuf_iterator<char> begin(std::cin), end; std::string s(begin, end); std::cout << s; }
fuente
std::istreambuf_iterator
lugar de unstd::istream_iterator
, pero ¿para qué?Probablemente más simple y generalmente eficiente:
#include <iostream> int main() { std::cout << std::cin.rdbuf(); }
Si es necesario, utilice un flujo de otros tipos
std::ostringstream
como búfer en lugar del flujo de salida estándar aquí.fuente
std::ostringstream std_input; std_input << std::cin.rdbuf(); std::string s = std_input.str()
. tienes toda la entrada adentros
(ten cuidadostd::string
si la entrada es demasiado grande)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'.
fuente
Nota al margen triste: 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 un rendimiento de 2 MB / s. Microsoft Visual C ++ 2010 (/ O2) lo convirtió en 40 MB / s para el mismo código.Después de reescribir el IO a C puro,
while (fgets(buf, 100, stdin))
el rendimiento saltó a 90 MB / s en ambos compiladores probados. Eso marca la diferencia para cualquier entrada mayor de 10 MB ...fuente
std::ios::sync_with_stdio(false);
antes de su ciclo while.cin.tie(NULL);
también puede ayudar si intercala la lectura y la escritura.while(std::cin) { // do something }
fuente
// do something
no contiene verificaciones adicionales de los valores de retorno de las operaciones de E / S, y la verificación que contiene no tiene sentido.Espera, ¿te estoy entendiendo correctamente? ¿Está usando cin para la entrada del teclado y desea dejar de leer la entrada cuando el usuario ingresa el carácter EOF? ¿Por qué el usuario escribiría 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 especificar el EOF como delimitador?
// Needed headers: iostream char buffer[256]; cin.get( buffer, '\x1A' );
Si quiere dejar de leer de un archivo en el EOF, simplemente use getline y una vez más especifique 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(); }
fuente
Una opción es utilizar un contenedor, por ejemplo
std::vector<char> data;
y redirigir toda la entrada a esta colección hasta que
EOF
se reciba, es decirstd::copy(std::istream_iterator<char>(std::cin), std::istream_iterator<char>(), std::back_inserter(data));
Sin embargo, es posible que el contenedor usado necesite reasignar memoria con demasiada frecuencia, o terminará con una
std::bad_alloc
excepción cuando su sistema se quede sin memoria. Para resolver estos problemas, puede reservar una cantidad fijaN
de elementos y procesar esta cantidad de elementos de forma aislada, es decirdata.reserve(N); while (/*some condition is met*/) { std::copy_n(std::istream_iterator<char>(std::cin), N, std::back_inserter(data)); /* process data */ data.clear(); }
fuente