2009-10-02 16 views
20

Mam zaszczyt z następujących, ale nie wiem, jak uwzględnić ograniczniki z nim.Tokenize ciąg znaków i ograniczniki w C++

void Tokenize(const string str, vector<string>& tokens, const string& delimiters) 
{ 

    int startpos = 0; 
    int pos = str.find_first_of(delimiters, startpos); 
    string strTemp; 


    while (string::npos != pos || string::npos != startpos) 
    { 

     strTemp = str.substr(startpos, pos - startpos); 
     tokens.push_back(strTemp.substr(0, strTemp.length())); 

     startpos = str.find_first_not_of(delimiters, pos); 
     pos = str.find_first_of(delimiters, startpos); 

    } 
} 

Odpowiedz

16

C++ String Toolkit Library (StrTk) ma następujące rozwiązanie:

std::string str = "abc,123 xyz"; 
std::vector<std::string> token_list; 
strtk::split(";., ", 
      str, 
      strtk::range_to_type_back_inserter(token_list), 
      strtk::include_delimiters); 

Należy wynikać z token_list z następujących elementów:

 
Token0 = "abc," 
Token1 = "123 " 
Token2 = "xyz" 

Więcej przykładów można znaleźć Here

2

Nie podążam za Twoim kodem, czy mógłbyś opublikować działający program?

W każdym razie, to jest proste tokenizer bez przypadków krawędź testowania:

#include <iostream> 
#include <string> 
#include <vector> 

using namespace std; 

void tokenize(vector<string>& tokens, const string& text, const string& del) 
{ 
    string::size_type startpos = 0, 
     currentpos = text.find(del, startpos); 

    do 
    { 
     tokens.push_back(text.substr(startpos, currentpos-startpos+del.size())); 

     startpos = currentpos + del.size(); 
     currentpos = text.find(del, startpos); 
    } while(currentpos != string::npos); 

    tokens.push_back(text.substr(startpos, currentpos-startpos+del.size())); 
} 

Przykład wejściowego ogranicznik = $$:

Hello$$Stack$$Over$$$Flow$$$$! 

Żetony:

Hello$$ 
Stack$$ 
Over$$ 
$Flow$$ 
$$ 
! 

uwaga: nigdy nie użyłbym tokenizera, który napisałem bez testowania! proszę użyć boost::tokenizer!

+2

+1 do Boost.Tokenizer wspomina o –

+0

Edytowałem m y post, aby uwzględnić całą funkcję. Widzę, co zrobiłeś, ale ograniczniki będą ciągiem znaków, a każdy znak w ciągu będzie ogranicznikiem. Tak jak poprzednio ",.! \ N" Tak więc przecinek, kropka, wykrzyknik i nowa linia będą również wepchnięte do wektora, ale nie do spacji. W ten sposób mogę dołączyć do wektora i użyć spacji pomiędzy elementami wektora i odbudować ciąg. – Jeremiah

+0

przecinek, kropka, wykrzyknik i nowa linia, w tym spacja, będą ogranicznikami. Przepraszam, chciałem to wyjaśnić. – Jeremiah

0

To zależy od tego, czy chcesz poprzedzających ograniczników, następujących ograniczników, czy obu, i co chcesz zrobić z ciągami na początku i końcu łańcucha, które mogą nie mieć ograniczników przed/po nich.

Założę się, że chcesz, aby każde słowo, z jego poprzedzających i następujących ograniczników, ale nie żadnych ciągów ograniczników przez siebie (np. Jeśli istnieje ogranicznik po ostatnim ciągu).

template <class iter> 
void tokenize(std::string const &str, std::string const &delims, iter out) { 
    int pos = 0; 
    do { 
     int beg_word = str.find_first_not_of(delims, pos); 
     if (beg_word == std::string::npos) 
      break; 
     int end_word = str.find_first_of(delims, beg_word); 
     int beg_next_word = str.find_first_not_of(delims, end_word); 
     *out++ = std::string(str, pos, beg_next_word-pos); 
     pos = end_word; 
    } while (pos != std::string::npos); 
} 

na chwilę, pisałem go bardziej jak algorytm STL, biorąc iterator na wyjściu zamiast zakładając, że zawsze naciska na zbiór. Ponieważ zależy to od chwili, w której dane wejściowe są ciągami, nie korzysta z iteratorów dla danych wejściowych.

+0

Chcę ciąg "Ciąg testowy w Internecie. \ NTest pierwszej linii." być tak typowymi żetonami. Chcę przestrzeni, commmy, okresu i \ n być ogranicznikiem. test ciąg , na internetowej . \ n Test linia jeden . – Jeremiah

+0

Niestety, nie wysłano poprawnie. Po separatorze słowo miało mieć każdą rzecz na nowej linii. – Jeremiah

2

jeśli separatory są znakami, a nie ciągami, można użyć strtok.

+0

huh? co jest złego w strtok? –

+0

Dzięki .. Prawie zapomniałem o tej funkcji: P – poorva

+1

'strtok' zużywa tokeny separatora, jak sądzę. – Santa

4

Teraz to trochę zaniedbany, ale to właśnie skończyłem. Nie chciałem używać boostu, ponieważ jest to zadanie szkolne, a mój instruktor chciał, abym użył find_first_of, aby to osiągnąć.

Dzięki za pomoc wszystkich.

vector<string> Tokenize(const string& strInput, const string& strDelims) 
{ 
vector<string> vS; 

string strOne = strInput; 
string delimiters = strDelims; 

int startpos = 0; 
int pos = strOne.find_first_of(delimiters, startpos); 

while (string::npos != pos || string::npos != startpos) 
{ 
    if(strOne.substr(startpos, pos - startpos) != "") 
    vS.push_back(strOne.substr(startpos, pos - startpos)); 

    // if delimiter is a new line (\n) then addt new line 
    if(strOne.substr(pos, 1) == "\n") 
    vS.push_back("\\n"); 
    // else if the delimiter is not a space 
    else if (strOne.substr(pos, 1) != " ") 
    vS.push_back(strOne.substr(pos, 1)); 

    if(string::npos == strOne.find_first_not_of(delimiters, pos)) 
    startpos = strOne.find_first_not_of(delimiters, pos); 
    else 
    startpos = pos + 1; 

     pos = strOne.find_first_of(delimiters, startpos); 

} 

return vS; 
}