C Proqramlaşdırma funksiyaları

giriş

Tutaq ki, iki ədədi daxil etmək və istifadəçinin xahiş etdiyi arifmetik əməliyyatı yerinə yetirmək üçün bir proqram yazmalıyıq. İstifadəçi toplama, çıxma, vurma və bölmə kimi hər hansı bir hesab əməliyyatını istəyə bilər. Proqramı necə yazacağıq? Əsas funksiyası olan bir C proqramı yazacağıq, burada iki ədədi və əməliyyatı qəbul edəcəyik. İstifadəçinin daxil etdiyi əməliyyata görə, nömrələri əlavə / çıxartmaq / çoxaltmaq / bölmək şərtimiz olacaqdır. Bu sadə tələb üçün birbaşa irəli addımlardır. Təsəvvür edin ki, iki ədəd üzərində bu əməliyyatlar daha çox ədədin və ya sıra massivinin artması ilə artır. Sonra hər 'if' ifadəsi içindəki kod da artacaq. Yəni tələb dəyişdikdə və ya mürəkkəbləşdikdə kod da artır və mürəkkəbləşir. Bu da kodun oxunaqlılığını azaldır. Bu əməliyyatlar toplusunu adlandırılmış bir blokda həyata keçirsək və tələb olunduqda bu bloku çağırsaq nə olacaq? Kodun oxunaqlılığını artırır və istifadəçinin onu asanlıqla başa düşməsini təmin edir.

Məsələn, ədədlər seriyası üçün eyni arifmetik əməliyyatlar əlavə (), çıxma (), vurma () və bölmə () kimi fərqli funksiyalarda və bu funksiyaları 'if' ifadəsində çağırırıqsa əsas funksiyada yaradılır. əməliyyat, daha sonra kod daha sadə və anlaşılması daha asan görünür. Bu əməliyyatlar üçün istifadə olunan məntiq burada daha az əhəmiyyət kəsb edir. Əgər məntiqi bilməyimiz lazım olsa, müvafiq funksiyanı yoxlaya bilərik. Fərz edənin sıfır olub olmadığını yoxlamaq üçün bölünərkən bəzi əlavə tələblər olduğunu düşünək. Sonra bölmə əməliyyat kodunu alanadək bütün əsas funksiyanı keçməməliyik. Daha doğrusu, Division () funksiyasını birbaşa gətirə bilərik və sıfırın yoxlanılması üçün yeni kod dəsti əlavə edə bilərik. Beləliklə funksiyanın yaradılması yeni tələbin əlavə edilməsini də asanlaşdırır. Beləliklə C funksiyalarında geniş istifadə olunur.

C-də hər şey bir funksiya daxilində yazılmışdır. Proqram özü () funksiyasından başlayır. Adından da göründüyü kimi, kodun icrasına başlanılan hər hansı bir proqramdakı əsas funksiyadır. İstifadəçinin digər tələbləri daha sonra birdən çox funksiyaya bölünür və əsas funksiyadan çağırılır. Hər hansı digər funksiya eyni və ya digər funksiyanı da zəng edə bilər. Bir sözlə C funksiyalar olmadan tam deyil!

Bir funksiya bir və ya daha çox giriş qəbul edə bilər, onlarda bəzi əməliyyatlar həyata keçirə bilər və ya çıxışı çağırış funksiyasına qaytara bilər. Hər hansı bir funksiyadan, istənilən dəfə zəng edilə bilər. Bu o deməkdir ki, bir funksiya proqramdakı yenidən istifadə edilə bilən kod blokudur.

Funksiya növləri

C-də iki növ funksiyamız var.

Kitabxana funksiyası

Kitabxana funksiyaları C-dəki daxili funksiyalardır, istifadəçidən giriş əldə etmək, çıxışı ekranda göstərmək, hər iki simli müqayisə etmək, iki simli dəyərin kopyalanması, yaddaşın ayrılması və s. Kimi ən çox istifadə olunan funksiyalar onsuz da fərqli funksiyalara kodlaşdırılmışdır. C və kitabxanalarda yerləşdirilmişdir. Bu funksiyalar proqramımızda nə vaxt tələb olunduğu kimi adlandırıla bilər.

Məsələn, adları klaviaturadan daxil etməliyik. Bu o deməkdir ki, proqram klaviatura girişlərini oxumalı və bəzi dəyişənlərdə saxlaya bilməlidir. Funksiya müxtəlif növ dəyişənləri qəbul edəcək qədər çevik olmalıdır. Bütün bu tələblər əvvəlcədən işlənir və scanf () adlı funksiyaya daxil edilir.

Kitabxana funksiyalarının bəzi digər nümunələri printf (), main (), strcpy (), strcmp (), strlen (), malloc () və s.

Bu kitabxana funksiyaları yenidən istifadə və funksionallıqlarına görə kateqoriyalara ayrılır və fərqli sənədlərdə yerləşdirilir. Bu fayllar başlıq faylları kimi tanınır. Bu sənədlər başlıq sənədlərini göstərən '.h' uzantıları ilə qeyd olunur. Ən çox istifadə olunan giriş və çıxış funksiyaları stdio.h başlıq sənədinə yerləşdirilir. Bu başlıq faylında bütün main (), scanf, printf, gets, getchar, puts, putchar və s. String ilə əlaqəli bütün kitabxana funksiyaları string.h başlıq sənədində yerləşdirilir.

Bir proqram yazdığımızda, bu daxili funksiyanın harada olduğunu və ya bu funksiyaları haradan götürəcəyimizi bilmir. Bunları açıq şəkildə kodumuza daxil etməliyik. Bu, kompilyatorun proqramda istifadə ediləcək funksiyaları bilməsinə kömək edəcək və bütün daxili funksiyaları kodumuza daxil etməkdən çəkinəcəkdir. Bu, yalnız proqram üçün tələb olunan başlıq sənədlərini daxil etməyimizə imkan verir. Yalnız proqramın tələb etdiyi başlıq sənədlərindən istifadə edə bilərik. Bu başlıq sənədləri '#include' adlanan bir ön prosessor direktivindən istifadə edərək proqramımıza əlavə olunur;

