Məzmuna keç
Educora
Orta17 dəq4 / 8

Funksiyalar

C-də öz funksiyalarını yaz: prototiplər, parametrlərin qiymətə görə ötürülməsi, return, void funksiyalar, standart riyazi funksiyalar və rekursiyanın əsasları.

Özünü yoxla
Bu dərsdə öyrənəcəksən
  • Qaytarma tipi, adı və parametrləri olan funksiya təyin edib çağırmaq
  • Funksiya prototipinin nə üçün lazım olduğunu izah etmək
  • Parametrlərin qiymətə görə (surət kimi) ötürüldüyünü anlamaq
  • Baza halı olan sadə rekursiv funksiya yazmaq

Sən artıq iki funksiyanı yaxşı tanıyırsan: hər proqramın başladığı main və ekrana mətn çıxaran printf. Böyük proqramlar yüzlərlə kiçik funksiyadan ibarətdir: biri balı hesablayır, biri cədvəli çap edir, biri faylı oxuyur. Hər funksiya bir işi görür, bir dəfə yazılır və istənilən qədər çağırılır. Səhv tapılanda isə onu yalnız bir yerdə düzəltmək kifayətdir.

Funksiyanın quruluşu

  • Qaytarma tipi — funksiyanın hansı tipdə nəticə verdiyi (int, double...). Heç nə qaytarmayan funksiya üçün void yazılır.
  • Ad — funksiyanın nə etdiyini deyən ad, məsələn, max və ya print_line.
  • Parametrlər — mötərizədə tipləri ilə birlikdə yazılan giriş qiymətləri: (int a, int b). Parametr yoxdursa, (void) yazılır.
  • Gövdə — fiqurlu mötərizələr arasındakı kod. return nəticəni çağırış yerinə qaytarır və funksiyanı dərhal bitirir.

C kompilyatoru faylı yuxarıdan aşağı oxuyur. Əgər main başqa funksiyanı onun təyinindən əvvəl çağırırsa, kompilyator həmin funksiyanı əvvəlcədən tanımalıdır. Bunun üçün faylın əvvəlində prototip yazılır: funksiyanın başlığı və sonda ;.

Tərif
Funksiya prototipi

Funksiyanın adını, qaytarma tipini və parametrlərinin tiplərini bildirən, amma gövdəsi olmayan elan. Məsələn: int max(int a, int b);. Başlıq faylları (stdio.h kimi) əsasən prototiplərdən ibarətdir.

C
#include <stdio.h>

int max(int a, int b);
double average(int a, int b, int c);

int main(void) {
    printf("Max: %d\n", max(12, 31));
    printf("Average: %.2f\n", average(5, 4, 4));
    return 0;
}

int max(int a, int b) {
    if (a > b) {
        return a;
    }
    return b;
}

double average(int a, int b, int c) {
    return (a + b + c) / 3.0;
}
Gözlənilən nəticə
Max: 31
Average: 4.33
Prototiplər sayəsində main faylın əvvəlində qala bilir. 3.0 ilə bölmə kəsr nəticə verir: 13 / 3 ≈ 4,33.

void funksiyalar və qiymətə görə ötürmə

Bəzi funksiyalar nəticə qaytarmır, sadəcə iş görür — məsələn, ekrana xətt çəkir. Onların qaytarma tipi void-dir. Aşağıdakı proqram həm də çox vacib bir qaydanı göstərir: C-də arqumentlər qiymətə görə ötürülür. Funksiya dəyişənin özünü yox, onun surətini alır, ona görə parametri dəyişmək çağıran tərəfdəki dəyişənə təsir etmir.

C
#include <stdio.h>

void print_line(int n) {
    for (int i = 0; i < n; i++) {
        printf("-");
    }
    printf("\n");
}

void try_to_change(int x) {
    x = 100;
    printf("Inside: x = %d\n", x);
}

int main(void) {
    int x = 5;
    print_line(12);
    try_to_change(x);
    printf("Outside: x = %d\n", x);
    print_line(12);
    return 0;
}
Gözlənilən nəticə
------------
Inside: x = 100
Outside: x = 5
------------
Funksiyanın içindəki x surətdir: o, 100 oldu, main-dəki x isə 5 olaraq qaldı.

Hər funksiyanı özün yazmalı deyilsən. Standart kitabxananın math.h başlığında hazır riyazi funksiyalar var: sqrt (kvadrat kök), pow (qüvvət), fabs (modul) və başqaları. Onlar double qəbul edir və double qaytarır. Linux-da belə proqramı kompilyasiya edərkən sona -lm əlavə etmək lazım ola bilər.

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

int main(void) {
    printf("%.2f\n", sqrt(16.0));
    printf("%.0f\n", pow(2, 10));
    printf("%.1f\n", fabs(-7.5));
    return 0;
}
Gözlənilən nəticə
4.00
1024
7.5

Rekursiya: özünü çağıran funksiya

Funksiya özünü də çağıra bilər — buna rekursiya deyilir. Rekursiv funksiyanın iki hissəsi var: məsələni dərhal həll edən baza halı və məsələni bir az kiçildib özünü yenidən çağıran rekursiv addım. Klassik nümunə faktorialdır: n! = n · (n − 1)!, baza halı isə 1! = 1.

C
#include <stdio.h>

long long factorial(int n) {
    if (n <= 1) {
        return 1;
    }
    return n * factorial(n - 1);
}

int main(void) {
    for (int i = 1; i <= 5; i++) {
        printf("%d! = %lld\n", i, factorial(i));
    }
    printf("20! = %lld\n", factorial(20));
    return 0;
}
Gözlənilən nəticə
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
20! = 2432902008176640000
Faktorial çox tez böyüyür, ona görə long long tipi (%lld) seçilib — 20! artıq int-ə sığmır.
factorial(4) necə hesablanır?

factorial(4) çağırışını addım-addım izlə.

Həllini göstər
factorial(4) = 4 · factorial(3)
factorial(3) = 3 · factorial(2)
factorial(2) = 2 · factorial(1)
factorial(1) = 1 — baza halı, çağırışlar dayanır.
İndi nəticələr geri qayıdır: 2 · 1 = 2, 3 · 2 = 6, 4 · 6 = 24.

Əsas fikirlər

  • Funksiya: qaytarma tipi, ad, parametrlər və gövdə; return nəticəni qaytarır.
  • Funksiya təyinindən əvvəl çağırılırsa, faylın əvvəlində prototipi yazılmalıdır.
  • Heç nə qaytarmayan funksiyanın tipi void-dir.
  • C-də arqumentlər qiymətə görə ötürülür: funksiya surətlə işləyir.
  • Rekursiv funksiyanın mütləq baza halı olmalıdır, yoxsa stek dolur.

Özünü yoxla

10 sual. Hər düzgün cavab XP qazandırır.

1 / 10
Funksiya prototipi nədir?