čtení znaku s diakritiku z konzole bez echa a entru

Místo pro dotazy a rady ohledně programovacích jazyků (C++, C#, PHP, ASP, Javascript, VBS..) a tvorby webových stránek

Moderátor: Mods_senior

xerostomus
nováček
Příspěvky: 7
Registrován: březen 14
Pohlaví: Nespecifikováno
Stav:
Offline

čtení znaku s diakritiku z konzole bez echa a entru

Příspěvekod xerostomus » 14 bře 2014 22:57

Vazeni panove,
mam větší problém, než jsem čekal. Chtěl jsem v C či C++ napsat jednoduchý zkoušecí program:
V terminalu v Linuxu se objevi instrukce:
Opište slovo: řečiště
student napíše
řeči
ale pak misto š zmacne s.
Tak ted je treba, aby to nic nenapsalo na terminal.
Tedy potrebuji, aby to cetlo česke znaky bez entru a bez echa. zkontrolovalo znak a kdyz je spravny, tak vypsalo na monitor.
Pokud mozne ne keycodes ci jine harakiri.

Zkoušel jsem nejjednodušší wchar programy a nefungovaly pod gcc, lubuntu 13.10 korektne:
#include <stdio.h>
#include <wchar.h>

int main ()
{
wchar_t wc;
fputws (L"Enter text. Include a dot (.) in a sentence to exit:\n",stdout);
do {
wc=getwchar();
putwchar (wc);
} while (wc != L'.');
return 0;
}
Jednak procesor je v te smyčce na 100 %
po zkompilovani to jelo takto divne:
Enter text. Include a dot (.) in a sentence to exit:
a
a //correctly repeated twice // spravne opsalo pismeno a
s
s
d
d
ě //stopped echoing on wide characters //přestalo vypisovat druhe pismeno
š
č
a //echoing is still off // stale to nepremava... :-((
s
d
. //event dot is not terminating //tecka, dot, bodka ani nekuda to neukonci.
.
.
.
.
^C //I had to kill it //musel jsem to krute ubit k smrti
Tak ted babo rad, co s tim...
diky
xerostomus

Reklama
Uživatelský avatar
faraon
Master Level 8.5
Master Level 8.5
Příspěvky: 7366
Registrován: prosinec 10
Pohlaví: Muž
Stav:
Offline

Re: čtení znaku s diakritiku z konzole bez echa a entru

Příspěvekod faraon » 15 bře 2014 10:46

Vítej na PC-help.

Hlavní problém je v tom, že netestuješ návratovou hodnotu getwchar(). Ta funkce v případě neúspěchu vrací WEOF, což je prostě -1, a nečitelný znak nechá v bufferu, takže na něj při příštím čtení zase narazí. To je důvod proč se už nikdy k té tečce nedostaneš.
Já jsem nikdy wchar nepoužíval, protože jsou určené pro omezené šestnáctibitové UTF-16 ve Widlích, zatímco Linux (až na pár vykopávek) už jede v UTF-8, které zvládá jedenatřicetibitové znaky (v něm také fungují normálně klasické funkce jako getchar()), takže se to pere mezi sebou. Navíc to dělá problémy při binárním ukládání, protože v Linuxu je wchar_t dvaatřicetibitový!

Vzhledem k tomu že C-jazyky nehlídají chyby vzniklé při běhu, je potřeba aby si je programátor ohlídal sám. S tím mají pochopitelně značný problém dnešní "moderní" javovské kódovací opice a podobné nedokvašky, spoléhající na try a catch... Tak jsem ti ten program upravil tak, aby zvládl překlopýtat chybný vstup:

Kód: Vybrat vše

#include <stdio.h>
#include <wchar.h>



int main ()
    {
    wchar_t wc;

    fputws (L"Enter text. Include a dot (.) in a sentence to exit:\n",stdout);
    do {
       if ((wc=getwchar()) != WEOF)
          {
          putwchar (wc);
          }
       else
          {
          getchar();
          }
       } while (wc != L'.');

    return 0;
    }


Dál je tu poznámka pod tím programem, z překladače mi vypadlo: "Jednoduchý psací stroj. Každá věta se ozývá, jakmile stisknete klávesu ENTER, dokud tečka (.) Je zahrnut v textu."
Takže tímhle stylem psací stroj určitě neuděláš, nejlepší způsob (a samozřejmě přenositelný) jak dosáhnout toho co jsi chtěl je knihovna ncurses.

No a nakonec je potřeba odstranit ty problémy tam kde začaly, aby program zvládl i ty znaky s diakritikou. Toho se dosáhne lokalizací, aby se knihovna wchar přizpůsobila aktuálně nastavenému kódování. S tím mají problém zase příchozí z Windoze, protože tam se to nedělá. Každá instalace je napevno zkompilovaná pro konkrétní jazyk a konkrétní znakovou sadu, není možné je měnit. Naopak Linuxu jsou takové věci u (_!_), protože v něm se tohle nastavuje za běhu, nejprve pomocí konfiguračních skriptů, a i potom se to dá libovolně přepínat. Každý program se pak může sám hodit do správného jazyka podle nastavení locales.
A to ty můžeš v tom programu mírně prasecky ošetřit příkazem setlocale(LC_ALL, ""); z knihovny locale.h, ale s tím už si zkus poradit sám ;-)
"Král Lávra má dlouhé oslí uši, král je ušatec!

