Struktury
V této kapitole si představíme, jak si můžeme sami vytvářet komplexní datové typy. Sloužit nám k tomu budou struktury
(klíčové slovo struct
).
Mějme program, který dostane tři souřadnice bodu a vytiskne daný bod tolikrát, kolikrát mu definujeme parametrem pocet_tisk
.
#include <stdio.h>
void vytiskni_bod(int x, int y, int z, int pocet_tisku) {
for (int i = 0; i < pocet_tisku; i = i + 1) {
printf("x je %i, y je %i, z je %i\n", x, y, z);
}
}
int main()
{
int x = 1;
int y = 2;
int z = 3;
int pocet_tisku = 1;
vytiskni_bod(x, y, z, pocet_tisku);
return 0;
}
S rostoucím počtem parametrů a proměnných je někdy těžké pak určit, co patří k čemu. Tento problém nám řeší struktury, které nám umožňují logicky spojit hodnoty, které patří k sobě.
Struktury se definují následovně
Kde název struktury je klasický identifikátor jako u proměnných a funkcí (spolu se stejnými omezeními).
Každá struktura může mít libovolný počet tzv. fieldů. Field obsahuje název a datový typ. Je to velmi podobné definování proměnné.
Definujme si strukturu s názvem bod
, která bude mít tři fieldy typu int.
struct bod { int x; int y; int z; };
Tohle je náš nový datový typ s názvem struct bod
. Jak vytvoříme proměnnou tohoto datového typu? Stejně jako bychom to udělali v případě datového typu int. Tzv. nejdříve napíšeme datový typ a následně název proměnné. Vytvořme si tedy proměnnou s názvem prvni_bod
.
struct bod prvni_bod;
Pro použití struktury tedy potřebujeme dva kroky
- Nejdříve datovou strukturu definovat
- Poté vytvořit proměnnou, která bude datového typu námi vytvořené struktury
Stejně jako můžeme vytvořit více proměnných typu int
, tak můžeme vytvořit i více proměnných datového typu struct bod
.
struct bod prvni_bod;
struct bod druhy_bod;
struct bod treti_bod;
Můžeme nyní přepsat náš program pomocí struktury
#include <stdio.h>
struct bod { int x; int y; int z; };
void vytiskni_bod(struct bod bod_k_tisku, int pocet_tisku) {
for (int i = 0; i < pocet_tisku; i = i + 1) {
printf("x je %i, y je %i, z je %i\n", bod_k_tisku.x, bod_k_tisku.y, bod_k_tisku.z);
}
}
int main()
{
struct bod prvni_bod;
prvni_bod.x = 1;
prvni_bod.y = 2;
prvni_bod.z = 3;
int pocet_tisku = 1;
vytiskni_bod(prvni_bod, pocet_tisku);
return 0;
}
Všimněme si, že struktury definujeme v hlavním bloku programu (pod #include
). Další důležitá věc je, že pokud chceme pracovat s fieldy struktury, tak musíme napsat název proměnné, pak tečku a pak název fieldu. Například pokud chceme nastavit field x
naší proměnné prvni_bod
, tak uděláme
prvni_bod.x = 1;
Pozor na to, že pokud byste definovali strukturu uvnitř funkce, tak se vám to sice podaří
#include <stdio.h>
int main()
{
struct bod { int x; int y; int z; };
struct bod prvni_bod;
prvni_bod.x = 1;
prvni_bod.y = 2;
prvni_bod.z = 3;
return 0;
}
Ale jakmile se ji pokusíte použít v jiné funkci, tak dojde k chybě. Například zde
#include <stdio.h>
void vytiskni_bod(struct bod bod_k_tisku, int pocet_tisku) {
for (int i = 0; i < pocet_tisku; i = i + 1) {
printf("x je %i, y je %i, z je %i\n", bod_k_tisku.x, bod_k_tisku.y, bod_k_tisku.z);
}
}
int main()
{
struct bod { int x; int y; int z; };
struct bod prvni_bod;
prvni_bod.x = 1;
prvni_bod.y = 2;
prvni_bod.z = 3;
return 0;
}
Dostáváme informaci
...\main.c|3|warning: 'struct bod' declared inside parameter list will not be visible outside of this definition or declaration|
To nám říká, že počítač si myslí, že se snažíme definovat strukturu na řádku 3 (protože nevidí na definici uvnitř funkce main
).
Dále dostáváme chybu
...\main.c|3|error: parameter 1 ('bod_k_tisku') has incomplete type|
Počítač si myslí, že se snažíme definovat strukturu, ale definice je špatně (chybí fieldy). To je ale omyl, my jsme se na řádku 3 nesnažili nic definovat, akorát program nevidí naši definici uvnitř funkce main
.
Proto musíme dávat definice struktur vždy mimo funkce.
Anonymní struktura
Pokud bychom chtěli strukturu použít jenom v jedné funkci a pouze pro jednu proměnnou, tak můžeme strukturu definovat anonymně (bez názvu) přímo u dané proměnné
#include <stdio.h>
int main()
{
struct { int x; int y; int z; } prvni_bod;
prvni_bod.x = 1;
prvni_bod.y = 2;
prvni_bod.z = 3;
return 0;
}
Tento zápis není moc praktický a využívá se především při vytváření aliasů pomocí klíčového slova typedef
viz níže.
Inicializace
Strukturu můžeme inicializovat tak, že dáme honotu do složených závorek a pro každý field dáme tečku, název fieldu, rovnítko a hodnota. Následující program
#include <stdio.h>
struct bod { int x; int y; int z; };
int main()
{
struct bod prvni_bod = { .x = 1, .y = 2, .z = 3 };
printf("x je %i, y je %i, z je %i\n", prvni_bod.x, prvni_bod.y, prvni_bod.z);
return 0;
}
Vytiskne
x je 1, y je 2, z je 3
Typedef
Klíčové slovo typedef
nám umožňuje definovat nové jméno již existujícímu datovému typu (říkáme alias).
Velmi často se to používá se strukturama. Abychom nemuseli psát při definici proměnné
struct bod prvni_bod;
Můžeme vytvořit alias naší struktůře pomocí
typedef struct bod bod_alias;
A pak můžeme definovat proměnné typu struct bod
pomocí
bod_alias prvni_bod;
Náš předchozí program bychom mohli přepsat na
#include <stdio.h>
struct struktura_bod { int x; int y; int z; };
typedef struct struktura_bod bod;
void vytiskni_bod(bod bod_k_tisku, int pocet_tisku) {
for (int i = 0; i < pocet_tisku; i = i + 1) {
printf("x je %i, y je %i, z je %i\n", bod_k_tisku.x, bod_k_tisku.y, bod_k_tisku.z);
}
}
int main()
{
bod prvni_bod;
prvni_bod.x = 1;
prvni_bod.y = 2;
prvni_bod.z = 3;
int pocet_tisku = 1;
vytiskni_bod(prvni_bod, pocet_tisku);
return 0;
}
A již můžeme všude psát bod
místo struct bod
.
Definici struktury a její alias můžeme spojit i do jednoho řádku. Místo
struct struktura_bod { int x; int y; int z; };
typedef struct struktura_bod bod;
Napíšeme
typedef struct { int x; int y; int z; } bod;
Využívá se tu principu anonymní struktury.
Vytvářet aliasy můžete i pro libovolné jiné datové typy. Například si můžete vytvořit vlastní alias pro datový typ int
.
#include <stdio.h>
typedef int muj_int;
int main()
{
muj_int x = 10;
printf("x je %i\n", x);
return 0;
}
Aliasy je možné pak kombinovat i s původním datovým typem. Je to pouze pro programátory pro lepší přehlednost.
#include <stdio.h>
typedef int muj_int;
int main()
{
muj_int x = 10;
int y = x;
printf("x je %i, y je %i\n", x, y);
return 0;
}
Úkoly na procvičení
Úkol 1
XXX
Klikni pro zobrazení možného řešení
#include <stdio.h>
int main()
{
char vstup;
printf("Zadejte znak:\n");
scanf("%c", &vstup);
printf("Zadali jste znak %c\n", vstup);
return 0;
}
Fun fact
Jedna z velmi vlivných programátorek byla Margaret Hamilton. Podílela se na vývoji softwaru pro Apollo program od NASA.
Právě ona definovala pojem "softwarové inženýrství". Tím přidala další typ inženýrství (jako chemické, mechanické, elektrické atd.).
Na obrázku je Margaret vyfocená s vytisknutým zdrojovým kódem, který dostal Apollo 11 na Měsíc. Tento zdrojový kód je dnes veřejně dostupný na Githubu zde.
Více například zde (anglický zdroj)
Odkazy
Následující kapitola: Práce se soubory