I N V E S T I C E D O RO Z VO J E V Z D Ě L Á V Á N Í
Inovace a zvýšení atraktivity studia optiky reg. č.: CZ.1.07/2.2.00/07.0289
Úvod do programování Lekce 5
Tento projekt je spolufinancován Evropským sociálním fondem a státním rozpočtem České republiky.
Funkce definice funkce zahrnuje specifikaci počtu a typů parametrů, typu návratové hodnoty, a vlastního těla funkce příklad: funkce najde maximum ze dvou celých čísel #include<stdio.h> int maximum(int a, int b){ // hlavicka funkce return(a>b ? a : b); // telo funkce } main(){ int c1,c2; printf("zadej dve cela cisla: "); scanf("%d %d",&c1,&c2); printf("vetsi je cislo %d\n",maximum(c1,c2)); // volani funkce } poznámky: ● příkaz return předává řízení nadřazené funkci a zároveň vrací výsledek ● pokud funkce nemá parametry, popř. nevrací žádnou hodnotu, použijeme typ void příklad: program využívá funkce tab() a podtrhni() pro formátování výpisu #include<stdio.h> void tab(void){ // zadne parametry, nevraci hodnotu printf(" "); // telo funkce } // neni nutno pouzit return() void podtrhni(void){ int i; putchar('\n'); for(i=1;i<60;i++) // podtrhne putchar(''); putchar('\n'); // ukonci radek } main(){ printf("prvni sloupec"); tab(); // zavorky () nesmi byt vynechany printf("druhy sloupec"); tab(); printf("treti sloupec"); podtrhni(); } rekurzivní funkce ● funkce může volat sama sebe ● využití rekurze může vést k nepřednému a neefektivnímu kódu – nevyužívat, pokud není nutné
příklad: výpočet faktoriálu celého čísla s využitím rekurze #include<stdio.h> int fakt(int n){ return((n<=0)? 1 : n*fakt(n1)); // rekurzivni volani funkce } main(){ int k; printf("zadej k:"); scanf("%d",&k); printf("k!=%d\n",fakt(k)); } oblast platnosti proměnných ● lokální proměnné – definice uvnitř funkce, platnost do konce funkce ● globální proměnné – definice vně funkce, platí do konce souboru příklad: lokální proměnná z funkce main() je nedostupná ve funkci tisk_b() #include<stdio.h> int a; // definice globalni promenne void tisk_a(void){ printf("%d\n",a); } void tisk_b(void){ int b; // definice lokalni promenne ve fci tisk_b() b=20; printf("%d\n",b); // tiskne hodnotu "20" } main(){ int b; // definice lokalni promenne ve fci main() a=b=10; tisk_a(); // tiskne hodnotu "10" tisk_b(); printf("%d\n",b); // tiskne hodnotu "10" } volání parametrů ● volání hodnotou – do funkce se předávají kopie skutečných parametrů, nelze je tedy uvnitř funkce měnit ● volání odkazem – jazyk C nezná, lze obejít předáním ukazatelů na skutečné parametry, viz. např. funkce scanf() příklad: funkce vymění obsah proměnných #include<stdio.h> void vymen(int *p_x, int *p_y){ int pom;
pom=*p_x; // referencni operator ziska obsah na adrese "p_x" *p_x=*p_y; *p_y=pom; } main(){ int a=1,b=1; printf("puvodne: %d %d\n",a,b); vymen(&a,&b); // do funkce posilame adresy! printf("po vymene:%d %d\n",a,b); } poznámky: ● operátor * umožňuje přístup k obsahu adresy, např. a=*adr ● operátor & získá adresu proměnné, např. adr=&a ● předání ukazatelů na parametry (předání parametrů odkazem) lze využít pro vrácení dvou a více hodnot z funkce, viz. následující příklad příklad: funkce vypočítá součet a rozdíl dvou celých čísel a výsledek vrátí skrz parametry #include<stdio.h> void spatne(int a, int b, int soucet, int rozdil){ soucet=a+b; // tyto hodnoty budou po opusteni rozdil=ab; // funkce zapomenuty } void spravne(int a, int b, int *soucet, int *rozdil){ *soucet=a+b; // "soucet" ukazuje na "s" *rozdil=ab; // "rozdil" ukazuje na "r" } main(){ int a,b,s,r; a=10; b=22; s=0; r=0; spatne(a,b,s,r); // volani hodnotou printf("funkce spatne(): s=%3d r=%3d\n",s,r); spravne(a,b,&s,&r); // volani odkazem printf("funkce spravne(): s=%3d r=%3d\n",s,r); } příklad: program demonstruje chybu výpočtu numerické derivace #include<stdio.h> #include<math.h> double der(double x, double dx){ double d; d=(sin(x+dx)sin(x))/dx; // numericka derivace return(d); } main(){ int i; double dx;
for(i=1;i>16;i){ dx=pow(10,i); // nastavi dx printf("%d %.20f\n",i,cos(M_PI/4)der(M_PI/4,dx)); } } příklad: program ověří přesnost vlastní implementace funkce sin(x) založené na rozvoji sin(x) v mocninnou řadu: sin x =
∞
i 1 2 i−1
x ∑ −1 2i−1! i=1
#include<stdio.h> #include<math.h> #define pi 3.141592653589793 double faktorial(int n){ double f=1; int i; for(i=2;i<=n;i++) f*=i; return(f); } double mocnina(double x, int a){ double moc=1; int i; for(i=1;i<=a;i++) moc*=x; return(moc); } double mujsin(double x, int clenu){ double suma; int i,n,znamenko; suma=0; znamenko=1; for(i=1;i<=clenu;i++){ n=2*i1; suma+=znamenko*mocnina(x,n)/faktorial(n); znamenko*=1; // znamenko v rade alternuje } return(suma); } main(){ double x,dx,s1,s2,ds; int clenu; x=pi/4.; // nejdrive zjistime jak presnost vypoctu zavisi na poctu clenu // toto provedeme pro uhel pi/4 printf("clenu mujsin sin rozdil\n"); printf("\n"); for(clenu=1;clenu<=5;clenu++){ s1=mujsin(x,clenu); s2=sin(x); ds=s1s2;
printf("%3d %15.8f %12.8f %12.8f\n",clenu,s1,s2,ds); } // nyni overime zda je presnost stejna pro vsechny uhly clenu=3; dx=pi/2./10.; // krok v uhlu printf("\n\n"); // odradkuje printf(" x mujsin sin rozdil\n"); printf("\n"); for(x=0;x<=pi/2.;x+=dx){ s1=mujsin(x,clenu); s2=sin(x); ds=s1s2; printf("%6.4f %15.8f %12.8f %12.8f\n",x,s1,s2,ds); } } funkční prototyp pokud v programu volání nějaké funkce předchází její definici, uvedeme na začátku programu úplný funkční prototyp volané funkce; často jsou tyto deklarace umístěny v hlavičkovém souboru příklad: funkce mujsin() a mujcos() se volají navzájem #include<stdio.h> #include<math.h> #define pi 3.141592653589793 double mujsin(double x); // uplny funkcni prototyp double mujcos(double x){ if(x