alterando o delimitador para cin (c ++)

Eu redirecionei “cin” para ler de um stream de arquivo cin.rdbug(inF.rdbug()) Quando uso o operador de extração, ele lê até atingir um caractere de espaço em branco.

É possível usar outro delimitador? Eu passei pela API no cplusplus.com, mas não encontrei nada.

É possível alterar o delimitador entre palavras para cin ou qualquer outro std::istream , usando std::ios_base::imbue para adicionar uma facet personalizada ctype .

Se você estiver lendo um arquivo no estilo / etc / passwd, o programa a seguir lerá cada um : -delimited word separately.

 #include  #include  struct colon_is_space : std::ctype { colon_is_space() : std::ctype(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"; } } 

Para strings, você pode usar as sobrecargas std::getline para ler usando um delimitador diferente.

Para a extração de números, o delimitador não é realmente “espaço em branco” para começar, mas qualquer caractere é inválido em um número.

Isso é uma melhoria na resposta de Rob , porque essa é a correta (e estou decepcionada por não ter sido aceita).

O que você precisa fazer é alterar a matriz que o ctype examina para decidir o que é um delimitador.

No caso mais simples, você poderia criar o seu próprio:

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

Na minha máquina '\n' é 10. Eu configurei esse elemento da matriz para o valor do delimitador: ctype_base::space . Um ctype inicializado com foo só delimitaria '\n' não ' ' ou '\t' .

Agora, isso é um problema, porque o array passado para o ctype define mais do que apenas um delimitador, ele também define leters, números, símbolos e algum outro lixo necessário para o streaming. (A resposta de Ben Voigt toca nisso.) Então, o que realmente queremos fazer é modificar uma mask , e não criar uma a partir do zero.

Isso pode ser feito assim:

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

Um ctype inicializado com bar delimitaria '\n' e ':' mas não ' ' ou '\t' .

Você vai configurar cin , ou qualquer outro istream , para usar seu tipo personalizado como este:

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

Você também pode alternar entre ctype s e o comportamento será alterado no meio do stream:

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

Se você precisar voltar ao comportamento padrão, faça o seguinte:

 cin.imbue(locale(cin.getloc(), new ctype)); 

Exemplo ao vivo