C++
std :: string
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()
:
- Sur une chaîne non-const, le comportement est indéfini .
- 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.
- Une référence à un caractère avec la valeur
CharT()
(le caractère nul ) est renvoyée. - 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!"
//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!"
//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'
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:
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 plusieursstrings
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 lestd::string
sur lequel il opère, il ne peut donc pas être utilisé sur desconst string
const char*
, desconst char*
s ou des chaînes littérales, pour marquer l'un de ces éléments avecstd::strtok
ou pour fonctionner sur unstd::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);
-
std::istream_iterator
utilise de manière itérative l'opérateur d'extraction du flux. Si l'entréestd::string
est délimitée par des espaces blancs, elle peut être étendue à l'optionstd::strtok
en éliminant ses difficultés, permettant ainsi la tokenisation en ligne, ce qui prend en charge la génération d'unconst 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>());
- Le
std::regex_token_iterator
utilise unstd::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:
// 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()
};
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.
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
.
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.
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>
.
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 retournetrue
, sinon retournefalse
.opérateur
!=
:Si
str1.length() != str2.length()
ou une paire de caractères ne correspond pas, renvoietrue
, sinon elle renvoiefalse
.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]
où 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:
- Comparez les premiers caractères,
'B' == 'B'
- continuez. - Comparez les deuxièmes caractères,
'a' == 'a'
- continuez. - Comparez les troisièmes caractères,
'r' == 'r'
- continuez. - La plage
str2
est maintenant épuisée, alors que la plagestr1
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 typechar
std::wstring
est construit avec des éléments de typewchar_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 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
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());
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 :
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
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.
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();
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;
}
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"