Programovací jazyk C++



Podobné dokumenty
1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme:

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme:

Programovací jazyk Pascal

Program převod z desítkové na dvojkovou soustavu: /* Prevod desitkove na binarni */ #include <stdio.h>

Úvod do programování. Lekce 1

- jak udělat konstantu long int: L long velka = 78L;

Algoritmizace a programování

Obsah. Předmluva 13 Zpětná vazba od čtenářů 14 Zdrojové kódy ke knize 15 Errata 15

8. lekce Úvod do jazyka C 3. část Základní příkazy jazyka C Miroslav Jílek

Lekce 9 IMPLEMENTACE OPERAČNÍHO SYSTÉMU LINUX DO VÝUKY INFORMAČNÍCH TECHNOLOGIÍ JAZYK C

Úvod do jazyka C. Ing. Jan Fikejz (KST, FEI) Fakulta elektrotechniky a informatiky Katedra softwarových technologií

for (i = 0, j = 5; i < 10; i++) { // tělo cyklu }

Jazyk C Program v jazyku C má následující strukturu: konstanty nebo proměnné musí Jednoduché datové typy: Strukturované datové typy Výrazy operátory

Programování v C++ 1, 1. cvičení

Programování v jazyce C pro chemiky (C2160) 3. Příkaz switch, příkaz cyklu for, operátory ++ a --, pole

Formátové specifikace formátovací řetězce

Programovací jazyk C++ Hodina 1

Jazyk C++, některá rozšíření oproti C

1.1 Struktura programu v Pascalu Vstup a výstup Operátory a některé matematické funkce 5

2 Základní funkce a operátory V této kapitole se seznámíme s použitím funkce printf, probereme základní operátory a uvedeme nejdůležitější funkce.

Výrazy a operátory. Operátory Unární - unární a unární + Např.: a +b

PROMĚNNÉ, KONSTANTY A DATOVÉ TYPY TEORIE DATUM VYTVOŘENÍ: KLÍČOVÁ AKTIVITA: 02 PROGRAMOVÁNÍ 2. ROČNÍK (PRG2) HODINOVÁ DOTACE: 1

Čtvrtek 8. prosince. Pascal - opakování základů. Struktura programu:

Základy algoritmizace a programování

5 Přehled operátorů, příkazy, přetypování

Začínáme vážně programovat. Řídící struktury Přetypování Vstupně výstupní operace Vlastní tvorba programů

EVROPSKÝ SOCIÁLNÍ FOND. Úvod do PHP PRAHA & EU INVESTUJEME DO VAŠÍ BUDOUCNOSTI

Algoritmizace a programování

Logické operace. Datový typ bool. Relační operátory. Logické operátory. IAJCE Přednáška č. 3. může nabýt hodnot: o true o false

Algoritmizace a programování. Ak. rok 2012/2013 vbp 1. ze 44

6. Příkazy a řídící struktury v Javě

for (int i = 0; i < sizeof(hodnoty) / sizeof(int); i++) { cout<<hodonoty[i]<< endl; } cin.get(); return 0; }

Racionální čísla, operátory, výrazy, knihovní funkce

Úvod do programování. Lekce 3

Proměnná a její uložení v paměti

Vyučovací hodina. 1vyučovací hodina: 2vyučovací hodiny: Opakování z minulé hodiny. Procvičení nové látky

Základy jazyka C. Základy programování 1 Martin Kauer (Tomáš Kühr)

Řídicí struktury. alg3 1

Funkce, intuitivní chápání složitosti

Martin Flusser. Faculty of Nuclear Sciences and Physical Engineering Czech Technical University in Prague. October 17, 2016

Paměť počítače. alg2 1

Algoritmizace a programování. Ak. rok 2012/2013 vbp 1. ze 44

VÝUKOVÝ MATERIÁL. Bratislavská 2166, Varnsdorf, IČO: tel Číslo projektu

Příkazy preprocesoru - Před překladem kódu překladačem mu předpřipraví kód preprocesor - Preprocesor vypouští nadbytečné (prázdné) mezery a řádky -

2 Datové typy v jazyce C

Operační systémy. Cvičení 3: Programování v C pod Unixem

Programy na PODMÍNĚNÝ příkaz IF a CASE

PROGRAMOVÁNÍ V JAZYCE C V PŘÍKLADECH 11 Dynamické datové struktury 11.1 Spojové struktury Příklad PROG_

Racionální čísla, operátory, výrazy, knihovní funkce

Lekce 6 IMPLEMENTACE OPERAČNÍHO SYSTÉMU LINUX DO VÝUKY INFORMAČNÍCH TECHNOLOGIÍ JAZYK C

Základní datové typy, proměnné - deklarujeme předem - C je case sensitive rozlišuje malá a velká písmena v názvech proměnných a funkcí

C++ Akademie SH. 2. Prom nné, podmínky, cykly, funkce, rekurze, operátory. Michal Kvasni ka. 20. b ezna Za áte níci C++

Data, výrazy, příkazy

ALGORITMIZACE A PROGRAMOVÁNÍ

7 Formátovaný výstup, třídy, objekty, pole, chyby v programech

Odvozené a strukturované typy dat

VISUAL BASIC. Práce se soubory

Základy algoritmizace a programování

8 Třídy, objekty, metody, předávání argumentů metod

Programovací jazyk. - norma PASCAL (1974) - implementace Turbo Pascal, Borland Pascal FreePascal Object Pascal (Delphi)

- speciální symboly + - * / =., < > <> <= >= a další. Klíčová slova jsou chráněnými útvary, které nelze použít ve významu identifikátorů.

Formátová specifikace má tvar (některé sekce nemají smysl pro načítání) %

3. přednáška. Obsah: Řídící struktury sekvence, if-else, switch, for, while, do-while. Zpracování posloupnosti

Jazyk C# a platforma.net

Úvod do programovacích jazyků (Java)

Výrazy, operace, příkazy

Opakování programování

Programovací jazyk C(++) C++ area->vm_mm->locked_vm -= len >> PAGE_SHIFT;

Proměnná. Datový typ. IAJCE Cvičení č. 3. Pojmenované místo v paměti sloužící pro uložení hodnoty.

přetížení operátorů (o)

Systém je citlivý na velikost písmen CASE SENSITIVE rozeznává malá velká písmena, např. PROM=1; PROm=1; PRom=1; Prom=1; prom=1; - 5 různých proměnných

NPRG030 Programování I, 2016/17 1 / :58:13

2.1 Podmínka typu case Cykly Cyklus s podmínkou na začátku Cyklus s podmínkou na konci... 5

PROGRAMOVACÍ JAZYKY A PŘEKLADAČE REALIZACE PŘEKLADAČE I

NPRG030 Programování I, 2010/11

Programování v jazyce C pro chemiky (C2160) 4. Textové řetězce, zápis dat do souboru

- dělají se také pomocí #define - podobné (použitím) funkcím - předpřipravená jsou např. v ctype.h. - jak na vlastní makro:

Více o konstruktorech a destruktorech

Prezentace a vysvětlení programového prostředí NXC

MAXScript výukový kurz

Objektově orientované programování

Operátory, výrazy. Tomáš Pitner, upravil Marek Šabo

Zápis programu v jazyce C#

- znakové konstanty v apostrofech, např. a, +, (znak mezera) - proměnná zabírá 1 byte, obsahuje kód příslušného znaku

IUJCE 07/08 Přednáška č. 1

Úvod do programování. Lekce 5

Datové typy strana 29

Úvod do programování 7. hodina

Správné vytvoření a otevření textového souboru pro čtení a zápis představuje

Lekce 01 Úvod do algoritmizace

type Obdelnik = array [1..3, 1..4] of integer; var M: Obdelnik;

Programování v C++, 2. cvičení

6 Příkazy řízení toku

Stručný obsah První týden Druhý týden 211 Třetí týden 451 Rejstřík 787

Preprocesor. Karel Richta a kol. katedra počítačů FEL ČVUT v Praze. Karel Richta, Martin Hořeňovský, Aleš Hrabalík, 2016

Algoritmy I. Cvičení č. 2, 3 ALGI 2018/19

pi Ludolfovo číslo π = 3,14159 e Eulerovo číslo e = 2,71828 (lze spočítat jako exp(1)), např. je v Octave, v MATLABu tato konstanta e není

Stručný návod k programu Octave

Ukazka knihy z internetoveho knihkupectvi

Úvod do informatiky. Miroslav Kolařík

Transkript:

