| ← vytváření typů | C/C++ | ukazatele na funkce → |
V této kapitole si povíme o dalších podivuhodných konstrukcích jazyka C. Zde probírané konstrukce patří již k těm pokročilejším a jejich využití není tak časté, ale přesto se vyplatí je znát. Zvláště výčtový typ enum.
Typ enum nám umožní vytvořit proměnnou, která může obsahovat hodnoty konstant určených při deklaraci výčtového typu. Proměnná se vytváří pomocí typedef. Deklarace typu enum má hodně společného s deklarací struktury. Lze vytvořit buďto jen výčtový typ enum (stejně jako jenom strukturu), nebo pomocí typedef definovat nový datový typ. Protože je lepší a častější použití s typedef, ukáži jenom jednou syntaxi výčtového typu a dále v příkladech budu pracovat jen s konstrukcí s typedef.
enum [jmeno] {
seznam konstant
...
} [promenne];
Příklad vytvoření výčtového typu:
enum kalendar {
leden = 1, unor, brezen, duben, kveten, cerven, cervenec, srpen, zari, rijen,
listopad, prosinec
} a, b;
...
a = unor;
...
if (b == duben) { ...
V příkladu jsem vytvořil výčtový typ se jménem kalendar a definoval dvě proměnné a a b. Konstanty výčtového typu jsou vždy celočíselné. Pokud konstantě nepřiřadíme hodnotu (jako leden=1), pak má hodnotu o jednotku vyšší, než konstanta předešlá (unor tedy odpovídá číslu 2, brezen 3 atd). Pokud nepřiřadíte hodnotu ani první konstantě, automaticky je jí přiřazena nula. Hodnoty lze přiřadit kterékoliv konstantě ve výčtovém typu. Opět platí, že následující konstanta, pokud nemá přiřazenou hodnotu, je o jednotku větší, než předcházející konstanta. Překladač tyto konstanty chápe pouze jako čísla. Je tedy dost dobře možné je srovnávat s čísly (např if(leden == 1)),ale to by zcela postrádalo smysl. Výčtový typ se používá právě proto, aby se v programu nemusela konkrétní čísla používat. Použití výčtového typu se hodně podobá makrům preprocesoru. Jeho výhodou je právě to, že lze vytvářet proměnné výčtového typu, čímž se dá program zpřehlednit a jeho čtení je pak o něco snazší. Taktéž překladač může odhalit všelijaké chyby.
V následujícím příkladu je již vidět použití typu enum s konstrukcí typedef.
1: /*------------------------------------------------*/ 2: /* enum1.c */ 4: #include <stdio.h> 6: typedef enum { 7: vlevo, vpravo, stred, center = stred 8: } zarovnani; 11: void tiskni_znak(char ch, zarovnani zr) 12: { 13: switch (zr) { 14: case vlevo: 15: printf("%c\n", ch); 16: break; 17: case vpravo: 18: printf("%50c\n", ch); 19: break; 20: case stred: 21: printf("%25c\n", ch); 22: break; 23: default: 24: printf("%c%24c%25c\n", '?', '?', '?'); 25: } 26: } 28: int main(void) 29: { 30: tiskni_znak('A', 50); 31: tiskni_znak('X', vlevo); 32: tiskni_znak('Y', center); 33: tiskni_znak('Z', vpravo); 34: return 0; 35: } 37: /*------------------------------------------------*/
Výstup z programu:
? ? ?
X
Y
Z
Syntaxe typu union je stejná jako struktury, až na to, že místě klíčového slova struct se použije klíčové slovo union. Význam jednotlivých položek je stejný. Jeho použití s konstrukcí typedef také.
union [jmeno] {
typ jmeno_polozky;
typ jmeno_polozky;
...
} [promenne];
Rozdíl tu však je. Zatímco struktura si vytvoří paměťové místo pro všechny položky, typ union zabírá v paměti jen tolik místa, kolik největší jeho položka. Z toho také vyplývá, že lze používat v jeden okamžik jen jednu položku. Kterou, to už závisí na programátorovi. Každá položka začíná v začátku paměti unie.
Typ union může při programování ušetřit paměť. Navíc můžeme vytvořit funkci, která bude vracet různé datové typy jako typ union (viz příklad níže). Prvkem v union může být i struktura, nebo jiný typ union atp..
V příkladu se seznámíme, kromě použití výčtového typu enum a typu union, se dvěma novými funkcemi. Funkce rand() vrací pseudonáhodné číslo v rozmezí 0 až RAND_MAX. Pseudonáhodné proto, protože vrací čísla z číselné řady generované na základě nějakých matematických podmínek. Aby tyto čísla nebyli při spuštění programu generována vždy stejně, nastaví se počátek této řady pomocí funkce srand(). Argumentem této funkce je číslo typu unsigned int. Dobré je předat této funkci jako argument aktuální čas. Protože pracovat s časem ještě neumíme, nastavíme jej podle toho, co nám zadá uživatel. Budete-li jako uživatel zadávat stále stejné číslo, bude program vracet stále stejné výsledky. Příklad použití srand() s časem najdete až v kapitole věnující se standardnímu hlavičkovému souboru <time.h>.
Funkce rand() a srand() jsou definovány ve standardním hlavičkovém souboru <stdlib.h>.
1: /*------------------------------------------------*/ 2: /* union.c */ 4: #include <stdio.h> 5: #include <stdlib.h> 7: typedef enum { 8: znak, cele, racionalni 9: } typ; 11: typedef union { 12: char ch; 13: unsigned int uin; 14: float fl; 15: } datovy_typ; 17: datovy_typ nahodne_cislo(typ t) 18: { 19: datovy_typ x; 21: switch (t) { 22: case znak: 23: x.ch = (char) (rand() % ('z' - 'a')) + 'a'; 24: break; 25: case cele: 26: x.uin = (unsigned int) rand(); 27: break; 28: case racionalni: 29: x.fl = (float) rand() / RAND_MAX; 30: break; 31: } 32: return x; 33: } 35: int main(void) 36: { 37: datovy_typ un; 39: printf("Zadej cislo: "); 40: if (scanf("%u", &un.uin) == 0) 41: return 1; 43: srand(un.uin); 44: un = nahodne_cislo(racionalni); 45: printf("float = %f\n", un.fl); 47: un = nahodne_cislo(znak); 48: printf("char = %c\n", un.ch); 50: un = nahodne_cislo(cele); 51: printf("int = %i\n", un.uin); 53: printf("velikost un = %u == float = %u\n", sizeof(un), sizeof(float)); 54: return 0; 55: } 57: /*------------------------------------------------*/
Možný výstup z programu:
Zadej cislo: 123 float = 0.060051 char = n int = 436085873 velikost un = 4 == float = 4
| ← vytváření typů | C/C++ | ukazatele na funkce → |
