2012-04-29 8 views
13

W moim kodzie C++, chcę odczytać z pliku tekstowego (* .txt) i tokenizować każdy wpis. Dokładniej, chcę móc czytać poszczególne słowa z pliku, na przykład "format", "stos", "Jason", "europe", itd..Jak korzystać z domyślnych ograniczników podczas czytania pliku tekstowego ze std :: fstream?

wybrałem używać fstream wykonać to zadanie, a ja nie wiem jak ustawić to ogranicznik do tych, których nie chcą korzystać (przestrzeń, \n, jak również myślnikami a nawet apostrofy jak w „McDonal użytkownika”). Domyśliłem się, że przestrzeń i \n są domyślnymi ogranicznikami, ale myślniki nie są, ale chcę traktować je jako ograniczniki, więc podczas analizowania pliku, otrzymam słowa w "blah blah xxx animal - cat" jako po prostu "bla", "blah", "xxx", "animal", "cat".

Oznacza to, że chcę, aby być w stanie uzyskać dwa ciągi z „przepełnienie stosu”, „jesteś”, itp i nadal być w stanie utrzymać \n i przestrzeń jako ograniczniki w tym samym czasie.

+0

getline (strumień, zmienna, ogranicznik); –

+0

Chcesz odfiltrować "zwierzę - kot", ponieważ zawiera myślniki? To nie brzmi jak tokenizacja dla mnie. – Johnsyweb

+0

Nie próbuję ich odfiltrowywać; Próbuję odczytać zwierzęta i kota jako dwa osobne słowa. – FrozenLand

Odpowiedz

16

traktuje iStream "white space" jako ograniczniki. Używa ustawień narodowych, aby określić, jakie znaki są białą przestrzenią. Z kolei ustawienie regionalne zawiera klauzulę facet, która klasyfikuje typy znaków. Taki facet mógłby wyglądać następująco:

#include <locale> 
#include <iostream> 
#include <algorithm> 
#include <iterator> 
#include <vector> 
#include <sstream> 

class my_ctype : public 
std::ctype<char> 
{ 
    mask my_table[table_size]; 
public: 
    my_ctype(size_t refs = 0) 
     : std::ctype<char>(&my_table[0], false, refs) 
    { 
     std::copy_n(classic_table(), table_size, my_table); 
     my_table['-'] = (mask)space; 
     my_table['\''] = (mask)space; 
    } 
}; 

i trochę program testowy, aby pokazać to działa:

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<std::string>(input), 
     std::istream_iterator<std::string>(), 
     std::ostream_iterator<std::string>(std::cout, "\n")); 

    return 0; 
} 

Wynik:

This 
is 
some 
input 
from 
McDonald 
s 
and 
Burger 
King. 

istream_iterator<string> wykorzystuje >> czytać poszczególne ciągi ze strumienia, więc jeśli użyjesz ich bezpośrednio, powinieneś uzyskać te same wyniki. Części, które musisz uwzględnić, tworzą ustawienia regionalne i używają imbue, aby strumień używał tych ustawień narodowych.

+0

Czy używasz visual studio? Umieściłem kod w visual studio (poprawnie) i nie kompiluje ... – FrozenLand

+0

@ user1348863: Tak, testowałem to z Visual Studio 10. –

+1

Doskonale! N.B: [** std :: copy_n() '**] (http://en.cppreference.com/w/cpp/algorithm/copy_n) to C++ 11ism. Starsze kompilatory będą wymagały 'std :: copy (classic_table(), classic_table() + table_size, my_table);' (lub podobnego). – Johnsyweb

1

Można użyć

istream::getline(char* buffer, steamsize maxchars, char delim) 

chociaż ta obsługuje tylko jeden ogranicznik. Aby jeszcze bardziej podzielić linie na różne ograniczniki, można użyć funkcji

char* strtok(char* inString, const char* delims) 
Kiedy używasz strtok, musisz tylko podać mu adres swojego bufora po raz pierwszy - po tym po prostu przekazujesz wartość zerową i dostaniesz następny token od ostatniego, który ci dał, zwracając wskaźnik zerowy, gdy nie ma jeszcze.

EDIT: Konkretny wdrożenie byłoby coś

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 
    } 
} 
+0

Czy mógłbyś być bardziej konkretny? Powiedzmy, że chcę odczytać przepełnienie stosu jako dwa osobne stosy i przepełnienie, jak to zrobić? (Nadal muszę używać spacji i \ n jako ograniczników w tym samym czasie.) Również, na przykład, pozwólmy na let i s. Dziękuję Ci! – FrozenLand

+0

Edytowana wersja powinna tokenizować na \ n, ', - i spacji. – QuantumRipple

+0

Wygląda dobrze, ale co, jeśli mój plik ma * .txt 1 MB? co mam zastąpić 120? – FrozenLand

Powiązane problemy