Programování III. Mgr. Monika Pinkasová. Zlepšování podmínek pro využívání ICT ve výuce a rozvoj výuky angličtiny na SPŠei Ostrava



Podobné dokumenty
Pointery II. Jan Hnilica Počítačové modelování 17

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

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:

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

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

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

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

Vícerozměrná pole. Úvod do programování 2 Tomáš Kühr

II. Úlohy na vložené cykly a podprogramy

Př. další použití pointerů

Základy programování (IZP)

IUJCE 07/08 Přednáška č. 4. v paměti neexistuje. v paměti existuje

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

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

2 Datové typy v jazyce C

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

Základy C++ I. Jan Hnilica Počítačové modelování 18

Dynamická vícerozměrná pole. Základy programování 2 Tomáš Kühr

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

Pole a Funkce. Úvod do programování 1 Tomáš Kühr

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

Ukazatele, dynamická alokace

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

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

Pokročilé programování v jazyce C pro chemiky (C3220) Operátory new a delete, virtuální metody

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

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

Střední škola pedagogická, hotelnictví a služeb, Litoměříce, příspěvková organizace

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

Cykly a pole

Základy programování (IZP)

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

Pole a kolekce. v C#, Javě a C++

Algoritmizace a programování

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

Střední škola pedagogická, hotelnictví a služeb, Litoměříce, příspěvková organizace

ALGORITMIZACE A PROGRAMOVÁNÍ

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

Úvod do programování. Lekce 1

Sada 1 - Základy programování

DUM 07 téma: Proměnné, konstanty a pohyb po buňkách ve VBA

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

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

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

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

Standardní vstup a výstup

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

Základy programování (IZP)

Práce s binárními soubory. Základy programování 2 Tomáš Kühr

Algoritmizace a programování

9. lekce Úvod do jazyka C 4. část Funkce, rekurze Editace, kompilace, spuštění Miroslav Jílek

Jazyk C práce se soubory. Jan Hnilica Počítačové modelování 16

Strukturu lze funkci předat: (pole[i])+j. switch(výraz) velikost ukazatele

Úvod do programování. Lekce 5

III/2 Inovace a zkvalitnění výuky prostřednictvím ICT

10 Algoritmizace Příklad 2 Word 2007/ VBA

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

6. lekce Úvod do jazyka C knihovny datové typy, definice proměnných základní struktura programu a jeho editace Miroslav Jílek

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í II. Mgr. Monika Pinkasová. Zlepšování podmínek pro využívání ICT ve výuce a rozvoj výuky angličtiny na SPŠei Ostrava

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

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

Ukazatel (Pointer) jako datový typ - proměnné jsou umístěny v paměti na určitém místě (adrese) a zabírají určitý prostor (počet bytů), který je daný

Základy programování (IZP)

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

int t1, t2, t3, t4, t5, t6, t7, prumer; t1=sys.readint();... t7=sys.readint(); prume pru r = r = ( 1+t 1+t t3+ t3+ t4 t5+ t5+ +t7 +t7 )/ ;

Střední škola pedagogická, hotelnictví a služeb, Litoměříce, příspěvková organizace

Programovací jazyk Pascal

Základy programování (IZP)

Pole stručný úvod do začátku, podrobně později - zatím statická pole (ne dynamicky) - číslují se od 0

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

Vysoké učení technické v Brně, Fakulta elektrotechniky a komunikačních technologií Ústav automatizace a měřící techniky. Semestrální projekt

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 -

POČÍTAČE A PROGRAMOVÁNÍ

Pokročilé programování v jazyce C pro chemiky (C3220) Vstup a výstup v C++

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

Maticí typu (m, n), kde m, n jsou přirozená čísla, se rozumí soubor mn veličin a jk zapsaných do m řádků a n sloupců tvaru:

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.

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

Algoritmizace a programování

III/2 Inovace a zkvalitnění výuky prostřednictvím ICT

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

11a Dynamické dvourozměrné pole (obdobně vícerozměrné)

Projektč.3dopředmětuIZP. Maticové operace

0.1 Úvod do lineární algebry

IAJCE Přednáška č. 8. double tprumer = (t1 + t2 + t3 + t4 + t5 + t6 + t7) / 7; Console.Write("\nPrumerna teplota je {0}", tprumer);

Implementace LL(1) překladů

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

III/2 Inovace a zkvalitnění výuky prostřednictvím ICT

Pokročilé programování v jazyce C pro chemiky (C3220) Třídy v C++

Výčtový typ strana 67

Konstruktory a destruktory

Práce s polem a pamětí

DUM 06 téma: Tvorba makra pomocí VBA

Základy PERLu snadno a rychle

Zadání: TÉMA: Zápis algoritmu, čtení textového souboru, porovnání řetězců.

Ukazatele a pole. Chceme-li vyplnit celé pole nulami, použijeme prázdný inicializátor: 207 Čárka na konci seznamu inicializátorů

10 Práce s řetězci - pokračování

Transkript:

Programování III. Mgr. Monika Pinkasová Zlepšování podmínek pro využívání ICT ve výuce a rozvoj výuky angličtiny na SPŠei Ostrava č.projektu CZ.1.07/1.1.07/03.0089 Ostrava 2011

Obor: Informační technologie Předmět: Programování Ročník: 3.ročník Autor: Mgr. Monika Pinkasová Doporučená literatura: Herout, P.: Učebnice jazyka C 1.díl, Páté vydání, Kopp, 2008, ISBN 978-80- 7232-351-7 Herout, P.: Učebnice jazyka C 2.díl, Druhé přepracované vydání, Kopp, 2004, ISBN 80-7232-221-4 Kadlec, V.: Učíme se programovat v jazyce C, 2. Vyd., Brno : CP Books, 2005, ISBN 80-7226-715-9 Schildt, H.: Nauč se sám C, překlad Lubomír Kočí, Praha : SoftPress, c2001, ISBN 80-86497-16-X Mgr. Monika Pinkasová Střední průmyslová škola elektrotechniky a informatiky, Ostrava, příspěvková organizace

OBSAH Úvod... 9 1 Vícerozměrné statické pole... 10 1.1 Statické vícerozměrné pole...11 1.2 Přístup k prvkům vícerozměrného pole...12 2 Práce s vícerozměrným statickým polem... 14 3 Vícerozměrné pole - procvičování... 17 4 Vícerozměrné statické pole a funkce... 21 5 Vícerozměrné statické pole řešené příklady... 25 6 Vícerozměrné statické pole neřešené příklady... 30 7 Přístup k prvkům vícerozměrného pole... 33 8 Pole pointerů... 37 9 Pointer na pole... 41 10 Pointer na pointer... 44 11 Vícerozměrné dynamické pole shrnutí, příklady... 48 11.1 Porovnání vícerozměrných polí...48 11.2 y...49 12 Řetězce deklarace... 54 13 Řetězce základy práce... 57 13.1 Načtení řetězce...57 13.2 Výpis řetězce...58 13.3 Přístup řetězcům...59 14 Řetězce funkce pro práci s řetězci... 60 15 Řetězce řešené příklady... 64 16 Řetězce neřešené příklady... 70 17 Pole řetězců a parametry funkce main()... 73 17.1 Pole řetězců...73 17.2 Parametry funkce main()...75 18 Datový typ struktura... 78 19 Práce s položkami struktur... 83 20 Struktury - příklady... 86 21 Pole struktur... 90 22 Struktura ve struktuře a pole ve struktuře... 94 23 Dynamická struktura... 98 24 Struktura a funkce... 101

25 Struktura řešené příklady... 106 26 Struktura neřešené příklady... 109 27 Datový typ union... 113 28 Datový typ enum... 116 29 Datový typ enum a union - příklady... 120 30 Soubory... 126 31 Práce se soubory... 129 32 Funkce pro práci se soubory... 133 32.1 Čtení ze souboru... 133 32.2 Zápis do souboru... 135 32.3 Ostatní funkce pro práci se soubory... 136 33 Soubory řešené příklady... 138 34 Soubory neřešené příklady... 142 35 Shrnutí učiva... 144

