Recherche…


Introduction

Les chaînes sont des objets qui représentent des séquences de caractères. La norme string de classe offre une alternative simple, sûr et polyvalent à l' aide de tableaux explicites de char s lorsqu'ils traitent avec du texte et d' autres séquences de caractères. La classe de string C ++ fait partie de l'espace de noms std et a été standardisée en 1998.

Syntaxe

  • // Déclaration de chaîne vide

    std :: string s;

  • // Construire à partir de const char * (c-string)

    std :: string s ("Bonjour");

    std :: string s = "Bonjour";

  • // Construire en utilisant un constructeur de copie

    std :: string s1 ("Bonjour");

    std :: string s2 (s1);

  • // Construire à partir d'une sous-chaîne

    std :: string s1 ("Bonjour");

    std :: string s2 (s1, 0, 4); // Copie 4 caractères de la position 0 de s1 dans s2

  • // Construire à partir d'un tampon de caractères

    std :: string s1 ("Hello World");
    std :: string s2 (s1, 5); // Copie les 5 premiers caractères de s1 dans s2

  • // Construire en utilisant le constructeur de remplissage (char uniquement)

    std :: string s (5, 'a'); // s contient aaaaa

  • // Construit à l'aide du constructeur et de l'itérateur d'intervalle

    std :: string s1 ("Hello World");

    std :: string s2 (s1.begin (), s1.begin () + 5); // Copie les 5 premiers caractères de s1 dans s2

Remarques

Avant d'utiliser std::string , vous devez inclure la string tête, car elle inclut des fonctions / opérateurs / surcharges que les autres en-têtes (par exemple iostream ) n'incluent pas.


L'utilisation de const char * constructeur avec un nullptr conduit à un comportement indéfini.

std::string oops(nullptr);
std::cout << oops << "\n";

La méthode at lève une exception std::out_of_range si index >= size() .

Le comportement de l' operator[] est un peu plus compliqué, dans tous les cas il a un comportement indéfini si index > size() , mais quand index == size() :

C ++ 11
  1. Sur une chaîne non-const, le comportement est indéfini .
  2. Sur une chaîne de caractères const, une référence à un caractère avec la valeur CharT() (le caractère nul ) est renvoyée.
C ++ 11
  1. Une référence à un caractère avec la valeur CharT() (le caractère nul ) est renvoyée.
  2. La modification de cette référence est un comportement indéfini .

Depuis C ++ 14, au lieu d'utiliser "foo" , il est recommandé d'utiliser "foo"s , car s est un suffixe littéral défini par l'utilisateur , qui convertit le caractère const char* "foo" en std::string "foo" .

Remarque: vous devez utiliser l'espace de noms std::string_literals ou std::literals std::string_literals pour obtenir le littéral s .

Scission

Utilisez std::string::substr pour diviser une chaîne. Il existe deux variantes de cette fonction membre.

Le premier prend une position de départ à partir de laquelle la sous-chaîne renvoyée doit commencer. La position de départ doit être valide dans la plage (0, str.length()] :

std::string str = "Hello foo, bar and world!";
std::string newstr = str.substr(11); // "bar and world!"

La seconde prend une position de départ et une longueur totale de la nouvelle sous-chaîne. Quelle que soit la longueur , la sous-chaîne ne dépassera jamais la fin de la chaîne source:

std::string str = "Hello foo, bar and world!";
std::string newstr = str.substr(15, 3); // "and"

Notez que vous pouvez aussi appeler substr sans argument, dans ce cas une copie exacte de la chaîne est retournée

std::string str = "Hello foo, bar and world!";
std::string newstr = str.substr(); // "Hello foo, bar and world!"

Remplacement de cordes

Remplacer par la position

Pour remplacer une partie de std::string vous pouvez utiliser la méthode replace from std::string .

replace a beaucoup de surcharges utiles:

//Define string
std::string str = "Hello foo, bar and world!";
std::string alternate = "Hello foobar";

//1)
str.replace(6, 3, "bar"); //"Hello bar, bar and world!"

//2)
str.replace(str.begin() + 6, str.end(), "nobody!"); //"Hello nobody!"