Úvodní poznámka Programovací jazyk C++ Jiří Vogel 1994 Tato skripta vznikla po odpřednášení několika jednosemestrálních doporučených kurzů: Programovací jazyk C++. Při sestavování těchto přednášek jsem vycházel hlavně z publikace [3], jejíž autoři jsou zároveň tvůrci jazyka C. Jsou to zřejmě ty výjimečné typy lidí, kteří jsou skvělými programátory a zároveň výbornými pedagogy. Takže v prakticky celé 1. a 2. kapitole jsem se nechal vést jejich vzorem. Další publikace, do kterých jsem by» jen nahlédl, jsou uvedeny v seznamu literatury. Publikace [2] a [6] pojednávají o standardu ANSI C. Publikace [1] a [3] o původní K&R verzi jazyka C, skriptum [4] popisuje jazyk ANSI C a zároveň seznamuje čtenáře s verzí K&R. Jazyka C++ se týkají knihy [5], [7] a kniha [8], která je navíc věnována hlavně objektově orientovanému programování, protože C++ je jedním z mnoha jazyků, které tento programátorský styl práce umožňují. Skripta jsem se snažil psát maximálně stručně a důraz jsem kladl na příklady, které jsou všechny odladěny (většinou jsem použil produktu firmy Borland Turbo C++), takže syntaktické chyby ani chyby v algoritmizaci (snad s výjimkou volby optimálního algoritmu a chyb, které vznikly při přenosu programů do skript) by se v nich neměly vyskytovat. V prvé kapitole jsou základní struktury jazyka C++ vysvětleny pouze na příkladech. Tuto kapitolu by si měl každý čtenář důkladně promyslet, a odzkoušet jak odladěné příklady, tak zadaná cvičení. Ve druhé kapitole jsou uvedeny podrobnosti typu: Jak se zadávají konstanty? Kolik a jakých znaků smí mít jméno nějakého objektu? Jaké jsou základní typy hodnot, jaké jsou standardní operace v jazyku atd. Ve třetí kapitole se čtenář dozví další důležité podrobnosti o jazyku C++, kterými jsem nechtěl z pedagogických důvodů zatěžovat v prvních dvou kapitolách. Čtvrtá kapitola pojednává podrobně o polích a funkcích, o kterých čtenář skript, který došel až sem, již dost ví, a o ukazatelích (jiný český termín je spoj), které byly čtenáři prakticky zamlčeny. Pátá kapitola pojednává o strukturách, třídách (i když s nejdůležitějšími vlastnostmi tříd se čtenář seznámí až v kapitole šesté), unionech a takových podrobnostech jako jsou tzv. bitová pole. Šestá kapitola je věnována objektově orientovanému programování, které je vysvětleno na různě složitých příkladech, kdy jsem se vždy snažil vycházet od jednoduchých příkladů, ale závěrem jsem se nevyhnul ani příkladům dosti složitým, aby vynikl důvod, pro který tento programátorský styl vznikl. Sedmá kapitola je věnována předpřekladači (nebo, chcete-li, preprocesoru), který usnadňuje programování jak v jazyku C, tak v jazyku C++. Závěrem bych chtěl upozornit, že ten, kdo se chce seznámit se speciálními možnostmi konkrétní implementace jazyka C++, tj. např. grafickými a matematickými knihovnami, možnostmi optimalizace programu apod., ten nech» tato skripta odloží. Ten kdo se chce obecně, ale relativně podrobně seznámit s jazykem C++, ten by snad mohl toto skriptum použít jako užitečnou pomůcku.

Závěrem bych chtěl poděkovat studentu Jiřímu Vávrovi ze Strojní fakulty ČVUT a doktorandu Ing. Luďku Šárovi z Ústavu termomechaniky AV ČR za pečlivé přečtení rukopisu a oponentu Ing. Svenu Ubikovi, systémovému programátorovi z Informačního centra FS ČVUT za cenné připomínky k úpravě textu. Autor Poznámka k ťelektronickéť podobě skript Skripta jsem přepsal do jazyka HTML, aby se studentům usnadnil přístup a zároveň aby byla demonstrována užitečnost práce s tímto tvarem informací. Dnešním dnem ruším informaci: Contents under Construction, ale za jakékoliv připomínky na své e-mailové adrese: předem děkuji vogel@marian.fsik.cvut.cz nebo vogel@fsid.cvut.cz Praha 11. července 1998 Autor

Obsah 1. Úvod do jazyka C++ 1. Vstup a výstup 2. Příkazy cyklu for a do-while 3. Několik jednoduchých programů 1. Vstup a výstup po znacích 2. Kopírování souboru 3. Počítání znaků 4. Počítání řádků 5. Počítání slov 4. Pole 5. Funkce 1. Automatické a externí proměnné 2. Rekurzívní funkce 6. Závěrečné poznámky k 1. Kapitole 7. Cvičení 2. Typy, operátory, výrazy 1. Jména, typy, konstanty 1. Jména 2. Typy 3. Konstanty 2. Operátory 1. Aritmetické operátory 2. Přiřazovací operátory 3. Podmíněný výraz 4. Relační a logické operátory 3. Typová konverze 1. Priority operací 3. Podrobnosti k předchozím kapitolám 1. Příkazy a bloky 2. Operátor :: 3. Operátor čárka 4. Příkaz break 5. Příkaz continue 6. Registrové proměnné 7. Cvičení 4. Ukazatelé, pole, funkce

1. Ukazatelé a adresy 1. Ukazatelé a argumenty funkcí 2. Ukazatelé a pole 3. Ukazatelé a konstanty 4. Argumenty povelového řádku 5. Inicializace polí a polí ukazatelů 6. Ukazatelé a vícerozměrná pole 7. Ještě několik podrobností o funkcích 1. Vnitřní funkce 2. Dosazené parametry 3. Přetížené funkce 4. Funkce s nespecifikovaným počtem parametrů 8. Cvičení 5. Struktury, třídy, uniony, bitová pole 1. Struktury a třídy 1. Pole struktur 2. Typ union 1. Anonymní typ union 3. Příklady dynamických objektů 4. Bitová pole 5. Cvičení 6. Základy objektově orientovaného programování 1. Úvod 2. Příklady objektově orientovaného programování v C++ 3. Spřátelené funkce a třídy 4. Přetížené operátory 5. Závěrečná poznámka k OOP 6. Cvičení 7. Poznámky k předpřekladači Literatura 1. Direktiva #define 1. Direktiva #define bez parametrů 2. Direktiva #define s parametry 2. Operátory # a ## 3. Podmíněný překlad

Kapitola 1 Úvod do jazyka C++ V této kapitole se seznámíme s podstatnými prvky jazyka, aniž bychom zabíhali do podrobností. Jazyk budeme vykládat na příkladech. Tento způsob výkladu má svá úskalí, zejména pokud se jedná o přesnosti popisu jazyka, ale jediným způsobem jak se naučit programovací jazyk, je programovat, a proto zvolíme tuto strategii. Budeme postupovat tak, že nejprve zadáme úlohu, napíšeme program v jazyku C++ a program si vysvětlíme. 1. Vstup a výstup Příklad 1.1. Sestavme program, který vytiskne text Vítejte v kurzu jazyka C++ Řešení: 1. varianta: 2. #include <iostream.h> 3. main() 4. 5. cout << ťvitejte v kurzu jazyka C++ť << '\n'; 6. Vlastní program začíná slovem main(), které v tomto případě dává kompilátoru jazyka informaci, že se jedná o tzv. hlavní program. Program v jazyku C++ může sestávat z jednotlivých programových jednotek, kterým říkáme funkce. Každá funkce, může mít argumenty uvedené v okrouhlých závorkách za jménem funkce. Protože hlavní program je považován také za funkci, jsou za jménem main okrouhlé závorky. Později uvidíme, že i hlavní program smí mít argumenty. Složené závorky označují začátek a konec hlavního programu a příkaz cout je tzv. proudová funkce pro výstup. Zajistí (s pomocí operátorů proudového výstupu <<) výstup řetězce znaků, které jsou zapsány mezi uvozovkami a znaku \n, který je zapsán mezi apostrofy. Tento znak znamená přechod na nový řádek. Každý příkaz v jazyku C++ končí středníkem. Přesvědčte se, že lze též napsat: cout << ťvitejte v kurzu jazyka C++ \nť; První řádek programu je příkazem pro tzv. předpřekladač, který před překladem programu v tomto případě zajistí, aby byl zahrnut (anglický termín include) tzv. hlavičkový soubor iostream.h, který v jazyku C++ (obvykle) umožňuje proudové funkce pro vstup a výstup používat. 7. varianta: 8. #include <stdio.h> 9. main() 10. 11. printf(ťvitejte v kurzu jazyka C++\nť); 12.

