Funksiyanın sintaksisi

Bir main funksiyasından ibarət olan aşağıdakı sadə proq­ra­ma­ baxaq:

 

#include <iostream>

using namespace std;

int main()

{cout<<"Hello World";

return 0;

}

Burada birinci sətir int main() – funksiyanın başlığıdır və ope­­ratorlardan fərqli olaraq ondan sonra “;”işarəsi qoyu­l­mur. Funk­siyanın başlığı nəticənin tipindən, funksiyanın adın­dan və parametrlər siyahısından ibarət olur. main sözü­nün əvvəlindəki verilənlər tipi – qaytarılan tipdir, main – funk­­siyanın adıdır, () – isə parametrlər siyahısını saxlayır (bu misalda siyahı boşdur).

Funksiyanın başlığından sonra { mötərizəsi ilə funk­si­ya­nın gövdəsi başlayır və bağlayıcı } mötərizəsi ilə qurtarır. Qeyd edək ki, funksiyanın gövdəsində başqa mötərizələr də işti­rak edə bilər, məsələn, if şərt operatorunda və ya dövr ope­ratorunda bir neçə operatorun yerləşdirilməsi üçün istifadə edilə bilər.

Funksiyanın gövdəsi bir və ya bir neçə operatordan ibarət ola­ bilər. Baxılan misalda funksiyanın gövdəsi iki ope­ra­tor­dan ibarətdir. Sonuncu operator return 0- qayıdış opera­toru­dur. Əgər qayıtma tipi void -dirsə, onda qayıdış operatorunu qoy­maq­ məcburi deyil.

Funksiyanın gövdəsi və başlığı birlikdə funksiyanın təyi­ni­ adlanır. Əgər funksiya təyin olunmayıbsa, onda o işlə­mə­yə­cək. Funksiya təyin olunduqda isə çağırıldığı zaman işlə­yə­cək. Funksiya adətən kodda çağırılır, yalnız main funk­si­ya­sı istisna təşkil edir. main funksiyası proqram bura­xı­lar­kən avtomatik olaraq çağırılır.

6.2. Funksiyanın təyin olunması

Əvvəlki bənddəki proqrama baxaq və kodu iki fun­ksi­ya­ya ayıraq: mainprintmessage (“Hello World” – ü çıxarır). Şərhlər (// ilə başlayan) printmessage funksiyasının təyini­nin başlanğıc və sonunu, həmçinin bu funksiyanın çağırıl­ma­sı­nı işarə edirlər:

# include < iostream >

using namespace std;

// printmessage funksiyasinin təyininin baslangıcı

void printmessage (void)

{

cout <<”Hello World”;

}

//printmessage funksiyasının təyininin sonu

int main()

{

printmessage (); // printmessage funksiyasının cağırılması

return 0;

}

Burada əvvəlcə printmessage funksiyası təyin olunur. Funksiyanın adının qarşısındakı void xidməti sözü onu göstərir ki, printmessage funksiyası qiymət qaytarmır. Funksiyanın adından sonra mötərizə daxilindəki void sözü onu göstərir ki, bu funksiyanın parametrləri yoxdur. Mötərizədə heç nə yazılmaya da bilər, bu funksiyanın adından sonra void yazılışı ilə ekvivalentdir.

printmessage funksiyasının gövdəsində ekrana “Hello World” məlumatını çıxaran bir parametr yerləşir. Funk­si­ya­nın gövdəsində qayıtma operatorunu yazmaq vacib deyil, ona­ görə ki, əgər qayıtmanın tipi void-disə, onda belə hesab olu­nur ki, qayıtma operatoru işləməmişdir. Lakin aşkar şəkildə qayıtma operatorunu yazmaq olar. Onda printmes­sa­ge­ funksiyası belə olar:

void printmessage (void)

{

cout <<”hello world”;

return;

}

6.3. Funksiyanın çağırılması

Əvvəlki bənddəki printmessage funksiyası main funk­si­ya­sına

printmessage();

sətri şəklində çağırılır. Bu misalda printmessage funksiyası main funksiyasından çağırıl­dı­ğına görə çağırılan funksiyadır. Baş mötərizə onu göstərir ki, bu funksiya ilə heç bir qiymət ötürülmür. Proqramın işlə­mə qaydası aşağıdakı kimidir:

1) icra prosesi main funksiyası ilə başlayır;