#include <stdio.h>
#include <string.h>
#include <math.h>

Bu təlimatlar kodun əvvəlində yerləşdirilir. Tərtibçi kodu tərtib etdikdə və bu direktivləri gördükdə birbaşa onları müvafiq kodları ilə əvəz edir. Buna görə scanf, printf vs. kimi funksiyaları çağırdıqda, bunların tərifini bilir və bu kodları yerinə yetirir.

İstifadəçi tərəfindən təyin olunmuş funksiya

Bunlar istifadəçi tərəfindən proqram tələblərinə uyğun olaraq elan edilmiş və təyin edilmiş funksiyalardır. Bu funksiyalar yalnız müəyyən edildiyi cari proqram üçün mövcuddur. Bu, müəyyənləşdirildiyi proqram və proqramın bütün əlaqəli sənədləri tərəfindən istifadə edilə bilər. Ancaq bütün proqramlarda kitabxana funksiyası kimi istifadə edilə bilməz.

Blokda və ya hər hansı digər funksiyada bir funksiya çağırıldıqda, icra nəzarəti hücrəli funksiyaya keçəcək; funksiyadakı ifadələri yerinə yetirəcək və bəzi dəyərləri olmayan / olmayan blok / funksiyaya qayıdır.

Yuxarıdakı diaqramdan bir funksiya çağırışının necə işlədiyi aydındır. Etiket kimi davranır, lakin icrası bitdikdən sonra yenidən çağırış blokuna qayıdır.

Funksiyaların üstünlükləri

Proqramın oxunaqlığını artırır və eyni zamanda proqramın mürəkkəbliyini azaldır.

  • Hər hansı bir təkrarlanan kod bloku varsa, o bir funksiyaya yerləşdirilib və lazım olduğu yerə zəng edilə bilər. Proqramı sadə və asan başa düşülür.
  • Funksiyada yuxarıdan aşağıya doğru bir yanaşma istifadə edir - yəni əvvəlcə funksiyanın bütün yüksək səviyyəli məntiqlərini yerinə yetirir, daha sonra aşağı səviyyəli məntiqə keçir. Daha da spesifik olmaq üçün əvvəlcə problemi müxtəlif tapşırıqlara bölür və onlar üçün funksiyalar yaradır. Daha sonra funksiyada bu problemləri həll etmək üçün məntiq yaradır. Məsələn, rəqəmləri əlavə et / çıxart / vur / bölə kimi arifmetik əməliyyatları yerinə yetirmək üçün bir proqram yaz. Bir proqram yazdığımızda yalnız əvvəlcə rəqəmləri əlavə et / çıxart / vur / bölə və müvafiq funksiya yaratdığını görürük. Əməliyyatların aşağı səviyyələri olan bu əməliyyatların yerinə yetirilməsinə dair daha ətraflı məlumat müvafiq funksiyalar çərçivəsində həyata keçirilir.
  • Funksiyaları eyni proqramda və ya eyni istifadəçinin yazdığı digər proqramlarda yenidən istifadə edə bilərik. Hətta digər proqramlar, digər istifadəçilər və ya digər sistemlərdə yenidən istifadə edilə bilən funksiyalar yarada bilərik.
  • Proqramın məntiqini başa düşməyə və yaxşı işləməyə kömək edir. Ayrıca, bir kodun tam uzunluğunu ayıklamaqdansa, funksiyanı ayıklamanı asanlaşdırır. Məsələn, Division () funksiyasında hər hansı bir səhv varsa, birbaşa funksiyaya keçib problemi həll edə bilərik. Ancaq belə bir funksiya olmasaydı və tam uzunluqlu bir kod yazılmışdısa, onda tam kodun səhvini tapacağıq. C, bütün proqramı tərtib etməkdənsə, yalnız funksiyaları tərtib etməyimizə imkan verir. Bu da kodu düzəltmək üçün əlavə bir üstünlükdür. Bu testi asanlaşdırır.

İş Bəyannamələri

İstifadəçi tərəfindən təyin olunmuş funksiya istifadəçi / geliştirici tərəfindən kodlaşdırılmalı və C tərtibçisinin anlaya biləcəyi xüsusi bir formata sahib olmalıdır. Bir funksiyanın yaradılmasında ilk addım olaraq onları elan etməliyik. Fonksiyonu saxlamaq və funksiyadakı müxtəlif tapşırıqları yerinə yetirmək üçün RAM-də yaddaş sahəsi yaratmağa bərabərdir. Tipik bir funksiya əsasən iki hissədən ibarətdir - funksiya başlığı və funksiya gövdəsi. Funksiya başlığı, funksiyanın adını, funksiyaya verilən arqumentləri və funksiyanın qayıtma növünü qeyd edən funksiyanın ilk sətiridir. Bir sözlə, bir funksiya başlığı funksiyanın quruluşunu izah edir.

Bir proqramda bir funksiya yaratdığımızda, başlığı ilə bir funksiya elan edirik. yəni;

Datatype function_name (arqumentlər / parametrlər);

Burada məlumat növü funksiyanın nəticəsinin məlumat növüdür. Hər hansı bir ibtidai və ya primitiv olmayan bir məlumat növü ola bilər. Hətta etibarsız ola bilər - heç bir nəticə vermədiyini göstərir. Sonrakı funksiyanın adıdır. Adətən mənalı bir ad verilir ki, adın özünü görmək funksiyanın nə etdiyini başa düşsün. Funksiyanın adı yalnız proqrama xas olmalıdır. Eyni proqramdakı başqa heç bir funksiyanın eyni funksiya adı olmamalıdır. Ardından arqumentlərin / parametrlərin siyahısı. Bunlar çağırış funksiyasından funksiyaya ötürülən və ya olmayan dəyərlərdir. Funksiya heç bir mübahisəsiz də ola bilər. Dəlilləri keçsək, hər birinin məlumat tipini təyin etməliyik. Funksiyaya istənilən sayda arqument ötürə bilərik.

