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() :

C ++ 11
  1. Op een niet-const string is het gedrag niet gedefinieerd ;
  2. Op een const-tekenreeks wordt een verwijzing naar een teken met de waarde CharT() (het null- teken) geretourneerd.
C ++ 11
  1. Een verwijzing naar een teken met de waarde CharT() (het null- teken) wordt geretourneerd.
  2. 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!"
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!"

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'
C ++ 11

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:

  1. 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 meerdere strings 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 de std::string het werkt, dus het kan niet worden gebruikt op const string s, const char* s of letterlijke strings, om een van deze te std::strtok met std::strtok of om te werken op een std::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 en std::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);

Live voorbeeld

  1. De std::istream_iterator gebruikt iteratief de extractieoperator van de stroom. Als de invoer std::string is gescheiden door witruimte, kan deze worden uitgebreid naar de std::strtok optie door de moeilijkheden te elimineren, inline std::strtok mogelijk te maken waardoor het genereren van een const 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>());

Live voorbeeld

  1. De std::regex_token_iterator gebruikt een std::regex om iteratief te tokenize. Het zorgt voor een flexibelere afbakeningsdefinitie. Bijvoorbeeld, niet-gescheiden komma's en witruimte:
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() 
};

Live voorbeeld

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.

C ++ 17

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.

C ++ 11

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.

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();

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> .

C ++ 11

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 elk str1.length() == str2.length() overeenkomt, wordt true geretourneerd, anders wordt false geretourneerd.

  • operator != :

    Als str1.length() != str2.length() of een paar tekens komt niet overeen, wordt true geretourneerd, anders wordt false 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:

  1. Vergelijk de eerste tekens, 'B' == 'B' - ga verder.
  2. Vergelijk de tweede tekens, 'a' == 'a' - ga verder.
  3. Vergelijk de derde tekens, 'r' == 'r' - ga verder.
  4. Het str2 bereik is nu uitgeput, terwijl het str1 bereik nog steeds tekens bevat. Dus str2 < 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 type char

  • std::wstring is gebouwd met elementen van het type wchar_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

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

C ++ 11

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());
C ++ 11
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 :

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);

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

C ++ 14

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.

C ++ 14

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();
C ++ 17

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; 
}
C ++ 11

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"


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow