Já jsem si říkal, sice bez diakritiky, ale na puberťáka to vyjadřování moc nevypadá. Je dobře že se tu trochu zvedne věkový průměr.
Ale jinak bych dal přednost tykání, ono je to na Internetu zvykem, zvlášť že člověk nemůže dostat facku když se splete
(To mi připomnělo jak v jedné diskuzi u Fuxofta slavný troll Ross Hedvíček sjel puberťáky za to že mu tykají. Prohlásil něco takového:
"Já můžu tykat Fukovi, protože je mi dvakrát tolik co jemu, a Fuka může tykat vám, protože je mu dvakrát tolik co vám.")
Tak největší problém je tohle:
if (ch== 'ě')! Tak to zaručeně nepůjde, protože UTF-8 nemá pevnou délku znaků
To jsou právě ty dva inty (ve skutečnosti jen bajty) co se načtou, třeba v azbuce nebo čínském písmu by mohly být tři i čtyři. Teroreticky by jich mohlo být dokonce až šest, ale v Unicode je teď definovaných něco přes sto tisíc znaků, takže ty zbývající dvě miliardy kombinací se 'zatím' nepoužívají.
To je rezerva pro Klingonce, Vulkánce a další
Princip UTF-8 je jednoduchý. Pokud je znak obsažený v ASCII, tedy sedmibitový s nulou v nejvyšším bitu, stačí na jeho zakódování jeden bajt. Na tom nejvíc vydělávají anglicky mluvící země, sežere jim to nejméně paměti (zato Číňané z toho pochopitelně tak nadšení nejsou). Vyšší znaky s diakritikou (s kódy 128-255), které se dřív měnily v různých národních kódových stránkách, mají v nejvyšším bitu jedničku, a kódují se posloupností několika bajtů.
První bajt začíná (myšlen je nejvyšší bit) jedničkou, za níž následuje jedna až pět jedniček, a nula. Jedna až pět jedniček odpovídá jednomu až pěti následujícím bajtům. Zbytek prvního bajtu jsou datové bity.
Další bajty začínají vždy jednou jedničkou a nulou, a potom jsou další datové bity. Tak je možné jednoduše kontrolovat jestli proud dat není poškozený - pokud někde cestou jeden bajt vypadne, nesedí počty těch jedniček a následujících bajtů.
Těch datových bitů tedy může být dohromady jednatřicet. Na Wiki je pěkná tabulka která to vysvětluje ještě lépe:
http://cs.wikipedia.org/wiki/UTF-8Z toho vyplývá že znak v UTF-8 je vlastně řetězec, a je třeba ho načítat do pole, ne do obyčejné proměnné! A porovnávat nebo kopírovat se potom musí také pomocí funkcí pro práci s řetězci, které jsou ve <string.h>. Ale to budeme řešit až později, teď je potřeba rozchodit ty curses.
Pro začátek to nejjednodušší, spuštění a ukončení curses, vstup a výstup jednoho znaku podle stisknuté klávesy:
(kód programu je dobré zvýraznit tlačítkem Code nad editorem, ono se to pak lépe čte)Kód: Vybrat vše
#include <stdio.h>
#include <ncurses.h>
#include <string.h>
int main(void)
{
int c=0; /* pro jistotu inicializace hned v deklaraci */
/* přepneme terminál na curses */
initscr();
cbreak(); /* vypneme bufferování */
noecho(); /* a výpis znaku na vstupu */
/*********************************
* teď můžeme experimentovat *
*********************************/
/*** psací stroj - ukončení Escape ***/
while (27!=c) /* až do Escape */
{
c=getch(); /* vstup znaku */
if ('\n'==c) putchar('\r'); /* při Enter nejdřív návrat na začátek řádku */
putchar(c); /* výstup znaku se nezobrazí hned */
refresh(); /* dokud se neobnoví okno */
}
printf("\r\n_Zdrhám odsud!\r\n"); /* pozor na odřádkování CR LF a mizející první znak po Escape*/
refresh(); /* je potřeba zase obnovit okno aby se text zobrazil */
/*** potom přijde další experiment ***/
while (27!=(c=getch())); /* na konci opět počkáme na Escape */
/*** uklidíme po sobě a vypneme curses ***/
erase();
refresh();
endwin();
/*** teď už zase fungují standardní funkce normálně a vypisují hned ***/
printf("A to je konec!\n");
return 0;
}
Je tam pár háčků, například ten refresh(). Curses fungují tak, že simulují virtuální obrazovku, což je to hlavní okno, a veškeré výpisy se ukládají do dvourozměrného pole znaků. To je kromě jiného mnohem rychlejší než každý znak okamžitě samostatně čmárat, veškeré provedené změny se projeví až po refreshi, tím se celé pole najednou zobrazí. Je to vlastně také takový buffer, akorát že ten klasický ve <stdio.h> je jen řádkový.
Ten mizející znak po vypsání Escape by se dal vyřešit snadno, stačilo by tam mít klasické Céčkové
while (27!=(c=getch())), tím by také odpadla potřeba té počáteční inicializace nulou. Takhle jsem to udělal kvůli těm komentářům.
Teď to funguje tak, že se čtou jednotlivé znaky ze vstupu, a hned se zase jednotlivě vypisují. Znaky s diakritikou a další vícebajtové potvory se načtou a vypíšou naněkolikrát. Vypíše se všechno co se zmáčkne, tedy všechny alfanumerické klávesy. Ty ostatní (třeba šipky) se při čtení chápou jako escape sekvence, takže ten program ukončí!
Vyhovuje to takhle pro začátek? Že bysme začali řešit ty řetězce.
Jinak pěkný úvod do curses je tady:
http://www.linux.cz/noviny/1998-1112/clanek11.html Jsou tam i kouzla s barvičkami a funkčními klávesami, ovládáním kurzoru a podobně. Pak klasicky
man curses, akorát že to je anglicky.
K té inteligenci - před časem jsem v tom podpisu měl jinou hlášku:
"Suma inteligence je konstatní, populace roste." Je nás prostě moc
Euler byl borec, a spousta dalších (můj oblíbený Babbage), nebýt jich a jim podobných, tak dneska plácáme placky na plochém šutru a zapíjíme je kyselým mlékem.
P.S. Kompilovat a současně spouštět kompilovaný program není úplně bezpečný postup, radši to provádím postupně:
rm a.out;gcc -ansi -pedantic -Wall -lncurses znak.c;./a.outNejdřív smažu předchozí výsledek, tím se mi nespustí pokud kompilace skončí errorem. Pak to zkompiluji a nakonec spustím, proto ty středníky mezi příkazy.