na obsah klávesové zkratky na hlavní stránku na menu

Pole

Pole jsou jednou ze složitějších datových struktur. Tento článek stručně popisuje deklaraci pole, jeho inicializaci a práci s ním. Jsou též zmíněna vícerozměrná pole.

Úvod do polí

Pole je datová struktura, ve které jsou data uchována za sebou v paměti. Přístup do pole je časově konstantní, zatímco manipulace s polem – mazání a přidávání prvků – má amortizovanou lineární složitost. Pole je v paměti zarovnáno tak, jak je to zobrazeno na obrázku níže. V jazyce C se na rozdíl od Pascalu indexuje od nuly. Tedy první prvek pole má index nula a n-tý prvek má index n mínus jedna.

struktura pole, jeho podoba v paměti RAM

struktura pole, jeho podoba v paměti RAM

Deklarace pole

Pole je v jazyce C interně podporováno a tedy není nutné vkládat žádné speciální hlavičky. Deklarace pole má následující strukturu:

<typ> <jméno>[<[velikost]>];

Deklarace se tedy příliš neliší od deklarace proměnné. Typ je základní typ buňky pole (pole je homogenní, není možné měnit typ u jednotlivých buněk), jméno je identifikátor pole – jméno proměnné typu pole – a velikost určuje, kolik buněk bude pole mít. Až do standardu C99 nebylo možné použít jako velikost nic jiného než konstantu či výraz, který dokázal překladač vyhodnotit v době překladu. S nástupem nového standardu je možné používat i nekonstantní výrazy (lokální nekonstantní pole). Velikost je nepovinný údaj, stejně jako v kapitole o řetězcích stačí inicializovat pole a překladač si velikost doplní sám. Pokud velikost uvedeme, musíme vždy použít celé nezáporné číslo. V konkrétním případě tedy pole o deseti prvcích se jménem pole a typem int bude vypadat takto:

int pole[10];

Inicializace pole

Pole můžeme inicializovat jako každou jinou proměnnou při jejím vzniku. U pole je to ale o něco složitější. Musíme totiž vyjmenovat obsahy jednotlivých buněk.

int pole1[5] = {1, 2, 3, 4, 5};
int pole2[] = {1, 2, 3, 4, 5};
int pole3[5] = {1, 2};
int pole4[5] = {0};

Na první řádce kompletně inicializujeme pole s pěti buňkami. Na druhé řádce vytvoříme ekvivalentní pole s polem pole1, viz výše. Co se ale stane s polem pole3? Zde vyplníme pouze první dvě buňky, zbytek bude vynulován. Stejně tak pole4 bude kompletně vyplněné nulami.

Práce s polem

Indexace

Máme-li vytvořenou proměnnou typu pole, můžeme k jednotlivým buňkám přistupovat pomocí operátoru indexace, nebo-li indexem v hranatých závorkách. Nesmíme ovšem zapomínat na to, že první buňka má index nula

int pole[5] = {1, 2, 3, 4, 5};

int a = pole[0]; // první buňka pole, v a bude 1
int b = pole[1]; // druhá buňka pole, v b bude 2
int c = pole[5]; // chyba, saháme za konec pole!!

Na poslední řádce se pokoušíme číst buňku s indexem pět. To je samozřejmě chybně, protože pole má poslední buňku na indexu čtyři. Jazyk C nemá žádnou zabudovanou kontrolu mezí polí. V případě jako je výše, dojde k potenciálně nebezpečnému čtení paměti. To může způsobit pád programu nebo náhodně vrácená data.

Porovnávání polí

Pole nelze jednoduše porovnávat, jako to jde s jednoduchými číselnými typy. Od následujícího kódu nelze očekávat korektní chování, pokud nám jde o srovnání obsahu polí:

if (pole1 == pole2) // ...

Chceme-li srovnat obsahy polí, nezbude nám nic jiného, než vytvořit cyklus a porovnat buňku po buňce. Máme-li stejně dlouhá pole, provedeme srovnání následovně:

int pole1[10], pole2[10];
// ...
int shoda = 1;
for (i = 0; i < 10; i++)
{
  if (pole1[i] != pole2[i]) // pole se liší
  {
    shoda = 0;
    break; // přerušíme cyklus a pokračujeme za ním
  }
  if (shoda)
  {
    printf("pole se rovnaji\n");
  }
}

Další možností je použít funkci int memcmp(const void *pole1, const void *pole2, size_t velikost) z hlavičkového souboru string.h, která srovná dva úseky paměti zadané délky a vrátí podobně jako funkce strcmp() hodnotu menší než nula, nula, nebo větší než nula, pokud je první pole po bajtech menší, rovno, nebo větší než druhé pole.

Pole jako parametr funkce

Pole lze předávat do funkce jako každou jinou proměnnou. Stačí pouze označit, že se jedná o pole párem hranatých závorek:

void funkce (int pole[], int velikost)

Jako první parametr funkce funkce se očekává pole typu int. Ve druhém parametru předáváme délku pole. Délka pole se nedá jednoduše zjistit, a proto ji musíme předávat samostatně. S polem se v těle funkce pracuje jako s obyčejným lokálně vytvořeným polem.

Vícerozměrná pole

Doteď jsme se zabývali pouze jednorozměrným polem. Jazyk C nás ale v dimenzích pole neomezuje. Dvourozměrné pole vytvoříme zadáním velikosti nadvakrát.

int pole2d [3][3];

Zde jsme vytvořili dvourozměrnou matici 3x3. Vícerozměrná pole můžeme také inicializovat. Jelikož jsou pole v jazyce C ukládaná po řádkách, musíme inicializaci psát řádkově.

int pole2d1 [3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int pole2d2 [3][3] = {{1, 2, 3}};
int pole2d3 [3][3] = {{0}};

Jako v případě jednorozměrných polí, i zde můžeme část inicializace vynechat. Překladač zbytek doplní nulami. Pole pole2d3 bude tedy reprezentovat nulovou matici 3x3.

Na libovolný prvek pole se dá dostat vícenásobnou indexací.

int a = pole2d[1][1];

Stejně jako u jednorozměrných polí i zde se indexuje od nuly. Levý horní prvek matice má tedy index [0][0].