2013-03-28 12 views
15

Używam boost :: split do parsowania pliku danych. Plik danych zawiera następujące linie.Jak wykorzystać dzielenie boost, aby podzielić ciąg znaków i zignorować puste wartości?

dane.txt

1:1~15 ASTKGPSVFPLAPSS SVFPLAPSS -12.6 98.3  

białej przestrzeni między elementami są zaczepy. Kod, który muszę podzielić powyższą linię jest następujący.

std::string buf; 
/*Assign the line from the file to buf*/ 
std::vector<std::string> dataLine; 
boost::split(dataLine, buf , boost::is_any_of("\t "), boost::token_compress_on);  //Split data line 
cout << dataLine.size() << endl; 

Na powyższej linii kodu powinienem dostać wydruk z 5, ale dostaję 6. Próbowałem przeczytać w dokumentacji i rozwiązanie to wydaje się, że powinien robić to, co chcę, mogę jasno coś mi brakuje. Dzięki!

Edytuj: Uruchomienie pętli forLop w następujący sposób na linii danych otrzymasz następujące.

cout << "****" << endl; 
for(int i = 0 ; i < dataLine.size() ; i ++) cout << dataLine[i] << endl; 
cout << "****" << endl; 


**** 
1:1~15 
ASTKGPSVFPLAPSS 
SVFPLAPSS 
-12.6 
98.3 

**** 
+0

jakie są wartości przechowywane w DataLine? –

+0

[Otrzymuję 5] (http://liveworkspace.org/code/1KMXAm$1), twoje 'buf' zawiera coś innego. –

+0

Być może nie skopiował on poprawnie tej strony, skopiował go niepoprawnie na kod testowy. Pozwól, że sprawdzę, czy kopiuje się prawidłowo. – PhiloEpisteme

Odpowiedz

15

Choć „sąsiednie separatory są połączone ze sobą”, wydaje się, że końcowe delimeters sprawiają problemu, ponieważ nawet gdy są one traktowane jako jeden, to nadal jest jednym separatorem.

Twój problem nie może zostać rozwiązany samodzielnie przez split(). Ale na szczęście Boost String Algo ma trim() and trim_if(), który usuwa białe znaki lub delimetry od początku i końca łańcucha. Więc po prostu zadzwonić trim() na buf coś takiego:

std::string buf = "1:1~15 ASTKGPSVFPLAPSS SVFPLAPSS -12.6 98.3 "; 
std::vector<std::string> dataLine; 
boost::trim_if(buf, boost::is_any_of("\t ")); // could also use plain boost::trim 
boost::split(dataLine, buf, boost::is_any_of("\t "), boost::token_compress_on); 
std::cout << out.size() << std::endl; 

To pytanie zostało już zapytał: boost::split leaves empty tokens at the beginning and end of string - is this desired behaviour?

+0

Szukałem, ale nie mogłem znaleźć powyższego pytania. Przepraszam za repost. – PhiloEpisteme

7

polecam korzystania C++ String Toolkit Library. Ta biblioteka jest znacznie szybsza niż Boost w mojej opinii. Kiedyś użyłem Boost, aby podzielić (aka tokenize) linię tekstu, ale uznałem, że ta biblioteka jest bardziej zgodna z tym, czego chcę.

Jedną z wielkich rzeczy na temat strtk::parse jest konwersja tokenów na ich ostateczną wartość i sprawdzenie liczby elementów.

można go używać jako tak:

std::vector<std::string> tokens; 

// multiple delimiters should be treated as one 
if(!strtk::parse(dataLine, "\t", tokens)) 
{ 
    std::cout << "failed" << std::endl; 
} 

--- inną wersję

std::string token1; 
std::string token2; 
std::string token3: 
float value1; 
float value2; 

if(!strtk::parse(dataLine, "\t", token1, token2, token3, value1, value2)) 
{ 
    std::cout << "failed" << std::endl; 
    // fails if the number of elements is not what you want 
} 

Online dokumentacji dla biblioteki: String Tokenizer Documentation Link do kodu źródłowego: C++ String Toolkit Library

+0

Mogę rozważyć przejście na STL w przyszłości dla moich potrzeb, ale na razie mam dużo kodu używając boost. – PhiloEpisteme

+14

Mam też niesamowitą ilość boostu kodu. Używałem także tokenizera boost. Przełączam tę konkretną funkcjonalność na strtk ze względu na szybkość. Dodaj do prędkości dodaną zdolność do konwertowania tokenów na liczby w locie i nie było dla mnie kłopotu z przełączaniem. – DannyK

1

Leading i końcowe spacje są celowo pozostawione w spokoju przez boost::split, ponieważ nie wiedzą, czy to jest znaczący lub nie. Rozwiązaniem jest użycie boost::trim przed wywołaniem boost::split.

#include <boost/algorithm/string/trim.hpp> 

.... 

boost::trim(buf); 
+1

Przed dzwonieniem? Zwykle dzielisz, a następnie przycinasz tokeny, prawda? – Nick

+0

@Nick: To zależy. W oryginalnym pytaniu użytkownik dzielił pliki rozdzielane tabulatorami, więc wcześniejsze przycinanie było poprawne. –

Powiązane problemy