Analyser (diviser) une chaîne en C ++ en utilisant le délimiteur de chaîne (standard C ++)

Je parsing une chaîne en C ++ en utilisant ce qui suit:

ssortingng parsed,input="text to be parsed"; ssortingngstream input_ssortingngstream(input); if(getline(input_ssortingngstream,parsed,' ')) { // do some processing. } 

L’parsing avec un délimiteur de caractère unique convient. Mais que faire si je veux utiliser une chaîne en tant que délimiteur.

Exemple: je veux diviser:

 scott>=tiger 

avec> = comme délimiteur pour que je puisse obtenir Scott et Tiger.

Vous pouvez utiliser la fonction std::ssortingng::find() pour trouver la position de votre délimiteur de chaîne, puis utiliser std::ssortingng::substr() pour obtenir un jeton.

Exemple:

 std::ssortingng s = "scott>=tiger"; std::ssortingng delimiter = ">="; std::ssortingng token = s.substr(0, s.find(delimiter)); // token is "scott" 
  • La fonction find(const ssortingng& str, size_t pos = 0) renvoie la position de la première occurrence de str dans la chaîne, ou npos si la chaîne est introuvable.

  • La fonction substr(size_t pos = 0, size_t n = npos) renvoie une sous-chaîne de l’object, en commençant à la position pos et de la longueur npos .


Si vous avez plusieurs délimiteurs, après avoir extrait un jeton, vous pouvez le supprimer (délimiteur inclus) pour procéder aux extractions suivantes (si vous souhaitez conserver la chaîne d’origine, utilisez simplement s = s.substr(pos + delimiter.length()); ):

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

De cette façon, vous pouvez facilement faire une boucle pour obtenir chaque jeton.

Exemple complet

 std::ssortingng s = "scott>=tiger>=mushroom"; std::ssortingng delimiter = ">="; size_t pos = 0; std::ssortingng token; while ((pos = s.find(delimiter)) != std::ssortingng::npos) { token = s.substr(0, pos); std::cout << token << std::endl; s.erase(0, pos + delimiter.length()); } std::cout << s << std::endl; 

Sortie:

 scott tiger mushroom 

Cette méthode utilise std::ssortingng::find sans muter la chaîne d’origine en mémorisant le début et la fin du jeton de sous-chaîne précédent.

 #include  #include  int main() { std::ssortingng s = "scott>=tiger"; std::ssortingng delim = ">="; auto start = 0U; auto end = s.find(delim); while (end != std::ssortingng::npos) { std::cout << s.substr(start, end - start) << std::endl; start = end + delim.length(); end = s.find(delim, start); } std::cout << s.substr(start, end); } 

Vous pouvez utiliser la fonction suivante pour diviser la chaîne:

 vector split(const ssortingng& str, const ssortingng& delim) { vector tokens; size_t prev = 0, pos = 0; do { pos = str.find(delim, prev); if (pos == ssortingng::npos) pos = str.length(); ssortingng token = str.substr(prev, pos-prev); if (!token.empty()) tokens.push_back(token); prev = pos + delim.length(); } while (pos < str.length() && prev < str.length()); return tokens; } 

strtok vous permet de transmettre plusieurs caractères en tant que délimiteurs. Je parie que si vous avez passé “> =” votre exemple de chaîne serait divisé correctement (même si les> et = sont comptés comme des délimiteurs individuels).

EDIT si vous ne souhaitez pas utiliser c_str() pour convertir une chaîne en char *, vous pouvez utiliser substr et find_first_of pour tokenize.

 ssortingng token, myssortingng("scott>=tiger"); while(token != myssortingng){ token = myssortingng.substr(0,myssortingng.find_first_of(">=")); myssortingng = myssortingng.substr(myssortingng.find_first_of(">=") + 1); printf("%s ",token.c_str()); } 

Ce code sépare les lignes du texte et ajoute tout le monde dans un vecteur.

 vector split(char *phrase, ssortingng delimiter){ vector list; ssortingng s = ssortingng(phrase); size_t pos = 0; ssortingng token; while ((pos = s.find(delimiter)) != ssortingng::npos) { token = s.substr(0, pos); list.push_back(token); s.erase(0, pos + delimiter.length()); } return list; } 

Appelé par:

 vector listFilesMax = split(buffer, "\n"); 

Je voudrais utiliser boost::tokenizer . Voici la documentation expliquant comment créer une fonction de tokenizer appropriée: http://www.boost.org/doc/libs/1_52_0/libs/tokenizer/tokenizerfunction.htm

En voici un qui fonctionne pour votre cas.

 struct my_tokenizer_func { template bool operator()(It& next, It end, std::ssortingng & 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::ssortingng to_be_parsed = "1) one>=2) two>=3) three>=4) four"; for (auto i : boost::tokenizer(to_be_parsed)) std::cout << i << '\n'; } 

Voici mon sharepoint vue à ce sujet. Il gère les cas d’arête et prend un paramètre facultatif pour supprimer les entrées vides des résultats.

 bool endsWith(const std::ssortingng& s, const std::ssortingng& suffix) { return s.size() >= suffix.size() && s.substr(s.size() - suffix.size()) == suffix; } std::vector split(const std::ssortingng& s, const std::ssortingng& delimiter, const bool& removeEmptyEnsortinges = false) { std::vector tokens; for (size_t start = 0, end; start < s.length(); start = end + delimiter.length()) { size_t position = s.find(delimiter, start); end = position != string::npos ? position : s.length(); std::string token = s.substr(start, end - start); if (!removeEmptyEntries || !token.empty()) { tokens.push_back(token); } } if (!removeEmptyEntries && (s.empty() || endsWith(s, delimiter))) { tokens.push_back(""); } return tokens; } 

Exemples

 split("abc", "-"); // [3]("a","b","c") split("a--c", "-"); // [3]("a","","c") split("-b-", "-"); // [3]("","b","") split("--c--", "-"); // [5]("","","c","","") split("--c--", "-", true); // [1]("c") split("a", "-"); // [1]("a") split("", "-"); // [1]("") split("", "-", true); // [0]() 

Pour le délimiteur de chaîne
Séparer la chaîne en fonction de la chaîne de délimiteur. Tels que la chaîne de division "adsf-+qwret-+nvfkbdsj-+orthdfjgh-+dfjrleih" basée sur la chaîne de délimiteur "-+" , la sortie sera {"adsf", "qwret", "nvfkbdsj", "orthdfjgh", "dfjrleih"}

 #include  #include  #include  using namespace std; // for ssortingng delimiter vector split(ssortingng s, ssortingng delimiter) { size_t pos_start = 0, pos_end, delim_len = delimiter.length(); ssortingng token; vector res; while ((pos_end = s.find(delimiter, pos_start)) != ssortingng::npos) { token = s.substr(pos_start, pos_end - pos_start); pos_start = pos_end + delim_len; res.push_back(token); } res.push_back(s.substr(pos_start)); return res; } int main() { ssortingng str = "adsf-+qwret-+nvfkbdsj-+orthdfjgh-+dfjrleih"; ssortingng delimiter = "-+"; vector v = split(str, delimiter); for (auto i : v) cout << i << endl; return 0; } 

Pour un séparateur de caractère unique

 #include  #include  #include  using namespace std; vector split(const ssortingng &s, char delim) { vector result; ssortingngstream ss(s); ssortingng item; while (getline(ss, item, delim)) { result.push_back(item); } return result; } int main() { ssortingng str = "adsf+qwer+poui+fdgh"; vector v = split(str, '+'); for (auto i : v) cout << i << endl; return 0; } 

Si vous ne souhaitez pas modifier la chaîne (comme dans la réponse de Vincenzo Pii) et que vous souhaitez également afficher le dernier jeton, vous pouvez utiliser cette approche:

 inline std::vector splitSsortingng( const std::ssortingng &s, const std::ssortingng &delimiter ){ std::vector ret; size_t start = 0; size_t end = 0; size_t len = 0; std::ssortingng token; do{ end = s.find(delimiter,start); len = end - start; token = s.substr(start, len); ret.emplace_back( token ); start += len + delimiter.length(); std::cout << token << std::endl; }while ( end != std::string::npos ); return ret; } 
 #include #include using namespace std; int split_count(ssortingng str,char delimit){ return count(str.begin(),str.end(),delimit); } void split(ssortingng str,char delimit,ssortingng res[]){ int a=0,i=0; while(a 

PS: Fonctionne seulement si les longueurs des chaînes après la division sont égales

 std::vector split(const std::ssortingng& s, char c) { std::vector v; unsigned int ii = 0; unsigned int j = s.find(c); while (j < s.length()) { v.push_back(s.substr(i, j - i)); i = ++j; j = s.find(c, j); if (j >= s.length()) { v.push_back(s.substr(i, s,length())); break; } } return v; }