ləğv fnDisplay (chariot chrString []); // qayıtma dəyəri olmayan string parametri olan bir funksiya
int fn Əlavə (int intNum1, int intNum2); // tam ədədi çıxan 2 tam arqumentli bir funksiya
axıtma fnAverage (int intNum []); // arqumenti tam sayı kimi bir sıra, qayıtma dəyəri float olaraq

Bunlar tələbə, giriş parametrlərinə və onların qaytarma dəyərlərinə görə fərqli funksiyaların elan edilməsidir. Bir funksiya elanı kodda təyin olunmadan və istifadə edilmədən əvvəl edilir. Ümumiyyətlə funksiyanı preproessor direktivlərindən az sonra elan edirik.

#include <stdio.h>

//Function Declaration
void fnDisplay (char chrString []); // a function with string parameter with no return values
int fnAddition (int intNum1, int intNum2); // a function with 2 integer arguments with integer output
float fnAverage (int intNum []); // a function with argument as integer array with return value as float

void main (){
// example program
}

Funksiya tərifləri

Funksiya gövdəsi, ona ötürülən parametrlərdən istifadə edərək ifadələr və ifadələrlə kod məcmusudur. Funksiyanın funksionallığını müəyyənləşdirir. Funksiyanı elan edərkən və ya proqramın hər hansı bir yerində funksiya tərifini yerləşdirə bilərik.

Tipik bir funksiya tərifinə bir funksiya başlığı və ardından açıq bir mötərizə daxildir - '{'. Funksiya gövdəsi daxilində funksiyanın lokal dəyişənləri üçün bəyannamə, tapşırıqları yerinə yetirmək üçün kod və çağırış funksiyasına dəyəri qaytarmaq üçün bir qaytarma ifadəsi və ardından yaxın bir mötərizə - '}' ola bilər.

datatype function_name (arguments/parameters) {
	declaration part;
	expressions/ statements;
	return variable_name;
}

Bu, C dilindəki bir funksiya orqanının tipik quruluşudur. Aşağıda, bir funksiya çağırıldıqda proqramın idarəetməsinin necə atlandığını göstərən nümunə proqram verilmişdir. Burada funksiyanın tərifi kodun sonunda yerləşdirilir. Ancaq əsas funksiya başlamazdan əvvəl də funksiyanı elan etdik. Tərtibçi kodu tərtib etdikdə bəyannaməni görür və bunun üçün bir tərifin olduğunu başa düşür. Əsas funksiyadakı funksiyanı çağırdığımızda, funksiya çağırışını funksiya tərifi ilə əvəz edir və kodu yerinə yetirir. Funksiyanı əvvəldə elan etməmiş və əsas funksiyada çağırmış olsaydıq, kompilyator sonda funksiyanın təyin olunduğunu bilməyəcək və funksiyanın təyin olunmayan tərtib səhvini atacaq. Özünü elan edərkən funksiya tərifini də yerləşdirə bilərik.
#include <stdio.h>
void fnDisplay (char chrString []); // a function with string parameter with no return values

void main (){
	char chrStr [] = "Example of a Function";
	printf ("\nBefore calling the Function.....");
	fnDisplay (chrStr); // calling the function
	printf ("\nAfter calling the function.....");
}

// Function definition
void fnDisplay (char chrString []){
	printf ("\nInside the function Body......\n");
	printf ("%s", chrString);
	printf ("\nEnd of the function Body.....");
}

Zəng funksiyaları

Bir funksiyanın necə elan olunacağını və tərifinin müəyyənləşdirilməsini öyrəndik. İndi gəlin görək funksiyanı başqa bir funksiyadan necə çağırırıq. Hər hansı bir funksiyadan / kod blokundan bir ad adını çəkərək bir funksiya çağırıla bilər. Əlavə olaraq funksiya tərifinə uyğun olmalıdır - yəni bir funksiyanın parametrləri ötürülürsə, parametrləri '()' mötərizədə göstərərək funksiyaya ötürməliyik. Parametrlərin növü, funksiyada elan edilmiş tiplə tam uyğun olmalıdır. Funksiyaya ötürülən dəyişən adlar və funksiya bəyannaməsində göstərilən adlar fərqli ola bilər. Ancaq parametrlərin sayı və növləri həmişə uyğun olmalıdır.

fnDisplay (chrStr); // funksiyanı çağırmaq

Burada funksiya bir arqumenti qəbul edir və simli tiplidir. Funksiyaya zəng edərkən eyni tipli parametr ötürürük. Kimsə niyə yalnız dəyişən adın parametr olaraq ötürüldüyünü düşünə bilər. Burada simvol bir sıradır və massiv bir göstərici kimi işləyir - massivin adı göstərildiyi zaman massivin birinci elementini göstərir. Beləliklə, sətir digər normal dəyişən kimi işləməyə ötürülür. Eyni barədə daha çox məlumat göstərici hissəsindədir. Başqa bir dəyişən növü ötürürüksə, dəyişən adını göstərərək dəyəri parametr parametrinə ötürürük.

fnAddition (intVal1, intVal2);

Burada intVal1 və intVal2 tamsayı tiplidir və yuxarıdakı kimi keçdikdə adları dəyəri ilə əvəz olunur. Bu çağırış tərifi ilə əvəz olunduqda, kompilyator müvafiq olaraq intNum1 vəintNum2 dəyərini alır.

