Počítače a programování 1 pro obor EST KPC1E TUTORIÁL 4

Slides:



Advertisements
Podobné prezentace
A1PRG - Programování – Seminář Ing. Michal Typová konverze, oblast platnosti, paměťové třídy 9 Verze
Advertisements

Standardní knihovní funkce pro práci s textovými řetězci
Programování v C jazyku - SEMINÁŘ
Počítače a programování 1 Přednáška 13 Jiří Šebesta.
Programovací jazyk C++
Přednáška 11 Jiří Šebesta
Programování funkcí v Excelu
Programování 2 Cvičení 5.
BLIŽŠÍ POHLED NA TŘÍDY, DĚDIČNOST - úvod
Preprocess Úvod do tvorby funkcí Princip preprocesoringu Direktivy preprocesoru Podmíněný překlad Základy tvorby funkcí Zjednodušený popis principu předávaní.
Cvičení 2 Proměnné(jednoduché a složené) a konstanty První program Zápis výrazů.
Programování v C++ Cvičení.
Principy překladačů Běhová podpora Jakub Yaghob. Běhová podpora Statická podpora jazyka Překladač Interface na knihovny Hlavičkové soubory Dynamická podpora.
Skriptový jazyk, který se používá při tvorbě stránek.
Programování v Pascalu Přednáška 7
Materiály k přednášce Úvod do programování Ondřej Čepek.
Medians and Order Statistics Nechť A je množina obsahující n různých prvků: Definice: Statistika i-tého řádu je i-tý nejmenší prvek, tj., minimum = statistika.
MATLAB® ( Funkce v Matlabu ).
8. přednáška typedef - preprocesor Studijní materiály najdete na adrese:
Procedury a funkce Základní charakteristika a použití v programu.
A1PRG - Programování – Seminář Ing. Michal Standardní knihovní funkce pro práci se soubory 13 Verze
Vyučovací hodina 1 vyučovací hodina: Opakování z minulé hodiny 5 min Nová látka 20 min Procvičení nové látky 15 min Shrnutí 5 min 2 vyučovací hodiny: Opakování.
OSNOVA: a) Řetězce v C b) Funkce stdio.h pro řetězce c) Funkce string.h pro řetězce d) Příklad Jiří Šebesta Ústav radioelektroniky, FEKT VUT v Brně Počítače.
A1PRG - Programování – Seminář Ing. Michal Operátory (2. část) 4 Verze
Seminář C cvičení STL, Trolltech Ing. Jan Mikulka.
A1PRG - Programování – Seminář Ing. Michal Ukazatele a pole 10 Verze
Cvičení.
3. Příkazy  Příkazy dělíme na jednoduché a strukturované.  Jednoduché příkazy - žádnou jejich dílčí částí neni příkaz - přiřazovací, vstupu a výstupu,
OSNOVA: a)Programování se soubory b)Záloha databáze v souboru c) Příklady Jiří Šebesta Ústav radioelektroniky, FEKT VUT v Brně Počítače a programování.
OSNOVA: a) Úvod do OOPb) Třídy bez metod c) Třídy s metodamid) Konstruktory a destruktory e) Metody constf) Knihovní třídy g) Třídy ve tříděh) Přetížení.
Datové typy a struktury
Orbis pictus 21. století Tato prezentace byla vytvořena v rámci projektu.
A1PRG - Programování – Seminář Ing. Michal Standardní knihovní funkce pro vstup a výstup 12 Verze
C# - předávání parametrů Centrum pro virtuální a moderní metody a formy vzdělávání na Obchodní akademii T.G. Masaryka, Kostelec nad Orlicí.
OSNOVA: a) Přetížení členských funkcí b) Dědičnost tříd Jiří Šebesta Ústav radioelektroniky, FEKT VUT v Brně Počítače a programování 2 pro obor EST BPC2E.
OSNOVA: a) Preprocesor b) ANSI-C knihovny c) Příklady Jiří Šebesta Ústav radioelektroniky, FEKT VUT v Brně Počítače a programování 1 pro obor EST BPC1E.
7. Typ soubor Souborem dat běžně rozumíme uspořádanou množinu dat, uloženou mimo operační paměť počítače (na disku). Pascalský soubor je abstrakcí skutečného.
OSNOVA: a) Příkazy pro cykly II. b) Příkazy pro řízení přenosu c) Příkazy – příklad d) Řetězce v C e) Funkce “stdio.h“ pro řetězce f) Funkce “string.h“
OSNOVA: a) Příkazy pro větvení b) Příkazy pro cykly c) Příkazy pro řízení přenosu d) Příklad Jiří Šebesta Ústav radioelektroniky, FEKT VUT v Brně Počítače.
OSNOVA: a)Funkce – úvod b) Hlavičky funkcí c) Rekurze funkcí d)Knihovny funkcí e)Příklady Jiří Šebesta Ústav radioelektroniky, FEKT VUT v Brně Počítače.
Pole Arrays.
STRING A UKAZATELE. Co to je řetězec? Řetězec v Javě je samostatný objekt. Je konstantní, co znamená, že jednou vytvořený řetězec nelze změnit. Chceme-li.
Počítače a programování 1 7.přednáška. Základy Pole ve třídách a metodách Pole Arrays.
OSNOVA: a) Ukazatel b) Pole a ukazatel c) Pole ukazatelů d) Příklady Jiří Šebesta Ústav radioelektroniky, FEKT VUT v Brně Počítače a programování 1 pro.
Ukazatele, řetězce Přednáška č. 3. Ukazatele  Ukazatel (pointer) – typ o velikosti 4 bajty (v 32bit. systémech) pro uložení adresy objektu na který ukazuje.
Soubory BI-PA1 Programování a algoritmizace 1, ZS Katedra teoretické informatiky © Miroslav Balík Fakulta informačních technologií České vysoké.
Jazyk C A0B36PRI - PROGRAMOVÁNÍ Část II.
Vícerozměrná pole (1) Jazyk C povoluje, aby pole mělo více rozměrů (dimenzí) než jeden Z vícerozměrných polí bývá nejčastěji použí-váno pole dvourozměrné.
Pokročilé datové typy (struktury, unie, dynamické proměnné)
Funkce Přednáška č. 5. Funkce (functions)  posloupnost příkazů uvedená hlavičkou  využití – opakovaně volaná sekvence – strukturování programu – ošetření.
Programování KONSTANTY, ČTENÍ PO JEDNOM ZNAKU GETCHAR() FORMÁTOVANÝ VÝSTUP POMOCÍ PRINTF, VÝVOJOVÉ DIAGRAMY, CYKLY.
Programování ÚVOD, PROMĚNNÉ, OPERÁTORY A PODMÍNĚNÝ PŘÍKAZ ERIK KRÁL.
Programování OPERÁTOR SIZEOF, FUNKCE, POLE JAKO PARAMETRY FUNKCÍ ERIK KRÁL.
Počítače a programování 2
Typ struktura (1) Datový typ struktura (struct) je agrego-vaný heterogenní datový typ Jedná se o skupinu několika proměnných, které mohou mít různé datové.
Programování ENUM, SWITCH,pole jednorozměrná a vícerozměrná, deklarace, inicializace, kopírování, porovnání Erik Král.
Vícerozměrná pole (1) Jazyk C povoluje, aby pole mělo více rozměrů (dimenzí) než jeden Z vícerozměrných polí bývá nejčastěji použí-váno pole dvourozměrné.
Vzorové řešení zápočtového testu
Programovací jazyk C Autorem materiálu a všech jeho částí, není-li uvedeno jinak, je Ing. Jitka Vlčková. Dostupné z Metodického portálu ISSN.
Algoritmizace a programování
Programování v jazyce C++
Programování v jazyce C++
Funkce výstupu (2) Funkce printf: deklarována v: stdio.h
Reálné typy (1) Zahrnují konečnou podmnožinu těch reálných čísel, která jsou zobrazitelná v paměti počítače (v jistém rozsahu a s jistou přesností) Hodnoty.
Řetězce (24) Funkce strchr: deklarována v: string.h
Oblast platnosti identifikátoru (1)
Typ pole (1) Proměnná typu pole představuje kolekci proměnných stejného datového typu, které mohou být označovány společným jménem (identifikátorem) Pole.
Opakování ze 3. cvičení deklarace proměnných výpis na monitor (výstup)
Typ ukazatel (1) Proměnné typu ukazatel (pointer) uchovávají paměťovou adresu Hodnota ukazatele říká, kde (na jaké adrese) se v paměti nachází nějaký objekt.
Opakování ze 4. cvičení int a; printf("Zadej číslo: ");
Transkript prezentace:

