C ++ Kort gezegd snaren

Invoering

Strings zijn een van die lastige dingen in C en C ++. In de begindagen van de talen waren tekenreeksen allemaal tekenreeksen, meestal 7-bits ASCII (hoewel misschien EBCDIC op IBM-mainframes waarnaar C is geporteerd). Toen kwam een ​​puin van OS-specifieke workarounds, zoals codetabellen, om talen toe te staan ​​met tekens die niet in het Engelse alfabet stonden. Na een periode van chaos, kwam Unicode. Dan Unicode. En dan weer Unicode. En nog een paar meer Unicodes hier en daar, wat vandaag de wortel van het probleem is.

Unicode is in wezen twee dingen. Het is een gedefinieerde reeks codepunten waarin een één-op-één toewijzing van een bepaald codepunt aan een bepaalde waarde is, sommige zijn grafisch, anderen besturen en manipuleren het formatteren of verschaffen andere vereiste informatie. Iedereen die Unicode gebruikt, is het eens met al deze, inclusief de privégebruikscodepunten, die allen overeenkomen dat ze zijn gereserveerd voor Unicode-conforme applicaties. Tot nu toe, zo goed.

Dan zijn er de coderingsschema's waar de divisies vandaan komen. Er zijn 1.114.112 codepunten in Unicode. Hoe representeer je ze? Het antwoord was de coderingsschema's. UTF-16 was de eerste. Het werd later gevolgd door UTF-8 en UTF-32. Er zijn ook problemen met de endiantie bij sommige hiervan.

Andere indelingen kwamen en gingen, waarvan sommige zelfs nooit deel uitmaakten van Unicode.

Windows heeft uiteindelijk UTF-16 overgenomen net als .NET en Java. Veel GNU / Linux en andere UNIX-achtige systemen hebben UTF-8 gebruikt. Sommige UNIX-achtige systemen maken gebruik van UTF-32. Sommigen zouden UTF-16 kunnen gebruiken. Het web maakt grotendeels gebruik van UTF-8, omdat het opzettelijke ontwerp van die codering overwegend achterwaarts compatibel is met ASCII. Zolang je aan één systeem werkt, is alles goed. Wanneer u platformoverschrijdend probeert te worden, kunnen dingen verwarrend worden.

strings

char * strings

De tekenreeksen char * (wijzers naar arrays van char) betekenden oorspronkelijk ASCII-reeksen. Nu bedoelen ze soms ASCII, maar vaker betekent dit UTF-8. Dit geldt vooral in de UNIX-wereld.

Bij het programmeren voor Windows moet u er over het algemeen van uitgaan dat een tekenreeks * een ASCII-tekenreeks of een tekenreeks van een codetabel is. Codebladen gebruiken het extra bit dat is overgebleven van 7-bits ASCII om nog eens 128 tekens toe te voegen, waardoor er veel gelokaliseerde tekst ontstaat die nog steeds past binnen één byte per teken.

wchar_t * strings

wchar_t * strings (verwijzingen naar arrays van wchar_t, ook wel brede karakters genoemd) gebruik een andere, implementatie-afhankelijke tekenset. In Windows betekent dit een 16-bits waarde, die wordt gebruikt voor UTF-16. Je moet altijd werken met wchar_t als je native character type voor Windows, tenzij je echt hele oude OS-versies (d.w.z. de oude Windows 9X-serie) moet ondersteunen.

Wanneer u een tekenreeks met een breed tekenreeks in code schrijft, geeft u de dubbele openingsquotes als prefix op met een L. Bijvoorbeeld: const wchar_t * s = L "Hallo wereld";. Als je maar één personage nodig hebt, gebruik je de L opnieuw, maar met enkele aanhalingstekens: wchar_t ch = L'A ';.

std :: string en std :: wstring strings

De std :: string en std :: wstring klassen zijn te vinden in de header-bestand. Zoals je je misschien zou voorstellen, std :: string komt overeen met char * terwijl std :: wstring komt overeen met wchar_t *.

Deze klassen bieden een handige manier om reeksen van variabele lengte op te slaan en moeten worden gebruikt voor variabelen van klassenleden in plaats van hun overeenkomstige onbewerkte aanwijzers (char * en wchar_t *). Gebruik de onbewerkte pointers alleen om strings als argumenten door te geven, en dan alleen als de string as-is wordt gebruikt of lokaal wordt gekopieerd naar een van deze tekenreeksen.

In beide gevallen moet de functie de tekenreeksaanwijzer meenemen als aanwijzer naar const (bijv., const wchar_t * someStr). Immers, pointers hebben niet dezelfde kosten voor constructie en vernietiging die std :: string en std :: wstring doen. Het gebruik van een pointer naar const zorgt ervoor dat de functie niet per ongeluk de gegevens wijzigt of probeert het geheugen vrij te maken waarnaar wordt verwezen.

Als u een aanwijzer naar const wilt krijgen voor de inhoud van een van deze, roept u de functie c_str member aan. Houd er rekening mee dat de geretourneerde aanwijzer verwijst naar const, omdat de gegevens niet moeten worden gewijzigd en de aanwijzer ook niet moet worden opgeroepen. Het geheugen is nog steeds eigendom van en wordt beheerd door de onderliggende std :: string of std :: wstring instantie. Dit betekent ook dat als de onderliggende instantie wordt vernietigd, de aanwijzer die c_str u geeft ongeldig wordt. Daarom, als u de tekenreeksgegevens buiten het bereik van de functie waar deze aan wordt doorgegeven, moet u de tekenreeksgegevens altijd opslaan in een van deze typen in plaats van de aanwijzer rechtstreeks op te slaan.

Gebruik de functie Lid toevoegen om tekst toe te voegen.

Gebruik de functie find member of een van de meer specifieke varianten, zoals find_first_of om te zien of een bepaalde reeks tekens voorkomt in een tekenreeks. Als de reeks niet in de reeks voorkomt, is de retourwaarde gelijk std :: NPO. Anders is dit de index van het relevante startpunt voor de reeks.

Als u een subtekenreeks wilt, gebruikt u de functie Subonderdeel door deze de index op basis van het startnulpunt en het aantal elementen (dat wil zeggen het aantal char- of wchar_t-tekens) door te geven om te kopiëren. Het geeft een std :: string of een std :: wstring terug, zonder dat je een buffer kunt overlopen door een onnauwkeurige telling of een onjuiste startindex door te geven.

Er zijn andere bruikbare methoden, die allemaal gedocumenteerd zijn als onderdeel van de basic_string klasse, wat een template klasse is die std :: string en std :: wstring zijn vooraf gedefinieerde specialisaties van.

std :: wstringstream strings

De std :: wstringstream klasse (er is een std :: stringstream ook) is vergelijkbaar met de klasse .NET StringBuilder. Het is bruikbaar op vrijwel dezelfde manier als elke andere C ++ Standard Library-stream. Ik vind dit type erg handig voor het construeren van een string binnen een lidfunctie die dan wordt opgeslagen in een std :: wstring klaslid.

Voor een voorbeeld van het gebruik, zie de Toppings :: GetString lidfunctie in het bestand ConstructorsSample \ Toppings.h. Hier is de code, net als een opfriscursus:

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

Conclusie

Zoals ik in de inleiding al zei, is de geschiedenis van strings niet mooi, maar ik hoop dat dit artikel je een goed begrip heeft gegeven van strings in C ++. De volgende aflevering van deze serie behandelt gemeenschappelijke idioom in C++.

Deze les staat voor een hoofdstuk uit C ++ Kort gezegd, een gratis eBoek van het team van Syncfusion.