2009-10-02 9 views
20

Sono un token con il seguente, ma non sono sicuro di come includere i delimitatori con esso.Tokenizzare una stringa e includere delimitatori in 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); 

    } 
} 

risposta

16

Il C++ String Toolkit Library (StrTk) ha la seguente soluzione:

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); 

Si dovrebbe portare con TOKEN_LIST hanno le seguenti elementi:

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

Ulteriori esempi si possono trovare Here

2

Non riesco davvero a seguire il tuo codice, potresti pubblicare un programma di lavoro?

Comunque, questa è una semplice tokenizzatore, senza casi limite test:

#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())); 
} 

ingresso Esempio, delimitatore = $$:

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

Gettoni:

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

Nota: I non userei mai un tokenizer che ho scritto senza test! per favore usa boost::tokenizer!

+2

+1 per il Boost.Tokenizer menziona –

+0

ho modificato m y post per includere tutte le funzioni. Vedo cosa hai fatto, ma i delimitatori saranno una stringa e ogni carattere nella stringa sarà un delimitatore. Passato in questo modo ",.! \ N" Quindi una virgola, punto, punto esclamativo e nuova riga verranno inseriti nel vettore, ma non nello spazio. In questo modo posso unire il vettore indietro e utilizzare uno spazio tra gli elementi vettoriali e ricostruire la stringa. – Jeremiah

+0

virgola, punto, punto esclamativo e nuova riga compreso lo spazio saranno i delimitatori. scusa volevo chiarirmi. – Jeremiah

0

Dipende dal fatto che si desidera utilizzare i delimitatori precedenti, i seguenti delimitatori o entrambi e ciò che si desidera eseguire con le stringhe all'inizio e alla fine della stringa che potrebbero non avere delimitatori prima/dopo di esse.

Presumo che tu desideri ogni parola, con i suoi delimitatori precedenti e successivi, ma NON alcuna stringa di delimitatore da sola (ad esempio se c'è un delimitatore che segue l'ultima stringa).

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); 
} 

Per il momento, ho scritto più come un algoritmo STL, prendendo un iteratore per la sua uscita invece di assumere è sempre spingendo su una collezione. Poiché dipende (per il momento) dall'input che è una stringa, non usa gli iteratori per l'input.

+0

Voglio la stringa "Test string, sul web. \ NTest linea uno". essere token come questo. Voglio uno spazio, una virgola, un punto e \ n essere delimitatori. prova stringa , sul il web . \ n Test linea uno . – Jeremiah

+0

Siamo spiacenti, non è stato pubblicato correttamente. Dopo la parola delimitatore, doveva avere ogni cosa su una nuova riga. – Jeremiah

2

se i delimitatori sono caratteri e non stringhe, è possibile utilizzare strtok.

+0

eh? cosa c'è di sbagliato in strtok? –

+0

Grazie .. Avevo quasi dimenticato questa funzione: P – poorva

+1

'strtok' consuma i token delimitatore, credo. – Santa

4

Ora mi sento un po 'sciatto, ma questo è quello che ho finito. Non volevo usare boost dato che si trattava di un incarico scolastico e il mio istruttore voleva che io usassi find_first_of per realizzare questo.

Grazie per l'aiuto di tutti.

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; 
} 
Problemi correlati