2 votes

Diviser une chaîne de caractères par les N premières occurrences d'un délimiteur en utilisant boost::split

Je sais que c'est peut-être une question stupide, mais je n'ai pas encore trouvé de réponse. Supposons que j'ai la chaîne suivante :

std::string str("1,2,3,4,5,6,7,8,9,10");

Je voudrais le diviser en utilisant la virgule comme délimiteur, mais seulement aux N premières occurrences. Par exemple, pour N = 2, je devrais obtenir comme résultat :

{ "1", "2", "3,4,5,6,7,8,9,10" }.

Est-il possible de le faire avec boost::split ? Je l'ai toujours utilisé sous la forme suivante :

std::vector<std::string> values;
boost::split(values, str, boost::is_any_of(","), boost::token_compress_on);

qui divise la chaîne de caractères sur chaque occurrence du délimiteur.

Si ce n'est pas possible, quelqu'un peut-il me suggérer un moyen efficace de le faire ? Je voudrais éviter d'avoir à utiliser des regex, c'est-à-dire que je voudrais écrire une fonction du type :

std::vector<std::string> tokenize(const std::string& to_split, const std::string& delimiter, int occurrences)

Merci d'avance pour votre aide.

2voto

Vous pouvez utiliser :

find_nth(str, ",", 1);

de <boost/algorithm/string/find.hpp> pour trouver la 2ème (ou la nème) occurrence du caractère qui nous intéresse.

Ensuite, utilisez le traditionnel substr() sur cette possition.

Ensuite, il faut tokeniser la première partie de la chaîne boost::split. Et ajoute la dernière partie au vecteur.

0voto

Jodocus Points 5413

Vous pouvez utiliser stringstream et une locale modifiée :

#include <iostream>
#include <string>
#include <vector>
#include <sstream>

struct csv_whitespace : std::ctype<char> {
    static const mask* make_table() {
        static std::vector<mask> v(classic_table(), 
                                   classic_table() + table_size);
        v[','] |= space;
        v[' '] &= ~space;
        return &v[0];
    }

    csv_whitespace(std::size_t refs = 0) 
       : std::ctype<char>{ make_table(), false, refs } { }
};

int main() {
    std::string str("1,2,3,4,5,6,7,8,9,10");
    std::stringstream ss(str);
    auto loc = ss.getloc();
    ss.imbue(std::locale(loc, new csv_whitespace));
    std::size_t N = 3;
    while(N--) {
        std::string a;
        ss >> a;
        std::cout << a << '\n';
    }
    ss.ignore();
    ss.imbue(loc);
    std::string rest;
    ss >> rest;
    std::cout << "Rest: " << rest << "\n";
}

Démonstration en direct

L'astuce consiste ici à traiter les virgules comme des espaces, ce qui peut être fait dans la commande ctype<> facette.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X