Jazyk C (príklady) - Funkcie

Z Kiwiki
Verzia z 14:28, 30. apríl 2020, ktorú vytvoril PatrikC (diskusia | príspevky) (Vytvorená stránka „Kategória:Študijné materiály Kategória:Informatika {{Priklady_ZI}} __TOC__ ==Obsah== V tejto časti budeme pracovať s už vytvorenými programami (z predc…“)
(rozdiel) ← Staršia verzia | Aktuálna úprava (rozdiel) | Novšia verzia → (rozdiel)
Skočit na navigaci Skočit na vyhledávání


Základy informatiky - jazyk C


Riešené príklady

Algoritmy

Prvé programy

Podmienky

Cykly

Polia

Funkcie

Súbor

Vzorové príklady

Neriešené príklady


zdroj: Juraj Ďuďák, Zbierka úloh z algoritmizácie pre predmet Základy informatiky

ISBN: 978-80-8075-199-9

Obsah

V tejto časti budeme pracovať s už vytvorenými programami (z predchádzajúcich častí) s dôrazom na tvorbu funkcií. Pre zvládnutie týchto príkladov je potrebné poznať, akým spôsobom sa prenášajú argumenty funkcie (odkazom, hodnotou) a použitie návratovej hodnoty funkcie.

Funkcie a návratová hodnota

Funkcie delíme podľa typu návratovej hodnoty na

funkcie s návratovou hodnotou po skončení vykonávania funkcia vráti nejakú hodnotu, ktorú môžeme priradiť do premennej.

Príklad
1 int abs(int x)
2 { // telo funkcie
3     if(x<0)
4         return -x;
5     else
6         return x
7 }
  • hlavička funkcie: typ návratovej hodnoty: int (celé číslo)
  • argumenty: funkcia má jeden argument: x (x je celé číslo)
  • telo funkcie obsahuje konkrétne príkazy
  • hodnotu, ktorú má funkcia vrátiť, špecifikujeme kľúčovým slovom return, za ktorým nasleduje hodnota, ktorú chceme vrátiť. V príklade, ak je x<0, funkcia vráti hodnotu, čo je vlastne -x (kde x<0), čiže výsledok bude +x. V opačnom prípade vráti x.

funkcie bez návratovej hodnoty Tieto funkcie nič nevracajú. Ich návratový typ je void (prázdny). V jazyku Pascal sa takéto funkcie nazývajú procedúry.

Príklad
 1 void hlasenie(int cislo_chyby)
 2 {
 3     switch(cislo_chyby)
 4     {
 5         case 0: printf("Ziadna chyba"); break;
 6         case 1: printf("Chybne vstupne hodnoty"); break;
 7         case 2: printf("Chyba pocas vypoctu"); break;
 8         default: printf("Neznama chyba");
 9     }
10 }

Dana funkcia je bez návratovej hodnoty (void) a má jeden parameter: celé číslo cislo_chyby. Táto funkcia vypíše podľa hodnoty svojho parametra nejakú chybové hlásenie.

Parametre funkcie

Parametre prenášané hodnotou
V predchádzajúcom príklade (abs, hlasenie) boli argumenty prenášané hodnotou. To znamená, že pri volaní funkcie (napr. abs(3) ) sa hodnota parametru funkcie skopíruje do novovytvorenej premennej (argumentu) / abs(int x=3) / danej funkcie. Takto sa prenášajú všetky argumenty (okrem výnimiek, a ak to neurčíme inak). Premenné vytvorené vo funkciách sú lokálne a po skončení funkcie zaniknú. Premenné definované v jednej funkcie nie sú viditeľné v inej funkcii (aj keď majú rovnaké meno).
Parametre prenášané odkazom
Pri parametroch prenášaných odkazom je špecifické to, že pri volaní funkcie sa nekopírujú ich hodnoty, ale ich adresy (čo šetrí čas pri argumentoch s väčšími pamäťovými nárokmi). Dôsledok tejto zmeny je, že zmena hodnoty vo funkcii má za následok zmenu tejto premennej aj vo funkcii, z ktorej bola táto volaná. Upravme hlavičku funkcie abs, aby parameter x bol prenášaný odkazom: int abs(int &x); Operátor & (referencia) má význam adresy premennej. Premenné sa prenášajú odkazom, ak to určíme operandom &. Polia ako parametre funkcií sa prenášajú odkazom vždy (operátor & sa neuvádza).
Poznámka
parametre prenášané odkazom (operátor refencia - &) sú definované až v jazyku C++. Aj napriek tomuto faktu, budeme tento operátor používať pre jednoduchosť jeho použitia. Jazyk C definuje operátorderefencia - *. Práca s týmto operátorom je podobná práci s operátorom &.

Príklady

Najväčší spoločný delitel

Zadanie
Podľa už známeho (Euklidovho) algoritmu hľadania NSD vytvorte:
  • funkciu: int nsd(int a, int b); ktorá vypočíta NSD týchto dvoch čísel. Funkcia vráti hodnotu, ktorá je rovná najväčšiemuspoločnému deliteľu čísel a,b
  • funkciu: int nsd(int cisla[MAX], int n); ktorá vypočíta NSD n čísel, ktoré sú uložené v poli cisla.

Program načíta z klávesnice číslo n a následne n čísel, ktoré sa uložia do poľa data. Úlohou je vypočítať NSD z týchto čísel. Funkcia nebude nič načítavať ani vypisovať. Všetky vstupné dáta budú predané ako argumenty funkcie. Hodnotu NSD funkcia vráti.

Analýza problému
Problém NSD bol už precvičený v kapitole 4. Použijeme ten istý zdrojový kód, ale úlohu urobíme ako funkciu. Funkcia vráti nsd čísel a a b. Druhú časť úlohy vyriešime pomocou už vytvorenej funkcie nsd(a,b). Ak máme zistiť nsd n čísel, budeme to zisťovať postupne. Ako prvé vypočítame n0=nsd(cisla[0],cisla[1]). Ako ďalší krok bude n0=nsd(n0, cisla[2]), atď. Výsledkom bude hodnota n0. Hlavná funkcia main znázorňuje použitie funkcie nsd.
Program
 1 #include<stdio.h>
 2 #define MAX 100
 3 
 4 int nsd(int a, int b)
 5 {
 6 
 7     while(a!=b)
 8     {    if(a>b)
 9               a=a-b;
10          else
11               b=b-a;
12     }
13     return a;
14 
15 }
16 
17 int nsd(int cisla[MAX],int n)
18 {
19      int n0,i;
20      n0=nsd(cisla[0],cisla[1]);
21      for(i=2; i<n; i++)
22           n0=nsd(n0,cisla[i]);
23      return n0;
24 }
25 
26 void main()
27 {
28 
29     int i,n,vysledok,data[MAX];
30     printf("zadaj počet cisel: ");
31     scanf("%d",&n);
32     for(i=0; i<n; i++)
33         scanf("%d",&data[i]);
34     vysledok=nsd(data,n);
35     printf("NSD nacitanych cisel je %d", vysledok);
36 
37 }

Prvočíslo

Zadanie
podľa známeho algoritmu (časť cykly, úloha "test na prvočíslo“) naprogramujte funkciu int prvocislo(int a); ktorá otestuje, či je číslo a prvočíslo. Ak áno, funkcia vráti hodnotu 1, ak nie, funkcia vráti hodnotu 0. Vo funkcii sa nebude nič načítavať ani vypisovať.
Analýza problému
Algoritmus riešenia je už známy. Teda použijeme už hotový kód a vytvoríme funkciu. Vstupné dáta sa načítajú v hlavnej funkcii. Taktiež výpis výsledku bude vo funkcii main.
Program
 1 #include<stdio.h>
 2 
 3 int prvocislo(int a)
 4 {
 5      int del=2,prvocislo=1,podiel,zv;
 6      do
 7     {
 8        podiel=n/del;
 9        zv=n%del;
10        del++;
11        if(zv==0)
12           {    del=podiel+1;
13                prvocislo=0;
14           }
15      }while(podiel>del);
16      return prvocislo;
17 }
18 
19 void main()
20 {
21     int n;
22     printf("Zadaj cislo, ktore chces testovat na prvocislo\n");
23     scanf("%d",&n);
24     if(prvocislo(n)==1)
25           printf("%d je prvocislo",n);
26     else
27           printf("%d nie je prvocislo",n);
28 }

Maximálna hodnota 2

Zadanie
Naprogramujte funkciu, ktorá zistí maximum z dvoch čísel. Funkcia max bude mať dva parametre: čísla x a y. Funkcia vráti hodnotu maxima. Ďalej naprogramujte funkciu max, ktorá zistí maximálny prvok z n čísel. Funkcia bude mať parametre: pole cisla, v ktorom budú uložené dané čísla a premennú n, ktorá vyjadruje počet čísel v poli cisla. Počet čísel bude maximálne 100.
Analýza problému
Problém hľadania maxima z dvoch čísel bol vyriešený v časti "podmienky“. Tento zdrojový kód použijeme a vytvoríme funkciu: int max(int x, int y); V druhej časti úlohy máme použiť práve vytvorenú funkciu na zistenie maxima z n čísel. Budeme teda vytvárať funkciu, ktorá (podľa zadania) má nasledujúci funkčný prototyp: int max(int cisla[MAX], int n); kde MAX je (konštanta) max. počet prvkov v poli. Pri zisťovaní maximálneho prvku poľa musíme porovnať všetky prvky poľa. Ako prvé porovnáme prvé dva prvky (m=max(cisla[0],cisla[1];). Ďalej budeme vždy porovnávať aktuálne maximum (m) s nasledujúcim prvkom (ďalší krok bude m=max(m,cisla[2]);, atď). Ukážeme si ešte druhú možnosť hľadania maxima bez použitia prvej funkcie max (funkcia max2). Princíp je veľmi podobný. Na začiatku do premennej m priradíme prvý prvok poľa cisla. Následne prehľadávame celé pole. Každý prvok poľa testujeme, či je väčší ako aktuálne maximum. Ak áno, tak do premennej m priradíme aktuálne porovnávaný prvok poľa.
Program
 1 #include<stdio.h>
 2 #define MAX 100
 3 
 4 int max(int x, int y)
 5 {
 6      int m;
 7      if(x>y)
 8           m=x;
 9      else
10           m=y;
11      return m;
12 }
13 
14 int max1(int p[MAX], int n)
15 {
16      int m;
17      m=max(p[0],p[1]);
18      for(int i=2; i<n; i++)
19           m= max(m,p[i]);
20      return m;
21 }
22 
23 int max2(int p[MAX], int n)
24 {
25      int m = p[0];
26      for(int i=1; i<n; i++) //nemusime zacat od 0, pretoze 0-ty prvok je v premennej m
27           if(p[i] > m)
28                 m = p[i];
29      return m;
30 }
31 
32 void main()
33 {
34 
35     int n,cisla[MAX];
36     printf("Zadaj pocet nacitanych cisel\n");
37     scanf("%d",&n);
38     for(int i=0;i<n;i++)
39     scanf("%d",&cisla[i]);
40     printf("Maximum z nacitanych cisel: %d",max1(cisla,n));
41 
42 }

Maticová kalkulačka

Zadanie
Vytvorte program, ktorý bude pracovať s maticami. Program bude vedieť načítavať matice, sčítavať, odčítavať, násobiť a vypísať maticu na monitor. Každú jednu operáciu urobte ako funkciu. Výpis funkcií:
  • void NacitajMaticu(int &r, int &s, int M[MAX][MAX]);
  • void ScitajMatice(int r1, int s1, int M[MAX][MAX], int r2, int s2, int N[MAX][MAX], int O[MAX][MAX]));
  • void OdcitajMatice(int r1, int s1, int M[MAX][MAX], int r2, int s2, int N[MAX][MAX] , int O[MAX][MAX]));
  • void NasobMatice(int r1, int s1, int M[MAX][MAX], int r2, int s2, int N[MAX][MAX] , int O[MAX][MAX]));
  • void VypisMaticu(int r, int s, int M[MAX][MAX]);

