Een tekenreeks in C++ ontleden (splitsen) met behulp van een tekenreeksscheidingsteken (standaard C++)

Ik ben een string aan het ontleden in C++ met het volgende:

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

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

Parseren met een enkel char scheidingsteken gaat prima. Maar wat als ik een string als scheidingsteken wil gebruiken.

Voorbeeld: Ik wil splitsen:

scott>=tiger

met >= als scheidingsteken, zodat ik scott en tiger krijg.

Oplossing

Je kunt de [std::string::find()][1] functie gebruiken om de positie van je string scheidingsteken te vinden, gebruik dan [std::string::substr()][2] om een token te krijgen.

Voorbeeld:

std::string s = "scott>=tiger";
std::string delimiter = ">=";
std::string token = s.substr(0, s.find(delimiter)); // token is "scott"
  • De find(const string& str, size_t pos = 0) functie geeft de positie van het eerste voorkomen van str in de string terug, of [npos][3] als de string niet gevonden is.

  • De substr(size_t pos = 0, size_t n = npos) functie retourneert een substring van het object, beginnend op positie pos en met lengte npos.


Als je meerdere delimiters hebt, kun je nadat je een token hebt geëxtraheerd, deze verwijderen (inclusief delimiter) om verder te gaan met volgende extracties (als je de originele string wilt behouden, gebruik dan s = s.substr(pos + delimiter.length());):

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

Op deze manier kun je gemakkelijk een lus maken om elk token te krijgen.

Volledig voorbeeld


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 
Commentaren (5)

strtok staat je toe om meerdere tekens als scheidingstekens in te voeren. Ik wed dat als je ">=" zou invoeren, je voorbeeldstring correct zou worden gesplitst (ook al worden de > en = geteld als individuele scheidingstekens).

EDIT als je c_str() niet wilt gebruiken om van string naar char* te converteren, kun je substr en find_first_of gebruiken om te tokenize.

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

Ik zou boost::tokenizer gebruiken. Hier's documentatie die uitlegt hoe je een geschikte tokenizer functie maakt: http://www.boost.org/doc/libs/1_52_0/libs/tokenizer/tokenizerfunction.htm

Hier's een die werkt voor uw geval.


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 
Commentaren (2)