C++
std :: string
Zoeken…
Invoering
Tekenreeksen zijn objecten die reeksen tekens vertegenwoordigen. De standaard string
biedt een eenvoudig, veilig en veelzijdig alternatief voor het gebruik van expliciete reeksen char
bij het omgaan met tekst en andere reeksen tekens. De C ++ string
klasse maakt deel uit van de std
naamruimte en werd gestandaardiseerd in 1998.
Syntaxis
// Lege stringverklaring
std :: string s;
// Constructing from const char * (c-string)
std :: string s ("Hallo");
std :: string s = "Hallo";
// Constructie met behulp van copy constructor
std :: string s1 ("Hallo");
std :: string s2 (s1);
// Opbouwen vanuit substring
std :: string s1 ("Hallo");
std :: string s2 (s1, 0, 4); // Kopieer 4 tekens van positie 0 van s1 naar s2
// Opbouwen uit een buffer met tekens
std :: string s1 ("Hello World");
std :: string s2 (s1, 5); // Kopieer de eerste 5 tekens van s1 naar s2// Construct met behulp van fill constructor (alleen char)
std :: string s (5, 'a'); // s bevat aaaaa
// Construct met bereikconstructor en iterator
std :: string s1 ("Hello World");
std :: string s2 (s1.begin (), s1.begin () + 5); // Kopieer de eerste 5 tekens van s1 naar s2
Opmerkingen
Voor het gebruik van std::string
, moet je onder de header string
, omdat het beschikt over functies / exploitanten / overbelasting die andere headers (bijvoorbeeld iostream
) niet inbegrepen.
Het gebruik van const char * constructor met een nullptr leidt tot ongedefinieerd gedrag.
std::string oops(nullptr);
std::cout << oops << "\n";
De methode at
gooit een std::out_of_range
uitzondering wanneer index >= size()
.
Het gedrag van operator[]
is iets gecompliceerder, in alle gevallen heeft het ongedefinieerd gedrag als index > size()
, maar wanneer index == size()
:
- Op een niet-const string is het gedrag niet gedefinieerd ;
- Op een const-tekenreeks wordt een verwijzing naar een teken met de waarde
CharT()
(het null- teken) geretourneerd.
- Een verwijzing naar een teken met de waarde
CharT()
(het null- teken) wordt geretourneerd. - Het wijzigen van deze referentie is ongedefinieerd gedrag .
Omdat C ++ 14, in plaats van "foo"
, wordt aanbevolen om "foo"s
, aangezien s
een door de gebruiker gedefinieerd letterlijk achtervoegsel is , dat het const char*
"foo"
converteert naar std::string
"foo"
.
Opmerking: je moet de naamruimte std::string_literals
of std::literals
gebruiken om de letterlijke s
te krijgen.
Splitsen
Gebruik std::string::substr
om een string te splitsen. Er zijn twee varianten van deze lidfunctie.
De eerste neemt een startpositie van waaruit de geretourneerde substring moet beginnen. De startpositie moet geldig zijn in het bereik (0, str.length()]
:
std::string str = "Hello foo, bar and world!";
std::string newstr = str.substr(11); // "bar and world!"
De tweede neemt een startpositie en een totale lengte van de nieuwe substring in. Ongeacht de lengte , de substring komt nooit voorbij het einde van de bronreeks:
std::string str = "Hello foo, bar and world!";
std::string newstr = str.substr(15, 3); // "and"
Merk op dat je ook substr
kunt aanroepen zonder argumenten, in dit geval wordt een exacte kopie van de string teruggegeven
std::string str = "Hello foo, bar and world!";
std::string newstr = str.substr(); // "Hello foo, bar and world!"
String vervangen
Vervangen door positie
Om een deel van een std::string
te vervangen, kunt u de methode replace
van std::string
.
replace
heeft veel nuttige overbelastingen:
//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!"
Vervang exemplaren van een string door een andere string
Vervang alleen het eerste exemplaar van replace
door 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;
}
Vervang alle gevallen van replace
door with
in 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;
}
Aaneenschakeling
Je kunt std::string
s samenvoegen met de overbelaste operatoren +
en +=
. Met de operator +
:
std::string hello = "Hello";
std::string world = "world";
std::string helloworld = hello + world; // "Helloworld"
Met de operator +=
:
std::string hello = "Hello";
std::string world = "world";
hello += world; // "Helloworld"
U kunt ook C-reeksen toevoegen, inclusief tekenreeksliteralen:
std::string hello = "Hello";
std::string world = "world";
const char *comma = ", ";
std::string newhelloworld = hello + comma + world + "!"; // "Hello, world!"
Je kunt ook push_back()
gebruiken om afzonderlijke char
terug te duwen:
std::string s = "a, b, ";
s.push_back('c'); // "a, b, c"
Er is ook append()
, die ongeveer lijkt op +=
:
std::string app = "test and ";
app.append("test"); // "test and test"
Toegang tot een personage
Er zijn verschillende manieren om tekens uit een std::string
te extraheren en elk is subtiel anders.
std::string str("Hello world!");
operator [] (n)
Retourneert een verwijzing naar het teken bij index n.
std::string::operator[]
is niet grensgebonden en genereert geen uitzondering. De beller is verantwoordelijk voor de bewering dat de index zich binnen het bereik van de tekenreeks bevindt:
char c = str[6]; // 'w'
in (n)
Retourneert een verwijzing naar het teken bij index n.
std::string::at
is bounds aangevinkt, en zal std::out_of_range
gooien als de index niet binnen het bereik van de string ligt:
char c = str.at(7); // 'o'
Opmerking: Beide voorbeelden resulteren in ongedefinieerd gedrag als de tekenreeks leeg is.
voorkant()
Retourneert een verwijzing naar het eerste teken:
char c = str.front(); // 'H'
terug()
Retourneert een verwijzing naar het laatste teken:
char c = str.back(); // '!'
tokenize
Opgenomen van minst duur tot duurst tijdens runtime:
str::strtok
is de goedkoopste standaard verstrekte tokenisatiemethode, hiermee kan het scheidingsteken ook worden gewijzigd tussen tokens, maar het heeft 3 problemen met moderne C ++:-
std::strtok
kan niet tegelijkertijd op meerderestrings
worden gebruikt (hoewel sommige implementaties dit ondersteunen, zoals:strtok_s
) - Om dezelfde reden kan
std::strtok
niet tegelijkertijd op meerdere threads worden gebruikt (dit kan echter door de implementatie zijn gedefinieerd, bijvoorbeeld: de implementatie van Visual Studio is thread-safe ) - Het aanroepen van
std::strtok
wijzigt destd::string
het werkt, dus het kan niet worden gebruikt opconst string
s,const char*
s of letterlijke strings, om een van deze testd::strtok
metstd::strtok
of om te werken op eenstd::string
wiens inhoud moet worden bewaard, de invoer moet worden gekopieerd en vervolgens kan de kopie worden gebruikt
Over het algemeen zullen al deze
std::strtok
verborgen zijn in de toewijzingskosten van de tokens, maar als het goedkoopste algoritme vereist is enstd::strtok
de problemen van strtok zijn niet overweldigend, overweeg dan een handgesponnen oplossing .-
// 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);
- De
std::istream_iterator
gebruikt iteratief de extractieoperator van de stroom. Als de invoerstd::string
is gescheiden door witruimte, kan deze worden uitgebreid naar destd::strtok
optie door de moeilijkheden te elimineren, inlinestd::strtok
mogelijk te maken waardoor het genereren van eenconst vector<string>
wordt ondersteund en ondersteuning voor meerdere witruimte-teken afbakenen:
// 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>());
- De
std::regex_token_iterator
gebruikt eenstd::regex
om iteratief te tokenize. Het zorgt voor een flexibelere afbakeningsdefinitie. Bijvoorbeeld, niet-gescheiden komma's en witruimte:
// 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()
};
Zie het voorbeeld van regex_token_iterator
voor meer informatie.
Conversie naar (const) char *
Om const char*
toegang te krijgen tot de gegevens van een std::string
, kunt u de c_str()
de string gebruiken. Houd er rekening mee dat de aanwijzer alleen geldig is zolang het object std::string
zich binnen het bereik bevindt en ongewijzigd blijft, wat betekent dat alleen const
methoden op het object kunnen worden aangeroepen.
De data()
lidfunctie kan worden gebruikt om een aanpasbaar char*
te verkrijgen, dat kan worden gebruikt om de gegevens van het std::string
object te manipuleren.
Een aanpasbaar char*
kan ook worden verkregen door het adres van het eerste teken te nemen: &s[0]
. Binnen C ++ 11 levert dit gegarandeerd een goedgevormde string met nulstand op. Merk op dat &s[0]
goed is gevormd, zelfs als s
leeg is, terwijl &s.front()
is gedefinieerd als s
leeg is.
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();
Teken (s) zoeken in een string
Om een karakter of een andere string te vinden, kunt u std::string::find
. Het geeft de positie van het eerste karakter van de eerste wedstrijd terug. Als er geen overeenkomsten zijn gevonden, retourneert de functie 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";
Gevonden op positie: 21
De zoekmogelijkheden worden verder uitgebreid met de volgende functies:
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
Met deze functies kunt u zoeken naar tekens aan het einde van de tekenreeks en de negatieve hoofdletter vinden (bijvoorbeeld tekens die niet in de tekenreeks voorkomen). Hier is een voorbeeld:
std::string str = "dog dog cat cat";
std::cout << "Found at position: " << str.find_last_of("gzx") << '\n';
Gevonden op positie: 6
Opmerking: houd er rekening mee dat de bovenstaande functies niet zoeken naar substrings, maar naar tekens in de zoekreeks. In dit geval werd het laatste exemplaar van 'g'
gevonden op positie 6
(de andere tekens werden niet gevonden).
Tekens knippen aan begin / einde
Dit voorbeeld vereist de headers <algorithm>
, <locale>
en <utility>
.
Een reeks of tekenreeks bijsnijden betekent dat alle voorloop- en volgelementen (of tekens) die overeenkomen met een bepaald predicaat worden verwijderd. We knippen eerst de achterste elementen, omdat het geen elementen hoeft te verplaatsen, en vervolgens de voorste elementen. Merk op dat de onderstaande generalisaties werken voor alle soorten std::basic_string
(bijv. std::string
en std::wstring
), en per ongeluk ook voor sequentiecontainers (bijv. std::vector
en 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);
}
Bij het bijsnijden van de volgende elementen wordt gezocht naar het laatste element dat niet overeenkomt met het predicaat en vanaf dat moment wissen:
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;
}
Het bijsnijden van de leidende elementen omvat het vinden van het eerste element dat niet overeenkomt met het predicaat en tot daar wissen:
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;
}
Om het bovenstaande te specialiseren voor het bijsnijden van witruimte in een std::string
, kunnen we de functie std::isspace()
als predicaat:
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); });
}
Op dezelfde manier kunnen we de functie std::iswspace()
voor std::wstring
etc.
Als u een nieuwe reeks wilt maken die een bijgesneden kopie is, kunt u een afzonderlijke functie gebruiken:
template <typename Sequence, typename Pred>
Sequence trim_copy(Sequence seq, Pred pred) { // NOTE: passing seq by value
trim(seq, pred);
return seq;
}
Lexicografische vergelijking
Twee std::string
s kunnen lexicografisch worden vergeleken met de operatoren ==
!=
, <
, <=
, >
En >=
:
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);
Al deze functies gebruiken de onderliggende methode std::string::compare()
om de vergelijking uit te voeren en voor gemak booleaanse waarden terug te geven. De werking van deze functies kan als volgt worden geïnterpreteerd, ongeacht de daadwerkelijke implementatie:
operator
==
:Als
str1.length() == str2.length()
en elkstr1.length() == str2.length()
overeenkomt, wordttrue
geretourneerd, anders wordtfalse
geretourneerd.operator
!=
:Als
str1.length() != str2.length()
of een paar tekens komt niet overeen, wordttrue
geretourneerd, anders wordtfalse
geretourneerd.operator
<
of operator>
:Zoekt het eerste verschillende karakterpaar, vergelijkt ze en geeft vervolgens het Booleaanse resultaat terug.
operator
<=
of operator>=
:Zoekt het eerste verschillende karakterpaar, vergelijkt ze en geeft vervolgens het Booleaanse resultaat terug.
Opmerking: de term tekenpaar betekent de overeenkomstige tekens in beide reeksen van dezelfde posities. Voor een beter begrip, als twee voorbeeldreeksen str1
en str2
, en hun lengten respectievelijk n
en m
zijn, betekent str1[i]
van beide strings elke str1[i]
en str2[i]
paren waarbij i = 0, 1, 2 str2[i]
.., max (n, m) . Als voor een i waar het overeenkomstige teken niet bestaat, dat wil zeggen dat wanneer i groter is dan of gelijk is aan n
of m
, dit als de laagste waarde wordt beschouwd.
Hier is een voorbeeld van het gebruik van <
:
std::string str1 = "Barr";
std::string str2 = "Bar";
assert(str2 < str1);
De stappen zijn als volgt:
- Vergelijk de eerste tekens,
'B' == 'B'
- ga verder. - Vergelijk de tweede tekens,
'a' == 'a'
- ga verder. - Vergelijk de derde tekens,
'r' == 'r'
- ga verder. - Het
str2
bereik is nu uitgeput, terwijl hetstr1
bereik nog steeds tekens bevat. Dusstr2 < str1
.
Conversie naar std :: wstring
In C ++ worden reeksen tekens voorgesteld door de klasse std::basic_string
specialiseren met een native std::basic_string
. De twee belangrijkste collecties die door de standaardbibliotheek worden gedefinieerd, zijn std::string
en std::wstring
:
std::string
is gebouwd met elementen van het typechar
std::wstring
is gebouwd met elementen van het typewchar_t
Gebruik wstring_convert
om tussen de twee typen te converteren:
#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);
Om de bruikbaarheid en / of leesbaarheid te verbeteren, kunt u functies definiëren om de conversie uit te voeren:
#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);
}
Voorbeeld gebruik:
std::wstring a_wide_string = to_wstring("Hello World!");
Dat is zeker beter leesbaar dan std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes("Hello World!")
.
Let op: char
en wchar_t
houden geen codering in en geven geen indicatie van de grootte in bytes. wchar_t
wordt bijvoorbeeld gewoonlijk geïmplementeerd als een gegevenstype van 2 bytes en bevat meestal UTF-16-gecodeerde gegevens onder Windows (of UCS-2 in versies voorafgaand aan Windows 2000) en als een gegevenstype van 4 bytes gecodeerd met UTF-32 onder Linux. Dit is in tegenstelling tot de nieuwere typen char16_t
en char32_t
, die werden geïntroduceerd in C ++ 11 en gegarandeerd groot genoeg zijn om elk UTF16- of UTF32-'karakter '(of beter gezegd, codepunt ) te bevatten.
De klasse std :: string_view gebruiken
C ++ 17 introduceert std::string_view
, wat gewoon een niet-eigendom is van const char
, implementeerbaar als een paar aanwijzers of een aanwijzer en een lengte. Het is een superieur parametertype voor functies waarvoor niet-aanpasbare stringgegevens vereist zijn. Vóór C ++ 17 waren hier drie opties voor:
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
Al deze kunnen worden vervangen door:
void foo(std::string_view s); // post-C++17, single argument, tighter coupling
// zero copies regardless of how caller is storing
// the data
Merk op dat std::string_view
de onderliggende gegevens niet kan wijzigen .
string_view
is handig als u onnodige kopieën wilt vermijden.
Het biedt een nuttige subset van de functionaliteit die std::string
doet, hoewel sommige functies zich anders gedragen:
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';
Elk karakter doorlopen
std::string
ondersteunt iterators, en dus kun je een op afstand gebaseerde lus gebruiken om elk karakter te doorlopen:
std::string str = "Hello World!";
for (auto c : str)
std::cout << c;
Je kunt een "traditioneel" gebruiken for
elk personage lus te doorlopen:
std::string str = "Hello World!";
for (std::size_t i = 0; i < str.length(); ++i)
std::cout << str[i];
Conversie naar gehele getallen / drijvende komma types
Een std::string
die een nummer bevat, kan met behulp van conversiefuncties worden omgezet in een geheel getal of een type met drijvende komma.
Merk op dat al deze functies stoppen met het parseren van de invoertekenreeks zodra ze een niet-numeriek teken tegenkomen, dus "123abc"
wordt omgezet in 123
.
De std::ato*
van functies converteert tekenreeksen in C-stijl (tekenmatrices) naar typen met gehele getallen of drijvende komma:
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());
Het gebruik van deze functies wordt echter afgeraden omdat ze 0
retourneren als ze de string niet kunnen ontleden. Dit is slecht omdat 0
ook een geldig resultaat kan zijn, bijvoorbeeld als de invoertekenreeks "0" was, dus het is onmogelijk om te bepalen of de conversie daadwerkelijk is mislukt.
De nieuwere std::sto*
van functies converteert std::string
s naar typen met gehele getallen of drijvende komma en werpt uitzonderingen als ze hun invoer niet konden ontleden. Gebruik indien mogelijk deze functies :
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);
Bovendien kunnen deze functies ook octale en hex-strings verwerken in tegenstelling tot de std::ato*
. De tweede parameter is een wijzer naar het eerste niet-geconverteerde teken in de invoertekenreeks (hier niet geïllustreerd) en de derde parameter is de basis die moet worden gebruikt. 0
is automatische detectie van octaal (beginnend met 0
) en hex (beginnend met 0x
of 0X
), en elke andere waarde is de te gebruiken basis
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
Omzetten tussen karaktercoderingen
Converteren tussen coderingen is eenvoudig met C ++ 11 en de meeste compilers kunnen het platformonafhankelijk <codecvt>
via <codecvt>
en <locale>
headers.
#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;
}
Let op: Visual Studio 2015 biedt ondersteuning voor deze conversie, maar een bug in hun bibliotheekimplementatie vereist het gebruik van een andere sjabloon voor wstring_convert
bij het omgaan met 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());
}
Controleren of een string een prefix is van een andere
In C ++ 14 wordt dit eenvoudig gedaan door std::mismatch
die het eerste mismatchpaar uit twee bereiken retourneert:
std::string prefix = "foo";
std::string string = "foobar";
bool isPrefix = std::mismatch(prefix.begin(), prefix.end(),
string.begin(), string.end()).first == prefix.end();
Merk op dat er een reeks-en-een-halve versie van mismatch()
bestond vóór C ++ 14, maar dit is onveilig in het geval dat de tweede reeks de kortste van de twee is.
We kunnen nog steeds de range-and-a-half-versie van std::mismatch()
, maar we moeten eerst controleren of de eerste string maximaal even groot is als de tweede:
bool isPrefix = prefix.size() <= string.size() &&
std::mismatch(prefix.begin(), prefix.end(),
string.begin(), string.end()).first == prefix.end();
Met std::string_view
kunnen we de directe vergelijking schrijven die we willen, zonder ons zorgen te maken over overheadkosten of kopieën maken:
bool isPrefix(std::string_view prefix, std::string_view full)
{
return prefix == full.substr(0, prefix.size());
}
Converteren naar std :: string
std::ostringstream
kan worden gebruikt om elk streamable type naar een std::ostringstream
om te zetten, door het object in een std::ostringstream
object (met de streaminvoegoperator <<
) in te std::ostringstream
en vervolgens de hele std::ostringstream
naar een std::string
converteren std::string
.
Bijvoorbeeld voor int
:
#include <sstream>
int main()
{
int val = 4;
std::ostringstream str;
str << val;
std::string converted = str.str();
return 0;
}
Het schrijven van uw eigen conversiefunctie, de eenvoudige:
template<class T>
std::string toString(const T& x)
{
std::ostringstream ss;
ss << x;
return ss.str();
}
werkt maar is niet geschikt voor kritieke prestatiecode.
Door de gebruiker gedefinieerde klassen kunnen desgewenst de operator voor het invoegen van streams implementeren:
std::ostream operator<<( std::ostream& out, const A& a )
{
// write a string representation of a to out
return out;
}
Afgezien van streams, kunt u sinds C ++ 11 ook de functie std::to_string
(en std::to_wstring
) gebruiken die voor alle std::to_wstring
is overbelast en de tekenreeksrepresentatie van de parameter retourneert.
std::string s = to_string(0x12f3); // after this the string s contains "4851"