III.  

STANDARDNÍ  VSTUP  A  VÝSTUP


Vstupem i výstupem programu jsou data. Činnost programu pak spočívá v transformaci vstupních dat v data výstupní. Nositeli dat mimo operační paměť počítače jsou soubory dat. Pro přímou komunikaci mezi programem a uživatelem jsou používány soubory textové, v nichž jsou data uvedena ve své vnější reprezentaci — formou textu, členěného do řádek. Protikladem textových jsou soubory binární, v nichž jsou data uložena ve svém vnitřním tvaru. Používají se například pro archivaci dat nebo pro komunikaci mezi programy.

Při vstupně-výstupních operacích (čtení a zápisu dat) s textovými soubory je nutné provádět konverze dat mezi jejich vnějším (textovým) a vnitřním tvarem (má-li být například vypsána hodnota čísla, je třeba vypočíst jednotlivé číslice jeho dekadického zápisu), kdežto při vstupně-výstupních operacích s binárními soubory se žádné konverze neprovádějí.

Za textové soubory jsou považována také různá textová zařízení, ovládaná operačním systémem (klávesnice, displej, tiskárna atd.). Operační systém definuje, které z těchto zařízení je jeho standardním vstupním zařízením (obvykle klávesnice), a které standardním výstupním zařízením (obvykle displej).

Pro ovládání souborů dat je implementována řada standardních podprogramů. Úplný popis vlastností textových i binárních souborů a podrobný popis podprogramů, určených pro jejich ovládání, je uveden v kapitole IX. Zde je popsán speciálně vstup dat z klávesnice a výstup dat na displej.

III.1. 

Vstup z klávesnice

Vstup textu z klávesnice se uskutečňuje přes pomocnou vyrovnávací paměť. Vyrovnávací paměť má funkci fronty pro znaky, které již byly vygenerovány (klávesnicí), ale dosud nebyly zpracovány (přečteny programem). Při požadavku programu na vstup znaku z klávesnice je nejprve otestována vyrovnávací paměť. Pokud není prázdná, znak je z ní vyjmut a programu předán. Pokud však vyrovnávací paměť v okamžiku požadavku prázdná je, volá se nejprve speciální obslužný podprogram, který zajistí vstup jedné celé řádky textu z klávesnice do vyrovnávací paměti. Během zadávání je text vstupní řádky průběžně zobrazován na displeji a lze jej editovat, a to až do stisku klávesy ENTER. (Zjednodušeno.)

Na konci každé zadané řádky textu se nachází stiskem klávesy ENTER generovaná dvojice řídících znaků #13 a #10, označovaných zkratkami CR (Carriage Return) a LF (Line Feed). Jména těchto znaků jsou odvozena od jejich řídící funkce při výpisu na obrazovku — znak CR totiž vrací kurzor na začátek řádky a znak LF jej posouvá o řádku níže. Dalším řídícím znakem je znak #26 — EOF (End Of File) — který se používá pro označení konce souboru za posledním platným znakem. Na klávesnici jej lze generovat stiskem klávesy F6 nebo kombinace kláves CTRL+Z a pro potřeby editace textu vstupní řádky se zobrazí jako „^Z“.

Z pohledu programu je tedy vstup z klávesnice tvořen frontou neomezeného počtu znaků, členěnou na řádky výskytem oddělovačů CRLF, a ukončenou znakem konce souboru EOF. Čtení znaků z této fronty je striktně sekvenční — v každém okamžiku lze číst pouze aktuální znak z čela fronty, tj. první ze vstupujících znaků, který dosud přečten nebyl. Přečtením je znak z fronty vyjmut — do čela se dostává jeho následník ve frontě. Již přečtené znaky jsou proto nenávratně ztraceny (nelze je číst znovu).


POZNÁMKA: Kapacita vstupní řádky je 128 znaků (zhruba půl druhé řádky na displeji při šířce 80 znaků na řádku). Pokud při editaci obsahuje vstupní řádka již 127 znaků a dojde k pokusu o zadání dalšího znaku, reaguje operační systém akustickým signálem („pípnutím“) a stisk klávesy je ignorován, neboť poslední pozice je rezervována pro znak CR. Pokud je v tomto stavu vstupní řádka odeslána ke zpracování stiskem klávesy ENTER, pak z vygenerované dvojice oddělovačů CRLF se pouze znak CR „vejde“ do vyrovnávací paměti a je zobrazen na displeji (zobrazení znaku CR odpovídá přesun kurzoru na levý okraj aktuální řádky displeje). Znak LF vstupuje do vyrovnávací paměti až při dalším požadavku na její naplnění a rovněž až v tomto okamžiku je zobrazen (přesun kurzoru na novou řádku). Pokud tedy v době mezi odesláním vstupní řádky a zpracováním znaku LF dojde k výpisu nějakého textu na displej, bude jím obraz vstupní řádky na displeji přepsán.

