Vo všetkých prípadoch, ktoré sa doteraz vyskytli, sme pracne museli všetky premenné deklarovať jednu po druhej. Našťastie sme tých premenných zatiaľ nemuseli používať zvlášť veľa. Predstavte si ale, že by sme potrebovali deklarovať tisíc premenných typu int. Napísať tisíc deklarácií by bolo náročné na čas a vymyslieť tisíc názvov pre premenné náročné na prehľadnosť. A preto ľudia vymysleli polia.
Pole tisícich premenných typu int sa deklaruje ľahko. Stačí do deklarácií napísať int a[1000]; a máme 1000 int-ov k dispozícií. Premenné máme očíslované od 0 do 999 (číslovanie polí v jazyku C začína vždy od 0). Keď chceme napríklad do premennej číslo 28 vložiť hodnotu 9, spravíme to príkazom a[28] = 9; (Samozrejme, pole sa vôbec nemusí nazývať a. Voľba názvu je na vás.)
Použitie polí si ukážeme na známom algoritme "Eratostenovo sito", s pomocou ktorého nájdeme všetky prvočísla menšie ako tisíc. Bude fungovať takto: Spravíme si pole int-ov, ktoré bude mať 1000 prvkov. Ak bude na danom čísle uložená jednotka, znamená to, že číslo je prvočíslo. Ak tam bude nula, znamená to, že prvočíslo nie je. Tento stav dosiahneme nasledovne: Najprv celé pole naplníme jednotkami. Do premenných č. 0 a 1 vložíme nuly (0 ani 1 nie sú prvočísla). Potom prebehneme celé pole od začiatku do konca a keď niektoré číslo vyzerá byť prvočíslo (teda je na ňom nastavená jednotka), tak všetkým jeho násobkom nastavíme, že prvočísla nie sú -- na patričné miesta vložíme nuly. Naprogramované to vyzerá takto (nezabudnite pridať štandardnú omáčičku):
int pole[1000]; int i, k; for( i = 0; i < 1000; i++) pole[i] = 1; pole[0] = 0; pole[1] = 0; for( i = 0; i < 1000; i++) { /* ak je to prvocislo, vypisat a nasobky vynulovat */ if (pole[i] == 1) { printf("%d\n",i); for( k = 2*i; k < 1000; k = k + i ) pole[k] = 0; } }
Úloha č.1 Pochopte, napíšte, skompilujte. Zvlášť dobre si pozrite ten cyklus, ktorý je riadený premennou k a ktorý nuluje násobky nájdeného prvočísla. (To prvočíslo je i, lebo pole[i] je jednotka.)
Polia napodiv veľmi úzko súvisia so smerníkmi. Keď programu poviem, že budem používať pole pole[1000], tak sa mi v pamäti nevytvorí miesto pre toto pole len tak náhodne. Všetky premenné sú v pamäti uložené pekne za sebou. A premenná pole (bez hranatých zátvoriek) je smerník, ktorý ukazuje, kde táto oblasť začína. Takže ak spravím niečo takéto:
int a[10]; *a = 5; printf("%d\n",a[0]);program mi vypíše 5. Výraz *a znamená presne to isté ako a[0]. Aj k ďalším prvkom poľa môžeme pristupovať takýmto smerníkovým spôsobom. a[1] je to isté ako *(a+1) teda "vec, ktorá sa nachádza v pamäti na adrese a+1". 0.16
To, že prístup k poliam sa v podstate deje cez smerníky skrýva v sebe výhody aj nevýhody. Medzi výhody patrí, že smerníky môžu polia v istých situáciach nahrádzať, ako si to môžete všimnúť na nasledujúcom príklade:
int a[10],b[10],*c; a[2] = 2; b[2] = 3; c = a; printf("%d\n",c[2]); c = b; printf("%d\n",c[2]);Medzi nevýhody patrí napríklad to, že C-čko vám nekontroluje dĺžku poľa. Aj keď má pole c iba 10 prvkov, môžete použiť výraz c[13]. Program sa skrátka pozrie v pamäti o 13 ďalej, než ukazuje smerník c a niečo prečíta/zapíše. Pri troche šťastia vám program spadne (pod linuxom s hláškou "Segmentation fault") a vy budete vedieť, že v pamäti siahate niekam, kam nemáte. Ničmenej oveľa častejšie budete iba žasnúť, prečo sa vám mení nejaká iná premenná a celé to blbne.
Úloha č.2 Napíšte program, v ktorom si urobíte desaťprvkové pole, v cykle
do neho vložíte čísla od 1 do 10 a v ďalšom cykle obsah poľa vypíšete.
Úloha č.3 Napíšte procedúru, ktorá dostane na vstupe smerník na desaťprvkové pole typu int a ako hodnotu vráti najväčší prvok toho poľa. Vyskúšajte, či funguje s poľom z úlohy 2.
Úloha č.4 Naplňte dvadsaťprvkové pole prvkami Fibonacciho postupnosti 1,1,2,3,5,8,... Použite pri tom smerníkový zápis -- hranaté zátvorky smiete použiť len v deklarácii poľa.
Anino Belan 2003-10-26