Počítače a programování 1 pro obor EST KPC1E TUTORIÁL 4 OSNOVA: a) Ukazatele b) Pole a ukazatel c) Pole ukazatelů d) Ukazatele - příklady e) Funkce – úvod f) Hlavičky funkcí g) Rekurze funkcí h) Knihovny funkcí i) Funkce - příklady j) Preprocesor k) ANSI-C knihovny Jiří Šebesta Ústav radioelektroniky, FEKT VUT v Brně

Ukazatel (1/10) Ukazatel (pointer) je datový typ sloužící k uložení adresy v paměti počítače Požadovaná velikost pro uložení ukazatele v paměti (počet bytů) je dána paměťovým prostorem, který daný počítačový systém využívá Pro malé mikrokontrolé-rové aplikace je ukazatel obvykle 16ti bitový (2 B) s adresací paměťového prostoru do 64 kB (adresa hexadecimálně 0x0000 až 0xFFFF) 2

Ukazatel (2/10) Pokud je fyzický paměťový prostor větší, používá se segmentace – velký pamě-ťový prostor je rozdělen na segmenty (stránky) o veli-kosti 64 kB a ukazatel definuje adresu na dané stránce, tzv. blízký ukazatel, nebo je použit tzv. vzdálený ukazatel, který obsahuje i identifikaci příslušné pamě-ťové stránky a adresu (off-set) v rámci dané stránky 3

Ukazatel (3/10) U 32 bitových systémů se používá 32 bitový ukazatel, tj. 4 B a adresy v hexadecimálním rozsahu 0x00000000 do 0xFFFFFFFF, celkem 4 GB U 64 bitových systémů se používá 64 bitový ukazatel, tj. 8 B, celkem 16 HB (hexabytů) Pozn. 1 kB = 210 B = 1024 B 1 MB = 220 B = 1024 kB = 1048576 B 1 GB = 230 B = 1024 MB, 1 TB = 240 B = 1024 GB 1 PB = 250 B = 1024 TB, 1 HB = 260 B = 1024 HB, atd. 4