Tento program využívá hlavičkového souboru stdio.h (standardní input/output), který se používá i v jazyku C a jednu jeho funkci pro výstup ( printf) na standardní výstupní zařízení. Příklad 1.2. Zapišme tentýž text jako v příkladu do souboru, který např. pojmenujeme out.dat. Řešení: 1. varianta: 2. #include<fstream.h> 3. main() // Zapis do souboru out.dat 4. 5. // Nejprve otevřeni souboru out.dat pro zápis 6. ofstream fout(ťout.datť); 7. // a vlastni zápis 8. cout << ťvitejte v kurzu jazyka C++\nť; 9. // Uzavřeni souboru 10. cout.close(); 11. První řádek informuje předpřekladač, že má zavést soubor fstream.h, který umožňuje (obvykle) definovat libovolně pojmenované proudové funkce. V našem případě cout. Text za znaky // je v jazyku C++ považován až do konce řádku za poznámku. Je vhodné nestandardní soubory uzavřít (i když v tomto případě po ukončení programu se uzavře automaticky). Chceme-li soubor z nějakého důvodu uzavřít před ukončením programu, je tento příkaz povinný. 12. varianta: 13. #include <stdio.h> 14. main() 15. /* Tentýž přiklad prostředky, které jsou obvykle v jazyku C i C++ 16. */ 17. 18. /* Definice ukazatele typu FILE*/ 19. FILE *fp; 20. /* Otevření souboru out.dat pro zápis*/ 21. fp=fopen(ťout.datť,ťwť); 22. /* Zapis do souboru funkci fprint 23. ze souboru stdio.h*/ 24. fprint(fp,ťvitejte v kurzu jazyka C++\nť); 25. /* Uzavrení souboru*/ 26. fclose(fp); 27. V této variantě zápisu jsme použili poznámek uzavřených mezi znaky /* a */. Oba typy poznámek jsou v C++ použitelné a mohou se libovolně střídat. Je vhodné jednořádkové poznámky uvozovat znaky // a víceřádkové poznámky mezi znaky /* a */. Ukazatel zmíněný v poznámce budeme probírat podrobně v kapitole 4. Důležité upozornění: jazyk C i C++ rozlišují mezi malými a velkými písmeny: tedy FILE, File a file jsou tři různá jména.

Příklad 1.3. Sestavme program pro přečtení dvou hodnot ze standardního vstupního zařízení a jejich přiřazení proměnným x a i. Řešení: 1. varianta: 2. #include <iostream.h> 3. main() 4. 5. float x; // Definice reálné promenne x 6. int i; // Definice celočíselné proměnné i 7. 8. cout << ťcti x, i\nť; 9. // Čteni hodnoty a x a i (zleva doprava) 10. cin >> x >> i; 11. // Tisk hodnoty proměnné x a i (zleva doprava) 12. cout << ť\nx = ť << x << ť i = ť << i << '\n'; 13. Tento zápis je dostatečně jasný z poznámek. 14. varianta: 15. #include <stdio.h> 16. main() 17. 18. float x;int i; 19. 20. printf(ťcti x, i\nť); 21. // Čtení hodnoty x a i 22. scanf(ť%f %dť,&x,&i); 23. // Tisk hodnoty x a i 24. printf(ťx = %f i = %d \nť,x,i); 25. Zde je nová funkce scanf, která zajišťuje vstup hodnot, zdánlivě složitějším způsobem než cin. Právě tak jako funkce printf využívá tzv. formátu. Zde konverze f zajistí vstup reálné hodnoty a konverze i zajistí vstup celočíselné hodnoty. U proměnných x a i je povinný symbol &. Pamatujme si prozatím, že tento znak ve funkci scanf musí být u jednoduchých proměnných a indexovaných proměnných. Vysvětlení bude možné, až se naučíme pracovat s ukazateli. Příklad 1.4. Sestavme program pro přepočet palců na centimetry a obráceně. Budeme číst číselnou hodnotu a znak: p (převod palců na centimetry), c (převod centimetrů na palce). V případě chybného zadání znaku se vytiskne výstražná zpráva. Řešení: // Prepocet palcu na centimetry a obracene #include <iostream.h> main()

typedef float real; /*Definice noveho typu (zde v C++ jsme standardní float zamenili nestandardnim, ale v jinych jazycich obvyklym slovnim symbolem real*/ const real PREPOCET=2.54; // Definice konstanty real x,palec,cm; char ch=0; //Definice promenne typu char s pocatecnim prirazenim cout << ť\ncti délku a co je zadano: p -- palce c -- cm\nť; cin >> x >> ch; if(ch=='p') // Prepocet palcu na cm palec=x;cm=prepocet*x; else if(ch=='c') // Prepocet centimetru cm=x;palec=x/prepocet; if(ch=='p' ch=='c') cout << palec << ť\ť = ť << cm << ťcm\nť; else cout << ť\n Chybne zadani!!!\nť; V programu jsme použili definici nového typu, počáteční přiřazení (které se okamžitě realizuje při překladu zdrojového programu), definici symbolické konstanty (na rozdíl od proměnné se symbolické konstantě nesmí v průběhu plnění přiřadit nová hodnota), přiřazovacího příkazu (kdy v nejjednodušším případě se proměnné na levé straně přiřadí hodnota výrazu na straně pravé) a podmíněného příkazu: if (pravda) příkaz; else jiný_příkaz; Je-li hodnota pravda různá od nuly, provede se příkaz, je-li rovna nule provede se jiný_příkaz. Příkaz i jiný_příkaz musí končit středníkem a příkaz i jiný_příkaz může být jeden příkaz, nebo více příkazů - tzv. složený příkaz - uzavřených do složených závorek. (Ty v jazyku C a C++ nahrazují slovní symboly begin a end známé z jiných programovacích jazyků.) V podmínce if(ch=='p' ch=='c') se zjiš»uje, je-li ch rovno () znaku p, nebo ( disjunkce nebo-li logický součet v jazyku C i C++) je-li rovno znaku c. Pozor na operátor rovná se () a operátor přiřaď () začátečníkům (a nejenom jim) se někdy pletou. Je-li větev za else prázdná, může se vynechat (včetně slovního symbolu else). V příkazu cout << palec << ť\ť =ť << cm << ťcm\nť; jsme potřebovali zapsat v řetězci znak uvozovka ( ť). To jazyk C a C++ umožní předřazením znaku zpětné lomítko (\) před znak uvozovka. Příklad 1.5. Sestavme program pro tutéž úlohu, ale použijme tzv. přepínače. Řešení: // Piseme jen vlastni algoritmus bez deklaraci, ktere se nemeni //... switch(ch) case 'p': palec=x;

cm=prepocet*x; cout << palec << ť\ť = ť << cm << ťcm\nť; break; case 'c': cm=x; palec=x/prepocet; cout << palec << ť\ť = ť << cm << ťcm\nť; break; default: cout << ť\n Chybne zadani!!!\nť; break; //... Přepínač pracuje tak, že se procházejí jednotlivé alternativy case a nalezne-li se shoda mezi výrazem za slovním symbolem switch a výrazem za case, provedou se příkazy za tímto case. Pak by se prováděly další příkazy bez ohledu na další case; abychom tomuto nežádoucímu jevu zabránili, musíme na konci každé alternativy přepínače umístit příkaz break, který přepínač ukončí. Alternativa uvedená slovním symbolem default se provede v případě, že nevyhovuje žádná jiná alternativa. Alternativa default je nepovinná a příkaz break je v ní zbytečný, ale je zvykem jej na toto místo psát.. Příklad 1.6. Sestavme program pro přepočet palců na centimetry a obráceně. Budeme číst číselnou hodnotu a znak ( p - převod palců na centimetry, c - převod centimetrů na palce, k - konec čtení) a budeme je postupně zapisovat do souboru muj_s.dat. V případě, že čteme chybný znak, program bude požadovat opravu. Po přečtení hodnot soubor uzavřeme pro zápis, otevřeme pro čtení, budeme z něj číst a výsledky tisknout na standardním výstupním zařízení. Řešení: // Vstup a vystup do souboru v C++ /* Program ocekava vstup do promenne ch a x, zapise vysledky do souboru muj_s.dat, ktery predtim otevre. Po ukonceni zapisu (predpoklad cte se pismeno k a x je libovolne) se soubor zavre pro vystup a otevre pro vstup. Vypoctene hodnoty se prectou a vypisi na obrazovce. Prepocitavaji se palce na cm a obracene */ #include <fstream.h> #include <iomanip.h> main() const float prepocet=2.54; float x=1,palec,cm; char ch=0; // Vstup a zapis do souboru muj_s.dat ofstream fout(ťmuj_s.datť); while(1) ZNOVA: cout << ť\nzadejte, prosim, co se ma provadet:\nť << ťp - zadana hodnota v palcich\nť << ťc - zadana hodnota v cm\nť << ťk - konec vypoctu\nť << ť zadana hodnota\nť; cin >> ch >> x; switch (ch)