Bir funksiya dəyəri qaytarırsa, funksiya çağırışı qayıdış tipli bir dəyişənə təyin edilməlidir. FnDisplay funksiyasında qaytarma növü boşdur. Bu səbəbdən hər hansı bir dəyişənə funksiya çağırışı atamamız lazım deyil. FnAddition funksiyasında nəticəni çağırış funksiyasına qaytarır. Beləliklə nəticəni eyni tipli bir dəyişkəndə əldə etməliyik. Beləliklə funksiyanı aşağıdakı kimi adlandırırıq:

intResult = fnAddition (intVal1, intVal2); // funksiyanı çağırır

 

#include <stdio.h>
int fnAddition(int intNum1, int intNum2);

void main(){
	int intVal1, intVal2, intResult;

	printf("\nPlease enter first number to be added:");
	scanf("%d", &intVal1);
	printf("\nPlease enter second number to be added:"); 
	scanf("%d", &intVal2);
	intResult = fnAddition(intVal1, intVal2); //calls the function
	printf("\nSum of two number is:%d", intResult);
}
// Function definition
int fnAddition (int intNum1, int intNum2){
	return intNum1 + intNum2; // returns the sum of two numbers
}

İş parametrləri

Funksiyaların hansı parametrlərin olduğunu bilirik. Ancaq parametrlərin funksiyaya necə ötürülməsi və onların tərifindəki funksiya parametrlərinə necə dəyər veriləcəyi. Funksiya elanında elan olunan parametrlərə formal parametrlər deyilir. Bunlar funksiya çağırıldıqda yaradılır və funksiya daxilində yerli dəyişən rolunu oynayır. Funksiya tamamlandıqca yaddaşdan silinirlər. Eyni funksiya yenidən çağırılırsa, yenidən başqa bir yaddaş yerində yaradılacaqdır.

int fnAddition (int intNum1, int intNum2); // intNum1 and intNum2 are formal parameters
void fnDisplay (char chrString []){//chrString[] is formal parameter
	printf ("\nInside the function Body......\n");
	printf ("%s", chrString);
	printf ("\nEnd of the function Body.....");
}

Funksiyaya zəng edilərkən funksiyaya ötürülən parametrlər / dəyişənlər funksiyanın həqiqi parametrləri adlanır. Funksiya parametrlərinin həqiqi dəyərləri var və dəyərlərindən asılı olaraq qiymətləndirilir. Kod adlarında faktiki və formal parametrlərin adları eyni və ya fərqli ola bilər. Onları fərqləndirmək üçün fərqli saxlayırıq.

fnDisplay (chrStr); // chrStr həqiqi parametrdir
intResult = fnAddition (intVal1, intVal2); // intVal1 və intVal2 həqiqi parametrlərdir

Keçən faktiki parametrləri funksiyaya ötürməyin iki yolu var.

  • Dəyərdən keçir

Bu metodda bir funksiya çağırıldıqda, faktiki parametrlər qiymətləndiriləcək həqiqi dəyərlərə sahib olacaqdır. Tərtibçi funksiya çağırışını tərifi ilə əvəz etdikdə onun formal parametrləri dəyərlərlə əvəz olunur. Formal parametr onlara dəyər qazandığından, formal parametr dəyişkənindəki hər hansı bir dəyişiklik faktiki parametr dəyişəninin dəyərini dəyişdirməyəcəkdir. Bu funksiya daxilində təsir göstərmiş ola bilər, ancaq çağırış funksiyasına qayıtdıqda faktiki parametr dəyəri dəyişməz qalacaqdır.

intResult = fnAddition (intVal1, intVal2); // intVal1 və intVal2 parametrlərin həqiqi dəyərinə malikdir

kompilyator kodu tərtib etdikdə yuxarıdakı funksiya çağırışını aşağıdakı kimi əvəz edir:
Tutaq ki, intVal1 = 10 və intVal2 = 40, onda
intResult = fnAddition (10, 40);

int fnAddition (10, 40){
	return 10 + 40; // returns the sum of two numbers
}

Burada rəsmi parametri dəyişdirmədik və bu səbəbdən funksiya daxilindəki dəyərlərdə heç bir dəyişiklik yoxdur. Beləliklə, faktiki parametrlərdə də heç bir dəyişiklik yoxdur.

Tutaq ki, aşağıda göstərilən başqa bir funksiyamız var ki, bu da sadəcə parametrin dəyərini 10-a artırır. İntalın 25-ə bərabər olduğunu düşünək.

intResult = fnIncrement (intVal); // intVal həqiqi parametrdir

Funksiya yuxarıdakı kimi çağırıldıqda kompilyator bunu görür

intResult = fnIncrement (25); // intVal həqiqi parametrdir

Bu çağırışı aşağıdakı kimi funksiya tərifi ilə əvəz edir:

 

Aşağıdakı proqramda həqiqi və formal parametrlərin eyni təsirini görə bilərik. Funksiyadan sonra funksiyada formal parametrin dəyəri dəyişdirilsə də faktiki parametrin dəyərinin dəyişdirilmədiyini görə bilərik. Formal parametr ötürülmüş dəyərlə əvəzlənsə də, funksiya daxilində lokal dəyişən rolunu oynayır. Dəyəri funksiya bitən kimi yox olur.

#include <stdio.h>
int fnIncrement (intVal);

void main (){
	int intVal=25, intResult;

	printf ("\nValue of intVal before function call is %d", intVal);
	intResult = fnIncrement(intVal); //calls the function
	printf ("\nValue of intVal after function call is %d", intVal);
	printf ("\nIncremented Value is:%d", intResult);
}
// Function definition
int fnIncrement (int intNum){
	printf ("\nValue of intNum before incrementing is %d", intNum);
	intNum += 10;
	printf ("\nValue of intNum after incrementing is %d", intNum);
	return intNum;
 }

  • Arayışdan keçin

