Kurzusok
/
Julia
Julia
/
Tanterv
/
Karakterek
Ka

Karakterek ebben a kurzusban: Julia

4 feladat

A(z) Karakterek fogalomról

Ez egy nagy téma! Lehetne róla egy hosszú könyvet írni, és többen meg is tették (keress rá az Amazonon az „unicode book” kifejezésre, hogy láss néhány példát).

Egy nagyon rövid történelem

A karakterek kezelése a számítógépekben sokkal egyszerűbb volt a korábbi évtizedekben, amikor a programozók azt feltételezték, hogy az angol az egyetlen fontos nyelv. Szóval: 26 betű, kis- és nagybetű, 10 számjegy, néhány írásjel, plusz egy kód (0x07) a csengő megszólaltatásához, és mindez elfért 7 bitben: ez az ASCII karakterkészlet.

Természetesen az emberek elkezdték kérdezni, mi a helyzet az à, ä és Ł karakterekkel, aztán mások az ऄ, ஹ és ญ jelekről kezdtek kérdezni, a fiatalok pedig emojikat akartak 😱. Mit tegyünk?

Hogy rövidre fogjuk: sok okos és türelmes embernek évekig bizottságokban kellett ülnie, hogy kidolgozza a Unicode karakterkészlet és az olyan kódolások, mint a UTF-8 részleteit, és rengeteg szoftvert kellett nagyon bonyolultan újraírni. Ráadásul rengeteg új bug is bekerült.

Hogy ne minden törjön el, a Unicode/UTF-8 kialakítása gondoskodik róla, hogy az első 127 kód megegyezzen az ASCII-vel (a csengőt is beleértve).

Karakterek a Julia nyelvben

A nagyjából 2005 után tervezett nyelveknek hatalmas előnyük, hogy már létezett egy viszonylag stabil Unicode-szabvány.

A Julia (első kiadása 2012-ben) abból indulhatott ki, hogy minden Unicode lesz: a karakterek, a stringek, a változó- és függvénynevek, a matematikai operátorok...

A kézikönyvet idézve: „A Julia egyszerűen és hatékonyan kezeli a sima ASCII-szöveget, a Unicode kezelése pedig a lehető legegyszerűbb és leghatékonyabb.” Figyeld meg a „a lehető” részt, ez a megfogalmazás fontos eleme.

A karakterliterálokat aposztrófok közé írjuk, és megkülönböztetjük őket az idézőjelek közé írt stringektől.

Ez nyilvánvaló a C/C++ világából érkezőknek, a Python és Javascript programozóknak viszont zavaró lehet.

julia> a = 'a'  # Roman alphabet
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)

julia> typeof(a)
Char

julia> jha = 'झ'  # Devanagari alphabet
'झ': Unicode U+091D (category Lo: Letter, other)

julia> typeof(jha)
Char


julia> '❤'  # heart emoji
'❤': Unicode U+2764 (category So: Symbol, other)

A példákból láthatjuk, hogy a típus Char, és a Julia további információkkal szolgál a karakter kategóriájáról.

Közelebbről megnézve úgy tűnik, hogy ezek a karakterek 4 hexadecimális számjeggyel ábrázolhatók. A teljes karakterkészlethez akár 6 hexadecimális jegy is kell.

Ezeket a számokat „kódpontoknak” nevezik, és jelenleg U+0000-tól U+10FFFF-ig terjednek. A REPL-ben megjelennek, a kódban viszont a codepoints() függvénnyel kérheted le őket.

A Char és az Int közötti átalakítás egyszerű:

julia> Int('a')
97

julia> Char(97)
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)

A fordító a Char értékeken az egészszám-aritmetika néhány formáját engedélyezi:

julia> 'b' - 'a'  # interval, in alphabetic order
1

julia> 'b' + 'a'
ERROR: MethodError: no method matching +(::Char, ::Char)

julia> 'a' + 5
'f': ASCII/Unicode U+0066 (category Ll: Letter, lowercase)

julia> 'f' + ('A' - 'a')  # same as `uppercase('f')`
'F': ASCII/Unicode U+0046 (category Lu: Letter, uppercase)