case 'p': palec=x; cm=x*prepocet; break; case 'c': cm=x; palec=x/prepocet; break; case 'k': goto KONEC; default: cout << ť\n Chybny udaj zadava se c, p nebo k. Opakujte cteni\nť; x=0; ch='\0'; goto ZNOVA; // Zapis do souboru fout << palec << '\n'; fout << cm << '\n'; // Uzavreni souboru muj_s.dat pro zapis KONEC: fout.close(); // Ctou se data ze souboru muj_s.dat cout << ť\n A nyni hodnoty: palec, cm vytisknu\nť; ifstream fin(ťmuj_s.datť); while(!fin.eof()) //! je negace logickeho vyrazu fin >> palec; if(!fin.eof()) fin >> cm; cout << setw(6) << setprecision(2) << palec << ť\ť = ť << cm << ť cm\nť; // Uzavreni souboru muj_s.dat fin.close(); cout << ťkonec programu.\nť; U příkazu cout jsme použili tzv. manipulátorů (v systému, kde byly laděny programy pro tato skripta, jsou manipulátory definovány v souboru iomanip.h. Např. manipulátor setw(6) použitý v cout nastaví šířku slova na výstupu na hodnotu 6. Manipulátor setprecision(2) nastaví přesnost pro reálné hodnoty na 2 desetinná místa. Hlavičkový soubor iostream.h je součástí souboru fstream.h, takže nemusí být uveden. V programu jsme použili cyklus while. Jeho význam je jednoduchý. Příkaz uvedený za příkazem (eventuálně příkazy uzavřené v příkazových závorkách) while se provádí tak dlouho, dokud je výraz v závorkách za slovem while různý od nuly. V našem případě jsme použili tedy nekonečný cyklus a k ukončení jsme použili příkaz skoku a návěští, které se odděluje od příkazu, ke kterému se má provést skok, dvojtečkou. Je dobrou praxí, používat příkazů skoku co nejméně, protože někdy znepřehledňují program. V našem případě je tento příkaz vhodný v místě, kde kontrolujeme správnost vstupu. V druhém případě, kdy pomocí tohoto příkazu ukončujeme program, je lepší využít příkazu while.

Příklad 1.7. Sestavme program pro tisk tabulky Fahrenheit - Celsius. Pro přepočet použijte vzorce 5 C = (F-32) 9. Tabulku tiskněme ve tvaru: Stupne Fahrenheita Stupne Celsia dddd ddd.dd dddd ddd.dd...... kde d je číslice, znaménko minus nebo prázdný znak. Řešení: /*Tisk tabulky prevodu teplot ze stupnu Fahrenheit na stupne Celsius pro fahr = 0, 20,..., 300 */ #include<iostream.h> #include<iomanip.h> main() // Definice konstant pro dolni a horni mez a krok zmeny const int DOLNI=0,HORNI=300,KROK=20; float fahr=dolni; // Definice promenne fahr s pocatecnim prirazenim; float cels; /* Definice promenne, ktera bude nabyvat hodnot stupnu Celsia */ // Tisk zahlavi tabulky cout << ť Stupne Fahrenheita Stupne Celsia\nť; /*Prikaz while, ktery se bude provadet dokud fahr bude mensi nebo rovno 300*/ while(fahr<=horni) cels=5./9.*(fahr-32); cout << ť ť << setw(4) << fahr << ť ť << setw(5) << setprecision(2) << cels << '\n'; fahr=fahr+krok; Program je snad opět z poznámek srozumitelný. V příkazu while se provádí více příkazů, a proto jsou uzavřeny do složených (příkazových) závorek. Je nutno upozornit na zlomek 5 / 9, který jsme zapsali v přiřazovacím příkazu 5./9. a mohli jsme ho zapsat i ve tvarech: 5.0/9.0 nebo 5./9 popř. 5/9. apod. Nesmíme jej však zapsat ve tvaru: 5/9 To je v jazyku C i C++ tzv. celočíselné dělení. Výsledkem 5/9 je celočíselný výsledek dělení (po odříznutí zlomkové části) a to je nula. Právě tak výsledek dělení 3/2 je hodnota 1, výsledkem 11/5 je hodnota 2 atd. Fortranisté jsou na tuto skutečnost zvyklí a vědí, že se celočíselné dělení dá v mnoha případech s výhodou použít, ale v mnoha úlohách může být jeho přehlédnutí zdrojem těžko objevitelných chyb.

Na tomto místě znovu opakujeme, že v jazycích C++ a C je pravdivostní hodnota pravda realizována hodnotou různou od nuly a hodnota nepravda hodnotou nula. Hodnoty true a false známé z jiných programovacích jazyků tedy v C++ i C explicitně neexistují. 2. Příkazy cyklu for a do-while Příkazy cyklu jsou velmi důležitou a naštěstí nijak komplikovanou částí každého programovacího jazyka. V minulém odstavci jsme již probrali příkaz while a nyní se zmíníme o příkazu for. Význam ukážeme opět na příkladu. Příklad 1.7 naprogramujeme pomocí tohoto příkazu. /*Tisk tabulky prevodu teplot ze stupnu Fahrenheit na stupne Celsius pro fahr = 0, 20,..., 300 */ #include<iostream.h> #include<iomanip.h> main() // Definice konstant pro dolni a horni mez a krok zmeny const int DOLNI=0,HORNI=300,KROK=20; // Tisk zahlavi tabulky cout << ť Stupne Fahrenheita Stupne Celsia\nť; // Prikaz for for(int fahr=dolni;fahr<=horni;fahr=fahr+krok) cout << ť ť << setw(4) << fahr << ť ť << setw(6) << setprecision(2) << 5./9.*(fahr-32) << '\n'; Význam příkazu for lze popsat pomocí příkazu while následovně: //... fahr=dolni; while(fahr<=horni) cout...; fahr=fahr+krok; //... V příkazu jsme využili možnosti definice typu parametru cyklu přímo v příkazu for; to je v jazyku C++ možné. Definice proměnné pak platí až do konce funkce nebo bloku ve funkci (podrobněji v kap. 3 v čl. 3.1 a 3.2). Samozřejmě, že jsme mohli psát //... int fahr; //... for(fahr=dolni;fahr<=horni;fahr=fahr+krok)//... ale i //... int fahr=dolni; //... for(;fahr<=horni;fahr=fahr+krok)

Z ukázek je vidět, že v příkazu for lze jednotlivé složky příkazu vynechávat, podle toho, jak se nám hodí. Dalším příkazem cyklu v jazyku C++ je cyklus do-while. Syntaxe příkazu je do příkaz while(výraz) Nejprve se provede příkaz a pak se vyhodnotí výraz. Je-li pravdivý (tedy přesně řečeno různý od nuly) příkaz se provede znovu atd. Je-li nepravdivý (roven nule), cyklus se ukončí. Program z příkladu 1.7 můžeme pomocí příkazu do-while napsat takto (Je samozřejmé, že příkaz může být složený): /*Tisk tabulky prevodu teplot ze stupnu Fahrenheit na stupne Celsius pro fahr = 0, 20,..., 300 */ #include<iostream.h> #include<iomanip.h> main() // Definice konstant pro dolni a horni mez a krok zmeny const int DOLNI=0,HORNI=300,KROK=20; int fahr=dolni; //Definice promenne fahr s pocatecnim prirazenim // Tisk zahlavi tabulky cout << ť Stupne Fahrenheita Stupne Celsia\nť; // Prikaz do-while do cout << ť ť << setw(4) << fahr << ť ť << setw(6) << setprecision(2) << 5./9.*(fahr-32) << '\n'; fahr=fahr+krok; while(fahr<=horni); V příkazu do-while se provede příkaz alespoň jednou, protože tzv. zkouška konce se provádí po provedení příkazu. 3. Několik jednoduchých programů V této části si ukážeme několik jednoduchých programů pro práci se znaky. 3.1 Vstup a výstup po znacích V knihovnách jazyka C++ existují funkce, které po vyvolání přečtou nebo zapíší jeden znak. Uveďme některé: Funkce getchar() přečte při vyvolání vstupní znak z klávesnice a vrátí jej jako svoji hodnotu. Tedy po provedení příkazu c=getchar() se proměnné c přiřadí znak ze vstupu.

Funkce putchar(c) zapíše hodnotu c na obrazovku. Příkaz getc(fp) čte znak ze souboru fp, tedy c=getc(fp) přiřadí proměnné c znak ze souboru fp. Příkaz putc(c,fp) zapíše hodnotu c do souboru fp. Řekli jsme si, že funkce getchar čte z klávesnice (přesněji ze standardního vstupu) a putchar vypisuje znakové hodnoty na obrazovku (přesněji na standardní výstup). To ovšem můžeme snadno v moderních operačních systémech změnit tzv. přesměrováním, kdy vyvoláním pracovního programu, který se např. jmenuje mujprog, ve tvaru mujprog < mujvst > mujvys zajistíme, že standardním vstupem pro něj bude soubor mujvst a výstupem mujvys. Totéž samozřejmě docílíme, budeme-li ve zdrojovém programu mujprog.cpp psát příkazy getc(mujvst) a putc(nějaká znaková veličina, mujvys). 3.2 Kopírování souboru Příklad 1.8. Napišme program který znak po znaku kopíruje vstup na výstup. Řešení: 1. varianta: 2. #include<stdio.h> 3. /* Kopie ze standardniho vstupniho souboru na standardni vystupni 4. soubor*/ 5. main() 6. 7. int c; 8. c=getchar(); 9. while(c!=eof) 10. 11. putchar(c); 12. c=getchar(); 13. 14. Relační operátor!= má význam. Cyklus while tedy probíhá, dokud se nepřečte znak konec souboru, pak se cyklus ukončí. Znak konec souboru pro konkrétní systém je uložen v souboru stdio.h. Je označen jménem EOF. Funkce getchar vrací celočíselnou hodnotu, a proto i proměnnou c jsme definovali jako celočíselnou ( typ int) a ne typu char. Je to stručně řečeno proto, že některé znaky nejsou typu char (např. znak konce souboru EOF). 15. varianta: Programátor v jazyku C nebo C++ ovšem napíše program stručněji: #include <stdio.h> main() // Kopirovani vstupu na vystup strucneji

