Windows - Cross-platform C ++: Brug den oprindelige strengkodning eller standardiser på tværs af platforme?

Indlæg af Hanne Mølgaard Plasc

Problem



Vi er specielt eyeing Windows og Linux udvikling, og har kommet med to forskellige tilgange, som begge synes at have deres fordele. Den naturlige unicode-strengtype i Windows er UTF-16 og UTF-8 i Linux.


Vi kan ikke bestemme om den bedste tilgang:



  1. Standardiser på en af ​​de to i alle vores applikationslogik (og vedholdende data), og lad de andre platforme foretage de rette konverteringer

  2. Brug det naturlige format til operativsystemet til applikationslogik (og dermed foretage opkald til operativsystemet) og konverter kun på IPC og ved persistens.



For mig virker de som om de begge er lige så gode som hinanden.

Bedste reference



  og UTF-8 i linux.



Det er mest sandt for moderne Linux. Faktisk er kodning afhængig af, hvad API eller bibliotek bruges. Nogle er hardcoded til at bruge UTF-8. Men nogle læser LC\_ALL, LC\_CTYPE eller LANG miljøvariabler for at registrere kodning til brug (som Qt-bibliotek). Vær forsigtig.



  Vi kan ikke bestemme om den bedste tilgang



Som normalt afhænger det.


Hvis 90\% af koden skal håndtere platformspecifik API på platformspecifik måde, er det naturligvis bedre at bruge platformsspecifikke strenge. Som et eksempel - en enhedsdriver eller et indbygget iOS-program.


Hvis 90\% af koden er kompleks forretningslogik, der deles på tværs af platforme, er det naturligvis bedre at bruge samme kodning på alle platforme. Som et eksempel - chat-klient eller browser.


I andet tilfælde har du et valg:



  • Brug tværplatformsbibliotek, der giver strengeunderstøttelse (Qt, ICU, for eksempel)

  • Brug bare pointere (jeg overvejer også std :: string en 'bare pointer')



Hvis du arbejder med strenge er en væsentlig del af din ansøgning, vælger et godt bibliotek til strenge et godt træk. For eksempel har Qt et meget solid sæt af klasser, der dækker 99\% af de fælles opgaver. Desværre har jeg ingen ICU erfaring, men det ser også ud til at være meget flot.


Når du bruger et bibliotek til strenge, skal du kun bekymre sig om kodning, når du arbejder med eksterne biblioteker, platform API eller sender strenge over nettet (eller disken). For eksempel har en masse kakao, c # eller qt (alle har solid strenge støtte) programmører ved meget lidt om kodning detaljer (og det er godt, da de kan fokusere på deres vigtigste opgave).


Min erfaring med at arbejde med strenge er en lille specifik, så jeg foretrækker personligt bare pointere. Kode, der bruger dem, er meget bærbar (i forstand kan det nemt genbruges i andre projekter og platforme), fordi de har mindre eksterne afhængigheder. Det er ekstremt enkelt og hurtigt også (men man har sikkert brug for en del erfaring og Unicode-baggrund for at mærke det).


Jeg er enig i, at bare pointers tilgang er ikke for alle. Det er godt, når:



  • Du arbejder med hele strenge og opdeling, søgning, sammenligning er en sjælden opgave

  • Du kan bruge samme kodning i alle komponenter og behøver kun en konvertering, når du bruger platform-API

  • Alle dine understøttede platforme har API til:


    • Konverter fra din kodning til det, der bruges i API

    • Konverter fra API-kodning til det, der bruges i din kode


  • Pointers er ikke et problem i dit team



Fra min lille specifikke oplevelse er det faktisk en meget almindelig sag.


Når du arbejder med bare pointere, er det godt at vælge kodning, der bruges i hele projektet (eller i alle projekter).


Ud fra mit synspunkt er UTF-8 en ultimativ vinder. Hvis du ikke kan bruge UTF-8 - brug strenge bibliotek eller platform API til strenge - det vil spare dig for meget tid.


