Ändern des Trennzeichens für cin (c ++)

Ich habe “cin” umgeleitet, um aus einem Dateistrom cin.rdbug(inF.rdbug()) zu lesen. Wenn ich den Extraktionsoperator verwende, liest es, bis es ein Leerraumzeichen erreicht.

Ist es möglich, ein anderes Trennzeichen zu verwenden? Ich ging durch die API in cplusplus.com, fand aber nichts.

   

Es ist möglich, das Worttrennzeichen für cin oder jedes andere std::istream , indem Sie std::ios_base::imbue , um ein benutzerdefiniertes ctype std::ios_base::imbue hinzuzufügen.

Wenn Sie eine Datei im Stil von / etc / passwd lesen, liest das folgende Programm jedes : -begrenzte Wort separat.

 #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"; } } 

Bei Strings können Sie die std::getline Überladungen verwenden, um sie mit einem anderen Trennzeichen zu lesen.

Für die Zahlenextraktion ist das Trennzeichen nicht wirklich “Leerzeichen”, sondern jedes Zeichen, das in einer Zahl ungültig ist.

Dies ist eine Verbesserung gegenüber Robs Antwort, denn das ist die richtige (und ich bin enttäuscht, dass es nicht akzeptiert wurde.)

Was Sie tun müssen, ist, das Array, das ctype betrachtet, zu ctype um zu entscheiden, was ein Trennzeichen ist.

Im einfachsten Fall könntest du dein eigenes erstellen:

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

Auf meinem Rechner ist '\n' 10. Ich habe dieses Element des Arrays auf den Begrenzerwert gesetzt: ctype_base::space . Ein mit foo initialisierter ctype würde nur '\n' nicht ' ' oder '\t' abgrenzen.

Nun ist das ein Problem, da das in ctype Array mehr als nur das Trennzeichen definiert, es definiert auch Leter, Zahlen, Symbole und etwas anderes, das zum Streamen benötigt wird. ( Ben Voigts Antwort berührt das.) Also, was wir wirklich tun wollen, ist eine mask modifizieren , nicht eine von Grund auf neu zu erstellen.

Das kann so gemacht werden:

 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; 

Ein ctype mit einem bar initialisiert wurde bar würde auf '\n' und ':' aber nicht ' ' oder '\t' abgrenzen.

Sie gehen über das Einrichten von cin oder einem anderen istream , um Ihren benutzerdefinierten ctype wie istream zu verwenden:

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

Sie können auch zwischen ctype s wechseln und das Verhalten wird sich im ctype ändern:

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

Wenn Sie zum Standardverhalten zurückkehren müssen, tun Sie Folgendes:

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

Live-Beispiel