Distanční opora předmětu: Programování v jazyce C Tématický blok č. 1: Hello World, překlad programu, funkce Autor: RNDr. Jan Lánský, Ph.D. Obsah kapitoly 1 První program: Hello World 2 Struktura programu 2.1 Direktiva #include 3 Překlad programu 4 Funkce 4.1 Hlavička a tělo funkce 4.2 Vnořené funkce 4.3 Návratová hodnota funkce 4.4 Parametry funkce Studijní cíle Cíle nutné k zahájení studia dalšího tématického bloku Znát klíčové pojmy tohoto tématického bloku (alespoň pasivní znalost je podmínkou pro studium dalších bloků). Umět vytvořit jednoduchý program vypisující na obrazovku text. Umět program ladit. Umět zdrojový kód členit na funkce a správně je používat. Další cíle Znát průběh překladu zdrojových kódu kompilátorem a linkerem do podoby spustitelného souboru. Umět vytvořit program složený z více modulů
Čas potřebný ke studiu 15 minut - 1 hodina na nainstalování vývojového prostředí (doporučují Microsoft Visual Studio 2008 Express Edition) 1 - 2 hodiny na prostudování výukových textů + zodpovězení otázek k rekapitulaci 1 - 4 hodiny na vypracování modelových úloh na PC 30 minut - 1 hodina na praktické zopakování učiva na PC ( v jiný den) 15 minut na (znovu)zodpovězení otázek k rekapitulaci (v jiný den) Časy jsou hodně individuální a jsou závislé na míře znalostí z předmětu Úvod do programování a Programování a případných programátorských zkušenostech z jiných jazyků.
Úvod V tomto bloku probereme následující tři témata. Ukážeme si jednoduchý program v jazyku C a podrobně si ho vysvětlíme. Vysvětlíme si, jak se námi napsané zdrojové kódy zpracovávají kompilátorem a linkerem do podoby spustitelného souboru. Probereme funkce v jazyku C: návratová hodnota, parametry funkce, volání funkce. Naučíme se také vytvořit nový prázdný projekt v Microsoft Visual Studiu 2008 a napsat v tomto prostředí jednoduchý program, vyzkoušíme si prostředky k ladění programů (breakout, watch, call stack, trace into, trace over), které toto vývojové prostředí nabízí. Výkladová část Vysvětlivky Červený text – Porušením nebo opomenutím takto označených pravidel vznikají těžko odladitelné chyby (zejména pro začínající programátory). Modrý text – Doporučení jak programovat v praxi. Často prevence závažných chyb. 1 První program: Hello World Na slajdu č. 10 vidíme ukázku programu napsaného v C. Prohlédněte si tento zdrojový kód a zkuste uhodnout co program dělá. Odpověď zní: Program vypíše na standardní výstup (nejčastěji obrazovka) text „Hello“ a odřádkuje. Následně čeká na stisk libovolné klávesy. Pak program skončí. Malá poznámka na úvod. Jazyk C je case-sensitive, tedy rozlišuje malá a velká písmena. Pokud si zavedeme identifikátor ( = pojmenujete funkci či proměnnou názvem) test a poté někde dále v kódu použijete místo toho identifikátor Test, tak kompilátor zahlásí chybu neznámý identifikátor. Dokonce můžete vytvořit 20 různých variant, které se budou lišit pouze velikostí písmen (test, Test, tEst, teSt, tesT, TEst, TeSt, TesT, tESt, tEsT, teST, tEST, TeST, TEsT, TESt, TEST). Teoreticky, by jsme tedy takto mohli pojmenovat našich 20 prvních proměnných, ale výrazně bychom snížili přehlednost zdrojového kódu a také bychom zvýšili závažnost případně udělané chyby v programu. Obyčejný překlep ve velikosti písmene by už neodhalil kompilátor jako syntaktickou chybu, ale projevil by se jako logická chyba při běhu programu. Je dobré dodržovat pravidlo: Nevytváříme identifikátory, které by se od nějakého existujícího identifikátoru lišily jen velikostí písmen. Na slajdu č. 11 vidíme ten samý zdrojový kód, co na předchozím slajdu, ale doplněný o komentáře k jeho jednotlivým částem. Začneme třetím řádkem int main (int argc, char ** argv), kde vidíme hlavičku funkce main. Tato funkce zaujímá mezi ostatními funkcemi výsadní postavení, v každém
programu se začne vykonávat jako první po jeho spuštění. Obdobně jako v Pascalu, kde se program začínal vykonávat posledním begin – end blokem. Funkce main nemá povinně dané umístění v programu, ale bývá zvykem ji psát na konec zdrojového kódu. Před názvem funkce main vidíme typ její návratové hodnoty int, funkce tedy vrací nějaké celé číslo. V kulatých závorkách za main jsou uvedeny formální parametry ( = argumenty) funkce argc a argv. Před každým názvem formálního parametru funkce je uveden jeho datový typ. Jednotlivé parametry se oddělují čárkou. V případě funkce main slouží její parametry ke zpracování parametrů programu, se kterými byl spuštěn z příkazové řádky. Přesný význam parametrů argc a argv si vysvětlíme až v polovině semestru. Na čtvrtém řádku nalezneme jediný symbol: otvírací složená závorka { což je obdoba begin z Pascalu. Na Posledním řádku se nachází opět jediný symbol: zavírací složená závorka } což je obdoba end z Pascalu. V našem případě tyto složené závorky ohraničují tělo funkce main. Častou chybou bývá zapomenutí pravé uzavírací závorky. Je výhodné zavírací závorku napsat okamžitě po napsání otvírací závorky a příslušný zdrojový kód potom postupně psát dovnitř těchto závorek. Jednotlivé řádky (5. – 7.) uvnitř těla funkce main jsou příkazy. Každý příkaz je povinně ukončen středníkem, bez vyjímek. Na pátém řádku vidíme volání funkce printf se skutečným parametrem ( = s hodnotou) "Hello\n". Parametrem funkce printf je formátovací řetězec, který popisuje, co vše se vytiskne na standardní výstup, kterým je obvykle monitor. Každý textový řetězec musí být v uvozovkách "text". Velmi častou chybou je použití apostrofů 'text' nebo napsání textu jen tak bez ničeho. V našem případě se vytiskne text Hello. Následně se provede "\n" odřádkování (= kurzor se umístí na první pozici následujícího řádku). Funkce printf vrací jako návratovou hodnotu počet znaků, které se ji skutečně podařilo vytisknout. Zpracovávat návratové hodnoty u funkcí (např. je ukládat do proměnné) ale není povinné, v našem případě ji tedy nijak nezpracováváme. Vážnější zájemce o funkci printf se určitě potěší slajd č. 69. Na šestém řádku vidíme volání funkce getch, která je volána bez parametrů. Při volání funkce bez parametrů je nutné použít prázdné kulaté závorky () za názvem funkce, nelze je vynechat. Funkce getch načte z obrazovky jednu klávesu a tato načtená klávesa je návratovou hodnotou funkce. Podobně jako v předchozím případě u funkce printf návratovou hodnotu nijak nezpracováváme. K čemu tedy funkci getch voláme? Funkce getch nám slouží v programu mimo jiné jako pauza. Funkce totiž čeká na stisk libovolné klávesy, aby ji mohla vrátit jako návratovou hodnotu. My si tedy můžeme v klidu přečíst jaký je výstup na obrazovce a stiskem libovolné klávesy pokračujeme v běhu programu. Na sedmém řádku vidíme klíčové slovo return, které ukončuje běh libovolné funkce. Za return následuje návratová hodnota funkce, která musí být shodná s typem návratové hodnoty uvedeným v hlavičce funkce. V našem případě je návratovou hodnotou 0, která je celé číslo což odpovídá typu int, který jsme napsali jako návratovou hodnotu funkce main (vlevo před slovem main na 3. řádku). Je zde zásadní rozdíl oproti Pascalu, tam jste mohli funkci přiřadit návratovou hodnotu a vykonávat další příkazy. V jazyku C funkce končí svůj běh vykonáním příkazu return, zádně další příkazy se už v dané funkci nevykonají. První dva řádky #include<stdio.h> a #include jsme na začátku přeskočili, nyní se k nim vrátíme. Ve zdrojovém kódu můžeme používat pouze funkce, které jsou už definovány (= známy). My jsme použili ale funkci getch, která se nachází v knihovně conio.h a funkci printf, které se nachází v knihovně stdio.h. Použití direktivy include se jménem knihovny ve špičatých závorkách nám zpřístupní funkce a další
identifikátory v této knihovně obsažené pro použití v našem zdrojovém kódu. Úplně všechny funkce v jazyce C se nacházejí v některé z knihoven. V jaké knihovně se nachází konkrétní funkce, se dozvíme v nápovědě pro danou funkci (v Microsoft Visual Studiu je to sekce nápovědy Requirements). Všimněme si formátování zdrojového kódu na tomto slajdu (č. 11). Příkazy v těle funkce main jsou odsazeny o několik znaků (nebo 1 tabulátor) doprava oproti pozici hlavičky funkce. Pravidlo platí obecně, libovolný zdrojový kód uzavřený ve složených závorkách se odsazuje doprava. Pokud píšeme náš zdrojový kód ve Visual Studiu (a při jeho psaní neděláme zásadní syntaktické chyby), tak docílíme tohoto odsazení automaticky. Pokud neproběhne automatické odsazení příkazů uvnitř složených závorek, měli by jsme ho provést ručně. Správné formátování zdrojového kódu je velmi důležité pro jeho čitelnost. Neformátované zdrojové kódy ztěžují i hledání případných chyb. 2 Struktura programu Program v jazyce C se skládá z modulů, které jsou samostatně překládány kompilátorem. Z pohledu programátora je modul tvořen jedním zdrojovým souborem s příponou .c nebo .cpp. Koncovka .c je určena pro programy napsané v jazyku C, koncovka .cpp pro programy napsané v jazyku C++. Protože budeme už tento semestr používat překladač jazyka C++ (přestože v něm budeme psát syntaxí jazyka C), budeme používat koncovku .cpp. Jednotlivé moduly po jejich překladu kompilátorem se pak spojují linkerem. Modul by měl být vždy nějakým logickým celkem. Obvykle to bývá sada funkcí která pracuje se shodnou datovou strukturou (nebo strukturami). Proč se programy dělí na moduly ? Důvody jsou v zásadě dva. Prvním z nich je přehlednost kódu. Ve chvíli kdy jeden zdrojový soubor obsahuje 10 000 řádek zdrojového kódu stává se nepřehledným, špatně se v něm hledají případné chyby. Obvykle se doporučuje, aby modul obsahovat nejvýše 1 000 - 2 000 řádek. Druhým důvodem je znuvupoužitelnost kódu. Pokud je náš modul kvalitní, můžeme ho použít i v našich dalších programech, nebo může být využitý i jiným programátorem. V téměř každém modulu potřebujeme použít identifikátor (nejčastěji funkci), která v daném modulu není definována. Chceme využít funkci, která je součástí nějakého jiného modulu. Pokud si vzpomenete na slajd č.11, tam se jednalo o funkce getch a printf. K tomuto účelu slouží hlavičkové soubory ( = headery) .h, které obsahují definice identifikátorů, které se mohou používat ve více modulech. V případě, že daným identifikátorem je funkce, je v hlavičkovém souboru napsána hlavička toto funkce (návratová hodnota, jméno funkce, její parametry). Jednotlivé definice identifikátorů se oddělují středníkem. 2.1 Direktiva #include Chceme-li v modulu použít nějaký identifikátor z hlavičkového souboru, musíme tento hlavičkový soubor do modulu vložit za pomocí direktivy #include. Existují dva typy hlavičkových souborů. Prvním typem jsou hlavičkové soubory standardních knihoven jazyka C a jejich názvy se uzavírají do špičatých závorek (příklad #include). Druhým typem jsou hlavičkové soubory, které si napsal sám programátor, aby mohl používat identifikátory z jeho vlastních modulů. Tyto názvy se uzavírají do uvozovek (příklad #include"moje_hlavicka"). Pokud chceme v jednom modulu vložit více hlavičkových
souborů, musíme vložit každý samostatně, žádný zkrácený zápis vkládání více hlavičkových souborů najednou není možný. Každý #include se obvykle píše na samostatný řádek. Z hlediska překladu programu mají direktivy (kromě #include existují i další, více bude časem - slajd č. 99). speciální postavení. V každém kompilátoru je integrován textový preprocesor, který jako úplně první fázi překladu modulu provede nahrazení všech výskytů direktiv. Direktiva #include se nahrazuje obsahem souboru, který je uveden jako její parametr. Pokud je jméno souboru ve špičatých závorkách, soubor se hledá v adresářích definovaných vývojovým prostředím jako adresáře hlavičkových souborů standardních knihoven. Pokud je jméno souboru v uvozovkách, hledá se soubor v aktuálním pracovním adresáři vámi vytvářeného programu (případně můžete v nastavení vlastností vašeho programu specifikovat i speciální adresář pro tyto hlavičkové soubory). Jméno hlavičkového soubory, který je parametrem direktivy #include, může navíc obsahovat i absolutní nebo relativní cestu, kde je soubor umístěn. Jako parametr direktivy #include můžete použít naprosto libovolný soubor, klidně i náhodný binární soubor, preprocesor ho skutečné vloží, problémy nastanou až v další fázi překladu. Používání jiných než hlavičkových souborů se silně nedoporučuje. Z pohledu kompilátoru je modul samostatná jednotka překladu a vznikne ze zdrojového souboru jako výsledek práce preprocesoru. 3 Překlad programu Na slajdu č. 13 vidíme jak probíhá překlad programu tvořeného jedním modulem. Kompilátor (na slajdu označen jako CC) vezme zdrojový soubor .cpp a několik hlavičkových souborů .h standardních knihoven jazyka C. Kompilátor bývá také často nazýván jako překladač. Výsledek práce kompilátoru je objektový modul, je to přeložený zdrojový kód jednoho modulu. Tyto soubory se jmenují téměř stejně jako byl původní zdrojový soubor, pouze se liší koncovkou, kterou mají .obj. Další krok v překladu programu obstarává linker. Ten spojí ( = slinkuje) objektový modul právě vzniklý kompilátorem s objektovými moduly standardních knihoven (.obj, .lib), které jsme v našem programu použili. Výsledkem je pak spustitelný .exe soubor. Na slajdu č. 15 pak vidíme překlad programu tvořeného více moduly. Oproti slajdu č. jsou zde dva rozdíly. Prvním rozdílem je, že kompilátor zpracovává nejen hlavičkové soubory standardních knihoven, ale i hlavičkové soubory vytvořené samotným programátorem, které obsahují informace o funkcích z jiných modulů. Druhým rozdílem je, ze linker zpracovává větší množství objektových modulů. Na slajdu č. 17 vidíme, jak překlad programu s více moduly (obrázek ze slajdu č. 15) probíhá v integrovaném vývojovém prostředí (například Microsoft Visual Studia). Jednotlivé zdrojové a hlavičkové soubory můžete editovat v textovém editoru (obvykle s barevně zvýrazněnou syntaxí, automatickým doplňováním identifikátorů, vestavěnou nápovědou atd.). Spuštěním jednoho tlačítka proběhne celý překlad programu najednou a uživatel získá výsledný .exe soubor. Uživatel nemusí řešit, že překlad se skládá z více fází, nebo dokonce kompilátoru či linkeru říkat, jaké soubory mají vzít na vstupu a co z nich vyrobit. Další součástí těchto integrovaných vývojových prostředí bývá vestavěný debugger, který umožňuje ladit běžící programy. Můžeme s jeho pomocí zjišťovat hodnoty proměnných, krokovat program příkaz po příkaze, nebo ho zastavovat při splnění námi definovaných podmínek
Slajd č. 18 ukazuje, jak překlad programu s více moduly (obrázek ze slajdu č. 15) vypadá bez použití integrovaného vývojového prostředí, ale s použitím příkazu make, který provede překlad podle instrukcí zapsaných v souboru makefile. Tento typ překladu bývá obvyklý při práci v operačních systémech typu UNIX. V makefile se definují závislosti (ty co jsou na slajdu označeny šipkami) mezi jednotlivými .cpp, .h a .obj soubory. Rovněž se zde musí explicitně napsat, že jednotlivé moduly se vytvářejí pomocí kompilátoru (a s jakým nastavením jeho parametrů), a že pak moduly mají slinkovat do spustitelného souboru. 4 Funkce V jazyku C je funkce základní jednotkou, na kterou se člení zdrojové soubory. Běh programu začíná vyvoláním funkce s názvem main, tato funkce má pevně danou hlavičku int main (int argc, char ** argv), která slouží ke zpracování parametrů programu, se kterými byl zavolán při svém puštění z příkazové řádky. Před samotným spuštěním funkce main proběhne ještě inicializace běhového prostředí (alokace paměti, například nastavení hodnot globálních proměnných). Po skončení funkce main dochází k úklidu. Pořadí funkcí ve zdrojovém souboru není pevné dané, dodržuje se konvence, že funkce main je na konci zdrojového souboru v případě programu tvořeného jedním modulem. V případě programu tvořeného více moduly bývá funkce main umístěna v samostatném modulu. Ve chvílí kdy funkce ve svém těle volá jinou funkci, musí být volaná funkce kompilátoru známa, musel již zpracovat alespoň její hlavičku. Z tohoto důvodu se do zdrojových souborů vkládají hlavičkové soubory a z tohoto důvodu se také snažíme řadit funkce ve zdrojovém souboru postupně směrem dolů, jak je vytváříme. V případě, že chci volat dvě funkce navzájem rekurzivně, musíme jejich hlavičky oznámit kompilátoru pomocí hlavičkového souboru, nebo přímo napsáním hlaviček obou funkcí na začátek zdrojového souboru. 4.1 Hlavička a tělo funkce Funkce má hlavičku a tělo. Hlavička funkce obsahuje typ návratové hodnoty funkce, název funkce a v kulatých závorkách čárkami oddělené dvojice, které tvoří typ a název formálních parametrů. Tělo funkce je uzavřeno ve složených závorkách a obsahuje příkazy. V jazyku C nelze definovat dvě funkce se shodným názvem, které by se lišily jen počtem či typy parametrů (v jazyku C++ to jde) Podívejme se na slajd č. 20. Na levé straně slajdu v zeleném podkladu vidíme tři funkce. Funkce fce1 má návratovou hodnotu typu integer ( = celé číslo) a má dva parametry x a y, typu integer. Obsah složených závorek je tělo funkce, ve kterém je jediný příkaz return x + y. Funkce vrací jako svoji návratovou hodnotu (pomocí klíčového slova return) součet svých parametrů x a y. Funkce fce2 vypadá podobně, ve své hlavičce se liší od fce1 tím, že má místo dvou parametrů pouze jeden parametr a. V těle má funkce fce2 opět jediný příkaz, který určuje návratovou hodnotu funkce. Vidíme zde zavolání funkce fce1 s parametry 1 a 2*a+5. Všimněme si, že zde je důležité pořadí v jakém jsou funkce ve zdrojovém souboru napsány. Pokud by byly v opačném pořadí, kompilátor by neznal funkci fce1 při zpracovávání funkce fce2. Třetí z funkcí je funkce main, které má ve svém těle uvedeny tři tečky ( … ). Tento symbol budeme ve slajdech velmi často používat jako náhradu chybějícího zdrojového kódu, který by jsme si měli doplnit my sami. Pokud zkusíte takovýto zdrojový kód zkompilovat bez úprav, kompilátor zahlásí syntaktickou chybu, která nebude na první pohled srozumitelná. (Operátor tří teček v jazyku C existuje, ale my se nebudeme v tomto předmětu učit jeho význam.
4.2 Vnořené funkce Na rozdíl od Pascalu v jazyku C neexistují vnořené funkce, neznám ani žádný další programovací jazyk, který by je podporoval. Každá vnořená funkce jde na štěstí převést na funkci nevnořenou (obvykle stačí přidat pár parametrů funkce). Vpravo na slajdu č. 20 na červeném podkladu vidíte chybný pokus o deklaraci vnořené funkci. Funkci fce1 jsme zanořili do funkce fce2. Velmi často vytvoříme vnořenou funkci omylem, pokud do zdrojového kódu přidáváme novou funkci a nepíšeme ji logicky na konec zdrojového souboru, ale snažíme se ji vložit někam mezi funkce napsané dříve. Stačí přehlédnout složenou závorku nějaké z funkci a místo psaní funkce do prázdného prostoru vytváříte vnořenou funkci. 4.3 Návratová hodnota funkce Na slajdu č. 21 máme blíže vysvětlenou problematiku návratové hodnoty funkce. Typ návratové hodnoty funkce se píše v její hlavičce vlevo od názvu funkce. Funkce musí končit klíčovým slovem return po kterém následuje výraz stejného typu, jako je typ návratové hodnoty uvedený v hlavičce funkce. Návratovou hodnotou funkce je hodnota výrazu, který je po return uveden. Vlevo na slajdu vidíme funkci fce1, která má návratovou hodnotu typu int (celé číslo) a skutečně vrací výraz typu int. V jazyku C neexistuje procedura, ale lze ji nahradit funkcí, která vrací prázdnou hodnotu. K tomuto účelu se používá speciální datový typ void, který se uvede jako návratová hodnota dané funkce. Funkce s typem návratové hodnoty void, nemusí ve svém těle obsahovat klíčové slovo return. Pokud ho však obsahuje, tak za ním nesmí být uvedená žádná hodnota, pouze středník. Napravo na slajdu č. 21 vidíte funkci fce2, která tiskne pouze text na obrazovku, takže v jejím případě návratovou hodnotu nepotřebujeme. Funkce má tedy návratovou hodnotu typu void a neobsahuje return. Funkce fce3 je velmi podobná funkci fce2, pouze navíc testuje zda vstupní parametr je platný řetězec (zjednodušeně vysvětleno, co ten test přesně znamená, se dozvíme později při probírání řetězců) a může ho tedy vytisknout. Pokud vstupní parametr nebyl platný řetězec nemá smysl ve funkci dále pokračovat a ukončíme ji pomocí return. Pokud funkce zjistila při svém běhu chybu (například špatný vstupní parametr), velmi často se používá ukončení funkce pomocí return, hned po zjištění této skutečnosti. Zvýšíme tím přehlednost zdrojového kódu, protože celý zbytek těla funkce nebude zbytečně zanořen v else větvi podmínky. Návratovou hodnotu má i funkce main a její návratová hodnota se stává návratovou hodnotou celého programu, kterou můžeme zjistit z operačního systému. Bývá používána konvence, že pokud program proběhl v pořádku, je návratovou hodnotou 0. Pokud došlo k chybě, vracíme číslo chyby (obvykle hodnoty -1, -2, -3 atd). 4.4 Parametry funkce Funkce v jazyce C má v hlavičce funkce definovaný pevný počet parametrů a ty jsou pevného typu. Formální typy parametrů a jejich názvy se píší do kulatých závorek napravo od názvu funkce. Jednotlivé dvojice (formální typ parametru a jeho název) se oddělují od sebe čárkou. Na slajdu č. 22 toto demonstrují funkce fce1 a fce2. Funkce také může být bez parametrů
(viz fce3), potom se místo seznamu parametrů do kulatých závorek píše void. V jazyku C++ se může v případe funkce bez parametrů vynechat i slovo void, ale musí zde být alespoň prázdné kulaté závorky. Protože používáme překladač C++, tak tedy i zápis s vynecháním void bude správný. V definici parametrů funkce se velmi často chybuje. Pokud máme dva parametry, které jsou stejného formálního datového typu, tak nelze použít zkrácený zápis, jaký šlo použít v Pascalu a jaký můžete vidět u funkce fce4 napravo na slajdu č. 22 na červeném podkladu. Další chybou bývá zapomenutí kulatých závorek (obsahujících void, nebo prázdných) při deklaraci funkce bez parametrů (viz funkce fce5). Občas se také chybuje v nahrazení čárek (oddělující dvojice formální typ parametru a název) za středníky. V Jazyku C lze definovat i funkce s proměnlivým typem parametrů (příkladem takové funkce je printf). Vytváření funkcí s proměnlivým počtem parametrů není v učivu tohoto předmětu (pro zájemce: používá se k tomu operátor tří teček (…) a makra va_start a va_list). 4.4 Volání funkce Volat můžeme pouze funkci jejichž název kompilátor již zná. Je tedy již definována ve zdrojovém souboru nebo jejich hlavička se nachází v některém z hlavičkových souborů, které jsou vloženy pomocí direktivy #include. Parametry, se kterými funkci voláme, se nazývají skutečné. Parametry, které byly definovány v hlavičce funkce, se nazývá formální. Počet formálních a skutečných parametrů se musí shodovat, jejich typy musí být kompatibilní (typ skutečného parametru musí jít převést na typ formálního parametru). Volání funkce bez parametru musí obsahovat operátor (), závorky nelze vynechat. Návratovou hodnotu funkce můžeme ignorovat. Dokonce je velmi časté u volání funkcí, že návratová hodnota se nijak nevyužívá. Na slajdu č. 23 nalevo máme tři funkce. Funkce fce1 má definovány tři formální parametry typů int, int a float (reálné číslo). Funkce fce3 nemá formální parametry žádné, funkce fce2 má jeden formální parametr typu int. Ve funkci fce2 nejprve volám funkci fce1 se skutečnými parametry a, 1, a. Počet formálních i skutečných parametrů se shoduje – 3. Nyní budeme zjišťovat jejich kompatibilitu. První formální parametr funkce fce1 je typu int, první skutečný parametr je a (který je typu int). Druhý formální parametr funkce fce1 je typu int, druhý skutečný parametr je 1 (který může být typu int). Třetí formální parametr funkce fce1 je typu float, třetí skutečný parametr je a (který je typu int, ale typ int lze na float převést). Tedy funkce fce1 je volána správně. Funkce fce3 je volána také správně (počet formálních i skutečných parametrů je 0). Návratovou hodnotu volání funkcí fce1 a fce3 ignoruji. Na slajdu č. 23 napravo máme ukázáno několik chyb. Ve funkci fce5 voláme funkci fce4 celkem třikrát. Poprvé ji voláme bez kulatých závorek, podruhé se neshoduje počet formálních parametrů 3 s počtem skutečných parametrů 2. Při třetím volání počty parametrů souhlasí, ale třetí skutečný parametr je typu řetězec a není kompatibilní s typem reálného čísla, což je třetí formální parametr.
Klíčové pojmy Funkce main Hlavička funkce Tělo funkce Návratová hodnota funkce Parametry funkce (formální a skutečné) Direktiva #include Modul Kompilátor (= Překladač) Preprocesor Linker Debugger Hlavičkové soubory .h Zdrojové soubory .c a .cpp Integrované vývojové prostředí
Otázky k rekapitulaci Záleží v jazyku C na velikostí písmen v názvu proměnných, funkcí a klíčových slov ? Jaké funkce pro ze standardních knihoven jazyka C jsme zatím použili a co tyto funkce dělají? Jaké znáte typy souborů používané při programování v jazyku C nebo při kompilaci programu a jaké mají koncovky. Za jakým účelem se používá direktiva #include a jak je zpracována při překladu programu. Jak probíhá překlad programu tvořeného jedním zdrojovým souborem ? Jak probíhá překlad programu tvořeného více zdrojovými souborem ? Kdy je výhodné rozdělovat program do více modulů ? Čím je výjimečná funkce main a k čemu slouží její parametry ? Lze definovat vnořenou funkci ? Lze vytvořit funkci bez parametrů ? Jakým operátorem se oddělují od sebe parametry funkce ? Lze využít nějaký skácený zápis, pokud je více parametrů stejného typ ? Musí každá funkce končit return ? Existuje v jazyce C procedura ? Jaký je rozdíl mezi formálními a skutečnými parametry funkce. Záleží na pořadí funkcí ve zdrojovém souboru ? Své odpovědi zdůvodněte. Můžete přidat i syntaktické zápisy tam, kde je to vhodné.
Doporučené příklady k naprogramování
Nejprve si nainstalujeme vývojové prostředí Microsoft Visual Studio 2008 Express Edition. Při instalaci si můžete vybrat, které programovací jazyky chcete nainstalovat. Důležité je nainstalovat C++. Můžete také nainstalovat i nějaký jiný alternativní překladač, ale výklad (např. klávesové zkratky) je uváděn pouze pro Microsoft Visual Studio. Nyní si otevřeme nový prázdný projekt v jazyku C++. Postup je dost komplikovaný, popíšu ho krok za krokem. Z menu File dáme položku New a v ní položku Project. Vyskočí nám okno, ve kterém v levé části vybereme položku Visual C++ a její podpoložku Win32. V pravé části okna nyní vybereme ikonu s popisem Win32 Console Aplication. Dole jsou tři řádky. První z nich je jméno projektu, které musíme vyplnit (jména projektů zkuste vytvářet smysluplně dle úlohy, co řešíte.). Další řádky můžeme ponechat jak jsou. Klikněte na tlačítko OK a vyskočí další okno, ve kterém dáme položku next. V dalším okně zaškrtneme volbu Empty project a následně dáme tlačítko Finish. V tomto postupu je důležité neudělat žádnou chybu. Gratuluji, máte vytvořený prázdný projekt. Nyní v levé části obrazovky vidíte Solution Explorer, ve kterém můžete do projektu přidávat nové soubory. Potřebujeme přidat nový zdrojový soubor, klikneme tedy pravým tlačítkem myši na Ressource files a v menu vybereme Add a v dalším menu pak New Item. Nyní můžeme soubor pojmenovat a naší volbu potvrdit tlačítkem Add. Hlavičkové soubory se přidávají obdobně, celý postup provádíme na Header files.
Zadání příkladů: 1. Napište program, který vypíše na standardní výstup řetězec "Hello world". Ladění programu se spouští klávesou F5. 2. Upravte program z bodu (1) tak, aby využíval dvě bezparametrické funkce. První z nich vypíše slovo "Hello", druhá vypíše slovo "World". Nápověda: nepokoušejte se o napsání funkce s parametrem typu řetězec, znalosti k tomu potřebné získáte až později. 3. Modifikujte program z (2), tak aby jeho návratovou hodnotou byl počet znaků vytisknutých na standardní výstup. Nápověda: funkce printf vrací počet vytisknutých znaků. 4. Vytrasujte program pomocí klávesy F10 (Step Over). 5. Vytrasujte program pomocí klávesy F11 (Step Into). 6. Pomocí klávesy F9 nastavte v programu breakpoint a pomocí ladění programu si vyzkoušejte jeho efekt. 7. Sledujte hodnotu vybrané proměnné v průběhu ladění v okně "autos" nebo "watch1". 8. Sledujte zásobník volání funkcí "Call Stack" během ladění. 9. Rozdělte program z (4) do více modulů, každá funkce (včetně funkce main) bude v samostatném .cpp souboru. Vytvořte i příslušné .h soubory. Celkově tedy budete mít tři .cpp soubory a dva .h soubory.
Studijní literatura Výklad často odkazuje na slajdy (ve formátu .ppt), které je vhodné si vytisknout. Je vhodné si pořídit nějakou knihu o programování v C nebo C++. Uvedené příklady knih berte pouze jako inspirativní. Miroslav Virius: Programování v C++ (ČVUT, 2. vydání 2004) Jesse Liberty, Bradley L. Jones: Naučte se C++ za 21 dní (Computer Press, 2. vydání, 2007) Knihu je dobré číst postupně a vlastním tempem, můžete mít i mírné zpoždění oproti našemu výkladu. Pořadí kapitol v knize neodpovídá úplně přesně pořadí, v jakém učivo probíráme. Tento tématický blok se zaměřte na jednoduché ukázkové příklady pro jazyk C. Miroslav Virius: Pasti a propasti jazyka C++ (Brno, 2. vydání 2005) Kapitola 1.5 Funkce Kapitola 1.7 Překlad a sestavení