c++ stream whitespace delimiter cin

cambiando el delimitador para cin(c++)



stream whitespace (3)

He redirigido "cin" para leer desde una secuencia de archivo cin.rdbug(inF.rdbug()) Cuando uso el operador de extracción, se lee hasta que alcanza un carácter de espacio en blanco.

¿Es posible usar otro delimitador? Revisé la API en cplusplus.com, pero no encontré nada.


Es posible cambiar el delimitador entre palabras para cin o cualquier otra std::istream , usando std::ios_base::imbue para agregar una facet ctype personalizada.

Si está leyendo un archivo en el estilo de / etc / passwd, el siguiente programa leerá cada palabra : -limitada por separado.

#include <locale> #include <iostream> struct colon_is_space : std::ctype<char> { colon_is_space() : std::ctype<char>(get_table()) {} static mask const* get_table() { static mask rc[table_size]; rc['':''] = std::ctype_base::space; rc[''/n''] = std::ctype_base::space; return &rc[0]; } }; int main() { using std::string; using std::cin; using std::locale; cin.imbue(locale(cin.getloc(), new colon_is_space)); string word; while(cin >> word) { std::cout << word << "/n"; } }


Esta es una mejora en la respuesta de Robᵩ porque es la correcta (y estoy decepcionado de que no haya sido aceptado).

Lo que necesita hacer es cambiar la matriz que ctype examina para decidir qué es un delimitador.

En el caso más simple, podrías crear el tuyo propio:

const ctype<char>::mask foo[ctype<char>::table_size] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ctype_base::space};

En mi máquina ''/n'' es 10. Establecí ese elemento de la matriz en el valor del delimitador: ctype_base::space . Un tipo de ctype inicializado con foo solo delimitaría en ''/n'' not '' '' o ''/t'' .

Ahora esto es un problema porque la matriz pasada a ctype define algo más que lo que es un delimitador, también define leters, números, símbolos y alguna otra basura necesaria para la transmisión. (La respuesta de Ben Voigt toca esto). Entonces, lo que realmente queremos hacer es modificar una mask , no crear una desde cero.

Eso se puede lograr así:

const auto temp = ctype<char>::classic_table(); vector<ctype<char>::mask> bar(temp, temp + ctype<char>::table_size); bar['' ''] ^= ctype_base::space; bar[''/t''] &= ~(ctype_base::space | ctype_base::cntrl); bar['':''] |= ctype_base::space;

Un tipo de ctype inicializado con bar delimitaría en ''/n'' y '':'' pero no '' '' o ''/t'' .

Vas a configurar cin , o cualquier otro istream , para usar tu tipo de ctype personalizado de esta manera:

cin.imbue(locale(cin.getloc(), new ctype<char>(data(bar))));

También puede cambiar entre ctype y el comportamiento cambiará a mitad de la transmisión:

cin.imbue(locale(cin.getloc(), new ctype<char>(foo)));

Si necesita volver al comportamiento predeterminado, simplemente haga esto:

cin.imbue(locale(cin.getloc(), new ctype<char>));

Ejemplo en vivo


Para cadenas, puede usar las sobrecargas std::getline para leer usando un delimitador diferente.

Para la extracción de números, el delimitador no es realmente un "espacio en blanco" para empezar, sino cualquier carácter inválido en un número.