//3)
str.replace(19, 5, alternate, 6, 6); //"Hello foo, bar and foobar!"
C ++ 14
//4)
str.replace(19, 5, alternate, 6); //"Hello foo, bar and foobar!"
//5)
str.replace(str.begin(), str.begin() + 5, str.begin() + 6, str.begin() + 9);
//"foo foo, bar and world!"

//6)
str.replace(0, 5, 3, 'z'); //"zzz foo, bar and world!"

//7)
str.replace(str.begin() + 6, str.begin() + 9, 3, 'x'); //"Hello xxx, bar and world!"
C ++ 11
//8)
str.replace(str.begin(), str.begin() + 5, { 'x', 'y', 'z' }); //"xyz foo, bar and world!"

Remplacer les occurrences d'une chaîne par une autre chaîne

Ne remplacez que la première occurrence de replace with with in str :

std::string replaceString(std::string str,
                          const std::string& replace,
                          const std::string& with){
    std::size_t pos = str.find(replace);
    if (pos != std::string::npos)
        str.replace(pos, replace.length(), with);
    return str;
}

Remplace toutes les occurrences de replace par with in dans str :

std::string replaceStringAll(std::string str,
                             const std::string& replace,
                             const std::string& with) {
    if(!replace.empty()) {
        std::size_t pos = 0;
        while ((pos = str.find(replace, pos)) != std::string::npos) {
            str.replace(pos, replace.length(), with);
            pos += with.length();
        }
    }
    return str;
}

Enchaînement

Vous pouvez concaténer std::string s en utilisant les opérateurs + et += surchargés. En utilisant l'opérateur + :

std::string hello = "Hello";
std::string world = "world";
std::string helloworld = hello + world; // "Helloworld"

En utilisant l'opérateur += :

std::string hello = "Hello";
std::string world = "world";
hello += world; // "Helloworld"

Vous pouvez également ajouter des chaînes C, y compris des chaînes de caractères:

std::string hello = "Hello";
std::string world = "world";
const char *comma = ", ";
std::string newhelloworld = hello + comma + world + "!"; // "Hello, world!"

Vous pouvez également utiliser push_back() pour repousser personne char s:

std::string s = "a, b, ";
s.push_back('c'); // "a, b, c"

Il y a aussi append() , qui ressemble à += :

std::string app = "test and ";
app.append("test"); // "test and test"

Accéder à un personnage

Il existe plusieurs manières d'extraire des caractères d'une std::string et chacun est subtilement différent.

std::string str("Hello world!");

opérateur [] (n)

Renvoie une référence au caractère à l'index n.

std::string::operator[] n'est pas contrôlé par des limites et ne lance pas d'exception. L’appelant est responsable de l’affirmation que l’index se situe dans la plage de la chaîne:

char c = str[6]; // 'w'

en (n)

Renvoie une référence au caractère à l'index n.

std::string::at est vérifié et lancera std::out_of_range si l'index n'est pas dans la plage de la chaîne:

char c = str.at(7); // 'o'
C ++ 11

Remarque: Ces deux exemples entraîneront un comportement indéfini si la chaîne est vide.


de face()

Renvoie une référence au premier caractère:

char c = str.front(); // 'H'

arrière()

Renvoie une référence au dernier caractère:

char c = str.back(); // '!'

Tokenize