2) sonra main funksiyasının birinci operatoru- prin­tmes­sa­ge(­)­ funksiyası çağırılır;

3) bundan sonra icraetmə printmessage funksiyasına yönə­lir, onun birinci operatoru yerinə yetirilməyə başlayır və “Hello World” məlumatı ekrana çıxarılır.

4) printmessage funksiyasının işi sona çatdıqdan sonra proq­ram yenidən main funksiyasına, növbəti yerinə yeti­ril­mə­yən və proqramın sonuncu operatoru olan return 0 – ope­ra­­toruna qoşulur.

6.4. Prototipin yaradılması

Proqramın icrası main funksiyası ilə başladığından, on­da məntiqi olaraq belə nəticəyə gəlmək olar ki, main funk­si­ya­sı printmessage funksiyasından əvvəldə yerləş­mə­li­dir.Yəni,

#include <………..>

using namespace std;

int main()

{

printmessage();

return 0;

}

void printmessage (void)

{

cout <<”hello world”;

}

Lakin belə kod kompilyasiya olunmayacaq, print­messa­ge()­ sətri işıqlanacaq və “undeclared identifier” səhvi haqqında məlu­mat veriləcək.

Bu səhvin səbəbi ondan ibarətdir ki, kompilyator kodu yu­xa­rı­dan aşağıya keçərkən funksiyanın çağrılmasını görə­rək onun adını, qayıtma tipini və parametrlərini artıq bil­mə­li­dir. Lakin printmessage funksiyası main funksi­ya­sın­dan əv­vəl təyin olunduqda isə, kompilyator main funksi­ya­sın­da printmessage() müraciətini tapır, lakin onun haqqında hə­lə­lik­ heç nə bilmir: nə onun adını, nə qaytarılan qiymətin ti­pi­ni, nə parametrləri.

Bu problemin həlli – bütün funksiyaların təyininin main funk­siyasına qədər olmasından ibarətdir. Düzdür, bu halda proq­ram daha az oxunaqlı olacaq. Qeyd etmək lazımdır ki, funksiyaların yerləşmə ardıcıllığından asılı olmayaraq proq­ra­mın işi həmişə main funksiyası ilə başlayır. Funksiyaların sa­yı çox olduqda isə main funksiyası onları bir- birinin ar­dın­ca çağırır. Mürəkkəb proqramlarda, yəni bir funksiya di­gər bir funksiyanı, o isə başqa bir funksiyanı və s. çağır­dıq­da funk­si­ya­ların təyin olunma ardıcıllığında səhv olmaması üçün main-dən başqa bütün funksiyaların prototipinin yaradılması zəru­ri­dir. Aşağıdakı proqramda printmessage() funksiyası üçün pro­to­tipin necə yaradılması göstərilir:

# include <inter>

using namespace std;

void printmessage (void);// bu prototipdir

int main()

{

printmessage();

return 0;

}

void printmessage (void)

{

cout <<”hello world”;

}

Beləliklə, prototip bütün funksiyaların təyinindən yük­sək­də da­yanır və kompilyator kodu yuxarıdan aşağıya ke­çər­­kən hər bir funksiyanın qarşısında dəqiq prototip görür. Onu da qeyd edək ki, prototip funksiyasının başlığına ox­şa­yır, əsas fərq on­da­dır ki, o operatordur və ondan sonra hə­mi­şə­ nöqtə vergül ya­zı­lır.

 

Lokal dəyişənlər

