Wiki-kopiopeilipalvelin

Tämä on pascal.chatin wikin peilipalvelin. Muokkaus, historia ja kirjautuminen ovat siellä.

UTF8 strings and characters/fi

English · Suomi · Русский

UTF-8 merkit ja merkkijonot

UTF-8:n kauneus

Tavut joiden ylin bitti on '0' (0xxxxxxx) on varattu ASCII- yhteensopiville yhden tavun merkille. Monitavuisilla 1: n lukumäärä ensimmäisessä tavussa määrää koodin tavujen tavujen määrän. Esimerkit :

Merkistökoodaus UTF-8:n suunnittelussa on joitain etuja verrattuna muihin koodauksiin:

Kuitenkin tämä taaksepäin yhteensopivuus ei ulotu koodiin, koska koodia on käsiteltävä niin että vältetään utf8-merkkijonoja.

Huomaa, että UTF-16: ssä on samanlaisia ​​eheysominaisuuksia. (D800-alue signaalit ensin korvikkeena, DC00-alue signaalit toissijaisen korvaavan osan)

Esimerkit

Yksinkertainen iterointi merkkien yli ikään kuin merkkijono olisi joukko yhtä suuria elementtejä ei toimi Unikoodissa. Tämä ei ole pelkästään UTF-8: lle ominaista, Unicode-standardi on monimutkainen ja sana "merkki" on epäselvä. Jos halutaan iteroida UTF-8-merkkijonon merkkejä, on periaatteessa kaksi tapaa:

Alimerkkijonon etsiminen

UTF8: n erityisluonteen vuoksi voit yksinkertaisesti käyttää tavanomaisia ​​merkkijonofunktioita alimerkkijonon etsimiseen. Kelvollisen UTF-8-merkkijonon etsiminen Pos: lla palauttaa aina oikean UTF-8 tavun paikan:

pascal
uses LazUTF8;
...
procedure Where(SearchFor, aText: string);
var
  BytePos: LongInt;
  CodepointPos: LongInt;
begin
  BytePos:=Pos(SearchFor,aText);
  CodepointPos:=UTF8Pos(SearchFor,aText);
  writeln('The substring "',SearchFor,'" is in the text "',aText,'"',
    ' at byte position ',BytePos,' and at codepoint position ',CodepointPos);
end;

Etsi ja kopioi

Toinen esimerkki siitä, miten Pos (), Copy () ja Length () toimivat UTF-8: n kanssa. Tällä toiminnolla ei ole koodia käsitellä UTF-8-koodausta, mutta se toimii aina voimassa olevan UTF-8-tekstin kanssa.

pascal
function SplitInHalf(Txt, Separator: string; out Half1, Half2: string): Boolean;
var
  i: Integer;
begin
  i := Pos(Separator, Txt);
  Result := i > 0;
  if Result then
  begin
    Half1 := Copy(Txt, 1, i-1);
    Half2 := Copy(Txt, i+Length(Separator), Length(Txt));
  end;
end;

Iterointi merkkijonon yli etsien ASCII merkkejä

Jos halutaan vain etsiä merkkejä ASCII-alueella, voidaan käyttää Char-tyyppiä ja verrata Txt[i] -muotoon aivan kuten aiemmin tehtiin. Useimmat jäsentimet tekevät niin ja ne toimivat yhä.

pascal
procedure ParseAscii(Txt: string);
var
  i: Integer;
begin
  for i:=1 to Length(Txt) do
    case Txt[i] of
      '(': PushOpenBracketPos(i);
      ')': HandleBracketText(i);
    end;
end;

Iterointi merkkijonon yli etsien Unikoodi merkkejä tai tekstiä

Jos halutaan löytää merkkijonossa kaikki tietyn merkin tai alimerkkijonon esiintymät niin kutsutaan PosEx()-funktiota toistuvasti.

Jos halutaan testata eri tekstiä silmukan sisällä, voidaan silti käyttää nopeata Copy() ja Length() funktiota. UTF-8-ominaisuuksia voitaisiin käyttää, mutta niitä ei tarvita.

pascal
procedure ParseUnicode(Txt: string);
var
  Ch1, Ch2, Ch3: String;
  i: Integer;
begin
  Ch1 := 'Й';  // Characters to search for. They can also
  Ch2 := 'ﯚ';  //  be combined codepoints or longer text.
  Ch3 := 'Å';
  for i:=1 to Length(Txt) do
  begin
    if Copy(Txt, i, Length(Ch1)) = Ch1 then
      DoCh1(...)
    else if Copy(Txt, i, Length(Ch2)) = Ch2 then
      DoCh2(...)
    else if Copy(Txt, i, Length(Ch3)) = Ch3 then
      DoCh3(...)
  end;