Vysvětlivky k používaným symbolům Obsah hodiny popisuje náplň hodiny Cíl hodiny specifikace dovedností a znalostí, které si studující osvojí během hodiny Klíčová slova nové pojmy, specifické termíny či cizí slova, jejichž význam je v textu vysvětlen Definice definování a vysvětlení nového pojmu či jevu objasnění nebo konkretizování problematiky na příkladu ze života, z praxe, ze společenské reality apod. Shrnutí shrnutí probrané látky, shrnutí kapitoly Kontrolní otázky a úkoly prověřují, do jaké míry studující text a problematiku pochopil, zapamatoval si podstatné a důležité informace a zda je dokáže aplikovat při řešení problémů Otázky k zamyšlení - úkoly rozšiřující úroveň základních znalostí Literatura literatura a zdroje pro doplnění a rozšíření poznatků kapitoly

9 Úvod Tento výukový modul se zabývá prohlubování znalostí programování v jazyce C. Navazuje tak na výukový modul Programování I. a Programování II. a znalosti těchto modulů jsou nezbytně nutné vstupní předpoklady modulu Programování III. Modul Programování III. je určen pro studenty 3. ročníku oboru Informační technologie. Cílem modulu Programování III. je rozšířit a zdokonalit stávající znalosti programování v jazyce C. Studenti se seznámí se rozšiřujícími ale přesto i základními prvky jazyka C - s vícerozměrnými poli, řetězci, strukturovanými datovými typy struktura, enum, union, soubor a jejich využitím. Prostudováním tohoto textu si student osvojí základní znalosti a pojmy. Ale jen cvičením a používáním těchto znalostí v praktickém programování se může dostat k aktivnímu použití jazyka C.

10 1 Vícerozměrné statické pole Obsah hodiny Seznámíme se s vícerozměrným polem, s jeho deklarací, charakteristikou a přístupem k prvkům. Cíl hodiny Po této hodině budete schopni: deklarovat statické vícerozměrné pole popsat alokaci statického vícerozměrného pole pracovat s prvky vícerozměrného pole Klíčová slova Vícerozměrné pole, statické pole, deklarace vícerozměrného pole, přístup k prvkům vícerozměrného pole Velice často potřebujeme zpracovat větší množství dat stejného datového typu, které jsou seskupeny do skupin. V programu, který bude zpracovávat průměrnou denní teplotu v prvních 5 týdnech v roce. Měli bychom 5*7=35 reálných čísel. Pokud bychom potřebovali týdenní průměry, maxima, minima, potřebujeme jen prvních sedm čísel. Pro podobné zpracování třetího týdně potřebujeme jen hodnoty 15 až 21. Bylo by proto rozumnější, seskupit data pro jeden týden do pole. A pak tedy budeme mít pole polí. Můžeme pak se všemi hodnotami v daném týdnu pracovat jednoduše a efektivně. Graficky bychom mohli takto strukturovaná data zobrazit takto: Jednotlivé týdny Dny v týdnu

11 Vytvořili jsme tak matici čísel o pěti řádcích a sedmi sloupcích. Tuto datovou strukturu realizujeme v programování pomocí vícerozměrných polí. Vícerozměrné pole chápeme jako pole polí. To znamená, že jde o pole, jehož prvky jsou další pole. Stejně jako u jednorozměrného pole můžeme prvky pole vytvořit staticky (automaticky, v zásobníku) nebo dynamicky (pomocí malloc v haldě) 1.1 Statické vícerozměrné pole Statické vícerozměrné pole je alokováno v zásobníku. Počet řádků i sloupců musíme znát již před překladem programu. Deklarace statického vícerozměrného pole: datový_typ_prvků název [počet_řádků] [počet_sloupců] int pole[3][4]; Vytvoří se v paměti matice 12 celých čísel, které jsou uspořádány do 3 řádků a 4 sloupců. Obdélníkové schéma matice je jen naše představa vícerozměrného pole. Prvky pole se totiž uloží v paměti za sebou. Název pole je stejně jako u jednorozměrného pole ukazatel na první prvek v poli resp. adresa prvního prvku pole. deklarace s využitím maker #define R 3 //počet řádků #define S 4 //počet sloupců int pole[r][s]; Ještě před překladem preprocesor rozvine makra zamění tedy R ta číslo 3 a S za číslo 4, proto při překladu bude známa velikost vícerozměrného pole. Pokud makra použijeme v celém programu pro práci s vícerozměrným polem, jednoduchou změnou hodnot maker můžeme změnit rozměr vícerozměrného pole v celém programu.

12 deklarace s inicializací Stejně jako u jednorozměrného pole můžeme při deklaraci prvky pole ihned inicializovat. int p[ ][4]= {{1,2,3,4, {11,12,13,14, {21,22,23,24; Počet sloupců musí být v této deklaraci uveden. Počet sloupců bude určen podle počtu čtyřprvkových polí, které jsou uvedeny v závorkách {. Vytvoří se pole p: 1.2 Přístup k prvkům vícerozměrného pole Pro přístup k prvkům vícerozměrného pole budeme potřebovat dva indexy prvku řádkový a sloupcový index. p int p[3][4]; p[0][1]= 8; Tímto příkazem uložíme číslo 8 do druhého prvku (index 1) na prvním řádku (index 0). scanf( %d,&p[1][2]); Načteme od uživatele třetí prvek na druhém řádku. srand((long)time(null)); p[2][1]= rand() % 10; Náhodně vygenerujeme číslo a uložíme jej do druhého prvku na třetím řádku. Předpokládejme, že uživatel zadá číslo 5 a že bude vygenerováno číslo 7.

13 p[0][4]= 3; Zapisujeme hodnotu 3 do pátého prvku na prvním řádku. V každém řádku máme ale jen 4 prvku. Tento příkaz nebude hlásit chybu, protože C nekontroluje meze polí. Číslo 3 bude zapsáno do dalšího prvku tedy do dalšího řádku. Této postup sice nehlásí chybu, ale nedoporučuje se, protože může dojít k přemazání hodnot, které už v poli máme uloženy nebo můžeme zapisovat do nevyblokované paměti, což je činnost velice nebezpečná a chyba těžko dohledatelná. p[3][0]= 6; Chybný příkaz, který píše mimo vyblokovanou paměť. Shrnutí kapitoly Vícerozměrné pole je pole polí, které odpovídá matematickému pojmu matice o daném počtu řádků a sloupců- U statického vícerozměrného pole musíme znát počet řádků i sloupců již před překladem. Prvky pole jsou alokovány v zásobníku za sebou v souvislém bloku. K prvkům vícerozměrného pole přistupujeme pomocí řádkových a sloupcových indexů. Kontrolní otázky a úkoly 1) Popište, deklarujte a zakreslete vícerozměrné statické pole o 5 řádcích a 3 sloupcích. Zapište na do všech prvků v prvním sloupci číslo 5. Načtěte od uživatele všechny prvky v druhém sloupci. Náhodně vygenerujte hodnoty pro prvky ve třetím sloupci. 2) Kontroluje jazyk C meze polí?

14 2 Práce s vícerozměrným statickým polem Obsah hodiny Seznámíme se s prací se všemi prvky vícerozměrného pole. Cíl hodiny Po této hodině budete schopni: načíst všechny prvky vícerozměrného pole vypsat prvky vícerozměrného pole ve tvaru matice Klíčová slova Načtení vícerozměrného pole, výpis vícerozměrného pole Ve vícerozměrném poli pracujeme s větším množstvím prvků, které organizujeme do řádků a sloupců. Poté co jste prostudovali učivo o jednorozměrných polích je zřejmé, že nebudeme s prvky pracovat jednotlivě, ale najednou pomocí cyklů. Protože známe rozměry pole počet řádků i počet sloupců, použijeme cyklus s danám počtem opakování - cyklus for. Jestliže chceme načíst jeden řádek jedno jednorozměrné pole, použijeme jeden cyklus for. Ve vícerozměrném poli máme těchto řádků více, proto musíme dalším cyklem for zajistit opakování načítání jednotlivých řádků. Načítání vícerozměrného pole budeme provádět vnitřním a vnějším cyklem for. Načítání vícerozměrného pole int p[3][4], i, j; srand((long)time(null)); for(i=0;i<3;i++) for(j=0;j<4;j++) p[i][j]= rand() % 100; //nebo scanf( %d,&p[i][j]);

15 Vnitřní cyklus for(j=0;j<4;j++) p[i][j]= rand() % 100; zajistí načtení jednoho řádku všechny 4 prvky na řádku s indexem i. Vnější cyklus for(i=0;i<3;i++) zajistí opakování vnitřního cyklu tak, aby byly načteny všechny tři řádky ve vícerozměrném poli p. Velice podobně provádíme výpis vícerozměrného pole. Abychom jej však zobrazili na více řádcích, musíme po každém vypsání jednoho řádku odřádkovat. Výpis vícerozměrného pole for(i=0;i<3;i++) { for(j=0;j<4;j++) printf( %d, p[i][j] ); printf( \n ); //vnitřní cyklus vypíše jeden řádek //po vypsání řádku přejde na nový řádek Pomocí vnitřního a vnějšího cyklu zpracováváme vícerozměrná pole téměř vždy. Zjištění maximálního prvku ve vícerozměrném poli int p[3][4], i, j, max; //načtení popř. i výpis pole max=p[0][0]; for(i=0;i<3;i++) for(j=0;j<4;j++) if (max<p[i][j]) max=p[i][j]; printf( Maximum je %d, max); // nastavíme hodnotu maxima na první prvek // jestliže je prvek větší než maximum // pak maximum přepíšeme prvkem

16 Zjištění aritmetického průměru všech kladných čísel ve vícerozměrném poli. int p[3][4], i, j, pocect=0, soucet=0; //načtení popř. i výpis pole for(i=0;i<3;i++) for(j=0;j<4;j++) if (p[i][j]>0) { pocet++; soucet+=p[i][j]; // jestliže je prvek kladný printf( Průměr všech kladných je %f, (float)soucet/pocet); Shrnutí kapitoly Ve vícerozměrných polích máme data organizovány do řádků a sloupců, proto při zpracovávání dat ve vícerozměrných polích používáme vnější a vnitřní cyklus for. Vnitřní cyklus provede zpracování dat na jednom řádku a vnější cyklus zajistí opakování dané činnosti pro všechny řádky vícerozměrného pole. Kontrolní otázky a úkoly 1) Popište podrobně provádění výpisu vícerozměrného pole ve tvaru matice. 2) Vytvořte program, který pro vícerozměrné pole int p[3][4] zjistí počet všech sudých čísel v tomto poli.

17 3 Vícerozměrné pole - procvičování Obsah hodiny Procvičíme práci s vícerozměrným polem i s přístupem k jednotlivým prvkům vícerozměrného pole. Cíl hodiny Po této hodině budete schopni: zpracovat data ve vícerozměrných polích využít vícerozměrná pole pro řešení problémů 1 1) Vytvořte statické reálné vícerozměrné pole matice o 5 řádcích a 4 sloupcích. 2) Načtěte pole matice hodnotami od uživatele. 3) Vypište pole matice ve tvaru matice (obdélník). 4) Načtěte od uživatele řádek a sloupec a vypište hodnotu v poli matice na tomto zadaném řádku a sloupci. 5) Najděte minimální prvek v poli matice (jeho první výskyt). Vypište jej a vypište i na kterém řádku a ve kterém sloupci se nachází. 6) Zjistěte kolik čísel v poli matice je z intervalu <-10;10). 7)Načtěte od uživatele číslo sloupce a najděte maximální hodnotu v tomto zadaném sloupci v poli matice. 8) Načtěte od uživatele číslo řádku a vypočtěte aritmetický průměr hodnot v tomto zadaném řádku v poli matice. 9) Načtěte od uživatele číslo řádku a do tohoto řádku v poli matice zapište samé nuly a pole matice znovu vypište. 10) Načtěte od uživatele číslo řádku a setřiďte vzestupně zadaný řádek v poli matice. Poli matice opět vypište.