(pravil K. H. Borovský o cenzuře internetu)

xerostomus
nováček
Příspěvky: 7
Registrován: březen 14
Pohlaví: Nespecifikováno
Stav:
Offline

Re: čtení znaku s diakritiku z konzole bez echa a entru

Příspěvekod xerostomus » 15 bře 2014 22:05

Vazeny pane Faraone,

mockrat dekuji, jak za program, tak za vysvetleni. Osobne nijak na wchar.h nelpim, ale vyzkousel jsem asi dvacet zpusobu a zadny nedela to, aby to spolehlive precetlo zmacknutou klavesu a vyhodilo dlouhy znak. Ja jsem na lubuntu, takze UTF8 je optimalni znakova sada. Rad si necham poradit, v jake knihovne to mam naprogramovat. Ale nefuntovalo mi nic.
Ja to mam naprogramovane v Libreofficu - ale tam to nestiha interpret, tak jsem si rekl, udelam si to v kompilatoru. Zahorel jsem na nejprimitivnejsi veci - precti znak na vstupu a podle toho jestli je spravny, tak by ho mel program zobrazit nebo ne.

//gcc -o pokus pokus.c -lncurses && ./pokus
#include <ncurses.h>
int main()
{
int ch;
initscr();
cbreak();
noecho(); // funguje - vypina nutnost klavesy enter a nevypisuje nic na konzolu
printw("zmáčkněte nějaký ten čudl:\n "); //toto se vypíše i pres noecho(), ale diakritiku to poničí
do {
noecho(); // funguje - vypina nutnost klavesy enter a nevypisuje nic na konzolu
ch = getch(); //funguje jen na obyčejné ascii
echo();
// printw("\n%c - %d\n", ch, ch);
if (ch== 'ě') printw(" bingo je to ě ");/nebo € nebo ščřž nebo שדגכ nebo cokoli divnýho
printw(" - %c - %d | ", ch, ch);
} while (ch!='.');
printw("no dobrá, tak konec\n");
getch();
endwin();
return 0;
}


Tohle jsem zkousel uz davno, je to blizko tomu, co bych potreboval, ale diakritiku to totalně zprasi, getch nenačte znak s diakritikou, ale postupne po sobe nejake dva integery, se kterymi si tak jako tak nevim rady.
Proste potrebuju funkci, ktera vrati znak s diakritikou, co je zmacknut. pak porovna se predlohou. Kdyz ok, zobrazi. Nic, co by to dokazalo, jsem nedokazal rozchodit. Jinak nepotrebuju zadnou přenositelnost - opustil jsem windows , abych se uz nikda nevratil...

Ani to Vase nezobrazovalo znaky s diakritikou.
Takze, kdybyste mi dokazal s timto pomoci, byl bych rad.
diky
Xerostomus