İndiyə qədər bütün dəyişənlər main funksiyasının yuxarı his­səsində yerləşirdi. Bir main funksiyası olan proqramlarda bu dəyişənlərə proqramın istənilən yerində müraciət etmək olar. Lakin kodu bir neçə müxtəlif funksiyaya böldükdə dəyi­şənin görünmə oblastı və mövcudluq zamanı ilə bağlı problemlər ya­ra­nı­r.

Eyni bir funksiyanı bir neçə dəfə çağırmaq olar. Aşa­ğı­da­kı proq­ramda printmessage funksiyası istifadəçinin istə­di­yi qədər ça­ğırılır və hər dəfə ekrana bu funksiyanın çağrılma sa­yı çıxarılır:

# include <inter>

using namespace std;

void printmesage (void);

int main()

{

int times=0;

char choice;

do {

cout <<”Enter Q to quit, any other character to continue:”;

cin >> choice;

if (choice ==’Q’)

cout << ”input stopped”;

else printmessage ();

} while (choice !=’Q’);

return 0;

}

void printmesage (void)

{

times + +;

cout << ”this function colled”<< times << ”times \ n”;

}

Bu kod kompilyasiya olunmayacaq, belə ki, print­mes­sa­g­e funk­siyasında times dəyişəni elan olunmayıb (“undeclared iden­tifier”). Kompilyatorun bu səhvini times dəyişəninin ela­nı­nı printmessage funksiyasına köçürməklə aradan qaldırmaq olar:

void printmessage (void)

{

int times=0;

times ++;

cout << “ this function called” << times << ”times \ n;

}

times dəyişəni printmessage funksiyası üçün lokal dəyi­şən­dir, çün­ki həmin funksiyanın daxilində təyin olunub. Ona gö­rə də times lokal dəyişən olduğundan hər dəfə print­mes­sa­ge­ funk­si­ya­sı çağırılarkən o yaradılır, hər dəfə printmessage funk­siya­sı­nın icrası sona çatdıqdan sonra o ləğv olunur. Beləliklə, ikin­ci dəfə print­mes­sage funksiyası çağırıldıqda times də­yi­şə­ni print­mes­sage funksiyasının birinci çağırışında yara­dı­lan times dəyi­şə­ninin davamı ol­mur. print­mes­sage funk­si­ya­sı­nın hər bir çağırışında times dəyişəni yenidən yaradılır.

Qeyd edək ki, funksiyaya müxtəlif müraciətlər zamanı dəyi­şənin qiymətini iki üsulla saxlamaq olar. Birincisi, lokal dəyi­­şən əvəzinə qlobal dəyişən istifadə etməklə, ikincisi, statik lokal dəyişəndən istifadə etməklə.

Qlobal dəyişənlər

“Qlobal” termini onu göstərir ki, dəyişən bütün proqram da­xilində görünmə oblastına malikdir, ona görə də onun möv­cud­luq vaxtı yalnız proqram öz işini sona çatdırdıqdan son­ra qur­ta­rır. Dəyişənin qlobal olması üçün onu funk­si­ya­la­rın pro­to­tip­lə­ri ilə bütün funksiyaların tipinə qədər elan et­mək lazımdır:

# include <inter>

using namespace std;

void printessage ();

int times;

int main()

{

times=0;

char choice;

do{

cout <<”Enter Q to quit, any other character to continue:”;

cin >> choice;

if (choice==’Q’)

cout <<”input stopped”;

else

printmessage();

} while (choice!=’Q’);

return 0;

}

void printmessage (void)

{

times++;

cout << ”this function called” << times <<”times \ n”;

}

Qeyd edək ki, dəyişənlərin qloballaşdırılması onlara proq­ra­mın istənilən yerində müraciət etməyə imkan versə də, qlo­bal dəyişənin nə səbəbə düzgün olmayan qiymət almasını tap­maq prosesi çətinləşir. Ona görə də imkan daxilində proq­ram­çıların qlobal dəyişənlərdən istifadə etməmələri məs­lə­hətdir. Qlobal də­yişənlərə alternativ olaraq statik lokal də­yi­­şənləri göstərmək olar.