Analýza problému: Práca s maticami bola vysvetlená v časti polia. Teraz sa zameriame na prácu funkcií. Všetky funkcie sú bez návratovej hodnoty (void), keďže funkcia nemôže vrátiť typ pole. Avšak, polia ako parametre funkcií sú predávané pomocou odkazu (referencie), takže všetky zmeny vykonané v týchto funkciách sa prejavia aj v hlavnej funkcii. Vo funkcii NacitajMaticu sa aj premenné r a s prenášajú pomocou odkazu, lebo vo funkcii sa tieto hodnoty budú načítavať a budeme ich potrebovať aj v ďalších funkciách. Matice sa dajú sčítavať (odčítavať) iba ak r1=r2 a zároveň s1=s2. Ak toto neplatí, nech sa vypíše chybová hláška a funkcia sa ukončí. Výsledná matica bude mať rozmery r1×s1. Násobenie matíc je definované pre 2 matice, pre rozmery ktorých platí: s1=r2. Ak toto neplatí, postupujte podobne ako pri sčítaní. Výsledná matica bude mať rozmery r1×s2. Pri operáciách s maticami vždy platí: O=M+N, O=M-N, O=M*N

  1 #include<stdio.h>
  2 #define MAX 100
  3 
  4 void NacitajMaticu(int &r, int &s, int M[MAX][MAX])
  5 {
  6 
  7     printf("Zadaj rozmery matice (r,s)\n");
  8     scanf("%d %d",&r,&s);
  9     int i,j;
 10     for(i=0; i<r; i++) // nacitavanie matice A
 11          for(j=0; j<s; j++)
 12          {  
 13              printf("\nZadaj prvok M[%d][%d] ",i,j);
 14              scanf("%d",&M[i][j]); // nacitavanie prvku Ai,j
 15          }
 16 
 17 }
 18 
 19 void ScitajMatice(int r1,int s1, int M[MAX][MAX],int r2,int s2,int N[MAX][MAX],int O[MAX][MAX])
 20 {
 21 
 22     if((r1!=r2) || (s1!=s2))
 23     {
 24         printf("\nMatice musia mat rovnake rozmery");
 25         return;
 26     }
 27     int i,j;
 28     for(i=0; i<r1; i++) // scitanie O=M+N
 29         for(j=0; j<s1; j++)
 30             O[i][j]=M[i][j]+N[i][j];
 31 
 32 }
 33 
 34 void OdcitajMatice(int r1,int s1, int M[MAX][MAX],int r2,int s2,int N[MAX][MAX],int O[MAX][MAX])
 35 {
 36 
 37     if((r1!=r2) || (s1!=s2))
 38     {
 39         printf("\nMatice musia mat rovnake rozmery");
 40         return;
 41     }
 42     int i,j;
 43     for(i=0; i<r1; i++) // odcitanie O=M-N
 44         for(j=0; j<s1; j++)
 45             O[i][j]=M[i][j]-N[i][j];
 46 
 47 }
 48 
 49 void NasobMatice(int r1,int s1, int M[MAX][MAX],int r2,int s2,int N[MAX][MAX],int O[MAX][MAX])
 50 {
 51 
 52     if(s1!=r2)
 53     {
 54         printf("\nPri nasobeni musí platit: s1==r2 ");
 55         return;
 56     }
 57     int i,j,k;
 58     for(i=0; i<r1; i++) // nasobenie O=M*N
 59         for(j=0; j<s2; j++)
 60         {
 61             O[i][j]=0;
 62             for(k=0; k<s1; k++)
 63                 O[i][j]+=M[i][k]*N[k][j];
 64         }
 65 
 66 }
 67 
 68 void VypisMaticu(int r, int s, int M[MAX][MAX])
 69 {
 70 
 71     printf("Vypis matice: \n");
 72     int i,j;
 73     for(i=0; i<r; i++) // vypis matice M
 74     {    for(j=0; j<s; j++) 
 75              printf("%6d",M[i][j]);
 76           printf("\n");
 77     }
 78     printf("\n");
 79 
 80 }
 81 
 82 void main()
 83 {
 84 
 85     int A[MAX][MAX], B[MAX][MAX], C[MAX][MAX];
 86     int rr1,ss1,rr2,ss2;
 87     NacitajMaticu(rr1,ss1,A);
 88     NacitajMaticu(rr2,ss2,B);
 89 
 90  
 91     ScitajMatice(rr1,ss1,A,rr2,ss2,B,C);
 92     printf("C=A+B\n");
 93     VypisMaticu(rr1,ss1,C);
 94 
 95     OdcitajMatice(rr1,ss1,A,rr2,ss2,B,C);
 96     printf("C=A-B\n");
 97     VypisMaticu(rr1,ss1,C);
 98 
 99   
100     NasobMatice(rr1,ss1,A,rr2,ss2,B,C);
101     printf("C=A*B\n");
102     VypisMaticu(rr1,ss2,C);
103     
104 }