FAKULTA ELEKTROTECHNIKY A KOMUNIKAČNÍCH TECHNOLOGIÍ VYSOKÉ UČENÍ TECHNICKÉ V BRNĚ Počítače a programování 2 Garant předmětu: Doc. Dr. Ing. Zbyněk Raida Autoři textu: Doc. Dr. Ing. Zbyněk Raida Ing. Pavel Fiala, Ph.D.
Počítače a programování 2 1 Obsah 1 ÚVOD...3 1.1 PROGRAMOVÁNÍ...3 1.2 ZÁKLADNÍ POJMY A UJEDNÁNÍ...5 1.3 ZÁKLADNÍ PRINCIPY, FUNKCE POČÍTAČE...6 1.4 ZÁKLADNÍ PRVKY ZÁPISU BLOKOVÉHO SCHÉMATU...8 1.5 ALGORITMY...9 1.6 KONTROLNÍ PŘÍKLADY (ALGORITMIZACE)...10 1.7 KONTROLNÍ OTÁZKY...11 2 BORLAND C++ BUILDER 5.0...13 2.1 VÝVOJ APLIKACE...14 2.1.1 Spuštění Builderu...14 2.1.2 Základní nastavení...15 2.1.3 Sestavení okna...15 2.1.4 Ošetření událostí...16 2.1.5 Ladění...17 2.2 KONTROLNÍ PŘÍKLADY...18 2.3 KONTROLNÍ OTÁZKY...19 3 JAZYK C...19 3.1 IDENTIFIKÁTORY...19 3.2 TYPY DAT, PROMĚNNÉ...20 3.2.1 Lokální a globální proměnné...20 3.2.2 Pravidla deklarování proměnných...21 3.2.3 Základní typy proměnných...22 3.2.4 Ukazatele...22 3.2.5 Pole...23 3.2.6 Inicializace proměnných...26 3.2.7 Kontrolní příklady...26 3.2.8 Kontrolní otázky...26 3.3 LITERÁLY...27 3.3.1 Celočíselné konstanty...27 3.3.2 Racionální konstanty...27 3.3.3 Znakové konstanty...28 3.3.4 Řetězcové konstanty...28 3.4 VÝRAZY A OPERÁTORY...28 3.4.1 Aritmetické konverze...29 3.4.2 Priorita operací...30 3.4.3 Aritmetické operátory...31 3.4.4 Relační operátory...31 3.4.5 Logické operátory...31 3.4.6 Bitové operátory...34 3.4.7 Operátory inkrementování a dekrementování...35 3.4.8 Přiřazovací operátory...36 3.4.9 Kontrolní příklady...36 3.4.10 Kontrolní otázky...36 3.5 PŘÍKAZY...37 3.5.1 Příkazy pro větvení programu...39
2 Fakulta elektrotechniky a komunikačních technologií VUT v Brně 3.5.2 Příkazy pro cykly... 40 3.5.3 Příkazy pro přenos řízení... 42 3.5.4 Kontrolní příklady... 45 3.5.5 Kontrolní otázky... 45 3.6 FUNKCE... 46 3.6.1 Rekurze funkcí... 49 3.6.2 Funkce main... 50 3.6.3 Kontrolní příklady... 51 3.6.4 Kontrolní otázky... 51 3.7 VÍCE O DATOVÝCH TYPECH... 52 3.7.1 Struktury... 52 3.7.2 Unie... 56 3.7.3 Výčtové typy... 56 3.7.4 Dynamické proměnné... 59 3.7.5 Kontrolní příklady... 69 3.7.6 Kontrolní otázky... 70 3.8 NÁMĚTY TÉMAT ZÁVĚREČNÝCH PROJEKTŮ... 70 3.9 ZÁVĚR... 71 3.10 LITERATURA... 71 4 MATLAB... 72 4.1 UŽIVATELSKÉ ROZHRANÍ MATLABU... 73 4.2 OPERACE S MATICEMI... 75 4.2.1 Vytváření matic... 76 4.2.2 Aritmetické operace... 81 4.2.3 Logické operace... 83 4.2.4 Relační operace... 84 4.2.5 Kontrolní příklady... 84 4.2.6 Kontrolní otázky... 85 4.3 M-SOUBORY... 86 4.3.1 Skripty... 86 4.3.2 Funkce... 87 4.3.3 Globální proměnné, lokální funkce... 88 4.3.4 Řízení běhu programu... 90 4.3.5 Kontrolní příklady... 97 4.3.6 Kontrolní otázky... 98 4.4 PŘÍKLADY ELEKTROTECHNICKÝCH VÝPOČTŮ... 98 4.4.1 Numerické integrování... 98 4.4.2 Výpočet spektra signálu... 101 4.4.3 Kontrolní příklady... 104 4.4.4 Kontrolní otázky... 105 4.5 ZÁVĚR... 105
Počítače a programování 2 3 1 Úvod Předmět Počítače a programování 2 je vyučován v letním semestru 1. ročníku bakalářského studia. Předmět je společný všem oborům bakalářského studijního programu Elektrotechnika, elektronika, komunikační a řídicí technika. I když je předkládané skriptum věnováno předmětu letního semestru, jeho úvodní pasáže použijeme i v semestru zimním, v předmětu Počítače a programování 1. Zde se totiž poprvé seznámíme s jazykem C a s vývojovým nástrojem Borland C++ Builder 5.0, s jehož pomocí budeme společně do tajů jazyka C pronikat. Poté co se v našem kursu podrobně seznámíme s programováním v jazyce C, přejdeme k programu Matlab. Matlab je speciální matematický program pro inženýrské a vědecké výpočty. Většina matematických operací či metod pro zobrazování výsledků již byla tvůrci Matlabu vytvořena a je nám v současnosti k dispozici. Píšeme-li svůj algoritmus v Matlabu, nemusíme se matematikou zabývat a můžeme se soustředit na vlastní jádro našeho programu. Abychom získali popsané znalosti a dovednosti, musíme dobře rozumět tomu, proč počítač funguje a jak pracuje, co jsou základní části počítače a jaká je jejich funkce. Všechny tyto znalosti získáme v předmětu Počítače a programování 1. 1.1 Programování Pod pojmem programování rozumíme psaní textu, který procesoru počítače jednoznačně říká, co má dělat a jak. Psaní programu můžeme rozdělit do následujících kroků: 1. Sestavení algoritmu. Na základě zadaného úkolu navrhneme postup (sestavíme algoritmus), jakým lze danou úlohu vyřešit. Algoritmus obvykle vyjadřujeme blokovým schématem. Na pevném disku počítače máme v souboru teplo.dat uloženy teploty, které byly během předchozího dne naměřeny v každou celou hodinu. Našim úkolem je určit tu hodinu, kdy byla teplota nejnižší. Soubor tedy otevřeme (data uložíme do pole temp) a do pomocné proměnné min_temp uložíme nerealisticky vysokou teplotu (900 C). Obsah proměnné min_temp budeme postupně porovnávat s jednotlivými zaznamenanými teplotami (na právě porovnávaný údaj ukazuje index m). Pokud je některá zaznamenaná teplota nižší nežli obsah min_temp (větev ANO) uložíme tuto hodnotu do min_temp, a start temp teplo.dat min_temp 900 m 1 min_temp >temp(m) ANO NE min_temp teplo(m) min_time m m<25 m m + 1 ANO NE konec Obr. 1.1 Algoritmus hledání nejnižší teploty
4 Fakulta elektrotechniky a komunikačních technologií VUT v Brně současně do proměnné min_time uložíme pořadí daného čísla (dané teploty) v souboru teplot; pořadí čísla v souboru totiž odpovídá hodině, kdy byla teplota naměřena. V opačném případě (testovaná teplota ze souboru je vyšší nežli obsah min_temp) se nic neděje. Jakmile projdeme všechna čísla v souboru (index m je větší než počet hodin dne), budeme mít v proměnné min_temp údaj o nejnižší naměřené teplotě a v proměnné min_time údaj o hodině, kdy byla tato teplota naměřena. Popsaný algoritmus lze vyjádřit blokovým schématem z obr. 1.1. 2. Zapsání algoritmu pomocí programovacího jazyka. Na základě přesně daných pravidel napíšeme text (zdrojový kód), který překladač programovacího jazyka umí přeložit do kódu strojového do kódu, kterému rozumí procesor našeho počítače. Pokud se rozhodneme algoritmus pro vyhledávání nejnižší teploty (obr. 1.1) vyjádřit v jazyku C (s využitím Borland C++ Builder), bude zdrojový kód algoritmu vypadat následovně: void fastcall TForm1::find_min(TObject *Sender) // pole teplot; první údaj naměřen v 1:00, poslední údaj // naměřen ve 24:00 double temp[24] = -8.1, -8.3, -8.6, -9.2, -9.4, -9.2, -9.0, -8.5, -7.9, -6.7, -5.0, -2.3, +1.1, +2.3, +1.2, -0.8, -2.6, -4.1, -5.2, -6.3, -7.7, -8.5, -9.1, -9.3; double min_temp; // nejnižší teplota int min_time; // hodina, kdy naměřena min.teplota int m; // index pro vyhledávání min_temp = 900; // počáteční nastavení for( m=1; m<25; m++) // cyklus přes 24 hodiny if( temp[m-1]<min_temp) // pokud v m-té hodině teplota nižší // nežli min_temp min_temp = temp[m-1]; // změň obsah min_temp min_time = m; // ulož údaj o hodině s min.teplotou result->caption = FloatToStr( min_temp); // zobraz min.teplotu hour->caption = IntToStr( min_time); // zobraz hodinu První řádek obsahuje hlavičku, automaticky generovanou Builderem. Složené závorky označují kód, který společně tvoří jeden blok. Za dvojité lomítko můžeme psát svůj komentář (znaky komentáře jsou překladačem ignorovány). Slovo double uvozuje reálnou proměnnou, slovo int celočíselnou proměnnou. Proměnná temp sestává z 24 reálných čísel. Pomocí znaménka = vložíme do proměnné konkrétní číselnou hodnotu. Řádkem for říkáme, že následný kód budeme vykonávat od m=1 do m=24 (poté přestane platit m<25), přičemž po každém vykonání následného kódu bude hodnota indexu m zvýšena o jedničku (m++). Pokud je splněna nerovnost v kulaté závorce za if, vykoná se následný blok ve složené závorce; v opačném případě nebude vykonáno nic. Poslední dva řádky vypíší nejnižší teplotu a odpovídající hodinu do okna programu. 3. Ladění programu. Člověk je omylný, a proto se při psaní zdrojového kódu dopouští omylů. Naše možné chyby přitom můžeme rozdělit na omyly syntaktické a omyly logické.
Počítače a programování 2 5 Syntaktickým omylem rozumíme omyl v zápisu (záměna malého a velkého písmene, odkaz na neexistující proměnnou, atd.). Na syntaktický omyl nás upozorní překladač, který v důsledku našeho omylu není schopen převést náš zdrojový kód na kód strojový. Pokud bychom cyklus v našem příkladu zahájili slovem For, dopustili bychom se syntaktického omylu (v syntaxi jazyka C je pro cyklus rezervováno slovo for). Logickým omylem je omyl, který překladač neodhalí; po spuštění programu se však naše aplikace chová jinak, než jsme očekávali. Napíšeme-li v našem příkladu místo přiřazení min_time=m nesprávně min_time=m+1, bude údaj o času nejnižší teploty posunut o jednu hodinu. Běh programu bude bezproblémový, avšak produkovaný výsledek bude chybný. Proces odstraňování omylů je nazýván laděním (debugging). Ladění je posledním krokem při vývoji programu. Soubory výše popsaného programu jsou uloženy v adresáři min_temp. 1.2 Základní pojmy a ujednání Programátoři mezi sebou komunikují specifickým jazykem. Abychom tomuto jazyku porozuměli, seznámíme se nyní společně s pojmy, s nimiž se budeme setkávat. Program, aplikace (program, application) v podstatě říká procesoru počítače, co má dělat, aby byl splněn zadaný úkol. Program sestává z dat (číselné údaje, které v programu zpracováváme) a z kódu (posloupnost instrukcí, jak mají být data zpracovávána). Proměnná (variable) reprezentuje v programu data. Proměnná představuje náš vlastní název části paměti počítače, do níž můžeme uložit údaje a z níž můžeme dříve uložené údaje číst. Funkce (function) je část kódu, která definuje odezvu programu na určitou událost. Funkce je posloupnost příkazů, které jsou při jejím volání postupně vykonávány. Objekt, třída (object, class) je jakýmsi rámem, svazujícím dohromady data (proměnné) a kód (funkce). Původní jazyk C objekty (objektově orientované programování) nepodporuje. Objektová verze jazyka C se jmenuje C++. Komponent (component) je objekt, který můžeme vizuálně programovat. V Borland C++ Builder jsou komponenty umístěny na paletě, z níž si je programátor myší vybírá a umisťuje do okna svého programu. Událost (event) popisuje přesně definovanou situaci, na níž má program reagovat. Událostí je kliknutí na tlačítko v okně (OnClick), událostí je stisknutí klávesy na klávesnici (onkeydown) či otočení kolečkem mezi tlačítky myši (OnMouseWheel). Pracujeme-li v Borland C++ Builder, píšeme tzv. událostmi řízený program. Pro události, na které má náš program reagovat, sestavujeme obslužné funkce. Vznik události odpovídající funkci automaticky vyvolá. Programová jednotka (unit). Aby bylo dosaženo větší přehlednosti zdrojového kódu rozsáhlých programů, může být tento kód rozdělen do mnoha diskových souborů. Tyto diskové soubory se nazývají jednotky. Pracujeme-li v Borland C++ Builder, každé okno programu je uloženo ve zvláštní jednotce. Jednotka má příponu *.cpp.
6 Fakulta elektrotechniky a komunikačních technologií VUT v Brně Projekt (project) je jakýmsi rámem, svazujícím dohromady všechny jednotky, z nichž sestává program. V Borland C++ Builder je projekt sestavován samočinně; soubor projektu má příponu *.bpr. Co se týká textu naší učebnice, budeme v ní střídat různá písma: Times New Roman zvýraznění částí textů (zejména různé názvy) Courier části zdrojových textů Courier klíčová slova ve zdrojovém textu Courier komentář zdrojových textů Arial Arial Arial název diskového souboru nebo adresáře nově zaváděný termín anglický překlad nově zaváděného termínu Nyní, když máme definovány základní pojmy a stanovena základní pravidla, budeme se věnovat procvičení algoritmického myšlení. Sestavené algoritmy budeme v dalším převádět do zdrojového kódu v jazyce C a v jazyce Matlabu. Dříve, než tak učiníme, zopakujeme si základní vědomosti o počítačích, s nimiž jsme se seznámili v předchozím kursu. 1.3 Základní principy, funkce počítače V současné době se můžeme setkat s mnoha typy počítačů. Rozlišujeme mezi programovatelnou kalkulačkou a počítačem. Jsou používány kapesní počítače (pocket computers), osobní počítače (personal computers) stolní (tower, desktop), přenosné (notebook) a stanice (stations). Vyšší systémy a třídy počítačů zatím nebudou uváděny. Jednotlivé třídy počítačů mají jak vlastní způsob řešení technického vybavení (hardware), tak vybavení programového (software). Kapesní počítače bývají omezeny ve svých funkcích, zobrazovacím zařízení (display), výstupních zařízeních tisk (printer), kresba (plotter). Jsou omezeny v maximální použité operační (vnitřní) paměti RAM (Random Access Memory), použitém procesoru. Těmito skutečnostmi je ovlivněna možnost použití programu, který ovládá základní funkce procesoru, vstupního zařízení (klávesnice), výstupního zařízení, zobrazovacího zařízení a dalších, a nazýváme jej operačním systém (OS). V třídě kapesních počítačů zatím pracují operační systémy jak instrukcemi řízené, tak událost- Kapesní počítač SW- operační systém Překladač textu uživatelského programu Procesor Sběrnice RAM- text uživatelského programu Zobrazovací jednotka - display Vstupní jednotkaklávesnice Obr. 1.4 Instrukcemi řízený OS Smyčka
Počítače a programování 2 7 mi řízené. Jejich principiální funkce je na obr. 1.4 a obr. 1.5. Operační systém Systémová fronta Překladač textu uživatelského programu Aplikace I Aplikace II Procesor RAM Sběrnice Zobrazovací jednotka - display Vstupní jednotkaklávesnice Kapesní počítač SW Smyčka V instrukcemi řízeném systému je použita pouze jedna smyčka, kde zařazené instrukce jsou okamžitě provedeny. K této smyčce není programově snadný přístup. Většinou do ní musíme vstupovat v jazyce procesoru (jazyk symbolických adres ASEMBLER). Text programu je uložen v paměti RAM. Nejsou zde příliš rozšířené externí paměti v podobě diskových jednotek. Jádro operačního systému prověřuje jednotlivé části počítače v pravidelných intervalech, které nelze jednoduše měnit. Pokud toto zařízení předává nějakou instrukci, ta je v nejkratší možné době provedena. Standardním vybavením takového kapesního počítače je překladač jazyka. Většinou se jedná o jazyk BASIC, který vyniká jednoduchostí a snadností programování. Program napsaný uživatelem je uložen do paměti RAM a při spuštění programu dojde k procházení paměti a k překladu textu programu slovo za slovem. Mluví se o tak zvaných interpretrech. Nedojde k překladu programu a potom jeho spuštění, k ale postup- Obr. 1.5 Událostmi řízený OS nému překládání a podle získaných instrukcí je ovlivňován chod programu. Programy, spouštěné pomocí interpreterů jsou velmi pomalé, ale jsou snadno a rychle měnitelné. V událostmi řízeném systému (obr. 1.5), se několik skutečností změnilo. Bylo to způsobeno rozšiřováním grafických operačních systémů, zejména v třídě osobních počítačů. Jako komerčně úspěšné firmy lze uvést například výrobce počítačů Apple Macintosh nebo v naší zemi rozšířené produkty firmy Microsoft. Tedy u kapesních počítačů se objevují grafické operační systémy, které pracují jako událostmi řízené programy. Smyčka je programově přístupná, její doba a pořadí přístupu k aplikacím nebo částem počítače je řízena programem, to znamená i uživatelem. Překladač je jako samostatný program. Text programu překladač přeloží a uloží do paměti. Program je uložen ve formě spustitelného souboru. Osobní počítače (PC) jsou velmi rozšířenou skupinou počítačů. Jejich velké rozšíření bylo způsobenou několika faktory: pořizovací cena počítače je nízká vzhledem ke stanicím a k sálovým počítačům, jsou snadno modifikovatelné, mají přijatelný výkon za svou cenu, je k dispozici velké množství programů spustitelných na PC. Osobní počítače mají malé rozměry, jsou tvořeny do jisté míry samostatnými komponenty (klávesnice, monitor, tiskárna, myš, tablet, scanner, skříň počítače). Vzhledem ke kapesním počítačům jsou vybaveny o další prvky. Na obr. 1.6 je zachycen princip funkce programu v událostmi řízeném operačním systému. Důležitou částí je vnější paměť, disk. Přenosná a archivační paměťová média jsou diskety, ZIP disky, JAZ disky, kompaktní disky CD, digitální videodisky DVD a samozřejmě záznamové jednotky. Klávesnice je vzhledem ke kapesním počítačům rozšířená a má svůj standard. Vstupní zařízení je pro grafické operační systémy rozšířeno o takzvanou myš. Jedná se o zpětnovazební prvek, se kterým se lze v grafickém prostředí pohybovat, zadávat jednoduché povely. Operační systémy jsou sestavovány tak, aby případný výpadek funkce myši byl
8 Fakulta elektrotechniky a komunikačních technologií VUT v Brně nahrazen klávesnicí. Dalším vstupním zařízením je tablet. Slouží pro specializované aplikace k zadávání dat. Standardním výstupním zařízením osobního počítače je zobrazovací jednotka monitor. Jsou na něj kladeny vyšší požadavky než je u kapesních počítačů. Má vyšší rozlišovací schopnost, barevnou věrnost, kvalitní zobrazení po celé ploše, minimální je fyziologická zátěž zraku. Tiskárny u osobních počítačů mají standard rozhraní, jsou ovládány vlastními programy, které se spouštějí v operačním systému počítače. Vlastní část počítače je umístěn ve skříni. Skládá se ze základní desky (mainboard, matherboard) a ze zdroje. Na základní desce je umístěn procesor, paměť RAM a komponenty přizpůsobení k dalším zařízením (karty). Karty jsou prostředky technického vybavení, které mají standardizovaný rozměr a připojení k základní desce. Vnější paměť (disk) je umístěna mimo desku. Bývá připojeno minimálně Operační systém Fronta aplikací Systémová fronta Překladač textu uživatelského programu Aplikace I Aplikace II Procesor RAM Sběrnice Zobrazovací jednotka - display Vstupní jednotkaklávesnice SW HW Smyčka server Obr. 1.6 Událostmi řízený OS osobní počítač jedno zapisovací a čtecí zařízení pro přenosná a archivační paměťová média disketa, CD, ZIP. Stanice jsou méně cenově dostupné počítače. Jsou výkonnější než osobní počítače a jejich vývoj je díky menšímu nasazení drahý. Konstrukce je blízká osobním počítačům. Je zde kladen velký důraz na vysoký výkon vlastní části počítače, značně velkou a rychlou paměť RAM. Vnější paměť bývá realizovaná ve zvláštních částech disková pole. Počítač mívá více procesorů. Díky malému rozšíření počítačů je programové vybavení drahé. Používá se zde událostmi řízených operačních systémů s vysokým stupněm zabezpečení. Například systémy jako UNIX, LINUX a další jsou psány v jazyce C, C++. Rozšiřují se grafické nástavby pro tyto operační systémy. V následujícím odstavci se seznámíme podrobněji se základními značkami, které slouží k vyjádření algoritmu pomocí blokového schématu. 1.4 Základní prvky zápisu blokového schématu Abychom mohli srozumitelně zapisovat algoritmy programů, seznámíme se se základními značkami, které se objevují v blokových schématech. Značka pro předepsaný postup: A=B, A=A+1, A=A*B
Počítače a programování 2 9 Značka pro načtení, výstup Vstup A, Výstup A Značka pro rozhodnutí Značka pro začátek, konec začátek konec Značka pro funkci, podprogram A<B, A>B, A=B, A B, A B, A B a, nebo, negace A A Značka pro cyklus cyklus I = 1,.., N Značka pro skok skok na 1.5 Algoritmy Má-li se řešit nějaká programátorská úloha, naskytne se více přístupů a postupů řešení. Z nich je třeba vybrat jeden postup a ten formulovat pomocí vývojového diagramu. Pro výběr se musí určit nějaká kritéria, podle kterých se zvolí postup řešení programu. Musí se tedy rozhodnout, který postup je lepší a který je horší. Co to je lepší a horší? Kritéria pro posuzování kvality algoritmu jsou jak subjektivní tak objektivní. Dále se budeme zabývat více těmi objektivními kritérii. Základní objektivní kritéria hodnocení algoritmu tedy jsou: 1. Rychlost algoritmu (výpočtu) 2. Paměťová náročnost operační i externí paměť 3. Stabilita algoritmu Problematika těchto kritérií je velmi rozsáhlá, ale pro účely tohoto textu se budeme držet nutných pojmů a praktických důsledků bez uvedení odvození a důkazů. Prvně dvě kritéria jsou významná hlediska při hodnocení algoritmů. Jsou odlišná a velmi často stojí proti sobě. Bývají algoritmy takové, že jeden z nich je pomalejší, ale používá malou operační paměť, zatímco druhý je rychlejší, ale má vysoké nároky na operační paměť. To je často způsobeno tím, že pro zrychlení algoritmu je použita další pomocná proměnná nebo množina proměnných, které budou uchovány v operační paměti. Tím se zvětší
10 Fakulta elektrotechniky a komunikačních technologií VUT v Brně nároky na paměť za cenu zrychlení výpočtu. Pro volbu paměťové náročnosti a rychlosti neexistuje obecné řešení, záleží vždy na požadavcích, které jsou kladeny na program. Samozřejmě první dvě kritéria jsou závislá také na použitém technickém vybavení (hardware). Jako příklad lze uvést úlohu vyhledání telefonního čísla v seznamu. Jedním z postupů je vyhledání čísla tak, že začneme procházet seznam od počátku, až nalezneme to hledané. Tento postup se nazývá sekvenčním vyhledáváním. Ve skutečnosti jsou jména v seznamu seřazena podle abecedy. Postup při vyhledávání je podle srovnání rostoucích n-tic písmen jména. Pokud hledané jméno je Novák, první n-tice je N. Dále je hledána druhá n-tice No, atd. Stabilita algoritmu závisí jak na vstupních údajích programu, tak na zvolené metodě algoritmu. Doba výpočtu i paměťové nároky bývají také závislé na vstupních údajích. Program většinou řeší celou třídu podobných problémů, které se liší právě zadávanými vstupními údaji. Ale trvání výpočtu i paměťové nároky často neovlivňují konkrétní zadané hodnoty, jen velikost vstupních dat. Prakticky, je jedno zda vyhledávám jedno telefonní číslo v telefonním seznamu s 3000 položkami nebo vyhledávám naměřenou teplotu s 3000 údaji. Ale je rozdíl, pokud vyhledávám telefonní číslo v seznamu Znojma a Brna. Potom bude algoritmus mít rozdílnou dobu trvání. Paměťová náročnost u algoritmů se uvádí v jednotkách jakými jsou bit nebo bajt. Bit je jednotka, která může být nuď ve stavu logické jednotky nebo ve stavu logické nuly. Bajt je jednotka (slovo), která je složena z několika bitů. Počet bitů v bajtu je dán mnoha kritérii. Jsou obvykle používány 8, 16, (24), 32, 64, 128, bitová slova. Časová náročnost se udává v souvislosti s použitým typem procesoru, velikostí RAM a její rychlosti, konfiguraci základní desky, typem a výrobcem operačního systému. Udává se buď jako doba pro nejhorší případ složitosti algoritmu se vstupními daty velikosti N nebo jako průměrný případ výpočtu z N vstupních dat. Algoritmy se porovnávají v jejich časové náročnosti. Ta je porovnána a je rozhodnuto, který z nich je rychlejší. Stává se, že vstupní data a jejich rozsah nejsou specifikovány. Potom nelze stanovit časovou náročnost. Postupuje se tak, že se zvolí pro rozsah dat velké číslo N a provede se srovnání algoritmů s uvedením podmínek. Jedná se tedy o asymptotickou časovou náročnost. Tedy časová náročnost lepšího algoritmu roste pomaleji s rostoucími hodnotami N. Časovou náročnost lze popsat typem funkce a jejím řádem. Rozeznáváme tedy základní polynomiální a exponenciální funkce. 1.6 Kontrolní příklady (algoritmizace) Příklad 1. Sestavte a nakreslete diagram algoritmu pro nalezení minimálního čísla z řady N zadaných. Nechť je výsledek zobrazen na výstupním zařízení. Příklad 2. Sestavte a nakreslete diagram algoritmu pro nalezení maximálního čísla z řady N zadaných. Nechť je výsledek zobrazen na výstupním zařízení. Příklad 3. Sestavte a nakreslete diagram algoritmu pro nalezení součtu čísel z množiny A a množiny B. Prvky množiny A i B jsou celá čísla, počet prvků množiny A je N a množiny B je M. Nechť je výsledek zobrazen na výstupním zařízení. Příklad 4. Sestavte a nakreslete diagram algoritmu pro nalezení součinu čísel z množiny A a množiny B. Prvky množiny A i B jsou reálná čísla, počet prvků množiny A je N a množiny B je M. Platí, že M=N. Nechť je výsledek zobrazen na výstupním zařízení.
Počítače a programování 2 11 Příklad 5. Sestavte a nakreslete diagram algoritmu pro porovnání obsahu množiny A a množiny B. Prvky množiny A i B jsou celá čísla, počet prvků množiny A je N a množiny B je M. Pokud množiny mají společný prvek (číslo) zobrazte je na výstupním zařízení. Příklad 6. Sestavte a nakreslete diagram algoritmu pro průnik C obsahu množiny A a množiny B. Prvky množiny A i B jsou reálná čísla, počet prvků množiny A je N a množiny B je M. Množinu C zobrazte na výstupním zařízení. Příklad 7. Sestavte a nakreslete diagram algoritmu pro sjednocení C obsahu množiny A a množiny B. Prvky množiny A i B jsou reálná čísla, počet prvků množiny A je N a množiny B je M. Množinu C zobrazte na výstupním zařízení. Příklad 8. Sestavte a nakreslete diagram algoritmu pro zjištění, zda zadané číslo N je prvočíslo. Příklad 9.Sestavte a nakreslete diagram algoritmu pro výpočet funkce 5 555. Příklad 10. Sestavte a nakreslete diagram algoritmu pro součet matic A a B. Prvky množiny A i B jsou reálná čísla, počet prvků množiny A je N N a množiny B je M M. Množinu C zobrazte na výstupním zařízení. Příklad 11. Sestavte a nakreslete diagram algoritmu pro součin matice A a vektoru B. Prvky množiny A i B jsou reálná čísla, počet prvků množiny A je N N a množiny B je M. Množinu C zobrazte na výstupním zařízení. Příklad 12. Sestavte a nakreslete diagram algoritmu pro součin matic A a B. Prvky množiny A i B jsou reálná čísla, počet prvků množiny A je N N a množiny B je M M. Množinu C zobrazte na výstupním zařízení. 1.7 Kontrolní otázky 1. Určete maximální časovou náročnost třech vnořených cyklů s maximálním N smyčkami. 2. Určete průměrnou časovou náročnost třech vnořených cyklů s maximálním N smyčkami. 3. Určete časovou náročnost algoritmu, který zjišťuje, zda zadané číslo je prvočíslo. 4. Na čem je závislá časová náročnost algoritmu? 5. Existuje optimální nastavení paměťové a časové náročnosti algoritmu? 6. Jak ovlivní počet vnořených cyklů časovou náročnost algoritmu? 7. Jaký je rozdíl v časové náročnosti třech vnořených a třech postupně zařazených cyklů? 8. Mohou hodnoty vstupních dat ovlivnit časovou náročnost programu? 9. Může rozsah vstupních dat ovlivnit časovou náročnost programu? 10. Může rozsah vstupních dat ovlivnit stabilitu programu? 11. Mohou hodnoty vstupních dat ovlivnit stabilitu programu? 12. Vysvětlete rozdíl mezi operačním systémem řízeným událostmi a instrukcemi. 13. Je výhodné používat pro spuštění programu v osobním počítači interpreter? 14. Co je to algoritmus? 15. Co je to funkce, proměnná, objekt, třída? 16. K čemu je dobrý programovací jazyk?
speedbar paleta komponentů inspektor objektů formulář editor Obr. 2.1 Borland C++ Builder, verze 5: integrované uživatelské rozhraní
Počítače a programování 2 13 2 Borland C++ Builder 5.0 Borland C++ Builder je nástrojem pro vývoj programů, určených pro operační systémy Microsoft Windows. Builder pracuje se zdrojovými kódy, sestavenými v programovacím jazyce C++. Builder využívá principů tzv. vizuálního programování (drag &drop design). Psaní aplikace probíhá tak, že programátor sestavuje myší uživatelské rozhraní svého programu, a Builder mu generuje odpovídající zdrojový kód, napsaný v jazyce C++. Pokud programátor zasáhne do zdrojového kódu, změna se samočinně promítne do vizuálně sestaveného prvku a naopak (tzv. two-way tool). Integrované prostředí nástroje Builderu sestává ze sedmi základních částí (obr. 2.1): Paleta komponentů (component palette) je tvořena sadou záložek, na kterých jsou umístěny komponenty, z nichž lze vizuálně sestavovat okno programu (formulář, form). Volná místa na záložkách jsou připravena pro umístění originálních komponentů, vytvořených programátorem. Formulář (form) je základní okno operačního systému Windows s tečkovaným rastrem, do něhož myší umisťujeme jednotlivé komponenty. Jednotlivé parametry (proměnné) formuláře a vkládaných komponentů můžeme zadávat buď pomocí myši (umístění, rozměr), a jednak je můžeme určovat prostřednictvím inspektoru objektů (viz dále). Všechny zadané hodnoty proměnných se samočinně promítnou do zdrojového kódu vyvíjené aplikace. Inspektor objektů (Object Inspector) sestává ze dvou záložek ze záložky s názvem Proměnné (Properties) a ze záložky s názvem Události (Events). Záložka Properties obsahuje seznam všech parametrů toho komponentu, který je zaostřen (focused, programátor na něm kliknul myší). Nastavíme-li např. šířku a výšku komponentu myší, numerické vyjádření nastavených rozměrů komponentu se automaticky objeví v inspektoru objektů vedle proměnných Height a Width. Postupovat lze samozřejmě i obráceně. Záložka Events obsahuje seznam událostí objektu, který je právě zaostřen ve formuláři. Událostí rozumíme vše, co může nastat při zaostření daného komponentu. Např. při kliknutí na tlačítko je generována událost OnClick. Má-li kliknutí na tlačítko spustit vykonávání určitého kódu (má být volána určitá funkce), vepíšeme do editačního řádku vedle události jméno funkce a stiskneme klávesu Enter. Builder automaticky vygeneruje hlavičku funkce, a nám stačí její tělo (prostor mezi složenými závorkami) vyplnit zdrojovým kódem. Editor kódu (Code Editor) slouží k vytváření zdrojového kódu, napsaného v jazyce C++. Část kódu je generována samočinně jako reakce na vizuální sestavování formuláře, zbytek musí programátor dopsat sám. Každý formulář aplikace je uložen v samostatné programové jednotce (unit). Zdrojový text jednotky má příponu *.cpp. Urychlující panel (Speedbar) je sestaven z tlačítek, soužících k vyvolání nejčastějších akcí. Detail rychlého panelu a popis funkce jednotlivých tlačítek je zobrazen na obr. 2.2. Anglický popis tlačítka je zobrazován v bublinové nápovědě. Tlačítka Trace Into a Step Over slouží ke krokování programu (programátor manuálně vykonává instrukci za instrukcí). Při Trace Into se vnoříme se do funkce a řádek po řádku vy-
14 Fakulta elektrotechniky a komunikačních technologií VUT v Brně konáváme jednotlivé její příkazy. Při Step Over se do funkce nevnoříme a vykonáme ji jako jeden jediný příkaz. uložení všech souborů uložení souboru otevření souboru otevření projektu přidání jednotky do projektu vyjmutí jednotky z projektu nový objekt seznam jednotek seznam formulářů jednotka formulář nový formulář nápověda "step over" "trace into" přerušení běhu programu spuštění programu Obr. 2.2 Význam tlačítek na rychlém panelu Menu. Vzhledem k obrovskému množství položek, jež jsou do menu zahrnuty, nemá asi smysl brát jednu položku po druhé a vysvětlovat jejich význam. Situaci tedy vyřešíme tak, že se o důležitých položkách zmíníme v kapitole o psaní aplikací. Ladič (Debugger) není na obrázku vidět, protože je do Builderu integrován. Kliknutím na levý okraj řádku v editoru kódu vložíme na tento řádek tzv. přerušovací bod (Breakpoint). Spuštěný program se na daném řádku zastaví, takže programátor zde může kontrolovat a měnit obsah proměnných, může program krokovat nebo jej může znovu spustit, aby pokračoval ve svém chodu. Opětovným kliknutím na totéž místo přerušovací bod odstraníme. Nyní, když jsme se seznámili s integrovaným prostředím Builderu, ukážeme si na příkladu postup vývoje aplikace. 2.1 Vývoj aplikace Vývoj aplikace v Borland C++ Builderu lze rozdělit do několika základních kroků. Nyní si tyto kroky podrobně probereme, abychom mohli vytvořit svůj vlastní program. Základní kroky budeme vysvětlovat na programu, který po stisku tlačítka Počítej načte sčítance, jež uživatel vepíše do editačních řádků formuláře, zadané sčítance sečte a výsledek zobrazí. Formulář programu je zobrazen na obr. 2.3. 2.1.1 Spuštění Builderu Po spuštění obsahuje Builder Obr. 2.3 Okno programu pro sčítání prázdný formulář a prázdné editační okno, které odpovídá programové jednotce tohoto formuláře. Před zahájením práce je vhodné tuto prázdnou aplikaci uložit. Stisknutím čtvrté horní ikony rychlého panelu (Save All) otevřeme standardní dialog pro ukládání do souboru. Builder nám v řádku Název souboru nabídne standardní jméno jednotky formuláře (unit1.cpp). My toto jméno změníme na add_form.cpp (formulář pro sčítání čísel), aby se nám v souborech lépe orientovalo. Po tisku tlačítka Uložit nám Builder nabídne standardní jméno projektu (project1.bpr), přičemž my toto jméno změníme na addition.bpr.
Počítače a programování 2 15 Pokud prázdný, právě uložený projekt spustíme (pátá dolní ikona, Run), objeví se prázdné okno se standardní ikonou a s názvem Form1. Ve stavové liště Windows je běžící aplikace reprezentována tlačítkem se stejnou ikonou a se jménem Addition (jméno odpovídá zvolenému pojmenování projektu). 2.1.2 Základní nastavení Každému programu bývá většinou přiřazena vlastní ikona. Ikonu vytvoříme pomocí editoru, který v Builderu spustíme prostřednictvím položky menu Tools Image editor (editor obrázků). Vybereme-li z menu editoru obrázků položku File New Icon file (a potvrdíme-li standardní parametry ikony 32 32 bodů, 16 barev), spustíme jednoduchý grafický editor, v němž můžeme bod po bodu ikonu sestavit. Výběrem položky menu File Save uložíme ikonu do adresáře k ostatním souborům našeho programu (soubor add_icon.ico). Vytvořenou ikonu přiřadíme naší aplikaci prostřednictvím položky menu Builderu Project Options. Otevřeme tím dialog s třemi řadami záložek. Vybereme záložku Application a stiskem tlačítka Load Icon načteme námi vytvořenou ikonu. Do řádku Title vepíšeme řetězec Sčítání. Stiskem tlačítka OK dialog uzavřeme. Spustíme-li naši aplikaci znovu, jak okno tak tlačítko ve stavové liště Windows budou mít naši ikonu, a navíc, tlačítko v liště bude obsahovat český název Sčítání místo původního Addition. Po základním nastavení aplikace se zaměříme na nastavení parametrů formuláře: 1. Pevné rozměry okna. Myší nastavíme rozměr formuláře (v inspektoru se automaticky mění obsah proměnných Height a Width). V inspektoru nastavíme BorderStyle na bssingle (okno nepůjde roztáhnout myší taháním za okraje) a v BorderIcons nastavíme bimaximize na false (zablokujeme ikonu pro roztažení okna přes celou obrazovku). 2. Popis okna. V inspektorovi naplníme parametr Caption = Sčítání (dosud parametr obsahoval řetězec Form1). Tím jsou základní nastavení dokončena. 2.1.3 Sestavení okna V dalším kroku postupně umístíme dovnitř formuláře komponenty z palety. Jak je vidět z obr. 2.3, pracujeme se třemi komponenty (všechny tři se v paletě nacházejí na záložce Standard). Návěští (Label). Jedná se o text, kterým ve formuláři popisujeme další objekty (v našem případě editační řádky). Návěští můžeme rovněž použít jako textový výstup (v našem případě pro vypsání součtu). V inspektorovi vyplňujeme u návěští proměnné Caption (řetězec, který se objeví ve formuláři), Font (otevře se standardní dialog pro výběr parametrů písma) a Name (jméno návěští). Pro snadnější orientaci ve zdrojovém kódu je vhodné přepisovat standardní jména generovaná Builderem jmény vlastními. Editační řádek (Edit). Jedná se o jednoduchý jednořádkový editor, který můžeme využít jako textový vstup programu (v našem případě pro načítání sčítanců). V inspektoru vyplňujeme u editačního řádku Text (obsah editačního řádku; v našem případě prázdný řetězec tedy nic), Font a v případě potřeby jméno řádku Name.
16 Fakulta elektrotechniky a komunikačních technologií VUT v Brně Pokud chceme editační řádek doplnit bublinkovou nápovědou, nastavíme v inspektoru ShowHint = true a do proměnné Hint vepíšeme obsah bublinky (v našem případě vepíšeme upozornění, že lze vepsat pouze celé číslo). Obdobný mechanismus funguje i u ostatních komponentů. Tlačítko (Button). Základním úkolem tlačítka je dát pokyn k provedení nějaké akce. Pokud uživatel na tlačítko klikne nebo pokud ho stiskne prostřednictvím klávesnice, vždy je generována událost tlačítka OnClick. Tuto událost nalezneme v inspektoru na záložce Events. Vepíšeme-li do editačního řádku vedle události jméno funkce, Builder tuto funkci deklaruje v editoru kódu (jako prázdnou) a její volání pevně sváže s danou událostí. V našem případě nazveme obslužnou funkci addition a její tělo si popíšeme v další podkapitole. Na záložce Properties inspektora zadáme text uvnitř tlačítka Caption = &Počítej (znak & způsobí podtržení následujícího písmene; při stisku klávesové kombinace Alt+P dojde ke stlačení tlačítka). Opět můžeme změnit jméno objektu (Name) a parametry písma uvnitř objektu (Font). Na závěr uveďme ještě jednu poznámku. Je zvykem, že při postupném mačkání tabelační klávesy postupně zaostřujeme jednotlivé komponenty v okně. Pořadí zaostřování komponentů přitom odpovídá pořadí, v němž byly komponenty do okna vkládány. Pokud chceme pořadí zaostřování změnit, učiníme tak v inspektoru prostřednictvím parametru TabOrder. Pokud nechceme, aby se tabelátor na určitém komponentu zastavil, nastavíme pro něj v inspektoru TabStop = false. 2.1.4 Ošetření událostí V našem programu pro sčítání dvou čísel budeme pracovat s jedinou událostí, a to se stiskem tlačítka Počítej. Jakmile uživatel programu toto tlačítko stiskne (objeví se událost tlačítka OnClick), zavoláme funkci addition. Abychom funkci svázali s uvedenou událostí tlačítka, tlačítko zaostříme (klikneme na něj myší) a v inspektoru vepíšeme na záložce Events řetězec addition vedle události OnClick. Potvrdíme-li svou volbu stiskem klávesy Enter, Builder vygeneruje deklaraci této funkce: void fastcall TForm1::addition( TObject *Sender) Funkce je samozřejmě prázdná (neobsahuje žádnou instrukci, nic nedělá). Reakci na stisk tlačítka musíme mezi složené závorky napsat sami jako posloupnost vhodných instrukcí. Než začneme sestavovat program, vysvětleme si stručně význam jednotlivých slov v hlavičce funkce (první řádek). Slovo void označuje funkci, která nevrací žádnou hodnotu. Zatímco např. sin(0.5) vrací sinus 0.5 radiánu, od funkce pro ošetření stisku tlačítka žádnou hodnotu neočekáváme. Slovo fastcall udává způsob, jakým má být funkce volána. Všechny funkce pro ošetření událostí musejí být volány s tímto slovem. Konstrukce TForm1::addition říká, že funkce addition je pevně svázána s hlavním formulářem našeho programu (na ploše tohoto formuláře naše tlačítko leží). Hlavnímu formuláři jsme ponechali standardní název Form1 (položka Name na záložce inspektora Properties), a proto má naše funkce tzv. předponu TForm1.
Počítače a programování 2 17 V závorce za jménem funkce je uveden seznam vstupních parametrů (seznam proměnných, jejichž hodnoty funkci předáváme). V našem případě se jedná o adresu proměnné Sender (hvězdička říká, že nepředáváme funkci číselný obsah proměnné, ale její adresu). Proměnná Sender je typu TObject. O tom, co je to datový typ TObject, se dozvíme později. Nyní již hlavičce vygenerované prázdné funkce rozumíme, a proto se můžeme začít věnovat psaní jejího těla: void fastcall TForm1::addition( TObject *Sender) int first, second; // -1- první a druhý sčítanec first = StrToInt( Add1Edit->Text); second = StrToInt( Add2Edit->Text); // -2- první edit.řádek na číslo // -3- druhý edit.řádek na číslo Result->Caption = IntToStr( first + second); // -4- sečtení a zobrazení Na řádku č.1 zavádíme dvě pomocné proměnné, které existují jen uvnitř naší funkce. Proměnné first a second jsou typu int (celé číslo). Druhý a třetí řádek musíme začít číst zprava. Konstrukce Add1Edit->Text říká, že budeme pracovat s textem, který uživatel vepíše do prvého editačního řádku (v inspektoru jsme ho pojmenovali prostřednictvím položky Name Add1Edit). Vepsaný text je uložen ve formě řetězce (posloupnost znaků) v proměnné editačního řádku Text (viz inspektor, záložka Properties). Abychom mohli provést operaci sčítání, musíme převést řetězec na číslo. O tuto konverzi se stará standardní funkce StrToInt (String To Integer, převod řetězce na celé číslo). Vstupním parametrem je řetězec Add1Edit->Text, výstupním parametrem je celé číslo. Získané celé číslo uložíme do celočíselné pomocné proměnné first. S obsahem druhého editačního řádku a s jeho převodem na druhý sčítanec je to obdobné. Výsledkem je druhý řetězec převedený na celé číslo second. Na posledním řádku obě čísla sečteme (first+second) a součet převedeme z celočíselné formy na řetězec (IntToStr, Integer To String). K zobrazení získaného řetězce využijeme modrého návěští vedle tlačítka Počítej (pojmenovali jsme ho Result inspektor, položka Name). Text návěští je uložen v jeho proměnné Caption. Konstrukce Result->Caption = s tedy říká, že řetězec s ukládáme do proměnné Caption, která patří návěští Result. Dále si můžeme povšimnout, že pro lepší srozumitelnost je naše funkce doplněna komentáři. Komentářem rozumíme libovolný řetězec, umístěný za dvojité lomítko. Komentář může obsahovat libovolné znaky včetně mezer a českých písmen. Text za dvojitým lomítkem je překladačem ignorován. Naši jedinou událost tedy máme ošetřenu. Nyní je třeba zkontrolovat, zda program funguje a zda pracuje správně. 2.1.5 Ladění Při ladění zastavíme program na začátku bloku, v němž předpokládáme chybu (na odpovídající řádek programu vložíme přerušovací bod, breakpoint. Poté kritický blok krokujeme pomocí Trace Into nebo Step Over. V jednotlivých krocích prohlížíme obsah proměnných a
18 Fakulta elektrotechniky a komunikačních technologií VUT v Brně ověřujeme správnost jejich obsahu. Pokud zjistíme nesprávnou hodnotu, můžeme ji pro další ladění nahradit hodnotou korektní. Ke kontrole obsahu proměnných a jejich změně slouží položka menu Run Evaluate/ Modify. Výběrem této položky otevřeme okno z obr. 2.4a. Do řádku Expression vepíšeme název proměnné, stiskneme Evaluate a v editačním poli Result objeví její obsah. Chceme-li obsah proměnné změnit, vepíšeme do řádku New value novou hodnotu proměnné a stiskneme Modify. Do řádku Expression lze psát i celé výrazy (např. i+j). Obr. 2.4 Okno pro vyčíslení výrazů a změnu obsahu proměnných (vlevo). Obsah vybraných proměnných (vpravo). K prostému prohlížení obsahu proměnných slouží jednak bublinová nápověda editačního okna (zastavíme-li kurzor myši na jménu proměnné, objeví se barevný obdélník s textovým vyjádřením obsahu proměnné) a jednak tzv. Watch List (obr. 2.4b). Watch List je okno (otevřeme ho prostřednictvím položky menu Run Add watch), zobrazující seznam vložených proměnných a jejich obsah. Proměnné vkládáme stisknutím klávesy Insert a mažeme klávesou Delete. Proměnnou (nebo výraz) do okna Watch List je možné rovněž přenést z řádku Expression okna Evaluate/Modify stiskem Watch. Ladicí nástroje Builderu jsou velmi efektivní a velmi pohodlné. Přesto je lepší dobře si promyslet a také nakreslit algoritmus sestavovaného programu, abychom se nedopouštěli zbytečných logických omylů. Nutné je dobře se naučit syntaxi programovacího jazyka, abychom se nedopouštěli zbytečných omylů syntaktických. Takže hurá na studium jazyka C. 2.2 Kontrolní příklady Příklad 1. Navrhněte a sestavte program, který bude pomocí tří editačních řádků provádět operace součet a rozdíl. Výsledek bude zobrazen do třetího editačního řádku. Operaci součtu nebo rozdílu proveďte po kliknutí na odpovídající tlačítko. Výsledek se okamžitě zobrazí v příslušném editačním řádku. Příklad 2. Navrhněte a sestavte program, který bude pomocí jednoho editačního řádku provádět operace součet a rozdíl. Výsledek bude zobrazen v editačním řádku. Operaci součtu nebo rozdílu proveďte po kliknutí na odpovídající klávesu pro zobrazení výsledku. Příklad 3. Navrhněte a sestavte program, který bude pomocí jednoho editačního řádku provádět operace součet, rozdíl, součin a podíl. Výsledek bude zobrazen v editačním řádku. Operace proveďte a zobrazte po kliknutí na odpovídající tlačítko pro zobrazení výsledku. Příklad 4. Navrhněte a sestavte program, který bude pomocí jednoho editačního řádku a tlačítek pro zadání čísel provádět operace součet, rozdíl, součin a podíl. Výsledek bude zo-