end;

Silmukkaa voidaan optimoida hyppäämällä jo käsiteltävien osien päälle.

Merkkijonon yli iterointi analysoimalla yksittäisiä koodipisteitä

Tämä koodi kopioi kunkin koodipisteen String-tyyppiseen muuttujaan, jota voidaan sitten käsitellä edelleen.

pascal
procedure IterateUTF8(S: String);
var
  CurP, EndP: PChar;
  Len: Integer;
  ACodePoint: String;
begin
  CurP := PChar(S);        // if S='' then PChar(S) returns a pointer to #0
  EndP := CurP + length(S);
  while CurP < EndP do
  begin
    Len := UTF8CodepointSize(CurP);
    SetLength(ACodePoint, Len);
    Move(CurP^, ACodePoint[1], Len);
    // A single codepoint is copied from the string. Do your thing with it.
    ShowMessageFmt('CodePoint=%s, Len=%d', [ACodePoint, Len]);
    // ...
    inc(CurP, Len);
  end;
end;

Tavujen käyttäminen yhdellä UTF8-koodipisteellä

UTF-8-koodatut koodipisteet voivat vaihdella pituudeltaan, joten paras ratkaisu niiden käyttämiseen on käyttää iteraatiota. Voidaan iteroida koodeja käyttämällä tätä koodia:

pascal
uses LazUTF8;
...
procedure DoSomethingWithString(AnUTF8String: string);
var
  p: PChar;
  CPLen: integer;
  FirstByte, SecondByte, ThirdByte, FourthByte: Char;
begin
  p:=PChar(AnUTF8String);
  repeat
    CPLen := UTF8CodepointSize(p);

    // Here you have a pointer to the char and its length
    // You can access the bytes of the UTF-8 Char like this:
    if CPLen >= 1 then FirstByte := P[0];
    if CPLen >= 2 then SecondByte := P[1];
    if CPLen >= 3 then ThirdByte := P[2];
    if CPLen = 4 then FourthByte := P[3];

    inc(p,CPLen);
  until (CPLen=0) or (p^ = #0);
end;

Pääsy N:teen UTF8-koodipisteeseen

Iteraation lisäksi voi olla myös halu päästä satunnaiseen UTF-8-koodipisteeseen.

pascal
uses LazUTF8;
...
var
  AnUTF8String, NthCodepoint: string;
begin
  NthCodepoint := UTF8Copy(AnUTF8String, N, 1);

Näytetään koodipisteet UTF8CodepointToUnicode-ohjelmalla

Seuraavassa on esimerkki siitä, miten kunkin koodipisteen 32 bittisen koodipisteen arvo näytetään UTF8-merkkijonona:

pascal
uses LazUTF8;
...
procedure IterateUTF8Codepoints(const AnUTF8String: string);
var
  p: PChar;
  unicode: Cardinal;
  CPLen: integer;
begin
  p:=PChar(AnUTF8String);
  repeat
    unicode:=UTF8CodepointToUnicode(p,CPLen);
    writeln('Unicode=',unicode);
    inc(p,CPLen);
  until (CPLen=0) or (unicode=0);
end;

Hajotetut merkit

Unicoden epäselvyyden vuoksi vertailufunktioissa ja Pos() saattaa näkyä odottamatonta käyttäytymistä, kun esimerkiksi yksi merkkijono sisältää hajonneita merkkejä, kun taas toinen käyttää samaan kirjaimeen suoria koodeja. RTL ei käsittele sitä automaattisesti. Se ei ole mikään koodaus, mutta yleensä Unicode.

macOS

FileUtil-yksikön tiedostotoiminnot huolehtivat myös Mac OS X - käyttöjärjestelmäkohtaisesta käyttäytymisestä: OS X normalisoi tiedostonimet. Esimerkiksi filename 'ä.txt' voidaan koodata Unicodessa kahdella eri sekvenssillä (#$C3#$A4 ja 'a'#$CC#$88). Linuxissa ja BSD:ssä voidaan luoda tiedostonimi molemmilla koodauksilla. OS X muuntaa automaattisesti umlaut kolmelle tavujärjestykselle. Tämä tarkoittaa:

pascal
if Filename1 = Filename2 then ... // is not sufficient under OS X
if AnsiCompareFileName(Filename1, Filename2) = 0 then ... // not sufficient under fpc 2.2.2, not even with cwstring
if CompareFilenames(Filename1, Filename2) = 0 then ... // this always works (unit FileUtil or FileProcs

Katso myös


From the Free Pascal wiki, page "UTF8 strings and characters/fi", as it stood on 2020-03-04 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Versio 1, viimeksi muokannut WikiArchive .