Standardní vstup podléhá univerzálnímu mechanismu zpracování textových souborů, takže pro něj nejsou implementovány operace, které souvisí se speciálními vlastnostmi zařízení klávesnice (viz Jednotka Crt).

Procedury Read a Readln   Ke čtení vnější reprezentace vstupní hodnoty a její konverzi na reprezentaci vnitřní lze použít standardní proceduru Read nebo Readln.

procedure Read (seznam proměnných);

Pro každou z uvedených proměnných přečte procedura ze vstupu všechny znaky, tvořící vnější reprezentaci hodnoty příslušného typu, provede její konverzi na reprezentaci vnitřní (například z posloupnosti dekadických číslic vypočte odpovídající číslo) a výslednou hodnotu proměnné přiřadí. Uvedené proměnné mohou být pouze znakového, řetězcového nebo číselného typu (pro hodnoty jiných typů nejsou definovány vstupní konverze).

Pokud má být současně čteno více hodnot, lze použít odpovídajícího počtu volání procedury Read zvlášť pro každou z nich nebo jediného volání s více parametry. Jednotlivé proměnné se pak v seznamu vzájemně oddělují čárkou. Například trojici příkazů pro postupné načtení hodnot do proměnných A, BC

Read (A); Read (B); Read (C)
lze nahradit jediným příkazem ve tvaru
Read (A, B, C)

Syntakticky správné je i volání procedury Read bez parametrů (seznam proměnných je pak prázdný a neuvádí se ani závorka, která jej ohraničuje) nemá však žádný efekt.

procedure Readln (seznam proměnných);

V některých případech mohou překážet znaky CR a LF, vkládané na konec vstupní řádky. Procedura Readln přečte hodnoty do všech uvedených proměnných, stejně jako procedura Read, navíc však ze vstupní řádky odstraní všechny zbývající nezpracované znaky, včetně oddělovačů CRLF.

Ve tvaru bez parametrů Readln pouze vyprazdňuje buffer klávesnice. Pokud je však buffer prázdný nebo obsahuje-li pouze znak LF, Readln vyžádá vstup další řádky a odstraní ji rovněž — toho lze využít například jako „čekání na stisk klávesy ENTER“.

Vstupní konverze   Pomocí výše popsaných procedur ReadReadln lze ze vstupní řádky v závislosti na typu jejich parametrů číst znaky, řetězce znaků a čísla.

Čtení znaku
Do proměnné znakového typu je přečten aktuální znak ze vstupní řádky (může jím být i některý z řídících znaků CR, LF a EOF).

Čtení řetězce znaků

Řetězec je zvláštní druh pole znaků (viz Typy řetězec). Do jednotlivých prvků řetězcové proměnné jsou postupně načítány znaky ze vstupní řádky — aktuální znak do prvního prvku, další do druhého atd. Postupné čtení je ukončeno buď zaplněním řetězcové proměnné nebo přečtením posledního znaku vstupní řádky před ukončovacím znakem CR nebo EOF. Skutečná délka řetězce (počet přečtených znaků) je pak dosazena do délkového bytu řetězcové proměnné.

Znak CR ani EOF není do řetězce načten nikdy — pokud je při zahájení čtení řetězce aktuálním znakem CR nebo EOF, nebude přečten žádný znak a výslednou hodnotou řetězcové proměnné bude prázdný řetězec.

Čtení čísla

Pokud je parametrem procedury Read nebo Readln proměnná některého z číselných typů, přečte se ze vstupní řádky textová reprezentace celého resp. reálného čísla (podle typu parametru), odpovídající syntaxi číselných literálů, i s případným znaménkem. Konverzí vypočtená hodnota čísla je pak dosazena do proměnné.

Pokud je uvedeno znaménko, musí ihned za ním (bez mezery) následovat první znak literálu. Textové reprezentaci čísla může (ale nemusí) předcházet libovolný počet mezer, tabulátorů a oddělovačů řádek (ty jsou přečteny a ignorovány), ukončena musí být alespoň jednou mezerou, tabulátorem, oddělovačem řádek nebo znakem konce souboru (ty však již přečteny nejsou). Pokud textová reprezentace čísla nevyhovuje těmto požadavkům, dojde při jeho čtení k chybě. Pokud je při zahájení čtení čísla aktuálním znakem EOF, nebude přečten žádný znak a výslednou hodnotou číselné proměnné bude nula.