Bu metodda keçiləcək dəyərin saxlandığı həqiqi dəyişənin ünvanını ötürürük. Bu, onun həqiqi dəyəri olmayan dəyərə istinad edildiyini bildirir. Beləliklə, burada həm rəsmi, həm də faktiki parametrlər yaddaşdakı eyni yaddaş yerlərinə işarə edəcəkdir. Beləliklə, rəsmi və ya faktiki parametrdəki hər hansı bir dəyişiklik həm dəyərləri dəyişəcəkdir. Bu, hər iki parametr tərəfindən göstərilən ünvanın eyni qalması deməkdir, ancaq bu ünvandakı dəyər istənilən bir dəyərə dəyişə bilər.

Yuxarıdakı eyni artım proqramını nəzərdən keçirin. Parametri referansla ötürək - funksiya çağırıldıqda intVal ünvanını parametr kimi ötürək. Sonra intNum rəsmi parametri də intValın ünvanını alır və bu səbəbdən hər ikisi indi eyni dəyərə istinad edir.

#include <stdio.h>
int fnIncrement (int *intNum); // formal parameter needs to be a pointer, inorder to accept the address

void main (){
	int intVal = 25, intResult;

	printf ("\nValue and Address of intVal before function call is %d and %x", intVal, &intVal);
	intResult = fnIncrement (&intVal); //pass by reference
	printf ("\nValue and Address of intVal after function call is %d and %x", intVal, &intVal);
	printf ("\nIncremented Value and address of intResult is:%d and %x", intResult, &intResult);
}
// Function definition
int fnIncrement (int *intNum){// even though address is passed, the '*' now points to the value at the address passed
	printf ("\nValue and Address of intNum before incrementing is %d and %x", *intNum, intNum);
	*intNum += 10; // inorder to increment the value at the address passed, pointer notation needs to be used. Address of the variable remains same
	printf ("\nValue and Address of intNum after incrementing is %d and %x", *intNum, intNum);
	return *intNum; //returns the incremented value
}

Proqramda funksiyanın göstərici dəyişəni ilə elan olunduğunu görə bilərik. Göstərici dəyişən başqa bir dəyişənin ünvanını göstərir. Beləliklə, faktiki parametrin ünvanını funksiya çağırışına keçirdikdə, formal parametr, intNum, intVal-a işarə etmək üçün yaradılır. Funksiyada intNum-u 10 artırdığımızda intNum dəyərini artırmalıyıq, ancaq ünvanı yox. Bu səbəbdən intNum-dan əvvəl '*' istifadə edirik. Beləliklə, dəyər dəyişsə də intNum tərəfindən göstərilən ünvan dəyişməz qalır. İntNum və intVal artımından sonra eyni dəyər və ünvan olacaqdır. Dəyəri zəng funksiyasına qaytardığımızdan (ünvanı yox, dəyəri qaytardığımızı qeyd edin), intResult dəyəri fərqli ünvanda alacaq. Tutaq ki, intNum ünvanını qaytardıq, onda intResult da eyni ünvana işarə etmiş olardı.

Proqramın aşağıda intResult-u eyni ünvanda necə əldə edəcəyinizi göstərir. Bütün bu parametrlər bunu etmək üçün göstəricilərdən istifadə edir. Bu mərhələdə bir az mürəkkəb görünə bilər, amma göstərici başa düşüldükdən sonra aydın olacaq. Həmişə unutmayın ki, * Num başqa bir ünvandakı dəyəri göstərir, Num başqa yerin ünvanını göstərir və & Num isə öz ünvanıdır. Ancaq zəhmət olmasa funksiyanın necə elan edildiyini, çağırıldığını, dəyərlərin necə ötürüldüyünü, qaytarılacağını və göstərildiyini unutmayın.

#include <stdio.h>
int *fnIncrement (int *intNum); // formal parameter needs to be a pointer, inorder to accept the address

void main () {
    int intVal = 25,*intResult;

    printf ("\nValue and Address of intVal before function call is %d and %x", intVal, &intVal);
    intResult = fnIncrement (&intVal); //pass by reference
    printf ("\nValue and Address of intVal after function call is %d and %x", intVal, &intVal);
    printf ("\nIncremented Value and address of intResult is:%d and %x", *intResult, intResult);
}
// Function definition
int *fnIncrement (int *intNum){// even though address is passed, the '*' now points to the value at the address passed
    printf ("\nValue and Address of intNum before incrementing is %d and %x", *intNum, intNum);
    *intNum += 10; // inorder to increment the value at the address passed, pointer notation needs to be used. Address of the variable remains same
    printf ("\nValue and Address of intNum after incrementing is %d and %x", *intNum, intNum);
    return intNum; //returns the incremented value
}

Funksiyaların bu tip xüsusiyyətləri əsasən iki dəyəri kopyalamağımız, iki ədədi dəyişdirməyimiz lazım olduqda istifadə olunur.

Variadik funksiyalar

Bəzən ötürülən parametrlərin sayını və məlumat növlərini bilmirik. Belə vəziyyətlərdə isteğe bağlı parametrlərlə funksiyalar yarada bilərik. Ancaq bilinən məlumat növü ilə ən azı bir parametr keçməliyik. Funksiya dəyişən sayda mübahisəni / parametri qəbul etdiyinə görə funksiyaya dəyişən funksiya deyilir. Bu funksiyanı elan etmək üçün ümumi sintaksis aşağıdakılardır:

Datatype funksiya_adı (datatype arqument1,...);

int fn Əlavə (int intCount,…);

