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
.

(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:
{CPP_CONSOLE} const int delkaPole = 10; int pole[delkaPole]; for (int i = 0; i < delkaPole; i++) pole[i] = i + 1; for (int i = 0; i < delkaPole; i++) cout << pole[i] << ' '; {/CPP_CONSOLE}
Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.
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; }
Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.
count()
#include <iostream> #include <algorithm> using namespace std; int main(void) { 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(); return 0; }
Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.
Funkce count()
nám spočítá, kolikrát se v poli vyskytuje
předaná hodnota - v ukázce 6
.
copy()
#include <iostream> #include <algorithm> using namespace std; int main(void) { 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(); return 0; }
Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.
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()
#include <iostream> #include <algorithm> using namespace std; int main(void) { 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(); return 0; }
Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.
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()
#include <iostream> #include <algorithm> using namespace std; int main(void) { 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(); return 0; }
Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.
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()
#include <iostream> #include <algorithm> using namespace std; int main(void) { 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(); return 0; }
Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.
Funkce sort()
vzestupně seřadí prvky v poli (pomocí
operátoru <
).
fill()
#include <iostream> #include <algorithm> using namespace std; int main(void) { 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(); return 0; }
Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.
Funkce fill()
naplní pole zadanou hodnotou.
reverse()
#include <iostream> #include <algorithm> using namespace std; int main(void) { 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(); return 0; }
Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.
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; }
Zkontroluj, zda výstupy programu odpovídají předloze. S jinými texty testy neprojdou.
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í.