Dnešní díl bude věnován hojně využívané datové struktuře, kterou je pole. Naučíme se jak pole vytvářet a jak je možné jej využít.
Co je pole?
Pole je datová struktura, která obsahuje určitý počet proměnných. Tyto proměnné jsou nazývány prvky pole. Prvky pole jsou indexovány a pomocí těchto indexů je později možné prvky z pole získávat.
V jazyku C# jsou prvky pole indexovány od nuly. Všechny prvky pole jsou stejného typu. V prostředí .NET frameworku je pole objektem referenčního typu, který je potomkem třídy System.Array. Prvky jsou v poli uloženy, podle toho jakého jsou typu. Jestliže jsou prvky představovány objekty referenčního typu (například typu string), jsou v poli uloženy odkazy na objekty. V případě, že prvky pole jsou hodnotového typu (například typu int), pole obsahuje přímo hodnoty objektů.
Deklarace pole
Předtím než je možné pole používat, musíme si jej nejdříve založit. Deklarace pole je složena ze dvou částí, které představují název pole a jeho typ.
datový_typ[] identifikátor;
Tímto jsme vytvořili referenční proměnnou typu pole, která má nyní hodnotu null, protože jsme objekt pole ještě nevytvořili.
Pro vytvoření instance pole slouží, stejně jako u všech referenčních typů, operátor new, jehož pomocí jsme schopni inicializovat pole o specifikované velikosti.
identifikátor = new datový_typ[velikost_pole];
Počáteční hodnota prvků pole po jeho inicializaci zavisí na tom, jestli se jedná o pole objektů hodnotového typu nebo referenčního typu. V případě objektů hodnotového typu inicializace pole zapříčiní vytvoření objektů o specifikovaném počtu a pokud se jedná o objekty referenčního typu jsou vytvořeny pouze odkazy s hodnotou null.
Je také možné provést inicializaci pole už při jeho deklaraci.
datový_typ[] identifikátor = new datový_typ[velikost_pole];
Pokud tedy chceme vytvořit pole, jehož prvky budou představovat 32-bitová celá čísla (int) provedeme to následujícím způsobem :
int[] ciselnePole = new int[4];
Jak bylo zmíněno, tak k prvkům pole se přistupuje pomocí jejich indexu, který je u prvního prvku roven nule.
ciselnePole[0] = 1;
ciselnePole[1] = 2;
ciselnePole[2] = 3;
ciselnePole[3] = 4;
Pro lepší pochopení je možné si tuto datovou strukturu a její indexování představit, tak jak ukazuje následující obrázek:
Další možnosti inicializace
Někdy můžeme chtít určit hodnoty prvků pole už při jeho inicializaci. Když určujeme hodnoty prvků pole už při jeho inicializaci, není nutné specifikovat velikost pole. V jazyku C# je toto proveditelné takto:
int[] ciselnePole = new int[] {1,2,3,4};
… a v případě pole obsahujícího řetězce takto:
string[] dnyTydnu = new string[] {"Po","Ut","St","Ct","Pa","So","Ne"};
Zápis lze provést ještě kratší cestou:
int[] ciselnePole = {1,2,3,4};
string[] dnyTydnu = {"Po","Ut","St","Ct","Pa","So","Ne"};
Hodnoty prvků inicializovaného pole tímto způsobem, lze samozřejmě později normálně měnit.
Vlastnost Length
Třída System.Array, tedy i každé námi vytvořené pole obsahuje vlastnost Length, která může být pouze čtena a je pomocí ní možné zjistit délku pole.
int[] ciselnePole = new int[4];
int delkaPole = ciselnePole.Length; //je vracena hodnota 4
Následující příklad ukazuje vypsání všech prvků pole použitím známého cyklu for, kde je v jeho řídící části použita vlastnost Length.
public static void VypisObsahPole()
{
int[] ciselnePole = {1,2,3,4};
for (int i = 0; i < ciselnePole.Length; i++)
Console.WriteLine((i+1) + ". prvek pole - " + ciselnePole[i]);
}
Vícerozměrná pole
Pole mohou nabývat více rozměrů než pouze jednoho. Následující deklarace vytvoří dvourozměrné pole o čtyřech řádcích a třech sloupcích:
int[,] dvouRozmernePole = new int[4,3];
K prvku, který se nachází na prvním řádku a druhém sloupci přistoupíme tímto způsobem:
int prvek = dvouRozmernePole[0,1];
Pole o více než dvou rozměrech by bylo deklarováno analogicky:
int[,,] viceRozmernePole = new int[2,3,4];
Podobně jako u jednorozměrných polí je možné specifikovat počáteční hodnoty prvků pole při jeho inicializaci.
int[,] dvouRozmernePole = new int[,]{{1,2},{3,4}};
… nebo ještě kratší cestou:
int[,] dvouRozmernePole = {{1,2},{3,4}};
K získávání délky rozměrů ve vícerozměrných polí již nepoužijeme vlastnost Length, protože ta v případě vícerozměrných polí vrací součin délek jednotlivých rozměrů, ale využijeme metody GetLength, jejímž argumentem je číslo rozměru, jehož délku požadujeme získat. Rozměry jsou číslovány od nuly, takže když potřebujeme zjistit délku druhého rozměru, zápis bude vypadat následovně:
int delkaDruhehoRozmeru = dvouRozmernePole.GetLength(1);
Kód, zajišťující vypsání všech prvků dvourozměrného pole pomocí vnořeného cyklu for a metody GetLength by mohl vypadat takto:
public static void VypisObsahPole()
{
int[,] viceRozmernePole = new int[3,3];
viceRozmernePole[0,0] = 1;
viceRozmernePole[1,1] = 1;
viceRozmernePole[2,2] = 1;
for (int i = 0; i < viceRozmernePole.GetLength(0); i++)
{
for (int j = 0; j < viceRozmernePole.GetLength(1); j++)
Console.Write(viceRozmernePole[i,j]);
Console.WriteLine();
}
}
Pole polí
Pole polí, která jsou někdy nazývána „zubatá“ jsou pole jejichž prvky jsou pole. Pole tvořící prvky tohoto druhu polí mohou mít různou velikost. Vytvoření pole o velikosti 3 prvků, jehož prvky tvoří pole typu int se zapisuje takto:
int[][] zubatePole = new int[3][];
Jelikož po tomto vytvoření jsou prvky pole pouze prázdné odkazy na vnořená pole je vhodné vnořená pole inicializovat.
zubatePole[0] = new int[3];
zubatePole[1] = new int[4];
zubatePole[2] = new int[5];
Pokud se vám zdá tento postup příliš zdlouhavý, existuje zde i možnost vnořená pole inicializovat a to včetně jejich počátečních hodnot.
int [][] zubatePole = new int[][]{
new int[]{1,2},
new int[]{1,2,3},
new int[]{1,2,3,4}
};
Přiřazování hodnot prvkům vnořených polí se provádí dvojicí hranatých závorek, kde první označuje index vnořeného pole a druhá index prvku vnořeného pole.
zubatePole[0][1] = 5;
zubatePole[1][3] = 10;
zubatePole[2][0] = 15;
Velikost vnořených polí je možné zjistit pomocí vlastnosti Length takto:
int delkaVnorenehoPole = zubatePole[0].Length;
Uvedený příklad ukazuje možný způsob, kterým lze vypsat všechny prvky vnořených polí:
public static void VypisObsahPole ()
{
int [][] zubatePole = new int[][]{
new int[]{1,2},
new int[]{1,2,3},
new int[]{1,2,3,4}
};
for (int i = 0; i < zubatePole.Length; i++)
{
for (int j = 0; j < zubatePole[i].Length; j++)
Console.WriteLine((j + 1) + ".prvek v " + (i + 1) + ".vnorenem poli - " + zubatePole[i][j]);
}
}
Vnořená pole mohou být i vícerozměrná. Kolik mají vnořená pole rozměrů určíme při deklaraci pole.
int[][,] zubatePole = new int[5][,];
//inicializace prvku
zubatePole[0] = new int[3,4];
Pole jako parametr metody
Jak jsme si řekli, pole jsou v prostředí .NET frameworku objekty referenčního typu, tudíž nám nic nebrání v jejich předání metodám ve formě parametru. Jelikož se jedná o referenční typ, je metodě předán pouze odkaz na existující objekt a není do proměnné parametru metody zkopírována jeho hodnota (obsah), jak se tomu děje v případě hodnotových typů. Následující příklad ukazuje použití pole jako parametru metody:
public class PrikladParametr
{
public static void VypisObsahPole(string[] poleProVypsani)
{
for (int i = 0; i < poleProVypsani.Length; i++)
Console.WriteLine((i+1) + ". prvek pole - " + poleProVypsani[i]);
}
public static void NaplnPole(string[] poleProNaplneni)
{
for (int i = 0; i < poleProNaplneni.Length; i++)
poleProNaplneni[i] = (i+1) + ".prvek";
}
}
class Zive11Test{
public static void Main(string[] args)
{
//deklarace a inicializace pole
string[] pole = new string[10];
//predani pole jako parametru do metody pro jeho naplneni
PrikladParametr.NaplnPole(pole);
//predani pole jako parametru do metody pro jeho vypsani
PrikladParametr.VypisObsahPole(pole);
Console.ReadLine();
}
}
Zdrojové kódy příkladů je možné získat zde.
V příštím díle si doplníme naše znalosti o polích a blíže se podíváme na třídu System.Array.