2015-06-12 21 views
5

sto cercando di dividere una stringa e metterlo in un vettorescissione una stringa ma mantenendo gettoni vuote C++

però, voglio anche mantenere un token vuoto quando ci sono delimitatore consecutive:

Ad esempio :

string mystring = "::aa;;bb;cc;;c" 

Mi piacerebbe tokenize questa stringa su:; delimitatori ma tra delimitatori come :: e ;; Vorrei spingere nel mio vettore una stringa vuota;

so my desired output for this string is: 

"" (empty) 
aa 
"" (empty) 
bb 
cc 
"" (empty) 
c 

Anche il mio requisito non è quello di utilizzare la libreria boost.

se qualcuno mi prestasse un'idea.

grazie

codice che tokenize una stringa, ma non include i token vuote

void Tokenize(const string& str,vector<string>& tokens, const string& delim) 
{ 
     // Skip delimiters at beginning. 
    string::size_type lastPos = str.find_first_not_of(delimiters, 0); 
    // Find first "non-delimiter". 
    string::size_type pos  = str.find_first_of(delimiters, lastPos); 

while (string::npos != pos || string::npos != lastPos) 
{ 
    // Found a token, add it to the vector. 
    tokens.push_back(str.substr(lastPos, pos - lastPos)); 
    // Skip delimiters. Note the "not_of" 
    lastPos = str.find_first_not_of(delimiters, pos); 
    // Find next "non-delimiter" 
    pos = str.find_first_of(delimiters, lastPos); 
    } 
} 
+1

avete provato qualcosa? – Amit

+0

Ho provato il codice sopra per tokenizzare la mia stringa e funziona ma esclude solo i token vuoti – XDProgrammer

+0

Perché non aggiungi un 'tokens.push_back (" ");' subito dopo 'tokens.push_back (str.substr (lastPos, pos - lastPos)); '? – Bastien

risposta

4

È possibile rendere il vostro lavoro algoritmo con alcune semplici modifiche. Innanzitutto, non saltare i delimitatori all'inizio, quindi anziché saltare i delimitatori nel mezzo della stringa, basta incrementare la posizione di uno. Inoltre, il tuo controllo npos deve garantire che le posizioni entrambe non siano npos quindi dovrebbe essere && anziché ||.

void Tokenize(const string& str,vector<string>& tokens, const string& delimiters) 
{ 
    // Start at the beginning 
    string::size_type lastPos = 0; 
    // Find position of the first delimiter 
    string::size_type pos = str.find_first_of(delimiters, lastPos); 

    // While we still have string to read 
    while (string::npos != pos && string::npos != lastPos) 
    { 
     // Found a token, add it to the vector 
     tokens.push_back(str.substr(lastPos, pos - lastPos)); 
     // Look at the next token instead of skipping delimiters 
     lastPos = pos+1; 
     // Find the position of the next delimiter 
     pos = str.find_first_of(delimiters, lastPos); 
    } 

    // Push the last token 
    tokens.push_back(str.substr(lastPos, pos - lastPos)); 
} 
+0

* "// Trova successivo" non-delimitatore "* non descrive cosa' pos = str.find_first_of (delimitatori, lastPos); 'fa e non si aggiunge il token dopo l'ultimo delimitatore (o per un' str 'Senza alcun delimitatore.) Generare approccio è suono però. –

+0

Non dovresti aggiungere' tokens.push_back (str.substr (lastPos, pos-lastPos)); 'alla fine aggiungere l'ultima stringa se non vuota? – Bastien

+0

Grazie , fisso .. – TartanLlama

2

Ho una versione usando iteratori:

std::vector<std::string> split_from(const std::string& s 
    , const std::string& d, unsigned r = 20) 
{ 
    std::vector<std::string> v; 
    v.reserve(r); 

    auto pos = s.begin(); 
    auto end = pos; 

    while(end != s.end()) 
    { 
     end = std::find_first_of(pos, s.end(), d.begin(), d.end()); 
     v.emplace_back(pos, end); 
     pos = end + 1; 
    } 

    return v; 
} 

Usando l'interfaccia:

void Tokenize(const std::string& s, std::vector<std::string>& tokens 
    , const std::string& delims) 
{ 
    auto pos = s.begin(); 
    auto end = pos; 

    while(end != s.end()) 
    { 
     end = std::find_first_of(pos, s.end(), delims.begin(), delims.end()); 
     tokens.emplace_back(pos, end); 
     pos = end + 1; 
    } 
} 
+0

molto bello molto più semplificato .. grazie – XDProgrammer