B-PROG2 K štruktúram

K štruktúram


Dátový typ


Jazyk C je typový, a teda každá premenná musí mať určitý dátový typ. Čím je charakterizovaný dátový typ?

  1. určuje, koľko miesta premenná zaberie v pamäti
    • napr. typ int zaberá viac miesta ako typ char
    • na zistenie potrebného miesta slúži operátor sizeof
  2. určuje, ako interpretujeme dáta patriace do tejto premennej
    • u celých čísel rozsah/znamienko: int, long int, unsigned short int, char (pozn.: aj char je v C-čku celočíselný typ)
    • u desatinných čísel aj presnosť: float vs. double
    • u smerníka typ údaju na adrese uloženej v smerníkovej premennej: int*, int**, void* (pozn.: posledný je typ beztypový smerník. Premenná tohto typu má typ void*, ale miesto, kam ukazuje je bez určeného typu, t.j. ľubovoľné!)
  3. určuje, aké operácie sú platné pre premenné daného typ
    • dá sa čítať hodnota premennej, a zapisovať nová hodnota (u premennej konštantného typu (napr. const int) sa hodnota po prvom zápise nedá zmeniť)
    • nad celočíselnými premennými sa dajú prevádzať aritmetické, bitové a logické operácie
    • pre float/double sú povolené aritmetické a logické operácie (ale nie napr. operácia %)
    • pre typové smerníky sa vykonáva smerníková aritmetika (pripočítanie celého čísla ako posun adresy, rozdiel 2 smerníkov)

Špecifickým údajovým typom je zložený údajový typ – štruktúra, viď napr.: (http://en.wikipedia.org/wiki/Struct_%28C_programming_language%29)

Štruktúrový typ podporuje priradenie (čítanie/zápis), ale nepodporuje aritmetické a logické operácie. Ak potrebujeme operácie, musíme si pripraviť v jazyku C vlastné funkcie.

Príklad zo skúšky


  • Napíšte deklaráciu zloženého dátového typu s názvom Point s 2 zložkami x, y (celé čísla).

Použijeme klasickú deklaráciu s typedef, aby sme nemuseli všade ďalej písať struct:

  • Napíšte funkciu, ktorej vstupom sú 2 body (t.j. typ je novo zadefinovaný Point), a výstupom je ich (Euklidovská) vzdialenosť (t.j. VZOREC, kde x1, y1 a x2, y2 sú príslušné súradnice bodov).

Akonáhle nový typ zadefinujeme, už ho môžeme používať na deklaráciu premenných úplne klasicky. Funkcia dostane 2 body (povedzme A, B) a vyrobí desatinné číslo (odmocnina vo vzorci!). Kým v matematickom vzorci vystupujú x1, y1 a x2,y2, pre nás to budú x-ová a y-ová zložka bodov A, a B. Pri umocňovaní na druhú spravíme optimalizáciu s medzipremennou. Výsledok je: 

Všimnite si prototyp:

Programátor, čo chce funkciu použiť, vie, že musí pripraviť 2 body a ona mu vypočíta ich vzdialenosť. Nemusí pracovať so 4 vstupmi, ale iba s dvomi. Nemusí sa zaoberať, v akom poradí sú súradnice, použiť (x1, x2, y1, y2) alebo radšej (x1, y1, x2, y2), alebo na preskáčku? Na otestovanie stačí:

Keby sme chceli použiť 3D priestor, stačí ľahká úprava:

  • Napíšte deklaráciu zloženého dátového typu Triangle s 3 zložkami A,B,C (typu Point).

Toto je vlastne príklad na vnorenú štruktúru. Využíva sa fakt, že v štruktúre môže byť ľubovoľný počet zložiek ľubovoľných typov. U nás sú to tri body, t.j.

  • Napíšte funkciu, ktorej vstupom je trojuholník (typ Triangle) a výstupom je jeho obvod.

Tu využijeme extrémne zjednodušenie poskytnuté štruktúrami. Namiesto uvažovania so 6 vstupmi (v 2D priestore: po 2 súradnice 3 bodov, v 3D priestore by to bolo až 9 vstupov), stačí uvažovať jediný vstup – celý trojuholník. Výstupom je obvod, a teda desatinné číslo. Obvod je súčet dĺžok strán. Dĺžku strany ale vieme jednoducho vypočítať pomocou funkcie dist. Riešenie je teda:

Úprava na 3D priestor je ešte triviálnejšia ako v predošlom prípade:

  • Úloha: (POZOR, MATEMATIKA :) ) Napíšte funkciu, ktorej vstupom sú dva trojuholníky (2D). Funkcia zistí, či sa prekrývajú (vráti pravda/nepravda).

Zložitejší príklad


Štruktúry sa dajú využívať podobne ako základné typy na vytvorenie poľa, štruktúry vieme vracať z funkcie, dajú sa používať smerníky na štruktúry. Pozrime sa na nasledujúci príklad: Vstupom funkcie je pole trojuholníkov. Funkcia vráti trojuholník s najväčším obvodom.

Napíšme si najprv klasickú funkciu na nájdenie najväčšieho čísla v poli:

Čo treba zmeniť? Pracujeme nie s číslami (int), ale s trojuholníkmi (Triangle):

Horeuvedený kód by sa ale nemal dať skompilovať, keďže trojuholníky nevieme porovnávať operátorom >. Nemáme však porovnávať trojuholníky, ale ich obvod, čiže píšeme:

Nevýhoda tohto riešenia je, že vždy nanovo počítame obvod trojuholníka max. Ak nám záleží na efektivite, kód vieme ďalej upraviť pomocou pomocných premenných:

Posledný zdroj neefektivity spočíva v príkaze max = pole[i]. Týmto príkazom sa skopíruje 6 súradníc z trojuholníka pole[i] do premennej max. Namiesto toho si nám stačí zapamätať index v poli (alebo pointer!):