Fordele ved UTF-8:



  • Fuldt ASCII-kompatibel. Enhver ASCII-streng er en gyldig UTF-8-streng.

  • C std bibliotek fungerer fint med UTF-8 strings. (*)

  • C ++ std bibliotek fungerer fint med UTF-8 (std :: string og venner). (*)

  • Legacy-kode fungerer fint med UTF-8.

  • En hvilken som helst platform understøtter UTF-8.

  • Fejlfinding er meget lettere med UTF-8 (da den er ASCII-kompatibel).

  • Intet lille endian/Big-endian rod.

  • Du vil ikke få en klassisk fejl 'Åh, UTF-16 er ikke altid 2 byte?'.



(*) Indtil du er nødt til at sammenligne dem leksikalsk, transformer case (toUpper/toLower), skift normaliseringsformular eller noget lignende - hvis du gør det - skal du bruge strenge bibliotek eller platform API.


Ulempen er tvivlsom:



  • Mindre kompakt til kinesisk (og andre symboler med store kodepunktstal) end UTF-16.

  • Hardere (lidt faktisk) for at gentage symboler.



Så jeg anbefaler at bruge UTF-8 som almindelig kodning for projekter, der ikke bruger et strings bibliotek.


Men kodning er ikke det eneste spørgsmål, du skal besvare.


Der er sådanne ting som normalisering. For at sige det enkelt kan nogle bogstaver være repræsenteret på flere måder - som en glyph eller som en kombination af forskellige glyfer. Det fælles problem med dette er, at de fleste af streng sammenligne funktioner behandler dem som forskellige symboler. Hvis du arbejder på tværs-platformsprojekt, vælges en af ​​normaliseringsskemaerne som standard, et rigtigt skridt. Dette vil spare din tid. [6]


F.eks. Hvis brugeradgangskode indeholder 'йёжиг', vil det være forskelligt repræsenteret (både i UTF-8 og UTF-16), når de er indtastet på Mac (der hovedsagelig bruger Normaliseringsformular D) og på Windows (som normalt kan lide Normaliseringsformular C). Så hvis bruger registreret under Windows med sådan adgangskode, vil det være et problem for ham at logge ind under Mac.


Derudover vil jeg ikke anbefale at bruge wchar\_t (eller bruge den kun i Windows-kode som en UCS-2/UTF-16 char type). Problemet med wchar\_t er, at der ikke er nogen kodning forbundet med det. Det er bare et abstrakt bredt char, der er større end normal char (16 bits på Windows, 32 bits på de fleste * Nix).

Andre referencer 1


Jeg bruger den samme kodning internt og normaliserer dataene ved indtastningspunktet. Dette indebærer mindre kode, mindre gotchas og giver dig mulighed for at bruge det samme krydsplatformsbibliotek til strengbehandling.


Jeg bruger unicode (utf-16), fordi det er enklere at håndtere internt og skal fungere bedre på grund af den konstante længde for hver karakter. UTF-8 er ideel til udgang og lagring, fordi det er baglæns kompatibelt med latin ascii og unikt bruger 8 bit til engelske tegn. Men indenfor programmet er 16-bit lettere at håndtere.

Andre referencer 2


C + + 11 giver de nye strengtyper u16string og u32string. Afhængigt af den støtte, som dine kompileringsversioner leverer, og den forventede forventede levetid, kan det være en ide at forblive forenelig med dem.


Bortset fra det er det sandsynligvis det bedste skud på tværs af platformskompatibilitet at bruge ICU-biblioteket. [7]

Andre referencer 3


Dette synes at være ret oplysende om emnet. http://www.utf8everywhere.org/[8]

Andre referencer 4


Programmering med UTF-8 er vanskelig som længder og forskydninger er blandet op. f.eks.


    std::string s = Something();
    std::cout << s.substr(0, 4);


finder ikke nødvendigvis de første 4 tegn.


Jeg ville bruge hvad en wchar\_t er. På Windows bliver UTF-16. På nogle * nix platforme kan det være UTF-32.


Når jeg gemmer til en fil, vil jeg anbefale at konvertere til UTF-8. Det gør ofte filen mindre, og fjerner eventuelle platformafhængigheder på grund af forskelle i sizeof(wchar\_t) eller til byteordre.