Függvények karakterekhez

A stringkezelő függvények egy része Char bemeneten is működik.

  • A megfelelő ábécék esetében válts kis- és nagybetűt az uppercase() és a lowercase() függvénnyel.
  • Vizsgáld a kis- és nagybetűs írásmódot az isuppercase() és az islowercase() függvénnyel.
  • Vizsgáld a karakter típusát ezekkel:
    • isletter(), sok ábécét lefed
    • isdigit(), szigorúan a 0:9 tartományt vizsgálja
    • isnumeric(), tágabb, mint az isdigit, ezért true a ¾-re és több nem európai írásrendszerre is
    • isxdigit(), hexadecimális számjegyek
    • isascii(), Unicode előtti karakter
    • ispunct(), írásjel
    • isspace(), bármilyen whitespace-karakter
    • isprint(), nyomtatható karakterek (az ellentéte az iscntrl())
islowercase('A')  # false
uppercase('γ')  # 'Γ': Unicode U+0393 (category Lu: Letter, uppercase)
ispunct('@')  # true
isdigit('A')  # false
isxdigit('A')  # true

Annak ellenőrzésére, hogy egy karakter szerepel-e egy stringben, az in operátort használhatjuk. Figyeld meg, hogy ez eltér a részstringek vizsgálatától:

# char search
julia> 'a' ∈ "xabcahliazlnkiw"
true

# substring search
julia> "a" ∈ "xabcahliazlnkiw"
use occursin(needle, haystack) for string containment

A reguláris kifejezések (amelyekről egy másik fogalom szól) szintén hatékony keresést és módosítást tesznek lehetővé.

Char vektorok és stringek közötti átalakítás

Stringből Char-vektorba a collect() függvénnyel juthatunk.

Char-vektorból stringbe a String() konstruktorral.

julia> s = "abcde"
"abcde"

julia> cv = collect(s)
5-element Vector{Char}:
 'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
 'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
 'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase)
 'e': ASCII/Unicode U+0065 (category Ll: Letter, lowercase)

julia> String(cv)
"abcde"

Ez bármilyen karakterrel működik, nem csak ASCII-vel.

julia> collect("❤,😱")
3-element Vector{Char}:
 '❤': Unicode U+2764 (category So: Symbol, other)
 ',': ASCII/Unicode U+002C (category Po: Punctuation, other)
 '😱': Unicode U+1F631 (category So: Symbol, other)

Figyeld meg, hogy a String() konstruktor egy vektoron működik. Ahhoz, hogy egyetlen Char-t egykarakteres stringgé alakíts, a string() függvény kell, kisbetűs s-sel.

julia> string('a')
"a"

Tárolás

A dokumentumban eddig minden viszonylag egyszerűnek tűnik, szóval tényleg nincs miért aggódni?

Sajnos ez túl optimista!

Az egyik bonyodalom abból adódik, hogy kódpontonként „akár” 6 hexadecimális jegyre lehet szükség. Ez azt jelenti, hogy UTF-8 kódolás esetén a különböző karakterek különböző mennyiségű memóriát foglalnak.

Egy byte csak legfeljebb 255-ig, azaz két hexadecimális jegyig tud (előjel nélküli) számokat tárolni, ezért a UTF-8 változó számú byte-ot (1-4) használ egy Char tárolására. Ezeket „kódegységeknek” nevezik, és az ncodeunits() függvény adja vissza, mennyi kell egy adott karakterhez.

julia> codepoint(jha)  # jha 'झ' is defined in an earlier example
0x0000091d

julia> ncodeunits(jha)
3

julia> ncodeunits('a')  # ASCII character
1

julia> ncodeunits('😱')  # emoji
4

Ráadásul nem minden, a képernyőn megjeleníthető dolognak van saját egyedi kódpontja. Néhány vizuálisan elkülönülő karaktert másokból származtatottnak tekintenek, ezért a Unicode egy szülőkarakter és egy módosító kombinációjaként kezeli őket.

Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg

Tanuld meg a(z) Karakterek fogalmat

A gyakorlás zárolva

Oldj fel még 3 feladatot, hogy gyakorolhasd a(z) Karakterek fogalmat