18 Řešení Některé úkoly řešte obdobně podle příkladů z předchozí kapitoly. ad 7) float matice[5][4], max; int i, j, sloupec; //načtení popř. i výpis pole matice // načteme číslo sloupce scanf( %d,&sloupec); sloupec--; // číslo sloupce snížíme o 1, protože pole indexujeme od nuly // nastavíme hodnotu maxima na první prvek max=matice[0][0]; // sloupec ve zpracování pole matice zůstává stále stejný, // proto bude stačit jen jeden cyklus, který bude měnit // řádkový index // v cyklu budeme zjišťovat, jestli je daný prvek větší než // maximum, pak maximum přepíšeme daným prvkem for(i=0;i<5;i++) if (max< matice[i][sloupec]) max= matice[i][sloupec]; printf( Maximum je %d, max); ad 10) Z předchozího modulu víme, že pro třídění jednorozměrného pole Bubble sortem potřebujeme dva cykly for. Stejně tak to bude i třídění jednoho řádku v poli matice, protože porovnáváme jen prvky vedle sebe na stejném řádku - řádkový index zůstává stále stejný float matice[5][4]; int i, j,pom, radek; //načtení popř. i výpis pole scanf( %d,&radek); radek --;

19 for(i=0;i<3;i++) for(j=0;j<3;j++) if ( matice[radek][j]< matice[radek][j+1] ) { pom= matice[radek][j]; matice[radek][j] = matice[radek][j+1]; matice[radek][j+1] = pom; 2 1) Napište program, který načte do vícerozměrného pole znaky - matice typu 5 x 7 náhodně vybrané znaky z ASCII tabulky s ordinálními čísly v intervalu <33; 126>. Pole znaky vypište. 2) Zjistěte počet malých písmen a velkých písmen v poli znaky. 3) Vytvořte jednorozměrné dynamické pole mala podle počtu malých písmen v poli znaky, do kterého uložíte všechna malá písmena z pole znaky. 4) Vytvořte jednorozměrné dynamické pole velka, do kterého uložíte všechna velká písmena z pole znaky. 5) Vytvořte jednorozměrné dynamické pole ostatni a uložte do něj všechny ostatní znaky, která jste neuložili do pole mala ani do pole velka. 6) Všechna pole vypište. 7) Setřiďte pole mala vzestupně a vypište. 8) Pole velka setřiďte sestupně a vypište. 3 1) Napište program, který bude obsahovat definici typu čtvercové matice celých čísel (velikost bude určena konstantou MAX). 2) Načtěte prvky matice náhodnými čísly z intervalu <-20;20>. 3) Vypište matici. 4) Zjistěte kolik je v matici prvků dělitelných číslem 5.

20 5) Přičtěte číslo 10 ke všem prvkům matice na zadaném řádku, který načtete od uživatele. 6) Zaměňte dva zadané řádky v matici. Jejich indexy načtěte od uživatele. 7) Vypočtěte součet prvků na obvodu matice 8) Vypočtěte průměrnou hodnotu prvků hlavní diagonály. 9) Vypište prvky vedlejší diagonály. 10) Vypište matici tak, aby pod hlavní diagonálou byly samé nuly. 4 1) Napište program, který načte náhodná celá čísla do matice celých čísel typu 3 x 4. 2) Zjistěte aritmetický průměr všech prvků této matice. 3) Vytvořte novou matici reálných čísel typu 3 x 4. Do jejich prvků uložte rozdíl příslušného prvku původní matice od aritmetického průměru prvků celočíselné matice.

21 4 Vícerozměrné statické pole a funkce Obsah hodiny Seznámíme se zpracováním vícerozměrných polí ve funkcích. Cíl hodiny Po této hodině budete schopni: co nejvhodněji sestavit hlavičku funkce pro práci s vícerozměrným polem vytvořit funkci pro zpracování vícerozměrného pole správně zavolat funkci pro práci s vícerozměrným polem Klíčová slova Skutečný parametr, formální parametr Podobně jako u jednorozměrných polí nebudeme ve funkci, která pracuje s vícerozměrným polem, vytvářet toto pole duplicitně. Znamenalo by to, že bychom ve funkci museli pole znovu vyalokovat a všechny hodnoty nakopírovat ze skutečného parametru do formálního parametru. Byla by to činnost náročná na čas i paměť. Skutečným parametrem funkce, která zpracovává vícerozměrné pole, je název pole adresa prvního prvku. Formálním parametrem je pointer na pole s uvedeným počtem sloupců. Přesněji jde o název vícerozměrného pole s rozměry, kde první rozměr (závorka [ ]) se zůstává prázdná a druhá dimenze musí být uvedena jako konstanta. Musíme tedy pevně zadat počet sloupců. První rozměr zůstává v zápisu prázdný, protože jde v podstatě o pointer na pole. Můžeme tedy formální parametr zapsat jako pointer na pole. Vytvoříme funkci nacti pro načtení vícerozměrného pole int pole[3][4]. Do funkce tedy budeme posílat jen adresu prvního provku pole, která je uložena v pointeru pole. Ve funkci nacti si uložíme tuto adresu do

