Implémentation de fonctions de découpage de chaînes de caractères en C++

La bibliothèque standard du C++ ne fournit pas de fonction native équivalente au split de Java ou Python pour fractionner une chaîne de caractères (std::string). Cette opération est pourtant incontournable, en particulier lors du traitement des flux d'entrée ou de l'analyse syntaxique. Voici trois approches techniques pour pallier cette absence, allant des méthodes orientées objet aux fonctions héritées du C.

  1. Séparateur unique avec std::string::find

Pour diviser une chaîne en utilisant un délimiteur spécifique (qui peut être un caractère unique ou une sous-chaîne), l'utilisation combinée de find et substr offre une solution performante. Cette implémentation retourne directement un vecteur de chaînes pour faciliter l'intégration dans des pipelines de traitement.

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

std::vector<std::string> tokenize(const std::string& text, const std::string& delimiter) {
    std::vector<std::string> tokens;
    std::string::size_type start = 0;
    std::string::size_type end = text.find(delimiter);

    while (end != std::string::npos) {
        tokens.push_back(text.substr(start, end - start));
        start = end + delimiter.length();
        end = text.find(delimiter, start);
    }
    
    if (start < text.length()) {
        tokens.push_back(text.substr(start));
    }
    return tokens;
}

int main() {
    std::string data = "moduleA-moduleB-moduleC";
    std::vector<std::string> parts = tokenize(data, "-");

    for (const auto& part : parts) {
        std::cout << part << "\n";
    }
    return 0;
}
  1. Gestion de séparateurs multiples

Lorsque le fractionnement doit s'opérer sur n'importe quel caractère appartenant à un ensemble défini (par exemple, une virgule, un point ou un astérisque), l'implémentation manuelle avec des boucles imbriquées est sous-optimale. L'utilisation des algorithmes find_first_of et find_first_not_of permet de parcourir la chaîne de manière beaucoup plus efficace, en ignorant automatiquement les délimiteurs consécutifs.

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

std::vector<std::string> splitMultipleDelimiters(const std::string& input, const std::string& delimiters) {
    std::vector<std::string> result;
    std::string::size_type current_pos = 0;
    std::string::size_type next_pos = 0;

    while ((current_pos = input.find_first_not_of(delimiters, next_pos)) != std::string::npos) {
        next_pos = input.find_first_of(delimiters, current_pos);
        if (next_pos == std::string::npos) {
            result.push_back(input.substr(current_pos));
            break;
        }
        result.push_back(input.substr(current_pos, next_pos - current_pos));
    }
    return result;
}

int main() {
    std::string text = "node1,node2*node3.node4";
    std::vector<std::string> nodes = splitMultipleDelimiters(text, ",*.");

    for (const auto& node : nodes) {
        std::cout << "[" << node << "] ";
    }
    std::cout << std::endl;
    return 0;
}
  1. Utilisation de strtok pour les chaînes de style C

Pour manipuler directement des tableaux de caractères mutables, la bibliothèque standard C propose la fonctino strtok. Il est crucial de noter que cette fonction altère la chaîne originale en remplaçant les délimiteurs par des caractères nuls terminaux. Elle nécessite donc un tableau modifiable et ne peut être appliquée à des littéraux de chaîne constants.

#include <iostream>
#include <cstring>
#include <vector>

std::vector<std::string> splitCString(char* text, const char* delimiters) {
    std::vector<std::string> tokens;
    char* token = std::strtok(text, delimiters);
    
    while (token != nullptr) {
        tokens.push_back(std::string(token));
        token = std::strtok(nullptr, delimiters);
    }
    return tokens;
}

int main() {
    char buffer[] = "alpha|beta|gamma";
    const char* seps = "|";
    
    std::vector<std::string> values = splitCString(buffer, seps);
    
    for (const auto& val : values) {
        std::cout << val << " ";
    }
    std::cout << std::endl;
    return 0;
}

Étiquettes: C++ std::string Parsing algorithms C-library

Publié le 13 juin à 22h47