C ++ Succinct Corzi

Introducere

Corzile sunt unul dintre aceste lucruri supărătoare în C și C ++. În primele zile ale limbilor, șiruri de caractere au fost toate matricele de caractere, de obicei ASCII de 7 biți (deși probabil EBCDIC pe mainframele IBM la care era portat C). Apoi a venit o mulțime de soluții specifice OS, cum ar fi paginile de cod, pentru a permite limbile cu caractere care nu erau în alfabetul englez. După o perioadă de haos, a venit Unicode. Apoi Unicode. Și apoi din nou Unicode. Și mai multe Unicodes aici și acolo, care este rădăcina problemei de azi.

Unicode este, în esență, două lucruri. Este o serie definită de puncte de cod în care există o mapare unu-la-un anumit punct de cod la o anumită valoare, unele sunt grafice, altele controlează și manipulează formatul sau furnizează alte informații necesare. Toată lumea care utilizează Unicode este de acord cu toate acestea, inclusiv cu codurile de utilizare privată, toate fiind de acord că sunt rezervate aplicațiilor conforme cu standardele Unicode. Până acum, bine.

Apoi, există schemele de codificare de unde vin diviziile. Există 1.114.112 de coduri în Unicode. Cum îi reprezinți? Răspunsul a fost schemele de codificare. UTF-16 a fost primul. Ulterior au fost urmate de UTF-8 și UTF-32. Există, de asemenea, probleme de endianitate cu unele dintre acestea.

Au apărut și s-au dus și alte formate, dintre care unele nu au făcut niciodată parte din Unicode.

Windows a adoptat în cele din urmă UTF-16, la fel ca și .NET și Java. Multe sisteme GNU / Linux și alte sisteme similare UNIX au adoptat UTF-8. Unele sisteme de tip UNIX utilizează UTF-32. Unele ar putea folosi UTF-16. Webul folosește UTF-8 în cea mai mare parte, datorită faptului că designul intenționat al codificării este în mare parte compatibil cu ASCII. Atâta timp cât lucrați la un sistem, totul este bine. Când încerci să devii cross-platformă, lucrurile pot deveni mai confuze.

Siruri de caractere

carboniza* Siruri de caractere

Caracterele char * (pointers to arrays of char) au însemnat inițial șiruri de caractere ASCII. Acum, acestea înseamnă uneori ASCII, dar mai des, înseamnă UTF-8. Acest lucru este valabil mai ales în lumea UNIX.

La programarea pentru Windows, în general, ar trebui să presupuiți că un șir char * este un șir ASCII sau un șir de coduri de pagină. Paginile de cod utilizează bitul suplimentar rămas din ASCII pe 7 biți pentru a adăuga alte 128 de caractere, creând astfel o mulțime de text localizat care se potrivește încă într-un octet pe caracter.

wchar_t * Siruri de caractere

wchar_t * siruri de caractere (pointeri la matrice de wchar_t, numite și caractere mari) utilizează un alt set de caractere dependent de implementare. Pe Windows, aceasta înseamnă o valoare pe 16 biți, care este utilizată pentru UTF-16. Ar trebui să lucrați întotdeauna cu wchar_t ca tip de caractere nativ pentru Windows, cu excepția cazului în care trebuie să sprijiniți într-adevăr versiuni vechi ale sistemului de operare (de ex. Seria Windows 9X veche).

Atunci când scrieți un șir de caractere lat, constant în cod, prefixați ghilimele duble de deschidere cu un L. De exemplu: const wchar_t * s = L "Hello World";. Dacă aveți nevoie doar de un singur caracter, utilizați din nou L, dar cu citare simple: wchar_t ch = L'A ';.

std :: string și std :: wstring Siruri de caractere

std :: string și std :: wstring clasele se găsesc în fișierul antet. Așa cum vă puteți imagina, std :: string corespunde carboniza* in timp ce std :: wstring corespunde wchar_t *.

Aceste clase oferă o modalitate convenabilă de a stoca șiruri de lungime variabilă și ar trebui să fie folosite pentru variabilele membrilor de clasă în locul indicatorilor lor corespondenți (char * și wchar_t *). Ar trebui să utilizați numai pointerii brute pentru a transfera șiruri de caractere ca argumente, și numai dacă șirul va fi folosit ca-este sau copiat local într-unul din aceste tipuri de șir.

