Písmena s diakritikou

Emin farmářský obchod teď prodává i dýně a pšenici a takové názvy potřebují zvláštní péči. Tady je proč.

Počítač ukládá text jako řadu bajtů, malých čísel od 0 do 255. Texty ve vašich programech jsou, stejně jako většina textů na světě, v kódování UTF-8: každé písmeno anglické abecedy, každá číslice, mezera i interpunkce zabírá jeden bajt, ale písmeno s diakritikou, třeba č nebo ý, zabírá dva (a některé znaky, třeba emoji, dokonce čtyři). Funkce pro řetězce v Lua o písmenech nevědí nic: počítají a stříhají bajty. V textu bez diakritiky je jeden bajt jeden znak, takže si ničeho nevšimnete. S diakritikou ano, a to na čtyřech místech.

1. Délka. # i len počítají bajty. Znaky spočítá utf8.len z knihovny utf8, kterou Lua má právě na tohle:

local slovo = "dýně"
print(#slovo, slovo:len(), utf8.len(slovo))

Vypíše:

6	6	4

2. Velká a malá písmena. upper a lower mění jen písmena od a do z; písmena s diakritikou nechají, jak jsou:

print(("farma Slunečnice"):upper())
print(("ŘEPA"):lower())

Vypíše:

FARMA SLUNEčNICE
Řepa

Když takové slovo potřebujete velkými písmeny, napište ho tak rovnou do kódu: "SLUNEČNICE".

3. Stříhání. Pozice v sub jsou také bajty. V "dýně" zabírá ý pozice 2 a 3, takže první dvě písmena jsou sub(1, 3) a sub(1, 2) rozstřihne ý v půlce:

local slovo = "dýně"
print(slovo:sub(1, 3))
print(slovo:sub(1, 2))
print(slovo:sub(1, 2) == "dý")

Vypíše:

dý
d�
false

Polovina písmena není žádný znak, a tak se místo ní vypíše �. Totéž platí pro reverse, který prohodí dva bajty každého písmena s diakritikou: ("dýně"):reverse() vrátí ��n��d. Bezpečně můžete stříhat na pozicích, které vám dal find (to jsou také bajty), a se zápornými pozicemi, když konec textu diakritiku nemá.

4. Šířky. %-10s doplní text na 10 bajtů, takže slovo dostane o mezeru méně za každé písmeno s diakritikou:

print(("%-10s|"):format("mrkev"))
print(("%-10s|"):format("dýně"))

Vypíše:

mrkev     |
dýně    |

Pomůže doplnit mezery ručně: tolik, kolik je šířka mínus počet znaků. Udělá to malá funkce:

local function doplnit(text, sirka)
    return text .. (" "):rep(sirka - utf8.len(text))
end

print(doplnit("mrkev", 10) .. "|")
print(doplnit("dýně", 10) .. "|")

Vypíše:

mrkev     |
dýně      |

Když je text delší než šířka, vyjde počet záporný a rep vrátí prázdný text, takže se nic neořízne, stejně jako u %-10s.

Stejný problém s diakritikou mají i vzory v dalším cvičení; uvidíte ho tam. Pravidlo pro všechno: vypisovat, spojovat a hledat texty s diakritikou můžete vždy bez obav. Když počítáte, stříháte, zarovnáváte nebo měníte velikost písmen, myslete na bajty.

Pokyny

Spusťte program: dva řádky seznamu jsou posunuté. Abyste viděli proč, přidejte nad seznam samostatný cyklus, který vypíše počet znaků každého názvu, spočítaný pomocí utf8.len:

mrkev: 5
dýně: 4
pšenice: 7

Teď seznam opravte. Místo %-10s doplňte každý název mezerami na 10 znaků sami, pomocí rep a utf8.len; hmotnost zůstane formátovaná pomocí %6.2f. Seznam se srovná:

mrkev       12.50 kg
dýně        30.00 kg
pšenice      6.75 kg

Začněte programovat zdarma

Registrací souhlasíte s provozními podmínkami a zásadami ochrany osobních údajů.

Nebo se registrujte pomocí:

5/9