Prezentace se nahrává, počkejte prosím

Prezentace se nahrává, počkejte prosím

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

Podobné prezentace


Prezentace na téma: "Počítače a programování 1 pro obor EST KPC1E TUTORIÁL 4"— Transkript prezentace:

1 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ě

2 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

3 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

4 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 0x 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 = 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

5 Ukazatel (4/10) Ukazatelová aritmetika (Pointer aritmetics) zahrnuje výpočetní operace nad ukazateli. Adresovatelnou jednotkou může být 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

6 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

7 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

8 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

9 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

10 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=# 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 F, uspořádání je od nejméně významného bytu pro nejvíce významný Příklad: KPC1E_Ex47.c 10

11 Ukazatel (10/10) 1,2 ve float rozlišení má tedy tvar
hexa: x F A binárně: 0b znaménko: 0 = + exponent: 0b = 127 mantisa: 0b = 11

12 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

13 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

14 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

15 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

16 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

17 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

18 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

19 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

20 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

21 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

22 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

23 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; Výstup na obrazovce: Příklad: KPC1E_Ex53.c 23

24 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

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

26 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

27 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

28 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)); }

29 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; }

30 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

31 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; }

32 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

33 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 }

34 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

35 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 }

36 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

37 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)

38 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;

39 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

40 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

41 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

42 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

43 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í

44 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ů

45 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++)

46 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;

47 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;

48 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];

49 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;

50 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)

51 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);

52 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 *a*b;} double s_tri (double a, double b) { return 0.5*a*b;} Příklad: KPC1E_Ex61.c + areas2D.c(h)

53 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

54 Č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"

55 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 - za všechna PI nahradí ve zdrojovém textu

56 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)

57 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 #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

58 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

59 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 = proč? Příklad: KPC1E_Ex64.c

60 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

61 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

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

63 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.).

64 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

65 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 #endif #ifdef PI c=2*PI*r;

66 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);

67 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);

68 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));

69 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

70 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í

71 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

72 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


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

Podobné prezentace


Reklamy Google