Burada '...' tərtibçiyə istənilən növ və istənilən sayda isteğe bağlı arqumentləri olduğunu bildirir. Funksiyada isteğe bağlı parametrlərə va_start, va_list və s. Kimi bir makrolardan istifadə edərək müraciət edirik. Bu makrolar stdarg.h başlıq sənədində müəyyənləşdirilir və dəyişkən funksiyalardan istifadə edirsinizsə bu faylı daxil etməliyik. Funksiya elanında və tərifində ilk arqument məcburidir. Ümumiyyətlə bu ilk arqument bu funksiyaya verilən arqumentlərin sayı olacaqdır. Funksiyanı çağırdıqda, nə qədər arqument keçəcəyimizi, ardınca həqiqi arqument siyahısını təyin edirik. Beləliklə, işləmə zamanı funksiya çağırışı ona neçə arqument ötürüldüyünü öyrənir.

Keçən dəyişkən arqumentləri tutmaq, hər arqumenti işləmək və s. Üçün istifadə olunan bəzi makrolardan istifadə edir.

  • va_list: Bu variadic funksiyasına ötürülən arqumentləri saxlamaq üçün istifadə olunan kitabxana dəyişənidir. Funksiyaya ötürülən arqumentləri tutmaq üçün va_list tipli bir dəyişən elan edirik.

   va_list dəyişən_ad;
  va_list parametrlər; // və_list tipli 'parametrləri' dəyişən elan edin

Bu kitabxana dəyişəni va_start, va_end və va_arg kimi variadik funksiyalar tərəfindən istifadə olunan makrolar üçün dəyişənləri tutmaq üçün əlverişlidir.

  • va_start: Bu parametrlər dəyişənlər siyahısını va_list tərəfindən elan olunan dəyişənə başlamaq üçün istifadə olunan makrodur. Bu makro funksiyaya ötürülən bütün parametrləri dəyişən va_list tipinə daxil edir və arqumentlər siyahısının əvvəlinə işarə edir. Bu makro iki arqument götürür - biri va_list tipli parametrlər siyahısı dəyişənidir, digəri funksiyaya ötürülən ilk sabit arqument olan son arqumentdir (funksiyalar arqument siyahılarını sondan əvvələ keçir; bu səbəbdən sabit birinci arqument deyilir) son dəlil).

va_start (va_list arg_list, son_arg);
va_start (parametrlər, intCount); // Əvvəldən istəyə uyğun parametrə daxil olmağa başlayır

Burada 'parametrlər' dəyişkən parametrlər siyahısının funksiya çağırışına keçməsi üçün başlanğıc ediləcəkdir. 'intCount' funksiyanın son arqumentidir, burada olan, funksiyaya verilən bir sıra arqumentlər.

  • va_arg: Bu makro parametrlər siyahısından növbəti arqumenti almaq üçün istifadə olunur.

     type va_arg(va_list arg_list, type));

Arqumentlər siyahısındakı hər bir arqumenti 'tip' olaraq məlumat növü ilə keçir. Funksiyaya ötürülən parametrlərin sayını və məlumat növünü bilməyəcəyik. Beləliklə, keçilən arqumentlərə bəzi məlumat növü təyin etməliyik və istifadəçi və_arg makrosundan istifadə edərək alınan arqumentlərin növünü açıq şəkildə təyin edir. Va_arg makrosunun sahib olduğu eyni 'tip' bir arqumenti qaytarır.

intParam = va_arg(parametrlər, int));// parametrləri 'parametrlərdən' alır və onları 'int' tipinə atır və 'int' növü olan 'intParam' dəyişəninə verir.

  • va_end: Bu makro, funksiyanın parametr siyahısının istifadəsinin bitməsini göstərmək üçün istifadə olunur. Bu makro çağırılmasa, funksiya qaytarılmayacaq və nəticəsi təyin olunmayacaq. Makro va_end heç bir şey gətirməsə də, funksiyanın dəyişən parametrlərinin istifadəsinin sonunu göstərmək üçün bu makronu təyin etməliyik.

    va_end(va_list arg_list); // parametrlərin istifadəsini bitirmək
    va_end(parametrlər); // parametrlərin istifadəsini bitirmək

#include <stdarg.h>
#include <stdio.h>

// Function declaration and definition
int fnAddition (int intCount, ...){
	int intSum = 0;
	va_list parameters; // declare a variable 'parameters' of type va_list

	va_start (parameters, intCount); //Starts accessing the optional parameter from the beginning
	printf("\nNumber of parameters passed is:%d", intCount);

	printf("\nNumbers that are passed to the function are:\n");
	for (int index = 0; index < intCount; index++)
		printf("%d\t", va_arg(parameters, int));

	va_start(parameters, intCount); //Starts accessing the optional parameter from the beginning
	for (int index = 0; index < intCount; index++)
		intSum += va_arg(parameters, int);
	
	va_end(parameters); // end the use of parameters
	return intSum; //return the result
}

void main (){
	int intResult;
	intResult = fnAddition (5, 10, 20, 30, 40, 50); //calls the function 5 parameters
	printf ("\nSum the numbers is:%d", intResult);
}

Əsas funksiya

Bu, hər hansı bir C proqramının vacib funksiyasıdır. Hər hansı bir proqramın içində bu standart funksiya olmalıdır. Bu funksiya C proqramının icrasına başlandığı funksiyadır. Bu səbəbdən funksiyanın prototipini elan etməyə ehtiyacımız yoxdur, ancaq bu funksiyanı təyin etməliyik. Yəni dəyərləri qəbul etdiyimiz, funksiyaları çağıran, nəticələri əks etdirən bu əsas funksiyaya sahib olmalıyıq. Əsas funksiya ümumiyyətlə proqramın vəziyyətini kompilyatora göstərmək üçün istifadə olunan int olaraq qaytarma növünə malikdir. Ret növünü int olaraq istifadə etsək, proqramda 'return 0;' olmalıdır. sonunda proqramın uğurla tərtib edildiyini göstərmək üçün. Bununla yanaşı, geri qaytarma növünü də etibarsız olaraq əldə edə bilərik - kompilyatora heç bir status göstərmir.