int c; while((c=getchar())!=eof) putchar(c); Program nejprve v příkazu while přiřadí proměnné c hodnotu a pak se testuje, je-li tato hodnota různá od EOF. Je-li různá, provede se příkaz putchar, není-li různá, cyklus a program se ukončí. Protože operátor přiřazení (=) má nižší prioritu než operátor (!=), musí být přiřazovací příkaz uzávorkován. V jazyku C a C++ je mnoho možností, jak psát stručné programy. Necháme-li se však touto vlastností, může se nám stát, že budeme psát zcela nesrozumitelné programy, kterým, po čase, nebudeme rozumět ani my sami. 3.3 Počítání znaků Příklad 1.9. Napišme program, který spočítá znaky ve vstupním textu. Řešení: #include<stdio.h> main()// Pocitani znaku ve vstupnim textu long nc=0; while(getchar()!=eof) ++nc; printf(ťpocet znaku ve vstupnim textu = %ld\nť,nc); V programu se objevil nový operátor ++, který znamená zvětšení o jednotku. Je možné psát nc=nc+1, ale ++nc je stručnější a mnohdy efektivnější. Operátory inkrementace mohou být prefixové ++nc nebo postfixové nc++.rozdíl si vysvětlíme později. Vedle operátorů inkrementace máme i operátory dekrementace -, které se obdobně využívají při odečítání jedničky. V programu jsem využili nového typu long, který je stručnějším zápisem long int; u typu long je zaručeno, že že maximální hodnota tohoto typu nebude menší než maximální hodnota typu int. Konverze v printf a scanf pro tento typ je %ld.

3.4 Počítání řádků Příklad 1.10. Sestavme program, který spočítá řádky zapsané v souboru muj_sou. Předpokládáme, že každý řádek je ukončený znakem nový řádek ( \n ). Řešení: #include <stdio.h> main() // Pocitani radku int zn,nr=0; // zn - cteny znak, nr - pocet radku FILE *ms; // Definice ukazatele typu FILE ms=fopen(ťmuj_souť,ťrť); // Otevreni souboru while((zn=getc(ms))!=eof) if(zn=='\n') ++nr; printf(ťpocet radku= %d\nť,nr); fclose(ms); /* Zavreni souboru. V tomto pripade nepovinne. Po ukonceni programu se vsechny otevrene soubory automaticky uzavrou */ 3.5 Počítání slov Příklad 1.11. Sestavme program, který spočítá slova, řádky a znaky zapsané v souboru msbr. Předpokládáme, že slovo je posloupnost znaků, která neobsahuje znaky mezera, tabelátor (\t), nebo nový řádek (\n). Řešení: #include<stdio.h> main() // Pocitani slov, radek a znaku v souboru msbr typedef int BOOL; FILE *sb=fopen(ťmsbrť,ťrť); // Otevreni souboru msbr const BOOL ANO=1,NE=0; // Definice logickych konstant int zn,nz,nr,ns; /* zn - cteny znak, nz - pocet znaku, nr - pocet radku, ns - pocet slov */ BOOL ve_slove; /* ve_slove je logicka (Booleovska) promenna, nabyvajici logickych hodnot ANO a NE */ ve_slove=ne; // A priorni predpoklad: nejsem uvnitr slova; nz=nr=ns=0; // Vynulovani hodnot promennych while((zn=getc(sb))!=eof) ++nz; // Opakovani: ++nz je totozne s nz=nz+1; if(zn=='\n')++nr; if(zn==' ' zn=='\t' zn=='\n') ve_slove=ne; else if(ve_slove==ne) ve_slove=ano; ++ns; printf(ť\nv souboru je:\n \n pocet znaku = %d,\n pocet radku = %d,\nť, ť pocet slov = %d\nť,nz,nr,ns);

Čtenář při troše přemýšlení jistě porozumí popsanému algoritmu. Všimněme si snad jen pro úplnost zřetězeného příkazu nz = nr = ns = 0; který se realizuje takto nz = (nr = (ns = 0)); a pro zopakování toho, že v jazycích C a C++ neexistují tzv. logické (Booleovské) proměnné: chceme-li je explicitně použít, musíme to realizovat např. tak, jako v tomto programu. 4. Pole Příklad 1.12. Sestavme program, který spočítá výskyty jednotlivých číslic, mezer, tabelátorů, nových řádek a ostatních znaků. Řešení: #include<stdio.h> #include<conio.h>// Soubor pro ovládání obrazovky v systému TURBO C++ main() // Pocitani cislic a ostatnich znaku int cis[10],bily_zn=0,ost_zn=0,zn; FILE *ms; ms=fopen(ťvzorek.datť,ťrť); clrscr(); // Mazani obrazovky v systému TURBO C++ for(int i=0;i<10;++i) cis[i]=0; // Nulovani prvku pole // A vlastni realizace algoritmu while((zn=getc(ms))!=eof) /* Je-li zn >= '0'a zaroven jeli zn <= '9' (operator &&), vypocte se hodnota indexu: c - '0' a k prislusnemu prvku se pricte jednicka */ if(zn>='0' && zn<='9') ++cis[zn-'0']; else if(zn==' ' zn=='\t' zn=='\n') ++bily_zn; else ++ost_zn; // Tisk vysledku printf(ť\ncislice Pocet cislic\n\nť); for(i=0;i<10;++i) printf(ť %d %d\nť,i, cis[i]); printf(ť\n\npocet: bilych znaku: %d a ostatnich %dť,bily_zn, ost_zn); V programu je použito jednorozměrné pole tj. vektor cis, jež má deset prvků o indexech měnících se od nuly do devíti. Typické pro pole v jazyku C i C++ je právě indexování od nuly. Mez udaná v definici tedy znamená pocet prvků pole a ne horní mez indexu. To umožňuje v cyklu for psát ostrou nerovnost. V programu jsme použili nový hlavičkový soubor conio.h, který v systému, ve kterém byly programy laděny slouží k ovládání obrazovky; např. funkce clrscr() maže obrazovku.

Příklad 1.13. Sestavme program, který vypočítá součet matic typu (m,n), kde m 5 a n 5 podle vzorce c ij = a ij +b ij, i = 1,2,...m; j = 1,2,...,n. Matice budeme číst ze souboru vzorek.dat a výsledek bude zapsán do téhož souboru. Řešení: #include<stdio.h> main() FILE *vz=fopen(ťvzorek.datť,ťrť); //Otevreni souboru pro cteni const int m=5,n=5; int a[m][n],b[m][n],c[m][n];// Definice matic typu(m,n) int ms,ns; // Definice skutecneho poctu radku (ms) a sloupcu (ns) fscanf(vz,ť %d %dť,&ms,&ns); // Cteni hodnot ms, ns for(int i=0;i<ms;++i) // Cyklus i s definici parametru cyklu i for(int j=0;j<ns;++j) // Cyklus j s definici parametru cyklu j fscanf(vz,ť%d ť,&a[i][j]); // Cteni prvku matice A; for(i=0;i<ms;++i) for(j=0;j<ns;++j) fscanf(vz,ť%d ť,&b[i][j]); // Cteni prvku matice B for(i=0;i<ms;++i) for(j=0;j<ns;++j) c[i][j]=a[i][j]+b[i][j]; // Vypocet souctu (matice C) fclose(vz); vz=fopen(ťvzorek.datť,ťwť); fprintf(vz,ťtisk souctu matic: C = A + B\n\nMatice A:ť ť\n=========\nť); for(i=0;i<ms;++i) // Tisk matice A fprintf(vz,ť\nť); for(j=0;j<ns;++j) fprintf(vz,ť%d ť,a[i][j]); // Konec Tisku matice A fprintf(vz,ť\n\nmatice B:\n=========\nť); for(i=0;i<ms;++i) // Tisk matice B fprintf(vz,ť\nť); for(j=0;j<ns;++j) fprintf(vz,ť%d ť,b[i][j]); // Konec tisku matice B fprintf(vz,ť\n\nmatice C:\n=========\nť); for(i=0;i<ms;++i) // Tisk matice C fprintf(vz,ť\nť); for(j=0;j<ns;++j) fprintf(vz,ť%d ť,c[i][j]); // Konec tisku matice C Program doplněný poznámkami je snad dostatečně čitelný. Upozorňujeme jen na zápis dvojrozměrných polí, tj. matic, který je oproti většině programovacích jazyků poněkud atypický, ale později uvidíme, že má své výhody. Též je nutno dát pozor na meze indexů. Parametry cyklů i a j jsme definovali při prvém použití způsobem povoleným v C++; standardní způsob zápisu je samozřejmě přípustný.

