Ricerca…


introduzione

Le stringhe sono oggetti che rappresentano sequenze di personaggi. La classe di string standard fornisce un'alternativa semplice, sicura e versatile all'utilizzo di array espliciti di char quando si tratta di testo e altre sequenze di caratteri. La classe di string C ++ fa parte dello spazio dei nomi std ed è stata standardizzata nel 1998.

Sintassi

  • // Dichiarazione di stringa vuota

    std :: string s;

  • // Costruire da const char * (c-string)

    std :: string s ("Hello");

    std :: string s = "Ciao";

  • // Costruire usando il costruttore di copie

    std :: string s1 ("Hello");

    std :: string s2 (s1);

  • // Costruire dalla sottostringa

    std :: string s1 ("Hello");

    std :: string s2 (s1, 0, 4); // Copia 4 caratteri dalla posizione 0 di s1 a s2

  • // Costruire da un buffer di caratteri

    std :: string s1 ("Hello World");
    std :: string s2 (s1, 5); // Copia i primi 5 caratteri di s1 in s2

  • // Costruisci usando fill constructor (solo char)

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

  • // Costruisce usando il costruttore di intervalli e l'iteratore

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

    std :: string s2 (s1.begin (), s1.begin () + 5); // Copia i primi 5 caratteri di s1 in s2

Osservazioni

Prima di usare std::string , dovresti includere la string intestazione, poiché include funzioni / operatori / sovraccarichi che altre intestazioni (ad esempio iostream ) non includono.


L'uso del costruttore const char * con un nullptr porta a un comportamento non definito.

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

Il metodo at lancia uno std::out_of_range un'eccezione se index >= size() .

Il comportamento di operator[] è un po 'più complicato, in tutti i casi ha un comportamento indefinito se index > size() , ma quando index == size() :

C ++ 11
  1. Su una stringa non const, il comportamento non è definito ;
  2. Su una stringa const, viene restituito un riferimento a un carattere con valore CharT() (il carattere null ).
C ++ 11
  1. Viene restituito un riferimento a un carattere con valore CharT() (il carattere null ).
  2. La modifica di questo riferimento è un comportamento non definito .

Dal momento che C ++ 14, invece di usare "foo" , si consiglia di usare "foo"s , poichè s è un suffisso letterale definito dall'utente , che converte il const char* "foo" in std::string "foo" .

Nota: è necessario utilizzare lo spazio dei nomi std::string_literals o std::literals per ottenere i letterali s .

scissione

Usa std::string::substr per dividere una stringa. Ci sono due varianti di questa funzione membro.

Il primo prende una posizione di partenza da cui dovrebbe iniziare la sottostringa restituita. La posizione di partenza deve essere valida nell'intervallo (0, str.length()] :

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

Il secondo prende una posizione di partenza e una lunghezza totale della nuova sottostringa. Indipendentemente dalla lunghezza , la sottostringa non andrà mai oltre la fine della stringa di origine:

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

Nota che puoi anche chiamare substr senza argomenti, in questo caso viene restituita una copia esatta della stringa

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

Sostituzione di corde

Sostituisci per posizione

Per sostituire una parte di una std::string puoi utilizzare il metodo replace da std::string .

replace ha molti sovraccarichi utili:

//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!"

Sostituisci le occorrenze di una stringa con un'altra stringa

Sostituisci solo la prima occorrenza di replace con 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;
}

Sostituisci tutte le occorrenze di replace con 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;
}

Concatenazione

Puoi concatenare std::string s usando gli operatori + e += sovraccaricati. Usando l'operatore + :

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

Usando l'operatore += :

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

È anche possibile aggiungere stringhe C, compresi i letterali stringa:

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

Puoi anche usare push_back() per respingere i singoli char :

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

C'è anche append() , che è più o meno come += :

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

Accedere a un personaggio

Esistono diversi modi per estrarre i caratteri da una std::string e ognuno è sottilmente differente.

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

operatore [] (n)

Restituisce un riferimento al carattere all'indice n.

std::string::operator[] non è controllato e non genera un'eccezione. Il chiamante è responsabile per affermare che l'indice si trova all'interno dell'intervallo della stringa:

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

a (n)

Restituisce un riferimento al carattere all'indice n.