POZNÁMKA: Ve skutečnosti může textové reprezentaci čísla předcházet libovolný počet znaků menších nebo rovných znaku mezera, vyjma znaku EOF (tj. takových znaků, jejichž ordinální čísla jsou vesměs menší nebo rovna číslu 32 a různá od čísla 26) — všechny takové znaky jsou při čtení čísla chápány jako oddělovače a tudíž ignorovány. Z praktických důvodů se však ve funkci oddělovačů čísel používají jen mezery, tabulátory a oddělovače řádek.

Testovací funkce   Pro testování aktuálního stavu vstupu z klávesnice jsou k dispozici standardní funkce EOF (End of File), EOLn (End of Line), SeekEOFSeekEOLn. Testují, zda je aktuálním znakem na vstupu znak CR resp. znak EOF a výsledek testu vracejí jako hodnotu typu Boolean (tj. True nebo False). Pokud je buffer klávesnice v okamžiku testu prázdný, generují nejprve požadavek na jeho naplnění.

function EOF: Boolean;

Testuje stav konec souboru. Vrací True právě tehdy, když je na vstupu aktuálním znakem znak EOF (#26).

function EOLn: Boolean;

Testuje stav konec řádky. Vrací True právě tehdy, když je na vstupu aktuálním znakem CR (#13) nebo EOF (#26).

function SeekEOF: Boolean;

Používá se pro test stavu konec souboru při zpracování posloupnosti čísel. Testu předchází „přeskočení“ všech oddělovačů, tj. všech znaků menších nebo rovných znaku mezera (#32) a současně různých od znaku EOF.

function SeekEOLn: Boolean;

Pracuje obdobně jako SeekEOF, testován je však stav konec řádky a mezi oddělovače není počítán ani znak CR.

III.2. 

Výstup na obrazovku

Pozice znaku na obrazovce je definována jeho souřadnicemi — vertikálně řádkou a horizontálně sloupcem. Operační systém uchovává souřadnice aktuální pozice, tedy pozice, na kterou bude uskutečněn výstup následujícího znaku. Na obrazovce je tato pozice vizuálně vyznačena kurzorem. Po výstupu (obyčejného) znaku se kurzor automaticky posouvá v aktuálním řádce do následujícího sloupce. Pokud je vypsaný znak v posledním sloupci, je kurzor přesunut do prvního sloupce následující řádky. Pokud je znak vypsán do posledního sloupce poslední řádky, roluje obsah obrazovky o jednu řádku nahoru a kurzor je přesunut na začátek takto uprázdněné poslední řádky.

Obrazovka není při startu programu nijak inicializována, její obsah i počáteční pozice kurzoru jsou dány aktuálním stavem. Standardní výstup podléhá univerzálnímu mechanismu zpracování textových souborů, takže pro něj nejsou implementovány operace, které souvisí se speciálními vlastnostmi zařízení obrazovka — výmaz, nastavení pozice kurzoru apod. (viz Jednotka Crt).


POZNÁMKA: Při průběžném načítání dat z klávesnice a vypisování výsledků výpočtu na displej dochází ke smíchání textu vstupních řádek s textem řádného výstupu. Pokud toto míchání vadí, lze například směrovat výstup do diskového souboru a jeho obsah vytisknout na displej dodatečně (popis práce se soubory obsahuje kapitola IX).

Procedury Write a Writeln   Výpis znaků na displej uskutečňují standardní procedury WriteWriteln. Výpis je zahájen na aktuální pozici kurzoru.

procedure Write (seznam prvků tisku);

Procedura Write postupně vypíše od aktuální pozice kurzoru vnější reprezentace hodnot prvků tisku, uvedených v seznamu. Jednotlivé prvky jsou v seznamu vzájemně odděleny čárkami. Syntakticky přípustné je i volání procedury Write bez parametrů, nemá však žádný efekt.

Základním tvarem každého prvku tisku je výraz, jehož hodnota je vypočtena, zkonvertována na textový tvar a vytištěna. Výraz musí být znakového, řetězcového, číselného nebo logického typu (pro hodnoty jiných typů nejsou definovány výstupní konverze).

Za výrazem smí být v prvku tisku uvedeny požadavky na formát jeho výpisu. Pro výraz kteréhokoliv z povolených typů lze definovat celkový počet znaků vnější reprezentace jeho hodnoty takto:

výraz : počet_znaků
Specifikovaný počet znaků musí být celočíselný výraz. Pokud je pak počet znaků vnější reprezentace hodnoty vypisovaného výrazu menší než počet takto předepsaný, je vnější reprezentace doplněna zleva potřebným počtem mezer. V opačném případě je předepsaný počet znaků ignorován. Například:
Write ('' : 5, 7 * 11 : 5, 'lupičů' : 5)
Tímto příkazem bude vytištěno celkem 16 znaků: předepsaných 5 formátovacích mezer vnější reprezentace prázdného řetězce '', neobsahujícího žádný znak; další 3 formátovací mezery a 2 číslice hodnoty 77 výrazu 7 * 11 (dohromady požadovaných 5 znaků) a konečně 6 písmen řetězce 'lupičů' (předepsaných 5 znaků se neuplatní).

Pro výrazy reálných typů může specifikace formátu výpisu obsahovat navíc i požadavek na počet desetinných míst vnější reprezentace hodnoty:

výraz : počet_znaků : počet_desetinných_míst
Hodnota, získaná výpočtem výrazu, je pak zaokrouhlena na předepsaný počet desetinných míst a konvertována na tvar s pevnou desetinnou tečkou (bez exponentu). Záporný počet desetinných míst je ignorován. Například:
Write (-2/3 : 7 : 2)
Tímto příkazem bude vytištěno požadovaných 7 znaků: 2 formátovací mezery a číslo –0.67 (5 znaků).

procedure Writeln (seznam prvků tisku);

Volání procedury Writeln má stejnou syntax a funkci jako volání procedury Write. Procedura Writeln však navíc po výpisu hodnot všech uvedených prvků odřádkuje — přesune kurzor na začátek další řádky (tj. doplní výpis znaky CR a LF). Ve tvaru bez parametrů Writeln pouze odřádkuje. Toho je možné využít například k výpisu prázdných (vynechaných) řádek.

Výstupní konverze   Procedury WriteWriteln provádějí před výpisem požadované hodnoty její konverzi z vnitřního na vnější (textový) tvar. Konverze jsou definovány pro hodnoty znakového, řetězcového, číselného a logického typu.

Výpis znaku a řetězce
Při výpisu hodnoty typu znak resp. řetězec vystupuje na displej příslušný znak resp. všechny platné znaky řetězce (v počtu, daném jeho aktuální délkou) a příslušný počet formátovacích mezer. Při výpisu prázdného řetězce tedy vystupují pouze formátovací mezery. Některé znaky jsou při výpisu těchto hodnot používány jako řídící (viz tabulka), ostatní jsou zobrazeny „normálně“.
Tabulka 11: Řídící znaky výstupu na obrazovku
znak řídící funkce
BELL (#7) akustický signál (pípnutí)
BACKSPACE (#8) posun kurzoru o pozici vlevo (není-li na začátku řádky)
LF (#10) posun kurzoru o pozici dolů
CR (#13) posun kurzoru na začátek řádky
EOF (#26) ukončení výpisu právě aktivní procedury Write nebo Writeln — žádné další znaky (ani znaky konce řádky) již nejsou vypsány
Výpis celého čísla
Při výpisu celého čísla je počet vystupujících znaků vnější reprezentace dán počtem cifer jeho dekadického zápisu, případným záporným znaménkem (kladné se nevypisuje) a příslušným počtem formátovacích mezer.

Výpis reálného čísla

Výslednou hodnotou výrazu reálného typu je číslo typu Real resp. Extended, podle nastavení direktivy {$N–} resp. {$N+}. Pokud není specifikován formát, obsahuje vnější reprezentace reálného čísla následující znaky:

~ znaménko mantisy (mezera nebo minus)
~ první platná číslice mantisy
~ desetinná tečka
~ 10 resp. 14 číslic desetinné části mantisy
~ oddělovač exponentu (E)
~ znaménko exponentu (plus nebo minus)
~ 2 resp. 4 číslice exponentu

Pokud je specifikován počet znaků a není specifikován počet desetinných míst, může být počet číslic v desetinné části mantisy 1 až 10 resp. 1 až 17. Pokud je specifikován i počet desetinných míst, odpovídá vnější reprezentace běžnému zápisu reálného čísla s pevnou desetinnou tečkou (bez exponentu). Maximální počet zobrazených desetinných míst je pak 11 resp. 18. Nezáporná čísla jsou v tomto případě zobrazena bez znaménka.

Výpis logické hodnoty

Při výpisu logické hodnoty vystupuje na obrazovku řetězec 'FALSE' resp. 'TRUE', doplněný zleva o příslušný počet formátovacích mezer.