5. Funkce Funkce v jazyku C i C++ tvoří samostatné programové jednotky, pravě tak jako v jazyku Fortran. Příklad 1.14. Zapišme funkci, která umo'ní celočíselné umocňování celočíselné hodnoty. Umocňování není standardní operací jazyka a bývá součástí matematické knihovny příslušných systémů. Obvykle se jmenuje pow. Řešení: #include<stdio.h> main() //Testovani funkce umocneni int umoc(int,int); /* Toto je tzv. prototyp, ktery je v C++ povinny nepredchazi-li nahodou popis funkce jednotce, ve ktere je pouzivana. V prototypu je receno, jakeho je funkce typu a kolik a jakeho typu jsou parametry. */ for(int i=0;i<=10;++i) printf(ť%d na %d = %d\nť,2,i,umoc(2,i)); int umoc(int m,int n) // Funkce umocnovani m na n int p=1; //Pocatecni prirazeni hodnoty pomocne (!!!) promenne p for(int i=1;i<=n;++i)p=p*m; //Primitivni zpusob vypoctu mocniny return p; // Vraceni hodnoty funkce (mozny je i zapis return(p)) Funkci nebo skupinu funkcí lze překládat samostatně a propojení závisí na konkrétním systému. Program z příkladu 1.14 jsme zapsali jako jeden soubor. Pracujeme-li v operačním systému UNIX a jmenuje-li se soubor ukazka.cc, lze obvykle přelo'it program příkazem c++ ukazka.cc -o uk kdy pracovní (spustitelný) program se bude jmenovat uk. Budeme-li program z příkladu 1.14 psát jako dva soubory - hlavni.cc a funkce.cc, pak budeme postupovat např. takto c++ -c hlavni.cc funkce.cc Příkaz zajistí překlad souborů do sestavitelných modulů (majících v unixu postfixovou koncovku o a příkazem c++ hlavni.o funkce.o -o uk se realizuje sestavení obou modulů do spustitelné verze uk. Kombinací je samozřejmě mnoho, ale práce se soubory a funkcemi je přehledná a praktická. Překlad a sestavení mů'eme však provést najednou zápisem c++ hlavni.cc funkce.cc -o uk

Napíšeme-li jen c++ program.cc funkce.cc bude mít výsledný produkt standardní jméno a.out. V produktech firmy Borland je první případ (překlad souboru ukazka.cpp - koncovka cpp povinná) jasný z menu borlandského prostředí. Druhý případ se realizuje v okně project takto: otevřeme project např. pod názvem uk.prj (postfixová koncovka prj), ulo'íme do něj (viz menu) soubory hlavni.cpp a funkce.cpp, otevřeme compile a přelo'íme (menu make). Parametry funkce, tzv. formální parametry, které stojí na místě jednoduché proměnné nebo indexované proměnné (prvku pole), jsou, není-li řečeno jinak,(viz) volány hodnotou; to znamená, 'e se jim po zavolání funkce přiřadí hodnota skutečných parametrů. Hodnota formálních parametrů se uvnitř funkce mů'e jakkoliv měnit, ale hodnota skutečných parametrů zůstane po ukončení funkce nezměněna. Ve funkci mocnina jsme toho vyu'ili a ušetřili jsme jednu proměnnou. // Vyuziti vlastnosti volani hodnotou float mocnina (float x,int n) for (float p=1;n>0;n--) /* parametr n se meni, ale jemu odpovidajici skutecny parametr zůstane beze změny */ p=p*x; return p; Funkce v tomto případě vrací reálnou hodnotu, a proto jsme ji museli definovat jako reálnou (float). Příklad 1.15. Sestavme program pro čtení řádků znakového souboru a tisku nejdelšího z nich. Řešení: Algoritmus mů'eme stručně slovně popsat takto: pokud (existuje další řádek) Jestli'e (je delší ne' poslední nejdelší ) ulo' řádek a jeho délku; Tiskni nejdelší řádek; /* hrad.cpp - Cteni radku ze souboru ms a tisk nejdelsiho z nich. Program testuje soubor funkci frad.cpp */ #include <stdio.h>; int getline(char[],int); /* Prototyp funkce getline. Informace v nem obsazena rika, ze funkce vraci hodnotu typu int a ma dva parametry: jeden parametr je vektor - do nej se ukladaji znaky cteneho radku, druhy parametr je celociselna hodnota urcujici

maximalni pripustnou delku retezce. Funkce mohla byt tez zapsana: getline(char[],int); protoze v takovem pripade se automaticky rozumi, ze funkce vraci hodnotu typu int. Jsme-li priznivci uplne informace, lze vsak maximalisticky psat int getline(char s[],int m_del_r) */ void copy(char s1[],char s2[]); /* Prototyp funkce copy. Funkce kopiruje hodnoty prvku vektoru s1 do prislusnych prvku vektoru s2. Mohli jsme tez psat void copy(chr[],char[]).slovni symbol void sdeluje kompilatoru, ze se jedna o funkci, ktera nevraci hodnotu. V jinych programovacich jazycich se takove programove jednotce rika podprogram nebo vlastni procedura. Slovni symbol je povinny, nenapiseme-li ho, jsme kompilatorem varovani, ze funkce ma vratit hodnotu typu int a nevraci nic */ FILE *ms; /* Definice tzv. externi promenne, ktera se uziva v ruznych funkcich jednoho nebo vice programovych souboru */ main() const int MAXDEL=100;// Maximalni delka radku int delka, // bezneho radku max; // delka nejdelsiho radku char radek[maxdel], // bezny radek mradek[maxdel]; // nejdelsi radek; ms=fopen(ťmsť,ťrť); // otevreni souboru ms pro cteni a zapis max=0; while ((delka=getline(radek,maxdel))>0) /* getline vraci delku radku a vektoru radek priradi retezec znaku radku */ if(delka>max) // Je-li cteni radek zatim nejdelsi z ctenych, pak max=delka; copy(radek,mradek); // Zapis radek do mradek fclose(ms); // Uzavreni souboru pro cteni ms=fopen(ťmsť,ťwť); // Otevreni souboru pro zapis if(max>0) //Cetlo se vubec neco? // Tisk radku do souboru ms fprintf(ms,ťradek %s\nje nejdelsi a ma delku %d\nť,mradek,max); // Soubor frad.cpp #include<stdio.h>; int i; // Externi promenna, ktera se smi uzivat v celem souboru frad.cpp getline(char s[],int lim) // Cteni radku s maximalni delkou lim extern FILE *ms; /* Deklarace (ne definice) externi promenne definovane v souboru hrad.cpp (viz pozn. na konci odst. 1.5.1) */ char c; /* V prikazu for je uzita operace konjunkce (tzv. logickeho soucinu) znama z vyrokove logiky. (V C++ se znaci &&) */ for(i=0;i<lim-1&&(c=getc(ms))!=eof&&c!='\n';i++) s[i]=c; if(c=='\n') s[i]='\n'; ++i; s[i]='\0'; //Oznaceni konce retezce v C++ return i; void copy(char s1[],char s2[]) // Kopirovani s1 do s2

i=0; while((s2[i]=s1[i])!='\0') i++; Poznámky: Pro úsporu místa bylo snahou vše vysvětlit poznámkami přímo v programu. Zde jen tři vysvětlení: Řetězec znaků je v jazyku C a C++ automaticky doplňován znakem '\0'. To znamená, 'e napíšeme-li text ťnazdarť kompilátor jej automaticky rozšíří takto: Nazdar\0V případě, 'e vytváříme řetězec sami, nesmíme zapomenout znak '\0'. doplnit. Zde také je nutno upozornit na rozdíl mezi zápisem 'x' a ťxť; 'x' je znak, kde'to ťxť je řetězec o dvou znacích. Sestává ze znaku x a tzv. prázdného znaku \0. Není-li u identifikátoru funkce napsán explicitně typ funkce, předpokládá se, 'e funkce je typu int, tedy 'e vrací hodnotu typu int. Nevrací-li např. 'ádnou hodnotu, píšeme typ void. Toto platí i pro hlavní program, který obvykle nevrací 'ádnou hodnotu, a proto má být před identifikátorem main slovní symbol void. Nenapíšeme-li tento slovní symbol, hlásí některé systémy varování, 'e funkce main nevrací hodnotu. Zápisu void před main se pak mů'eme vyhnout tak, 'e zapíšeme na konci hlavního programu příkaz return a vracíme nějakou hodnotu: např. skončil-li program správně, vracíme hodnotu 1, jinak 0 apod. Formální parametry jsme pou'ili ve funkci copy. U formálních parametrů v tomto případě nesmíme uvést rozměr pole. To je u jednorozměrného pole (vektoru) charakteristické. U dvojrozměrného pole je situace trochu slo'itější a v čl. se k této problematice vrátíme. Zvláštní zmínku si ovšem zaslou'í tzv. externí proměnné, pou'ité v příkladu 1.15. 5.1 Automatické a externí proměnné Proměnné ve funkci main, tj. např. delka, max, radek, mradek jsou lokální v main. ádná funkce k nim nemá přístup. Totéž platí o jakékoliv programové jednotce v níž je nějaká lokální proměnná definovaná. Lokální proměnná začne existovat až po vyvolání funkce a její hodnota se ztrácí po ukončení činnosti příslušné funkce. V jazycích C a C++ se těmto proměnným říká automatické proměnné. Při vstupu do programové jednotky jim musí být vždy znovu přiřazena hodnota, protože jinak by obsahovaly hodnotu náhodnou. Mohou se inicializovat, tj. může se jim přiřadit počáteční hodnota ihned při definici. Pak se při každém vstupu do funkce inicializují znovu. V jazyku C se automatická pole inicializovat nesmějí (mají při vstupu do funkce vždy hodnotu nula), avšak v jazyku C++ toto omezení neplatí. Proměnné, které chceme používat ve více funkcích, a nechceme-li nebo nemůžeme-li použít mechanismu formální - skutečný parametr, zavedeme jako tzv. externí proměnné. Tyto proměnné jsou definovány globálně pro celý soubor funkcí a jsou dostupné pro všechny funkce souboru,. Externí proměnné se musí definovat mimo funkce a deklarovat buď explicitně deklarací extern, nebo implicitně svým použitím v příslušné funkci. Externí proměnné a pole se inicializují jen jednou v procesu plnění programu. Neprovede-li se inicializace mají napočátku externí proměnné hodnotu nulovou.