22 formálního parametru int p[ ][4], který je ukazatelem na čtyřprvková pole. Může být proto také zapsán (*p)[4]. V našem příkladu jsou tyto pole tři. Tento počet polí pošleme do funkce jako další parametr funkce. Oba ukazatelé pole a p ukazují na první prvek vícerozměrného pole. Pro práci s polem používáne pointer pole ve funkci main a pointer p používáme ve funkci nacti. p Řešení void nacti(int p[ ][4], int radky ); //nebo pointer na pole void nacti(int (*p)[4], int radky ) int main() { int pole[3][4]; nacti(pole,3); return 0; void nacti(int p[ ][4], int radky ) //nebo pointer na pole void nacti(int (*p)[4], int radky ) { int i,j; srand((long)time(null)); for(i=0; i<radky ; i++) for(j=0; j<4; j++) p[i][j]= rand() % 100;

23 Optimální řešení by bylo použití maker bez parametrů konstant pro rozměry vícerozměrného pole, jak je uvedeno v následujícím příkladu. Změnou maker pak změníte velikost pole v celém programu. Vytvořte pro vícerozměrné pole reálných čísel funkci pro výpis pole ve tvaru matice a funkci pro výpočet aritmetického průměru všech prvků pole. #define RADKY 4 #define SLOUPCE 4 //definujeme konstanty pro řádky a sloupce void vypis(float pole[ ][SLOUPCE], int radky); float prumer(float pole[ ][SLOUPCE], int radky); int main( ) { float matice[radky][sloupce]; int i,j; for(i=0;i<radky ;i++) //načtení pole for(j=0;j<sloupce;j++) scanf("%f",&matice[i][j]); vypis(matice, RADKY); //výpis matice printf("prumer prvku matice je: %f", prumer(matice, RADKY)); //volání funkce prumer getch(); return 0; void vypis(float pole[][sloupce],int radky) { int i,j; for(i=0;i<radky;i++) {for(j=0;j<sloupce;j++) printf("%7.2f",pole[i][j]); printf("\n"); //vypsání jednoho řádku //odřádkování

24 float prumer(float pole[][sloupce],int radky) { int i,j; float soucet=0; for(i=0;i<radky;i++) for(j=0;j<sloupce;j++) soucet+=pole[i][j]; //sečtení všech prvků pole return(soucet/(radky*sloupce)); //výpočet průměru Shrnutí kapitoly Skutečným parametrem funkce, která zpracovává vícerozměrné pole, je název pole adresa prvního prvku. Formálním parametrem je pointer na pole s uvedeným počtem sloupců. Jde o název vícerozměrného pole, kde první dimenze (závorka [ ]) se zůstává prázdná a druhá dimenze musí být uvedena jako konstanta. To znamená, že musíme pevně zadat počet sloupců Kontrolní otázky a úkoly 1) Proč posíláme do funkce jen adresu pole? 2) Zapište správně hlavičku funkce, která bude zjišťovat a vracet maximální prvek matice int hodnoty[5][3]. Uveďte i vhodné volání této funkce.

25 5 Vícerozměrné statické pole řešené příklady Obsah hodiny Seznámíme se s tvorbou funkcí pro zpracovávání vícerozměrných statických polí. Cíl hodiny Po této hodině budete schopni: co nejvhodněji sestavit hlavičku funkce pro práci s vícerozměrným polem vytvořit funkci pro zpracování vícerozměrného pole správně zavolat funkci pro práci s vícerozměrným polem Napište program, který bude obsahovat definici typu čtvercové matice celých čísel (velikost bude určena konstantou MAX, kterou si určete sami). Vytvořte funkci, která: 1) Načte matici náhodnými čísly z intervalu <-20;20>. 2) Vypíše matici. 3) Vypíše prvek na daném řádku a daném sloupci (požadovaný řádek a sloupec budou parametry funkce) 4) Vrátí maximální prvek v matici a pomocí parametrů vrátí jeho řádkový a sloupcový index 5) Přičte maximální prvek (zjištěný předchozím podprogramem) ke všem prvkům matice na zadaném řádku (zadaný řádek bude parametrem funkce) 6) Setřídí vzestupně zadaný sloupec matice (zadaný sloupec bude parametrem funkce) 7) Zamění dva zadané řádky v matici, jejichž indexy budou parametry funkce

26 #define MAX 4 void nacti(int pole[][max], int radky); void vypis(int pole[][max], int radky); int prvek(int pole[][max], int r, int s); int maximum(int pole[][max], int radky, int *indexr, int *indexs); void prictimax(int pole[][max], int maxim, int radek); void setrid(int pole[][max], int sloupec); void zamena(int pole[][max], int rad1, int rad2); int main() { int matice[max][max]; int i,j,radek, radek2, sloupec, maxim; srand((long)time(null)); //1) nacti(matice, MAX); //2) vypis(matice, MAX); //3) printf("zadej cislo radku: "); scanf("%d",&radek); printf("zadej cislo sloupce: "); scanf("%d",&sloupec); printf("prvek na %d.radku a %d.sloupci je d.\n\n", radek, sloupec, prvek(matice, radek,sloupec)) //4) maxim=maximum(matice,max,&radek,&sloupec); printf("maximum je %d a je na %d.radku a %d.sloupci.\n\n", maxim,radek, sloupec); //5) printf("zadej cislo radku: "); scanf("%d",&radek); prictimax(matice,maxim,radek); printf("po pricteni maxima k radku %d: \n\n", radek); vypis(matice, MAX); //6) printf("zadej cislo sloupce: ");

27 scanf("%d",&sloupec); setrid(matice,sloupec); printf("po serizeni %d.sloupce: \n\n",sloupec); vypis(matice, MAX); //7) printf("zadej cislo prvniho radku: "); scanf("%d",&radek); printf("zadej cislo druheho radku: "); scanf("%d",&radek2); zamena(matice,radek,radek2); printf("po zamene %d.radku s %d.radkem je pole: \n\n", radek, radek2); vypis(matice, MAX); getch(); return 0; //--------------------------------------------------------------------------- void nacti(int pole[][max],int radky) { int i,j; for(i=0;i<max ;i++) for(j=0;j<max;j++) pole[i][j]= rand() % 41-20; void vypis(int pole[][max],int radky) { int i,j; for(i=0;i<max;i++) { for(j=0;j<max;j++) printf("%5d",pole[i][j]); printf("\n"); int prvek(int pole[][max], int r, int s) {

