9. díl - Pole v C++

C++ Základní konstrukce C++ Pole v C++

Minule jsme si v našem C++ seriálu ukázali ošetření uživatelských vstupů. Dnes si představíme datovou strukturu pole a vyzkoušíme si, co všechno umí.

Pole

Představte si, že si chcete uložit nějaké údaje o více prvcích. Např. chcete v paměti uchovávat 10 čísel, políčka šachovnice nebo jména 50ti uživatelů. Asi vám dojde, že v programování bude nějaká lepší cesta, než začít "bušit" proměnné s názvy uzivatel1, uzivatel2... až uzivatel50. Nehledě na to, že jich může být třeba 1000. A jak by se v tom potom hledalo? Brrr, takle ne :)

Pokud potřebujeme uchovávat větší množství proměnných stejného typu, můžeme použít pole. Můžeme si ho představit jako řadu přihrádek, kde v každé máme uložený jeden prvek. Přihrádky jsou očíslované tzv. indexy, první má index 0.

Struktura pole

(Na obrázku je vidět pole osmi čísel)

Možná vás napadá, proč se tu zabýváme s polem, když má evidentně mnoho omezení a existují lepší datové struktury. Odpověď je prostá: pole je totiž jednoduché. Nemyslím pro nás na pochopení (to také), ale zejména pro počítač. Rychle se s ním pracuje, protože prvky jsou v paměti jednoduše uloženy za sebou, zabírají všechny stejně místa a rychle se k nim přistupuje. Je to klíčová struktura. Pro hromadnou manipulaci s prvky pole se pak používají cykly.

Pole deklarujeme pomocí hranatých závorek, ve kterých uvedeme jeho velikost:

int pole[16];

pole je samozřejmě název naší proměnné.

Naše pole má ale jednu nevýhodu. Jeho velikost je pevně zadaná číslem ve zdrojovém kódu. Schválně si zkuste místo čísla použít proměnnou. Visual Studio to označí za chybu.

Pokud nám pevná velikost pole stačí, ale chceme jeho velikost zadat proměnnou (např. abychom ji pak použili v podmínce v cyklu), musíme použít tzv. konstantu. To je proměnná, jejíž hodnotu nelze měnit. Vytváří se téměř stejně jako běžné proměnné, jen před datový typ napíšeme klíčové slovo const:

const int delkaPole = 24;
int pole[delkaPole];

Většinou ale potřebujeme délku pole zadat pomocí proměnné. S tím nám pomůže operátor new, který dynamicky vytvoří pole. Získané pole pak uložíme do ukazatele.

int delkaPole = 24;
int *pole = new int[delkaPole];

Nyní nám pole ukazuje na pole o velikosti 24 intů.

V jazycích typu C#, Java apod. nám program automaticky odstraní pole, která už nemůžeme používat. V C++ je ale situace jiná: dynamicky vytvořené pole, na které všechny ukazatele zanikly (např. tím že skončil blok kde bylo pole vytvořeno - třeba u if) stále existuje a zabírá místo v paměti, ale nemáme jak k němu přistupovat. Jedná se o tzv. Memory leak (únik paměti). Aby k tomu nedošlo, musíme pole odstranit ve chvíli, kdy už ho nepotřebujeme. K tomu je tu operátor delete[]. Ten uvolní paměť, kterou pole používá.

int delkaPole = 24;
int *pole = new int[delkaPole];
// práce s polem
delete[] pole;

Pozn.: Nikdy se nesnažte přistupovat k paměti, kterou jste již uvolnili pomocí delete, stejně tak nikdy nepoužívejte delete na ukazatele, do kterých jste nic nepřiřadili.

K prvkům pole potom přistupujeme přes hranatou závorku. Pojďme na první index (tedy index 0) uložit číslo 1.

int *pole = new int[10];
pole[0] = 1;

Plnit pole takhle ručně by bylo příliš pracné, použijeme cyklus a naplníme si pole čísly od 1 do 10. K naplnění použijeme for cyklus:

const int delkaPole = 10;
int pole[delkaPole];
for (int i = 0; i < delkaPole; i++)
        pole[i] = i + 1;

Pozn.: Délku pole bychom měli vždy mít uloženou v proměnné. Kdybychom jí totiž chtěli změnit, museli bychom jí změnit i ve všech cyklech kde s polem pracujeme.

Pozn 2.: Nikdy se nesnažte přistupovat k prvkům za koncem pole (např k 20. prvku v poli o 10 prvcích). V lepším případě dostanete nedefinovaný výsledek (hodnoty co zrovna byli náhodou uloženy v paměti), v tom horším případě program spadne.

Abychom pole vypsali, můžeme za předchozí kód připsat:

for (int i = 0; i < delkaPole; i++)
        cout << pole[i] << ' ';

Naplnit pole hodnotami můžeme ještě jedním způsobem. Pokud známe jeho prvky předem, můžeme využít následující syntaxi:

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

