Programski jezik C - 6. deo (materijal sa predavanja D. Vitasa) EXIT Funkcija exit Funkcija exit se nalazi u <stdlib.h> sa prototipom void exit( status ); Izaziva normalan završetak programa (zatvaranje datoteka, itd.) 1
exit Razlika u main između exit i return: return izraz ekvivalentno sa exit( izraz ) Prednost je što se exit može pozvati iz drugih funkcija (osim main) PREUSMERAVANJE Redirekcija ili preusmeravanje Neka program prg očekuje podatke sa tastaure, a rezultate neka ispisuje na ekranu: stdin scanf prg printf stdout Ponekada, umesto sa standardnih U/I, potrebno je da podaci stižu ili se upisuju u neku datoteku. 2
Redirekcija ili preusmeravanje Operator < preusmerava ulaz tako da progaram umesto sa stdin, podatke uzima iz datoteke. Slično, operator > preusmerava izlaz umesto na stdin u neku datoteku. < ulaz scanf prg printf > izlaz Poziv: prg <ulaz >izlaz Redirekcija ili preusmeravanje Preusmeravanje iz stdin: operator < Preusmeravanje u stdout: operator > Preusmeravanje u stderr: operator 2> Režim dopisivanja: operator >> Pretraživanje niza (struktura) 3
Problem pretraživanja Dat je niz, npr. 1. Petar 1.82m 70k 2. Jelena 1.76m 72k 3. Milan 1.76m 75k 4. Ana 1.60m 53k Treba utvrditi da li se ključ k javlja u nizu ili ne. Npr. ključ visina --> k = 1.60m Odgovor: Da ključ težina --> k = 100k Odgovor: Ne ključ ime --> k = Milan Odgovor: Da Identifikacija ključa omogućava da se pronađe informacija koja je pridružena ključu. Jednostavna varijanta lineranog pretraživanja N = 8 a.k 5 4 2 7 1 4 3 1 0 1 2 3 4 5 6 7 8 9 10 11 Ključ je kljuc = 7. Polazeći od pozicija i =0, ispitujemo da li je a[ i ] == kljuc (jeste, za i = 4) Ako jeste, ključ je prisutan u nizu, vraćamo informaciju o poziciji ključa. Inače se upućuje poruka da ključ nije u nizu Tada su moguće različite akcije, npr. umetanje ključa. Linerano pretraživanje int N; int a[n ]; // Niz koji se pretrazuje... int lin_pretraga( int kljuc) { for( i = 0; i < N; i++ ) if( a[i] == kljuc ) return i; return -1; // indeks je normalno >= 0! (Funkcija vraća indeks prvog elementa niza koji je jednak ključu.) 4
Složenija varijanta lineranog pretraživanja 1. struct element { int kljuc; int info; // char, char[], struct,... 2. struct element a[100]; 3. Implementacije pretraživanja Linerano pretraživanje N = 8 a.k 5 4 2 7 1 4 3 1 0 1 2 3 4 5 6 7 8 9 10 11 Ključ je kljuc = 7. Polazeći od pozicija i =0, ispitujemo da li je a.k[ i ] == kljuc (jeste, za i = 4) Ako jeste, ključ je prisutan u nizu i uzimamo a.info [ i ]. Inače se upućuje poruka da ključ nije u nizu (tada su moguće različite akcije, npr. umetanje ključa). Implementacija int N; struct element a[n ]; // Niz koji se pretrazuje... int lin_pretraga( int kljuc) { for( i = 0; i < N; i++ ) if( a[i].k == kljuc ) return i; return -1; // Indikator da ključ nije u nizu (Funkcija vraća indeks prvog elementa niza koji je jednak ključu.) 5
Komentari Uloga stražara : obezbeđuje da ključ uvek nađe u nizu, a preko izabrane vrednost info (npr, -1) saopštava da ga nema. Komponenta info može da bude vrlo složena struktura (npr. ime, datum, JMBG,...) Postupak ne zavisi od tipa ključa. Npr. ako int ključ zamenimo sa char *kljuc, a u while poređenje obezbedimo preko strcmp, funkcija linpretraga pretraživaće niske!!! Složenost: za neuspelo pretraživanje N+1 poređenja kod uspešnog pretraživanja N/2 poređenja Binarno pretraživanje Princip "Podeli, pa vladaj" Osnovna pretpostavka: niz je sortiran u odnosu na neki poredak pridružen tipu niza. Princip: kljuc=7 N = 10 a 1 2 3 4 7 9 10 12 22 30 l (l+d)/2 d Implementacija int binsearch( int v ) { int l = 0, d = N -1, x; while( d > l ) { x = ( l + d )/2; if( v < a[x].k ) d = x - 1; else l = x + 1; if( v == a[x].k ) return a[x].info; return -1; 6
Primer i 0 1 2 3 4 5 6 7 a: 1 3 5 7 9 11 13 15 a: 9 11 13 15 N = 8, v = 13 l = 0; d = 8 x = 4 --> a[x].k = 9 < v l = 5; d = 8 x = 6 --> a[x].k = 13 = v Složenost: najviše log N + 1 poređenja, bez obzira da li je uspešno ili ne POLINOMI Izračunavanje polinoma Polinomi koeficijenti P(x) = a n x n +... + a 1 x + a 0 se koriste u razlučitim prilikama: a. reprezentacija brojeva: x = b k 2 k +... + b 1 2 1 + b 0 2 0 b. aproksimacija funkcija sin(x) x 5 /5! - x 3 /3! + x/1! c. itd. 7
Reprezentacija polinoma Jedan način predstavljanja polinoma je preko niza koeficijenta: float a[ N ]; u koji se unose koeficijenti polinoma a[0],...,a [N-1]. Kako ispisati polinom: 0.0*x^3 + 1.0*x ^2 + 0.0*x^1 + 1.0 (TeX) Funkcija za ispis void ispis( float p[] ) { // ispis polinoma printf("%.1f", p[0] ); // 0-ti clan for( i = 1; i < N; i++ ) printf("+ %.1f x^%d", p[ i ], i ); printf("\n"); Kako se izvršava za float a[n = {1, 0, 1, 0? Druga reprezentacija Drugi način predstavljanja je pomoću struktura: typedef struct { float koef[ N ]; int stepen; Polinom; 8
Primer Opis polinoma x^3 + 2*x^1-1.0 (TeX) se zadaje sa: #define N 10 Polinom p; p.stepen = 3; p.koef[3] = 1; p.koef[2] = 0; p.koef[1] = 2; p.koef[0] = -1; Funkcija za ispis void ispis( Polinom p ) { // ispis polinoma printf("%.1f", p.koef[0] ); // 0-ti clan for( i = 1; i <= p.stepen; i++ ) printf("+ %.1f x^%d", p.koef[ i ], i ); printf("\n"); Operacije sa polinomima: zbir Ako su dati polinomi onda P(x) = a n x n +... + a 1 x + a 0 Q(x) = +b n x n +... + b 1 x + b 0 P(x)+Q(x) = (a n +b n )x n +...+(a 1 +b 1 )x+(a 0 +b 0 ) 9
Zbir polinoma - 1. način void zbir(float p[], float q[], float r[]) { for( i = 0; i < N; i++ ) r[ i ] = p[ i ] + q[ i ]; void main( void ){ float a[n] = {1,0,1,0, b[n] = {0,1,-1,0, float c[n]; zbir( a, b, c ); ispis( c ); // 1.0 + 1.0*x ^1 + 0.0*x^2 + 0.0*x^3 Zbir polinoma - 2. način Polinom zbir( Polinom p, Polinom q ) { Polinom r; r.stepen=(p.stepen>q.stepen)? p.stepen : q.stepen; //? for( i = 0; i <= r.stepen; i++ ) r.koef[ i ] = p.koef[ i ] + q.koef[ i ]; /* Svodjenje stepena */ for( i = r.stepen; (i >= 0) && (r.koef[ i ] == 0 ); r.stepen--); return r; Proizvod polinoma Proizvod polinoma je dat sa p(x) * q(x) = c 2n x 2n +... + c 1 x + c 0 gde je c k = Σ a i b j (i + j = k) Da bismo izračunali proizvod, pretpostavimo da je stepen proizvoda N-1. 10
1. verzija void proizvod(float p[], float q[], float r[]) { int i, k; float s; for( k = 0; k < N; k++ ) { s = 0.; // suma koeficijenata for( i = 0; i <= k; i++ ) { s = s + p[i] * q[k-i]; r[ k ] = s; 2. varijanta (struktura) Polinom proizvod( Polinom p, Polinom q ) { int i, j, k; Polinom r; r.stepen= p.stepen + q.stepen; for( k = 0; k <= r.stepen; k++ ) r.koef[ i ] = 0; for( i = 0; i <= p.stepen; i++ ) { for( j = 0; j <= q.stepen; j++ ) { r.koef[ i+j ] += p.koef[ i ]*q.koef[ j ]; return r; Izračunavanje vrednosti Potrebno je izračunati P(x) = a n x n +... + a 1 x + a 0 kada je x = k i to tako da izračunavanje bude a. brzo b. neposredno (bez pomoćnog niza vrednosti) 11
1. način Da bismo izračunali P(k) = a n k n +... + a 1 k + a 0 Izračunavamo zbir za i = 1,...,n i to a. stepen k i b. proizvod a i k i Da bi izračunavanje k i bilo brzo, računamo sdesna na levo: 1, k, k 2,..., k n Rešenje (naivno) float eval( float a[], float k) { float v, y; v= 0; // vrednost y= 1; // član uz a_0 for (i= 0; i<n; i++) { v= v + a[i]*y; // a(i)*k^n y = y*k; // sledeći stepen return v; 2. način (Hornerova šema) Polinom se može predstaviti u fatorisanom obliku: P(x) = (...(a n x + a n-1 )x... + a 1 )x + a 0 Izračunavanje se vrši sleva na desno i to za i = n-1,..., 1, 0: a. množimo sa k b. dodajemo a i 12
Rešenje (Horner) float horner(float a[], float k) { float v; v = a[n-1]; for (i = N-2; i>=0; i--) v = v*k+a[i]; return v; Poređenje Hornerove i naivne metode a. Broj operacija za polinom stepena n: naivno Horner sabiranja n n množenja 2n n b. Hornerova metoda ima rekurzivnu definiciju: p(x) = q(x) * x + a c. U Hornerovoj metodi nije potrebno poznavati indeks i koeficijenata (primena: izračunavanje vrednosti broja sa osnovom k) 13