28 return(pole[r-1][s-1]); int maximum(int pole[][max], int radky, int *indexr, int *indexs) { int i,j,max=-20; for(i=0;i<max ;i++) for(j=0;j<max;j++) if(max < pole[i][j]) { max=pole[i][j]; *indexr=i+1; *indexs=j+1; return max; void prictimax(int pole[][max], int maxim, int radek) { int i; for(i=0;i<max ;i++) pole[radek-1][i]+=maxim; void setrid(int pole[][max], int sloupec) { int i,j,pom; for(i=0;i<max-1;i++) for(j=0;j<max-1;j++) if(pole[j][sloupec-1]<pole[j+1][sloupec-1]) { pom=pole[j][sloupec-1]; pole[j][sloupec-1]=pole[j+1][sloupec-1]; pole[j+1][sloupec-1]=pom;

29 void zamena(int pole[][max], int rad1, int rad2) { int i,pom; for(i=0;i<max ;i++) { pom=pole[rad1-1][i]; pole[rad1-1][i]=pole[rad2-1][i]; pole[rad2-1][i]=pom; Kontrolní otázky a úkoly Vyzkoušejte funkčnost programu v kapitole a doplňte jej další funkce: Vypočte součet prvků na obvodu matice Vypočte průměrnou hodnotu prvků hlavní diagonály Vypíše prvky vedlejší diagonály Vypíše matici tak, aby pod hlavní diagonálou byly samé nuly

30 6 Vícerozměrné statické pole neřešené příklady Obsah hodiny Samostatně vytvoříte funkce pro zpracovávání vícerozměrných statických polí. Cíl hodiny Po této hodině budete schopni: co nejvhodněji sestavit hlavičku funkce pro práci s vícerozměrným polem vytvořit funkci pro zpracování vícerozměrného pole správně zavolat funkci pro práci s vícerozměrným polem 1 Vytvořte program s následujícími úlohami: 1) Do statického pole A pěti celých čísel načtěte pět náhodně vybraných čísel z intervalu <5,20>. 2) Vytvořte funkci pro vypsání pole pěti čísel. Pomocí této funkce vypište pole A. 3) Pomoci pointeru B vytvořte dynamické pole pěti celých čísel. Načtěte do něj prvních pět násobku zadaného čísla (př: zadané číslo 3 -> do pole uložíte čísla 3,6,9,12,15) Pole B vypište pomocí již vytvořené funkce (ad. 2.) 4) Ze zadaných poli vytvořte matici MATICE 5x5 celých čísel. Do matice uložte prvky z pole A (označené A1 až A5) a prvky pole B (označené B1 až B5) podle následujících řádků, kde / znamená celočíselné dělení. A1 A2 A3 A4 A5 B1 B2 B3 B4 B5 A1+B1 A2+B2 A3+B3 A4+B4 A5+B5 A1*B1 A2*B2 A3*B3 A4*B4 A5*B5 A1/B1 A2/B2 A3/B3 A4/B4 A5/B5

31 5) Vytvořte funkci pro vypsání dvourozměrného pole ve tvaru matice. Pomocí této funkce vypište pole MATICE. 6) Pomoci funkce setřiďte sestupně zadaný sloupec matice MATICE. Index sloupce načtěte od uživatele ve funkci main() a pošlete jej do funkce jako parametr. Matici opět vypište. 7) Vytvořte funkci, která bude vracet(!!!) tři hodnoty- minimální sudou hodnotu v matici MATICE a její pozici (číslo řádku i sloupce). Tyto hodnoty vypište ve funkci main(). 2 Vytvořte program s následujícími úlohami: 1) Do statického pole A čtyř reálných čísel načtěte čtyři náhodně vybraná čísla z intervalu <-10,20> (Abyste získali reálnou hodnotu, vygenerujte pomocí rand() číslo z intervalu <-70,140> a vydělte jej číslem 7. Výsledek pak uložte do pole A.). 2) Vytvořte funkci pro vypsání pole čtyř čísel. Pomocí této funkce vypište pole A. 3) Pomoci pointeru B vytvořte dynamické pole čtyř reálných čísel. Načtěte do něj hodnoty od uživatele. Pole B vypište pomocí již vytvořené funkce (ad. 2.) 4) Ze zadaných poli vytvořte matici POLE 6x4 celých čísel. Do matice uložte prvky z pole A (označené A1 až A4) a prvky pole B (označené B1 až B4) podle následujících řádků. A1 A2 A3 A4 B1 B2 B3 B4 A1+B1 A2+B2 A3+B3 A4+B4 A1-B1 A2-B2 A3-B3 A4-B4 A1*B1 A2*B2 A3*B3 A4*B4 A1/B1 A2/B2 A3/B3 A4/B4 5) Vytvořte funkci pro vypsání dvourozměrného pole ve tvaru matice. Pomocí této funkce vypište pole POLE. 6) Pomoci funkce setřiďte vzestupně zadaný sloupec matice POLE. Index sloupce načtěte od uživatele ve funkci main() a pošlete jej do funkce jako parametr. Matici opět vypište.

32 7) Vytvořte funkci, která bude vracet(!!!) tři hodnoty- průměrnou hodnotu a počet záporných čísel v matici POLE a součet všech kladných prvků v matici POLE. Tyto hodnoty vypište ve funkci main(). 3 Napište program, který bude obsahovat definici typu čtvercové matice reálných čísel (velikost bude určena konstantou). Napište funkce, které budou řešit následující operace s maticemi: součet dvou matic součin reálného čísla a matice součin dvou matic. Vytvořte dynamické celočíselné dvojrozměrné pole matice podle zadaných rozměrů od uživatele. Vytvořte dynamické jednorozměrné celočíselné pole radky podle počtu řádků a dynamické jednorozměrné celočíselné pole sloupce podle počtu sloupců. Vytvořte funkci pro naplnění pole matice náhodnými čísly z intervalu <-100,100>. Vytvořte funkci, která uloží do pole radky součty všech prvků v jednotlivých řádcích pole matice. Vytvořte funkci, která uloží do pole sloupce součty všech prvků v jednotlivých sloupcích pole matice. Pomocí funkce vypište pole matice. Pomocí funkce vypište pole radky a pak i pole sloupce.

33 7 Přístup k prvkům vícerozměrného pole Obsah hodiny Seznámíme se s různými možnostmi přístupů k prvkům vícerozměrného statického pole s využitím pointerové aritmetiky. Cíl hodiny Po této hodině budete schopni: využít pointerové aritmetiky k přístupu k prvkům odlišit zápis adres a zápis hodnot prvků vícerozměrného pole. Při užití pointerové aritmetiky v jednorozměrném poli jsme si vysvětlili, že v jednorozměrném poli int p[5] můžeme hodnotu druhého prvku získat pomocí zápisu p[1] nebo *(p+1). Tyto dva zápisy jsou ekvivalentní. Totéž bude samozřejmě platit i ve vícerozměrných polích. Ve vícerozměrných polích popisujeme prvky pomocí dvou indexů řádek a sloupec např. p[2][3] je prvek na třetím řádku a čtvrtém sloupci. Proto využití pointerové aritmetiky budeme moci využít pro oba indexy. Všechny možnosti zápisů adres i hodnot vícerozměrného pole si předvedeme na příkladu pole int p[3][4]. Adresy jednotlivých řádku resp. adresy prvních prvků na řádku můžeme popsat těmito pointery: p[0] adresa prvního řádku p[1] adresa druhého řádku p[2] adresa třetího řádku Ekvivalentní zápisy jsou *(p+0), *(p+1), *(p+2). Pokud zapíšeme p[2]+1 znamená to adresa třetího řádku plus dna prvky typu int. Jde tedy o adresu druhého prvku na třetím řádku. Pokud rozepíšeme adresu třetího řádku pomocí pointerové aritmetiky, získáme ekvivalentní zápis adresy druhého prvku na třetím řádku *(p+2)+1. Další zápis téže adresy je &p[2][1].

34 Podobně můžeme přepsat i hodnoty prvků ve vícerozměrném poli. Vezměme si například čtvrtý prvek v druhém řádku p[1][3], který můžeme také zapsat zápisem *(p[1]+3). Tento zápis můžeme číst jako hodnota na adrese druhého řádku posunuté o tři prvky int. Pokud rozepíšeme i řádkový index pomocí pointerové aritmetiky, získáme další ekvivalentní zápis *((p+1)+3). Přehledný popis zápisu adres i hodnot prvků vícerozměrného pole int p[3][4] najdete v následující obrázku. HODNOTY ADRESY Otestujte následující program a překontrolujte výpisy hodnot i adres prvků.

35 #include <stdio.h> main() { int x[3][4]={{1,2,3,4,{4,5,6,7,{7,8,9,0; int i,j; for (i=0;i<3;i++) { for (j=0;j<4;j++) printf(" %d",x[i][j]); printf(" \n"); printf(" \n\nadresy \n"); for (i=0;i<3;i++) { for (j=0;j<4;j++) printf(" %p",&x[i][j]); printf(" \n"); printf(" \n\nadresy \n"); printf(" Prvni v prvnim radku : %p %p %p %p \n", &x[0][0], x[0], *x, x); printf(" Druhy v prvnim radku : %p %p %p \n", &x[0][1], x[0]+1, *x+1 ); printf(" Prvni v druhem radku : %p %p %p \n", &x[1][0], x[1], *(x+1)); printf(" Treti v druhem radku : %p %p %p \n", &x[1][2], x[1]+2, *(x+1)+2); printf(" Prvni v tretim radku : %p %p %p\n", &x[2][0], x[2], *(x+2)); printf(" \n\nhodnoty \n"); printf(" Prvni v prvnim radku: %d %d %d \n", x[0][0], *(x[0]),*(*x)); printf(" Druhy v prvnim radku:%d %d %d \n", x[0][1], *(x[0]+1), *(*x+1)); printf(" Prvni v druhem radku: %d %d %d \n", x[1][0], *(x[1]), *(*(x+1))); printf("treti v druhem radku: %d %d %d \n",x[1][2],*(x[1]+2),*(*(x+1)+2)); printf(" Prvni v tretim radku: %d %d %d \n", x[2][0], *(x[2]), *(*(x+2))); getch(); return 0;