Bu funksiyanın mübahisələri ola bilər və ya olmaya bilər. Proqramı icra edərkən girişləri əmr sətri ilə tutmalı olduğumuz zaman arqumentlər funksiyaya ötürülür. Əgər istifadəçi proqramı icra edərkən bütün nümunələr kimi girişə daxil olarsa, arqumentləri əsas funksiyaya ötürməyə ehtiyac yoxdur.

#include <stdio.h>

int main (){
	printf ("\Example of main function without arguments");

	return 0; // indicates compiler that program is executed successfully and can exit from the program
}

Arqumentlər əsas funksiyaya ötürüldükdə, iki arqument qəbul edir - tam saylı arqumentlərin sayı, digəri isə char tipli parametrlər massividir. Hər hansı bir ad verilə bilər, ancaq izah edildiyi kimi eyni məlumat növünə sahib olmalıdırlar.

int əsas (int arc, chariot * argv []) {….}

arq - funksiyaya ötürülən parametrlərin sayıdır

* argv [] - arqumentlərin massivinə işarə göstəricisidir. Arqs parametrlərini arrayına qəbul edəcəkdir.

#include <stdio.h>

int main(int argc, char *argv[]){

	printf("\nTotal Number of arguments passed is : %d", argc);
	printf("\nArguments passed through command line is : \n");
	for (int index = 0; index<argc; index++)// traverses each arguments one by one
		printf("%s\t" , argv[index]);

	return 0; // indicates compiler that program is executed successfully and can exit from the program
}

Rekursiv funksiyalar

Eyni funksiya daxilində dəfələrlə çağırılan funksiyalar bunlardır. Bu, bir funksiyanın özü tərəfindən adlandırıldığı deməkdir.

datatype fn_name (){
	….
	fn_name(); // same function is being called
	….
}


Rekursiya funksiyasını izah etmək üçün məşhur nümunə bir ədədin faktoridir. Ədədin faktorialı ədədi və -1 ədədi faktorialının məhsuludur. yəni;
faktorial (n) = n * faktorial (n-1)
= n * (n-1) * faktiki (n-2)
=….
= n * (n-1) * (n-2) *… .. * 3 * 2 * faktiki (1)
= n * (n-1) * (n-2) *… .. * 3 * 2 * 1
Burada bir ədədin faktorialını hesablamaqda nümunəni müşahidə edə bilərik. Yəni əvvəlki ədədin faktorialını dəfələrlə hesablayır və cari rəqəmlə vurur. Bu o deməkdir ki, faktorialı hesablamaq üçün bir funksiya yazdığımızda loop və ya üçün heç bir şey yazmamalıyıq döngə zamanı faktoru almaq üçün rəqəmləri davamlı olaraq çoxaltdığımız yer. Bunun əvəzinə 1 nömrəni əldə edənə qədər eyni funksiyanın özünə dəfələrlə zəng edə bilərik. Bir sözlə, faktorial funksiya aşağıdakı kimidir:
int fnFactorial(int intNum){
	if (intNum < 1)
		return 1;
	else
		return (intNum * fnFactorial(intNum - 1));
}

Funksiya eyni funksiya daxilində adlandırıldığından rekursiv funksiya yaratmaq üçün diqqətli olmalıyıq. Müvafiq dayandırma əmri istifadə edilmirsə, sonsuz döngədə sona çatır. Yuxarıdakı nümunədə sayın birdən az olub olmadığını yoxlamaq üçün bir şərt var. Birdən azdırsa, funksiyanı oraya çağırmırıq; əvəzinə funksiya çağırışını dayandıraraq 1-i qaytarın. Ancaq rəqəm birdən çox və ya ona bərabərdirsə, fasiləsiz intNum -1-ə bərabər say üçün funksiyanı çağırırıq. Fonksiyonu necə söyləyir və bir nöqtədə dayanır.
#include <stdio.h>
int fnFactorial(int intNum);

void main(){
	int intVal;

	printf("\n Please enter the number whose factorial to be found:");
	scanf("%d", &intVal);
	printf("\n Factorial of a number %d is : %d:", intVal, fnFactorial(intVal));
}
int fnFactorial(int intNum){
	if (intNum < 1)
		return 1;
	else
		return (intNum * fnFactorial(intNum - 1));
}

Statik funksiyalar

Fərz edək ki, proqrama daxil olan bəzi funksiyaları yazmalıyıq və heç bir istifadəçinin bu funksiyadan istifadə etməsini istəmirik. Bu daxili funksiyalar eyni proqramdakı digər funksiyalar tərəfindən istifadə edilə bilər, lakin digər proqramlar, fayllar və ya istifadəçilər üçün əlçatan olmamalıdır. Məsələn, fərdi hesabat, kollec illik hesabatı və bəzi digər işçi hesabatları kimi müxtəlif hesabatlar hazırladığımız bir proqramın olduğunu düşünək. Ancaq bunların hamısının kollec adı, ünvanı, telefonu, faksı və s. İlə birlikdə ümumi bir hesabat başlığı var, bu səbəbdən də bütün bu başlıq məlumatlarının hesabata yazdırılması üçün bir funksiyamız ola bilər. Ancaq başlığı göstərmək üçün funksiya hesabat yaradan fərqli funksiyalar tərəfindən çağırılacaqdır. Buna görə bu başlıq funksiyasının istifadəçilərlə heç bir əlaqəsi yoxdur. Eynilə tələbə ilə əlaqəli digər proqramlar da bu başlıq funksiyasını tələb etmir. Qısası, başqa bir proqram və ya fayl və ya istifadəçinin hesabat başlığı olması üçün xüsusi olaraq yaradılan bu başlıq funksiyasına daxil olmasını istəmirik. Beləliklə, bu başlıq funksiyasını başqa hər hansı bir fayldan və ya istifadəçidən gizlədə və yazıldığı fayl / proqram tərəfindən istifadə oluna bilərik. Bu, funksiya bəyannaməsindən əvvəl 'statik' bir açar söz istifadə edərək edilir.

