Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 8 - Pole v C++

V předešlém cvičení, Řešené úlohy k 6.-7. lekci C++, jsme si procvičili nabyté zkušenosti z předchozích lekcí.

Dnes si v C++ tutoriálu 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 - Základní konstrukce jazyka C++

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

Programovací jazyky se velmi liší v tom, jak s polem pracují. V některých jazycích (zejména kompilovaných) není možné za běhu programu vytvořit pole s dynamickou velikostí (např. mu dát velikost dle nějaké proměnné). Pole se zde musí deklarovat s konstantní velikostí přímo ve zdrojovém kódu. Lze to obejít pointery a vlastními datovými strukturami. Naopak některé modernější interpretované jazyky nebo jazyky s virtuálním strojem umožňují nejen deklarovat pole s libovolnou velikostí, ale dokonce tuto velikost na již existujícím poli měnit (např. PHP). C++ je jazyk čistě kompilovaný, u pole tedy budeme vždy velikostně omezeni.

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 poté používají cykly.

Pole deklarujeme pomocí hranatých závorek, ve kterých uvedeme jeho velikost. Před název proměnné nezapomeneme uvést datový typ jeho prvků, zde celá čísla:

int pole[16];

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

Velikost pole 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];

Ohledně změny délky jsme si sice za běhu programu nepomohli, nicméně, když si jako programátoři rozmyslíme, že chceme zadat napevno jiný počet prvků, změní se konstanta na všech místech v programu. Bez konstant, kdybychom pole poté vypisovali cykly, mohli bychom např. zapomenou změnit počet prvků i tam a z pole vyjet nebo jej nevypsat celé.

Často potřebujeme délku pole zadat pomocí obyčejné proměnné. Takové pole musíme založit tzv. dynamicky, což se naučíme v navazujícím C++ kurzu. Probírat tuto problematiku hned v úvodním kurzu by určitě nebyl dobrý nápad.

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

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

Plnit pole takto 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;

Všimněte si, že délku pole máme opět uloženou v konstantě.

Pozn.: 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 byly zrovna 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 poté 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 poté 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()

Funkce find() nám vrací tzv. ukazatel na první výskyt hodnoty, kterou jsme jí předali. S ukazateli se teprve setkáme, ale abychom mohli hledání v poli používat již nyní, naučíme se funkci volat již teď. Pole je vnitřně ukazatel, který ukazuje na určité místo v paměti, kde pole začíná (např. může ukazovat na adresu 100). Funkce find() nám vrátí ukazatel na místo v paměti, kde je prvek, který hledáme (např. na adresu 120). Ukazatel deklarujeme pomocí hvězdičky. Pokud od této adresy odečteme adresu začátku pole, získáme s těmito čísly hodnotu 20, což je pozice prvku (prvek byl 20 pozic od začátku pole). Pokud vás to zmátlo, používejte funkci zatím pouze intuitivně, s ukazateli se ještě bohatě setkáme dále v kurzu a vše si velmi podrobně vysvětlíme. Byla by ovšem škoda psát si hledací funkci pokaždé znovu, když ji můžeme použít již nyní.

Pojďme si vše ukázat na příkladu a nechme si najít pozici hodnoty 7 v poli několika čísel:

#include <iostream>
#include <algorithm>
using namespace std;

int main(void)
{
    const int delkaPole = 5;
    int pole[delkaPole] = { 1, 7, 3, 4, 10 };
    int hledanyPrvek = 7;
    int *i = find(pole, pole + delkaPole, hledanyPrvek);
    int pozice = i - pole;
    if (pozice < delkaPole)
        cout << "Prvek " << hledanyPrvek << " nalezen na pozici: " << pozice << "." << endl;
    else
        cout << "Prvek nenalezen." << endl;
    cin.get();
    return 0;
}

count()

const int delkaPole = 6;
int pole[delkaPole] = { 1, 6, 9, 2, 6, 3 };
int c = count(pole, pole + delkaPole, 6);
cout << c; // c = 2
cin.get();

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

copy()

const int delkaPole = 5;
int pole[delkaPole] = { 1, 2, 3, 4, 5 };
int pole2[delkaPole] = { 0, 0, 0, 0, 0 };
copy(pole, pole + delkaPole, pole2);
// pole = { 1, 2, 3, 4, 5 }, pole2 = { 1, 2, 3, 4, 5 }
for (int i = 0; i < delkaPole; i++)
{
    cout << pole[i] << "->" << pole2[i] << " ";
}
cin.get();

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()

const int delkaPole = 5;
int pole[delkaPole] = { 2, 1, 4, 5, 3 };
int *i = max_element(pole, pole + delkaPole);
cout << *i; // i = pole + 3, *i = 5
cin.get();

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. Pozici získáme stejně jako u příkladu s find().

min_element()

const int delkaPole = 5;
int pole[delkaPole] = { 2, 1, 4, 5, 3 };
int *i = min_element(pole, pole + delkaPole);
cout << *i; // i = pole + 1, *i = 1
cin.get();

Funkce min_element() je obdoba předchozí funkce s jediným rozdílem - vrací ukazatel na nejnižší hodnotu v poli. Pozici získáme stejně jako u příkladu s find().

sort()

const int delkaPole = 5;
int pole[delkaPole] = { 2, 1, 4, 5, 3 };
sort(pole, pole + delkaPole);
// pole = { 1, 2, 3, 4, 5 }
for (int i = 0; i < delkaPole; i++)
{
    cout << pole[i] << " ";
}
cin.get();

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

fill()

const int delkaPole = 5;
int pole[delkaPole] = { 1, 2, 3, 4, 5 };
fill(pole, pole + delkaPole, 5);
// pole = { 5, 5, 5, 5, 5 }
for (int i = 0; i < delkaPole; i++)
{
    cout << pole[i] << " ";
}
cin.get();

Funkce fill() naplní pole zadanou hodnotou.

reverse()

const int delkaPole = 5;
int pole[delkaPole] = { 1, 2, 3, 4, 5 };
reverse(pole, pole + delkaPole);
// pole = { 5, 4, 3, 2, 1 }
for (int i = 0; i < delkaPole; i++)
{
    cout << pole[i] << " ";
}
cin.get();

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

random_shuffle()

#include <iostream>
#include <algorithm>
#include <ctime>
using namespace std;

int main(void)
{
    srand(unsigned(time(0))); // inicializuje generátor náhodných čísel
    const int delkaPole = 5;
    int pole[delkaPole] = { 1, 2, 3, 4, 5 };
    random_shuffle(pole, pole + delkaPole);
    // např. pole = { 3, 1, 5, 2, 4 }
    for (int i = 0; i < delkaPole; i++)
    {
        cout << pole[i] << " ";
    }
    cin.get();
    // Prosím, pamatujte, že pokud používáte náš online kompiler, výsledky jsou
    // cachované a zůstávají tedy stejné po několik dní. Pro vynucení nové kompilace
    // a tedy vygenerování nových náhodných čísel je třeba kód upravit, stačí upravit
    // i jen komentář.
    return 0;
}

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.

V následujícím kvízu, Kvíz - Podmínky, cykly, pole v C++, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.


 

Předchozí článek
Řešené úlohy k 6.-7. lekci C++
Všechny články v sekci
Základní konstrukce jazyka C++
Přeskočit článek
(nedoporučujeme)
Kvíz - Podmínky, cykly, pole v C++
Článek pro vás napsal Zdeněk Pavlátka
Avatar
Uživatelské hodnocení:
105 hlasů
Autor se věnuje spoustě zajímavých věcí ze světa informatiky a grafiky
Aktivity