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
Kruzok(100, 100); // parameter x==100 a y==100 Kruzok(200, 100); // parameter x==200 a y==100

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.