2016-12-07 2 views
0

Ich möchte einen Text Wort für Wort lesen und alle nicht-alphanumerischen Zeichen auf einfache Weise vermeiden. Nachdem ich aus Text mit Leerzeichen und '\ n' 'entwickelt' habe, muss ich das Problem lösen, falls es auch ',', '.' beispielsweise. Der erste Fall wurde einfach gelöst, indem getline mit dem Begrenzer '' verwendet wurde. Ich fragte mich, ob es eine Möglichkeit gibt, getline mit mehreren Trennzeichen oder sogar mit einer Art von regulären Ausdruck zu verwenden (zum Beispiel '.'|' '|','|'\n').Mehrere Trennzeichen für die getline-Funktion, C++

Soweit ich weiß, funktioniert getline in einer Weise, dass es Zeichen aus dem Eingabestrom liest, bis entweder '\ n' oder delimiter Zeichen erreicht. Meine erste Vermutung war, dass es ziemlich einfach ist, es mit mehreren Trennzeichen zu versehen, aber ich fand heraus, dass es nicht ist.

Edit: nur als eine Klarstellung. Jeder C-Stil (strtok zum Beispiel, der meiner Meinung nach sehr hässlich ist) oder algorithmischer Lösungsweg ist nicht das, wonach ich suche. Es ist ziemlich einfach, einen einfachen Algorithmus zu finden, um dieses Problem zu lösen und zu implementieren. Ich suche eine elegantere Lösung, oder zumindest eine Erklärung dafür, warum wir damit nicht umgehen können mit der getline Funktion, da, wenn ich nicht völlig falsch verstanden habe, in der Lage sein könnte, mehr als ein Trennzeichen zu akzeptieren.

+0

@GabeNones Eh, können wir nicht halten die Menschen für Tagging sowohl C und C++ und dann schließen Sie diese C++ Frage als Betrogene dieser C Frage zu schreien. Wir sollten einen C++ - Betrüger finden. –

+0

@BaummitAugen: Das Finden eines C++ - Dupes wäre in Ordnung - aber das, gegen das du es geschlossen hast, ist kein besonders guter Dupe (zumindest IMO). Eine Antwort befasst sich nicht mit diesem Problem (es handelt sich nur um das Aufteilen einer Zeichenkette und nicht das Lesen aus einem Stream, wie hier gefordert). Das andere funktioniert zufällig, aber nur zufällig. (Dies legt fest, dass '\ n' ein Trennzeichen sein sollte, aber es funktioniert nicht für andere, die das nicht wollen). –

+0

@JerryCoffin Die Frage scheint jedoch die gleiche zu sein. Wenn die andere Frage bessere Antworten benötigt, kann man noch eine hinzufügen, sie ist nicht geschlossen. –

Antwort

1

Es gibt gute Nachrichten und schlechte Nachrichten. Die gute Nachricht ist, dass Sie das tun können.

Die schlechte Nachricht ist, dass es ziemlich umständlich ist, und einige Leute finden es ausgesprochen hässlich und gemein.

, es zu tun, starten Sie durch zwei Tatsachen zu beobachten:

  1. Das normale String-Extraktor verwendet Leerzeichen zu begrenzen „Worte“.
  2. Was als Leerzeichen definiert ist, wird im Gebietsschema des Streams definiert.

diejenigen zusammen Einlochen, wird die Antwort ziemlich offensichtlich (wenn Umwegen): mehrere Trennzeichen zu definieren, definieren wir ein Gebietsschema, das uns, welche Zeichen angeben können, sollte (dh Leerraum) als Trennzeichen behandelt werden:

struct word_reader : std::ctype<char> { 
    word_reader(std::string const &delims) : std::ctype<char>(get_table(delims)) {} 
    static std::ctype_base::mask const* get_table(std::string const &delims) { 
     static std::vector<std::ctype_base::mask> rc(table_size, std::ctype_base::mask()); 

     for (char ch : delims) 
      rc[ch] = std::ctype_base::space; 
     return &rc[0]; 
    } 
}; 

dann brauchen wir den Strom sagen, dass die Gebietsschema zu verwenden (na ja, ein locale mit dieser ctype Facette), die Zeichen geben wir als Trennzeichen verwendet werden soll, und dann Wörter aus dem Strom zu extrahieren:

int main() { 
    std::istringstream in("word1, word2. word3,word4"); 

    // create a ctype facet specifying delimiters, and tell stream to use it: 
    in.imbue(std::locale(std::locale(), new word_reader(" ,.\n"))); 
    std::string word; 

    // read words from the stream. Note we just use `>>`, not `std::getline`: 
    while (in >> word) 
     std::cout << word << "\n"; 
} 

Das Ergebnis ist, was Sie wünschen (ich hoffe): jedes Wort ohne die Interpunktion zu extrahieren, die wir sagten, war "weißer Raum".

word1 
word2 
word3 
word4 
+0

Nun, das ist in der Tat eine feste Lösung, aber wie Sie erwähnt, ziemlich trivial und hat einige "Betrug" Essenz (ersetzt unsere erforderlichen Trennzeichen durch Leerzeichen). Ich fragte mich, ob es eine elegantere Lösung gibt, die genau N Operationen benötigt, da N die Dateilänge ist, genau wie 'getline' funktioniert, wenn unsere Begrenzerwelt auf Leerzeichen und \ n eingeengt wird. – GoldenSpecOps

+0

@GoldenSpecOps: Wir ersetzen nichts. Der Stream sucht nach dem Ende eines Wortes. Es bekommt einen Charakter. Fragt das Gebietsschema: "Ist das Whitespace"? Fügt dem Wort weitere Zeichen hinzu, bis es das Ende der Datei erreicht, oder das Gebietsschema sagt: "Ja, das ist Leerraum". Dann springt es so lange vorwärts, wie das Gebietsschema sagt, dass das nächste Zeichen Leerraum ist. Aufschäumen, abspülen, wiederholen. –

+0

Der einzige große Unterschied zu getline ist, dass, wenn Sie etwas wie 'a \ n \ n \ nz' haben,' getline ''a' lesen wird, leere Zeile, leere Zeile,' z', aber '>>' wird gelesen es ist nur "a", "z". –

Verwandte Themen