web-dev-qa-db-fra.com

Bonne façon de diviser un std :: string en un vecteur <string>

Dupliquer possible:
Comment diviser une chaîne?

Quelle est la bonne façon de diviser une chaîne en un vecteur de chaînes. Le délimiteur est un espace ou une virgule.

53
devnull

Pour les chaînes séparées par des espaces, vous pouvez alors procéder comme suit:

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

Sortie:

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

Démo en ligne: http://ideone.com/d8E2G


chaîne qui a la virgule et l'espace

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

Sortie:

right
way
wrong
way
correct
way

Démo en ligne: http://ideone.com/aKL0m

73
Nawaz

Un moyen pratique serait la bibliothèque d'algorithmes de chaîne de boost .

#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);
111
UncleBens

Si la chaîne comporte à la fois des espaces et des virgules, vous pouvez utiliser la fonction de classe string 

found_index = myString.find_first_of(delims_str, begin_index) 

en boucle. Vérification de! = Npos et insertion dans un vecteur. Si vous préférez la vieille école, vous pouvez aussi utiliser le C

strtok() 

méthode.

9
Tod
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", "jeton") ==> ["1", "2", "3"]

5
Shiqi Ai

Vous pouvez utiliser getline avec le délimiteur:

string s, tmp; 
stringstream ss(s);
vector<string> words;

while(getline(ss, tmp, ',')){
    words.Push_back(tmp);
    .....
}
1
James

j'ai créé cette fonction personnalisée qui convertira la ligne en vecteur 

#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;
}
0
Ankit Baid