statik məlumat növü function_name (arqument / s);
   statik boşluq displayHeader ();

Statik funksiya, yaradıldığı fayldakı funksiyalar tərəfindən əldə edilə bilən funksiyadır. İstifadəçilər və ya digər proqramlar üçün açıq şəkildə mövcud deyil.

Tələbə, işçi heyəti və illik hesabatları göstərmək üçün iki sənəd - std_staff_report.c və hesabatın başlığını göstərmək üçün displayHeader.c faylını yarataq. DisplayHeader faylındakı displayHeader () funksiyasını std_staff_report.c faylından funksiyanı statik etmədən çağıraq. Digər fayllar kimi normal işləyəcəkdir. Fonksiyonu statik hala gətirsək, std_staff_report.c faylından gələn funksiya çağırışı səhv edəcək. Bu funksiyaları displayHeader.c faylı daxilində std_staff_report.c-də yazsaq və onlara zəng etsək, normal işləyəcəkdir. Yəni statik funksiyalar yalnız eyni faylda olan funksiyalar üçün mövcuddur. Statik funksiyalar yazıldığı yerdən başqa hər hansı bir istifadəçi / fayl / proqram üçün mövcud deyil.

// displayHeader.c
#include <stdio.h>
 static void displayHeader(){
	printf("\nDisplaying Header");
}

 
//std_staff_report.c
#include <stdio.h>
#include "displayHeader.c"// comment this line to see the affect of static
void displayStdReport(char *stdName);
void displayStaffReport(char *staffName);
void displayAnnualReport();

void main(){
	printf("\n\nStudent Report is:");
	displayStdReport("Rose");
	printf("\n\nStaff Report is:");
	displayStaffReport("Robert");
	printf("\n\nAnual Report is:");
	displayAnnualReport();

}
void displayStdReport(char *stdName){
	printf("\nInside %s Student Report Function:", stdName);
	displayHeader();
	printf("\nDisplaying %s Student Report :", stdName);

}
void displayStaffReport(char * staffName){
	printf("\nInside %s Staff Report Function:", staffName);
	displayHeader();
	printf("\nDisplaying %s Staff Report:", staffName);
}
void displayAnnualReport(){
	printf("\nInside Annual Report");
		displayHeader();
		printf("\nDisplaying Annual Report");
}

Yerləşmiş funksiyalar

İçəridə olan funksiyalar, içərisində bir və ya daha çox funksiyası adlandırılan funksiyalardır. Məsələn, bir əsas funksiyadakı bir funksiya çağırışı, əsas funksiyanı yuvalanmış bir funksiya halına gətirir. Yerləşdirilmiş funksiyaların sayında məhdudiyyət yoxdur. Artıq əsas funksiyada, rekursiya funksiyasında, statik funksiyada və s. Funksiyaların yuvalanmasını gördük.

datatype function_name(arguments){
	datatype function_name1(); // declare another function
	…
	datatype function_name1(); // call the function
	….
	datatype function_name1(){ //define the function
	…
	}
}

Əsas funksiya daxilində yerinə yetirilən fərqli hesab əməliyyatları iç içə əylənməyə nümunədir.
#include <stdio.h>

//Function Declaration
void add(int intNum1, int intNum2);
void minus(int intNum1, int intNum2);
void divide(int intNum1, int intNum2);
void multiply(int intNum1, int intNum2);

void main(){
	// calling different functions within another function
	add(30, 60);
	minus(100, 23);
	divide(25, 5);
	multiply(400, 7);
	printf("\n End of the arithmetic Operation….");
}

void add (int intNum1, int intNum2){
	printf("\nSum of %d and %d is : %d", intNum1, intNum2, intNum1 + intNum2);
}
void minus(int intNum1, int intNum2){
	printf("\nDifference of %d and %d is : %d", intNum1, intNum2, intNum1 - intNum2);
}
void divide(int intNum1, int intNum2){
	printf("\nResult of %d / %d is : %d", intNum1, intNum2, intNum1 / intNum2);
}
void multiply(int intNum1, int intNum2){
	printf("\nResult of %d * %d is : %d", intNum1, intNum2, intNum1*intNum2);
}

xülasə

  • Bir funksiya, proqramda adı verilən yenidən istifadə edilə bilən bir kod blokudur.
  • İki növ funksiya mövcuddur - Kitabxana funksiyaları və istifadəçi tərəfindən təyin olunan funksiyalar.
  • Kitabxana funksiyaları: main (), scanf, gets, getchar, printf, put, putchar, malloc, calloc, sqrt, sin, cos, tan, floor, exp, tolower, toupper, isdigit, isalpha və s.
  • Funksiyanın parametrləri iki yolla ötürülə bilər - dəyərdən keçmək və istinadla keçmək.
  • Keçid dəyərində həqiqi parametrin dəyəri ötürülür və funksiya həqiqi parametr dəyərini dəyişdirə bilməz
  • Keçiddə faktiki parametrin ünvanı ötürülür və formal parametrin dəyərindəki hər hansı bir dəyişiklik həqiqi parametrlərin dəyərini də dəyişdirəcəkdir. Ancaq hər iki parametrin ünvanı eyni qalır.
  • Dəyişən funksiyalar istənilən tip dəyişən sayını qəbul edən funksiyalardır.
  • Statik funksiyalar, yazıldığı fayl xaricində fayllar və ya proqramlar və ya istifadəçilər tərəfindən görünməyən funksiyalardır.
  • İç içə qalan funksiyalar başqa bir funksiya daxilində təyin olunan funksiyalardır.
  • Rekursiv funksiya eyni funksiyaların daxilində dəfələrlə çağırıldığı funksiyadır.

Şərh yaz

Translate »