De juiste manier om een std::string te splitsen in een vector<string>

Mogelijk duplicaat:
Hoe splits ik een string?

Wat is de juiste manier om een string te splitsen in een vector van strings. Scheidingsteken is spatie of komma.


Antwoord 1, autoriteit 100%

Voor door spaties gescheiden tekenreeksen kunt u dit doen:

std::string s = "What is the right way to split a string into a vector of strings";
std::stringstream ss(s);
std::istream_iterator<std::string> begin(ss);
std::istream_iterator<std::string> end;
std::vector<std::string> vstrings(begin, end);
std::copy(vstrings.begin(), vstrings.end(), std::ostream_iterator<std::string>(std::cout, "\n"));

Uitvoer:

What
is
the
right
way
to
split
a
string
into
a
vector
of
strings

tekenreeks die zowel een komma als een spatie bevat

struct tokens: std::ctype<char> 
{
    tokens(): std::ctype<char>(get_table()) {}
    static std::ctype_base::mask const* get_table()
    {
        typedef std::ctype<char> cctype;
        static const cctype::mask *const_rc= cctype::classic_table();
        static cctype::mask rc[cctype::table_size];
        std::memcpy(rc, const_rc, cctype::table_size * sizeof(cctype::mask));
        rc[','] = std::ctype_base::space; 
        rc[' '] = std::ctype_base::space; 
        return &rc[0];
    }
};
std::string s = "right way, wrong way, correct way";
std::stringstream ss(s);
ss.imbue(std::locale(std::locale(), new tokens()));
std::istream_iterator<std::string> begin(ss);
std::istream_iterator<std::string> end;
std::vector<std::string> vstrings(begin, end);
std::copy(vstrings.begin(), vstrings.end(), std::ostream_iterator<std::string>(std::cout, "\n"));

Uitvoer:

right
way
wrong
way
correct
way

Antwoord 2, autoriteit 97%

Een handige manier zijn de string-algoritmen van boost bibliotheek.

#include <boost/algorithm/string/classification.hpp> // Include boost::for is_any_of
#include <boost/algorithm/string/split.hpp> // Include for boost::split
// ...
std::vector<std::string> words;
std::string s;
boost::split(words, s, boost::is_any_of(", "), boost::token_compress_on);

Antwoord 3, autoriteit 16%

U kunt getline gebruiken met scheidingsteken:

string s, tmp; 
stringstream ss(s);
vector<string> words;
while(getline(ss, tmp, ',')){
    words.push_back(tmp);
    .....
}

Antwoord 4, autoriteit 15%

vector<string> split(string str, string token){
    vector<string>result;
    while(str.size()){
        int index = str.find(token);
        if(index!=string::npos){
            result.push_back(str.substr(0,index));
            str = str.substr(index+token.size());
            if(str.size()==0)result.push_back(str);
        }else{
            result.push_back(str);
            str = "";
        }
    }
    return result;
}

split(“1,2,3″,”,”) ==> [“1″,”2″,”3”]

split(“1,2,”,”,”) ==> [“1″,”2″,””]

split(“1token2token3″,”token”) ==> [“1″,”2″,”3”]


Antwoord 5, autoriteit 9%

Als de tekenreeks zowel spaties als komma’s heeft, kunt u de tekenreeksklassefunctie gebruiken

found_index = myString.find_first_of(delims_str, begin_index) 

in een lus. Controleren op != npos en invoegen in een vector. Als je de voorkeur geeft aan old school, kun je ook C’s gebruiken

strtok() 

methode.


Antwoord 6, autoriteit 6%

std::vector<std::string> split(std::string text, char delim) {
    std::string line;
    std::vector<std::string> vec;
    std::stringstream ss(text);
    while(std::getline(ss, line, delim)) {
        vec.push_back(line);
    }
    return vec;
}

split("String will be split", ' ')-> {"String", "will", "be", "split"}

split("Hello, how are you?", ',')-> {"Hello", "how are you?"}

EDIT:Hier is iets dat ik heb gemaakt, dit kan scheidingstekens met meerdere tekens gebruiken, hoewel ik niet 100% zeker weet of het altijd werkt:

std::vector<std::string> split(std::string text, std::string delim) {
    std::vector<std::string> vec;
    size_t pos = 0, prevPos = 0;
    while (1) {
        pos = text.find(delim, prevPos);
        if (pos == std::string::npos) {
            vec.push_back(text.substr(prevPos));
            return vec;
        }
        vec.push_back(text.substr(prevPos, pos - prevPos));
        prevPos = pos + delim.length();
    }
}

Antwoord 7, autoriteit 2%

Verbeterde versie van Techie Delight:

#include <string>
#include <vector>
std::vector<std::string> split(const std::string& str, char delim) {
    std::vector<std::string> strings;
    size_t start;
    size_t end = 0;
    while ((start = str.find_first_not_of(delim, end)) != std::string::npos) {
        end = str.find(delim, start);
        strings.push_back(str.substr(start, end - start));
    }
    return strings;
}

Antwoord 8

ik heb deze aangepaste functie gemaakt die de lijn naar vector zal converteren

#include <iostream>
#include <vector>
#include <ctime>
#include <string>
using namespace std;
int main(){
    string line;
    getline(cin, line);
    int len = line.length();
    vector<string> subArray;
    for (int j = 0, k = 0; j < len; j++) {
        if (line[j] == ' ') {
            string ch = line.substr(k, j - k);
            k = j+1;
            subArray.push_back(ch);
        }
        if (j == len - 1) {
            string ch = line.substr(k, j - k+1);
            subArray.push_back(ch);
        }
    }
    return 0;
}

Antwoord 9

Hier is een aangepaste versie van de oplossing van roach die wordt gesplitst op basis van een reeks scheidingstekens van één teken + ondersteunt de optie om dubbele scheidingstekens te comprimeren.

std::vector<std::string> split(std::string text, std::string delim, bool compress) 
{
    std::vector<std::string> vec;
    size_t pos = 0, prevPos = 0;
    while (1) 
    {
        pos = text.find_first_of(delim, prevPos);
        while(compress) 
        {
            if( prevPos == pos )
                prevPos++;
            else
                break;
            pos = text.find_first_of(delim, prevPos);
        }
        if (pos == std::string::npos) {
            if(prevPos != text.size())
                vec.push_back(text.substr(prevPos));
            return vec;
        }
        vec.push_back(text.substr(prevPos, pos - prevPos));
        prevPos = pos + 1;
    }
}

Voorbeeld zonder comprimeren:

std::string s = "  1.2  foo@foo . ";
auto res = split(s, ".@ ", false);
    for(auto i : res)
        std::cout << "string {" << i << "}" << std::endl;

Uitvoer:

string {}
string {}
string {1}
string {2}
string {}
string {foo}
string {foo}
string {}
string {}

Met compress split(s, ".@ ", true);

string {1}
string {2}
string {foo}
string {foo}

Antwoord 10

Ik schrijf deze aangepaste functie, dit zal je helpen. Maar maak discussies over de tijdscomplexiteit.

std::vector<std::string> words;
std::string s;
std::string separator = ",";
while(s.find(separator) != std::string::npos){
   separatorIndex = s.find(separator)
   vtags.push_back(s.substr(0, separatorIndex ));
   words= s.substr(separatorIndex + 1, s.length());
}
words.push_back(s);

Other episodes