std::string::at is bounds checked, e getterà std::out_of_range se l'indice non è all'interno dell'intervallo della stringa:

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

Nota: entrambi questi esempi generano un comportamento indefinito se la stringa è vuota.


davanti()

Restituisce un riferimento al primo carattere:

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

indietro()

Restituisce un riferimento all'ultimo carattere:

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

tokenize

Elencato dal meno costoso al più costoso in fase di esecuzione:

  1. str::strtok è il metodo di tokenizzazione standard più economico fornito, consente inoltre di modificare il delimitatore tra i token, ma comporta 3 difficoltà con il C ++ moderno:

    • std::strtok non può essere utilizzato su più strings contemporaneamente (anche se alcune implementazioni si estendono per supportare questo, come ad esempio: strtok_s )
    • Per lo stesso motivo, std::strtok non può essere utilizzato su più thread simultaneamente (questo potrebbe essere tuttavia definito dall'implementazione, ad esempio: l'implementazione di Visual Studio è thread-safe )
    • Chiamare std::strtok modifica la std::string cui sta operando, quindi non può essere usata su const string s, const char* s o stringhe letterali, per tokenizzare uno di questi con std::strtok o per operare su un std::string chi ha il contenuto da conservare, l'input dovrebbe essere copiato, quindi la copia può essere utilizzata

    Generalmente, qualsiasi costo di queste opzioni sarà nascosto nel costo di allocazione dei token, ma se è richiesto l'algoritmo più economico e le difficoltà di std::strtok non sono sovrastimabili, si consideri una soluzione filata a mano .

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

Esempio dal vivo

  1. std::istream_iterator utilizza iterativamente l'operatore di estrazione del flusso. Se l'input std::string è delimitato da spazi bianchi, questo è in grado di espandersi sull'opzione std::strtok eliminando le sue difficoltà, consentendo la tokenizzazione in linea supportando in tal modo la generazione di un const vector<string> e aggiungendo il supporto per più delimitare il carattere dello spazio bianco:
// 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>());

Esempio dal vivo

  1. std::regex_token_iterator usa una std::regex to iterativamente tokenize. Fornisce una definizione delimitatore più flessibile. Ad esempio, virgole non delimitate e spazi bianchi:
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() 
};

Esempio dal vivo

Vedi l' esempio regex_token_iterator per maggiori dettagli.

Conversione in (const) char *

Per ottenere un accesso const char* ai dati di una std::string puoi utilizzare la funzione membro c_str() della stringa. Tieni presente che il puntatore è valido solo finché l'oggetto std::string è all'interno dell'ambito e rimane invariato, il che significa che solo i metodi const possono essere richiamati sull'oggetto.

C ++ 17

La funzione membro data() può essere utilizzata per ottenere un char* modificabile, che può essere utilizzato per manipolare i dati dell'oggetto std::string .

C ++ 11

Un char* modificabile char* può anche essere ottenuto prendendo l'indirizzo del primo carattere: &s[0] . All'interno di C ++ 11, questo è garantito per produrre una stringa ben formata, con terminazione nulla. Nota che &s[0] è ben formato anche se s è vuoto, mentre &s.front() non è definito se s è vuoto.

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

Trovare caratteri (s) in una stringa

Per trovare un carattere o un'altra stringa, puoi usare std::string::find . Restituisce la posizione del primo carattere della prima partita. Se non sono state trovate corrispondenze, la funzione restituisce 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";

Trovato in posizione: 21


Le opportunità di ricerca sono ulteriormente ampliate dalle seguenti funzioni:

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 

Queste funzioni consentono di cercare caratteri dalla fine della stringa e di trovare il caso negativo (cioè i caratteri che non sono nella stringa). Ecco un esempio:

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

Trovato in posizione: 6

Nota: tenere presente che le funzioni di cui sopra non cercano sottostringhe, ma piuttosto per i caratteri contenuti nella stringa di ricerca. In questo caso, l'ultima occorrenza di 'g' stata trovata nella posizione 6 (gli altri caratteri non sono stati trovati).

Taglio di caratteri all'inizio / fine

Questo esempio richiede le intestazioni <algorithm> , <locale> e <utility> .

C ++ 11