Inscrit du moins cher au plus cher à l'exécution:

  1. str::strtok est la méthode de tokenisation standard la moins chère, elle permet également de modifier le délimiteur entre les jetons, mais cela entraîne 3 difficultés avec le C ++ moderne:

    • std::strtok ne peut pas être utilisé sur plusieurs strings en même temps (bien que certaines implémentations s'étendent pour supporter ceci, telles que: strtok_s )
    • Pour la même raison, std::strtok ne peut pas être utilisé sur plusieurs threads simultanément (cela peut cependant être défini par l'implémentation, par exemple: l'implémentation de Visual Studio est thread-safe )
    • L'appel de std::strtok modifie le std::string sur lequel il opère, il ne peut donc pas être utilisé sur des const string const char* , des const char* s ou des chaînes littérales, pour marquer l'un de ces éléments avec std::strtok ou pour fonctionner sur un std::string dont le contenu doit être préservé, l'entrée doit être copiée, puis la copie peut être utilisée

    Généralement, le coût de ces options est caché dans le coût d'allocation des jetons, mais si l'algorithme le moins cher est requis et que les difficultés de std::strtok ne sont pas surmontables, envisagez une solution manuelle .

// String to tokenize
std::string str{ "The quick brown fox" };
// Vector to store tokens
vector<std::string> tokens;

for (auto i = strtok(&str[0], " "); i != NULL; i = strtok(NULL, " "))
    tokens.push_back(i);

Exemple Live

  1. std::istream_iterator utilise de manière itérative l'opérateur d'extraction du flux. Si l'entrée std::string est délimitée par des espaces blancs, elle peut être étendue à l'option std::strtok en éliminant ses difficultés, permettant ainsi la tokenisation en ligne, ce qui prend en charge la génération d'un const vector<string> et en ajoutant plusieurs délimiter le caractère d'espace blanc:
// String to tokenize
const std::string str("The  quick \tbrown \nfox");
std::istringstream is(str);
// Vector to store tokens
const std::vector<std::string> tokens = std::vector<std::string>(
                                        std::istream_iterator<std::string>(is),
                                        std::istream_iterator<std::string>());

Exemple Live

  1. Le std::regex_token_iterator utilise un std::regex pour marquer de manière itérative. Il fournit une définition de délimiteur plus souple. Par exemple, les virgules non délimitées et les espaces blancs:
C ++ 11
// String to tokenize
const std::string str{ "The ,qu\\,ick ,\tbrown, fox" };
const std::regex re{ "\\s*((?:[^\\\\,]|\\\\.)*?)\\s*(?:,|$)" };
// Vector to store tokens
const std::vector<std::string> tokens{ 
    std::sregex_token_iterator(str.begin(), str.end(), re, 1), 
    std::sregex_token_iterator() 
};

Exemple Live

Voir l' exemple de regex_token_iterator pour plus de détails.

Conversion en (const) char *

Afin d'obtenir const char* l' accès aux données d'un std::string , vous pouvez utiliser de la chaîne c_str() la fonction de membre. Gardez à l'esprit que le pointeur n'est valide que tant que l'objet std::string est dans la portée et reste inchangé, ce qui signifie que seules des méthodes const peuvent être appelées sur l'objet.

C ++ 17

La fonction membre data() peut être utilisée pour obtenir un caractère modifiable char* , qui peut être utilisé pour manipuler les données de l'objet std::string .

C ++ 11

Un caractère modifiable char* peut également être obtenu en prenant l'adresse du premier caractère: &s[0] . Dans C ++ 11, il est garanti de générer une chaîne bien formée, terminée par un caractère nul. Notez que &s[0] est bien formé même si s est vide, alors que &s.front() est indéfini si s est vide.

C ++ 11
std::string str("This is a string.");
const char* cstr = str.c_str(); // cstr points to: "This is a string.\0"
const char* data = str.data();  // data points to: "This is a string.\0"
std::string str("This is a string.");

// Copy the contents of str to untie lifetime from the std::string object
std::unique_ptr<char []> cstr = std::make_unique<char[]>(str.size() + 1);

// Alternative to the line above (no exception safety):
// char* cstr_unsafe = new char[str.size() + 1];

std::copy(str.data(), str.data() + str.size(), cstr);
cstr[str.size()] = '\0'; // A null-terminator needs to be added

// delete[] cstr_unsafe;
std::cout << cstr.get();

Recherche de caractère (s) dans une chaîne

Pour trouver un caractère ou une autre chaîne, vous pouvez utiliser std::string::find . Il renvoie la position du premier caractère du premier match. Si aucune correspondance n'a été trouvée, la fonction renvoie std::string::npos

std::string str = "Curiosity killed the cat";
auto it = str.find("cat");

if (it != std::string::npos)
    std::cout << "Found at position: " << it << '\n';
else
    std::cout << "Not found!\n";

Trouvé à la position: 21


Les possibilités de recherche sont élargies par les fonctions suivantes:

find_first_of     // Find first occurrence of characters 
find_first_not_of // Find first absence of characters 
find_last_of      // Find last occurrence of characters 
find_last_not_of  // Find last absence of characters 

Ces fonctions peuvent vous permettre de rechercher des caractères à la fin de la chaîne et de trouver la casse négative (c.-à-d. Des caractères qui ne sont pas dans la chaîne). Voici un exemple:

std::string str = "dog dog cat cat";
std::cout << "Found at position: " << str.find_last_of("gzx") << '\n';

Trouvé à la position: 6

Remarque: Sachez que les fonctions ci-dessus ne recherchent pas des sous-chaînes, mais plutôt des caractères contenus dans la chaîne de recherche. Dans ce cas, la dernière occurrence de 'g' été trouvée à la position 6 (les autres caractères n'ont pas été trouvés).

Découpe des caractères au début / à la fin

Cet exemple requiert les en-têtes <algorithm> , <locale> et <utility> .

C ++ 11

Pour découper une séquence ou une chaîne, vous devez supprimer tous les éléments (ou caractères) de début et de fin correspondant à un prédicat donné. Nous découpons d'abord les éléments de fin, car cela n'implique aucun déplacement d'éléments, puis nous découpons les éléments principaux. Notez que les généralisations ci-dessous fonctionnent pour tous les types de std::basic_string (par exemple std::string et std::wstring ), et accidentellement également pour les conteneurs de séquence (par exemple std::vector et std::list ).

template <typename Sequence, // any basic_string, vector, list etc.
          typename Pred>     // a predicate on the element (character) type
Sequence& trim(Sequence& seq, Pred pred) {
    return trim_start(trim_end(seq, pred), pred);
}

Découper les éléments de fin implique de trouver le dernier élément ne correspondant pas au prédicat et d’effacer à partir de là:

template <typename Sequence, typename Pred>
Sequence& trim_end(Sequence& seq, Pred pred) {
    auto last = std::find_if_not(seq.rbegin(),
                                 seq.rend(),
                                 pred);
    seq.erase(last.base(), seq.end());
    return seq;
}

Découper les éléments principaux implique de trouver le premier élément ne correspondant pas au prédicat et d’y effacer:

template <typename Sequence, typename Pred>
Sequence& trim_start(Sequence& seq, Pred pred) {
    auto first = std::find_if_not(seq.begin(),
                                  seq.end(),
                                  pred);
    seq.erase(seq.begin(), first);
    return seq;
}

Pour spécialiser ce qui précède pour couper les espaces dans un std::string nous pouvons utiliser la fonction std::isspace() comme prédicat:

std::string& trim(std::string& str, const std::locale& loc = std::locale()) {
    return trim(str, [&loc](const char c){ return std::isspace(c, loc); });
}

std::string& trim_start(std::string& str, const std::locale& loc = std::locale()) {
    return trim_start(str, [&loc](const char c){ return std::isspace(c, loc); });
}

std::string& trim_end(std::string& str, const std::locale& loc = std::locale()) {
    return trim_end(str, [&loc](const char c){ return std::isspace(c, loc); });
}

De même, nous pouvons utiliser la fonction std::iswspace() pour std::wstring etc.

Si vous souhaitez créer une nouvelle séquence qui est une copie rognée, vous pouvez utiliser une fonction distincte:

template <typename Sequence, typename Pred>
Sequence trim_copy(Sequence seq, Pred pred) { // NOTE: passing seq by value
    trim(seq, pred);
    return seq;
}

Comparaison lexicographique

Deux std::string s peuvent être comparés lexicographiquement en utilisant les opérateurs == != , < , <= , > Et >= :

std::string str1 = "Foo";
std::string str2 = "Bar";

assert(!(str1 < str2));
assert(str > str2);
assert(!(str1 <= str2));
assert(str1 >= str2);
assert(!(str1 == str2));
assert(str1 != str2);

Toutes ces fonctions utilisent la méthode std::string::compare() sous-jacente pour effectuer la comparaison et renvoient les valeurs booléennes de commodité. Le fonctionnement de ces fonctions peut être interprété comme suit, quelle que soit l'implémentation réelle:

  • opérateur == :

    Si str1.length() == str2.length() et que chaque paire de caractères correspond, alors retourne true , sinon retourne false .

  • opérateur != :

    Si str1.length() != str2.length() ou une paire de caractères ne correspond pas, renvoie true , sinon elle renvoie false .

  • opérateur < ou opérateur > :

    Trouve la première paire de caractères différente, les compare, puis retourne le résultat booléen.

  • opérateur <= ou opérateur >= :

    Trouve la première paire de caractères différente, les compare, puis retourne le résultat booléen.

Remarque: Le terme " paire de caractères" désigne les caractères correspondants dans les deux chaînes des mêmes positions. Pour mieux comprendre, si deux exemples de chaînes sont str1 et str2 , et que leurs longueurs sont respectivement n et m , alors les paires de caractères des deux chaînes signifient chaque str1[i] et str2[i]i = 0, 1, 2 str2[i] .., max (n, m) . Si pour tout i où le caractère correspondant n'existe pas, c'est-à-dire lorsque i est supérieur ou égal à n ou m , il serait considéré comme la valeur la plus basse.


Voici un exemple d'utilisation de < :

std::string str1 = "Barr";
std::string str2 = "Bar";

assert(str2 < str1);

Les étapes sont les suivantes:

  1. Comparez les premiers caractères, 'B' == 'B' - continuez.
  2. Comparez les deuxièmes caractères, 'a' == 'a' - continuez.
  3. Comparez les troisièmes caractères, 'r' == 'r' - continuez.
  4. La plage str2 est maintenant épuisée, alors que la plage str1 a toujours des caractères. Ainsi, str2 < str1 .

Conversion en std :: wstring

En C ++, les séquences de caractères sont représentées en spécialisant la classe std::basic_string avec un type de caractère natif. Les deux principales collections définies par la bibliothèque standard sont std::string et std::wstring :

  • std::string est construit avec des éléments de type char

  • std::wstring est construit avec des éléments de type wchar_t

Pour convertir entre les deux types, utilisez wstring_convert :

#include <string>
#include <codecvt>
#include <locale>

std::string input_str = "this is a -string-, which is a sequence based on the -char- type.";
std::wstring input_wstr = L"this is a -wide- string, which is based on the -wchar_t- type.";

// conversion
std::wstring str_turned_to_wstr = std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes(input_str);

std::string wstr_turned_to_str = std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(input_wstr);

Afin d'améliorer la convivialité et / ou la lisibilité, vous pouvez définir des fonctions pour effectuer la conversion:

#include <string>
#include <codecvt>
#include <locale>

using convert_t = std::codecvt_utf8<wchar_t>;
std::wstring_convert<convert_t, wchar_t> strconverter;

std::string to_string(std::wstring wstr)
{
    return strconverter.to_bytes(wstr);
}

std::wstring to_wstring(std::string str)
{
    return strconverter.from_bytes(str);
}

Exemple d'utilisation:

std::wstring a_wide_string = to_wstring("Hello World!");

C'est certainement plus lisible que std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes("Hello World!") .


Veuillez noter que char et wchar_t n'impliquent pas de codage et ne donne aucune indication de taille en octets. Par exemple, wchar_t est généralement implémenté en tant que type de données à 2 octets et contient généralement des données encodées en UTF-16 sous Windows (ou UCS-2 dans les versions antérieures à Windows 2000) et un type de données à 4 octets encodé en UTF-32. Linux Ceci est en contraste avec les nouveaux types char16_t et char32_t , qui ont été introduits en C ++ 11 et qui sont garantis suffisamment grands pour contenir respectivement tout "caractère" UTF16 ou UTF32 (ou plus précisément, point de code ).

Utiliser la classe std :: string_view

C ++ 17

C ++ 17 introduit std::string_view , qui est simplement une plage non propriétaire de const char , implémentable sous la forme d'une paire de pointeurs ou d'un pointeur et d'une longueur. C'est un type de paramètre supérieur pour les fonctions qui nécessitent des données de chaîne non modifiables. Avant C ++ 17, il y avait trois options pour cela:

void foo(std::string const& s);      // pre-C++17, single argument, could incur
                                     // allocation if caller's data was not in a string
                                     // (e.g. string literal or vector<char> )

void foo(const char* s, size_t len); // pre-C++17, two arguments, have to pass them
                                     // both everywhere

void foo(const char* s);             // pre-C++17, single argument, but need to call
                                     // strlen()

template <class StringT>
void foo(StringT const& s);          // pre-C++17, caller can pass arbitrary char data
                                     // provider, but now foo() has to live in a header

Tous ces éléments peuvent être remplacés par:

void foo(std::string_view s);        // post-C++17, single argument, tighter coupling
                                     // zero copies regardless of how caller is storing
                                     // the data

Notez que std::string_view ne peut modifier ses données sous-jacentes .

string_view est utile lorsque vous souhaitez éviter les copies inutiles.

Il offre un sous-ensemble utile des fonctionnalités de std::string , bien que certaines fonctions se comportent différemment:

std::string str = "lllloooonnnngggg sssstttrrriiinnnggg"; //A really long string

//Bad way - 'string::substr' returns a new string (expensive if the string is long)
std::cout << str.substr(15, 10) << '\n';

//Good way - No copies are created!
std::string_view view = str;

// string_view::substr returns a new string_view
std::cout << view.substr(15, 10) << '\n';

En boucle à travers chaque personnage

C ++ 11

std::string supporte les itérateurs, et vous pouvez donc utiliser une boucle basée sur la distance pour parcourir chaque caractère:

std::string str = "Hello World!";
for (auto c : str)
    std::cout << c;

Vous pouvez utiliser une boucle "traditionnelle" for parcourir chaque caractère:

std::string str = "Hello World!";
for (std::size_t i = 0; i < str.length(); ++i)
    std::cout << str[i];

Conversion en entiers / types à virgule flottante

Un std::string contenant un nombre peut être converti en un type entier, ou un type à virgule flottante, en utilisant des fonctions de conversion.

Notez que toutes ces fonctions cessent d'analyser la chaîne d'entrée dès qu'elles rencontrent un caractère non numérique, ainsi "123abc" sera converti en 123 .


La famille de fonctions std::ato* convertit les chaînes de style C (tableaux de caractères) en types entiers ou à virgule flottante:

std::string ten = "10";

double num1 = std::atof(ten.c_str());
int num2 = std::atoi(ten.c_str());
long num3 = std::atol(ten.c_str());
C ++ 11
long long num4 = std::atoll(ten.c_str());

Cependant, l'utilisation de ces fonctions est déconseillée car elles renvoient 0 si elles ne permettent pas d'analyser la chaîne. Ceci est mauvais car 0 peut aussi être un résultat valide, si par exemple la chaîne d'entrée était "0", il est donc impossible de déterminer si la conversion a réellement échoué.

La nouvelle famille de fonctions std::sto* convertit std::string s en types entiers ou à virgule flottante et lance des exceptions si elles ne peuvent pas analyser leurs entrées. Vous devriez utiliser ces fonctions si possible :

C ++ 11
std::string ten = "10";

int num1 = std::stoi(ten);
long num2 = std::stol(ten);
long long num3 = std::stoll(ten);

float num4 = std::stof(ten);
double num5 = std::stod(ten);
long double num6 = std::stold(ten);

De plus, ces fonctions traitent également les chaînes octales et hexadécimales, contrairement à la famille std::ato* . Le deuxième paramètre est un pointeur sur le premier caractère non converti dans la chaîne d'entrée (non illustré ici), et le troisième paramètre est la base à utiliser. 0 est la détection automatique d'octal (commençant par 0 ) et hexadécimal (commençant par 0x ou 0X ), et toute autre valeur est la base à utiliser

std::string ten = "10";
std::string ten_octal = "12";
std::string ten_hex = "0xA";

int num1 = std::stoi(ten, 0, 2); // Returns 2
int num2 = std::stoi(ten_octal, 0, 8); // Returns 10
long num3 = std::stol(ten_hex, 0, 16);  // Returns 10
long num4 = std::stol(ten_hex);  // Returns 0
long num5 = std::stol(ten_hex, 0, 0); // Returns 10 as it detects the leading 0x

Conversion entre les encodages de caractères

La conversion entre encodages est facile avec C ++ 11 et la plupart des compilateurs sont capables de la gérer de manière multi-plateforme via les en- <codecvt> et <locale> .

#include <iostream>
#include <codecvt>
#include <locale>
#include <string>
using namespace std;

int main() {
    // converts between wstring and utf8 string
    wstring_convert<codecvt_utf8_utf16<wchar_t>> wchar_to_utf8;
    // converts between u16string and utf8 string
    wstring_convert<codecvt_utf8_utf16<char16_t>, char16_t> utf16_to_utf8;
    
    wstring wstr = L"foobar";
    string utf8str = wchar_to_utf8.to_bytes(wstr);
    wstring wstr2 = wchar_to_utf8.from_bytes(utf8str);
    
    wcout << wstr << endl;
    cout << utf8str << endl;
    wcout << wstr2 << endl;
    
    u16string u16str = u"foobar";
    string utf8str2 = utf16_to_utf8.to_bytes(u16str);
    u16string u16str2 = utf16_to_utf8.from_bytes(utf8str2);
    
    return 0;
}

Rappelez-vous que Visual Studio 2015 prend en charge ces conversions, mais qu'un bogue dans leur implémentation de bibliothèque nécessite l'utilisation d'un modèle différent pour wstring_convert lorsqu'il s'agit de char16_t :

using utf16_char = unsigned short;
wstring_convert<codecvt_utf8_utf16<utf16_char>, utf16_char> conv_utf8_utf16;

void strings::utf16_to_utf8(const std::u16string& utf16, std::string& utf8)
{
  std::basic_string<utf16_char> tmp;
  tmp.resize(utf16.length());
  std::copy(utf16.begin(), utf16.end(), tmp.begin());
  utf8 = conv_utf8_utf16.to_bytes(tmp);
}
void strings::utf8_to_utf16(const std::string& utf8, std::u16string& utf16)
{ 
  std::basic_string<utf16_char> tmp = conv_utf8_utf16.from_bytes(utf8);
  utf16.clear();
  utf16.resize(tmp.length());
  std::copy(tmp.begin(), tmp.end(), utf16.begin());
}

Vérifier si une chaîne est un préfixe d'un autre

C ++ 14

En C ++ 14, cela se fait facilement par std::mismatch qui renvoie la première paire incompatible entre deux plages:

std::string prefix = "foo";
std::string string = "foobar";

bool isPrefix = std::mismatch(prefix.begin(), prefix.end(),
    string.begin(), string.end()).first == prefix.end();

Notez que la version de mismatch() était antérieure à C ++ 14, mais elle est dangereuse dans le cas où la deuxième chaîne est la plus courte des deux.

C ++ 14

Nous pouvons toujours utiliser la version range-and-demi de std::mismatch() , mais nous devons d'abord vérifier que la première chaîne est au maximum aussi grande que la seconde:

bool isPrefix = prefix.size() <= string.size() &&
    std::mismatch(prefix.begin(), prefix.end(),
        string.begin(), string.end()).first == prefix.end();
C ++ 17

Avec std::string_view , nous pouvons écrire la comparaison directe que nous voulons sans avoir à nous soucier de la surcharge de l'allocation ou de faire des copies:

bool isPrefix(std::string_view prefix, std::string_view full)
{
    return prefix == full.substr(0, prefix.size());
}

Conversion en std :: string

std::ostringstream peut être utilisé pour convertir n'importe quel type pouvant être traité en une chaîne, en insérant l'objet dans un objet std::ostringstream (avec l'opérateur d'insertion de flux << ), puis en convertissant l'intégralité de std::ostringstream en std::string .

Pour int par exemple:

#include <sstream>

int main()
{
    int val = 4;
    std::ostringstream str;
    str << val;
    std::string converted = str.str();
    return 0;
}

Écrire votre propre fonction de conversion, le plus simple:

template<class T>
std::string toString(const T& x)
{
  std::ostringstream ss;
  ss << x;
  return ss.str();
}

fonctionne mais ne convient pas au code de performance critique.

Les classes définies par l'utilisateur peuvent implémenter l'opérateur d'insertion de flux si désiré:

std::ostream operator<<( std::ostream& out, const A& a )
{
    // write a string representation of a to out
    return out; 
}
C ++ 11

Outre les flux, depuis C ++ 11, vous pouvez également utiliser la fonction std::to_string (et std::to_wstring ) qui est surchargée pour tous les types fondamentaux et retourne la représentation sous forme de chaîne de son paramètre.

std::string s = to_string(0x12f3);  // after this the string s contains "4851"


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow