Lokálne a globálne premenné
Lokálne premenné sme používali doteraz:
void __fastcall TForm1::Button1Click(TObject *Sender) { int Pocet=0; Pocet++; Button1->Caption=Pocet; }
Premenná Pocet je deklarovaná v rámci tela funkcie. Taká premenná:
- vznikne pri spustení funkcie a zanikne pri skončení funkcie - má lokálnu existenciu
- je "viditeľná" od miesta deklarácie, ale iba pre príkazy funkcie, v ktorej bola deklarovaná (príkazy inej funkcie ju nevidia) - má lokálnu viditeľnosť
Takáto premenná sa nazýva lokálna premenná.
Premenné sa dajú deklarovať aj mimo tela funkcie:
int Pocet=0;
void __fastcall TForm1::Button1Click(TObject *Sender) { Pocet++; Button1->Caption=Pocet; }
Premenná Pocet je globálna premenná:
- vznikne pri spustení programu, zanikne pri skončení programu
- je viditeľná od miesta deklarácie
Pozor na globálne a lokálne premenné, ktoré majú rovnaké mená: int Pocet=0;
void __fastcall TForm1::Button1Click(TObject *Sender) { int Pocet=0; Pocet++; Button1->Caption=Pocet; }
Pri vykonávaní funkcie:
- v pamäti počítača existujú dve premenné Pocet (lokálna a globálna premenná)
- príkazy funkcie však vidia (používajú) iba lokálnu premennú Pocet - hovoríme, že lokálna premenná prekryla globálnu premennú.
Grafická plocha ako globálna premenná
Zadeklarujeme globálne premenné g, Sirka, Vyska. Tieto premenné musíme inicializovať vo funkcii TForm1::TForm1, ktorá sa, zjednodušene povedané, vykoná po spustení programu: TCanvas *g; int Sirka, Vyska;
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { g=Image1->Canvas; Sirka=Image1->Width; Vyska=Image1->Height; }
void __fastcall TForm1::Button2Click(TObject *Sender) { g->Rectangle(0, 0, 50, 50); }
void __fastcall TForm1::Button3Click(TObject *Sender) { g->Ellipse(0, 0, 50, 50); }
V programoch sa vo všeobecnosti vyhýbame globálnym premenným a snažíme sa, čo možno najviac, používať lokálne premenné.
Definovanie vlastných funkcií
Čo už vieme:
- program v C++ sa skladá z niekoľkých (väčšinou veľmi veľa) funkcií
- telo každej funkcie obsahuje príkazy, ktoré sa postupne vykonávajú
- niektoré funkcie sme používali (StrToInt, random ... sú to funkcie, aj keď sme im doteraz hovorili všeobecnejšie - príkazy)
- programovali sme telá funkcií, ktoré sa vykonávali pri kliknutí na tlačidlo.
Definovanie funkcie bez parametrov a návratovej hodnoty:
void MenoFunkcie() { telo_funkcie }
* hlavička funkcie:
o vyhradené slovo void znamená, že funkcia iba vykoná príkazy o meno funkcie je identifikátor (platia preň rovnaké pravidlá, ako pre pomenovanie premenných) o do zátvoriek () uvádzame parametre (funkcia zatiaľ nemá žiadne parametre, preto sú zátvorky prázdne)
- za hlavičkou funkcie nasleduje telo funkcie - príkazy sú uzavreté v zložených zátvorkách { }
Vytvoríme vlastnú funkciu NahodnyKruzok:
void NahodnyKruzok() // hlavička funkcie { int x, y; // telo funkcie x=random(Sirka); y=random(Vyska); g->Ellipse(x-10, y-10, x+10, y+10); }
void __fastcall TForm1::Button4Click(TObject *Sender) { NahodnyKruzok(); // volanie funkcie }
void __fastcall TForm1::Button5Click(TObject *Sender) { int i; for (i=1; iBrush->Color=clWhite; g->Pen->Color=clWhite; g->Rectangle(0, 0, Sirka, Vyska); }
Poznámka: Vo vlastných funkciách nemôžeme inicializovať grafickú týmto spôsobom: TCanvas * g=Image1->Canvas; g->Rectangle(0, 0, Image1->Width, Image1->Height); Je to preto, že komponenty formulára nie sú vo vlastných funkciách priamo viditeľné. Museli by sme písať: TCanvas * g=Form1->Image1->Canvas; g->Rectangle(0, 0, Image1->Width, Image1->Height); My radšej budeme používať globálne premenné g, Sirka, Vyska.
Funkcie s jednoduchými parametrami
Teraz nechceme kresliť náhodne umiestnený krúžok. Chceme nakresliť krúžok, ktorý leží na určitom mieste - napríklad, jeho stred má súradnice x, y. Treba zabezpečiť, aby sa funkcia "dozvedela" tieto súradnice. Na to požívame parametre funkcie: void Kruzok(int x, int y) { g->Ellipse(x-10, y-10, x+10, y+10); }
void __fastcall TForm1::Button6Click(TObject *Sender) { Kruzok(100, 100); // volanie funkcie s parametrami Kruzok(200, 100); }
Hlavička funkcie obsahuje zoznam parametrov:
- parametre deklarujeme v tvare: typ_parametra názov_parametra
- ak má funkcia viacero parametrov, oddeľujeme ich čiarkami: typ1 nazov1, typ2 nazov2 ....
Parametre funkcie majú podobné vlastnosti ako lokálne premenné:
- sú viditeľné pre príkazy z tela funkcie
- vzniknú pri zavolaní funkcie, zaniknú pri skončení funkcie
- navyše, do parametrov sa priradia hodnoty, ktoré sme uviedli v zátvorkách pri volaní funkcie
Príklad: Funkcia Usecka:
void Usecka(int x1, int y1, int x2, int y2) { g->MoveTo(x1, y1); g->LineTo(x2, y2); }
void __fastcall TForm1::Button7Click(TObject *Sender) { Usecka(10, 10, 100, 50); }
void __fastcall TForm1::Button8Click(TObject *Sender) { int i; for (i=0; iTextOut(0, 0, n); // vypíše sa 40 }
Hlavička funkcie obsahuje namiesto slova void vyhradené slovo int. Tým je povedané, že výsledok funkcie je celé číslo (takáto funkcia nielenže vykonáva príkazy, ale "dáva" celočíselný výsledok).
Príkaz return hodnota;:
- týmto príkazom určíme výsledok funkcie - tzv. návratovú hodnotu
- v prípade, že sa za vyhradeným slovom return nachádza výraz, výraz sa najskôr vyhodnotí a jeho hodnota sa použije ako výsledok funkcie
- príkaz return zároveň ukončí vykonávanie funkcie (ak by za príkazom return nasledovali ďalšie príkazy, nevykonajú sa)
Príklad: Z matematiky poznáme definíciu mocniny: x->x2. To isté môžeme v C++ zapísať nasledujúcim spôsobom: float Mocnia(float x) { return x*x; // vráť výsledok x2 }
void __fastcall TForm1::Button10Click(TObject *Sender) { g->TextOut(0, 20, Mocnina(10)); // výsledok vypíšeme priamo do grafickej plochy }
Nasledujúca funkcia vypočíta súčet 1+2+...+n:
int Sucet(int n) { int i, s; s=0; for (i=1; iTextOut(0, 40, Sucet(10)); g->TextOut(0, 60, Sucet(20)); }
Knižnice funkcií
V programoch môžeme používať rôzne matematické funkcie, ktoré už niekto naprogramoval a zabalil to tzv. knižníc. Matematické funkcie, napr., sin, cos, sqrt (sínus, kosínus, odmocnina) a ďalšie sa nachádzajú v matematickej knižnici s názvom math. Aby sme príkazy mohli používať, treba na začiatok programu vložiť informáciu pre kompilátor o tom, ktoré knižnice program potrebuje: #include #pragma hdrstop
#include #include "Unit1.h"
Teraz môžeme použiť funkciu sin:
g->TextOut(0, 60, sin(1)); // sínus 1 radiánu
Farby pomocou RGB
Poznáme typ TColor a niekoľko základných farieb: clBlack, clWhite, clRed... Ak chceme používať iné farby musíme ich "namiešať". V počítačoch sa farby miešajú pomocou svetiel Red, Green, Blue - ich vzájomná intenzita určuje výslednú farby. Intenzita každého svetla sa udáva celým číslom v rozsahu . K dispozícií tak máme 2563 možných kombinácií, ktoré sú očíslované.
Funkcia RGB(r, g, b) vráti číslo farby, ktorá vznikne zmiešaním červeného, zeleného a modrého svetla:
RGB(0, 0, 0) ... číslo pre čiernu farbu RGB(255, 0, 0) ... číslo pre červenú farbu RGB(255, 0, 255) ... číslo pre fialovú farbu
V programoch pri nastavovaní farby nepoužívame čísla ale hodnoty typu TColor - z "čísla farby" treba vyrobiť "farbu": TColor(RGB(255, 0, 0)).
Príklad použitia:
void __fastcall TForm1::Button8Click(TObject *Sender) { int i; for (i=0; iPen->Color=TColor(RGB(i, i, 0)); Usecka(i, 0, i, 100); } }
Zhrnutie
Písanie funkcií je veľmi elegantný a efektívny spôsob vytvárania programov. Ak chceme používať rovnaký algoritmus na viacerých miestach programu, vytvoríme funkciu, v ktorej algoritmus raz naprogramuje. Potom funkciu voláme na miestach, kde sa má algoritmus vykonať.
Definovanie funkcie:
typ meno(parametre) { telo_funkcie }
- typ ... typ výsledku - aké hodnoty funkcia vracia (void, int, float ...)
- meno ... meno funkcie
- parametre ... zoznam parametrov oddelených čiarkami
- telo_funkcie ... príkazy
Ak funkcia vracia výsledok (ak typ výsledku nie je void), musíme v tele funkcie vykonať príkaz:
return výraz;
Príkaz return ukončí vykonávanie funkcie, pričom výsledkom funkcie bude hodnota výrazu.