Tagliare una sequenza o una stringa significa rimuovere tutti gli elementi iniziali e finali (o caratteri) che corrispondono a un determinato predicato. Per prima cosa tagliamo gli elementi finali, perché non implica lo spostamento di alcun elemento e quindi taglia gli elementi principali. Si noti che le generalizzazioni di seguito funzionano per tutti i tipi di std::basic_string (ad es. std::string e std::wstring ), e accidentalmente anche per contenitori di sequenze (ad es. std::vector e 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);
}

Ritagliare gli elementi finali significa trovare l' ultimo elemento che non corrisponde al predicato e cancellare da lì in poi:

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

Il taglio degli elementi principali comporta la ricerca del primo elemento che non corrisponde al predicato e che cancella fino a lì:

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

Per specializzare quanto sopra per il taglio degli spazi bianchi in una std::string possiamo usare la funzione std::isspace() come predicato:

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

Allo stesso modo, possiamo usare la funzione std::iswspace() per std::wstring ecc.

Se desideri creare una nuova sequenza che è una copia tagliata, puoi utilizzare una funzione separata:

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

Confronto lessicografico

Due std::string s possono essere confrontati lessicograficamente usando gli operatori == != , < , <= , > E >= :

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

Tutte queste funzioni utilizzano il metodo std::string::compare() sottostante per eseguire il confronto e restituiscono valori convenienza booleani. L'operazione di queste funzioni può essere interpretata come segue, indipendentemente dall'attuale implementazione:

  • operatore == :

    Se str1.length() == str2.length() e ogni coppia di caratteri corrisponde, restituisce true , altrimenti restituisce false .

  • operatore != :

    Se str1.length() != str2.length() o una coppia di caratteri non corrisponde, restituisce true , altrimenti restituisce false .

  • operatore < o operatore > :

    Trova la prima coppia di caratteri diversa, li confronta e restituisce il risultato booleano.

  • operatore <= o operatore >= :

    Trova la prima coppia di caratteri diversa, li confronta e restituisce il risultato booleano.

Nota: il termine coppia di caratteri indica i caratteri corrispondenti in entrambe le stringhe delle stesse posizioni. Per capire meglio, se due stringhe di esempio sono str1 e str2 e le loro lunghezze sono rispettivamente n e m , allora le coppie di caratteri di entrambe le stringhe significano ogni str1[i] e str2[i] dove i = 0, 1, 2 str1[i] .., max (n, m) . Se per qualsiasi i dove il carattere corrispondente non esiste, cioè quando i è maggiore o uguale a n o m , sarebbe considerato come il valore più basso.


Ecco un esempio di utilizzo di < :

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

assert(str2 < str1);

I passi sono come segue:

  1. Confronta i primi caratteri, 'B' == 'B' - vai avanti.
  2. Confronta i secondi caratteri, 'a' == 'a' - vai avanti.
  3. Confronta i terzi caratteri, 'r' == 'r' - vai avanti.
  4. La gamma str2 è ora esaurita, mentre la gamma str1 ha ancora caratteri. Quindi, str2 < str1 .

Conversione a std :: wstring

In C ++, le sequenze di caratteri sono rappresentate specializzando la classe std::basic_string con un tipo di carattere nativo. Le due principali raccolte definite dalla libreria standard sono std::string e std::wstring :

  • std::string è costruito con elementi di tipo char

  • std::wstring è costruito con elementi di tipo wchar_t

Per convertire tra i due tipi, utilizzare 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);

Al fine di migliorare l'usabilità e / o la leggibilità, è possibile definire le funzioni per eseguire la conversione:

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

Esempio di utilizzo:

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

Questo è sicuramente più leggibile di std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes("Hello World!") .


Si noti che char e wchar_t non implicano la codifica e non forniscono indicazioni sulla dimensione in byte. Ad esempio, wchar_t viene comunemente implementato come un tipo di dati da 2 byte e in genere contiene dati codificati UTF-16 in Windows (o UCS-2 nelle versioni precedenti a Windows 2000) e come un tipo di dati di 4 byte codificati con UTF-32 in Linux. Questo è in contrasto con i nuovi tipi char16_t e char32_t , che sono stati introdotti in C ++ 11 e sono garantiti per essere abbastanza grandi da contenere un "carattere" UTF16 o UTF32 (o più precisamente, punto di codice ), rispettivamente.

Usando la classe std :: string_view

C ++ 17