Ukazatel (4/10) Ukazatelová aritmetika (Pointer aritmetics) zahrnuje výpočetní operace nad ukazateli. Adresovatelnou jednotkou může být 1 byte, 1 slovo (2 B), v jazyce C velikost datového typu (char = 1B, int = 4B, …), jenž ukazatel adresuje. int *a, *b; //pointers to integer int x; int y[5] = {1, 2, 3, 4, 5}; a = &x; //pointer a contents address of variable x *a = y[2]; //fill address defined by a by y[2], x=y[2] printf("%d\n", x); b = &(y[3]); //pointer b contents address of var. y[3] *b = *a; //content of address pointed by a is copied to content of address pointed by b printf("%d\n", y[3]); Příklad: KPC1E_Ex42.c 5

Ukazatel (5/10) Prvky jednorozměrného pole jsou v paměti řazeny za sebou, indexovat (ukázat na x-tý prvek) pole lze pomocí ukazatelů. int *adr; //pointer to integer int arr[50], i; adr = &(arr[49]); //pointer is set to the last element for(i=0; i<50; i++) { *adr = i; //a number is paste to the address //defined by pointer adr adr--; //pointer is shifted down (-1 element //of arr = -4 bytes due to int type } printf("%d\n", arr[i]); Příklad: KPC1E_Ex43.c 6

Ukazatel (6/10) Jméno pole bez indexu je ukazatelem na první prvek pole: zápis A[0] je ekvivalentní *A zápis A[5] je ekvivalentní *(A+5) int *adr; //pointer to integer int arr[50], i; adr = arr; //pointer is set to the first element for(i=0; i<50; i++) { *adr = i; //a number is paste to the address //defined by pointer adr adr++; //pointer is shifted up (+1 element //of arr = +4 bytes due to int type } printf("%d\n", arr[i]); Příklad: KPC1E_Ex44.c 7

Ukazatel (7/10) Př. Aplikace relačních operátorů na ukazatele int *a, *b, *c; // pointers to integer int arr[20], i; a = arr; for(i=0; i<20; i++) {*a = i; a++;} for(i=0; i<20; i++) printf("%3d", arr[i]); b = arr+5; c = arr+15; for(i=0; i<20; i++) { if (b<a && c>a) //address a must be between b and c *a=0; a++; } Příklad: KPC1E_Ex45.c 8

Ukazatel (8/10) Př. Integer v paměti po bytech Příklad: KPC1E_Ex46.c int *a; //pointer to int char *b; //pointer to char int arr[5], i; for(i=0; i<5; i++) arr[i] = i; a=arr; for(i=0; i<5; i++) //int address and value displaying { printf("%x %3d\n", a, *a); a++; } b=arr; for(i=0; i<20; i++) //char (byte) addr. and value disp. printf("%x %3d\n", b, *b); b++; Příklad: KPC1E_Ex46.c 9

Ukazatel (9/10) Př. Float v paměti po bytech unsigned char *a; //pointer to uchar float num = 1.2; //float value in memory int i; a=&num; for(i=0; i<4; i++) //four bytes of float value in mem. { printf("%x ", a); //address printf("%x\n", *a); //content a++; } Pro hodnotu 1,2 uloženou jako typ float je v paměti uloženo (hexa) 9A 99 99 3F, uspořádání je od nejméně významného bytu pro nejvíce významný Příklad: KPC1E_Ex47.c 10

Ukazatel (10/10) 1,2 ve float rozlišení má tedy tvar hexa: 0x 3 F 9 9 9 9 9 A binárně: 0b0-01111111-00110011001100110011010 znaménko: 0 = + exponent: 0b01111111 = 127 mantisa: 0b00110011001100110011010 = 1677722 11

Pole a ukazatel (1/3) Dvourozměrné pole v paměti Příklad: KPC1E_Ex48.c int *a; //pointer to int int arr[4][5], i, j; for(i=0; i<4; i++) { for(j=0; j<5; j++) arr[i][j]= 10*i+j;v printf("%3d", arr[i][j]); } printf("\n"); a=arr; for(i=0; i<20; i++, a++) //20 elements of array in mem printf("%x %3d\n", a, *a); //printing Příklad: KPC1E_Ex48.c 12

Pole a ukazatel (2/3) Vícerozměrné pole v paměti Příklad: KPC1E_Ex49.c int *a; //pointer to int int arr[3][3][3], i, j, k; for(i=0; i<3; i++) for(j=0; j<3; j++) for(k=0; k<3; k++) arr[i][j][k] = 100*i + 10*j + k; for(i=0; i<27; i++, a++) //27 elements of array 3x3x3 printf("%x %3d\n", a, *a); //in memory printing Příklad: KPC1E_Ex49.c 13

Pole a ukazatel (3/3) Vícerozměrné pole a ukládání jeho prvků v paměti: Ekvivalentní zápis: arr[i][j][k] = *(arr+i*3*3+j*3+k) 14

