Nel mio codice C ++, voglio leggere da un file di testo (* .txt) e tokenize ogni voce. Più in particolare, voglio essere in grado di leggere singole parole da un file, come “format”, “stack”, “Jason”, “europe”, ecc .
Ho scelto di usare fstream
per eseguire questo compito, e non so come impostare il suo delimitatore su quelli che voglio usare (spazio, \n
, come pure i trattini e persino gli apostrofi come in “Mcdonal’s”). Ho trovato spazio e \n
sono i delimitatori di default, ma i trattini non lo sono, ma voglio trattarli come delimitatori in modo che quando analizzo il file, otterrò le parole in “blah blah xxx animal – cat” come semplicemente “blah” , “blah”, “xxx”, “animal”, “cat”.
Cioè, voglio essere in grado di ottenere due stringhe da “stack-overflow”, “you’re”, ecc., Ed essere ancora in grado di mantenere \n
e lo spazio come delimitatori allo stesso tempo.
Un istante tratta lo “spazio bianco” come delimitatore. Usa un locale per dirgli quali caratteri sono lo spazio bianco. Una locale, a sua volta, include un faccetto di tipo ctype che classifica i tipi di carattere. Un aspetto del genere potrebbe essere qualcosa del genere:
#include #include #include #include #include #include class my_ctype : public std::ctype { mask my_table[table_size]; public: my_ctype(size_t refs = 0) : std::ctype (&my_table[0], false, refs) { std::copy_n(classic_table(), table_size, my_table); my_table['-'] = (mask)space; my_table['\''] = (mask)space; } };
E un piccolo programma di test per dimostrarlo funziona:
int main() { std::istringstream input("This is some input from McDonald's and Burger-King."); std::locale x(std::locale::classic(), new my_ctype); input.imbue(x); std::copy(std::istream_iterator(input), std::istream_iterator (), std::ostream_iterator (std::cout, "\n")); return 0; }
Risultato:
This is some input from McDonald s and Burger King.
istream_iterator
usa >>
per leggere le singole stringhe dallo stream, quindi se le usi direttamente, dovresti ottenere gli stessi risultati. Le parti che devi includere sono la creazione delle impostazioni internazionali e l’utilizzo di imbue
per far sì che lo stream usi quella locale.
Puoi usare
istream::getline(char* buffer, steamsize maxchars, char delim)
anche se questo supporta solo un singolo delimitatore. Per dividere ulteriormente le linee sui diversi delimitatori, è ansible utilizzare
char* strtok(char* inString, const char* delims)
che prende più delimitatori. Quando usi strtok devi solo passarlo l’indirizzo del tuo buffer la prima volta – dopo di ciò basta passare un null e ti darà il prossimo token dall’ultimo che ti ha dato, restituendo un puntatore nullo quando non ci sono Di Più.
EDIT: Un’implementazione specifica sarebbe qualcosa di simile
char buffer[120]; //this size is dependent on what you expect the file to contain while (!myIstream.eofbit) //I may have forgotten the exact syntax of the end bit { myIstream.getline(buffer, 120); //using default delimiter of \n char* tokBuffer; tokBuffer = strtok(buffer, "'- "); while (tokBuffer != null) { cout << "token is: " << tokBuffer << "\n"; tokBuffer = strtok(null, "'- "); //I don't need to pass in the buffer again because it remembers the first time I called it } }