117
Príručka pre jazyk Marek Kubran

Príručka pre jazyk - vutbr.czhlavicka/vyuka/PriruckaC...jazyka C sa naučíte používať zložitejšie údajové štruktúry, ako sú napr. polia alebo reťazce, a pokročilejšie

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

  • Príručka pre jazyk

    Marek Kubran

  • Obsah

    Úvod............................................................................................................................................................................... 5

    I. lekcia: Komponenty programu v jazyku C ............................................................................................................ 7 Prvý C program .......................................................................................................................................................... 7 Programové komponenty ........................................................................................................................................... 8 Zhrnutie .................................................................................................................................................................... 10 Cvičenia.................................................................................................................................................................... 10

    II. lekcia: Funkcie a práca s pamäťou...................................................................................................................... 11 Hlavička funkcie ...................................................................................................................................................... 11 Deklarácia a definícia funkcie .................................................................................................................................. 11 Procedúry a dátový typ void..................................................................................................................................... 13 Parametre funkcií ..................................................................................................................................................... 13 Definície premenných .............................................................................................................................................. 14 Cvičenia.................................................................................................................................................................... 14

    III. lekcia: Formátovaný vstup/výstup z/na terminál.............................................................................................. 15 Formátovaný výstup na obrazovku .......................................................................................................................... 15 Formátovaný vstup z klávesnice .............................................................................................................................. 16 Cvičenia.................................................................................................................................................................... 17

    IV. lekcia: Riadiace štruktúry – príkaz vetvenia..................................................................................................... 19 Príkaz if .................................................................................................................................................................... 19 Ternárny operátor ..................................................................................................................................................... 20 Cvičenia.................................................................................................................................................................... 21

    V. lekcia: Booleovské výrazy ..................................................................................................................................... 22 Logické a relačné operátory v jazyku C ................................................................................................................... 23 Skrátené vyhodnocovanie logických výrazov .......................................................................................................... 24 Cvičenia.................................................................................................................................................................... 24 Tipy a triky............................................................................................................................................................... 24

    VI. lekcia: Riadiace štruktúry – iteračné príkazy ................................................................................................... 25 Operátor porovnania................................................................................................................................................. 26 Cyklus s podmienkou na začiatku ............................................................................................................................ 26 Príkazy break a continue .......................................................................................................................................... 27 Cvičenia.................................................................................................................................................................... 27

    VII. lekcia: Riadiace štruktúry – iteračné príkazy.................................................................................................. 28 Cyklus s podmienkou na konci................................................................................................................................. 30 Cvičenia.................................................................................................................................................................... 31

    VIII. lekcia: Riadiace štruktúry – iteračné príkazy ................................................................................................ 32 Typové modifikátory................................................................................................................................................ 33 Cyklus for................................................................................................................................................................. 33 Cvičenia.................................................................................................................................................................... 35

    IX. lekcia: Iterácia pomocou rekurzie ...................................................................................................................... 36 Cvičenia.................................................................................................................................................................... 37

  • X. lekcia: Typová konverzia ...................................................................................................................................... 38 Cvičenia.................................................................................................................................................................... 39

    XI. lekcia: Preprocesor jazyka C .............................................................................................................................. 40 Preprocesor jazyka C................................................................................................................................................ 41 Makrá bez parametrov.............................................................................................................................................. 42 Makrá s parametrami................................................................................................................................................ 42 Zrušenie definície makra .......................................................................................................................................... 43 Podmienený preklad riadený definíciou makra ........................................................................................................ 43 Cvičenia.................................................................................................................................................................... 44 Tipy a triky............................................................................................................................................................... 45

    XII. lekcia: Unárne operátory ++ a ––; Reťazce ako jednorozmerné polia ......................................................... 46 Unárne operátory ++ a –– ........................................................................................................................................ 47 Jednorozmerné polia ................................................................................................................................................ 47 Reťazce..................................................................................................................................................................... 49

    Práca s reťazcom .................................................................................................................................................. 49 Cvičenia.................................................................................................................................................................... 50

    XIII. lekcia: Smerníky a volanie odkazom............................................................................................................... 51 Smerníky .................................................................................................................................................................. 52 Smerníky a jednoduché premenné............................................................................................................................ 53 Smerníky a typy premenných................................................................................................................................... 54 Smerníky a funkcie – volanie odkazom ................................................................................................................... 55 Tipy a triky............................................................................................................................................................... 58 Cvičenia.................................................................................................................................................................... 58

    XIV. lekcia: Smerníky a polia, pointerová aritmetika, pole reťazcov ................................................................... 59 Smerníky a polia....................................................................................................................................................... 60 Pointerová aritmetika ............................................................................................................................................... 61 Vzťah medzi smerníkmi a poliami ........................................................................................................................... 61 Pole reťazcov............................................................................................................................................................ 62 Cvičenia.................................................................................................................................................................... 63

    XV. lekcia: Parametre funkcie main() a príkaz switch ........................................................................................... 65 Parametre funkcie main() ......................................................................................................................................... 69 Príkaz switch ............................................................................................................................................................ 70 Cvičenia.................................................................................................................................................................... 72 Tipy a triky............................................................................................................................................................... 73

    XVI. lekcia: Definícia nového typu, vymenovaný typ, operátor čiarky................................................................. 74 Definícia nového typu .............................................................................................................................................. 79 Vymenovaný typ ...................................................................................................................................................... 80 Operátor čiarky......................................................................................................................................................... 81 Cvičenia.................................................................................................................................................................... 82

    XVII. lekcia: Práca so súbormi, štandardný vstup/výstup ..................................................................................... 84 Práca so súbormi ...................................................................................................................................................... 88 Otvorenie súboru ...................................................................................................................................................... 89 Uzavretie súboru ...................................................................................................................................................... 89

  • Štandardný vstup a výstup........................................................................................................................................ 90 Základné operácie s otvoreným súborom................................................................................................................. 90 Presmerovanie štandardného vstupu a výstupu ........................................................................................................ 93 Cvičenia.................................................................................................................................................................... 93

    XVIII. lekcia: Zostavenie programu kalkulátor – I. časť ....................................................................................... 95 Funkcia exit ............................................................................................................................................................ 101 Syntaktický analyzátor s vyhodnocovaním výrazov .............................................................................................. 102

    Analýza funkcie vyraz() ..................................................................................................................................... 103 Analýza funkcie term()....................................................................................................................................... 104 Analýza funkcie faktor() .................................................................................................................................... 104

    Zhrnutie: ................................................................................................................................................................. 104 Cvičenia.................................................................................................................................................................. 105

    XIX. lekcia: Zostavenie programu kalkulátor – II. časť ...................................................................................... 106 Doplnenie funkcie vyraz() o interpretáciu unárnych operátorov............................................................................ 109 Rozšírenie funkcie faktor() o syntaktickú analýzu a vyhodnotenie funkcií MAX a MIN...................................... 109 Cvičenia.................................................................................................................................................................. 110

    Príloha ....................................................................................................................................................................... 114

    Literatúra.................................................................................................................................................................. 115

    Register...................................................................................................................................................................... 116

  • 5

    Úvod Príručka, ktorú práve držíte v ruke, je súčasťou záverečného projektu, ktorého cieľom bolo vytvoriť textovú

    príručku pre cvičenie programovania v jazyku C. Hlavným obsahom príručky má byť postupnosť programovacích príkladov, ktorá je konzistentná, didakticky optimalizovaná a má modulárny charakter.

    Príručka je teda venovaná študentom prvého ročníka FEI STU, ktorí majú zapísaný predmet Programovanie v C. Môže však poslúžiť aj ostatným čitateľom, ktorí nemajú skúsenosti z programovacieho jazyka C. Príručka nie je učebnicou programovania, ale učebnicou jazyka C, pretože sa v nej oboznamujete s príkazmi, funkciami a konštruk-ciami programovacieho jazyka C.

    Cieľom projektu nebolo vytvoriť ďalšiu príručku k stovkám existujúcich ani vyčerpávajúcu encyklopédiu, ale skôr učebnicu, podľa ktorej by mohlo prebiehať cvičenie na princípe stavebnice LEGO a krátkych príkladov. V jednotlivých lekciách sa vytvoria jednoduché funkcie, na ktorých sa oboznámite so základnými prvkami a kon-štrukciami jazyka C, a tie potom poskladáte do jedného väčšieho programu.

    Nosnou témou príručky je program kalkulátor, ktorý pozostáva z konzistentnej postupnosti programovacích príkladov. Celé vysvetľovanie problematiky jazyka C sa orientuje na túto tému. Cieľom preštudovania príručky nie je len získanie a osvojenie si nových vedomostí z jazyka C, ale aj vybudovanie programu kalkulátor. Na jeho vývoji sa budete priamo zúčastňovať aj vy, a to formou riešenia úloh zadaných v cvičeniach na konci každej lekcie. Okrem problematiky jazyka C sa v príručke dozviete čiastočne aj o prekladačoch, pretože kalkulátor bude v sebe imple-mentovať aj jednoduchý lexikálny a syntaktický analyzátor. Tým, že celá príručka je monotematicky ladená, t.j. nesie sa v duchu vytvorenia jediného uceleného programu, je to prvá publikácia svojho druhu zameraná na výučbu jazyka C.

    Príručka je rozdelená do 19 lekcií, ktoré nasledujú za sebou v postupnosti, v akej sa program kalkulátor imple-mentuje. Na rozdiel od bežných učebníc jazyka C sa hneď na začiatku (II. lekcia) zoznámite s funkciami, ktoré sú základným stavebným kameňom jazyka C, a ktorých poznanie vám dovolí od počiatku vytvárať program kalkulátor ako program skladajúci sa z postupnosti programovacích príkladov.

    V ďalších lekciách sa oboznámite s riadiacimi konštrukciami jazyka C, ako sú napr. príkaz vetvenia a s ním súvisiace Booleovské výrazy, iteračné príkazy, t.j. cykly a rekurzívne funkcie. Po zoznámení sa s riadiacimi príkazmi jazyka C sa naučíte používať zložitejšie údajové štruktúry, ako sú napr. polia alebo reťazce, a pokročilejšie techniky programovania, ako sú napr. smerníky a ich využitie pri volaní odkazom, vzťah medzi smerníkmi a poliami, direktí-vy preprocesora a pod. Pri vytváraní lexikálneho a syntaktického analyzátora s vyhodnocovaním matematických výrazov sa oboznámite s vymenovaným typom v jazyku C, ktorý vám umožní reprezentovať matematické výrazy pomocou symbolov. Nakoniec sa naučíte pracovať aj so súbormi, ktoré poslúžia používateľovi programu kalkulátor na to, aby mohol zadávať vstupné matematické výrazy priamo zo súboru.

    Samotný plne funkčný program zostavíte až v posledných dvoch lekciách. Dovtedy budete vytvárať väčšinou univerzálne použiteľné funkcie, ktoré sa dajú použiť aj v inom programe ako je kalkulátor. Cieľový program kalkulátor by mal byť pre vás veľkou motiváciou, pretože bude pre mnohých z vás prvým väčším programom, ktorý bude zmysluplný a reálne použiteľný. Kalkulátor by mal vedieť počítať aj také matematické výrazy, ktoré obsahujú neštandardné funkcie, ako sú napr. najväčší spoločný deliteľ, funkcie na zistenie väčšieho/menšieho čísla z dvoch argumentov, rôzne typy zaokrúhľovania, …

    Všetky lekcie majú nasledujúcu štruktúru: • Názov lekcie • Úvod • Výpis programu • Vysvetlivky • Text • Tipy a triky • Cvičenia

    Úvod vás oboznamuje s tým, čo sa v lekcii naučíte z problematiky jazyka C, a čo bude výstupom lekcie pre program kalkulátor.

  • 6

    Po krátkom úvode nasleduje výpis programu, na ktorom sa vysvetľuje jazyk C. Riadky programov uvedených vo výpisoch sú očíslované kvôli identifikácii vysvetľovaných častí programu. Čísla riadkov zodpovedajú fyzickým číslam riadkov zdrojových kódov programov.

    Vo vysvetlivkách sú uvedené nové výrazy/slovíčka nachádzajúce sa vo výpise programu. Vysvetlivky majú charakter slovníka a sú veľmi dôležitou súčasťou lekcie, pretože sa nimi zavádzajú nové pojmy, t.j. oboznamujú vás s tým, ako sa čo nazýva.

    Po vysvetlivkách nasleduje samotný text, v ktorom sa vysvetľujú nové pojmy, vysvetľuje sa problematika jazyka C a zároveň problematika funkcií kalkulátora. Časť tipy a triky nie je súčasťou každej lekcie a niekedy sa nachádza až za cvičeniami. V cvičeniach sú zadané úlohy, ktoré máte riešiť. Cieľom úloh je precvičenie a osvojenie si novonadobudnutých vedomostí z problematiky jazyka C. Väčšina úloh nadväzuje na seba, tzn. ak budete riešiť všetky úlohy v uvedenej postupnosti, v poslednej lekcii by ste mali dospieť ku konečnému výsledku, ktorým je cie-ľový program kalkulátor.

    Za poslednou lekciou sa nachádza príloha so zoznamom neprebraných alebo len čiastočne vysvetlených tém z jazyka C, ktoré zostávajú na samoštúdium. V závere príručky nájdete register, v ktorom sú uvedené všetky kľúčové slová a odkazy na strany, kde sa príslušné slovo nachádza. Register vám umožní rýchlo vyhľadať informácie vysvet-ľujúce dané kľúčové slovo, funkciu alebo príkaz.

    Príručka má celkovo 117 strán, pričom značnú časť zaberajú výpisy zdrojových textov programov, na ktorých sa vysvetľuje preberaná problematika. Príručka je ilustrovaná 25 inštruktívnymi obrázkami, obsahuje niekoľko tabuliek, asi desiatku tipov a trikov, ktoré je dobré vedieť, a po ktorých osvojení si získate prinajmenšom zručnosť pri vytvára-ní programov. Príručka obsahuje celkovo 105 úloh, z ktorých 94 je vyriešených. Riešené úlohy sa nachádzajú v adre-sári CVICENIA\, ktorý je súčasťou elektronického média dodávaného k tejto príručke. Disketa taktiež obsahuje adresár VYKLAD\, v ktorom sa nachádzajú zdrojové texty všetkých programov uvedených vo výpisoch príručky.

    Pre štúdium príručky predpokladáme u čitateľa nižšie uvedené znalosti. V príručke nie sú uvedené kvôli tomu, že ide zväčša o referenčné informácie, ktoré môžete získať z ľubovoľnej dostupnej literatúry k jazyku C alebo z ma-nuálov k prekladaču jazyka C.

    - spôsob tvorby programu: Editor à Preprocesor à Prekladač à Linker à Debugger - čo je ASCII tabuľka - zápis identifikátorov a kľúčové slová (napr. identifikátor musí začínať písmenom a je ”case sensitive“,

    identifikátorom nemôže byť kľúčové slovo, …) - zápis konštánt (pre celé čísla aj v rôznych sústavách) a literálov - údajové typy v jazyku C a ich rozsahy

  • 7

    I. lekcia: Komponenty programu v jazyku C Každý program v jazyku C sa skladá z niekoľkých komponentov, kombinovaných určitým spôsobom. Väčšia

    časť tejto príručky je venovaná vysvetľovaniu rôznych programových častí a ako ich máme používať. Na celkovú predstavu by sme mali začať kompletným (hoci malým) programom napísaným v jazyku C s identifikáciou jednotlivých častí. V tejto lekcii sa naučíme:

    • o jednotlivých častiach programu v jazyku C • o význame jednotlivých programových častí

    Prvý C program Dole uvedený výpis programu predstavuje zdrojový kód programu P01.CPP. Program načíta z klávesnice dve

    čísla, zistí a vypíše maximum z obidvoch čísel. V tomto štádiu sa neznepokojujte tým, ako program pracuje a čo jednotlivé príkazy znamenajú. Ide tu o pochopenie jednotlivých častí (komponentov) programu, aby sme lepšie poro-zumeli výpisom programov v ďalších lekciách tejto príručky.

    Predtým, než začneme rozoberať jednotlivé časti, musíme vedieť, čo je to funkcia, pretože funkcie sú základnou stavebnicou programovania v jazyku C. Funkcia je nezávislá časť programového kódu, ktorá vykonáva určitú úlohu, a ktorá má pridelené meno. Použitím mena funkcie v programe sa vykoná kód tela funkcie. Program môže tiež posielať funkcii informácie, nazývané argumenty, a funkcia môže vrátiť informáciu časti programu, odkiaľ bola volaná. V jazyku C existujú dva typy funkcií: knižničné funkcie, ktoré sú súčasťou prekladača jazyka C a užívateľom definované funkcie (užívateľské funkcie), ktoré programátor vytvára. V tejto príručke sa naučíte o obidvoch typoch funkcií. Poznámka: Čísla riadkov vo výpisoch programov nie sú súčasťou zdrojového kódu programu. V programe sú uvádzané iba kvôli identifikácii, takže v zdrojových programoch ich nepíšte!

    Výpis programu P01.CPP 1: #include 2: 3: int c; 4: 5: int max(int x, int y); 6: 7: main() 8: { 9: int a, b; 10: 11: /* nacitanie prveho cisla */ 12: printf("Zadaj 1. cislo: "); 13: scanf("%d", &a); 14: 15: /* nacitanie druheho cisla */ 16: printf("Zadaj 2. cislo: "); 17: scanf("%d", &b); 18: 19: /* najdenie vacsieho cisla a zobrazenie vysledku */ 20: c = max(a, b); 21: printf("Maximum z %d a %d je %d\n", a, b, c); 22: 23: return (0); 24: } 25: 26: /* Funkcia vrati maximum z dvoch cisel - argumentov funkcie */ 27: int max(int x, int y) 28: { 29: return (x > y ? x : y); 30: }

  • 8

    Programové komponenty Nasledujúce odseky opisujú rôzne časti predchádzajúceho ukážkového programu. Riadky sú očíslované, takže

    môžete jednoducho identifikovať programové časti, ktoré sa práve rozoberajú. Funkcia main() (riadky 7 až 24)

    Jediná časť, ktorá je povinná v každom C programe, je funkcia main(). V najjednoduchšej forme funkcia main() pozostáva z mena main nasledovaného párom prázdnych zátvoriek (()) a párom zložených zátvoriek ({}). Vo vnútri zložených zátvoriek sú príkazy, ktoré vytvárajú telo programu. Za normálnych okolností, vykonávanie programu začína na prvom príkaze vo funkcii main() a končí posledným príkazom v main(). Direktíva #include (riadok 1)

    Direktíva #include nariaďuje prekladaču C, aby vložil obsah include súboru, uvedeného bezprostredne za týmto príkazom, do programu v čase prekladu. Include súbor je samostatný súbor, ktorý obsahuje informácie potrebné pre náš program alebo prekladač. Väčšina týchto súborov (niekedy nazývaných aj hlavičkové súbory) je súčasťou prekladača. Obsah týchto súborov nie je potrebné nikdy meniť a preto sú udržiavané separátne od našich zdrojových kódov. Všetky vkladané súbory by mali mať príponu .H (napr. STDIO.H). V našom ukážkovom programe direktíva #include nariaďuje prekladaču „vlož obsah súboru STDIO.H do programu P01.CPP na miesto, kde sa nachádza direktíva #include“. Väčšina C programov vkladá jeden alebo viac hlavičkových súborov. Viac informácií o vkladaní súborov nájdete v lekcii XI, „Preprocesor jazyka C“. Definícia premennej (riadky 3 a 9)

    Premenná je meno, ktoré je priradené určitej pamäťovej adrese. Programy používajú premenné na ukladanie rozličných druhov dát počas behu programu. V jazyku C musí byť premenná definovaná pred jej prvým použitím! Definícia premennej informuje prekladač o mene premennej a type dát, ktorý táto premenná uchováva. V našom ukážkovom programe definície premenných v riadkoch 3 a 9: int c; int a, b; definujú tri premenné pomenované c, a, b, z ktorých každá uchováva celočíselnú hodnotu. Viac informácií o premenných a ich definovaní získate v lekcii II „Funkcie a práca s pamäťou“. Funkčný prototyp (riadok 5)

    Funkčný prototyp poskytuje prekladaču informácie (meno a argumenty) o funkcii, ktorú program obsahuje. Funkčný prototyp musí byť definovaný ešte predtým, než je funkcia prvýkrát použitá, pokiaľ ešte nebola definovaná. Prototyp funkcie je odlišný od definície funkcie, ktorá obsahuje konkrétne príkazy, ktoré tvoria funkciu. (Definícia funkcií je preberaná v ďalšej lekcii tejto príručky.) Príkazy programu (riadky 12, 13, 16, 17, 20, 21, 23 a 29)

    Skutočná práca programu v jazyku C je určená jeho príkazmi. C príkazy zobrazujú informácie na obrazovke, čítajú vstup z klávesnice, vykonávajú matematické operácie, volajú funkcie, čítajú súbory z disku a realizujú všetky ostatné operácie, ktoré potrebuje program vykonať. Veľká časť tejto príručky je venovaná práve príkazom jazyka C. Nateraz je pre nás podstatné iba to, že v zdrojových kódoch programov je každý príkaz zapísaný na samostatnom riadku a končí sa bodkočiarkou (;). Príkazy programu P01.CPP sú v krátkosti vysvetlené v nasledovných odstavcoch. printf()

    Príkaz printf() (riadky 12, 16 a 21) je knižničná funkcia, ktorá zobrazuje informáciu na obrazovke. printf() môže zobraziť jednoduchú textovú správu (ako napr. v riadku 12 a 16) alebo správu s hodnotou jednej alebo viacerých premenných (ako v riadku 21). scanf()

    Príkaz scanf() (riadky 13 a 17) je iná knižničná funkcia, ktorá číta údaje z klávesnice a priradí tieto údaje jednej alebo viacerým programovým premenným. Príkaz programu v riadku 20 volá funkciu pomenovanú max. Inými slovami, vykoná príkazy, ktoré obsahuje funkcia max(). Zároveň tento príkaz pošle funkcii argumenty a a b. Po dokončení vykonávania príkazov vo funkcii max(), funkcia max() vráti hodnotu programu (riadenie sa vráti späť na miesto, odkiaľ bola funkcia volaná) a uloží ju do premennej c. return

    Riadky 23 a 29 obsahujú príkaz return. V príkaze return (riadok 29), ktorý je súčasťou funkcie max(), je zapísaný výraz, ktorý zistí väčšiu hodnotu z dvoch premenných x a y a výsledok vráti na miesto volania funkcie max(). Príkaz return v riadku 23 vráti nulu operačnému systému, tesne pred ukončením vykonávania programu.

  • 9

    Definícia funkcie (riadky 27 až 30) Funkcia je nezávislá časť programu, ktorá obsahuje vlastný kód napísaný tak, aby vykonával určitú úlohu.

    Každá funkcia má meno a kód. Kód, ktorý funkcia obsahuje, sa vykoná zapísaním mena funkcie v príkaze programu. Toto sa nazýva volanie funkcie.

    Funkcia max() (riadky 27 až 29), je užívateľom definovaná funkcia. Ako už názov napovedá, užívateľom definované funkcie sú napísané programátorom počas vývoja programu. Funkcia max() je jednoduchá a všetko čo robí, je, že porovná dve hodnoty (x a y) a vráti väčšiu z nich programu, ktorý funkciu zavolal. (Príkaz podmienka ? výraz1 : výraz2 vyhodnotí výraz1 v prípade platnosti podmienky, ináč vyhodnotí výraz2). V nasledujúcej lekcii „Funkcie a práca s pamäťou“ sa naučíme správnemu používaniu funkcií.

    Poznamenajme, že v reálnych programoch by sme asi nepoužili funkciu s takou jednoduchou úlohou, ako je vrátenie väčšej hodnoty z dvoch vstupných hodnôt. V našom ukážkovom programe sme tak spravili z demonštrač-ných dôvodov.

    C-čko obsahuje taktiež knižničné funkcie, ktoré sú súčasťou balíka prekladača jazyka C. Knižničné funkcie vykonávajú väčšinou bežné úlohy (ako je vstup/výstup na obrazovku, z klávesnice a disku), ktoré programy zväčša potrebujú. V našom príklade sú takými funkciami printf() a scanf(), ktoré sú obsiahnuté v knižnici STDIO (STandarD Input/Output). Komentáre (riadky 11, 15, 19 a 26)

    Ľubovoľná časť programu, ktorá začína dvojicou znakov /* a končí */, sa nazýva komentár. Prekladač všetky komentáre ignoruje, takže komentáre nemajú žiadny vplyv na vykonateľný program. Do komentára môžeme zapísať hocičo a pritom spôsob práce programu sa nezmení. Komentáre slúžia najmä pre programátorov, pretože sprehľad-ňujú niekedy na prvý pohľad nepochopiteľný program. Komentáre síce robia zdrojové kódy programov väčšími, ale obyčajne tvoria iba malý podiel.

    Komentáre by ste mali do programu písať už pri vytváraní zdrojového súboru a nie až po odladení („až na to niekedy zostane čas“).

    Komentár môže obsiahnuť časť riadku, celý riadok alebo niekoľko riadkov. ANSI norma jazyka C nedovoľuje používať vnorené komentáre (nested comments), napr.:

    /* toto je komentár /* a toto je vnorený komentár */ */. Väčšina začínajúcich programátorov považuje komentáre za neužitočnú a čas plytvajúcu vec. Toto je omyl!

    Funkcia vášho programu môže byť vcelku jasná, kým program píšete, alebo píšete veľmi jednoduchý program. Ale akonáhle začína byť program väčší a zložitejší, alebo keď potrebujete modifikovať program, ktorý ste napísali pred šiestimi mesiacmi, zistíte, že komentáre sú neoceniteľnou súčasťou programu.

    Komentujte váš zdrojový program, špeciálne príkazy alebo funkcie, ktoré by mohli byť nejasné vám alebo niekomu inému, kto bude modifikovať program neskôr. Uvádzajte komentár pred každou logicky ucelenou časťou kódu. Nekomentujte úplne jasné a samozrejmé príkazy, pretože prílišným komentovaním zneprehľadňujete program, čo sa týka čitateľnosti. Napr.: i = i + 1; /* zvysenie hodnoty premennej i o jedna */ Komentár má obsahovať iba užitočnú informáciu!

    Zložené zátvorky (riadky 8, 24, 28 a 30) Zložené zátvorky ({}) používame na uzavretie riadkov, ktoré vytvárajú každú funkciu v jazyku C – vrátane

    funkcie main(). Skupina jedného alebo viacerých príkazov uzavretých v zložených zátvorkách sa nazýva blok. Blok môže byť použitý vo väčšine prípadov tam, kde sa používa príkaz samostatne. Ako uvidíme v ďalších lekciách, jazyk C používa bloky na rôzne účely.

  • 10

    Zhrnutie Táto lekcia bola krátka, ale dosť dôležitá, pretože vás uviedla do problematiky komponentov programu v jazyku

    C. Naučili ste sa, že jediná povinná časť každého C programu je funkcia main(). Tiež ste sa naučili, že skutočné vykonávanie programu je realizované pomocou príkazov, ktoré nariaďujú počítaču, čo má vykonať. Táto lekcia vám ďalej vysvetlila pojmy premenná a definícia premennej, a ukázala vám, ako používať komentáre vo vašich zdrojových kódoch.

    Okrem funkcie main() môže C program používať dva typy funkcií: knižničné funkcie, dodávané ako súčasť balíka k prekladaču, a užívateľské (resp. užívateľom definované) funkcie, vytvorené programátorom.

    Cvičenia 1. Napíšte čo najmenší program.

    Riešenie: program c01-1.cpp

    2. Napíšte príklad komentára. Riešenie: súbor c01-2.cpp

    3. Uvažujte nasledovný program: 1: /* c01-3.cpp */ 2: #include 3: 4: void zobraz_ascii(void); 5: 6: main() 7: { 8: printf("ASCII tabulka viditelnych znakov (33 - 127)\n"); 9: zobraz_ascii(); 10: 11: return (0); 12: } 13: 14: /* vypise tabulku znakov */ 15: void zobraz_ascii(void) 16: { 17: int c; 18: 19: for (c = 33; c < 128; c++) 20: printf("%d\t%X\t%c\n", c, c, c); 21: } 22: /* koniec programu */

    a. Ktoré riadky obsahujú príkazy? b. Ktoré riadky obsahujú definície premenných? c. Ktoré riadky obsahujú funkčné prototypy? d. Ktoré riadky obsahujú definície funkcií? e. Ktoré riadky obsahujú komentáre?

    Riešenie: súbor c01-3.txt

    4. Čo vykonáva program z predchádzajúceho cvičenia? (preložte a spustite ho) Riešenie: súbor c01-4.txt

  • 11

    II. lekcia: Funkcie a práca s pamäťou V tejto lekcii sa zoznámime s funkciami ako so základným staveným kameňom každého programu v jazyku C.

    Naučíte sa, čo sú to funkcie, argumenty resp. parametre funkcie a ako sa do funkcie prenášajú, čo je to návratová hodnota funkcie a akým spôsobom sa odovzdáva volajúcej funkcii, čo je to hlavička funkcie a funkčný prototyp. Ďalej sa naučíte, ako sa funkcie deklarujú a definujú, aké problémy môžu nastať pri definícii funkcie a ako sú v jazy-ku C implementované procedúry. Nakoniec sa oboznámite s pojmami globálna, lokálna a lokálna statická premenná, naučíte sa o viditeľnosti a rozsahu platnosti premennej. Lekcia je teda venovaná funkciám a všetkému, čo s nimi súvisí. V tejto lekcii nie je uvedený výpis programu, pretože celá problematika sa demonštruje na výpise programu P01.CPP z predchádzajúcej lekcie.

    Jazyk C je založený na funkciách a teda každý program obsahuje jednu alebo viac funkcií. Ako už vieme, každý program v C musí obsahovať minimálne jednu funkciu, a tou je main(). Spracovávanie programu začína volaním funkcie main() a zväčša aj končí opustením tejto funkcie.

    Funkcia je nezávislá časť programového kódu, ktorá vykonáva určitú úlohu, a ktorá má pridelené meno. Použitím mena funkcie v programe sa vykoná kód tela funkcie. Program môže tiež posielať funkcii informácie, nazývané argumenty alebo parametre, a funkcia môže vrátiť informáciu, nazývanú návratová hodnota, časti programu, odkiaľ bola funkcia volaná. Každá funkcia má štandardne iba jeden výstup (návratová hodnota), no môže vrátiť i viacero hodnôt – pomocou smerníkov resp. globálnych premenných (viď. lekciu XIII – „Smerníky a volanie odkazom“).

    Funkcie v jazyku C nemôžu byť vnorené, t.j. jedna funkcia nemôže obsahovať v svojom tele definíciu druhej funkcie. Z toho vyplýva, že formálne parametre a lokálne premenné sú prístupné iba vo funkcii, v ktorej boli definované, a sú skryté zvonka tejto funkcie. Všetky funkcie v C vracajú hodnotu, no dajú sa použiť aj ako procedúry – možnosti viď. ďalej „Procedúry a dátový typ void“.

    Hlavička funkcie Hlavička funkcie poskytuje interfejs pre funkciu. Hlavička funkcie alebo interfejs je špecifikácia, ktorá vytvára

    spoločné rozhranie pre komunikáciu medzi funkciou a volajúcim programom.

    Obr. 2-1 Hlavička funkcie vytvára rozhranie medzi funkciou a volajúcim programom.

    Hlavička funkcie informuje prekladač, aké údaje (počet a typ parametrov) funkcia prijíma z volajúceho programu a aký údaj (typ návratovej hodnoty) funkcia vráti volajúcemu programu. Hlavička funkcie nie je ukončená bodkočiarkou ‘;’.

    Hlavička funkcie má tvar: typ_funkcie meno_funkcie(deklarácia_parametrov), kde typ_funkcie určuje typ návratovej hodnoty a deklarácia parametrov je zoznam dvojíc typ parameter, oddelený čiarkami. Parametre uvedené v zozname parametrov nazývame formálne parametre a pri volaní funkcie sú nahradené skutočnými hodnotami nazývanými aktuálne parametre. Napr. funkcia max() z príkladu P01.CPP má formálne parametre x a y (obidva sú typu int), a pri volaní funkcie v tele funkcie main() sú nahradené aktuálnymi parametrami a a b. Hlavička tejto funkcie je: int max(int x, int y)

    Deklarácia a definícia funkcie Definícia funkcie určuje ako hlavičku, tak aj jej telo, zatiaľ čo deklarácia funkcie špecifikuje iba hlavičku

    funkcie, t.j. meno funkcie, typ návratovej hodnoty a prípadne i typ a počet jej parametrov. Pokiaľ typ funkcie (typ návratovej hodnoty funkcie) neuvedieme, implicitne je funkcia typu int, napr. funkcia main() programu P01.CPP.

    parametre

    návratová hodnota

    Volajúci program

    Hlavička funkcie

    (interfejs)

    Telo funkcie

  • 12

    Keďže každá funkcia vracia nejakú hodnotu vrátane funkcie main() – má táto funkcia na poslednom riadku (riadok 23) príkaz return číslo; (funkcia je implicitne typu int). Podobne hlavička funkcie max() môže mať tvar:

    max(int x, int y) Telo funkcie je uzavreté do zložených zátvoriek „{“ a „}“, a môže obsahovať príkazy aj definície premenných.

    Návratová hodnota sa volajúcej funkcii odovzdáva pomocou príkazu: return (vyraz); alebo return vyraz;

    ktorý vypočíta hodnotu výrazu vyraz, vráti ju volajúcej funkcii a túto funkciu ukončí. Príkaz return môžeme špecifikovať nasledovne: Ak vykonávanie programu príde na príkaz return, ukončí sa

    vykonávanie funkcie, ktorá tento príkaz obsahuje. Vo funkcii main() príkaz return ukončí celý program. Ak sa po-mocou return vracia nejaká hodnota, jej typ záleží od typu funkcie (pozri hlavičku funkcie).

    Funkcia, ktorá nemá žiadne parametre, musí byť definovaná aj volaná včítane oboch okrúhlych zátvoriek! Ako už vieme, funkcia nemôže byť definovaná vo vnútri inej funkcie. Samozrejme, že funkcia môže byť vo

    vnútri inej funkcie volaná. Problém môže nastať, keď je funkcia definovaná až za definíciou funkcie, ktorá túto funkciu volá. Volajúca funkcia v tomto prípade nemá doposiaľ žiadne informácie o volanej funkcii (o návratovej hodnote, počte a typoch parametrov). Teda prekladaču je nutné oznámiť aspoň návratový typ a meno volanej funkcie pred jej volaním (počet a typ parametrov volanej funkcie nie je dôležitý). Pre umožnenie kontroly počtu a typov skutočných parametrov volanej funkcie je potrebné zadeklarovať volanú funkciu pomocou funkčného prototypu ešte pred samotným volaním funkcie.

    Funkčný prototyp poskytuje prekladaču informácie (meno a argumenty) o funkcii, ktorú program obsahuje. Funkčný prototyp musí byť definovaný ešte predtým, než je funkcia prvýkrát volaná, pokiaľ ešte nie je zadefinovaná. Typický problém s umiestnením definície funkcie vyvstáva, keď potrebujeme vo funkcii a() volať funkciu b(), ktorá rekurzívne (tzn. opäť) volá funkciu a(). Ako uvidíme neskôr, v našom programe kalkulátor sa tento problém vyskytne pri definícii funkcie faktor(), ktorá rekurzívne volá funkciu vyraz(). Funkcia vyraz() volá funkciu term() a funkcia term() zase volá funkciu faktor(). Situácia je znázornená na nasledujúcom obrázku:

    Obr. 2-2 Rekurzívne volanie funkcie vyraz() z funkcie faktor().

    Ak sa rozhodneme napísať definície týchto troch funkcií v postupnosti ich volaní, narazíme na problém definovania funkcie faktor(). Pripomíname, že funkciu môžeme volať až po jej definícii. Postupnosť definovania funkcií by bola nasledovná. Funkcia main() volá funkciu vyraz(), teda funkciu vyraz() musíme zadefinovať ešte pred funkciou main(). Keďže funkcia vyraz() používa funkciu term(), definíciu funkcie term() umiestnime pred definíciu funkcie vyraz(). Vo vnútri funkcie term() sa však volá funkcia faktor(), a teda definícia funkcie faktor() musí byť umiestnená v programe ešte pred definíciou funkcie term(). Funkcia faktor() ale volá funkciu vyraz(), ktorá je definovaná v zdrojovom súbore až za ňou!

    Na riešenie tohto problému využijeme funkčný prototyp, ktorým ešte pred samotnou definíciou funkcie faktor() oznámime prekladaču kompletné informácie (typ návratovej hodnoty, typy a počet argumentov) o funkcii vyraz().

    Úplný funkčný prototyp sa skladá z hlavičky funkcie ukončenej bodkočiarkou ‘;’. Napr. v programe P01.CPP máme v riadku 5 uvedený funkčný prototyp funkcie max(), ktorým sme funkciu iba zadeklarovali, ale jej definícia sa nachádza až v riadkoch 27 až 30. Na upresnenie uvádzame, že riadok 27 predstavuje hlavičku funkcie max().

    faktor()

    vyraz() term()

  • 13

    Procedúry a dátový typ void Formálne síce v C procedúry neexistujú, ale sú dva spôsoby, ako tento „nedostatok“ obísť: 1. Funkcia návratovú hodnotu síce vráti, ale nikto ju nechce. Typický príklad je čakanie na stlačenie klávesu

    pomocou funkcie getchar() z knižnice STDIO.H, ktorá pri normálnom použití vráti stlačený znak, teda návra-tová hodnota funkcie je stlačený znak. Príklad volania funkcie ako procedúry:

    getchar(); /* čakanie na stlačenie klávesu */ 2. Funkcia sa definuje ako funkcia vracajúca typ void (tzn., že nevracia žiadnu hodnotu), napr.:

    void pouzitie() { printf("Help k programu calc\n––––––––\n"); ... }

    Príkaz return v tomto prípade nie je nutný. Pokiaľ nie je uvedený, nahrádza ho uzatvárajúca zložená zátvorka funkcie „}“. Príkaz return sa potom používa iba pre nútené ukončenie funkcie pred dosiahnutím jej konca, napr. po nejakej podmienke, a má tvar return;. Typ void sa používa aj v prípade, že funkcia nemá žiadne formálne parametre, aby bol prekladač o tom uistený. Napr. ak hlavná funkcia nemá žiadne vstupné parametre a ani nevracia operačnému systému žiadnu návratovú hodnotu, potom hlavička funkcie vyzerá nasledovne:

    void main(void)

    Parametre funkcií Jazyk C umožňuje iba jeden spôsob dodávania parametrov funkcii, a to hodnotou. Pri tomto spôsobe prenášania

    parametrov sa hodnoty aktuálnych (skutočných) parametrov kopírujú cez zásobník do formálnych parametrov funk-cie. Obr. 2-3 Volanie hodnotou.

    Pri prenášaní parametrov hodnotou skutočné parametre nemôžu byť vo funkcii zmenené, pretože vo funkcii sa pracuje s kópiou hodnôt skutočných parametrov. Teda akákoľvek zmena parametrov vo vnútri funkcie je iba dočasná a po opustení funkcie sa stráca.

    Ak potrebujeme vo funkcii zmeniť hodnoty skutočných parametrov – urobiť trvalú zmenu, musíme funkcii dodať namiesto hodnoty parametra jeho adresu (adresu v pamäti, kde sa argument nachádza). Potom už funkcia môže zmeniť hodnotu parametra, pretože bude meniť obsah na dodanej adrese v pamäti. Tento spôsob riešenia sa nazýva volanie odkazom. Na prenos adresy sa využívajú smerníky. Obr. 2-4 Volanie odkazom.

    S realizáciou volania odkazom sa bližšie oboznámime v lekcii XIII „Smerníky a funkcie – volanie odkazom“.

    Kopírovanie Skutočné parametre

    Formálne parametre

    Volajúci program Funkcia

    Skutočné parametre Adresa

    Formálne parametre

    Volajúci program Funkcia

  • 14

    Definície premenných Definícia premennej sa môže vyskytovať buď vonku/mimo funkcie, vtedy hovoríme o globálnej premennej,

    alebo vo vnútri funkcie, a vtedy takúto premennú nazývame lokálna premenná. Napríklad premenná c v riadku 3 programu P01.CPP je globálna premenná, ale premenné a a b uvedené v riadku 9 sú lokálne.

    Globálne premenné Definície globálnych premenných sa vyskytujú mimo definícií funkcií. Definícia globálnej premennej definuje

    premennú, ktorej rozsah platnosti je od miesta definície až do konca súboru – nie programu! (program môže pozostávať z viacerých súborov.) Prístup k tejto premennej má teda každá funkcia, ktorá je definovaná za definíciou globálnej premennej. Keďže globálnu premennú môže meniť ľubovoľná funkcia, snažíme sa vyhýbať používaniu týchto premenných, pretože pri nejednoznačnom toku (spracovávaní programu) nie je jednoduché zistiť, ktorá funkcia zmenila obsah tejto premennej. Používaním globálnych premenných sa zároveň znižuje modularita programu.

    Globálne premenné obsadzujú miesto v dátovej oblasti pamäti. Globálne premenné využívame najčastejšie vtedy, keď potrebujeme k premennej pristupovať v každej funkcii ⇒ hodnotu premennej nemusíme prenášať cez parameter; alebo ak by sa prenášaním hodnoty pomocou parametra a návratovej hodnoty funkcie príliš zneprehľadnil kód funkcie – viď. použitie globálnych premenných sym a cislo v rekurzívnej funkcii faktor(), term(), vyraz() a funkcii getSymbol() v príkladoch od lekcie XVI.

    Lokálne premenné Lokálnou premennou je každá premenná definovaná vo vnútri funkcie resp. bloku (pripomíname, že blok je

    ľubovoľná časť programu uzavretá v zložených zátvorkách { a }). Lokálna premenná vymedzuje miesto v zásobníku a je viditeľná iba zvnútra funkcie alebo bloku, v ktorom je definovaná. Rozsah platnosti lokálnej premennej je od miesta jej definície až po koniec funkcie/bloku, v ktorej bola premenná definovaná. S ukončením spracovávania funkcie/bloku lokálna premenná zaniká (zruší sa miesto vymedzené v zásobníku) a pri opätovnom vstupe do funkcie je jej hodnota nedefinovaná! Tip: Ak potrebujete zabezpečiť, aby sa hodnota lokálnej premennej medzi volaniami funkcie zachovala, napíšte pred definíciu premennej kľúčové slovo static.

    Ak vo funkcii zadefinujeme premennú s rovnakým názvom ako je názov globálnej premennej, prekryjeme globálnu premennú definíciou lokálnej premennej, a teda v tejto funkcii už nemáme prístup ku globálnej premennej (viď. príklad premennej cislo vo funkcii root cieľového programu kalkulátor).

    Cvičenia 1. Hodnota resp. výraz, ktorý pomocou príkazu return vraciame volajúcej funkcii, sa z konvencie píše do zátvo-

    riek, i keď sa nemusí. Vyskúšajte na príklade programu P01.CPP prepísať vo funkcii main() príkaz return bez zátvoriek a presvedčte sa o funkčnosti.

    Riešenie: program c02-1.cpp

    2. V programe P01.CPP definujte funkciu main() ako procedúru, tzn. nech funkcia nevracia žiadnu hodnotu. Aký význam má v tomto prípade príkaz return?

    Riešenie: program c02-2.cpp

  • 15

    III. lekcia: Formátovaný vstup/výstup z/na terminál Cieľom tejto lekcie je oboznámiť vás s príkazmi pre formátovaný vstup/výstup z/na terminál. Pod pojmom vstup

    z terminálu máme na mysli vstup z klávesnice a pod pojmom výstup na terminál máme na mysli výstup na obrazovku. S funkciami pre vstup/výstup zo/do súboru sa oboznámite v lekcii XVII – „Práca so súbormi, štandardný vstup/výstup“. Slovom formátovaný vyjadrujeme skutočnosť, že napr. vypísanie hodnoty čísla na obrazovku (prípadne jeho vstup z klávesnice) môžeme vykonať v rôznych formátoch (napr. dekadický, hexadecimálny alebo znakový tvar celého čísla, resp. rôzny počet desatinných miest pre zobrazenie reálnych čísel, zarovnanie hodnôt k pravému alebo ľavému okraju a pod.). Výpis programu P03.CPP 1: #include 2: 3: main() 4: { 5: int cislo; 6: 7: printf("Zadaj cele cislo: "); 8: scanf("%d", &cislo); 9: 10: printf("Zadal si cislo %d\n\n", cislo); 11: 12: return(0); 13: }

    Vysvetlivky: printf – príkaz na formátovaný výstup na obrazovku scanf – príkaz na formátovaný vstup z klávesnice "%d" – riadiaci reťazec formátu \n – znak nového riadku

    Formátovaný výstup na obrazovku Funkcia printf() slúži na formátovaný výstup na obrazovku. Jazyk C nedefinuje žiadnu I/O (vstupno/výstupnú –

    z angl. Input/Output) operáciu ako časť jazyka, ale na prácu s nimi poskytuje príkazy, ktoré sa nachádzajú v štandardnej knižnici STDIO. Preto pre prácu s funkciami pre vstup a výstup je potrebné na začiatku programu vložiť pomocou direktívy #include hlavičkový súbor STDIO.H (riadok 1), v ktorom sa nachádzajú prototypy týchto funkcií.

    Prvým argumentom funkcie printf() je tzv. riadiaci reťazec formátu. Riadiaci reťazec formátu je obyčajný reťazec znakov uzavretý v úvodzovkách, ktorý môže obsahovať:

    • formátové špecifikácie – postupnosť začínajúca znakom „%“, ktorá určuje formát výpisu hodnoty premennej • znakové postupnosti – postupnosť znakov, ktorá nezačína znakom „%“ a vypíše sa tak, ako je zapísaná Počet argumentov funkcie printf() je premenlivý a závisí od počtu formátových špecifikácií takto: koľko

    znakov % sa nachádza v riadiacom reťazci formátu, toľko parametrov oddelených čiarkami musí nasledovať za riadiacim reťazcom. Napr. v našom programe (riadok 10) sme v riadiacom reťazci formátu použili jednu formátovú špecifikáciu (jeden znak %), a teda za reťazcom nasleduje jeden parameter, kým v riadku 7 sme nepoužili žiadnu formátovú špecifikáciu, a teda za riadiacim reťazcom formátu nenasleduje žiadny parameter. Parametrom pre funkciu printf() môže byť premenná alebo konštanta. Napr. v riadku 10 môžeme namiesto premennej cislo priamo napísať číselnú konštantu 458.

    Formátovou špecifikáciou vo funkcii printf() určujeme, ako sa vypíše hodnota premennej alebo konštanty, ktorá nasleduje za riadiacim reťazcom formátu a v danom poradí prislúcha k formátovej špecifikácii. Napr. v našom programe sme definovali premennú cislo typu int (riadok 5), ktorej hodnotu vypisujeme v riadku 10. Keďže premenná je typu int, formátovou špecifikáciou %d uvádzame, že na danom mieste (kde sa nachádza v riadiacom reťazci formátu) sa má vypísať hodnota celého čísla typu int v desiatkovom tvare. Vo funkcii printf() za riadiacim reťazcom formátu uvádzame premenné, ktorých hodnoty chceme vypísať.

  • 16

    Pre typ int je teda formátová špecifikácia %d resp. %i pre zobrazenie čísla v desiatkovej sústave, %o pre zobrazenie čísla v osmičkovej sústave, %x resp. %X pre zobrazenie čísla v šestnástkovej sústave. Pre reálne čísla s dvojnásobnou presnosťou (typ double) má funkcia printf() k dispozícii formátové špecifikácie %lf, %le, %lg, %lE a %lG. Medzi znakom % a znakmi určujúcimi typ premennej vo formátovej špecifikácii môže byť uvedené číslo v tvare [m][.n] (obidva parametre sú voliteľné) udávajúce minimálnu šírku a presnosť, v ktorej sa vypíše reálne číslo (typ float, double, resp. long double), tzn. že číslo sa vypíše minimálne na m miest, z toho n desatinných miest včítane desatinnej bodky.

    Pre zobrazenie znaku sa používa formátová špecifikácia %c a pre reťazec %s. Medzi úvodným znakom % a koncovým znakom formátovej špecifikácie môžu byť uvedené ešte ďalšie symboly (napr. zarovnanie čísla doprava/doľava, zobrazenie čísla so znamienkom, doplnenie čísla nulami zľava a pod.), ktorých výklad nie je cieľom tejto príručky – je ich možné nájsť v referenčnej príručke jazyka C. Niektoré horeuvedené formátové špecifikácie si vyskúšate v cvičení č. 4 tejto lekcie.

    V riadiacom reťazci formátu je možné použiť aj tzv. escape sekvencie, čo sú znaky resp. čísla (buď v osmičko-vej alebo šestnástkovej sústave) uvedené za znakom „\“, ktoré majú špeciálny význam. Nasleduje výpis tých escape sekvencií aj s významom, ktoré použijeme v našom programe kalkulátor:

    \n – znak nového riadku (new line character); pri výstupe spôsobí odriadkovanie \t – znak tabelátora; pri výstupe spôsobí posunutie vpravo o určitý počet znakov \0 – nulový znak (null character); ukončuje reťazec V programe P03.CPP sme v riadku 10 použili znak ‘\n’ dvakrát, čím sme docielili, že za zobrazeným číslom sa

    odriadkuje a vypíše sa jeden prázdny riadok.

    Poznámka: Keďže znaky ‘\’ a ‘%’ majú v riadiacom reťazci formátu špeciálny význam, na ich zobrazenie pomocou funkcie printf() musíme príslušný znak zdvojiť, teda napr. %% vypíše znak percenta alebo \\ vypíše znak opačnej lomky. Ak potrebujeme zobraziť znak úvodzovky, musíme pred ňou uviesť znak ‘\’.

    Formátovaný vstup z klávesnice Štandardná knižnica STDIO nám na formátovaný vstup z klávesnice poskytuje funkciu scanf(). Funkcia má

    podobne ako printf() premenlivý počet parametrov, pričom prvým parametrom funkcie je opäť riadiaci reťazec formátu a zvyšný počet argumentov funkcie závisí od počtu formátových špecifikácii. V riadiacom reťazci formátu sa na rozdiel od funkcie printf() používajú iba formátové špecifikácie, oddeľovače (napr. znak medzera) a niektoré escape sekvencie, ktoré však majú pri vstupe z terminálu odlišný význam.

    Všetky formátové špecifikácie, ako sú napr. %d, %lf, %x, %s, %c a i., majú ekvivalentný význam ako vo funkcii printf(), tzn. sú zviazané s rovnakými údajovými typmi. Šírka [m] udáva maximálny počet znakov, ktoré sa načítajú z klávesnice a má význam iba pri reťazcoch. Pri reálnych číslach môžeme pri zadávaní čísla použiť aj exponenciálnu notáciu, t.j. tam, kde sa očakáva reálne číslo typu float, double resp. long double, môžeme zadať z klávesnice číslo v tvare 1234.56 rovnako ako 1.23456E4 alebo 12.3456e-2 a pod.

    Zásadný rozdiel vo volaní funkcie scanf() oproti funkcii printf() nastáva pri argumentoch uvedených za riadia-cim reťazcom formátu, pretože pred všetkými premennými jednoduchých typov (celé a reálne čísla – nie polia a reťazce) je potrebné uvádzať znak & (ampersand), ktorým označujeme adresu premennej, kam sa má uložiť načíta-ná hodnota. V predchádzajúcej lekcii sme sa dozvedeli, že funkcia dokáže vrátiť štandardne iba jednu hodnotu, a tou je pri funkcii scanf() počet úspešne načítaných položiek (čísel, znakov, reťazcov, ...). Ďalej sme sa dozvedeli, že parametre sa do funkcií prenášajú hodnotou (tzn. funkcia nedokáže meniť hodnotu skutočného parametra). Ak má teda prekladač zabezpečiť načítanie viacerých hodnôt a navyše funkcia má vrátiť počet načítaných hodnôt – všetko sú to výstupy funkcie („návratové hodnoty“) – musíme funkcii predať adresy premenných, kam sa uložia tieto hodnoty. Toto sa realizuje pridaním znaku & pred meno premennej a nazývame to volanie odkazom (viď. lekciu XIII „Smerníky a volanie odkazom“).

    Pozor! Ak zabudneme vo funkcii scanf() pred premennou uviesť adresný operátor (znak &), prekladač nevy-hlási žiadnu chybu ani varovanie a program pracuje nekorektne. Prekladač totiž predpokladá, že hodnota premennej predstavuje adresu, kam sa má uložiť výsledok (načítaná hodnota z klávesnice) a teda nepovažuje to za chybu.

  • 17

    V našom príklade chceme v riadku 8 načítať celé číslo typu int do premennej cislo. Ak používateľ zadá namiesto očakávaného čísla napr. reťazec „qkt48w“, funkcia scanf() vráti nulu a hodnota premennej cislo bude nedefinovaná, pretože premenná nie je inicializovaná a jej pamäťové miesto je vyhradené v zásobníku (viď. predchá-dzajúcu lekciu). Ak používateľ zadá číslo „4.135“, program načíta číslo 4, pretože podľa formátovej špecifikácie očakáva celé číslo a znak ‘.’ už nie je znakom celého čísla a reťazec „.135“ zostane v bufferi klávesnice.

    Funkcia scanf() úvodné biele znaky (medzery, tabulátory, odriadkovania) ignoruje, a je teda jedno, koľkokrát stlačíme napríklad kláves Enter pred zadaním čísla. Znak medzery v riadiacom reťazci formátu pred formátovou špecifikáciou označuje, že sa majú ignorovať biele znaky.

    Upozornenie – platí pre printf() aj scanf():

    Prekladač jazyka C nekontroluje, či typ premennej, ktorú vypisujeme alebo čítame, zodpovedá typu uvedenému vo formátovej špecifikácii riadiaceho reťazca a nehlási žiadnu chybu ani varovanie! Taktiež nekontroluje či počet argumentov za riadiacim reťazcom formátu zodpovedá počtu formátových špecifikácií (znakov %). Preto treba dávať veľký pozor pri používaní uvedených funkcií, aby počet a typ argumentov presne zodpovedal špecifikácii uvedenej v riadiacom reťazci formátu.

    Cvičenia 1. Napíšte procedúru pouzitie (bez parametrov), ktorá pomocou príkazov printf() vypíše návod na použitie

    programu kalkulátor s nasledovným textom: 1. riadok 2. riadok Help k programu calc 3. riadok -------------------- 4. riadok Spustenie programu: calc.exe [subor1] [subor2] 5. riadok bez parametrov - spusti kakulator v interaktivnom mode 6. riadok subor1 - vstupny subor, v ktorom su ulozene vyrazy 7. riadok subor2 - volitelne meno vystupneho suboru, v ktorom budu vypocitane vyrazy 8. riadok ak nie je zadane, vysledky sa vypisu na obrazovku 9. riadok

    Riešenie: súbor c03-1.cpp

    2. a) Odstráňte znak & pred premennou cislo vo funkcii scanf() programu P03.CPP, program skompilujte (preložte) a vyskúšajte jeho funkčnosť. Všimnite si počet chýb a varovaní pri preklade.

    Riešenie: program c03-2a.cpp

    b) Zameňte formátovú špecifikáciu %d v riadku 10 programu P03.CPP za %lf alebo ľubovolnú inú, ktorá sa používa pre reálne čísla, a vyskúšajte funkčnosť programu. Všimnite si počet chýb a varovaní pri preklade.

    Riešenie: program c03-2b.cpp

    c) Ako už vieme, vo funkcii printf() neuvádzame pred premennou znak &, pretože na mieste formátovej špecifikácie (napr. %d) sa očakáva hodnota a nie adresa. Znak & v tomto prípade spôsobí, že sa hodnota prečíta z adresy určenej obsahom premennej, t.j. jej hodnotou. Doplňte znak adresného operátora (znak &) pred premennú cislo v riadku 10 programu P03.CPP a vyskúšajte funkčnosť programu. Opäť si všimnite počet chýb a varovaní pri preklade.

    Riešenie: program c03-2c.cpp

  • 18

    3. Prepíšte program P03.CPP tak, aby načítal reálne číslo typu double a vypísal ho. Po spustení programu skúste zadať ako vstup číslo v exponenciálnom tvare (napr. číslo 4.87e-2).

    Riešenie: program c03-3.cpp

    4. Na programe z predchádzajúceho cvičenia v príkaze printf(), ktorým vypisujete zadanú hodnotu, vyskúšajte postupne formáty čísel: %5.2lf, %.3lf, %010.3lf, %lG, %+lG a %.15lG prípadne iba %lf a zistite, ako sa vypíšu čísla: 3, 4.12, -15.2e-3, 12.34567, atď.

    Riešenie: program c03-4.cpp

  • 19

    IV. lekcia: Riadiace štruktúry – príkaz vetvenia Príkaz if a ternárny operátor

    Cieľom tejto lekcie je oboznámiť vás s príkazom vetvenia, pomocou ktorého dosahujeme podmienené vykoná-vanie programu. Tzn., že na základe určitej podmienky sa vykoná jedna časť programu, zatiaľ čo pri jej nesplnení sa vykoná iná časť programu. V tejto lekcii sa tiež oboznámite s podmieneným výrazom, ktorého funkcionalita je podobná príkazu vetvenia a v jazyku C sa často používa, pretože skracuje zápis zdrojového kódu programu. Výpis programu P04.CPP 1: #include 2: 3: /* prototyp funkcie */ 4: double abs(double cislo); 5: 6: void main() 7: { 8: double cislo; 9: 10: printf("Zadaj realne cislo: "); 11: scanf("%lf", &cislo); 12: 13: printf("Absolutna hodnota z %+lG = %lG\n\n", cislo, abs(cislo)); 14: } 15: 16: /* funkcia vrati absolutnu hodnotu cisla */ 17: double abs(double cislo) 18: { 19: if (cislo < 0) 20: return(-cislo); 21: else 22: return(cislo); 23: }

    Vysvetlivky: if ... else ... – príkaz vetvenia programu < – relačný operátor „menší ako“

    Príkaz if Podmienené vykonávanie programu docielime pomocou príkazu if. Príkaz if má jeden z nasledujúcich tvarov:

    alebo

    Za príkazom if musí nasledovať výraz uzavretý v okrúhlych zátvorkách. Výraz sa vyhodnotí a jeho hodnota sa využije ako podmienka na vykonanie príkazu. Podmienkou býva najčastejšie Booleovský výraz, pričom logická hodnota FALSE (nepravda) zodpovedá hodnote 0, a logická hodnota TRUE (pravda) zodpovedá ľubovoľnej inej hodnote ako 0 (najčastejšie 1, ale nie je to podmienkou).

    Poznámka: Jazyk C priamo neobsahuje typ Boolean. Logické hodnoty sú reprezentované pomocou celočísel-ných hodnôt (typ int), ktoré sú interpretované vyššie uvedeným spôsobom.

    V konštrukcii if môžeme namiesto príkazu uviesť aj blok príkazov, t.j. niekoľko príkazov uzavretých do zlože-ných zátvoriek { a }. Zo syntaxe príkazu if vidíme, že vetva else nie je povinná (tvar príkazu if uvedený vľavo).

    if (výraz) príkaz;

    if (výraz) príkaz1; else príkaz2;

  • 20

    Sémantika príkazu if je jednoduchá. Najskôr sa vyhodnotí výraz uvedený v okrúhlych zátvorkách. Ak je výsledkom logická hodnota TRUE, vykoná sa príkaz1, ináč (logická hodnota FALSE) sa vykoná príkaz2. Pre tvar príkazu if, ktorý je uvedený vľavo, platí, že príkaz sa vyhodnotí iba v prípade, že podmienka (výraz) je splne-ná, t.j. výsledkom výrazu je logická hodnota TRUE. Celú sémantiku vyjadruje obrázok 4-1, na ktorom je uvedený vývojový diagram konštrukcie if–else.

    Obr. 4-1 Vývojový diagram konštrukcie if–else.

    V programe P04.CPP sme príkaz if použili vo funkcii pre výpočet absolútnej hodnoty (riadky 17 až 23). Ak je hodnota skutočného parametra cislo záporná (riadok 19), funkcia vráti negovanú hodnotu cisla (riadok 20), ináč vráti pôvodnú hodnotu cisla (riadok 22).

    Ternárny operátor Jazyk C poskytuje aj tzv. podmienený výraz, ktorým je ternárny operátor. Syntax podmieneného výrazu je:

    podmienka ? výraz1 : výraz2 a má ten význam, že podmienka sa vyhodnotí ako Booleovský výraz, a ak platí, vyhodnotí sa výraz1, ináč sa vyhodnotí výraz2. Ak za podmieneným výrazom uvedieme bodkočiarku ‘;’, stane sa z výrazu príkaz, ktorý je ekvivalentný s príkazom:

    if (podmienka) výraz1 else výraz2;.

    else

    if výraz

    príkaz1

    príkaz2

    true (nenulová hodnota)

    false (nulová hodnota)

  • 21

    Cvičenia 1. Napíšte funkciu abs() bez vetvy else. Využite znalosť, že príkaz return ukončuje vykonávanie funkcie.

    Riešenie: súbor c04-1.cpp

    2. Prepíšte funkciu abs() tak, že bude obsahovať iba príkaz return a skrátenú formu príkazu if, t.j. podmienený výraz.. Pozor! Zložené zátvorky { a } musia nasledovať za hlavičkou funkcie abs(), aj keď funkcia obsahuje v tomto prípade iba jeden príkaz, pretože oznamujú prekladaču definíciu funkcie (viď. lekciu II – časť „Dekla-rácia a definícia funkcie“).

    Riešenie: súbor c04-2.cpp

    3. Napíšte funkciu s prototypom double max(double x, double y); ktorá vráti väčšie číslo zo svojich argumentov x a y. Funkciu implementujte pomocou príkazu if aj pomocou ternárneho operátora. Na porovnanie hodnôt x a y použite relačný operátor „väčší“, ktorý má v jazyku C syntax „>”.

    Riešenie: súbor c04-3.cpp

    4. Podobne, ako v cvičení 3, napíšte funkciu min(x, y), ktorá vráti menšie číslo z x a y. Riešenie: súbor c04-4.cpp

  • 22

    V. lekcia: Booleovské výrazy Cieľom tejto lekcie je oboznámiť vás bližšie s Booleovskými výrazmi, najmä s ich vyhodnocovaním v jazyku C.

    Ako ste sa dozvedeli v predchádzajúcej lekcii, tak Booleovské výrazy najčastejšie používame ako podmienku pri podmienenom vykonávaní programu. V nasledujúcich lekciách uvidíme, že Booleovské výrazy sa používajú aj v ria-diacich častiach iteračných príkazov, ktorými sú napr. cykly, rekurzívne funkcie, atď. Keďže Booleovské výrazy sa v programoch veľmi často používajú, je im venovaná samostatná lekcia.

    V tejto lekcii si v cvičeniach precvičíte príkaz if a ternárny operátor, s ktorými ste sa oboznámili v predchádzajú-cej lekcii.

    Výpis programu P05.CPP 1: #include 2: 3: /* prototypy funkcii */ 4: int isdigit (char x); 5: int islower (char x); 6: char toupper (char ch); 7: 8: void main() 9: { 10: char znak; 11: 12: printf("\nZadaj jeden znak: "); 13: znak = getchar(); 14: 15: if (isdigit(znak)) 16: printf("Znak '%c' je cislica.\n", znak); 17: else 18: if (islower(znak)) 19: printf("Znak '%c' je velke pismeno.\n", toupper(znak)); 20: else 21: printf("Znak '%c' nie je ani cislica ani male pismeno.\n", znak); 22: 23: } 24: 25: /* Funkcia vrati TRUE (1), ak znak x predstavuje cislicu, * 26: * inac vrati FALSE (0) */ 27: int isdigit(char x) 28: { 29: return(x >= '0' && x = 'a' && x

  • 23

    Vysvetlivky: = – operátor priradenia >= – relačný operátor "väčší alebo rovný" Väčší cvičenie 3 predchádzajúcej lekcie >= Väčší alebo rovný riadky 29 a 36 programu P05.CPP

  • 24

    Skrátené vyhodnocovanie logických výrazov Logický súčin a súčet sa v jazyku C vyhodnocujú v tzv. skrátenom vyhodnocovaní (angl. lazy evaluation).

    Znamená to, že argumenty sú vyhodnocované zľava doprava a akonáhle je možné určiť konečný výsledok, vyhodno-covanie okamžite končí.

    Napr. vo funkcii islower() (riadky 34 až 37) ak znak x predstavuje číslicu '9', tak už hneď podmienka v prvom podvýraze (x >= 'a') nie je splnená, a teda je už známy konečný výsledok, pretože podvýrazy sú spojené logickým súčinom a FALSE krát hocičo je v logike vždy FALSE.

    Tento spôsob vyhodnocovania má v C praktické využitie. Napr. výraz: if (y != 0 && x / y < z) ...

    je úplne správny a k deleniu nulou v tomto prípade nikdy nemôže prísť, pretože prvá časť logického výrazu (y != 0) ukončí vyhodnocovanie tohto výrazu pred delením.

    Cvičenia 1. Presvedčte sa pomocou príkazu printf("%d", ...) a volania funkcie isdigit() raz s parametrom '5'

    a druhý raz s parametrom 'B', že návratová hodnota funkcie isdigit() je 1 v prípade TRUE a 0 v prípade FALSE.

    Riešenie: program c05-1.cpp

    2. Prepíšte telo funkcie isdigit() pomocou príkazu if a presvedčte sa na volaní funkcie, že nenulová návratová hodnota (napr. –1), v prípade splnenej podmienky, znamená TRUE.

    Riešenie: program c05-2.cpp

    3. Prepíšte ternárny operátor vo funkcii toupper() programu P05.CPP pomocou príkazu if, a naopak prepíšte konštrukciu if–else–if–else vo funkcii main() pomocou jediného príkazu printf() a ternárnych operátorov. Pomôcka: Ak potrebujete pomocou príkazu printf() vypísať reťazec, použite formátovú špecifikáciu %s

    v riadiacom reťazci formátu (pozri lekciu III).

    Riešenie: program c05-3.cpp

    Tipy a triky Tip 1: Podobne, ako funkcia getchar(), ktorá slúži na načítanie znaku zo štandardného vstupu, existuje aj funkcia

    putchar() s prototypom int putchar(int c), ktorá vypíše znak c na štandardný výstup (obrazovka). Tip 2: Ak potrebujete načítať z klávesnice práve jeden znak bez nutnosti stlačenia klávesu Enter, použite funkciu

    getch() resp. getche() z knižnice ConIO, ktorá však nie je súčasťou jazyka C podľa ANSI štandardu, tzn. nemusí ju obsahovať každý prekladač jazyka C. Prekladač od fy. Borland však tieto funkcie poskytuje. Predtým, než môžete použiť aspoň jednu z uvedených funkcií, musíte na začiatku programu vložiť hlavičkový súbor tejto knižnice pomocou direktívy #include . Rozdiel medzi getch() a getche() je v tom, že v prípade getche() sa znak načítaný z klávesnice vypíše aj na obrazovku. Vyskúšajte vo funkcii main() programu P05.CPP vymeniť riadok 13 za nasledovný a odskúšajte správanie sa programu:

    znak = getche();

  • 25

    VI. lekcia: Riadiace štruktúry – iteračné príkazy Príkazy while, break a continue

    Cieľom tejto lekcie je oboznámiť vás s príkazom cyklu s podmienkou na začiatku, pomocou ktorého dosahu-jeme opakované vykonávanie programu na základe určitej podmienky. Ďalej sa naučíme, ako môžeme ovplyvniť priebeh cyklu pomocou príkazov na riadenie cyklu. Nakoniec sa zoznámime so zloženým priraďovacím príkazom (príkaz priradenia s operátorom). Výstupom tejto lekcie bude funkcia pre výpočet najväčšieho spoločného deliteľa, ktorú využijeme v našom cieľovom programe kalkulátor. Výpis programu P06.CPP 1: #include 2: 3: /* prototypy funkcii */ 4: double abs(double cislo); 5: int NSD(int a, int b); 6: 7: void main() 8: { 9: int x, y; 10: int vysledok; 11: 12: printf("Zadaj dve cele cisla oddelene medzerou: "); 13: scanf("%d %d", &x, &y); 14: 15: vysledok = NSD(abs(x), abs(y)); 16: printf("Najvacsi spolocny delitel z %d a %d je %d\n\n", x, y, vysledok); 17: 18: } 19: 20: /* Dijkstrov algoritmus pre vypocet najvacsieho spolocneho delitela */ 21: int NSD(int a, int b) 22: { 23: if (a == 0 || b == 0) 24: return(1); 25: 26: while(a != b) 27: { 28: if (a > b) 29: a=(a-b); 30: else 31: b=(b-a); 32: } 33: 34: return (a); 35: } 36: 37: 38: /* funkcia vrati absolutnu hodnotu cisla */ 39: double abs(double cislo) 40: { 41: return (cislo < 0 ? -cislo : cislo); 42: }

    Vysvetlivky: == – operátor porovnania != – operátor nerovnosti || – logický súčet (OR) while – príkaz cyklu s podmienkou na začiatku

  • 26

    Operátor porovnania Pozor na rozdiel medzi porovnaním (operátor ==) a priradením (operátor =). a = 0 je celočíselný výraz s hodnotou 0, ktorú priraďuje premennej a – zmení jej pôvodnú hodnotu. a == 0 je celočíselný výraz poskytujúci 1 (TRUE), ak má premenná a hodnotu 0, alebo poskytujúci

    0 (FALSE), ak má a hodnotu inú než 0. Hodnota premennej a sa nemení! (viď. riadok 23)

    Cyklus s podmienkou na začiatku Syntax príkazu while:

    while (podmienka) príkaz;

    Poznámky: • V I. lekcii sme sa naučili, že tam, kde sa očakáva príkaz, môže byť väčšinou použitý aj blok, t.j. niekoľko

    príkazov uzavretých do zložených zátvoriek { a }, a preto namiesto príkazu môže byť uvedený blok príka-zov.

    • Zátvorky okolo podmienky sú povinné – podobne ako v príkaze if. • podmienka je Booleovský výraz, ktorý sa vyhodnotí a jeho výsledok (0 = FALSE; iné ako 0 = TRUE)

    sa použije ako podmienka na vykonanie tela cyklu (príkazu).

    Obr. 6-1 Vývojový diagram príkazu while.

    V našom príklade sme cyklus while použili na implementáciu funkcie NSD, ktorej cieľom je nájsť najväčší spo-ločný deliteľ dvoch čísiel (argumenty funkcie) pomocou Dijkstrovho algoritmu. Telo cyklu while (riadky 27 až 32) sa vykonáva dovtedy, kým je splnená podmienka vykonávania cyklu (riadok 26), t.j. kým hodnoty obidvoch premen-ných (formálne parametre a a b – pozri hlavičku funkcie v riadku 21) nie sú rovnaké.

    while podmienka

    príkaz(y) cyklu

    false

    true

  • 27

    Príkazy break a continue Vo všetkých typoch cyklov – while, do...while a for (viď. nasledujúce lekcie) – možno použiť príkazy break

    a continue, ktoré menia normálny priebeh cyklu a to nasledovne: • break – ukončuje najvnútornejšiu (pri vnorených cykloch) neuzavretú slučku, teda okamžite opúšťa cyklus. • continue – skáče na koniec najvnútornejšej neuzavretej slučky a tým vynúti ďalšiu iteráciu (ďalší cyklus).

    continue cyklus neopúšťa!

    Obr. 6-2 Funkcia príkazov break a continue.

    Cvičenia 1. S využitím znalosti rozšírenej formy priraďovacieho príkazu

    premenná = premenná operátor výraz; → premenná operátor= výraz; (napr. i = i + 5; → i += 5;) prepíšte telo funkcie NSD, t.j. vetvy príkazu if.

    Riešenie: program c06-1.cpp

    2. Prepíšte funkciu NSD pomocou nekonečného cyklu while(1) {...}, operátora porovnania a príkazov break a continue.

    Riešenie: program c06-2.cpp

    3. Telom cyklu while môže byť prázdny príkaz (;). Napíšte pomocou príkazu while najjednoduchší príklad "zacyklenia", t.j. nekonečného cyklu.

    Riešenie: program c06-3.cpp

    4. Napíšte pomocou príkazu while funkciu n-tej mocniny s prototypom double pow(double x, unsigned n); ktorá vráti hodnotu n-tej mocniny z x (n je prirodzené číslo včítane 0). unsgined znamená typový modifikátor, bližšie informácie nájdete v lekcii XIII.

    Riešenie: súbor c06-4.cpp

    5. Prepíšte funkciu pow() z predchádzajúceho cvičenia na funkciu s prototypom double pow(double x, int y); ktorá vráti y-tú mocninu z x (x je reálne číslo, y je celé číslo – teda aj záporné!)

    Riešenie: súbor c06-5.cpp

    6. Zväčšite rozsah čísel pre funkciu NSD() tak, že použijete namiesto typu int typ unsigned long. Bližšie informácie o typových modifikátoroch unsigned a long nájdete v lekcii XIII.

    Riešenie: súbor c06-6.cpp

  • 28

    VII. lekcia: Riadiace štruktúry – iteračné príkazy Príkaz do–while

    Cieľom tejto lekcie je oboznámiť vás s ďalším zo série iteračných príkazov, ktorým je príkaz do–while. Príkaz realizuje cyklus s podmienkou na konci. Pomocou príkazu budeme implementovať matematickú funkciu pre výpočet n-tej odmocniny z reálneho čísla. Funkcia má prototyp double root(double cislo, int n); a jej úlohou je vrátiť n-tú odmocninu z cislo. V prípade záporného čísla pod odmocninou vypíše chybovú správu a vráti 0 bez ohľadu na to, či je exponent n párne alebo nepárne číslo (napr. ). Podobne, funkcia bude ošetrovať prípad, keď n nie je prirodzené číslo.

    Je dosť pravdepodobné, že vás teraz asi zaujíma, ako chceme funkciu root() implementovať, keď programovo realizovaný výpočet odmocniny vlastne ani nepoznáme. Preto predtým, než uvedieme výpis programu, v ktorom je funkcia root() už implementovaná, uvádzame odvodenie vzorca pre výpočet odmocniny pomocou Newtonovej ite-račnej metódy. (Pozn.: Týmto spôsobom počítajú n-tú odmocninu v súčasnosti takmer všetky kalkulačky.)

    Odvodenie vzorca pre výpočet odmocniny

    Vzorec pre Newtonovu iteračnú metódu:

    Posledný vzťah udáva výsledný vzorec pre výpočet n-tej odmocniny z čísla A, pričom x k je hodnota odmocniny v k-tej iterácii a x k+1 je hodnota v nasledujúcom kroku. Iteráciu vykonávame dovtedy, kým rozdiel medzi hodnotou v (k+1). kroku a v k-tom (predchádzajúcom) kroku nie je menší než daná presnosť (epsilon). A teraz nasleduje im-plementácia tohto vzťahu pomocou cyklu do-while.

    3273 −=−

    1n

    n

    n

    n

    n)(0A)(

    Aneznáma - známe; -n A,A

    −⋅=′

    =−=

    =

    =

    xxfxxf

    xxx

    ( ) nA1-n

    An1

    n1-n

    An1

    nn

    nA

    :dosadení po a)()(

    1n1

    1n1

    1n1n

    n

    1

    1n

    n

    1

    1

    +⋅=

    ⋅+=

    −⋅−=

    −−=

    ′−=

    −+

    −+

    −−+

    −+

    +

    kkk

    kkk

    kk

    kkk

    k

    kkk

    k

    kkk

    xxx

    xxx

    xxx

    xx

    xx

    xx

    xfxf

    xx

  • 29

    Výpis programu P07.CPP 1: #include 2: 3: /* prototypy funkcii */ 4: double abs(double cislo); 5: double root(double cislo, int n); 6: double pow(double x, int y); 7: 8: void main() 9: { 10: double x; 11: int n; 12: 13: printf("Zadaj cislo, ktore chces odmocnit: "); 14: scanf("%lf", &x); 15: printf("Zadaj n (cele cislo) urcujuce n-tu odmocninu: "); 16: scanf("%d", &n); 17: 18: printf("%d. odmocnina z %lG je %.15lG\n\n", n, x, root(x,n)); 19: 20: } 21: 22: double root(double cislo, int n) 23: { 24: const double EPSILON = 1E-9; /* presnost pre vypocet odmocniny */ 25: double x_old = 1, /* x v kroku k */ 26: x_new, /* x v kroku k+1 */ 27: tmp; /* pomocna premenna na uschovanie povodnej hodnoty * 28: * x_old, t.j. este pred jej aktualizaciou */ 29: 30: if (cislo < 0) 31: { 32: printf("MATH Error: zaporne cislo pod odmocninou\n"); 33: return(0); 34: } 35: 36: if (n EPSILON); 47: 48: return(x_new); 49: } 50: 51: 52: /* funkcia vrati absolutnu hodnotu cisla */ 53: double abs(double cislo) 54: { 55: return (cislo < 0 ? -cislo : cislo); 56: } 57: 58: 59: double pow(double x, int y) 60: { 61: double vysledok=1;

  • 30

    62: 63: if (y == 0) return(1); 64: 65: while(y) 66: { 67: vysledok *= (y < 0 ? 1/x : x); 68: y < 0 ? y++ : y--; 69: } 70: 71: return(vysledok); 72: }

    Vysvetlivky: const double EPSILON = 1E-9; – definícia konštanty EPSILON. Konštantná premenná musí byť

    zároveň inicializovaná! do { ... } while – príkaz cyklu s podmienkou na začiatku *= – operátor priradenia s násobením (E1 *= E2 ⇔ E1 = E1 * E2) ++ – operátor inkrementácie (y++ ⇔ y = y + 1) –- – operátor dekrementácie (y–– ⇔ y = y - 1)

    Cyklus s podmienkou na konci Syntax príkazu do-while:

    do príkaz; while (podmienka);

    Poznámky: • Namiesto príkazu môže byť uvedený blok príkazov (uzavretý v zložených zátvorkách { a }). • Zátvorky okolo podmienky sú povinné – podobne ako v príkaze if. • podmienka je Booleovský výraz, ktorý sa vyhodnotí a jeho výsledok (0 = FALSE; iné ako 0 = TRUE)

    sa použije ako podmienka na vykonanie tela cyklu (príkazu).

    Obr. 7-1 Vývojový diagram príkazu do-while.

    V tomto cykle sa na rozdiel od cyklu while testuje podmienka až na konci (po prechode telom cyklu) ⇒ cyklus sa vykoná aspoň raz. Cyklus do-while pracuje tak dlho, kým je podmienka splnená, t.j. kým má hodnotu TRUE (nenulovú hodnotu).

    false …

    do

    podmienka

    príkaz(y) cyklu

    true

    while

    break

    continue

  • 31

    V našom príklade sa vykonávajú príkazy tela cyklu (riadky 43 až 45), kým nie je splnené, že rozdiel novej a starej hodnoty vypočítanej odmocniny je menší alebo rovný ako daná presnosť EPSILON (riadok 46). Riadok 43 realizuje vlastný výpočet odmocniny z hodnoty v predchádzajúcom kroku Newtonovej iteračnej metódy. Počiatočné x 0 bolo nastavené na východziu hodnotu 1 (riadok 25). Riadok 44 iba odpamätáva hodnotu x v kroku (k – 1), aby sa mohol vykonať test rozdielu hodnôt x k a x k–1 (riadok 46). Riadok 45 realizuje vlastnú iteráciu, t.j. vykonáva inkre-mentáciu indexu k. Poznámka: V cykle do-while je taktiež možné použiť príkazy break a continue na riadenie cyklu (viď. predchádza-

    júcu lekciu).

    Cvičenia 1. Prepíšte cyklus do-while vo funkcii root() pomocou nekonečného cyklu do {...} while(1); a príkazu

    break prípadne continue. Riešenie: program c07-1.cpp

    2. Znak ‘!’ pred výrazom znamená negáciu (NOT). Na príklade funkcie mocniny overte, že podmienka if (y == 0) ... je ekvivalentná s podmienkou if (!y) ...

    Riešenie: program c07-2.cpp

    3. Prepíšte funkciu root() tak, že nebude vypisovať matematické chyby, ale: • v prípade záporného čísla pod odmocninou vráti -1 a • v prípade n-tej odmocniny pre n

  • 32

    VIII. lekcia: Riadiace štruktúry – iteračné príkazy Príkaz for

    Cieľom tejto lekcie je oboznámiť vás s posledným zo série iteračných príkazov, ktorým je príkaz for. Príkaz for je typický príkaz cyklu, ktorý používame v prípade, že vopred poznáme počet prechodov cyklom. Pomocou príkazu for budeme implementovať matematickú funkciu pre výpočet faktoriálu z nezáporného čísla.

    Výstupom tejto lekcie bude funkcia na výpočet n-tej mocniny z reálneho čísla, ktorú využijeme v našom cieľo-vom programe kalkulátor. Vašou úlohou bude zimplementovať túto funkciu pomocou príkazu for.

    Výpis programu P08.CPP 1: #include 2: 3: /* prototyp funkcie */ 4: double faktorial(unsigned short x); 5: 6: void main() 7: { 8: short cislo; 9: 10: printf("Vypocet faktorialu\n------------------\n"); 11: printf("Zadaj cislo: "); 12: scanf("%d", &cislo); 13: 14: /* osetrenie na zaporne cislo a overflow; pre double je max. argument 15: faktorialu cislo 170, pretoze 170! = 7.257415615308E+306 */ 16: if (cislo < 0) 17: printf("MATH Error: Nemozem vyratat faktorial pre zaporne cislo...\n"); 18: else 19: if (cislo > 170) 20: printf("MATH Error: Number overflow for fact()...\n"); 21: else 22: printf("%d! = %.15lG\n\n", cislo, faktorial(cislo)); 23: 24: } 25: 26: /* funkcia pre vypocet faktorialu */ 27: double faktorial(unsigned short x) 28: { 29: double vysledok = 1; 30: unsigned short i; 31: 32: for (i = 2; i

  • 33

    Typové modifikátory Typové modifikátory short a unsigned slúžia na zmenu rozsahu čísel, ktoré môže typ (uvedený za nimi) uchová-

    vať. Ak sa typ, ku ktorému sa modifikátory vzťahujú, neuvedie (viď. riadky 4, 8, 27 a 30), berie sa za typ implicitne int. Obidva modifikátory môžu byť aplikované iba na celočíselné typy (char a int).

    Na platforme i80x86 nemá modifikátor short žiadny význam, pretože číslo typu int aj short (resp. short int) obsadzuje miesto v pamäti o veľkosti 2 bajty, takže rozsah čísel, ktoré dokáže typ short int uchovávať je –32768 až +32767. Ale napríklad na systémoch VAX premenná typu int alokuje 4 bajty pamäti, kým premenná „typu“ short iba 2 bajty.

    Modifikátor unsigned mení rozsah uchovávaných čísel tak, že posúva nulu zo stredu intervalu na jeho ľavý okraj, teda mení spodnú (⇒ aj hornú) hranicu rozsahu čísel, ktoré dokáže uchovávať premenná typu, na ktorú sa modifikátor aplikuje. Tak napr. na i80x86 platforme premenná typu int uchováva čísla v rozsahu -32768 až +328767, kým premenná toho istého typu s modifikátorom unsigned dokáže uchovať čísla v rozsahu 0 až 65535.

    Ďalším typovým modifikátorom je long, s ktorého využitím sa stretneme v lekcii X – „Typová konverzia“. Na túto chvíľu iba poznamenajme, že premenná typu long resp. long int dokáže na platforme i80x86 uchovávať celé čísla v rozsahu –2 147 483 648 až +2 147 483 647 a premenná typu unsigned long resp. unsigned long int čísla v roz-sahu 0 až 4 294 967 295.

    Cyklus for Syntax príkazu for:

    for (výraz_štart; výraz_stop; výraz_iter) príkaz;

    Poznámky: • Namiesto príkazu môžeme uviesť aj blok príkazov (uzavretý v zložených zátvorkách { a }). • Podobne ako pri cykloch while a do-while môžeme ovplyvniť riadenie prechodu cyklom pomocou príkazov

    break a continue (viď. lekciu VI).

    Obr. 8-1 Vývojový diagram príkazu for.

    false … for výraz_stop

    príkaz(y) cyklu

    true

    výraz_štart

    výraz_iter

    break

    continue

  • 34

    Podľa diagramu na obrázku 8-1 môžeme príkaz cyklu fo