Pamoka 5

Funkcijos

~35 min · 4 žingsniai · 5 / 6 pamokų
Ką pastatysi
Kodėl funkcijos?

Kai programa auga, viską kišti į main darosi nevaldoma. Funkcija yra pavadintas kodo blokas, kurį gali iškviesti daug kartų. Tai struktūrinio programavimo esmė — skaidyti didelį uždavinį į mažus, aiškius gabalus.

printf ir scanf, kuriuos jau naudojai, irgi yra funkcijos — tik kažkieno kito parašytos. Dabar rašysi savas.


Paprasta funkcija

#include <stdio.h>

// funkcija, kuri pasveikina
void pasveikink(void) {
    printf("Labas!\n");
}

int main(void) {
    pasveikink();   // iškvietimas
    pasveikink();   // gali kviesti daug kartų
    return 0;
}
  • void priekyje reiškia: funkcija negrąžina jokios reikšmės.
  • pasveikink() — funkcijos iškvietimas; programa „nušoka" į funkciją, ją įvykdo ir grįžta.

Parametrai — įvestis funkcijai

Funkcija gali priimti parametrus — duomenis, su kuriais dirba:

void pasveikink_varda(char vardas[]) {
    printf("Labas, %s!\n", vardas);
}

int main(void) {
    pasveikink_varda("Jonas");
    pasveikink_varda("Ona");
    return 0;
}

Grąžinama reikšmė

Naudingiausios funkcijos apskaičiuoja ir grąžina rezultatą su return. Tipas priekyje pasako, ką funkcija grąžina:

#include <stdio.h>

// grąžina dviejų skaičių sumą
int suma(int a, int b) {
    return a + b;
}

int main(void) {
    int rezultatas = suma(3, 4);
    printf("Suma: %d\n", rezultatas);  // 7
    return 0;
}

int priekyje sako: „ši funkcija grąžina sveiką skaičių". return a + b; apskaičiuoja ir grąžina jį iškvietusiajai vietai.


Pavyzdys: ar skaičius pirminis

Funkcijos puikiai tinka sąlygai patikrinti. Grąžinkim 1 (taip) arba 0 (ne):

int ar_pirminis(int n) {
    if (n < 2) return 0;
    for (int i = 2; i < n; i++) {
        if (n % i == 0) return 0;  // dalijasi -> ne pirminis
    }
    return 1;
}

int main(void) {
    for (int n = 2; n <= 10; n++) {
        if (ar_pirminis(n)) printf("%d yra pirminis\n", n);
    }
    return 0;
}

Pastebėk, kaip funkcija sujungia visus blokus: pasirinkimą (if), kartojimą (for) ir grąžinamą reikšmę. main lieka švarus ir lengvai skaitomas.


Trikčių sprendimas

undefined reference arba „funkcija nežinoma" — funkciją apibrėžk virš main arba paskelbk jos prototipą prieš main.

Funkcija nieko negrąžina — patikrink, ar yra return, ir ar tipas priekyje ne void.

Klaida „control reaches end of non-void function" — kažkuriame kelyje pamiršai return.


Projektas CLion

Iki šiol visas kodas gyveno main.c. Šioje pamokoje pirmą kartą suskaidysim projektą į kelis failus: mathutil.h (prototipai), mathutil.c (apibrėžimai) ir main.c (naudojimas). Tai tikras profesionalus būdas tvarkyti C kodą.

Žingsniai žemiau rodo pilną kiekvieno failo turinį. Svarbu: pridėjus mathutil.c, jį būtina įrašyti į CMakeLists.txt (3 žingsnis) — kitaip CLion jo nesurinks.


Apibendrinimas

Išmokai rašyti funkcijas su parametrais ir grąžinama reikšme bei skaidyti programą į švarius blokus. Tai padaro kodą skaitomą ir daugkartinį.

Paskutinėje pamokoje sujungsi viską su masyvais — daug reikšmių viename kintamajame.

mathutil.h create

Sukurk mathutil.h — funkcijų prototipai

#ifndef MATHUTIL_H
#define MATHUTIL_H

// Grazina dvieju skaiciu suma.
int suma(int a, int b);

// Grazina 1, jei n yra pirminis, kitaip 0.
int ar_pirminis(int n);

#endif

Sukurk naują failą mathutil.h projekto šaknyje (CLion: dešinys pelės klavišas ant projekto → New → C/C++ Header File). Tai antraštinis failas — jis tik skelbia funkcijas, bet jų neapibrėžia.

Ką šis kodas daro:

  • #ifndef MATHUTIL_H / #define MATHUTIL_H / #endif — apsauga, neleidžianti įtraukti failo du kartus.
  • int suma(int a, int b); — funkcijos prototipas: vardas, parametrai ir grąžinamas tipas, be kūno.

Svarbu: antraštinis failas pasako funkcija daro; kaip — bus mathutil.c.

mathutil.c create

Sukurk mathutil.c — funkcijų apibrėžimai

#include "mathutil.h"

int suma(int a, int b) {
    return a + b;
}

int ar_pirminis(int n) {
    if (n < 2) {
        return 0;
    }
    for (int i = 2; i < n; i++) {
        if (n % i == 0) {
            return 0;
        }
    }
    return 1;
}

Sukurk failą mathutil.c (New → C/C++ Source File) ir įrašyk funkcijų apibrėžimus.

Ką šis kodas daro:

  • #include "mathutil.h" — įtraukia mūsų antraštę (kabutės, ne <>, nes failas tavo projekte).
  • suma — grąžina dviejų skaičių sumą.
  • ar_pirminis — tikrina, ar n dalijasi iš kurio nors mažesnio skaičiaus; jei taip — ne pirminis.

Svarbu: prototipas faile .h ir apibrėžimas faile .c turi tiksliai sutapti (vardas, parametrai, tipas).

CMakeLists.txt modify

Atnaujink CMakeLists.txt — pridėk mathutil.c

cmake_minimum_required(VERSION 3.20)
project(StructuredC C)

set(CMAKE_C_STANDARD 11)

add_executable(StructuredC main.c mathutil.c)

Pakeisk CMakeLists.txt add_executable eilutę — pridėk mathutil.c. Be šito CLion nesurinks naujo failo ir gausi „undefined reference" klaidą.

Ką pakeisti:

  • Buvo: add_executable(StructuredC main.c)
  • Tapo: add_executable(StructuredC main.c mathutil.c)

Svarbu: antraštinių (.h) failų čia rašyti nereikia — tik .c failus. Po pakeitimo CLion gali paprašyti „Reload CMake project" — sutik.

main.c modify

Pakeisk main.c — naudok funkcijas

#include <stdio.h>
#include "mathutil.h"

int main(void) {
    printf("3 + 4 = %d\n", suma(3, 4));

    printf("Pirminiai iki 20: ");
    for (int n = 2; n <= 20; n++) {
        if (ar_pirminis(n)) {
            printf("%d ", n);
        }
    }
    printf("\n");
    return 0;
}

Pakeisk main.c, kad naudotų naująsias funkcijas iš mathutil.c.

Ką šis kodas daro:

  • #include "mathutil.h" — leidžia main matyti suma ir ar_pirminis.
  • suma(3, 4) — iškviečia funkciją ir gauna 7.
  • Ciklas su ar_pirminis(n) išspausdina visus pirminius iki 20.

Svarbu: main nieko nežino apie tai, kaip veikia funkcijos — tik jos grąžina. Tai ir yra skaidymo nauda.