Číslo v hranatých závorkách lze vynechat, délka pole se pak určí podle počtu prvků ve složených závorkách. Na druhou stranu můžeme v hranatých závorkách uvést hodnotu větší než počet prvků ve složených závorkách. Pole pak nebude mít všechny prvky nastavené.

Funkce pro práci s poli

Mnoho užitečných funkcí pro práci s poli můžeme najít v souboru "algorithm". Některé z nich si tu ukážeme (nesmíme zapomenout umístit #include <algorithm> na začátek souboru).

find

// pole = { 1, 2, 3, 4, 5 }
int *i = find(pole, pole + delka_pole, 3);
// i = pole + 2

Funkce find nám vrací ukazatel na první výskyt hodnoty, kterou jsme jí předali, v tomto případě 3. Pokud hodnotu nenajde, vrátí druhý předaný ukazatel (pole + delka_pole).

count

// pole = { 1, 6, 9, 2, 6, 3 }
int c = count(pole, pole + delka_pole, 6);
// c = 2

Funkce count nám spočítá, kolikrát se v poli vyskytuje předaná hodnota - v ukázce 6.

copy

// pole = { 1, 2, 3, 4, 5 }, pole2 = { 0, 0, 0, 0, 0 }
copy(pole, pole + delkaPole, pole2);
// pole = { 1, 2, 3, 4, 5 }, pole2 = { 1, 2, 3, 4, 5 }

Funkce copy zkopíruje obsah jednoho pole do druhého.

Pozn.: druhé pole musí být stejně dlouhé jako první pole, nebo delší

max_element

// pole = { 2, 1, 4, 5, 3 }
int *i = max_element(pole, pole + delka_pole);
// i = pole + 3, *i = 5

Funkce max_element vrací ukazatel na největší hodnotu v poli, hodnoty porovnává pomocí operátoru <. Pokud se nejvyšší hodnota vyskytuje v poli několikrát, vrácený ukazatel bude ukazovat na její první výskyt.

min_element

// pole = { 2, 1, 4, 5, 3 }
int *i = min_element(pole, pole + delka_pole);
// i = pole + 1, *i = 1

Funkce min_element je obdoba předchozí funkce s jediným rozdílem - vrací ukazatel na nejnižší hodnotu v poli.

Sort

// pole = { 2, 1, 4, 5, 3 }
sort(pole, pole + delka_pole);
// pole = { 1, 2, 3, 4, 5 }

Sort vzestupně seřadí prvky v poli (pomocí operátoru < ).

Fill

// pole = { 1, 2, 3, 4, 5 }
fill(pole, pole + delka_pole, 5);
// pole = { 5, 5, 5, 5, 5 }

Funkce fill naplní pole zadanou hodnotou.

Reverse

// pole = { 1, 2, 3, 4, 5 }
reverse(pole, pole + delka_pole);
// pole = { 5, 4, 3, 2, 1 }

Funkce reverse "převrátí" obsah pole. To znamená, že jeho hodnoty budou pozpátku.

Random shuffle

// pole = { 1, 2, 3, 4, 5 }
random_shuffle(pole, pole + delka_pole);
// např. pole = { 3, 1, 5, 2, 4 }

Funkce random_shuffle náhodně přehází prvky v poli.

To by pro dnešek stačilo, můžete si s polem hrát.


 

  Aktivity (4)

Článek pro vás napsal Zdeněk Pavlátka
Avatar
Autor se věnuje spoustě zajímavých věcí :)

Jak se ti líbí článek?
Celkem (2 hlasů) :
55555


 


Miniatura
Všechny články v sekci
Základy C++
Miniatura
Následující článek
Cvičení k 8.-9. lekci C++

 

 

Komentáře

Avatar
Jan Doskočil:

A kdy bude příště? Už se nemůžu dočkat...

Odpovědět 22. dubna 16:54
"Existuje pouze 10 typů lidí, ti kteří strojovému kódu rozumí a ti kteří ne."
Avatar
Zdeněk Pavlátka
Tým ITnetwork
Avatar
Odpovědět  +1 22. dubna 17:21
Kolik jazyků umíš, tolikrát jsi programátor.
Avatar
Odpovědět 23. dubna 19:22
"Existuje pouze 10 typů lidí, ti kteří strojovému kódu rozumí a ti kteří ne."
Avatar
Zdeněk Pavlátka
Tým ITnetwork
Avatar
Odpovídá na Jan Doskočil
Zdeněk Pavlátka:

Tak ještě ne, nic nestíhám :/ Ale už to mám rozepsané...

Editováno 24. dubna 22:05
Odpovědět  +2 24. dubna 22:05
Kolik jazyků umíš, tolikrát jsi programátor.
Avatar
Odpovídá na Zdeněk Pavlátka
Jan Doskočil:

Prosím už mě nemuč úvahami o přechodu na C#

Odpovědět 12. června 18:17
"Existuje pouze 10 typů lidí, ti kteří strojovému kódu rozumí a ti kteří ne."
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 5 zpráv z 5.