Pole ukazatelů (1/2) Př. Aplikace pole ukazatelů – vyhledání pozic znaků v textu char text[] = "okolo kola okolkovala koala"; char *o[10], *c; //o is array of pointers int i=0, j; printf("Original string: %s\n\n", text); printf("Addr. of the beginning of text: %x\n\n", text); o[i] = strchr(text, 'o'); while(o[i]) { c = o[i]+1; i++; o[i] = strchr(c, 'o'); //save addres of ’o’ to //array of pointers } 15

Pole ukazatelů (2/2) Příklad: KPC1E_Ex50.c printf("Addresses of the character o:\n"); for(j=0; j<i; j++) printf("%x - position %d\n", o[j], o[j]-text); for(j=0; o[j]!=0; j++) // changing of all ’o’ by ’k’ *o[j]='k'; printf("\n\nChanged string: %s\n", text); Příklad: KPC1E_Ex50.c 16

Ukazatele - příklady (1/7) Př. Záměna znaků pomocí ukazatele char text[]="okolo kola okolkovala koala"; char *a; printf("Original string: %s\n\n", text); a=text; while(*a!=NULL) { if(*a=='o') *a='k'; else if(*a=='k') *a='o'; a++; } printf("Changed string: %s\n", text); Příklad: KPC1E_Ex51.c 17

Ukazatele - příklady (2/7) Př. Vyhledání a náhrada textu bez std. funkcí pomocí ukazatelů char text[]="sokol kolem jezdil kolem dokola"; char test[]="kol"; char ntext[]="----------"; char *a, *b, *c; int tst; a=text; b=test; printf("Original string: %s\n\n", text); for(a=text; *a!=NULL; a++) { tst=1; c=a; for(b=test; *b!=NULL; b++,c++) if (*c!=*b) tst=0; 18

Ukazatele - příklady (3/7) if(tst) { c=ntext; for(b=test; *b!=NULL; b++, c++, a++) *a=*c; } printf("Changed string: %s\n", text); Příklad: KPC1E_Ex52.c 19

Ukazatele - příklady (4/7) Př. V řetězcové proměnné wtxt a btxt ve jsou uloženy zhuštěně pozice figurek bílého, resp. černého, na šachovnici se 64 políčky (8x8) ve formě písmeno řádku (A až H) a číslo sloupce (1 až 8). Doplňte program, který postupně projde texty ve wtxt a btxt a do pole field vloží na příslušná místa znaky 'W' a 'B' označující figurku příslušného hráče a situaci vytiskněte do konzolového okna. Procházení řetězci i polem řešte pomocí ukazatelů. #include <stdio.h> int main() { char wtxt[]="A6B8A4D7E2C3F1F2"; char btxt[]="C3A7B1D1E4E5F5H3H5"; char field[64]; char *p, *t, i, j; 20

Ukazatele - příklady (5/7) p=field; for(i=0, p=field; i<64; i++, p++) *p= ' '; p=wtxt; do { t=field+8*(*p-'A'); p++; t+=(*p-'1'); *t='W'; } while(*p!='\0'); 21

Ukazatele - příklady (6/7) p=btxt; do { t=field+8*(*p-'A'); p++; t+=(*p- '1' ); *t='B'; } while(*p!='\0'); printf("\n |"); for(i='1'; i<='8'; i++) printf("%c|", i); printf("\n -"); printf("--"); 22

Ukazatele - příklady (7/7) for(i='A', p=field; i<='H'; i++) { printf("\n%c |", i); for(j='1'; j<='8'; j++, p++) printf("%c|", *p); } return 0; http://www.uschovna.cz/zasilka/BB2W965K9U3BMRYB-Y5E/ Výstup na obrazovce: Příklad: KPC1E_Ex53.c 23

Funkce: posloupnost příkazů uvedená hlavičkou Funkce – úvod (1/3) Funkce: posloupnost příkazů uvedená hlavičkou Využití: opakovaně volaná sekvence = jeden kód pro danou část vykonávaného algoritmu, ušetří se programová paměť strukturování programu = funkce pro danou skupinu úloh (algoritmů) jsou zapouzdřeny ve společné knihovně (nezávislý soubor), volání dané funkce se provádí jen předáváním parametrů v hlavičce – např. y=cos(x), zdrojový soubor pro vykonání kosinu je skrytý v knihovním souboru ošetření událostí = v případě vzniku události na základě přerušení (aktivační signál) se zavolá příslušná funkce, např. pohyb myší zavolá funkci, která přepočítá novou pozici kurzoru

Co se děje při volání funkce: Funkce – úvod (2/3) Co se děje při volání funkce:

Funkce – úvod (3/3) Základní dělení funkcí: - funkce bez parametru - funkce s parametrem volané parametrem – nezmění obsah vstupních pro-měnných, ty jsou kopírovány do nových proměnných alokovaných během provádění funkce volané odkazem – mohou měnit obsah vstupních proměnných, předává se adresa proměnné, proto ji lze kdykoli během vykonávání funkce změnit) funkce s/bez návratové hodnoty – pokud potřebujeme vrátit více než jednu hodnotu (výstup), musíme místa pro uložení výstupů definovat jako volání odkazem

Hlavičky funkcí (1/13) Funkce bez parametru a bez návratové hodnoty: void func_name(void) { } void warning(void) // no input, no output { printf("Your computer is being destroyed"); getchar(); } void main(void) warning(); // calling the function