36 Shrnutí kapitoly Pointerovou aritmetiku můžeme použít pro zápis adres i hodnot prvků ve vícerozměrném poli. Využíváme toho, že zápis p[i] je ekvivalentní zápisu*(p+i), který ve vícerozměrném poli znamenají adresu i-tého řádku. Od tohoto zápisu se pak odvíjí všechny další zápisy. Kontrolní otázky a úkoly 1) V poli float pole[5][4] vypište všemi způsoby adresu třetího prvku na čtvrtém řádku a adresu prvního prvku na páté řádku. 2) V poli char znaky[4][10] vypište všemi způsoby hodnotu osmého prvku v druhém řádku a hodnotu prvního prvku na čtvrtém řádku.

37 8 Pole pointerů Obsah hodiny Seznámíme se s polem pointerů jedné z možností tvorby dynamického vícerozměrného pole. Cíl hodiny Po této hodině budete schopni: vytvořit dynamické vícerozměrné pole pomocí pole pointerů popsat tvorbu dynamického vícerozměrného pole pole pointerů Klíčová slova Dynamické vícerozměrné pole, pole pointerů V následujících kapitolách se seznámíme s třemi možnostmi vytvoření vícerozměrného dynamického pole. První možností je pole pointerů, kterou si předvedeme a popíšeme na praktickém příkladě. Deklarace int *p[3]; vytvoří v zásobníku pole tří pointerů, tzn. tříprvkové pole, jehož prvku jsou pointery, které mohou ukazovat na celá čísla. Tyto tři pointery jsou ukazatele na jednotlivé řádky budoucího vícerozměrného pole. Proto konstanta 3 uvedena v deklaraci int *p[3]; představuje počet řádků vícerozměrného pole, který musí být uvedena a musí být znám před překladem.

38 Pro tyto tři pointery vyblokujeme v haldě jednotlivé řádky. Počet prvků v každém řádku může zadat i uživatel až za běhu programu. p[0]=(int*)malloc(sizeof(int)*5); Příkaz malloc vyblokuje pět prvků v haldě, jejichž adresu uloží do pointeru p[0]. Těchto pět prvků tvoří první řádek vícerozměrného pole. Podobně alokujeme prvky dalších dvou řádků. p[1]=(int*)malloc(sizeof(int)*3); p[2]=(int*)malloc(sizeof(int)*4); Z obrázku je zřejmé, že řádky se nealokují za sebou v souvislém bloku, jako to bylo u statického vícerozměrného pole. Přístup k prvkům pole je však neliší.

39 p[0][2]=64; p[1][0]=57; Po využití dynamického vícerozměrného pole musíme odalokovat prvky, které jsme vyalokovali pomocí malloc. free(p[0]); Odalokuje prvky prvního řádku. V pointeru p[0] zůstane adresa prostoru v paměti, kde byl první řádek alokován. Proto abychom smazali i tuto adresu, pointer zakotvíme. p[0]=null; Totéž provedeme i s ostatními řádky. Můžeme také využít cyklus for.

40 for(i=0;i<3;i++) { free(p[i]); p[i]=null; Poté zůstane v zásobníku jen původní pole tří pointerů, které jsme nealokovali pomocí malloc a které se odalokuje na konci funkce. Shrnutí kapitoly Dynamické vícerozměrné pole můžeme vytvořit pomocí pole pointerů. Musím před překladem znát počet řádků. Každý řádek může mít jiný počet prvků, který můžeme načíst i od uživatele za běhu programu. Jednotlivé řádky se nealokují v jednom bloku za sebou. Práce s prvky pole je stejná jako u statického pole. Na konci musíme jednotlivé řádky odblokovat. Kontrolní otázky a úkoly 1) Popište samostatně postup tvorby vícerozměrného pole pomocí pole pointerů. 2) Zakreslete postup tvorby pole pointerů.

41 9 Pointer na pole Obsah hodiny Seznámíme se s pointrem na pole další možností tvorby dynamického vícerozměrného pole. Cíl hodiny Po této hodině budete schopni: vytvořit dynamické vícerozměrné pole pomocí pointeru na pole popsat tvorbu dynamického vícerozměrného pole pointer na pole Klíčová slova Pointer na pole Pokud známe před překladem počet sloupců vícerozměrného pole, můžeme využít tvorbu tohoto pole pomocí pointeru na pole. Deklarace int (*p)[4]; vytvoří v zásobníku pointer, který může ukazovat na pole čtyř celočíselných prvků. Kolik těchto polí bude, tedy kolik řádků bude mít naše vícerozměrné pole, můžeme načíst i od uživatele za běhu programu. Vícerozměrné dynamické pole musíme alokovat v haldě pomocí příkazu malloc. počet sloupců p=(int(*)[4])malloc(sizeof(int)*3*4); počet řádků

42 Tímto příkazem chceme vyalokovat pole o třech řádcích pro čtyři prvky na každém řádků. Proto díky parametru sizeof(int)*3*4 vyalokuje příkaz malloc dvanáct celých čísel v haldě. Pomocí (int(*)[4]) přetypujeme ukazatel na typ void, který vrací příkaz malloc, na ukazatel na ukazatel na pole čtyř celých čísel. V paměti se vyblokuje souvislý blok dvanácti prvků, který je velmi podobný vícerozměrnému statickému poli. Prvky pole v tomto případě jsou však alokovány v haldě. K prvkům pole přistupujeme stejně jako u statického vícerozměrného pole. p[0][2]=64; p[1][0]=57; Můžeme využít souvislého bloku a zapisovat do pole i takto. p[0][6]=39; Před ukončením práce s tímto polem musíme opět odalokovat prvky, které jsme alokovali pomocí příkazu malloc. free(p); V haldě se odalokuje paměť pro dvanáct prvků pole. V pointeru p však zůstane adresa místa, kdy byly prvky alokovány.

43 Toto adresu zrušíme zakotvením pointeru p. p=null; Pointer p se odalokuje automaticky s ukončením bloku či funkce, kde byl deklarován. Shrnutí kapitoly Pro tvorbu dynamické vícerozměrné pole, u kterého známe před překladem počet sloupců pole, použijeme typ pointer na pole. Deklarací int (*p)[4]; vyalokujeme pointer na čtyřprvková pole. Počet těchto polí tzn. počet řádků, můžeme zadat až za běhu programu. Prvky pole se alokují v haldě jako souvislý blok. Práce s prvky pole je stejná jako u statického pole. Na konci musíme prvky pole odalokovat. Kontrolní otázky a úkoly 1) Popište samostatně postup tvorby vícerozměrného pole pomocí pointeru na pole. 2) Zakreslete postup tvorby vícerozměrného dynamického pole pointer na pole.

44 10 Pointer na pointer Obsah hodiny Seznámíme se tvorbou vícerozměrného dynamického pole pomocí pointeru na pointer. Cíl hodiny Po této hodině budete schopni: vytvořit dynamické vícerozměrné pole pomocí pointeru na pointer popsat tvorbu dynamického vícerozměrného pole pointer na pointer Klíčová slova Pointer na pointer Pointer na pointer je možnost tvorby vícerozměrného dynamického pole, kdy před překladem nevíme ani počet řádků ani počet sloupců. Oba rozměry pro toto vícerozměrné pole můžeme načíst od uživatele až za běhu programu. Deklarace int **p; vytvoří v zásobníku jediný pointer, který může ukazovat na další pointer na datový typ int. Nejprve musíme alokovat pole pointerů, které budou pointery na jednotlivé řádky vícerozměrného dynamického pole. p=(int**)malloc(sizeof(int*)*3); Alokujeme tři pointery. Proto parametrem malloc je sizeof(int*)*3. Ukazatel na void, který vrací malloc musíme přetypovat pomocí (int**) na pointer na pointer na celočíselný typ, aby pravá a levá strana příkazu byla kompatibilní.

