Analizzare (dividere) una stringa in C++ usando il delimitatore di stringa (C++ standard)

Sto analizzando una stringa in C++ usando il seguente:

string parsed,input="text to be parsed";
stringstream input_stringstream(input);

if(getline(input_stringstream,parsed,' '))
{
     // do some processing.
}

Il parsing con un delimitatore a char singolo va bene. Ma cosa succede se voglio usare una stringa come delimitatore.

Esempio: Voglio dividere:

scott>=tiger

con >= come delimitatore in modo da ottenere scott e tiger.

Soluzione

Puoi usare la funzione [std::string::find()][1] per trovare la posizione del tuo delimitatore di stringa, poi usa [std::string::substr()][2] per ottenere un token.

Esempio:

std::string s = "scott>=tiger";
std::string delimiter = ">=";
std::string token = s.substr(0, s.find(delimiter)); // token is "scott"
  • La funzione find(const string& str, size_t pos = 0) restituisce la posizione della prima occorrenza di str nella stringa, o [npos][3] se la stringa non viene trovata.

  • La funzione substr(size_t pos = 0, size_t n = npos) restituisce una sottostringa dell'oggetto, a partire dalla posizione pos e di lunghezza npos.


Se avete più delimitatori, dopo aver estratto un token, potete rimuoverlo (delimitatore incluso) per procedere con le estrazioni successive (se volete conservare la stringa originale, usate semplicemente s = s.substr(pos + delimiter.length());):

s.erase(0, s.find(delimiter) + delimiter.length());

In questo modo si può facilmente fare un loop per ottenere ogni token.

Esempio completo


std::string s = "scott>=tiger>=mushroom";
std::string delimiter = ">=";

size_t pos = 0;
std::string token;
while ((pos = s.find(delimiter)) != std::string::npos) {
    token = s.substr(0, pos);
    std::cout 
Commentari (5)

strtok vi permette di passare più caratteri come delimitatori. Scommetto che se passaste ">=" la vostra stringa di esempio sarebbe divisa correttamente (anche se il > e = sono contati come delimitatori individuali).

EDIT se non vuoi usare c_str() per convertire da stringa a char*, puoi usare substr e find_first_of per codificare.

string token, mystring("scott>=tiger");
while(token != mystring){
  token = mystring.substr(0,mystring.find_first_of(">="));
  mystring = mystring.substr(mystring.find_first_of(">=") + 1);
  printf("%s ",token.c_str());
}
Commentari (4)

Io userei boost::tokenizer. Ecco la documentazione che spiega come fare una funzione tokenizer appropriata: http://www.boost.org/doc/libs/1_52_0/libs/tokenizer/tokenizerfunction.htm

Eccone uno che funziona per il tuo caso.


struct my_tokenizer_func
{
    template
    bool operator()(It& next, It end, std::string & tok)
    {
        if (next == end)
            return false;
        char const * del = ">=";
        auto pos = std::search(next, end, del, del + 2);
        tok.assign(next, pos);
        next = pos;
        if (next != end)
            std::advance(next, 2);
        return true;
    }

    void reset() {}
};

int main()
{
    std::string to_be_parsed = "1) one>=2) two>=3) three>=4) four";
    for (auto i : boost::tokenizer(to_be_parsed))
        std::cout 
Commentari (2)