Lekce 15 - Struktury v jazyce C
V předešlém cvičení, Řešené úlohy k 14. lekci Cečka, jsme si procvičili nabyté zkušenosti z předchozích lekcí.
V dnešním tutoriálu se naučíme používat neméně důležitou součást tohoto jazyka, kterou jsou tzv. struktury. Jelikož bude vytvořen opět jen jednoduchý program, tak ve výkladu funkce použity nebudou. My již víme, že kdyby byl program o chlup delší, tak bychom je určitě měli zavést.
Uložení složitých prvků
Když bychom chtěli uložit data jednoho uživatele, který se nějak jmenuje, má nějaký věk a bydlí v nějaké ulici, vytvořili bychom si s dosavadními znalostmi několik proměnných:
int main(int argc, char** argv) { char jmeno[] = "Tomáš Marný"; int vek = 33; char ulice[] = "Šikmá 5"; return (EXIT_SUCCESS); }
Jen zřídka ovšem ukládáme jen jednoho uživatele a tak jich budeme
chtít mít uložených hned několik. Již víme, že když chceme uložit
více prvků stejného typu, využijeme k tomu pole. Jelikož uživatel v sobě
ovšem obsahuje hodnoty třech typů, museli bychom si vytvořit 3 různá pole.
Jedno pro jména, druhé pro věky a třetí pro ulice. V dalším motivačním
příkladu si tedy vytvořme několik polí o velikosti 10
(tedy
max. pro uchování 10 uživatelů). Do pole si na zkoušku uložme data 2
uživatelů a uživatele v poli následně vypišme pomocí for
cyklu.
{C_IMPORTS}
#include <string.h>
{C_MAIN_BLOCK}
char jmena[10][51];
int veky[10];
char ulice[10][51];
strcpy(jmena[0], "Tomáš Marný");
veky[0] = 33;
strcpy(ulice[0], "Šikmá 5");
strcpy(jmena[1], "Josef Nový");
veky[1] = 28;
strcpy(ulice[1], "Ve Svahu 8");
int i;
for (i = 0; i < 2; i++)
{
printf("Uživatel na indexu %d\n", i);
printf("Jméno: %s\n", jmena[i]);
printf("Věk: %d\n", veky[i]);
printf("Ulice: %s\n\n", ulice[i]);
}
{/C_MAIN_BLOCK}
Výsledek:
Konzolová aplikace
Uživatel na indexu 0
Jméno: Tomáš Marný
Věk: 33
Ulice: Šikmá 5
Uživatel na indexu 1
Jméno: Josef Nový
Věk: 28
Ulice: Ve Svahu 8
Program vypadá na naše poměry docela působivě. Až se naučíme ukládat data do souborů, mohli bychom podobně naprogramovat např. telefonní seznam. Přesto výše uvedený kód není ideální. Nejprve si však povšimněme několika věcí.
Zajímavá je zejména definice polí jmena
a
ulice
. Protože chceme v každé přihrádce pole (jmena) další
pole znaků (jméno), musíme vytvořit proměnnou, která je polem polí. Proto
jsou uvedeny 2 hranaté závorky. V první závorce je uveden počet položek
vnějšího pole, tedy počet jmen v poli. V druhé závorce je uveden počet
položek pole, které je vložené v každé přihrádce. V našem případě je
to 50
znaků (+1 pro \0
).
Již víme, že v céčku nemůžeme dosadit řetězcovou konstantu jinak,
než při inicializaci proměnné. Proto zde musíme využít funkce
strcpy()
, která nám řetězec do již vytvořené proměnné
zkopíruje. Výpis cyklem by měl být jasný, projíždíme jen indexy
< 2
, protože více osob v poli zatím nemáme.
Struktury
Abychom nemuseli tvořit tolik složitých polí, umožňuje jazyk C
definovat tzv. strukturu. Jedná se o nový datový typ, který můžeme uložit
do jedné proměnné, ale který uvnitř zároveň obsahuje několik prvků
(někdy se mu říká záznamový typ). Vzdáleně se může podobat poli, jeho
prvky ovšem nemusejí být stejného typu a místo číselně jsou pojmenované
slovy. Pro evidenci uživatelů by bylo úplně nejjednodušší vytvořit si
strukturu UZIVATEL
. Někam do globálního prostoru, nad funkci
main()
, vložíme tuto definici:
typedef struct { char jmeno[51]; int vek; char ulice[51]; } UZIVATEL;
Ačkoli existuje, jak to již v céčku bývá, několik možností k
definování struktury, budeme se držet výhradně tohoto zápisu. Strukturu
definujeme jako nový datový typ pomocí klíčového slova
typedef
, čímž si dále usnadníme vytváření proměnných typu
UZIVATEL
. Následuje klíčové slovo struct
. Do
složených závorek deklarujeme prvky struktury jako obyčejné proměnné.
Název struktury uvádíme vždy VELKÝMI PÍSMENY a za ním následuje
středník.
Tělo funkce main()
nyní přepíšeme do následující
podoby:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char jmeno[51];
int vek;
char ulice[51];
} UZIVATEL;
int main(int argc, char** argv)
{
UZIVATEL uzivatele[10];
strcpy(uzivatele[0].jmeno, "Tomáš Marný");
uzivatele[0].vek = 33;
strcpy(uzivatele[0].ulice, "Šikmá 5");
strcpy(uzivatele[1].jmeno, "Josef Nový");
uzivatele[1].vek = 28;
strcpy(uzivatele[1].ulice, "Ve Svahu 8");
int i;
for (i = 0; i < 2; i++)
{
printf("Uživatel na indexu %d\n", i);
printf("Jméno: %s\n", uzivatele[i].jmeno);
printf("Věk: %d\n", uzivatele[i].vek);
printf("Ulice: %s\n\n", uzivatele[i].ulice);
}
return (EXIT_SUCCESS);
}
Celá aplikace je mnohem čitelnější. Obsahuje jednoduše jedno pole typu
UZIVATEL
místo předchozích 3 polí. K jednotlivým prvkům
struktur v poli přistupujeme pomocí operátoru tečky. Pokud jsou struktury
používány dynamicky (což ještě neumíme), používá se operátor šipky
(->
). Vše si ještě ukážeme dále v kurzu.
Další definice struktur
Jen pro úplnost si uveďme další způsoby, kterými lze strukturu
vytvořit a to zejména proto, abyste uměli číst cizí programy. Když
strukturu vytvoříme bez klíčového slova typedef
, pojmenujeme
ji malými písmeny:
struct uzivatel { char jmeno[51]; int vek; char ulice[51]; };
U proměnných typu této struktury musíme uvádět klíčové slovo
struct
:
struct uzivatel uzivatele[10];
Někdy se struktura definuje dokonce přímo s proměnnou:
struct { char jmeno[51]; int vek; char ulice[51]; } uzivatele[10];
Tento zápis berte spíše jako odstrašující příklad. To, že je něco kratší, vůbec neznamená, že je přehlednější. Navíc strukturu takto nemůžeme použít na více místech programu.
Pozn.: Struktury samozřejmě nemusíme používat jen v polích, je to
úplně normální datový typ jako např. int
. Zvyšuje
přehlednost a určitě ho používejte všude, kde potřebujete ukládat více
hodnot, které spolu logicky souvisí.
Pozn.: Kromě struktur můžeme v céčku definovat i tzv.
union
y. Ty se tváří stejně, jako struktury, ovšem proměnná
typu union
může mít vyplněnou jen jednu hodnotu. Každý
uživatel by tedy mohl mít vyplněné buď jen jméno, jen věk nebo jen ulici.
U uživatelů toto nedává příliš velký smysl, v praxi se nám teoreticky
může stát, že potřebujeme ukládat prvky a každý prvek je trochu jiný.
Stejně se union
y však příliš nepoužívají, je problém
poznat co je kde vyplněné (proto se často balí do struktur) a my se tu s
nimi nebudeme zabývat.
Ke strukturám se v kurzu ještě jednou vrátíme. Dnešní aplikaci máte níže ke stažení se zdrojovým kódem.
Tímto jste dočetli úvodní sekci seriálu do základů jazyka C. Gratuluji vám, jste seznámení s většinou jeho konstrukcí! Výuka samozřejmě pokračuje dále, jsou zde další cvičení a poté navazuje kurz Programování v jazyce C - Dynamická práce s pamětí v jazyce C, kde se dozvíte zejména jak v céčku dynamicky pracovat s pamětí a jak přestat být omezení délkou polí a řetězců. Protože je tato problematika poměrně komplikovaná a začátečníky často mate, byla od ni celá základní sekce odstíněná a vy jste si mohli bez zádrhelů vyzkoušet různé konstrukce céčka. Těším se na vás tedy dále, kdy začneme vytvářet reálně použitelné aplikace.
V následujícím cvičení, Řešené úlohy k 15. lekci Cečka, si procvičíme nabyté zkušenosti z předchozích lekcí.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 217x (32.65 kB)
Aplikace je včetně zdrojových kódů v jazyce C