C ++ Succinctly Strings

Introduksjon

Strings er en av de plagsomme tingene i C og C ++. I de tidlige dagene av språkene var strenger alle tegnrapporter, typisk 7-biters ASCII (selv om det kanskje var EBCDIC på IBM-hovedrammer som C ble portet til). Så kom et rot av OS-spesifikke løsninger, for eksempel kodesider, for å tillate språk med tegn som ikke var i det engelske alfabetet. Etter en periode med kaos kom Unicode. Så Unicode. Og så Unicode igjen. Og noen flere Unicodes her og der også, som er roten til problemet i dag.

Unicode er i hovedsak to ting. Det er en definert serie kodepunkter der det er en kartlegging av en bestemt kode til en bestemt verdi, noen er grafiske, andre kontrollerer og manipulerer formatering eller gir annen nødvendig informasjon. Alle som bruker Unicode, godtar alle disse, inkludert de private brukskodepunktene, som alle er enige om, er reservert for Unicode-kompatible applikasjoner. Så langt så bra.

Deretter er det kodingsordninger der divisjonene kommer fra. Det er 1,114,112 kodepoeng i Unicode. Hvordan representerer du dem? Svaret var kodingsordninger. UTF-16 var den første. Det ble senere fulgt av UTF-8 og UTF-32. Det er også endianhetsproblemer med noen av disse.

Andre formater kom og gikk, noen av dem var aldri en del av Unicode.

Windows til slutt vedtok UTF-16 som gjorde .NET og Java. Mange GNU / Linux og andre UNIX-lignende systemer vedtok UTF-8. Noen UNIX-lignende systemer bruker UTF-32. Noen kan bruke UTF-16. Internett bruker UTF-8 for det meste, på grunn av at kodingens forsettlige design er det meste bakoverkompatibelt med ASCII. Så lenge du jobber med ett system, er alt bra. Når du prøver å bli tverrplattform, kan ting bli forvirrende.

Strings

char * Strings

Karbonene (pekere til arrays of char) betydde opprinnelig ASCII-strenger. Nå betyr det noen ganger ASCII, men hyppigere betyr det UTF-8. Dette gjelder spesielt i UNIX-verdenen.

Når du programmerer for Windows, bør du vanligvis anta at en char * -streng er en ASCII-streng eller en kode-side-streng. Kodesider bruker ekstra bit igjen fra 7-biters ASCII for å legge til ytterligere 128 tegn, og dermed skape mye lokal tekst som fortsatt passer inn i en byte per tegn.

wchar_t * Strings

wchar_t * strenger (pekere til arrays of wchar_t, også kalt brede tegn) bruker et annet, implementeringsavhengig tegnsett. På Windows betyr dette en 16-biters verdi, som brukes til UTF-16. Du bør alltid jobbe med wchar_t som din opprinnelige karaktertype for Windows, med mindre du må støtte virkelig, virkelig gamle OS-versjoner (det vil si den gamle Windows 9X-serien).

Når du skriver en bred tegnstreng konstant i kode, prefixer du åpningsdobletter med en L. For eksempel: const wchar_t * s = L "Hello World";. Hvis du bare trenger et enkelt tegn, bruker du igjen L, men med enkelt anførselstegn: wchar_t ch = L'A ';.

std :: string og std :: wstring Strings

De std :: string og std :: wstring klasser er funnet i header fil. Som du kanskje forestiller deg, std :: string tilsvarer char * samtidig som std :: wstring tilsvarer wchar_t *.

Disse klassene gir en praktisk måte å lagre variabel lengde strenger på og bør brukes til klassemedlemvariabler i stedet for deres tilsvarende råpekere (char * og wchar_t *). Du bør bare bruke de rå pekerne til å sende strenger som argumenter, og bare hvis strengen blir brukt som-er eller kopiert lokalt til en av disse strengtyper.

I begge tilfeller bør funksjonen ta inn strengestiften som en peker til const (f.eks., const wchar_t * someStr). Tross alt, peker ikke på samme konstruksjons- og ødeleggelsesutgift som std :: streng og std :: wstring gjør. Ved å bruke en peker til const sikrer at funksjonen ikke ved et uhell vil endre dataene eller forsøke å frigjøre minnet som er pekt på.

For å få en pointer til const for innholdet i en av disse, ring sin c_str medlem funksjon. Vær oppmerksom på at den returnerte pekeren peker til const siden dataene ikke skal endres, og det bør heller ikke slettes bli peket på pekeren. Minnet eies og administreres fortsatt av den underliggende std :: strengen eller std :: wstring-forekomsten. Dette betyr også at hvis den underliggende forekomsten blir ødelagt, pekeren som c_str gir deg, blir ugyldig. Derfor må du alltid lagre strengdataene i en streng, hvis du trenger strengdataene utenfor funksjonsområdet. en av disse typene i stedet for å lagre pekeren direkte.

For å legge til tekst, bruk funksjonen til å legge til medlemmen.

For å se om en bestemt sekvens av tegn forekommer i en streng, bruk funnelementfunksjonen eller en av de mer spesifikke varianter, for eksempel find_first_of. Hvis sekvensen ikke er i strengen, vil returverdien være lik std :: npos. Ellers vil det være indeksen for det relevante utgangspunktet for sekvensen.

For å få en understreng, bruk substr medlem funksjonen, passere den start null-baserte indeksen og antall elementer (dvs. antall karbon eller wchar_t tegn) for å kopiere. Den vil returnere en std :: streng eller en std :: wstring uten å tillate deg å overlate en buffer ved å sende et unøyaktig antall eller en feil startindeks.

Det finnes andre nyttige metoder, som alle er dokumentert som en del av basic_string-klassen, som er en malklasse som std :: string and std :: wstring er forhåndsdefinerte spesialiseringer av.

std :: wstringstream Strings

De std :: wstringstream klasse (det er en std :: stringstream også) ligner på .NET StringBuilder-klassen. Den kan brukes på omtrent samme måte som alle andre C ++ Standard Library-strømmer. Jeg finner denne typen veldig nyttig for å bygge en streng i en medlemsfunksjon som da vil bli lagret i en std :: wstring klassemedlem.

For et eksempel på bruken, se Topping :: GetString medlemsfunksjonen i filen ConstructorsSample \ Toppings.h. Her er koden sin, akkurat som en oppdatering:

 const wchar_t * GetString (void) if (m_toppings == None) m_toppingsString = L "None"; returner m_toppingsString.c_str ();  bool addSpace = false; std :: wstringstream wstrstream; hvis (m_toppings & HotFudge) hvis (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(); 

Konklusjon

Som jeg nevnte i introduksjonen, er strangens historie ikke pen, men jeg håper at denne artikkelen har gitt deg en ordentlig forståelse av strenger i C ++. Neste del av denne serien dekker vanlige idiomer i C++.

Denne leksjonen representerer et kapittel fra C ++ Succinctly, en gratis eBok fra teamet på Syncfusion.