Počítačové modelování Zimní semestr: Počítačové modelování I 1/2 z Letní semestr: Počítačové modelování II 2/2 z, zk Jan Hnilica mail: hnilica@ih.cas.cz 1
Plán na zimní semestr Základní prostředky jazyka C - jednoduché typy (čísla, znaky), konstanty - práce s proměnnou, aritmetické výrazy - vstup a výstup na terminál - podmínky, logické výrazy - cykly, příkaz switch - ukazatele - pole, řetězce, struktury - funkce, rekurze Algoritmy a programovací techniky - složitost (časová, paměťová, asymptotická, notace O) - jednoduché třídící algoritmy - datové struktury zásobník a fronta - lineární seznamy - rekurze - prohledávání do hloubky - rozděl a panuj - prohledávání do šířky - binární vyhledávací strom - halda, haldové třídění - přihrádkové třídění 2
Materiály ke studiu prezentace z přednášek jazyk C Pavel Herout - Učebnice jazyka C (1. díl) 2016 (6. vydání), nakladatelství Kopp algoritmy Pavel Töpfer: Algoritmy a programovací techniky 2010 (2. vydání), nakladatelství Prometheus 2010 Piotr Wróblewski: Algoritmy 2015, nakladatelství Computer Press 3
Podmínky zápočtu: aktivní účast na cvičeních domácí úkoly = odevzdávání programů zápočtový test = napsání a odladění programu 4
Proč vlastně vytváříme programy? => proto, aby plnily úkoly a řešily problémy (plánovaly trasu, počítaly zatížení nosníku...) Pro vytvoření programu je nutné: Na počátku je vždy problém (zadání) 1. pochopit problém - důkladné pochopení zadání je základním předpokladem - je třeba získat přesné odpovědi na otázky jaké jsou vstupy? co má být výsledkem? jaká jsou pravidla a omezení? 2. zvolit postup (algoritmus) - postupů se vždy nabízí víc, je potřeba se pro jeden rozhodnout (a umět to zdůvodnit...) - nejlepší postup většinou nebývá ten, který nás napadne jako první 3. provést (napsat program) 4. zkontrolovat výsledky - nejlépe mnohokrát, s různými vstupy Rada: kreslete si obrázky! - tužka a papír jsou základními pomůckami programátora - obvykle platí, že čím více času strávíte s tužkou a papírem, tím rychleji program vytvoříte 5
Algoritmus = jednoznačný postup, který vede k řešení dané úlohy problém: najít největší ze tří různých čísel a, b, c - při zadání a = 7, b = 1, c = 9 můžeme odpovědět c, což je sice správná odpověď, ale pro jiné zadání už platit nemusí (např. 4, 14, 2) start obecný postup, který vrací správný výsledek při jakémkoliv zadání je znázorněn pomocí diagramu: ne a > b ano b > c ne ne a > c ano ano největší je b největší je c největší je a hotovo 6
Algoritmus problém: rozhodnout, zda je zadané číslo N prvočíslem prvočíslo je přirozené číslo větší než 1, které je beze zbytku dělitené pouze jedničkou a sebou samým. - problém budeme řešit tak, že zkusíme najít dělitele čísla N (tj. ukázat, že N není prvočíslo) - pokud dělitele nenajdeme, prohlásíme N za prvočíslo Možné postupy: 1) vyzkoušíme všechny dělitele od 2 do N - 1 2) budeme hledat pouze v intervalu od 2 do N/2 (proč?) - pokud tam dělitel není, prohlásíme N za prvočíslo 3) budeme hledat pouze v intervalu od 2 do N (proč?) - pokud tam dělitel není, prohlásíme N za prvočíslo 4) budeme hledat pouze v intervalu od 2 do N s vylepšením: - po vyzkoušení dvojky už budeme zkoušet jen liché dělitele 7
úroveň abstrakce Proč vlastně máme programovací jazyky? Počítačový program = posloupnost instrukcí vyšší programovací jazyky - příkazy srozumitelné lidské řeči (angličtině) - jeden příkaz obvykle mnoho strojových instrukcí - zhuštěný kód, (relativně) srozumitelný člověku JSA (jazyk symbolických adres, assembler ) - mnemotechnické zkratky instrukcí strojového kódu - kód nepřenositelný mezi procesory s různou architekturou c = a + b; WRITE( ahoj ); (nepřesné označení, assembler je překladač z JSA do strojového kódu) ADD... MOV... SUB... strojový kód (machine code) - instrukce přímo vykonatelné procesorem - zápis pomocí číselných kódů instrukcí - kód člověku zcela nesrozumitelný - obtížné ho psát, hledat chyby 00010010 11111100 01110101 1000001 8
Převod příkazů jazyka do strojového kódu: 1) kompilace (Pascal, C, C++ ) - kompletní převod do strojového kódu (kompilace) PŘED spuštěním programu - vyžaduje překladač (kompilátor, compiler) - výsledkem kompilace je spustitelný soubor (.out,.exe) - po jeho spuštění se rovnou vykonávají strojové instrukce Na počítači uživatele kompilátor být nemusí! 2) interpretace (Python, Perl ) - napsaný program se rovnou spustí - jednotlivé instrukce jsou ZA BĚHU PROGRAMU překládány do strojového kódu - vyžadují interpreter - program vykonávající překlad za běhu Interpreter musí být na počítači uživatele! pozn. kompilované programy jsou rychlejší - odpadá překlad každého kroku do strojového kódu 9
Programovací jazyk = prostředek komunikace mezi programátorem a počítačem (soubor pravidel, podle kterých se zapisují instrukce pro počítač) Syntaxe jazyka - pravidla zápisu příkazů ( gramatika ) Sémantika jazyka - význam příkazů syntaktická chyba = přestupek proti pravidlům zápisu (překlep ) - počítač vyžaduje zcela přesný zápis - odhalí ji kompilátor (=>program se vůbec nezkompiluje) sémantická chyba = chyba v logice programu - odhalí ji až chybné fungování programu (=> program se zkompiluje a jde spustit, ale produkuje chybné výsledky, padá ) 10
Programovací jazyk C - autor: Dennis Ritchie (70. léta) - univerzální programovací jazyk - nízkoúrovňový - pracuje pouze se standardními typy (znaky, čísla) - dovoluje práci s pamětí na nízké úrovni - neváže se na žádný konkrétní počítač, operační systém - kompilovaný - vývoj (tzv. normy jazyka) - K&R (1978) kniha Kernighan, Ritchie: The C Programming Language - ANSI C (1990) ANSI = American National Standards Institute - C 99 (2000) 11
Vytvoření programu v C (kam program zapsat a co se děje při zavolání kompilátoru) textový editor soubor.c preprocesor - do editoru zapisujeme příkazy programovacího jazyka - výsledkem je textový soubor - tzv. ZDROJOVÝ KÓD - přípona.c - soubor ve formě prostého textu (bez formátování) - např. Notepad, PSPad (ne Word) - součást kompilátoru - upravuje zdrojový soubor před kompilací (vložení hlavičkových souborů, rozvoj maker ) -> později - výsledek = upravený textový soubor (předán kompilátoru) kompilátor soubor.o linker soubor.exe - překládá zdrojový kód do tzv. relativního kódu (téměř hotový program) - výsledek = objektový soubor (přípona.o,.obj) - v programech jazyka C se většinou (vždy) volají podprogramy (funkce) ze standardních knihoven, někdy je program složen z více souborů - tyto dílčí části je potřeba sestavit do konečného celku - sestavovací program - sestaví moduly a knihovny do jednoho celku - výsledem je spustitelný soubor.exe PRAKTICKY: stačí napsat zdrojový kód a zavolat kompilátor 12
Vývojové prostředí (IDE - Integrated Development Environment): - komplexní nástroj pro vytváření software - obsahuje textový editor zvýrazňuje syntaxi jazyka (a umí další užitečné věci ) kompilátor lze ho volat stisknutím klávesy přímo z IDE, bez nutnosti opouštět editor debugger nástroj pro hledání logických chyb, tzv. odvšivovač obvykle další užitečné programy (např. správa verzí kódu) Code::Blocks http://www.codeblocks.org/ - open source IDE (lze zdarma stáhnout) pro Windows stahujte verzi: codeblocks-16.01mingw-setup.exe!!! (automatická instalace Code::Blocks spolu s kompilátorem MinGW) 13
Vývoj programu start zápis a editace zdrojového kódu kompilace ano chyby při kompilaci? ne spuštění, testování (opakovaně, různá data) ano běhové chyby? podezřelé výsledky? ne hotovo 14
Anatomie programu v C #include <stdio.h> int main() { printf( Kuk!!! ); return 0; } #include <stdio.h> - příkaz pro preprocesor, aby na toto místo vložil obsah souboru stdio.h - stdio.h je soubor standardní knihovny, který obsahuje definice příkazu printf - závorky < > kompilátor ví kde soubor hledat - příkazy pro preprocesor vždy začínají # - příkaz #include (zahrnout, vložit) se používá ve všech programech C int main() funkce budeme probírat později - každý program v C začíná funkcí nazvanou main - funkce main je po spuštění programu volána operačním systémem - do kulatých závorek () za názvem funkce se píší parametry funkce, main sice žádné nemá, ale i tak je nutné závorky () napsat - složené závorky { } ohraničují funkci main - int znamená, že funkce main vrací celočíselnou hodnotu - vrácení hodnoty se vykoná příkazem return 0; (je tedy vrácena 0) - příkazem return 0; končí funkce main => končí celý program všechny příkazy jsou ukončeny středníkem printf( Kuk!!! ); - zajišťuje výpis na monitor - v tomto případě vypíše text Kuk!!! informace pro OS o korektním ukončení programu 15
Hlášení kompilátoru Chybové hlášení - kompilátor sděluje, že zdrojový kód nelze přeložit - nejčastější příčinou je syntaktická chyba (ale může být i jiná) - hlášení obvykle obsahuje: název zdrojového souboru číslo řádky zdrojového kódu pokus o vysvětlení problému pozn. informace o čísle řádku a vysvětlení problému mohou být matoucí - příčina může být o několik řádek jinde než kde ji vidí kompilátor! prvni_program.c line 6 error:'return' with no value, in function returning non-void ( hlášení kompilátoru, pokud v předchozím příkladu vynecháme nulu za slovem return ) Varovnání - kompilátor sděluje, že zdrojový kód obsahuje něco podezřelého - program sice jde přeložit, ale varování často poukazuje na místo, které později způsobí pád programu či zdánlivě nesmyslné výsledky k varování přistupujeme stejně jako k chybám spokojeni jsme jen když kompilátor hlásí Build finished: 0 error(s), 0 warning(s) (což znamená, že v programu nejsou syntaktické chyby) 16
Styl psaní kódu I - prázdné znaky mezera, tabulátor, prázdný řádek - jsou kompilátorem ignorovány - program lze napsat takto: #include <stdio.h> int main() { printf("kuk!!!"); return 0; } nebo i takto #include <stdio.h> int main ( ){ printf("kuk!!!") ; return 0 ;} - pro kompilátor jsou oba zápisy identické, nicméně druhý zápis je z programátorského hlediska zcela nesmyslný - prázdné znaky mají sloužit k větší přehlednosti zdrojového kódu - každý programátor si vytváří vlastní styl psaní kódu, existují ale obecná doporučení, která se vyplatí dodržovat (budete na ně průběžně upozorňováni) pozn.: mezery nesmí být uvnitř slov, která mají pro kompilátor speciální význam (return, printf, názvy proměnných...), zápis re turn 0; způsobí chybu v době kompilace 17
Styl psaní kódu II - komentáře Komentáře - části zdrojového kódu, které kompilátor ignoruje (jsou odstraněny preprocesorem) - do kódu se píší proto aby se v něm vyznal někdo cizí, když ho bude číst vyznal sám programátor, když ho bude číst s časovým odstupem - dobře napsané komentáře výrazně zpřehledňují kód - styl a hustota komentářů jsou věcí vkusu každého programátora Jednořádkový komentář - začíná dvěma lomítky // - kompilátor ignoruje vše od lomítek až do konce řádku // toto je jednořádkový komentář psaní komentářů je rozhodně doporučeno! Víceřádkový komentář - začíná znaky /* a končí znaky */, kompilátor ignoruje celý obsah komentáře /* toto je víceřádkový komentář */ pozn. komentáře slouží i k dočasnému zneviditelnění ( vykomentování ) aktuálně nepotřebných úseků kódu při psaní a ladění programu 18