45 Nyní budeme alokovat jednotlivé řádky. Počet prvků na řádku můžeme načíst od uživatele. p[0]=(int*)malloc(sizeof(int)*5); Podobně alokujeme další řádky. Pro alokaci můžeme využít i cyklus for. p[1]=(int*)malloc(sizeof(int)*3); p[2]=(int*)malloc(sizeof(int)*4);

46 Řádky tohoto pole nejsou alokovány v souvislém bloku. Práce s prvky pole se opět neliší od práce s prvky statického vícerozměrného pole. p[0][2]=64; p[1][0]=57; Při odalokaci pole musíme postupovat v opačném pořadí. Nejprve musíme odalokovat jednotlivé řádky a pak teprve pole pointerů. Pro odalokaci řádků můžeme opět použít cyklus for. for(i=0;i<3;i++) { free(p[i]); p[i]=null; V paměti zůstane jen pole pointerů, které jsme alokovali jako první. Toto pole odalokujeme příkazy: free(p); p=null;

47 Shrnutí kapitoly Pro tvorbu dynamické vícerozměrné pole, u kterého neznáme před překladem ani počet sloupců ani počet řádků pole, použijeme typ pointer na pointer. Deklarací int **p; vyalokujeme pointer na pointer. Počet řádků i počet sloupců můžeme načíst od uživatele až za běhu programu. Nejprve vyblokujeme pole pointerů, které budou ukazovat na jednotlivé řádky. Pak alokujeme jednotlivé řádky. Řádky pole se nealokují v haldě za sebou jako souvislý blok. Práce s prvky pole je stejná jako u statického pole. Na konci práce s polem musíme prvky pole odalokovat v opačném pořadí, než v jakém jsme pole alokovali tzn. nejprve odalokujme řádky a nakonec odalokujeme pole pointerů. Kontrolní otázky a úkoly 1) Popište samostatně postup tvorby vícerozměrného pole pomocí pointeru na pointer. 2) Zakreslete postup tvorby vícerozměrného dynamického pole pointer na pointer.

48 11 Vícerozměrné dynamické pole shrnutí, příklady Obsah hodiny Shrneme vlastnosti statických i dynamických vícerozměrných polí. Vyzkoušíme si jednotlivé typy dynamických vícerozměrných polí na příkladech. Cíl hodiny Po této hodině budete schopni: popsat shodné a rozdílné vlastnosti statických i dynamických vícerozměrných polí vhodně vybrat typ dynamického vícerozměrného pole pro zadanou úlohu použít vícerozměrné dynamické pole v příkladech 11.1 Porovnání vícerozměrných polí Z předchozích kapitol jste zjistili, že přístup k prvkům vícerozměrných polí je shodný, ať se jedná o statické vícerozměrné pole nebo o dynamické vícerozměrné pole. Možná jste si také všimli, že některé části statických a dynamických vícerozměrných polí se alokují v paměti podobně. Statické vícerozměrné pole a dynamické pole pointer na pole se alokují jako souvislý blok paměti. Pro dynamické pole alokujeme prvky pole pomocí malloc a jsou alokovány v haldě. U statického pole se tyto prvky alokují v zásobníku stejně jako ukazatel na první prvek pole. Dynamická vícerozměrná pole vytvořená pomocí pole pointerů a pomocí pointer na pointer jsou také velice podobná. Všechny prvky polí jsou alokovány v haldě a nejsou alokovány jako souvislý blok. U pointeru na pointer alokujeme v haldě i adresy jednotlivých řádků prvky pole pointerů. Společné a rozdílné vlastnosti alokace jsou zobrazeny v následujícím obrázku.

49 11.2 y Realizujte pomocí vhodného dynamického vícerozměrného pole následující úkol: Místní dopravce má 4 garáže a v nich nákladní auta stejné značky i modelu. Do každé garáže se vejde maximálně 6 aut, ale ne všechny stání v garáži jsou zaplněny. Dopravce sleduje stav nádrže svých aut. Vytvořte program a datovou strukturu pro toto sledování. Při zadávání počtu aut v jednotlivých garážích spolupracujte s dopravcem (uživatelem). Uvažujte zda si informace o zaplněnosti jednotlivých garáží neuložíte do pomocného jednorozměrného pole. Načtěte aktuální stavy nádrží v jednotlivých zaparkovaných aut, maximum je 50litrů. (Pomožte si náhodně generovanými čísly.) Vypište přehledně stavy nádrží. (Vytvořte si funkci pro tento výpis.)

50 Všem autům, které mají méně než polovinu nádrže dotankujte nádrž do plna a zjistěte kolik litrů paliva bylo k tomuto třeba. (Opět si vytvořte na tuto činnost funkci, která počet litrů dotankovaného paliva bude vracet) Vypište opět pole a zkontrolujte správné stavy nádrží. Přeparkujte auta v jednotlivých garážích tak, aby ty s největším množstvím paliva stály hned vepředu a ty s nejméně množstvím paliva vzadu. Pole vytiskněte a zkontrolujte, zda se Vám přeparkování podařilo. Řešení #include <stdio.h> #include <stdlib.h> //--------------------------------------------------------------------------- void info(int **pole,int pole2[]); int palivo (int **pole,int pole2[]); void preparkovani (int **pole,int pole2[]); //--------------------------------------------------------------------------- int main() { int *pole[4],pole2[4],i,j,pal; srand((long)time(null)); for (i = 0; i < 4; i++) { printf ("Zadej pocet aut v %d garazi\n",i+1); scanf ("%d",&pole2[i]); pole[i]=(int*)malloc(sizeof(int)*pole2[i]); printf ("v %d garazi je %d aut\n",i+1,pole2[i]); for (i = 0; i <4 ; i++) for (j = 0; j <pole2[i]; j++) pole[i][j]=rand () % 100; info(pole,pole2); pal=fuel(pole,pole2); printf ("Celkove jsme dotankovali %d procent paliva\n",pal); info(pole,pole2); preparkovani(pole,pole2); printf ("\n");

51 printf ("Po preparkovani \n"); printf ("\n"); info(pole,pole2); getchar(); for(i=0;i<4;i++) free(pole[i]); //--------------------------------------------------------------------------- void info(int **pole,int pole2[]) { int i,j; for (i = 0; i < 4; i++) { printf ("Dalsi garaz\n"); for (j = 0; j <pole2[i]; j++) printf ("V %d. aute v %d. garazi je %d %% paliva\n\n", j+1,i+1,pole[i][j]); //--------------------------------------------------------------------------- int fuel (int **pole,int pole2[]) { int i,j,fuel=0; for (i = 0; i < 4; i++) for (j = 0; j <pole2[i]; j++) if(pole[i][j]<50) { fuel=fuel+(100-pole[i][j]); printf ("V %d. aute v %d. garazi bylo mene nez 50 %% paliva\n Třeba dotankovat %d procent\n\n",j+1,i+1,(100-pole[i][j])); pole[i][j]=100; return (fuel); //--------------------------------------------------------------------------- void preparkovani (int **pole,int pole2[]) { int i,j,pom,k; for(i=0; i<4;i++) for(k=0; k<pole2[i]-1;k++)

52 for(j=0; j<pole2[i]-1;j++) if(pole[i][j]<pole[i][j+1]) { pom=pole[i][j]; pole[i][j]=pole[i][j+1]; pole[i][j+1]=pom; Upravte předchozí program tak, aby jej mohli použít i dopravcovi konkurenti, kteří mají variabilní počet garáží. Shrnutí kapitoly K prvkům statického vícerozměrného pole i k prvkům dynamického vícerozměrného pole přistupujeme stejně. Podobně jsou také v paměti alokovány vícerozměrné pole statické a dynamické pole pointer na pole jde o souvislý blok v paměti. Druhá dvojice podobných alokací dynamických vícerozměrných pole je pointer na pole a pointer na pointer, která se nealokují jako souvislý blok a pro pointer na pointer se alokuje v haldě i pole pointerů, které ukazují na jednotlivé řádky pole.

53 Kontrolní otázky a úkoly 1) Napište program, ve kterém vytvoříte dynamické vícerozměrné celočíselné pole pomocí pointeru na pointer pro zadaný počet řádků a zadaný počet sloupců. Načte matici čísly z intervalu <-10;10>. Vypište matici. Vypočtěte součet prvků na hlavní diagonále. Vypište prvky na vedlejší diagonále. Vytvořte podprogram, který vrátí adresu maximálního prvku na zadaném řádku. Zadaný řádek bude parametrem funkce. Ve funkci main vypište nalezenou adresu i hodnotu na této adrese. 2) Napište program, ve kterém vytvoříte dynamické vícerozměrné znakové pole pomocí pointeru na pole pro zadaný počet řádků a 3 sloupce. Načte matici znaky načtenými z klávesnice. Vypište matici. Vypište všechna malá písmena z matice. Všechna velká písmena v matici přepište odpovídajícími velkými písmeny. 3) Setřiďte zadaný sloupec vzestupně podle ordinálních hodnot znaků. Napište program, ve kterém vytvoříte dynamické vícerozměrné reálné pole pointerů na pole pro 4 řádky a postupně pro 4, 3, 2, 1 sloupce. Př. : 5 5 5 5 5 5 5 5 5 5 Načte matici reálnými čísly načtenými z klávesnice. Vypište matici ve tvaru horní trojúhelníkové matice (viz. Př.). Vypište minimální hodnotu v matici, její řádkový i sloupcový index. Zaměňte nalezenou minimální hodnotu v matici za prvek na zadaném řádku a zadaném sloupci.

54 12 Řetězce deklarace Obsah hodiny Seznámíme se způsoby definování řetězců a s jejich použití v programech. Cíl hodiny Po této hodině budete schopni: popsat rozdíl mezi znakem a řetězcem nadeklarovat statickou proměnnou typu řetězec vytvořit dynamickou proměnnou typu řetězec Klíčová slova Statický řetězec, dynamický řetězec, ukončení řetězce \0 Pro řetězce nemá jazyk C speciální datový typ. Řetězec je jednorozměrné pole znaků a jako pole se deklaruje a jako s polem se s ním pracuje. Každý řetězec však musí být ukončen znakem EOS (end of string), což je znak s hodnotou nula v ASCII tabulce. Proto se také zapisuje \0. Hodnoty za tímto znakem se při běžné práci s řetězci nevyužívají. Délka řetězce je tedy omezena pouze velikostí paměti, kterou pro řetězec můžeme alokovat. Řetězce používáme již od začátku programování v jazyce C bez toho, že bychom se řetězcích dříve zmiňovali. Například pokud chceme vypsat na obrazovku informaci pro uživatele, použijeme příkaz printf, jehož prvním parametrem je řetězec. Každý konkrétní řetězec musíme označit uvozovkami. Je důležité uvědomit si rozdíl mezi znaky a řetězci. Znaky zapisujeme do apostrofů a překladač tak informujeme o tom, že budeme používat jediný znak. Jazyk C dále nepracuje přímo s tímto znakem, ale s jeho hodnotou c ASCII tabulce celým číslem.

55 Pokud tedy zapíšeme písmeno a do apostrofů, zapsali jsme jediný znak typu char. Tento znak zabere v paměti jeden Byte. Jestliže zapíšeme znak a do uvozovek, zapsali jsme řetězec. Ten zabere v paměti dva Byte, protože musíme započítat také ukončovací znak \0. Na následujících příkladech si ukážeme možnosti deklarace řetězců proměnných typu řetězec. y deklarace statických řetězců char a[5]; Deklarujeme řetězec, který může obsahovat nevýše 4 znaky. Poslední znak řetězce musí být znak \0. Tímto se pozná, kde řetězec končí. Například po uložení řetězce ahoj bude řetězec a v paměti vypadat takto: Můžeme také řetězce při deklaraci inicializovat. char b[6]= Ahoj ; char b[ ]= Ahoj ; Velikost řetězce není v deklaraci uvedena. Je doplněna podle délky řetězce, kterým řetězec při deklaraci inicializujeme. char d[ ]={ A, h, o, j, \0 ;

56 Velikost opět není uvedena. Řetězec je zadán pomocí jednotlivých písmen, proto v tomto zadání nesmíme zapomenout na ukončovací nulu. y deklarace dynamického řetězce char *a; Deklarujeme jen ukazatel na znaky. Samotný řetězec musíme vyalokovat v haldě. a = (char*)malloc(sizeof(char)*5); Všimněte si, že se alokace dynamického řetězce neliší od alokace statického pole. Jediným rozdílem je umístění prvků řetězce u statického řetězce jsou v zásobníku a u dynamického řetězce jsou v haldě. Také se nijak neliší práce s dynamickým a statickým řetězcem. Práci s dynamickým řetězcem nebudeme tedy v dalším textu Shrnutí kapitoly Řetězec je jednorozměrné pole znaků ukončené znakovou nulou \0. Řetězce zapisujeme do uvozovek. Deklarace řetězců jsou shodné s deklarací jednorozměrného pole. Práce s dynamickým i statickým řetězcem je stejná. Kontrolní otázky a úkoly 1) Co je to řetězec? 2) Jak poznáme konec řetězce? 3) Jaký je rozdíl mezi statickým a dynamickým řetězcem?

57 13 Řetězce základy práce Obsah hodiny Seznámíme se se základy práce a zpracování řetězců. Cíl hodiny Po této hodině budete schopni: načíst a vypsat vhodným způsobem řetězec zapsat do řetězcové proměnné konkrétní řetězec Klíčová slova Načtení řetězce, výpis řetězce, bílé znaky, čtecí buffer V předchozí kapitole jsme si řekli, že řetězec je pole znaků, které jsou zakončeny \0 tzv. znakovou nulou. Pokud bychom zapomněli zapsat ukončovací znak řetězce \0 nebo bychom si jej smazali, byl by za řetězec považován celá obsah paměti všechny znaky až do výskytu první ukončovací nuly. 13.1 Načtení řetězce Formátované načítání řetězce provádíme příkazem scanf. char retez[10]; scanf( %s,retez); %s je formát pro čtení i vypisování řetězce. Není potřeba před názvem řetězce retez psát adresní operátor &, protože název řetězce je adresou prvního znaku řetězce. Proto scat ví na jakou adresu uživatelem zadaný řetězec uložit. Znak \0 je uložen na konec zadaného řetězce automaticky uživatel jej nemusí psát. V jazyce C nejsou kontrolovány meze polí tedy ani řetězců. Do našeho řetězce retez může uložit nejvýše 9-ti znakový řetězec. Posledním znakem bude \0. Pokud uživatel zadá delší řetězec, nebude hlášena chyba. Zadaný řetězec se bude zapisovat dále do paměti, která je za

58 řetězcem retez a která není vyalokovaná. Příkazem scanf můžeme kontrolovat počet načtených znaků. char retez[10]; scanf( %9s,retez); Tento příkaz načte prvních 9 znaků a ostatní zůstanou v čtecím bufferu. Znak \0 bude opět zapsán na konec řetězce automaticky. Pokud cokoliv zůstane ve čtecím bufferu, musíme čtecí buffer vyčistit pomocí následujícího cyklu. while (getchar()!= \n ); Cyklus načítá znaky až do nalezení znaku \n, znaky nikam neukládá, jen je načítá z čtecího bufferu. Nevýhodou příkazu scanf je, že nečte bílé znaky, anglicky white spaces, což jsou znaky, které nejsou vidět na obrazovce. Jsou to oddělovací znaky jako mezera, tabulátor, nový řádek a podobně. Jestliže uživatel zadá dvě slova oddělená mezerou, načte příkaz scanf první slovo a mezera i další slovo zůstanou ve čtecím bufferu, který opět budeme muset vyčistit. Načítání řetězce s bílými znaky řeší příkaz gets. char retez[10]; gets(retez); Příkaz gets načte řetězec až do zadání enter, který se neuloží, ale nahradí se znakem \0. Příkaz gets čte bíle znaky a nekonroluje meze řetězce. 13.2 Výpis řetězce Řetězce vypisujeme pomocí příkazu printf nebo pomocí příkazu puts. Oba nemají problém s bílými znaky, oba vypisují znaky z řetězce až to nalezení znaku \0. char retez[ ]= PRG je fajn! ; puts(retez); printf( %s,retez); V příkazu printf nepíšeme *a, protože %s nese informaci, že budeme vypisovat řetězec, který je zadáván svou adresou.