PS. k te inteligenci. Problem inteteligentu je, ze se nijak vyrazne nemnozi. Takze evoluce ma problem - jak skloubit inteligenci a upornou touhu po velke rodine. Kdyby inteligenti byli inteligentni alespon jako Euler, tak bychom byli vyrazne dal:
Leonhard Euler (18. století) a jeho 13 dětí, které mu kupodivu stejně jako slepota nebránily v kariéře
Během jejich manželství měli třináct dětí, ale jen pět z nich se dožilo dospělosti. Euler později uvedl, že některé ze svých největších objevů učinil s dítětem v náručí a dalšími dětmi kolem sebe. Je neuvěřitelné, že téměř polovinu své vědecké práce Euler vytvořil po svém návratu do St. Petersburgu, i když byl slepý. Euler by samozřejmě nemohl nikdy dosáhnout takových výsledků, nebýt pomoci jeho synů a členů akademie.
18. září 1783 Euler strávil první polovinu dne jako obvykle. Věnoval hodinu matematiky jednomu ze svých vnoučat, provedl několik výpočtů o pohybu balónů křídou na dvou tabulích, pak diskutoval s Lexellem a Fussem o nedávném objevu planety Uran. Kolem páté hodiny odpoledne ho postihlo krvácení do mozku a řekl jen "umírám", než ztratil vědomí. Zemřel kolem jedenácté hodiny večer.
Euler byl nejproduktivnějším autorem textů z matematiky všech dob. Posunul hranice studia analytické geometrie a trigonometrie, kde jako první zavedl funkce sinus, cosinus a další.
Podle The MacTutor History of Mathematics Archive. Turnbull University of St Andrews

Uživatelský avatar
iTerminator
Level 1.5
Level 1.5
Příspěvky: 132
Registrován: únor 14
Pohlaví: Muž
Stav:
Offline

Re: čtení znaku s diakritiku z konzole bez echa a entru

Příspěvekod iTerminator » 16 bře 2014 00:19

Jseš snad první, kterej takhle poděkoval :D.
... na co jsem se v Nette podíval a co by většina programátorů napsala špatně, to bylo správně, vzorově. - Jakub Vrána

Do SZ mi píšete zbytečně, neboť problémy řeším pouze v tématech.
Za radu je slušné poděkovat.
Važ si rady, práci za tebe neudělám.

Používej Google!

xerostomus
nováček
Příspěvky: 7
Registrován: březen 14
Pohlaví: Nespecifikováno
Stav:
Offline

Re: čtení znaku s diakritiku z konzole bez echa a entru

Příspěvekod xerostomus » 16 bře 2014 07:55

To vite, stara skola...
:-)
xs

Uživatelský avatar
faraon
Master Level 8.5
Master Level 8.5
Příspěvky: 7366
Registrován: prosinec 10
Pohlaví: Muž
Stav:
Offline

Re: čtení znaku s diakritiku z konzole bez echa a entru

Příspěvekod faraon » 16 bře 2014 10:53

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 :oops:
(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ů :-o
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ší :lol:

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-8

Z 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 8)
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.out
Nejdří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.
"Král Lávra má dlouhé oslí uši, král je ušatec!

(pravil K. H. Borovský o cenzuře internetu)

xerostomus
nováček
Příspěvky: 7
Registrován: březen 14
Pohlaví: Nespecifikováno
Stav:
Offline

Re: čtení znaku s diakritiku z konzole bez echa a entru

Příspěvekod xerostomus » 16 bře 2014 20:09

Vazeny pane Faraone,

opet starosvetsky podekuji. :-)

S tim tykanim, to udelame tak, ze ja Vam budu vykat a vy mne muzete tykat. Ja mam problem jen tak tykat cizim lidem. :-)
Jinak na priklad s tykanim na pracovisti nemam dobre zkusenosti. Zvlaste pokud pracujete ve velkem kolektivu (>50 lidi).
Nikdy nevite, komu vykate, komu tykate, pak se nekdo urazi, ze mu drze tykate... Proste nejlepsi je vsem vykat a jet
podle pravidla, s tim z mych kolegu, se kterym si tyka moje zena a deti, tak s tim si tykam taky. :-)

Tak postupne -
- najednou to chce enter. psaci stroj nevyzaduje enter po kazdem pismenu.
- prikaz man curses ani man ncurses nefunguje, i kdyz mam nainstalovano sudo apt-get install libncurses5-dev
- putchar(c); putchar(c); Kdyz dam dvakrat tak to nefunguje - chapu, protoze to je UTF8
- printw("€"); za putchar(c) udela totalni chaos
- printw("karel"); za putchar jaxtax funguje, ale kdyz dam vice znaku za sebe, tak to legracne skace po obrazovce (vubec to nedrzi koordinaty)...
- crlf chapu, ale je to divny v Linuxu, asi ncurses...