În ambele cazuri, funcția ar trebui să ia în pointer șir ca un pointer la const (de ex., const wchar_t * someStr). La urma urmei, pointerii nu suporta aceeasi cheltuiala de construire si distrugere ca std :: string si std :: wstring. Folosind un pointer pentru const asigură că funcția nu modifică accidental datele sau încearcă să elibereze memoria la care este îndreptată.

Pentru a obține un pointer pentru const pentru conținutul unuia dintre acestea, apelați funcția sa membru c_str. Rețineți că pointerul returnat indică const, deoarece datele nu trebuie modificate și nici nu trebuie șterse să fie solicitate pe pointer. Memoria este încă deținută și administrată de instanța std :: string sau std :: wstring. Acest lucru înseamnă, de asemenea, că, dacă instanța de bază este distrusă, indicatorul care vă dă c_str devine nevalid, motiv pentru care, dacă aveți nevoie de datele de șir dincolo de domeniul de aplicare a funcției în care este transmis, trebuie să păstrați întotdeauna datele de șir în unul dintre aceste tipuri, mai degrabă decât să stocați direct pointerul.

Pentru a adăuga text, utilizați funcția de adăugare a membrilor.

Pentru a vedea dacă o anumită secvență de caractere apare într-un șir, utilizați funcția de membru al găsirii sau una dintre variantele sale mai specifice, cum ar fi find_first_of. Dacă secvența nu este în șir, atunci valoarea returnată va fi egală std :: NPOs. În caz contrar, acesta va fi indicele punctului de pornire relevant pentru secvență.

Pentru a obține un sub-șir, utilizați funcția membrului substr, dându-i indicele inițial bazat pe zero și numărul de elemente (adică numărul caracterelor char sau wchar_t) pentru copiere. Acesta va returna un std :: string sau un std :: wstring fără a vă permite să depășiți un tampon prin trecerea unui număr inexact sau un indice de pornire necorespunzător.

Există și alte metode utile, toate fiind documentate ca parte a clasei basic_string, care este o clasă de șabloane care std :: string și std :: wstring sunt specializări predefinite ale.

std :: wstringstream Siruri de caractere

std :: wstringstream clasa (există std :: stringstream de asemenea, este similar cu clasa .NET StringBuilder. Este utilizabil în același mod ca orice alt flux din Biblioteca Standard C ++. Consider că acest tip este foarte util pentru construirea unui șir în cadrul unei funcții a unui membru, care va fi apoi stocată într-un std :: wstring membru al clasei.

Pentru un exemplu de utilizare, consultați secțiunea Toppings :: getString membru în fișierul ConstructorsSample \ Toppings.h. Aici este codul său, la fel ca o reîmprospătare:

 const wchar_t * GetString (void) dacă (m_toppings == Nici unul) m_toppingsString = L "None"; returnați m_toppingsString.c_str ();  bool addSpace = false; std :: wstringstream wstrstream; dacă (m_toppings & HotFudge) if (addSpace) wstrstream << L" ";  wstrstream << L"Hot Fudge"; addSpace = true;  if (m_toppings & RaspberrySyrup)  if (addSpace)  wstrstream << L" ";  wstrstream << L"Raspberry Syrup"; addSpace = true;  if (m_toppings & CrushedWalnuts)  if (addSpace)  wstrstream << L" ";  wstrstream << L"Crushed Walnuts"; addSpace = true;  if (m_toppings & WhippedCream)  if (addSpace)  wstrstream << L" ";  wstrstream << L"Whipped Cream"; addSpace = true;  if (m_toppings & Cherry)  if (addSpace)  wstrstream << L" ";  wstrstream << L"Cherry"; addSpace = true;  m_toppingsString = std::wstring(wstrstream.str()); return m_toppingsString.c_str(); 

Concluzie

După cum am menționat în introducere, istoria șirurilor nu este destul de bună, dar sper că acest articol ți-a dat o înțelegere corectă a șirurilor în C ++. Următoarea tranșă din această serie acoperă idiomurile comune în C++.

Această lecție reprezintă un capitol din C ++ Succinctly, o carte electronică gratuită de la echipa de la Syncfusion.
Cod