Sestává-li program z více souborů, pak je externí proměnná definována v jednom souboru a lze ji tam použít shora popsaným způsobem; ve druhém souboru se externí proměnná musí deklarovat ve funkci, deklarací extern. V našem programu jsme museli definovat proměnnou ms jako externí. V souboru hrad jsme s ní pracovali bez jakékoliv deklarace, v souboru frad jsme ji museli ve funkci getline explicitně deklarovat. Proměnnou i v souboru frad jsme definovali na začátku souboru a implicitně použili v obou funkcích getline a copy. V druhém případě by bylo vhodnější definovat proměnnou v obou funkcích zvláš», náš záměr zde byl čistě pedagogický. Na tomto místě je třeba upozornit, že extern i a extern int i znamená totéž. Externí proměnné je vhodné užívat uvážlivě, protože mohou být (právě tak jako proměnné v popisu common v jazyku fortran) zdrojem nepříjemných chyb a mohou znepřehledňovat program. Závěrem si uveďme schéma na vysvětlenou: // soubor1.cpp int sp=0; // Definice externi promenne s inicializaci float val[1000]; // Definice externiho pole bez inicializace void main() extern sp; // Nepovinna deklarace //... funkce() extern float val[]; // Nepovinna deklarace // soubor2.cpp extern sp; // Povinna deklarace extern float val[]; //Povinna deklarace /* Toto byly povinne deklarace externich promennych. Pak se mohou pouzivat ve vsech funkcich souboru. Mohli jsem je ale tez deklarovat jen ve funkcich, ktere dane promenne pouzivaji */ //... Poznámka: Pozorný čtenář si jistě všiml, že používáme dva pojmy: definice a deklarace proměnné nebo pole. V jazyku C a C++ se těchto pojmů užívá takto: definice se vztahuje k místu, kde se proměnné skutečně přiděluje pamě», deklarace se vztahuje k místu, kde se popisuje druh proměnné bez přidělení paměti. 5.2 Rekurzívní funkce O funkci říkáme, že je rekurzívní, volá-li sama sebe ještě před dokončením svého algoritmu. Známým a jednoduchým příkladem rekurzívní funkce je výpočet faktoriálu. long fakt(int n) if(n==0 n==1) return(1); else return (n*fakt(n-1));

nebo ještě stručněji long fakt(int n) return (n==0 n==1)?1:n*fakt(n-1);// Na tomto velmi jednoduchém příkladu rekurzívní funkce si můžeme snadno vysvětlit princip výpočtu. Představme si, že funkci fakt zavoláme s parametrem 4. Formálnímu parametru se tedy přiřadí hodnota 4. Provede se zkouška, zda se n rovná nule nebo jedné. To se ale nerovná, protože se rovná čtyřem. Vyvolá se tedy znovu funkce fakt, ale tentokrát s novým parametrem, který má hodnotu n-1, tedy hodnotou tři. V tomto dalším bloku se provede další zkouška, a protože stále není hodnota parametru rovna nule nebo jedničce vyvolá se opět funkce fakt s hodnotou dvě, a pak ještě jednou s hodnotou jedna. Teprve nyní se vrací hodnota jedna, ta se násobí v funkci (podle algoritmu) dvěma, výsledek se opět v funkci násobí třemi a v původně volané funkci čtyřmi. Konečný výsledek je tedy 24. Z tohoto příkladu vidíme, že jsme sice rekurzívním zápisem zápis zjednodušili, ale místo jednoho parametru jsme potřebovali (aniž bychom to explicitně zadali) parametry čtyři. Obecně platí, že rekurzívní zápisy spotřebují více paměti než zápisy nerekurzívní a také více strojového času. Přesto mnohdy je zjednodušení a zpřehlednění zápisu tak významné, že rekurzivitu využíváme. 6. Závěrečné poznámky k 1. kapitole Po ukončení 1. kapitoly jsme schopni psát i dosti komplikované programy. Nejdůležitější skutečnosti, které vyžaduje zápis programu v C++, byly v této kapitole uvedeny; zde uvedeme jeden nový poznatek, jeden upřesňující poznatek a jedno důležité opakování. 1. Proměnné v jazyku C++ se nemusí definovat na začátku funkce, ale před prvním použitím ve funkci. Definice veličin mohou být tedy rozptýleny v celé operační části funkce nebo chcete-li v celém funkce. 2. V příkazu printf, fprintf, scanf a fscanf se používá tzv. formátová specifikace. Částečně jsme se s ní seznámili. Nyní se zmíníme o konverzích, o kterých jsme ještě nemluvili, popř. mluvili, ale příliš stručně. o %o Argument se konvertuje na hodnotu v osmičkové soustavě (printf) nebo se očekává hodnota v osmičkové soustavě ( scanf). o %x Totéž jako v předchozím případě, ale nyní se jedná o hodnotu v šestnáctkové soustavě. o %i Má stejný význam jako konverze %d, tj. očekává se nebo se tiskne celočíselná hodnota. o %u Argument se konvertuje do desítkové soustavy bez znaménka, nebo se očekává hodnota bez znaménka. o %e Argument je reálný a tiskne se desítkově ve tvaru [-]m.mmmmmme±nn, kde hodnota za desetinnou tečkou je specifikovaná přesnost. Implicitní přesnost je 6. Pro funkci scanf má konverze %e tentýž význam jako konverze %f. o %g Použije %e nebo %f podle toho, co je kratší. Nevýznamné nuly se netisknou. Pro funkci scanf má konverze tentýž význam jako konverze %f. o %c Zajistí čtení nebo tisk jednoho znaku.

Písmeno l uvedené před d, o a x označuje, že v seznamu argumentů funkcí odpovídá této konverzi forma (long) a u konverzi f nebo e označuje, že odpovídající argument není typu float, ale double, tj., že nabývá reálné hodnoty s dvojnásobnou přesností. Písmeno L označuje v tomto případě, že odpovídající argument je typu long double. Zastavme se ještě u tisku řetězce. Uvedeme nejzajímavější příklady aplikace konverze %s pro tisk řetězce: Nejneobhospodarovavatelnejsi o %s Nejneobhospodarovavatelnejsi o 10%s Nejneobhospodarovavatelnejsi o 35%s Nejneobhospodarovavatelnejsi o.9%s Nejneobho 3. Každá funkce volaná v jiné funkci musí mít před místem volání tzv. prototyp. Lze obejít hlavičkovým souborem, ve kterém uvedeme všechny prototypy funkcí a k souboru připojíme příkazem #include 7. Cvičení 1. [1.] Sestavte programy z příkladů 1.4. a 1.5. tak, že příkazy (funkce) cin a cout nahradíte voláním funkcí scanf a printf. 2. [2.] Pokuste se u všech u programů v příkladech 1.3 až 1.5 definovat konverzi pro výstup hodnot na výstupu (nevyužívat tedy standardní výstupní konverze). Návod: o U příkazu printf např. %3d zajistí tisk nejméně tří znaků celočíselné hodnoty, %6.1f zajistí tisk nejméně šesti znaků reálné hodnoty s jednou číslicí za desetinnou tečkou. Mnohé lze vynechat - např.%6f zajistí tisk nejméně šesti znaků reálné hodnoty %.4f požaduje dvě čísla za desetinnou tečkou, ale bez omezení šířky. %% znamená vytištění znaku %. o U příkazu cout je možno použít manipulátorů. 3. [3.] Sestavte program podle příkladu 1.6 tak, že použijete soubor stdio.h, funkci fprintf, fscanf a místo návěští KONEC a příslušného příkazu skoku zajistěte ukončení programu příkazem while. 4. [4.] Sestavte program pro převod teplot tak, aby tiskl tabulku v opačném pořadí, tj. od 300 do 0 stupňů Fahrenheita. 5. [5.] Sestavte program pro výpočet částečného součtu řady S n = 1+x+[(x 2 )/ 2!]+ +[(x n )/( n!)], kde n je nejmenší číslo, pro které platí [(x n )/( n!)] < ε Čísla x a ε jsou dána vstupními daty. Vypočet realizujte: o příkazem do-while,