Já to mam opravdu jednoduche:
mam slovo řečiště, z něho vezmu znak a čekám až ho student nadatluje do počítače, když se strefí, tak mu vypíše ten znak na obrazovku, do te doby blika kurzor a nic se neděje.
To asi bude hruza pres string.h, ne? Jak ma chudak program poznat, kolik ma slovo řečiště bytu a nakolikate pozici bude písmeno š?

K te diakritice - ja jsem zacinal na 8bitech, na IQ150 a jinych vykopavkach jsem psal diplomku. Trochu jsem programoval v assembleru - rezidentni klavesnice, ale dneska je vsechno jinak a navic jsem to vsechno zapomnel.

K te inteligenci na okraj: To, co tam mate nyni, je spis odpovida realite - proste prevalence dusevnich chorob je v populaci okolo 20%, zalezi jak tvrda kriteria vezmeme. 33 % depresi je ale moc. součet dementních, debilních a alkoholiku možná dá i víc než 14%, protože nas to čeká skoro všechny... :-)
"Suma inteligence je konstatní, populace roste." - jako vtip dobry, ale matematicky to nejde, protoze prumerne IQ je definovano jako 100, tedy i kdyz cela populace zblbne, tak prumerne IQ bude 100. Proste ta stovka je plovouci, proto se to spatne porovnava mezigeneracne a mezi kulturne.

Kazdopadne preji pekny zbytek nedele. My pujdeme asi s detmi spat.
dobrou noc
jk

Uživatelský avatar
faraon
Master Level 8.5
Master Level 8.5
Příspěvky: 7366
Registrován: prosinec 10
Pohlaví: Muž
Stav:
Offline

Re: čtení znaku s diakritiku z konzole bez echa a entru

Příspěvekod faraon » 16 bře 2014 22:54

V tom případě to vykání chápu. Já jsem vždycky dělal v malých kolektivech, tam se to dá snáz uhlídat :-)

Ten program, tak jak jsem ho napsal, fungoval jako psací stroj i bez Enteru?
Žádné další vestavěné příkazy jsem už neměl v plánu použít, možná že i nějaké vhodné pro tenhle účel existují, ale jak řekl Linus: "Princip Linuxu? Udělej si sám." Takže potřebné funkce prostě vytvoříme přesně na míru.

Věcem jako printw() bych se teď úplně vyhnul, ty už jsou příliš specifické, navíc nám tady bude stačit obyčejný prinf(), už je odzkoušený a funguje dostatečně.