C ++ 17 introduce std::string_view , che è semplicemente un intervallo non proprietario di const char , implementabile come una coppia di puntatori o un puntatore e una lunghezza. È un tipo di parametro superiore per le funzioni che richiedono dati stringa non modificabili. Prima di C ++ 17, c'erano tre opzioni per questo:

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

Tutti questi possono essere sostituiti con:

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

Si noti che std::string_view non può modificare i suoi dati sottostanti .

string_view è utile quando si desidera evitare copie non necessarie.

Offre un sottoinsieme utile della funzionalità che std::string fa, sebbene alcune funzioni si comportino diversamente:

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

In loop attraverso ogni personaggio

C ++ 11

std::string supporta gli iteratori e quindi puoi usare un loop basato su intervalli per scorrere ogni carattere:

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

Puoi usare un ciclo "tradizionale" for far passare in loop ogni personaggio:

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

Conversione in numeri interi / in virgola mobile

Una std::string contenente un numero può essere convertita in un tipo intero o in un tipo a virgola mobile, utilizzando le funzioni di conversione.

Nota che tutte queste funzioni smettono di analizzare la stringa di input non appena incontrano un carattere non numerico, quindi "123abc" sarà convertito in 123 .


La famiglia di funzioni std::ato* converte stringhe in stile C (matrici di caratteri) in numeri interi o in virgola mobile:

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

Tuttavia, l'uso di queste funzioni è sconsigliato perché restituiscono 0 se non riescono a analizzare la stringa. Questo è negativo perché 0 potrebbe anche essere un risultato valido, se per esempio la stringa di input era "0", quindi è impossibile determinare se la conversione è effettivamente fallita.

La più recente famiglia di funzioni std::sto* converte std::string s in interi o in virgola mobile e genera eccezioni se non possono analizzare il loro input. Dovresti usare queste funzioni se possibile :

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

Inoltre, queste funzioni gestiscono anche le stringhe ottale e esagonale a differenza della famiglia std::ato* . Il secondo parametro è un puntatore al primo carattere non convertito nella stringa di input (non illustrato qui) e il terzo parametro è la base da utilizzare. 0 è il rilevamento automatico di ottale (a partire da 0 ) e hex (a partire da 0x o 0X ), e qualsiasi altro valore è la base da usare

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

Conversione tra codifiche di caratteri

La conversione tra codifiche è facile con C ++ 11 e la maggior parte dei compilatori è in grado di <codecvt> modo multipiattaforma attraverso le <codecvt> e <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;
}

Ricorda che Visual Studio 2015 fornisce supporto per queste conversioni, ma un bug nella loro implementazione di libreria richiede l'utilizzo di un modello diverso per wstring_convert quando si ha a che fare con 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());
}

Verifica se una stringa è un prefisso di un'altra

C ++ 14

In C ++ 14, questo è fatto facilmente da std::mismatch che restituisce la prima coppia di mismatching da due intervalli:

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

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

Si noti che una versione di intervallo e mezza di mismatch() esisteva prima di C ++ 14, ma questo non è sicuro nel caso in cui la seconda stringa sia la più corta delle due.

C ++ 14

Possiamo ancora usare la versione range-and-half di std::mismatch() , ma dobbiamo prima verificare che la prima stringa sia al massimo grande come la seconda:

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

Con std::string_view , possiamo scrivere il confronto diretto che vogliamo senza doverci preoccupare del sovraccarico dell'allocazione o fare copie:

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

Conversione in std :: string

std::ostringstream può essere utilizzato per convertire qualsiasi tipo di streamable in una rappresentazione di stringa, inserendo l'oggetto in un oggetto std::ostringstream (con l'operatore di inserimento del flusso << ) e quindi convertendo l'intero std::ostringstream in uno std::string .

Per int per esempio:

#include <sstream>

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

Scrivendo la tua funzione di conversione, il semplice:

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

funziona ma non è adatto per il codice critico delle prestazioni.

Le classi definite dall'utente possono implementare l'operatore di inserimento del flusso se lo si desidera:

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

A parte i flussi, dal momento che in C ++ 11 è possibile utilizzare anche la funzione std::to_string (e std::to_wstring ) che è sovraccaricata per tutti i tipi fondamentali e restituisce la rappresentazione in stringa del suo parametro.

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


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow