====== Pole ====== Pole je datový typ skládající se z určitého počtu jiných datových typů. Zatím jsme se s poli setkali jen jako s řetězci (řetězec je pole jednotlivých znaků, pole končí znakem s ASCII hodnotou \x00). Nejlepší bude, pokud si to vysvětlíme na jednoduchém příkladu. Například budeme potřebovat uložit 10 čísel int, které budou všechny sloužit k podobnému účelu, ale je možné, že se jejich počet bude v budoucnosti měnit, nebo jsme líní pro je jednotlivě deklarovat (a byli bysme hloupí, kdybychom to tak dělali). Použijeme tedy např. tuto deklaraci: int cisla[10]; Tím jsme poprosili systém o 10*sizeof(int) bytů (neboli paměť potřebnou pro uložení 10 integerů, typicky to bude 20B). Nyní můžeme s čísli jednoduše pracovat, musíme si však pamatovat, že ačkoli jsme nadeklarovali 10 integerů, k prvnímu přistupujeme pomocí [0] a k desátému pomocí [9], proč tomu tak je si vysvětlíme za chvilku. ===== Příklad ===== int cisla[10], a = 2; cisla[0] = 1; cisla[1] = 2; cisla[a] = cisla[0]*cisla[1]+cisla[2]; cisla[2]++; //promenna cisla[2] drzi nyni hodnotu 5 cisla[10] = 18; //Zde by zase pravděpodobně došlo k pádu programu, protože se pokoušíme přistupovat k neexistující 11. položce pole. ===== Uložení pole v paměti ===== držme se naší deklarace z předchozího příkladu, tedy: int cisla[10]; V tom případě jsme si říkali, že bude v paměti alokováno 10*sizeof(int) bytů, to bude vypadat následovně: __ __ __ __ __ __ __ __ __ __ |00|00|00|00|00|00|00|00|00|00| -- -- -- -- -- -- -- -- -- -- ^ ^ |_ Toto je adresa &cisla |_ Toto je adresa &cisla+9*sizeof(int) (neboli cisla[9]) (neboli cisla[0]) Pokud si tedy zkusíme vytisknout printf("%d\n", &cisla);, získáme adresu v paměti (to dělá operátor &), na které je naše pole uložené, touto adresou je obyčejné číslo, je ale zvykem zapisovat ho šestnáctkově, toto je pro nás ale zatím dostačující. Tím, že použijeme zápis cisla[0] dojde k tomu, že získáme přístup k sizeof(int) bytům na adrese &cisla, tedy k prvnímu integeru, když chceme přistupovat k druhému integeru v poli použijeme cisla[1], protože tím se dostáváme z adresy &cisla o jeden int dále (tedy: &cisla+1*sizeof(int)), je tedy zřejmé, že pokud se pokusíme pracovat s cisla[10], octneme se již v části paměti, která nepatří našemu programu a náš program bude ukončen, protože v jiném případě by náš program mohl ovlivňovat práci jiného programu. ===== Zjištění velikosti pole ===== Je možné, že neznáme velikost pole, a potřebujeme ho zpracovat (např. v cyklu), k tomu opět použijeme operátor sizeof(). V následujícím příkladu si také můžete všimnout, že při deklaraci pole můžeme jeho velikost určit jinou celočíselnou proměnnou (to je možné až v novějších verzích jazyka C). Následující kus kódu ukazuje, jak zjistit a vypsat velikost pole. int i = 30; int cisla[i]; //Nejaky jiny kod printf("Pocet cisel: %d\n", sizeof(cisla)/sizeof(int)); Příkaz sizeof(cisla) nám vrátí počet bytů, které pole skutečně zabírá v paměti, to může být různé. nás ale zajímá kolik prvků (int) pole má a s kolika můžeme ve skutečnosti pracovat. K tomu musíme ještě toto číslo vydělit hodnotou sizeof(int) (nebo sizeof(jiny_typ_naseho_pole)), ta totiž určuje, kolik každý prvek pole zabírá v paměti. Když si to shrneme: Víme, kolik místa zabírá pole v RAMce a víme, kolik má zabírat jeden jediný prvek, jednoduše tedy vydělíme (vrátíme se ve vzpomínkách do 2. třídy ZŠ ;) a máme požadované číslo, pokud nás ovšem zajímá nejvyšší "offset" (to číslo v hranatých závorkách), jaké můžeme použít, nesmíme ještě zapomenout odečíst 1. ===== N-rozměrná pole ===== Můžeme také vytvářet mnohorozměrná pole (např.: dvou-rozměrná, tří-rozměrná, sto-rozměrná, n-rozměrná), takové mnohorozměrné pole je laicky řečeno pole polí, nebo pole polí polí polí polí, typickým příkladem je pole řetězců. Deklarace takového pole může vypadat takto: int a[3][40]; //a je pole 40ti polí o 3 integerech //Podobná pole si většinou představujeme jako 3x40 čtverečků (40 je výška) char c[4][6][8]; //Takové pole si pro změnu můžeme vizualizovat jako 8mi patrový kvádr, přičemž každé patro se zkládá z 4x6 kostiček (každá kostička drží nějaký znak). U složitějších polí si můžeme představit například několik takových kvádříků uspořádaných do několika polic v několika skříních v několika řadách,... Prostě jakkoli. Pokud máme například pole int pole[2][3], pak pole[0] je pole 3 integerů jako např. int druhe[3]. Ostatní práce s poli je naprosto analogická k polím jednorozměrným. ===== Řešený příklad - zpracování pole v cyklu ===== Toto je velmi často používaná věc! Více se dozvíte v kapitole "podmínky a cykly", tady jen uvádím jednoduchý příklad. Můžeme si zde všimnout dvou totožných cyklů, přičemž jeden je while() a druhý for(). /* arrays.c * Napiste program, ktery naplni pole integeru nahodnymy cisly a potom je vypise. * Pouzijte cykly for i while */ #include #include int main() { int i, cisla[10]; i=0; while(i ===== Samostatná cvičení ===== * Pomocí dvou vnořených cyklů naplňte dvojrozměrné pole znaků (char[x][y]) šachovnicí (8x8) z 1 a 0, pomocí dalšího vnořeného cyklu ji pak vytiskněte * Velikost šachovnice bude možno libovolně měnit pomocí dvou proměnných (int x = 8, y = 8;). * Očekávaný výsledek: 01010101 10101010 01010101 10101010 01010101 10101010 01010101 10101010 * Upravte program z předchozího cvičení tak, aby byly protilehlé rohy spojeny osmičkami. * Upravte program z předchozího cvičení tak, aby byl čtverec lemován nulami. *Očekávaný výsledek: 00000000 08101080 01810800 00188010 01088100 00801810 08010180 00000000