Hlavičky funkcí (2/13) Funkce s jedním parametrem volaným hodnotou a s návratovou hodnotou: double func_name(double A) { } int pow3(int A) // 1 input, 1 output { int y = A*A*A; return y; } void main(void) { int n; for(n=0; n<20; n++) printf("%d^3 is %d\n", n, pow3(n)); }

Hlavičky funkcí (3/13) Funkce se dvěma parametry volanými hodnotou a s návratovou hodnotou: double func_name(double A, double B) { } Funkce pro n-tou mocninu racionálního čísla float pow_n(float A, int B) // 2 inputs, 1 output { float y=1; int n; for(n=0; n<=B; n++) if(n>0) y*=A; return y; }

Hlavičky funkcí (4/13) Příklad: KPC1E_Ex54.c int main(void) { int n; float y[9]; float m = 5.123; for(n=2; n<11; n++) y[n-2] = pow_n(m, n); printf("%dth power of %f is %f\n", n, m ,y[n-2]); } getchar(); return 0; Příklad: KPC1E_Ex54.c

Hlavičky funkcí (5/13) Funkce s parametrem typu řetězec ??? func_name(char* A) { } Funkce pro nalezení počtu znaků číslic v řetězci int numinstr(char *s) { int n, cnt=0; for(n=0; s[n]!='\0'; n++) if(s[n]>='0‘ && s[n]<='9') cnt++; return cnt; }

Hlavičky funkcí (6/13) Příklad: KPC1E_Ex55.c int main(void) { char txt1[]="ab9bj65D9"; char txt2[]="34x9z56A0"; char txt3[]="3cvz1111E"; int n1, n2, n3; n1=numinstr(txt1); n2=numinstr(txt2); n3=numinstr(txt3); printf("%d in 1st, %d in 2nd, %d in 3rd", n1, n2, n3); getchar(); return 0; } Příklad: KPC1E_Ex55.c

Hlavičky funkcí (7/13) Funkce s parametry volanými odkazem ??? func_name(int *A, int *B) { } Parametry jsou ukazatele odkazující na pozice proměnných v paměti Funkce pro převod z polárních do kartézských souřadnic void polar2cart(float *A, float *B) // A is magnitude { // B is phase in deg. float pha; pha=3.1415**B/180; *B=*A*sin(pha); // B is imag. part *A=*A*cos(pha); // A is real part }

Hlavičky funkcí (8/13) Příklad: KPC1E_Ex56.c int main(void) { float x=2.0; float y=90.0; printf("Magnitude is %f and phase is %f deg.", x, y); polar2cart(&x, &y); printf("Real part is %f and imag. part is %f", x, y); getchar(); return 0; } Příklad: KPC1E_Ex56.c

Hlavičky funkcí (9/13) Funkce s parametrem jako odkazem na první prvek pole (podobně jako u řetězců) Funkce pro výpočet střední hodnoty vektoru racionálních čísel float mean(float *vect, int n) // vect is input vector { // n is length of the vector int m; float s=0; // s is partial sum for(m=0; m<n; m++) // for all elements of vector s+=vect[m]; return s/(1.0*n); // average computation }

Hlavičky funkcí (10/13) Příklad: KPC1E_Ex57.c int main(void) { float x[5], m; int len_x=5, n; srand(time(NULL)); for(n=0; n<len_x; n++) x[n]=(rand()%1000)/100.0; printf("%4.2f\n", x[n]); } m = mean(x, len_x); printf("The average of vector of number is %f", m); getchar(); return 0; Příklad: KPC1E_Ex57.c

Hlavičky funkcí (11/13) Definice proměnné vlastního typu pomocí typedef typedef int t_mat[3][3]; void func_name(t_mat A, t_mat B) { } int func_name(t_mat A) { } t_mat func_name(t_mat A) { } ! Funkce může vracet pouze hodnotu (ne pole)

Hlavičky funkcí (12/13) Funkce pro výpočet determinantu matice 3x3 typedef int t_mat[3][3]; int det_mat(t_mat x) // determinant of 3x3 matrix { int det=0, m, n, pplus, pminus; for(m=0; m<3; m++) pplus=1; pminus=1; for(n=0; n<3; n++) pplus*=x[(m+n)%3][n]; pminus*=x[(m+n)%3][2-n]; } det+=pplus-pminus; } return det;

Hlavičky funkcí (13/13) Příklad: KPC1E_Ex58.c int main(void) { t_mat mat; int m, n; srand(time(NULL)); for(m=0; m<3; m++) //random matrix for(n=0; n<3; n++) mat[m][n]=rand()%198-99; //from -99 to +99 printf("The determinant is %d", det_mat(mat)); getchar(); return 0; } Příklad: KPC1E_Ex58.c

Rekurze funkcí (1/1) Funkce může v jejím těle volat sebe samu – rekurzivní funkce int func_name(int A) { … x=func_name(y); … } Funkce pro výpočet faktoriálu unsigned int factorial(unsigned int n) { if(n) // test if n is not zero return n*factorial(n-1); // n is not zero else // n is zero return 1; } Příklad: KPC1E_Ex59.c

my_lib.c: soubor obsahující zdrojové kódy našich funkcí Knihovny funkcí (1/10) Ze souboru vlastních funkcí lze vytvořit knihovnu: my_lib.c: soubor obsahující zdrojové kódy našich funkcí my_lib.h: soubor obsahující hlavičky našich funkcí ze stejnojmenného souboru, v hlavičce jsou definovány typy proměnných a jméno funkce, jednotlivé hlavičky musí být odděleny středníkem pomocí direktivy #include "my_lib.h" vložené na začátek programu aktivuji přístup k funkcím z příslušného knihovního souboru my_lib.c, linker přidá knihovnu k projektu

Knihovny funkcí (2/10) Postup v Code::Blocks: File > New > File my_lib.c + my_lib.h do adresáře projektu nebo do vlast-ního adresáře s vlastními knihovnami

Knihovny funkcí (3/10) Nastavení cest pro kompilátor v Code::Blocks: Settings > Compiler přidat cesty se zdrojovými soubory a hlavičkami knihoven tak, aby se přeložili i zdrojové kódy vlastních knihovních funkcí

hlavičkový soubor matops.h Knihovny funkcí (4/10) Př. Vlastní knihovna funkcí pro práci s maticemi 3x3 hlavičkový soubor matops.h typedef int t_mat [3][3]; int det_mat(t_mat A); // determinant of A void print_mat(t_mat A); // printing A void gen_mat(t_mat A, int start, int stop); // gener. A void copy_mat(t_mat A, t_mat B); // copying A to B void add_mat(t_mat A, t_mat B); // A=A+B void sub_mat(t_mat A, t_mat B); // A=A-B void clr_mat(t_mat A); // zeroing A definice vlastních typů proměnných definice hlaviček funkcí s typy vstupních i výstupních parametrů

zdrojový soubor knihovny matops.c Knihovny funkcí (5/10) zdrojový soubor knihovny matops.c zdrojové kódy jednotlivých funkcí podle hlavičkového souboru matops.h #include <stdio.h> #include <time.h> #include <stdlib.h> typedef int t_mat[3][3]; int det_mat(t_mat A) // compute determinant { int det=0, m, n, pplus, pminus; for(m=0; m<3; m++)

Knihovny funkcí (6/10) pplus=1; pminus=1; for (n=0; n<3; n++) { pplus*=A[(m+n)%3][n]; pminus*=A[(m+n)%3][2-n]; } det+=pplus-pminus; return det;

Knihovny funkcí (4/10) void print_mat(t_mat A) // printing matrix A { int m,n; for(m=0; m<3; m++) { for(n=0; n<3; n++) { printf("%4d ", A[m][n]); } printf("\n"); void gen_mat(t_mat A, int start, int stop) // random { int m, n; // generation of matrix A srand(time(NULL)); for(n=0; n<3; n++) A[m][n]=rand()%(stop-start+1)+start;

Knihovny funkcí (4/10) void copy_mat(t_mat A, t_mat B) // copying A to B { int m, n; for(m=0; m<3; m++) for(n=0; n<3; n++) A[m][n]=B[m][n]; } void add_mat(t_mat A, t_mat B) // A=A+B A[m][n]+=B[m][n];

Knihovny funkcí (4/10) void sub_mat(t_mat A, t_mat B) // A=A-B { int m, n; for(m=0; m<3; m++) for(n=0; n<3; n++) A[m][n]-=B[m][n]; } void clr_mat(t_mat A) // zeroizing A int m,n; A[m][n]=0;

Knihovny funkcí (4/10) Př. Program, který využívá naši knihovnu matops.h #include <stdio.h> #include "matops.h" int main(void) { t_mat mat1, mat2, mat3; // this type was defined //in mathops.h int m, n; gen_mat(mat1, -9, 9); print_mat(mat1); printf("The det. of mat1 is %d\n",det_mat(mat1)); copy_mat(mat3, mat1); sub_mat(mat1, mat2); … Příklad: KPC1E_Ex60.c + matops.c(h)

Funkce - příklady (1/2) Př. Vytvořte knihovnu funkcí pro vý-počet plochy 2-D geometrických objektů (funkce sestavte pro obdélníka, elipsu a trojúhelník). Hlavičkový soubor knihovny areas2D.h double s_rect(double a, double b); double s_ell (double a, double b); double s_tri (double a, double b);

Funkce - příklady (2/2) Knihovní funkce areas2D.cpp #include "areas2D.h" double s_rect(double a, double b) { return a*b;} double s_ell (double a, double b) { return 3.1415*a*b;} double s_tri (double a, double b) { return 0.5*a*b;} Příklad: KPC1E_Ex61.c + areas2D.c(h)

Proces generování spustitelného kódu Preprocesor (1/13) Proces generování spustitelného kódu Úkolem preprocesoru je: odstranit komentáře ze zdrojo-vého kódu vložit soubory, které mají být kompilovány odstranit části kódu určeného direktivami #if rozvinout předdefinovaná makra

Činnost preprocesoru lze řídit direktivami: - začínají vždy znakem # Vložení jiného souboru do souboru – direktiva #include #include <jméno souboru> nový_řádek – pro vložení standardního hlavičkového souboru (musí být v adresáři pro standardní hlavičkové soubory) př. #include <stdio.h> #include "jméno souboru" nový_řádek – pro vložení vlastního zdrojového (hlavičkového) souboru (musí být v adresáři projektu nebo lze specifikovat i s cestou) př. #include "my_lib.h"

Preprocesor (3/13) #include MAKRO nový_řádek – pro vložení (rozvinutí) MAKRA specifikovaného dříve uvedenou direktivou #define (viz dále) (nesmí obsahovat < > ") př. #include my_macro Definice maker – direktiva #define Makro (makroinstrukce) nahrazuje posloupnost znaků posloup-ností nahrazujících znaků #define identifikátor řetězec nový_řádek – makro bez parametrů př. #define PI 3.1415 - za všechna PI nahradí ve zdrojovém textu 3.1415

Preprocesor (4/13) Každý výskyt identifikátoru je nahrazen řetězcem, to neplatí v ko-mentářích, řetězcích mezi " " a mezi < > v direktivě #include Není-li řetězec uveden, identifikátor je preprocesorem ze zdrojo-vého textu odstraněn #define identifikátor(seznam_parametrů) řetězec nový_řádek – makro s parametry př. #define ABS(re,im) sqrt(((re)*(re))+((im)*(im))) Vkládání závorek je důležité pro specifikaci priority operátorů: Pokud bude makro #define ABS(re,im) sqrt(re*re+im*im) a ve zdrojovém kódu c=ABS(a+1,b-1) pak po nahrazení preprocesorem bude c=sqrt(a+1*a+1+b-1*b-1) po zjednodušení výrazu c=sqrt(2*a)

Př. Makro pro absolutní hodnotu komplexního čísla Preprocesor (5/13) Př. Makro pro absolutní hodnotu komplexního čísla #include <stdio.h> #include <math.h> #define PI 3.1415 #define ABS(re,im) sqrt(((re)*(re))+((im)*(im))) int main() { float r=12, ar=1.6, ai=2.2; printf("Circle area is %f\n", PI*r*r); printf("Absolute value of %f + j*%f is %f\n", ar, ai, ABS(ar,ai)); return 0; } Příklad: KPC1E_Ex62.c

Preprocesor (6/13) Parametry v makru mohou reprezentovat různé datové typy – makro je univerzální (v příkladu float a int) #include <stdio.h> #include <math.h> #define ROOT1(a,b,c) (-(b)+sqrt((b)*(b)-4*(a)*(c)))/(2*(a)) #define ROOT2(a,b,c) (-(b)-sqrt((b)*(b)-4*(a)*(c)))/(2*(a)) int main() { float fa=1.3, fb=5.6, fc=1.2; int ia=1, ib=5, ic=2; printf("Roots for %3.1fx^2+%3.1fx+%3.1f=0 are %5.3f and %5.3f\n", fa, fb, fc, ROOT1(fa, fb, fc), ROOT2(fa, fb, fc)); printf("Roots for %dx^2+%dx+%d=0 are %5.3f and %5.3f\n", ia, ib, ic, ROOT1(ia, ib, ic), ROOT2(ia, ib, ic)); return 0; } Příklad: KPC1E_Ex63.c

Preprocesor (7/13) Nevhodné použití makra #include <stdio.h> #define POW3(A) ((A)*(A)*(A)) int main() { int x = 10; printf("%d^3 = %d\n", x, POW3(x)); printf("%d\n", POW3(++x)); return 0; } V prvním použití makra POW3 je vše v pořádku, při druhém použití makra POW3 bude rozvoj následující: ((++x)*(++x)*(++x)), výsledek bude 12*12*13 = 1872 proč? Příklad: KPC1E_Ex64.c

Preprocesor (8/13) Operátory # a ## v makrech Operátory # a ## se používají v makrech s parametry. Za operátor # se dosadí řetězec, který je stejný jako parametr makra. Operátor ## spojí své dva parametry v jeden řetězec. #include <stdio.h> #define SUM(A,B) printf("%s = %d\n",#A " + " #B,(A)+(B)) #define JOINT(A,B) A ## B int main() { int n1=10, n2=20; SUM(5,6); SUM(JOINT(n,1),JOINT(n,2)); return 0; } Příklad: KPC1E_Ex65.c

Preprocesor (9/13) Standardní makra (ANSI C) __TIME__ - aktuální čas spuštění preprocesoru (vrací řetězec) __DATE__ - aktuální datum spuštění preproc. (vrací řetězec) __FILE__ - jméno souboru zpracovávaného preprocesorem __LINE__ - číslo aktuálního řádku (vrací int) __STDC__ - definuje, zda překladač splňuje normu ANSI (vrací int – 1 splňuje / 0 nesplňuje) #include <stdio.h> int main() { printf("%s\n", __TIME__); printf("%s\n", __DATE__); printf("%s\n", __FILE__); printf("%d\n", __LINE__); printf("%d\n", __STDC__); return 0; } Příklad: KPC1E_Ex66.c

Preprocesor (10/13) Rušení platnosti maker – direktiva #undef #undef identifikátor – od daného místa se ruší platnost makra př. #define PI 3.1415 … #undef PI … // PI se už dále nenahrazuje #define PI 3.14 … // PI se zde nahrazuje za 3.14

Preprocesor (11/13) Podmíněný překlad – direktivy #if, #endif, #elif, #else #if podmínka_A zdrojový kód pro splněnou podmínku_A #elif podmínka_B zdrojový kód pro splněnou podmínku_B (nesplněna podmínka_A) #elif podmínka_C zdrojový kód pro splněnou podmínku_C (nesplněna A i B) #else zdrojový kód pro stav, kdy žádná z předchozích podmínek nebyla splněna #endif V podmínkách musí být výrazy, které může vyhodnotit preproce-sor (nelze používat hodnoty proměnných atd.).

Podmíněný překlad lze využít při různých úrovních ladění Preprocesor (12/13) Podmíněný překlad lze využít při různých úrovních ladění #include <stdio.h> #define DEBUGING 2 int main() { int a = 10; #if DEBUGING==1 a++; #elif DEBUGING==2 a=a*a*a; #else a=0; #endif printf("%d\n", a); return 0; } Příklad: KPC1E_Ex67.c

Preprocesor (13/13) Podmíněný překlad – direktivy #ifdef, #ifndef Pomocí #if defined lze vyhodnocovat, zda již existuje určité makro (bylo-li definováno), zkráceně #ifdef. Pomocí #if !defined lze vyhodnocovat, zda neexistuje určité makro (nebylo-li definováno), zkráceně #ifndef. Nejčastěji se používá pro ošetření násobné definice: #ifndef PI #define PI 3.1415 #endif #ifdef PI c=2*PI*r;

ANSI-C knihovny (1/6) Knihovna matematických funkcí math.h Trigonometrické funkce (úhly vždy v Radiánech): double sin(double x); double cos(double x); double tan(double x); double asin(double x); double acos(double x); double atan(double x); double atan2(double y, double x); printf("%f", 180/3.1415*atan2(sqrt(3)/3,1)) double sinh(double x); double cosh(double x); double tanh(double x);

ANSI-C knihovny (2/6) Exponenciální, logaritmické a mocninné funkce: double exp(double x); double log(double x); double log10(double x); double pow(double x, double y); //x^y double sqrt(double x); Ořezávání a další pomocné funkce (viz př.): double ceil(double x); double floor(double x); double fabs(double x); double ldexp(double x, int n); double frexp(double x, int* exp); double modf(double x, double* ip); double fmod(double x, double y);

ANSI-C knihovny (3/6) Př. #include <stdio.h> #include <stdlib.h> #include <math.h> int main() { double a=-1.11, b=2.21, i, f; int c=2, e; printf("atan2(%.2f,%.2f)=arctg(%.2f/%.2f)=%.2f\n\n", a, b, a, b, atan2(a,b)); printf("exp(%.2f)=e^%.2f=%.2f\n\n", a, a, exp(a)); printf("log(%.2f)=ln(%.2f)=%.2f\n\n", b, b, log(b)); printf("log10(%.2f)=%.2f\n\n", b, log10(b)); printf("fabs(%.2f)=%.2f\n\n", a, fabs(a)); printf("ceil(%.2f)=%.2f\n\n", a, ceil(a)); printf("floor(%.2f)=%.2f\n\n", a, floor(a));

ANSI-C knihovny (4/6) Příklad: KPC1E_Ex68.c printf("ldexp(%.2f, %d)=%.2f*2^%d=%.2f\n\n", a, c, a, c, ldexp(a,c)); printf("f=frexp(%.2f, &e): ", b); f=frexp(b, &e); printf("f=mantissa=%.4f; e=exponent=%d, ", f, e); printf("i.e. x=mantissa*2^exponent=%.4f*2^%d= %.2f\n\n", f, e, f*pow(2,e)); printf("f=modf(%.2f, &i): ", a); f=modf(a, &i); printf("f=fractional_part=%.2f;i=integral_part=%.2f\n\n", f, i); printf("fmod(%.2f,%.2f)=remainder(%.2f/%.2f)=%.2f\n\n", b, a, b, a, fmod(b,a)); return 0; } Příklad: KPC1E_Ex68.c

ANSI-C knihovny (5/6) Další knihovny assert.h – makro assert pro účely ladění ctype.h – funkce pro testování znaků, do jaké skupiny patří, např. islapha(char x) vrátí 1 (true) pokud je znak x z rozsahu 'A'až 'Z' nebo 'a'až 'z' errno.h – makra a proměnná errno pro definici chyby float.h – předdefinované konstanty pro maxima a minima hodnot racionálních typů limits.h – předdefinované konstanty pro maxima a minima hodnot celočíselných typů locale.h – nastavení a čtení národního nastavení, např. des. tečka/čárka apod. setjmp.h – funkce pro nastavení parametrů volání u funkcí

ANSI-C knihovny (6/6) signal.h – makra a funkce pro reporty signálů vznikajících během výkonu programu stdarg.h – makra pro práci s argumenty stddef.h – standardní definice (např. NULL) stdio.h – funkce pro vstupy a výstupy stdlib.h – různé základní funkce, např. konverze z řetězců na číselné hodnoty a naopak string.h – funkce pro práci s řetězci time.h – funkce pro práci s časem

Téma následujícího tutoriálu DĚKUJI ZA POZORNOST Téma následujícího tutoriálu Struktury Unie Výčtový typ Dynamické proměnné Programování se soubory Záloha databáze v souboru Algoritmy