o o příkazem while, příkazem for. Návod: Pro sestavení algoritmu je nutné si uvědomit, že každý příspěvek k částečném součtu řady lze vypočítat z předchozího příspěvku ze vztahu člen i = x / i člen i-1 a není tedy nutné počítat ani mocninu ani faktoriál. 6. [6.] Sestavte program pro realizaci Euklidova algoritmu výpočtu největšího společného dělitele (NSD) dvou přirozených čísel. Výpočet realizujte: o příkazem while, o příkazem for, o příkazem do-while. Návod: Vyjděte z vlastností NSD: pro x > y platí NSD(x,y) = NSD(x-y,y), pro x < y platí NSD(x,y) = NSD(x,y-x), pro x = y platí NSD(x,y) = x = y. 7. [7.] Sestavte program na počítání znaků mezera, tabelátor a nový řádek v souboru m_sbr 8. [8.] Sestavte program na kopírování souboru m_vst do souboru m_vys tak, že každý řetězec znaků mezera v souboru m_vst zamění za jediný znak mezera a znak tabelátor zamění šesti mezerami. 9. [9.] Sestavte program, který na každý řádek výstupního souboru zapíše maximálně deset slov ze vstupního souboru. 10. [10.] Upravte program z příkladu 1.11 tak, aby slovo zpracovával podle definice: Slovo je posloupnost písmen, číslic, znaků '_' a '.' začínající písmenem. 11. [11.] Sestavte program pro transponování čtvercové matice A stupně n, kde n 10. 12. [12.] Sestavte program pro výpočet stopy matice stupně n, kde n 20. Návod: Použijte vzorce s = i = 1 n a ii. 13. [13.] Sestavte program pro násobení matic C (m,n) = A (m,l) B (l,n). Návod: c ij = c ij + k=1 l a ik b kj, i = 1,2,.,m; j = 1,2,,n. 14. [14] Sestavte program, který zamění znaky tabelátor (\t) ze vstupu za správný počet mezer tak, aby vyplnil prostor po následující zarážku tabelátoru. Předpokládejte, že zarážky tabelátoru jsou pevné, např. na každé šesté pozici. 15. [15.] Sestavte program, který zamění řetězce znaků mezera za nejmenší počet znaků tabelátor a mezera tak, aby se zachovala grafická úprava textu.

16. [16.] Sestavte program, který zalomí dlouhé vstupní řádky za posledním znakem, který se vyskytne před n-tou pozicí vstupního řádku. n je parametr. 17. [17.] Napište předchozí program tak, aby řádky byly zarovnány. 18. [18.] Sestavte program, který vynechá z C++ programu všechny poznámky. 19. [19.] Sestavte funkci malep(chr z), která vrátí hodnotu z, není-li z písmeno, a malé písmeno, je-li z písmeno. Použijte funkci malep v programu, který konvertuje text na malá písmena. Návod: Využijte vlastnosti kódu ascii, kde číselné kódy malých a velkých písmen mají konstantní rozdíl; obě abecedy jsou spojité. 20. [20.] Sestavte funkci obrat(char s[]), která obrátí znakový řetězec s. Funkci použijte v programu. 21. [21.] Sestavte funkci sks(int x[],int y[],n) a void sks1(int x[],int y[],int s,n) pro výpočet skalárního součinu i = 1 n x i y i a použijte je v programu. 22. [22.] Sestavte rekurzívní funkci pro operaci umocňování podle následujícího efektivního rekurzívního algoritmu. 23. mocnina(int x,int n) 24. 25. int v=1; 26. while (n) 27. 28. while(n/2*2==n) 29. 30. n /= 2; x *= x; 31. 32. n--;v *= x; 33. 34. return v; 35.

Kapitola 2 Typy, operátory, výrazy V této kapitole nebudeme opakovat již probrané objekty, jen si řekneme některé podrobnosti. 1. Jména, typy, konstanty 1.1 Jména Jméno, nebo v odborné terminologii synonymum identifikátor, je v jazyku C++ posloupnost maximálně 31 písmen, číslic a znaků podtržení ( _) začínající písmenem. Znak _ se považuje za písmeno. Lépe je používat jména kratší než delší (maximálně osm, spíše šest). Slovní symboly (např. for, else, int, while apod. jsou tzv. vyhrazená slova, která se nesmějí používat jako jména. Malá a velká písmena se v C++ rozlišují: haha, Haha a HaHa jsou tři různá jména a For není slovní symbol. 1.2 Typy V jazyku C++ jsou následující základní standardní typy: char, int, unsigned, float a double, kterými definujeme proměnné, které mohou po řadě nabývat hodnoty: znak, celočíselná hodnota, celočíselná hodnota bez znaménka, reálná hodnota a reálná hodnota s dvojnásobnou přesností. Celočíselná proměnná může být označena kvalifikátorem short nebo long. Definice nebo deklarace: short int i a short i jsou totožné; právě tak long j a long int j. Dlouhé a krátké hodnoty můžeme definovat i pro typ unsigned: např. short unsigned u a long unsigned u (nebo unsigned short, unsigned long). Je možné také psát unsigned char nebo char unsigned. Dlouhá forma je možná i u proměnných typu double: např. long double ld. Můžeme odvozovat další typy např. struktury, unionya třídy. Na tomto místě se zmíníme o tzv. výčtovém typu. Dovoluje zpřehlednit program. Výčtový typ lze definovat několika způsoby. Uvedeme ten, který je v C++ nejjednodušší. Příklad 2.1. Sestavme program, který přečte hodnotu proměnné barva a bude-li barva červená, resp. žlutá, resp. zelená, bude se tisknout text STUJ, resp. PRIPRAV SE, resp. VOLNO. Řešení: #include<iostream.h> main() enum BARVAcervena,zluta,zelena; // Deklarace typu BARVA BARVA semafor; // Definice promenne semafor typu BARVA cin >> semafor;/* Cteni hodnoty. Neni-li receno jinak, plati cervena == 0, zluta == 1 a zelena == 2 */ switch(semafor) case cervena: cout << ťstuj\nť;break; case zluta: cout << ťpriprav SE\nť;break;

case zelena: cout << ťvolno\nť;break; Mohli bychom samozřejmě pracovat s čísly 0, 1, 2, ale shora uvedeným způsobem se zápis algoritmu zpřehlední. Implicitně zadané hodnoty položkám typu se mohou změnit, např. zápis enum DENpo=1,ut,st,ct,pa,so,ne zajistí, že položka po == 1, ut == 2, st == 3 atd. Zápis enum Dpo,ut,st,ct,pa=1,so=12,ne zajistí, že ut == pa == 1, so == 12, ne == 13. 1.3 Konstanty 4444444444444 4444444444444 Matematický zápis Zápis v C++ Matematický zápis Zápis v C++ -123-123 10-4 1e-4 2,345 2.345 x 'x' -0,5 -.5 (77) 8 077 1,2 5 1.2e5 (1A) 16 0x1a Zápisy číselných konstant jsou jasné z předchozí tabulky. Celočíselné konstanty se píší tak jako v matematice. U reálných konstant píšeme desetinnou tečku a exponent označujeme písmenem e nebo E (jako v jiných programovacích jazycích) a znaky píšeme mezi apostrofy. V C++ můžeme zapisovat i osmičkové nebo hexadecimální konstanty, tak jak je v tabulce uvedeno. Některé nezobrazitelné znaky je možné zapsat pomocí změnových posloupností, např. \n (nový řádek), \t (tabelátor), \0 (prázdný znak),\\ (zpětné lomítko), \' (apostrof) apod. Mimoto se může zápisem '\ddd' realizovat libovolný bitový řetězec, kde (d je osmičková číslice), popř.'\xdd', kde d je hexadecimální číslice. Napíšeme-li v programu konstantu desítkovou konstantu 48 nebo '\60' nebo '\x30', znamená to v kódu ascii znak nula; napíšemeli desítkově 95 nebo '\137' nebo '\x5f', je to v kódu ascii znak _. Definujeme-li např. v programu symbolickou konstantu: const char nova_str='\14'; definovali jsme novou stránku (pracujeme-li v kódu ASCII). 2. Operátory V tomto odstavci probereme podrobnosti o aritmetických, logických a dalších operátorech a zmíníme se o prioritách operací v C++ 2.1 Aritmetické operátory 1. Operátor o kterém jsme ještě nehovořili je operátor operace. Např. 5%4 - > 1, 3%4 - > 3, 10%2 - > 0. Příklad 2.2. Sestavme část programu, která zjistí, je-li rok přestupný.