Práce s Céčkovými řetězci není zase tak hrozná jak se zdá, všechno je založené na logice ASCIIZ (http://en.wikipedia.org/wiki/Null-terminated_string), kde Z znamená zero na konci. Každý řetězec je pole jednobajtových číselných kódů znaků, a za posledním je uložený znak /0, neboli nula. Proto veškeré načítání, vypisování, kopírování i porovnávání řetězců probíhá v cyklu až do té nuly, rychle a efektivně. A samozřejmě bez jakékoliv další kontroly, protože Céčko nic nehlídá, to si musí obstarat sám programátor, vždy v místě kde to považuje za nutné, a jen tam, protože takové kontroly zpomalují program.

České znaky s diakritikou jsou dvoubajtové, takže se vlastně postupně načítají a zobrazují jejich poloviny. Terminálu je to jedno, ten si zobrazí až celkový výsledek, takže z toho vždycky vyjde správný znak, pokud se ho teda půlka neztratí cestou. Potom se místo vadného písmene vypíše takový divný otazník v bublině.
Slovo řečiště je při uložení do paměti zakódované takhle:

Kód: Vybrat vše

197 = ř1
153 = ř2
101 = e
196 = č1
141 = č2
105 = i
197 = š1
161 = š2
116 = t
196 = ě1
155 = ě2
0   = konec řetězce

Znak ř je zakódovaný jako 11000101 10011001, znak e jako 01100101, a tak dále. Viz ten můj popis výše.

Můj začátek byl Didaktik Gama (mám ho dodnes a také jsem se tu s ním nedávno chlubil: viewtopic.php?f=44&t=128379&p=1005718#p1005718), ale na íkvéčku bych teda psát delší text nechtěl. Ta zvonková tlačítka vypadají hrůzostrašně už na pohled, nemluvě o legendární tepelné smrti, postihující tenhle přímotop v téměř pravidelných intervalech od zapnutí.
Do assembleru jsem moc nepronikl, zato BASIC je téměř mým druhým jazykem, používám ho občas dodnes. I jednoduchý textový editor jsem si v něm tenkrát napsal, dokonce s kompletní češtinou.

Ta suma inteligence je z Murphyho zákonů, takže opravdu vtip. Ale ono to tak vypadá, že každá další generace je blbější :lol:
"Král Lávra má dlouhé oslí uši, král je ušatec!

(pravil K. H. Borovský o cenzuře internetu)

xerostomus
nováček
Příspěvky: 7
Registrován: březen 14
Pohlaví: Nespecifikováno
Stav:
Offline

Re: čtení znaku s diakritiku z konzole bez echa a entru

Příspěvekod xerostomus » 17 bře 2014 05:08

Vazeny pane Faraone,
tak nakonec jsem to spachal takto:
#include <ncurses.h>
int main(void)
{
int c=0, i=0, j=1;
char cc[5];
initscr();
cbreak();
noecho();

while (27!=c)
{
j=1;
for (i=0;i<j;i++)
{
c=getch();
cc[i]=c;
if ((c & 0xc0)==0xc0) j=2;
if ((c & 0xe0)==0xe0) j=3;
printf("i:%d, j:%d - ",i, j);
printf("O:%o - H:%x - D:%d | ",cc[i],cc[i], cc[i]);
}
cc[i]=0;
printf(cc);
printf("\r\n");
}
echo();
printf("\r\n_Zdrhám odsud!\r\n");

while (27!=(c=getch()));

erase();
refresh();
endwin();

printf("A to je konec!\n");
return 0;
}
Nejvetsi problem nebyl ani tak to nacpat do arraye, ale nelogicke chovani putchar a printf a printw, ktery to nekdy posilaji do noveho okna jindy na puvodni konzoli, jindy se to vubec nezobrazi. Takhle to vubec zadne refresh nepotrebuje - nechapu proc, najednou to funguje jako psaci stroj, tedy co uder pismeno a bez enteru. To Vase opravdu potrebovalo enter po kazde klavese nebo skupine klaves pak putchar vypsal treba pet klaves najednou.
Kazdopadne toto je zaklad, ostatni je jen rutinni programovani.

U nas IQ150 netuhlo, ale topilo fest.
Jinak assembler fungoval, zase takova hruza to neni, ale problem je, ze clovek musi rozumet tomu zelezu za tim a k tomu zadne poradne prirucky jsem nemel. Takze kdyz se reklo programovatelny radic preruseni - tak jsem jen vedel, ze mam nekam poslat nejaky byte, ale vubec jsem nevedel proc a nac. Takze proto jsem se na to vykaslal. Navic dnes residentni klavesnice jaxi nejsou na poradu dne.

JInak je pravda, ze lidi blbnou, ale neni to mnozenim, ale spis naopak. Rozvodovost = neuroticky rodiče = silene neuroticky deti, ktere nejsou schopny se zklidnit a koukat do knihy ani zplodit dalsi deti. Dale lidi jen cumi do bedny ci si facebookuji, protoze trpi dost silenou samotou. Toto jim nahrazuje spolecnost.
Kazdopadne tato civilizace je sebedestruktivni. S úhrnnou plodnosti 1,4 ditete na zenu, kdyz je třeba 2,1 ditete na zenu, se to rovna 30% ubytku populace za jednu generaci zen. Evidentne je jen otazka casu nez se to cele zhrouti. Premyslim jen jak nasmerovat vlastni deti, aby je to znicilo, co nejmene... :-(

Tak jeste jednou diky za nasmerovani Vase do UTF8. :-)
s uctou
xs

Uživatelský avatar
faraon
Master Level 8.5
Master Level 8.5
Příspěvky: 7366
Registrován: prosinec 10
Pohlaví: Muž
Stav:
Offline

Re: čtení znaku s diakritiku z konzole bez echa a entru

Příspěvekod faraon » 17 bře 2014 05:56

Odpoledne to zkusím, je divné že to nefungovalo, mě to právě tak chodilo nejlépe.

Já jsem na to šel jinak, udělal jsem si právě vlastní funkce které mi načítají celý ten "řetězec". Nejdřív rozšířená hlavička:

Kód: Vybrat vše

#include <stdio.h>
#include <ncurses.h>
#include <string.h>

#define BIGCHAR 128                         /* to je číselná hodnota toho nejvyššího bitu */

Pak načítání znaku, ekvivalent knihovní funkce getchar():

Kód: Vybrat vše

int getznak(char pole[])                    /* funkce pro načtení vícebajtového znaku */
    {
    int c,i=0;

    if ((pole[i++]=c=getch())&BIGCHAR)      /* načteme znak do proměnné, do pole, a zjistíme nejvyšší bit */
       for (c=c<<1;c&BIGCHAR;c=c<<1)        /* vyhodíme první jedničku posunem a dokud je nějaká další opakujeme */
           pole[i++]=c=getch();             /* načítání do proměnné i pole */
    pole[i]='\0';                           /* potom nesmíme zapomenout ukončit řetězec */

    return pole[0];                         /* vrátíme první znak, aby program věděl kdy má skončit */
    }

Samozřejmě je potřeba ty znaky zase nějak vypsat, takže variace na putchar():

Kód: Vybrat vše

void putznak(char pole[])                   /* funkce pro zobrazení vícebajtového znaku */
     {
     printf("%s",pole);                     /* jednoduše vypíšeme celý řetězec */
     }

A nakonec nějaké omezení, aby se zobrazovaly jen znaky ze seznamu, což je pole řetězců:

Kód: Vybrat vše

int povoleny(char pole[])                   /* funkce pro zjištění povolených znaků */
    {
    int i=0;
    char *seznam[]={"A","Á","B","C","Č","D","Ď","E","É","Ě","F","G","H","I",
                    "Í","J","K","L","M","N","Ň","O","Ó","P","Q","R","Ř","S",
                    "Š","T","Ť","U","Ú","Ů","V","W","X","Y","Ý","Z","Ž","\n"};

    for (i=0;i<(sizeof(seznam)/sizeof(*seznam));++i)
        if (!strcmp(pole,seznam[i]))        /* když se řetězce shodují dostaneme nulu */
           return 1;                        /* a vrátíme TRUE */

    return 0;                               /* jinak FALSE */
    }


A potom další verze toho psacího stroje:

Kód: Vybrat vše

int main(void)
    {
    char znak[7]={0};                       /* on si to kompilátor stejně zarovná na 8 bajtů */

    /* přepneme terminál na curses */
    initscr();
    cbreak();                               /* vypneme bufferování */
    noecho();                               /* a výpis znaku na vstupu */
    refresh();

    /*********************************
     *   teď můžeme experimentovat   *
     *********************************/

    /*** a pojedeme naostro ***/
    printf("Pouze velká písmena:\r\n");     /* pokyn pro uživatele */
    refresh();
    while (27!=getznak(znak))               /* vstup znaku a test Escape */
          {
          if ('\n'==znak[0]) putchar('\r'); /* když LF tak nejdřív CR */
          if (povoleny(znak))               /* když je znak v seznamu povolených */
             putznak(znak);                 /* vypíše se */
          refresh();                        /* obnovení okna */
          }
    printf("\r\nTo mi stačilo.\r\n");       /* odřádkování CR LF */
    refresh();                              /* obnovení okna */

    /* na konci opět počkáme na Escape */
    while (27!=getch());

    /*** 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;
    }

Večer se kouknu na to jak kontrolovat to slovo.
"Král Lávra má dlouhé oslí uši, král je ušatec!

(pravil K. H. Borovský o cenzuře internetu)

xerostomus
nováček
Příspěvky: 7
Registrován: březen 14
Pohlaví: Nespecifikováno
Stav:
Offline

Re: čtení znaku s diakritiku z konzole bez echa a entru

Příspěvekod xerostomus » 17 bře 2014 11:03

Vazeny pane Faraone,
koukam, ze na to jdete od toho shiftu, do toho jsem nesel, ja to sproste na and_oval.
Jinak jsem vyhodil i ty ncurses a vyresil to nakonec takto:

#include "jkgetch.h"
int main(void)
{
char cc[5];
int pp;
do {
printf("klavesa: ");
pp=jkgetchutf(cc);
printf("%s - počet bytů %d",cc, pp);
printf("\n");
} while (cc[0]!=27);
return 0;
}

Kde je jkgetch.h je nadefinovana takto:
#include <stdio.h>
#include <termios.h>
#include <unistd.h>

int jkgetchutf(char *c)
{
struct termios oldt,
newt;
int ch, i, j=1;
for (i=0;i<j;i++)
{
tcgetattr( STDIN_FILENO, &oldt );
newt = oldt;
newt.c_lflag &= ~( ICANON | ECHO );
tcsetattr( STDIN_FILENO, TCSANOW, &newt );
ch = getchar();
tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
c[i]=ch;
if ((ch & 0xc0)==0xc0) j=2;
if ((ch & 0xe0)==0xe0) j=3;
// printf("i:%d, j:%d - ",i, j);
// printf("O:%o - H:%x - D:%d | ",cc[i],cc[i], cc[i]);
}
c[i]=0;
// printf(cc);
return j;
}

jinak ted musi jit programovani stranou, pac musim jit malovat byt... :-(((
Ach ta realita... :-)
s uctou
XS

--- Doplnění předchozího příspěvku (17 Bře 2014 11:04) ---

Kazdopadne diky za Vasi verzi jeste ji jednou projdu, zda z ni by nebylo dobre neco vykuchat... :-)
xs

--- Doplnění předchozího příspěvku (17 Bře 2014 11:06) ---

Jeste potvrzeni - opravdu mi to nefungovalo jako psaci stroj a zjistil jsem, ze to delat to printw a putchar - chovalo se to naprosto zahadne. Toto je primocare. Predelal jsem nejakou starsi vec co mela jen getchar.

Uživatelský avatar
faraon
Master Level 8.5
Master Level 8.5
Příspěvky: 7366
Registrován: prosinec 10
Pohlaví: Muž
Stav:
Offline

Re: čtení znaku s diakritiku z konzole bez echa a entru

Příspěvekod faraon » 17 bře 2014 21:47

Je víc způsobů jak stáhnout kočku z kůže, tady mi shiftování znaku připadalo užitečnější, protože nevadí že se tím ta data zničí. Jinak bych shiftoval masku :lol:

Ten program z rána mi nic nezobrazil, musel jsem doplnit právě ty refresh(), pak fungoval krásně. Začínám si myslet že ve Slaxu co teď používám je asi něco špatně, protože se prostě nic neukáže, dokud v curses nedojde k nějaké "události", třeba zápisu textu pomocí mvprintw().

Poslední způsob je také funkční, jenže mi po skončení toho programu zůstane terminál rozštelovaný, a chová se jinak než před ním. V okně to tolik nevadí, ale občas používám i textový, a tam by to byl docela problém.

Nakonec jsem dodělal i to porovnávání se slovem, to řečiště je tam sice napsané napevno, ale nebyl by problém celou tu rutinu vložit do funkce, slova třeba náhodně vybírat z tabulky nebo načítat ze souboru, a pak je té funkci posílat ke zkoušení...
Je to udělané tak, že správné písmeno se vypíše, při špatné klávese jen blikne obrazovka, ukončit přes Escape se ten cyklus už nedá, a po opsání celého textu počítač pípne. To mi také nevydá žádný zvuk, ale je zajímavé že jak flash() tak beep() refreshnou obrazovku, takže se ukáže to co byo mezitím vypsáno i bez refresh().

V příloze jsou zdrojáky i zkompilované binárky, opis1 je s refresh(), opis2 bez něj, a protože je to open source (jak praví tučňák v mém avataru), takže si z toho může každý vykuchat co se mu bude hodit 8)
Přílohy
psani.zip
(9.78 KiB) Staženo 14 x
"Král Lávra má dlouhé oslí uši, král je ušatec!

(pravil K. H. Borovský o cenzuře internetu)


  • Mohlo by vás zajímat
    Odpovědi
    Zobrazení
    Poslední příspěvek
  • Retro herní konzole s dosovými hrami v UHD nebo Full HD
    od darkmarek » 30 čer 2023 11:19 » v Herní konzole
    6
    3380
    od petr22 Zobrazit poslední příspěvek
    02 črc 2023 11:18

Zpět na “Programování a tvorba webu”

Kdo je online

Uživatelé prohlížející si toto fórum: Google [Bot] a 4 hosti