programski jazik

Upload: dule-stavrov

Post on 09-Apr-2018

293 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/8/2019 Programski jazik

    1/226

    Programiranje 2Programski jezik C

    Zadaci sa vezbi

    Milena Vujosevic - Janicic 2008/2009

  • 8/8/2019 Programski jazik

    2/226

    Predgovor

    Ovo je prateci materijal za vezbe koje drzim iz predmenta Programiranje 2. On nemoze zameniti pohadanje vezbi niti koriscenje druge preporucene literature.

    Deo materijala cine zadaci i resenja mr Filipa Marica (raspolozivi nawww.matf.bg.ac.yu/~filip/pp/0405/index.pl).Takode koriscen je i materijal sa sajta koleginice Jelene Grmusewww.matf.bg.ac.yu/~jelenagrkolege Miroslava Marica

    www.matf.bg.ac.yu/~maricmi kolege Milana Bankovicawww.matf.bg.ac.yu/~milan.Tekstovi i objasnjenja su uglavnom zasnovani na knjizi Programski jezik C, autoraKerninghan & Ritchie.

    Zahvaljujem svojim studentima na aktivnom ucescu u nastavi cime su mi pomogliu uoblicavanju ovog materijala.

    Svi komentari i sugestije vezane za ovaj materijal bice veoma dobrodosli.

    Milena Vujosevic-Janicicwww.matf.bg.ac.yu/~milena

    1

    http://www.matf.bg.ac.yu/~filip/pp/0405/index.plhttp://www.matf.bg.ac.yu/~filip/pp/0405/index.plhttp://www.matf.bg.ac.yu/~filip/pp/0405/index.plhttp://www.matf.bg.ac.yu/~jelenagrhttp://www.matf.bg.ac.yu/~jelenagrhttp://www.matf.bg.ac.yu/~jelenagrhttp://www.matf.bg.ac.yu/~maricmhttp://www.matf.bg.ac.yu/~maricmhttp://www.matf.bg.ac.yu/~maricmhttp://www.matf.bg.ac.yu/~milanhttp://www.matf.bg.ac.yu/~milanhttp://www.matf.bg.ac.yu/~milanhttp://www.matf.bg.ac.yu/~milenahttp://www.matf.bg.ac.yu/~milenahttp://www.matf.bg.ac.yu/~milenahttp://www.matf.bg.ac.yu/~milenahttp://www.matf.bg.ac.yu/~milanhttp://www.matf.bg.ac.yu/~maricmhttp://www.matf.bg.ac.yu/~jelenagrhttp://www.matf.bg.ac.yu/~filip/pp/0405/index.pl
  • 8/8/2019 Programski jazik

    3/226

  • 8/8/2019 Programski jazik

    4/226

    SADRZAJ SADRZAJ

    9 Dinamicka alokacija memorije 999.1 Matrice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1059.2 Realokacija memorije . . . . . . . . . . . . . . . . . . . . . . . . . . . 114

    10 Liste 11810.1 Implementacija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118

    10.2 Kruzna (ciklicna) lista . . . . . . . . . . . . . . . . . . . . . . . . . . 14310.3 Red . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14410.4 Stek . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15110.5 Dvostruko povezane liste . . . . . . . . . . . . . . . . . . . . . . . . . 160

    11 Stabla 16611.1 Binarno pretrazivacko stablo . . . . . . . . . . . . . . . . . . . . . . . 167

    12 Grafovi 209

    3

  • 8/8/2019 Programski jazik

    5/226

    Glava 1

    Argumenti komandne linije

    Primer 1.1 Argumenti komandne linije programa.

    /* Program pozivati sa npr.:a.outa.out prvia.out prvi drugi trecia.out -a -bc ime.txt

    */

    #include

    /* Imena ovih promenljivih mogu biti proizvoljna.Npr:

    main (int br_argumenata, char** argumenti);ipak, uobicajeno je da se koriste sledeca imena:

    main(int argc, char** argv)Cesto se koristi i sledeca (ekvivalentna) notacija main(int argc, char* argv[])

    */

    main(int argc, char* argv[]){

    int i;printf("argc = %d\n", argc);

    /* Nulti argument uvek je ime programa (a.out)*/

    for (i = 0; i

  • 8/8/2019 Programski jazik

    6/226

    Milena VujosevicJanicic Argumenti komandne linije

    iza jednog znaka - sledi i nekoliko opcija.Npr. zaa.out -abc -d -fg dat.txt -vxysu prisutne opcije a b c d f g */

    #include

    main(int argc, char** argv){

    /* Za svaki argument komande linije, pocevsi od argv[1](preskacemo ime programa) */int i;for (i = 1; i < argc; i++){/* Ukoliko i-ti argument pocinje crticom */if (argv[i][0] == -){

    /* Ispisujemo sva njegova slova pocevsi od pozicije 1 */

    int j;for (j = 1; argv[i][j] != \0; j++)printf("Prisutna je opcija : %c\n", argv[i][j]);

    }/* Ukoliko ne pocinje crticom, prekidamo */else

    break;}

    }Izlaz:Prisutna opcija : a

    Prisutna opcija : bPrisutna opcija : cPrisutna opcija : dPrisutna opcija : fPrisutna opcija : g

    Primer 1.3 Program ispisuje opcije navedene u komandnoj liniji. K&R resenje.

    #include

    /* Resnje se intenzivno zasniva na pokazivackoj aritmeticii prioritetu operatora */

    main(int argc, char** argv){

    char c;/* Dok jos ima argumenata i dok je karakter na poziciji

    0 upravo crtica */while(--argc>0 && (*++argv)[0]==-)

    5

  • 8/8/2019 Programski jazik

    7/226

    Milena VujosevicJanicic Argumenti komandne linije

    /* Dok god ne dodjemo do kraja tekuceg stringa */while (c=*++argv[0])

    printf("Prisutna opcija : %c\n",c);}

    6

  • 8/8/2019 Programski jazik

    8/226

    Glava 2

    Datoteke

    Primer 2.1 Program demonstrira otvaranje datoteka ("r" - read i"w" - write mod)i osnovne tehnike rada sa datotekama.

    /* U datoteku se upisuje prvih 10 prirodnihbrojeva, a zatim se iz iste datotekecitaju brojevi dok se ne stigne do kraja iispisuju se na standardni izlaz */

    #include #include

    main(){int i;

    /* Otvaramo datoteku sa imenom podaci.txt za pisanje */FILE* f = fopen("podaci.txt", "w");

    /* Ukoliko otvaranje nije uspelo, fopen vraca NULL.U tom slucaju, prijavljujemo gresku i zavrsavamo program */

    if (f == NULL){

    printf("Greska prilikom otvaranja datoteke podaci.txt za pisanje\n");exit(1);

    }

    /* Upisujemo u datoteku prvih 10 prirodnih brojeva(svaki u posebnom redu) */for (i = 0; i

  • 8/8/2019 Programski jazik

    9/226

    Milena VujosevicJanicic Datoteke

    fclose(f);

    /* Otvaramo datoteku sa imenom podaci.txt za citanje */f = fopen("podaci.txt", "r");

    /* Ukoliko otvaranje nije uspelo, fopen vraca NULL.

    U tom slucaju, prijavljujemo gresku i zavrsavamo program */if (f == NULL) {

    printf("Greska prilikom otvaranja datoteke podaci.txt za citanje\n");exit(1);

    }

    /* Citamo brojeve iz datoteke dok ne stignemo do kraja i ispisujemo ihna standardni izlaz */

    while(1) {int br;/* Pokusavamo da procitamo broj */

    fscanf(f, "%d", &br);

    /* Ukoliko smo dosli do kraja datoteke, prekidamo */if (feof(f))

    break;

    /* Ispisujemo procitani broj */printf("Procitano : %d\n", br);

    }

    /* Funkciju feof ne treba pozivati pre pokusaja citanja.

    Sledeci kod moze dovesti do greske:while (!feof(f))

    fscanf(f,"%d",&br);*/

    /* Zatvaramo datoteku */fclose(f);}

    Pokazivaci stdin, stdout i stderr su definisani u okviru stdio.h i mogu sekoristiti za pisanje na standardni ulaz, izlaz i izlaz za gresku.

    FILE* stdin;FILE* stdout;FILE* stderr;

    Primer 2.2 Program demonstrira a - append mod datoteka - nadovezivanje.

    #include

    8

  • 8/8/2019 Programski jazik

    10/226

    Milena VujosevicJanicic Datoteke

    #include

    main(){FILE* datoteka;

    /* Otvaramo datoteku za nadovezivanjei proveravamo da li je doslo do greske */

    if ( (datoteka=fopen("dat.txt","a"))==NULL){/*Funkcija fprintf u odnosu na funkciju printf ima

    jedan argument vise --- prvi argument je pokazivacna datoteku u koju treba upisati poruku*/

    fprintf(stderr,"Greska prilikom otvaranja dat.txt\n");

    /*exit je funkcija iz biblioteke stdlib koja omogucavatrenutno zaustavljanje rada programa*/

    exit(1);}

    /* Upisujemo sadrzaj u datoteku */fprintf(datoteka,"Zdravo svima\n");

    /* Zatvaramo datoteku */fclose(datoteka);}

    Primer 2.3 Program kopira sadrzaj datoteke ulaz.txt u datoteku izlaz.txt.

    #include #include

    main(){int c;FILE *in, *out;

    if ((in = fopen("ulaz.txt","r")) == NULL){

    fprintf(stderr, "Neuspesno otvaranje datoteke ulaz.txt\n");

    exit(1);}

    if ((out = fopen("izlaz.txt","w")) == NULL){

    fprintf(stderr, "Neuspesno otvaranje datoteke izlaz.txt\n");

    9

  • 8/8/2019 Programski jazik

    11/226

    Milena VujosevicJanicic Datoteke

    exit(1);}

    /*Funkcija fgetc ucitava iz datoteke jedan karakter.Funkcija fputc upisuje jedan karakter u datoteku. */

    while ((c=fgetc(in)) != EOF)

    fputc(c,out);

    /* Zatvaramo datoteke */fclose(in);fclose(out);}

    Primer 2.4 Program kopiran puta sadrzaj datoteke ulaz.txt u datotekuizlaz.txt.

    #include #include

    main(){int c, n;FILE *in, *out;

    if ((in = fopen("ulaz.txt","r")) == NULL){

    fprintf(stderr, "Neuspesno otvaranje datoteke ulaz.txt\n");exit(1);

    }

    if ((out = fopen("izlaz.txt","w")) == NULL){

    fprintf(stderr, "Neuspesno otvaranje datoteke izlaz.txt\n");exit(1);

    }

    printf("Unesi prirodan broj\n");scanf("%d", &n);

    for(i=0; i

  • 8/8/2019 Programski jazik

    12/226

    Milena VujosevicJanicic Datoteke

    }/* Zatvaramo datoteke */fclose(in);fclose(out);}

    Primer 2.5 Program ilustruje rad sa datotekama. Program kopira datoteku cije seime zadaje kao prvi argument komandne linije u datoteku cije se ime zadaje kaodrugi argument komandne linije. Uz svaku liniju se zapisuje i njen redni broj.

    #include #include

    #define MAX_LINE 256

    /* Funkcija fgets definisana je u stdio.h

    char* fgets(char *s, int n, FILE* stream)

    fgets ucitava najvise sledecih n-1 znakovau polje niza karaktera s, zaustavljajuci seako naidje na novu liniju koju takodjeupisuje u polje. Na kraju upisuje \0.Funkcija vraca s ili NULL ako dodje do krajadatoteke ili se pojavi greska.

    Funkcija fputs definisana je u stdio.h

    int fputs(char *s, FILE *stream)

    fputs upisuje nisku s u datoteku na kojupokazuje stream, vraca nenegativnu vrednost iliEOF ako se pojavi greska

    */

    main(int argc, char* argv[]){

    char line[MAX_LINE];FILE *in, *out;

    int line_num;

    if (argc != 3) {fprintf(stderr,"Neispravna upotreba programa!\n

    Pravilna upotreba:%s ulazna_datoteka izlazna_datoteka\n",argv[0]);

    11

  • 8/8/2019 Programski jazik

    13/226

    Milena VujosevicJanicic Datoteke

    exit(1);}

    if ((in = fopen(argv[1],"r")) == NULL){

    fprintf(stderr, "Neuspesno otvaranje datoteke %s\n", argv[1]);

    exit(1);}

    if ((out = fopen(argv[2],"w")) == NULL){

    fprintf(stderr, "Neuspesno otvaranje datoteke %s\n", argv[2]);exit(1);

    }

    line_num = 1;

    /* Citamo liniju po liniju sa ulaza*/while (fgets(line, MAX_LINE, in) != NULL){

    /* Ispisujemo broj linije i sadrzaj linije na izlaz */fprintf(out, "%d :\t", line_num++);fputs(line, out);

    }

    /* Zatvaramo datoteke */fclose(in);fclose(out);

    }

    Primer 2.6 Prodavnica - ilustruje citanje niza struktura iz tektsualne datoteke.

    /* Datoteka, cije se ime zadaje kao argument komandne linijeili ako se ne zada onda se ime unosi sa standardnogulaza, sadrzi podatke o proizvodima koji se prodajuu okviru odredjene prodavnice. Svakiproizvod se odlikuje sledecim podacima:

    bar-kod - petocifreni pozitivan brojime - niska karakteracena - realan broj zaokruzen na dve decimale

    pdv - stopa poreza - realan broj zaokruzen na dve decimalePretpostavljamo da su podaci u datotecikorektno zadati.Pretpostavljamo da se u prodavnici neprodaje vise od 1000 razlicitih artikalaNa standardni izlaz ispisujemo podatke o

    12

  • 8/8/2019 Programski jazik

    14/226

    Milena VujosevicJanicic Datoteke

    svim proizvodima koji se prodaju u prodavnici.

    Zadatak je moguce resiti i bez koriscenja nizova(i takvo resenje je bolje). */

    #include

    #include

    /* Maksimalna duzina imena proizvoda */#define MAX_IME 30

    /* Maksimalni broj artikala */#define MAX_ARTIKALA 1000

    /* Struktura za cuvanje podataka o jednom artiklu */typedef struct _artikal {

    int bar_kod;

    char ime[MAX_IME];float cena;float pdv;

    } artikal;

    /* Ucitava podatke o jednom artiklu iz date datoteke.Vraca da li su podaci uspesno procitani */

    int ucitaj_artikal(FILE* f, artikal* a){/* Citamo bar kod, ime, cenu, pdv */fscanf(f, "%d%s%f%f", &(a->bar_kod), a->ime, &(a->cena), &(a->pdv));

    /* Ukoliko smo dosli do kraja datoteke prilikom pokusaja ucitavanjaprijavljujemo neuspeh */

    if (feof(f))return 0;

    /* Prijavljujemo uspeh */return 1;}

    /* Izracunava ukupnu cenu datog artikla */

    float cena(artikal a){

    return a.cena*(1+a.pdv);}

    13

  • 8/8/2019 Programski jazik

    15/226

    Milena VujosevicJanicic Datoteke

    /* Ispisuje podatke o svim artiklima */void ispisi_artikle(artikal artikli[], int br_artikala){int i;for (i = 0; i

  • 8/8/2019 Programski jazik

    16/226

    Milena VujosevicJanicic Datoteke

    }

    br_artikala=0;/* Ucitavamo artikle */while (ucitaj_artikal(f, &artikli[br_artikala]))

    br_artikala++;

    /* Ispisujemo podatke o svim artiklima */ispisi_artikle(artikli, br_artikala);

    /* Zatvara se datoteka*/fclose(f);}

    Primer 2.7 Program u datoteku cije se ime zadaje kao prvi argument komandnelinije upisuje prvih N prirodnih brojeva (N se zadaje sa standardnog ulaza) i zatimizracunava duzinu datoteke u bajtovima.

    #include #include

    /*Deklaracija funkcije za racunanje duzine datoteke*/long filesize(FILE *f);

    void main(){

    FILE *f;int i, n;

    /* Ukoliko nije navedeno ime datoteke kaoargument komandne linije, zavrsavamo rad programa*/if (argc

  • 8/8/2019 Programski jazik

    17/226

    Milena VujosevicJanicic Datoteke

    /* Upisuje se sadrzaj u datoteku*/for(i=0; i

  • 8/8/2019 Programski jazik

    18/226

    Milena VujosevicJanicic Datoteke

    komandne linije zamenjuje sva pojavljivanja niske koja se zadaje kao drugi argumentkomandne linije niskom koja se zadaje kao treci argument komandne linije (pret-postaviti da ce obe niske iste duzine i da nisu duze od 20 karaktera). Na primer, akose program pokrene saa.out datoteka.txt ana Anatada se svako pojavljivanje reci ana u datoteci datoteka.txt zamenjuje sa Ana.

    #include #include #include

    int main(int argc, char* argv[]){

    FILE *f;int c;int i;long pos;

    int duzina;char rec1[20];char rec2[20];

    /* Ukoliko nisu navedeni odgovarajuciargumenti program se zavrsava */

    if (argc

  • 8/8/2019 Programski jazik

    19/226

    Milena VujosevicJanicic Datoteke

    pos = ftell(f); /*zapamtimo trenutnu poziciju*/duzina = strlen(rec1);

    /*petlja koja prepoznaje rec*/for(i=1; i

  • 8/8/2019 Programski jazik

    20/226

    Glava 3

    Bitski operatori

    Bitski operatori su operatori koji deluju nad bitovima i vazno je razlikovati ih odlogickih operatora.

    & bitsko AND

    | bitsko OR^ bitsko ekskluzivno OR> desno pomeranje~ jedinicni komplement

    Primer 3.1 Demonstracija bitskih operatora

    #include

    main(){ printf("%o %o\n",255,15);

    printf( "255 & 15 = %d\n", 255 & 15 );printf( "255 | 15 = %d\n", 255 | 15 );printf( "255 ^ 15 = %d\n", 255 ^ 15 );printf( "2 > 2 = %d\n", 16 >> 2 );

    }

    Izlaz iz programa je:377 17255 & 15 = 15255 | 15 = 255

    255 ^ 15 = 2402 > 2 = 4

    Primer 3.2 print bits - stampa bitove u zapisu datog celog broja x.

    #include

    19

  • 8/8/2019 Programski jazik

    21/226

    Milena VujosevicJanicic Bitski operatori

    /* Funkcija stampa bitove datog celog broja x.Vrednost bita na poziciji i je 0 ako isamo ako se pri konjunkciji broja x sa maskom000..010....000 - sve 0 osim 1 na poziciji i,dobija 0.

    Funkcija krece od pozicije najvece tezinekreirajuci masku pomeranjem jedinice u levoza duzina(x) - 1 mesto, i zatim pomerajuciovu masku za jedno mesto u levo u svakojsledecoj iteraciji sve dok maska ne postane 0.

    */

    void print_bits(int x){

    /* Broj bitova tipa unsigned */int wl = sizeof(int)*8;

    unsigned mask;for (mask = 1= 1)

    putchar(x&mask ? 1 : 0);

    putchar(\n);}

    main(){

    print_bits(127);

    print_bits(128);print_bits(0x00FF00FF);print_bits(0xFFFFFFFF);

    }

    Izlaz iz programa:00000000000000000000000001111111000000000000000000000000100000000000000011111111000000001111111111111111111111111111111111111111

    Primer 3.3 Program proverava da li se na k-tom mestu broja n nalazi bit koji imavrednost 1.

    #include

    /* Pozicije brojimo kao u sledecem primeru:p o z : . . . 1 0 9 8 7 6 5 4 3 2 1 0

    20

  • 8/8/2019 Programski jazik

    22/226

    Milena VujosevicJanicic Bitski operatori

    bit: ... 0 0 0 1 1 1 0 0 1 1 0 */

    main(){

    int n,k;printf("Unesite broj i poziciju tog broja koju zelite da proverite:\n");

    scanf("%d%d",&n,&k);if ((n & (1

  • 8/8/2019 Programski jazik

    23/226

    Milena VujosevicJanicic Bitski operatori

    Da li vazi sledeca jednakost (za prirodan broj k):((~0) >> k) == (~0)?Posto je 0 konstanta celobrojnog tipa, to je ~0 takodje tipa int, pri cemu je tobroj koji je zapisan svim jedinicama. Prema tome, njegovim siftovanjem u desnodobijamo isti taj broj, jer se upraznjen prostor sa desne strane popunjava jedinicama.

    VAZNO:

    Vrednost izraza ab je jednaka vrednosti a/2b.Bitovski operatori su efikasniji od operacija * i / tako da svaki put kad se javipotreba za mnozenjem ili deljenjem stepenom broja dva, treba koristiti operacije >.

    Primer 3.5 sum of bits - izracunava sumu bitova datog neoznacenog broja.

    #include

    /* Pomocna funkcija - stampa bitove neoznacenog broja */void print_bits(unsigned x)

    {int wl = sizeof(unsigned)*8;

    unsigned mask;for (mask = 1= 1)

    putchar(x&mask ? 1 : 0);

    putchar(\n);}

    int sum_of_bits(unsigned x)

    {int br;for (br = 0; x; x>>=1)

    if (x&1)br++;

    /* Drugo resenje:int wl = sizeof(unsigned)*8;int br = 0;

    unsigned mask;

    for (mask = 1= 1)if(x&mask) br++ ;

    */return br;

    }

    22

  • 8/8/2019 Programski jazik

    24/226

    Milena VujosevicJanicic Bitski operatori

    main(){

    printf("Binarni zapis broja 127 je\n");print_bits(127);printf("Suma bitova broja 127 je %d\n",sum_of_bits(127));printf("Binarni zapis broja 128 je\n");

    print_bits(128);printf("Suma bitova broja 128 je %d\n",sum_of_bits(128));printf("Binarni zapis broja 0x00FF00FF je\n");print_bits(0x00FF00FF);printf("Suma bitova broja 0x00FF00FF je %d\n",sum_of_bits(0x00FF00FF));printf("Binarni zapis broja 0xFFFFFFFF je\n");print_bits(0xFFFFFFFF);printf("Suma bitova broja 0xFFFFFFFF je %d\n",sum_of_bits(0xFFFFFFFF));

    }

    Izlaz iz programa:

    Binarni zapis broja 127 je00000000000000000000000001111111Suma bitova broja 127 je 7Binarni zapis broja 128 je00000000000000000000000010000000Suma bitova broja 128 je 1Binarni zapis broja 0x00FF00FF je00000000111111110000000011111111Suma bitova broja 0x00FF00FF je 16Binarni zapis broja 0xFFFFFFFF je11111111111111111111111111111111

    Suma bitova broja 0xFFFFFFFF je 32

    Primer 3.6 get_bits, set_bits, invert_bits - izdvajanje, postavljanje i inver-tovanje pojedinacnih bitova.

    #include

    /* Pomocna funkcija - stampa bitove neoznacenog broja */void print_bits(unsigned x){

    int wl = sizeof(unsigned)*8;

    unsigned mask;for (mask = 1= 1)

    putchar(x&mask ? 1 : 0);

    putchar(\n);}

    23

  • 8/8/2019 Programski jazik

    25/226

    Milena VujosevicJanicic Bitski operatori

    /* Funkcija vraca n bitova broja x koji pocinju na poziciji p */unsigned get_bits(unsigned x, int p, int n){

    /* Gradimo masku koja ima poslednjih n jedinica0000000...00011111

    tako sto sve jedinice ~0 pomerimo u levo za n mesta1111111...1100000

    a zatim komplementiramo*/unsigned last_n_1 = ~(~0 > p+1-n) & last_n_1;}

    /* Funkcija vraca modifikovano x tako sto mu je izmenjeno n bitovapocevsi od pozicije p i na ta mesta je upisano poslednjih n bitovabroja y */

    unsigned set_bits(unsigned x, int p, int n, unsigned y){

    /* Maska 000000...000111111 - poslednjih n jedinica */unsigned last_n_1 = ~(~0

  • 8/8/2019 Programski jazik

    26/226

    Milena VujosevicJanicic Bitski operatori

    unsigned middle_n_1 = ~(~0

  • 8/8/2019 Programski jazik

    27/226

    Milena VujosevicJanicic Bitski operatori

    {/* Poslednji bit broja x */unsigned last_bit = x & 1;

    /* x pomeramo za jedno mesto u desno */x >>= 1;

    /* Zapamceni poslednji bit stavljamo na pocetak broja x*/

    x |= last_bit

  • 8/8/2019 Programski jazik

    28/226

    Milena VujosevicJanicic Bitski operatori

    print_bits(mirror(x));print_bits(right_rotate(x, 2));

    }

    Izlaz iz programa:11111010111100001111101011110000

    0000111101011111000011110101111100111110101111000011111010111100

    Primer 3.8 Promeljiva c je tipa char. Sta ce biti vrednost promenljive c posle izrazadodele

    c=(15|3)>>1;?

    c=(15 & 3)

  • 8/8/2019 Programski jazik

    29/226

    Milena VujosevicJanicic Bitski operatori

    rezultat |= mask_i;/* Ako je na j-tom mestu 0, upisujemo

    to na i-to mesto*/else

    rezultat &= ~mask_i;

    return rezultat;}

    int main(int argc, char** argv){unsigned n, i, j, m;if(argc < 3){

    fprintf(stderr, "Neispravna upotreba programa!\n");exit(1);

    }

    printf("Unesi broj\n");scanf("%u", &n);

    /* Racunaju se brojevi na osnovu argumenatakomandne linije.

    */i = atoi(argv[1]);j = atoi(argv[2]);

    m = razmeni(n, i, j);

    printf("Broj nastao razmenom bitova (%u, %u) broja %u je %u\n",i, j, n, m);

    return 0;}

    Primer 3.10 Napisati funkciju koja prima ceo brojn i ispisuje razliku broja jedinicana parnim i neparnim pozicijama u binarnom zapisu broja n.

    PRIMER: za n = 19 = (10011)2 izlaz je 1.Napisati program koji pozivom ove funkcije racuna i stampa razliku broja jedinica

    za sve argumente komandne linije (pretpostavka je da su argumenti komandne linije

    zadati korektno).#include #include

    int par_nepar(int n){

    28

  • 8/8/2019 Programski jazik

    30/226

    Milena VujosevicJanicic Bitski operatori

    int br1_par = 0; /* int rezultat=0;*/int br1_nepar = 0;

    /* Broj bitova tipa unsigned */int wl = sizeof(int)*8;unsigned mask=1;

    char par = 1;for( ; mask; mask

  • 8/8/2019 Programski jazik

    31/226

    Glava 4

    Vezbanje

    4.1 Polinomi

    Primer 4.1 Program ilustruje rad sa polinomima.

    #include #include #define max(a, b) ((a) > (b) ? (a) : (b))

    /** Polinom 3*x^3 + 2*x + 1.5 se predstavlja kao:* stepen -> 3* koeficijenti -> 1.5 2 0 3 x x x x x ... x*/typedef struct polinom{

    float koeficijenti[21];int stepen;} Polinom;

    /** Funkcija vraca koeficijent uz x^i u polinomu p* Zbog efikasnosti ne prenosimo celu strukturu vec* samo pokazivac na strukturu.*/float vratiKoeficijent(Polinom* p, int i){

    return i stepen ? p->koeficijenti[i] : 0.0f;}

    /** Funkcija postavlja koeficijent uz x^i u polinomu p na* dati koeficijent k

    30

  • 8/8/2019 Programski jazik

    32/226

    Milena VujosevicJanicic 4.1 Polinomi

    */void postaviKoeficijent(Polinom* p, int i, float k){

    int j;

    /*

    Ukoliko je stepen polinoma bio manji, postavljamosve koeficijente izmedju na 0.0 i uvecavamo stepen*/if (i > p->stepen){

    for (j = p->stepen+1; j < i; j++)p->koeficijenti[j] = 0.0f;

    p->stepen = i;}p->koeficijenti[i] = k;

    }

    /** Funkcija kreira polinom datog stepena sa datim nizom* koeficijenata. Pretpostavlja se da su koeficijenti* u datom nizu koeficijenti[] uredjeni opadajuce po stepenima* polinoma.*/Polinom napraviPolinom(int stepen, float koeficijenti[]){

    int i;Polinom p;

    p.stepen = stepen;for (i = 0; i stepen; i >= 0; i--)

    31

  • 8/8/2019 Programski jazik

    33/226

    Milena VujosevicJanicic 4.1 Polinomi

    {printf("%.2f*x^%d", vratiKoeficijent(p, i), i);if (i > 0)

    printf(" + ");}printf("\n");

    }

    /** Funkcija izracunava vrednost polinoma u tacki x* Hornerovom shemom. Na primer,* 3*x^3 + 2*x + 1.5 =* (((0*x + 3)*x + 0)*x + 2)*x + 1.5* Postupak izracunavanja p(10):* 0.0* 1 0 * 0 . 0 + 3 = 3 . 0* 10 * 3.0 + 0 = 30.0

    * 10 * 30.0 + 2 = 302.0* 10 * 302.0 + 1.5 = 3021.5*/float vrednost(Polinom* p, float x){

    int i;float suma = 0.0f;for (i = p->stepen; i >= 0; i--){

    suma = suma*x + vratiKoeficijent(p, i);}

    return suma;}

    /** Funkcija sabira dva polinoma*/Polinom saberi(Polinom* p, Polinom* q){

    int i;Polinom zbir;zbir.stepen = max(p->stepen, q->stepen);

    for (i = 0; i

  • 8/8/2019 Programski jazik

    34/226

    Milena VujosevicJanicic 4.1 Polinomi

    }

    /** Funkcija mnozi dva polinoma. Na primer,** 1*x^2 + 2*x + 3

    * 4 * x + 7** 0.0*x^3 + 0.0*x^2 + 0.0*x + 0.0* 0.0*x^3 + 0.0*x^2 + 0.0*x + 21.0 i=0 j=0* 0.0*x^3 + 0.0*x^2 + 12.0*x + 21.0 i=0 j=1* 0.0*x^3 + 0.0*x^2 + 26.0*x + 21.0 i=1 j=0* 0.0*x^3 + 8.0*x^2 + 26.0*x + 21.0 i=1 j=1* 0.0*x^3 + 15.0*x^2 + 26.0*x + 21.0 i=2 j=0* 4.0*x^3 + 15.0*x^2 + 26.0*x + 21.0 i=2 j=1*/Polinom pomnozi(Polinom* p, Polinom* q)

    {int i, j;Polinom proizvod;proizvod.stepen = p->stepen + q->stepen;for (i = 0; i

  • 8/8/2019 Programski jazik

    35/226

    Milena VujosevicJanicic 4.2 Veliki brojevi

    ispisiPolinom(&r);}

    4.2 Veliki brojevi

    Primer 4.2 Program ilustruje rad sa velikim celim brojevima. Brojevi se internoreprezentuju preko niza svojih cifara.

    #include #include #include #define MAX_CIFRE 100

    /* Funkcija obrce cifre prosledjenog niza */void obrni_cifre (int cifre[], int duzina){

    int i, j;

    for (i=0, j=duzina-1; i0 && isdigit(c=getchar()))

    cifre[duzina++]=c-0;obrni_cifre(cifre, duzina);return duzina;

    }

    /* Funkcija ispisuje "veliki" broj predstavljennizom cifara cifre, duzine duzina, na standardniizlaz imajuci u vidu da su cifre u nizu zapisane"naopako" tj. pocevsi od cifre najmanje tezine */void ispisi_broj(int cifre[],int duzina)

    34

  • 8/8/2019 Programski jazik

    36/226

    Milena VujosevicJanicic 4.2 Veliki brojevi

    {int i;for (i=duzina-1; i>=0; i--)

    printf("%d",cifre[i]);putchar(\n);

    }

    /* Da li su dva broja data svojim nizovima cifara i duzinama jednaka?Funkcija vraca 1 ako jesu, a 0 ako nisu */int jednaki(int a[], int duzina_a, int b[], int duzina_b){

    int i;/* Poredimo duzine */if (duzina_a != duzina_b)

    return 0;

    /* Ako su brojevi iste duzine, poredimo cifru po cifru*/

    for (i=0; ib0 ako je a=b

    -1 ako je b>a*/int uporedi(int a[], int duzina_a, int b[], int duzina_b){

    int i;/* Uporedjujemo duzine brojeva a i b */if (duzina_a > duzina_b)

    return 1;if (duzina_a < duzina_b)

    return -1;/* U ovom trenutku znamo da su brojevi iste duzine, tako da

    prelazimo na poredjenje cifre po cifre, pocevsi od cifrenajvece tezine */for (i=duzina_a-1; i>=0; i--){

    if (a[i] > b[i])

    35

  • 8/8/2019 Programski jazik

    37/226

    Milena VujosevicJanicic 4.2 Veliki brojevi

    return 1;if (a[i] < b[i])

    return -1;}return 0;

    }

    /* Funkcija sabira dva broja data svojim nizovima cifarai duzinama */

    void saberi(int a[], int duzina_a, int b[], int duzina_b,int rezultat[],int* duzina_rezultata)

    {int i;

    /* Prenos sa prethodne pozicije */int prenos = 0;

    /* Sabiranje vrsimo dok ne prodjemo sve cifre duzeg od brojeva a i b */for(i=0; i

  • 8/8/2019 Programski jazik

    38/226

    Milena VujosevicJanicic 4.2 Veliki brojevi

    rezultat[i] = prenos;*duzina_rezultata = i+1;

    }}else

    *duzina_rezultata=i;

    return;}

    /* Funkcija mnozi broj, dat svojim nizom cifara i duzinom, datom cifrom c */void pomnozi_cifrom (int a[], int duzina_a, int cifra,

    int rezultat[],int* duzina_rezultata)

    {int i, prenos = 0;

    for (i=0; i=MAX_CIFRE){printf("Doslo je do prekoracenja !\n"); exit(1);}

    else{

    rezultat[i] = prenos;*duzina_rezultata = duzina_a+1;

    }}else

    37

  • 8/8/2019 Programski jazik

    39/226

    Milena VujosevicJanicic 4.2 Veliki brojevi

    *duzina_rezultata = duzina_a;}

    /* Funkcija mnozi dva broja data svojim nizovima cifara i duzinama*/void pomnozi (int a[], int duzina_a, int b[], int duzina_b,

    int rezultat[],

    int* duzina_rezultata){

    /* Ova funkcija se gradi kombinovanjem algoritama mnozenja broja cifrom isabiranja dva broja */int i,j,k;

    /* Broj pom ce da sadrzi rezultat mnozenja broja a jednom po jednomcifrom broja b, dok ce na broj rezultat da se dodaje svakiput (10^i)*pom */int pom[MAX_CIFRE], duzina_pom, prenos;

    *duzina_rezultata = 0;

    /*b=351 * a=123---------------

    1 korak ===> rez: 351 * 3 = 10532 korak ===> 351 * 2 = 702

    ------------------rez: 8073

    3 korak ===> 351 * 1 = 351------------------

    rez: 43173*/

    /* Za svaku cifru broja a */for (i=0; i

  • 8/8/2019 Programski jazik

    40/226

    Milena VujosevicJanicic 4.2 Veliki brojevi

    }if (prenos){

    rezultat[i+k] = prenos;*duzina_rezultata = i+k+1;

    }

    else*duzina_rezultata = i+k;

    }}

    /* Primer koriscenja funkcija */main(){

    /* duzina brojeva a i b */int duzina_a, duzina_b;

    /* nizovi cifara brojeva a i b */int a[MAX_CIFRE], b[MAX_CIFRE], zbir[MAX_CIFRE], proizvod[MAX_CIFRE];

    /* Ucitavaju se brojevi */printf("Unesite prvi broj : ");duzina_a = uzmi_broj(a,MAX_CIFRE);

    printf("Unesite drugi broj : ");duzina_b = uzmi_broj(b, MAX_CIFRE);

    /* Sabiraju se i ispisuje se zbir */

    saberi(a, duzina_a, b, duzina_b, zbir, &duzina_zbira);printf("Zbir je : ");ispisi_broj(zbir, duzina_zbira);

    /* Mnoze se i ispisuje se proizvod */pomnozi(a, duzina_a, b, duzina_b, proizvod, &duzina_proizvoda);printf("Proizvod je : ");ispisi_broj(proizvod, duzina_proizvoda);

    }

    39

  • 8/8/2019 Programski jazik

    41/226

    Glava 5

    Sortiranje

    Niz moze biti sortiran ili uredjen u

    opadajucem poretku:

    niz[0] > niz[1] > ... > niz[i] > niz[i + 1] > ... > niz[n 1]

    rastucem poretku:

    niz[0] < niz[1] < ... < niz[i] < niz[i + 1] < ... < niz[n 1]

    neopadajucem poretku:

    niz[0] niz[1] ... niz[i] niz[i + 1] ... niz[n 1]

    nerastucem poretku:

    niz[0] niz[1] ... niz[i] niz[i + 1] ... niz[n 1]

    U nastavku su dati primeri algoritama za sortiranje u nerastucem poretku celobro- jnog niza. Jednostavnim modifikacijama svakim od ovih algoritama niz se mozesortirati i u opadajucem, rastucem ili neopadajucem poretku.

    5.1 Vremenska slozenost

    Pogledati slike koje oslikavaju vremensku slozenost za razlicite algoritme i razlicitenizove:

    Rezultati dobijeni za slucajno generisane nizove:

    http://www.matf.bg.ac.yu/ ~filip/pp/0405/random-sort.gif

    Rezultati dobijeni za vec sortirane nizove:http://www.matf.bg.ac.yu/ ~filip/pp/0405/sorted-sort.gif

    Rezultati dobijeni za naopako sortirane nizove:http://www.matf.bg.ac.yu/ ~filip/pp/0405/reverse-sorted-sort.gif

    40

    http://www.matf.bg.ac.yu/~filip/pp/0405/random-sort.gifhttp://www.matf.bg.ac.yu/~filip/pp/0405/random-sort.gifhttp://www.matf.bg.ac.yu/~filip/pp/0405/random-sort.gifhttp://www.matf.bg.ac.yu/~filip/pp/0405/sorted-sort.gifhttp://www.matf.bg.ac.yu/~filip/pp/0405/sorted-sort.gifhttp://www.matf.bg.ac.yu/~filip/pp/0405/sorted-sort.gifhttp://www.matf.bg.ac.yu/~filip/pp/0405/reverse-sorted-sort.gifhttp://www.matf.bg.ac.yu/~filip/pp/0405/reverse-sorted-sort.gifhttp://www.matf.bg.ac.yu/~filip/pp/0405/reverse-sorted-sort.gifhttp://www.matf.bg.ac.yu/~filip/pp/0405/reverse-sorted-sort.gifhttp://www.matf.bg.ac.yu/~filip/pp/0405/sorted-sort.gifhttp://www.matf.bg.ac.yu/~filip/pp/0405/random-sort.gif
  • 8/8/2019 Programski jazik

    42/226

    Milena VujosevicJanicic 5.2 Selection sort

    5.2 Selection sort

    Primer 5.1 (Selection sort) U prvom prolazu se razmenjuju vrednosti a[0] saonim clanovima ostatka niza koji su veci od njega. Na taj nacin ce se posle prvogprolaza kroz niza[0] postaviti na najveci element niza. U svakom sledecem prolazu,postavlja se na i-to mesto najveci element niza a[i], a[i+1] ... a[n-1].

    Primer sortiranja:

    n = 6 a: 1 3 5 2 6 8-------------i = 0 j = 1 => a: 3 1 5 2 6 8i = 0 j = 2 => a: 5 1 3 2 6 8i = 0 j = 3 => a: 5 1 3 2 6 8i = 0 j = 4 => a: 6 1 3 2 5 8i = 0 j = 5 => a: 8 1 3 2 5 6-------------i = 1 j = 2 => a: 8 3 1 2 5 6i = 1 j = 3 => a: 8 3 1 2 5 6i = 1 j = 4 => a: 8 5 1 2 3 6i = 1 j = 5 => a: 8 6 1 2 3 5...

    #include#include

    #define MAXDUZ 100

    void selection(int a[], int n){

    /* pomocna i brojacke promenljive */int pom,i,j;

    /*Sortiranje*/for(i=0; i

  • 8/8/2019 Programski jazik

    43/226

    Milena VujosevicJanicic 5.2 Selection sort

    int a[MAXDUZ];

    /* Dimenzija niza, pomocna i brojacke promenljive */int n,i;

    printf("Unesite dimenziju niza\n");

    scanf("%d",&n);

    if (n>MAXDUZ){

    printf("Nedozvoljena vrednost za n\n");exit(1);

    }

    /* Unos clanova niza */for(i=0; i a: 8 6 5 2 1 3-------------i = 2 => a: 8 6 5 2 1 3-------------

    42

  • 8/8/2019 Programski jazik

    44/226

    Milena VujosevicJanicic 5.3 Bubble sort

    ...

    void selection2(int a[], int n){

    int i, j, max;

    /*Sortiranje - bez stalnih zamena vec sepronalazi indeks trenutno najveceg clana niza*/for(i=0; i a: 3 5 2 1 6 8i = 5 j = 3 => a: 3 5 2 6 1 8i = 5 j = 4 => a: 3 5 2 6 8 1-------------

    43

  • 8/8/2019 Programski jazik

    45/226

    Milena VujosevicJanicic 5.3 Bubble sort

    i = 4 j = 0 => a: 5 3 2 6 8 1...

    void bubble(int a[], int n){

    int i, j, pom;

    for(i=n-1; i>0; i--)for(j=0; j

  • 8/8/2019 Programski jazik

    46/226

    Milena VujosevicJanicic 5.4 Insertion sort

    }

    5.4 Insertion sort

    Primer 5.5 (Insertion sort) U svakom trenutku je pocetak niza sortiran, a sorti-

    ranje se vrsi tako sto se jedan po jedan element niza sa kraja ubacuje na odgovarajucemesto.Primer sortiranja:

    n = 6 a: 1 3 5 2 6 8-------------i = 1 j = 1 => a: 3 1 5 2 6 8-------------i = 2 j = 2 => a: 3 5 1 2 6 8i = 2 j = 1 => a: 5 3 1 2 6 8-------------i = 3 j = 3 => a: 5 3 2 1 6 8

    -------------i = 4 j = 4 => a: 5 3 2 6 1 8...

    void insertion(int a[], int n){

    /* Pomocna i brojacke promenljive */int pom,i,j;

    for(i=1; i0) && (a[j]>a[j-1]); j--)

    {pom=a[j];a[j]=a[j-1];a[j-1]=pom;

    }}

    Primer 5.6 (Insertion sort 2) Broj dodela se moze redukovati tako sto se umestostalnih zamena koristi dodela privremenoj promenljivoj elemente niza pomeramoza jedno mesto sve dok ne nademo poziciju na koju treba da postavimo dati element(koji je sacuvan u privremenoj promenljivoj).

    void insertion2(int a[], int n){

    int i, j, tmp;for (i = 1; i < n; i++){

    int tmp = a[i];

    45

  • 8/8/2019 Programski jazik

    47/226

    Milena VujosevicJanicic 5.5 Razni zadaci

    for (j = i; j > 0 && a[j-1] < tmp; j--){a[j] = a[j-1];

    }a[j] = tmp;

    }}

    5.5 Razni zadaci

    Primer 5.7 Napisati funkciju koja od dva sortirana niza formira treci sortiran niz(nizovi su sortirani neopadajucie).

    #include

    /* Funkcija spaja dva uredjena niza:a koji ima na elemenata ib koji ima nb elemenata

    i na osnovu njih gradi uredjeni niz c cijibroj elemenata vraca.Pretpostavlja se da u nizu c ima dovoljno prostora.

    */int merge(int a[], int na, int b[], int nb, int c[]){

    /* Dok god ima elemenata u oba niza uzima se manji od dva tekuca i prepisuje u niz c */

    i n t i = 0 , j = 0 , k = 0 ;while(i < na && j < nb){

    if (a[i] < b[j])c[k++] = a[i++];

    elsec[k++] = b[j++];

    }

    /* Prepisujemo eventualno preostale elemente niza a */for (; i < na; i++, k++)

    c[k] = a[i];

    /* Prepisujemo eventualno preostale elemente niza b */

    for (; j < nb; j++, k++)c[k] = b[j];

    return k;}

    46

  • 8/8/2019 Programski jazik

    48/226

  • 8/8/2019 Programski jazik

    49/226

    Milena VujosevicJanicic 5.5 Razni zadaci

    else return i;

    }

    /* Funkcija ucitava niz studenata, vraca duzinu niza koji ucita */int UcitajPodatke(student studenti[], int max)

    {int i=0;while(i0){

    if (getword(studenti[i].prezime, MAX_IME) < 0)break;

    scanf("%d",&studenti[i].ocena);i++;

    }return i;}

    void IspisiPodatke(student studenti[], int br_studenata){int i;printf("IME PREZIME OCENA\n");printf("--------------------------------------\n");for (i=0; i

  • 8/8/2019 Programski jazik

    50/226

    Milena VujosevicJanicic 5.5 Razni zadaci

    int br_studenata = UcitajPodatke(studenti,100);

    SelectionSort(studenti, br_studenata);IspisiPodatke(studenti, br_studenata);

    }

    Primer 5.9 Program ucitava informacije o studentima iz datoteke cije se ime zadajeiz komandne linije, i koja je u formatu:

    nprezime1 ime1 smer1 prosek1prezime2 ime2 smer2 prosek2...prezimen imen smern prosekn

    Studenti se sortiraju leksikografski po prezimenima i imenima, a zatim se njihovipodaci tako sortirani ispisuju na izlaz, ili u izlazni fajl, ako je njegovo ime zadato ukomandnoj liniji.

    #include #include

    #define MAX_IME 20#define MAX_PREZIME 30#define MAX_SMER 10

    #define MAX_STUDENATA 100

    /* Struktura koja predstavlja informacije o studentu */typedef struct student {

    char ime[MAX_IME];char prezime[MAX_PREZIME];char smer[MAX_SMER];double prosek;

    } Student;

    /* Funkcija uporedjuje dva studenta po leksikografskom poretkunjihovih imena i prezimena. Funkcija vraca vrednost manju od

    nule ako je prvi student "manji" od drugog, vrednost vecuod nule ako je prvi student "veci" od drugog, dok nulu vracaako se studenti zovu isto. */

    int uporedi(Student *s, Student *p){

    int t;

    49

  • 8/8/2019 Programski jazik

    51/226

  • 8/8/2019 Programski jazik

    52/226

    Milena VujosevicJanicic 5.5 Razni zadaci

    fscanf(in, "%lf", &s->prosek);}

    /* Ispisujemo informacije o studentu */void ispisi(FILE *out, Student *s){

    fprintf(out, "%s %s %s %f\n", s->prezime, s->ime, s->smer, s->prosek);}

    /* Funkcija main */int main (int argc, char ** argv){

    int n, i;FILE *in = stdin, *out = stdout;Student studenti[MAX_STUDENATA];

    /* Ako je korisnik uneo ime ulaznog fajla...*/if(argc > 1)

    if((in = fopen(argv[1], "r")) == NULL){

    fprintf(stderr, "Greska prilikom otvaranja fajla!\n");return 1;

    }

    /* Ako je korisnik uneo i ime izlaznog fajla...*/if(argc > 2)

    if((out = fopen(argv[2], "w")) == NULL)

    {fprintf(stderr, "Greska prilikom otvaranja fajla!\n");return 1;

    }

    /* Ucitavamo broj studenata */fscanf(in, "%d", &n);

    /* Ucitavamo informacije o studentima */for(i = 0; i < n; i++)

    ucitaj(in, &studenti[i]);

    /* Sortiramo niz studenata */sortiraj(studenti, n);

    /* Ispisujemo niz studenata */

    51

  • 8/8/2019 Programski jazik

    53/226

    Milena VujosevicJanicic 5.5 Razni zadaci

    for(i = 0; i < n; i++)ispisi(out, &studenti[i]);

    fclose(in);fclose(out);

    return 0;}

    Primer 5.10 Program utvrduje da li su dve niske karaktera anagrami. Dve niskesu anagrami ako se sastoje od istog broja istih karaktera. Na primer, niske travei vetar jesu anagrami, dok vetar i vatra nisu.

    #include #include

    #define MAX 1024

    /* Funkcija sortira karaktere stringa s */void sortiraj (char s[]){

    int i, j;int min;char pom;int n;

    /* Racunamo duzinu stringa */for (n = 0; s[n] != \0; n++)

    ;

    /* Ostatak funkcije je identican funkcijiza sortiranje celih brojeva. */

    for (i = 0; i < n - 1; i++){

    min = i;for (j = i + 1; j < n; j++)

    if (s[j] < s[min]) min = j;

    if (min != i)

    {pom = s[i];s[i] = s[min];s[min] = pom;}

    }

    52

  • 8/8/2019 Programski jazik

    54/226

    Milena VujosevicJanicic 5.5 Razni zadaci

    }

    /* Funkcija utvrdjuje da li su reci s i t anagrami.Za reci kazemo da su anagrami, ako se jedna rec

    moze dobiti od druge premestanjem slova u reci */int anagrami (char *s, char *t)

    {char sp[MAX];char tp[MAX];

    /* Kopiramo stringove (reci) u pomocne nizove sp i tpzato sto ne zelimo da nasa funkcija promeni originalnenizove. */

    strcpy (sp, s);strcpy (tp, t);

    /* Sortiramo karaktere stringova u pomocnim nizovima */

    sortiraj (sp);sortiraj (tp);

    /* Ako su stringovi nakon sortiranja jednaki, tada su polazne recibile anagrami */

    return strcmp (sp, tp) == 0;}

    /* Test program */int main ()

    {

    char s[MAX], t[MAX];

    /* Ucitavamo dve reci */printf ("Uneti prvu rec: ");scanf ("%s", s);printf ("Uneti drugu rec: ");scanf ("%s", t);

    /* Utvrdjujemo da li su anagrami i ispisujemo poruku */

    if (anagrami (s, t))printf ("Reci %s i %s su anagrami\n", s, t);

    elseprintf ("Reci %s i %s nisu anagrami\n", s, t);

    53

  • 8/8/2019 Programski jazik

    55/226

    Milena VujosevicJanicic 5.5 Razni zadaci

    return 0;}

    Primer 5.11 Interpolaciona pretraga se moze porediti sa pretragom recnika:ako neko trazi rec na slovo B, sigurno nece da otvori recnik na polovini, vec verovatnonegde blize pocetku.

    /* Funkcija trazi u SORTIRANOM nizu a[] duzine nbroj x. Vraca indeks pozicije nadjenog elementaili -1, ako element nije pronadjen */

    int interpolaciona_pretraga (int a[], int n, int x){

    int l = 0;i n t d = n - 1 ;int s;

    /* Dokle god je indeks l levo od indeksa d... */while (l a[d])

    return -1;/* U suprotnom, x je izmedju a[l] i a[d], pa ako su a[l] i a[d]

    jednaki, tada je jasno da je x jednako ovim vrednostima, pa

    vracamo indeks l (ili indeks d, sve jedno je).Ova provera jeneophodna, zato sto bismo inace prilikom izracunavanja s imalideljenje nulom.

    */else if(a[l] == a[d])

    return l;

    /* Indeks s je uvek izmedju l i d, ali ceverovatno biti blize trazenoj vrednosti nego dasmo prosto uvek uzimali srednji element.*/

    /* Racunamo sredisnji indeks */

    s = l + ((double)(x - a[l]) / (a[d] - a[l])) * (d - l);

    /* Ako je sredisnji element veci od x,tada se x mora nalaziti u levoj polovini niza */

    if (x < a[s])d = s - 1;

    54

  • 8/8/2019 Programski jazik

    56/226

    Milena VujosevicJanicic 5.5 Razni zadaci

    /* Ako je sredisnji element manji od x,tada se x mora nalaziti u desnoj polovini niza

    */else if (x > a[s])

    l = s + 1;else

    /* Ako je sredisnji element jednak x,tada smo pronasli x na poziciji s

    */return s;

    }

    /* ako nije pronadjen vracamo -1 */return -1;

    }

    Primer 5.12 Data su dva rastuca niza A i B, napisati funkciju koja formira niz C

    koji sadrzi:(a) zajednicke elemente nizova A i B (presek skupova A i B).

    (b) elemente koje sadrzi niz A a ne sadrzi niz B (razlika skupova A i B).

    (c) sve elemente koje sadrze nizovi A iB (unija skupovaA iB) ovo je ekvivalentnospajanju dva uredena niza primer 5.7.

    /* Funkcija kreira presek dva rastuca niza a i b i rezultat smesta uniz c (takodje u rastucem radosledu). Funkcija vraca broj elemenatapreseka */

    int kreiraj_presek(int a[], int n_a, int b[], int n_b, int c[])

    {i n t i = 0 , j = 0 , k = 0 ;

    /* Dokle god ima elemenata u oba niza... */while (i < n_a && j < n_b)

    {/* Ako su jednaki, ubacujemo vrednost u presek,

    i prelazimo na sledece elemente u oba niza. */if(a[i] == b[j])

    {c[k++] = a[i];

    i++;j++;

    }/* Ako je element niza a manji, tada u tom nizu prelazimo

    na sledeci element */else if(a[i] < b[j])

    55

  • 8/8/2019 Programski jazik

    57/226

    Milena VujosevicJanicic 5.5 Razni zadaci

    i++;/* Ako je element niza b manji, tada u tom nizu prelazimo

    na sledeci element */else

    j++;}

    /* Vracamo broj elemenata preseka */return k;

    }

    /* Funkcija kreira razliku dva rastuca niza a i b i rezultat smesta uniz c (takodje u rastucem radosledu). Funkcija vraca broj elemenatarazlike */

    int kreiraj_razliku (int a[], int n_a, int b[], int n_b, int c[]){

    int i = 0, j = 0 , k = 0;

    /* Sve dok ima elemenata u oba niza...*/while(i < n_a && j < n_b){

    /* Ako je tekuci element niza a manji, tadaje on u razlici, jer su svi sledeci elementiniza b jos veci. Ubacujemo ga u razliku iprelazimo na sledeci element niza a */

    if(a[i] < b[j])c[k++] = a[i++];

    /* Ako je tekuci element niza b manji, tada

    prelazimo na sledeci element u nizu b */else if (a[i] > b[j])

    j++;/* Ako su jednaki, tada ih oba preskacemo. Tekuci

    element niza a ocigledno nije u razlici. */else

    {i++;j++;

    }}

    /* Ako su preostali elementi niza a, tada su oni u razlicijer su svi elementi niza b bili manji od tekuceg elementaniza a, i svih koji za njim slede */

    while (i < n_a)

    56

  • 8/8/2019 Programski jazik

    58/226

    Milena VujosevicJanicic 5.5 Razni zadaci

    c[k++] = a[i++];

    /* Vracamo broj elemenata u razlici */return k;

    }

    57

  • 8/8/2019 Programski jazik

    59/226

    Glava 6

    Pokazivaci

    Pokazivac je promenljiva koja sadrzi adresu promenljive.

    int x=1, y=1;int *ip; /* ip je pokazivac na int, odnosno *ip je tipa int */

    ip = &x; /* ip cuva adresu promenljive x, tj ip pokazuje na x */y=*ip; /* y dobija vrednost onoga sto se nalazi na adresi koju

    cuva promenljiva ip, tj posto ip cuva adresu promenljivex, a x ima vrednost 1 to je i y sada 1 */

    *ip = 0; /* preko pokazivaca njema se sadrzaj na adresi koju cuva ip,prema tome, x je sada 0 */

    *ip+=10; /* x je sada 10*/++*ip; /* x je sada 11*/(*ip)++; /* x je sada 12,

    zagrada neophodna zbog prioriteta operatora*/

    Pored pokazivaca na osnovne tipove, postoji i pokazivac na prazan tip void.

    void *pp;

    Njemu moze da se dodeli da pokazuje na int, char, float ili na bilo koji drugi tipali je neophodno eksplicitno naglasiti na koji tip ukazuje pokazivac svaki put kadazelimo da koristimo sadrzaj adrese koju pokazivac cuva.

    Primer 6.1 Upotreba pokazivaca na prazan tip.

    #include

    main(){void *pp; /* Ovaj pokazivac moze da pokazuje na adrese

    na kojima se nalaze razliciti tipovipodataka. */

    int x=2;

    58

  • 8/8/2019 Programski jazik

    60/226

  • 8/8/2019 Programski jazik

    61/226

    Milena VujosevicJanicic 6.1 Pokazivacka aritmetika primeri

    return (n>=0) ? niz : NULL;}

    main(){

    int a[]={1,2,3,4,5,6,7,8};

    int* poz=nadjiint(a,sizeof(a)/sizeof(int),4);

    if (poz!=NULL)printf("Element pronadjen na poziciji %d\n",poz-a);

    }

    Primer 6.3 Funkcije izracunavaju duzinu niske koriscenjem pokazivaca.

    int string_length1(char *s){

    int n;for(n=0; *s != \0; s++)

    n++;return n;

    }

    /* Druga varijanta iste funkcije */int string_length2(char *s){

    char* t;for (t = s; *t; t++)

    ;return t - s;

    }

    Primer 6.4 Funkcija kopira string t u string s (podrazumeva se da je za string srezervisano dovoljno mesta).

    void copy(char* dest, char* src){while (*dest++=*src++)

    ;}

    /* Ovo je bio skraceni zapis za sledeci kodwhile(*src != \0)

    {*dest=*src;dest++;src++;

    60

  • 8/8/2019 Programski jazik

    62/226

    Milena VujosevicJanicic 6.1 Pokazivacka aritmetika primeri

    }*dest = \0;

    */

    Primer 6.5 Nadovezuje string t na kraj stringa s. Pretpostavlja da u s ima do-voljno prostora.

    void string_concatenate(char *s, char *t){

    /* Pronalazimo kraj stringa s */while (*s) /* while (*s != 0)*/

    s++;/* Nakon prethodne petlje, s pokazuje na \0, kopiranje

    pocinje od tog mesta, tako da ce znak \0 biti prepisan. *//* Kopiranje se vrisi slicno funkciji string_copy */while (*s++ = *t++)

    ;}

    Primer 6.6 Funkcija strcmp vrsi leksikografsko poredenje dva stringa. Vraca:0 ukoliko su stringovi jednaki

    0 ukoliko je s leksikografski iza t

    int strcmp(char *s, char *t){

    /* Petlja tece sve dok ne naidjemona prvi razliciti karakter */

    for (; *s == *t; s++, t++)if (*s == \0) /* Naisli smo na kraj

    oba stringa, a nismo nasli razliku */return 0;

    /* *s i *t su prvi karakteri u kojima se niskerazlikuju. Na osnovu njihovog odnosa,odredjuje se odnos stringova */

    return *s - *t;

    }

    Primer 6.7 Pronalazi prvu poziciju karaktera c u stringu s, i vraca pokazivac nanju, odnosno NULL ukoliko s ne sadrzi c.

    char* string_char(char *s, char c){

    61

  • 8/8/2019 Programski jazik

    63/226

    Milena VujosevicJanicic 6.1 Pokazivacka aritmetika primeri

    int i;for (; *s; s++)

    if (*s == c)return s;

    /* Nije nadjeno */

    return NULL;}

    Primer 6.8 Pronalazi poslednju poziciju karaktera c u stringu s, i vraca pokazivacna nju, odnosno NULL ukoliko s ne sadrzi c.

    char* string_last_char(char *s, char c){

    char *t = s;/* Pronalazimo kraj stringa s */while (*t)

    t++;

    /* Krecemo od kraja i trazimo c unazad */for (t--; t >= s; t--)

    if (*t == c)return t;

    /* Nije nadjeno */return NULL;

    }

    Primer 6.9 Za svaku liniju ucitanu sa ulaza proverava se da li sadrzi rec zdravo.

    #include

    /* Proverava da li se niska t nalazi unutar niske sVraca poziciju na kojoj string pocinje odnosno-1 ukoliko niska t nije podniska niske s. */

    int sadrzi_string(char s[], char t[]){

    int i;for (i = 0; s[i]; i++){

    int j;for (j=0, k=0; s[i+j]==t[j]; j++)

    if (t[j+1]==\0)return i;

    }return -1;

    62

  • 8/8/2019 Programski jazik

    64/226

    Milena VujosevicJanicic 6.1 Pokazivacka aritmetika primeri

    }

    /* Proverava da li string str sadrzi string sub.Vraca pokazivac na kojoj sub pocinje,odnosno NULL ukoliko ga nema. */

    char* string_string(char *str, char *sub)

    {char *s, *t;

    /* Proveravamo da li sub pocinje na svakoj poziciji i */for (; *str; str++)

    /* Poredimo sub sa str pocevsi od pozicije na koju ukazujestr sve dok ne naidjemo na razliku */

    for (s = str, t = sub; *s == *t; s++, t++)/* Nismo naisli na razliku a ispitali smo sve

    karaktere niske sub */if (*(t+1) == \0)

    return str;

    /* Nije nadjeno */return NULL;

    }

    /* Cita liniju sa stadnardnog ulaza i vraca njenu duzinu */int getline(char* line, int max){

    char *s=line;int c;

    while ( max-->0 && (c=getchar())!=\n && c!=EOF)*s++ = c; /* ekvivalentno sa *s=c; s++; */

    if (c==\n)*s++ = c;

    *s = \0;return s - line;

    }

    main()

    {char rec[]="zdravo";char linija[100];while (getline(linija, 100))

    if (sadrzi_string_pok(linija, rec))

    63

  • 8/8/2019 Programski jazik

    65/226

    Milena VujosevicJanicic 6.2 Niska karaktera i pokazivac na konstantnu nisku

    printf("%s",linija);}

    6.2 Niska karaktera i pokazivac na konstantnu nisku

    Prilikom deklaracije treba praviti razliku izmedu niza znakova i pokazivaca na kon-stantnu nisku. Ukoliko su date deklaracije:

    char poruka[]="danas je lep dan!";char *pporuka = "danas je lep dan!";

    tada vazi:

    poruka je niz znakova koji sadrzi tekst danas je lep dan!. Pojedine znakemoguce je promeniti, na primer, nakon naredbeporuka[0] = D;poruka ce sadrzati tekst Danas je lep dan!. Niska poruka se uvek odnosi nanovo mesto u memoriji.

    pporuka je pokazivac, koji je inicijalizovan da pokazuje na konstantnu nisku,on moze biti preusmeren da pokazuje na nesto drugo, na primer, moguce jepreusmeriti ovaj pokazivac sledecom naredbompporuka = poruka;i u ovom slucaju ce pokazivac pporuka pokazivati na mesto u memoriji nakojem se nalazi poruka. Pokusaj modifikacije elementa niske karaktera na kojuukazuje pporuka nije definisan (jer je to konstantna niska). Na primer, rezultatnaredbe pporuka[0]=D je nedefinisan.

    Ako deklarisemo

    char *pporuka1 = "danas je lep dan!";char *pporuka2 = "danas je lep dan!";char *pporuka3 = "danas pada kisa";

    tada ce pokazivaci pporuka1 i pporuka2 pokazivati na isto mesto u memoriji, apporuka3 na drugo mesto u memoriji.

    Ako uporedimo(pporuka1==pporuka3)uporedice se vrednosti pokazivaca. Ako uporedimo(pporuka1 < pporuka2)uporedice se vrednosti pokazivaca. Ako dodelimopporuka1=pporuka3

    tada ce pporuka1 dobiti vrednost pokazivaca pporuka3 i pokazivace na isto mestou memoriji. Nece se izvrsiti kopiranje sadrzaja memorije.

    Primer 6.10 Nakon deklaracije

    char a[] = "informatika";char *p = "informatika";

    64

  • 8/8/2019 Programski jazik

    66/226

    Milena VujosevicJanicic 6.3 Pokazivaci na pokazivace

    Loliko elemenata ima niz a?

    Koju vrednost ima a?

    Da li se moze promeniti vrednost a?

    Koju vrednost ima a[0]?

    Da li se moze promeniti vrednost a[0]?

    Koju vrednost ima p?

    Da li se moze promeniti vrednost p?

    Koju vrednost ima p[0]?

    Da li se moze promeniti vrednost p[0]?

    6.3 Pokazivaci na pokazivace

    Pokazivacke promenljive su podaci kao i svi drugi, pa samim tim imaju svoju adresuu memoriji. Zbog toga je moguce govoriti o pokazivacima na pokazivace. Na primer,ako je definisan pokazivac na int:

    int *p;

    tada mozemo definisati pokazivac na pokazivac na int:

    int **pp;

    Ovaj pokazivac moze uzeti adresu pokazivacke promenljive p:

    pp = &p;

    Nakon toga se pokazivackoj promenljivoj p moze pristupiti i indirektno, preko pokazivacana pokazivac pp, zato sto je *pp ekvivalentno sa p. Takode, celom broju na kojipokazuje p moze se pristupiti i sa **pp zato sto je **pp ekvivalentno sa *p.

    6.4 Nizovi pokazivaca

    Elementi nizova mogu biti bilo kog tipa, pa i pokazivaci. Na primer, niz pokazivacana karaktere se moze definisati na sledeci nacin:

    char * pokazivaci[100];

    Ovim se rezervise prostor za niz od 100 pokazivaca na karaktere. Njima se pris-tupa putem indeksa, kako je i uobicajeno. S obzirom da se ime niza uvek ponasakao adresa prvog objekta u nizu, sledi da je izraz pokazivaci tipa pokazivac napokazivac na char. Otuda se uobicajena pokazivacka aritmetika moze primenjivatii na nizove pokazivaca.

    65

  • 8/8/2019 Programski jazik

    67/226

    Milena VujosevicJanicic 6.4 Nizovi pokazivaca

    Primer 6.11 Program ucitava linije iz fajla ulaz.txt i zatim ih ispisuje na stan-dardnom izlazu sortirane po duzini, pocev od najkrace linije.

    #include #include #include

    #include

    #define MAX_RED 1024#define MAX_REDOVA 1024

    /* Funkcija sortira niz pokazivaca na karaktere, pri cemuje kriterijum sortiranja duzina stringova na koje pokazujuti pokazivaci. */

    void sortiraj(char *redovi[], int n);

    int main()

    { char redovi[MAX_REDOVA][MAX_RED];char *p_redovi[MAX_REDOVA];

    int i, n;FILE * in;

    /* Otvaramo fajl */in = fopen("ulaz.txt", "r");

    /* Proveravamo da li smo uspesno otvorili fajl */

    if(in == NULL){

    printf("Greska! Fajl nije uspesno otvoren!\n");exit(1);

    }

    /* Citamo linije, i smestamo ih u dvodimenzioni niz karaktera redovi[] (i-tuliniju smestamo u niz redovi[i]). Citamo najvise MAX_REDOVA. Pokazivacp_redovi[i] postavljamo da pokazuje na prvi karakter u nizu redovi[i]. */

    for(i = 0; i < MAX_REDOVA; i++)if(fgets(redovi[i], MAX_RED, in) != NULL)

    p_redovi[i] = redovi[i];else

    break;

    n = i ;

    66

  • 8/8/2019 Programski jazik

    68/226

    Milena VujosevicJanicic 6.4 Nizovi pokazivaca

    /* Zatavaramo fajl */fclose(in);

    /* NAPOMENA: Umesto da sortiramo niz nizova, sto podrazumeva zamenuvrednosti citavih nizova, efikasnije je da definisemo niz pokazivacana karaktere koje cemo da usmerimo najpre na odgovarajuce stringove

    koji se nalaze u nizu nizova redovi[] (Pokazivac p_redovi[i] sese usmerava na string u nizu redovi[i]). Nakon toga se sortira nizpokazivaca, tj. pokazivaci se ispremestaju tako da redom pokazujuna stringove po rastucim duzinama. Ovim je sortiranje bitno efikasnijejer je brze razmeniti dva pokazivaca nego citave nizove. */

    /* Sortiramo niz pokazivaca */sortiraj(p_redovi, n);

    /* Prikazujemo linije u poretku rasta duzina */

    for(i = 0; i < n; i++)fputs(p_redovi[i], stdout);

    return 0;}

    /* Funkcija razmenjuje vrednosti dva pokazivaca na karaktere.S obzirom da je potrebno preneti adrese ovih promenljivih,parametri su tipa "pokazivac na pokazivac na char". */

    void razmeni(char **s, char **t)

    {char *p;

    p = *s;*s = *t;*t = p;

    }

    /* Funkcija implementira uobicajeni algoritam sortiranja izboromnajmanjeg elementa, pri cemu se pod najmanjim elementom ovdepodrazumeva pokazivac koji pokazuje na string koji je najkraci */

    void sortiraj(char *redovi[], int n){

    int i,j, min;

    67

  • 8/8/2019 Programski jazik

    69/226

    Milena VujosevicJanicic 6.4 Nizovi pokazivaca

    for(i = 0; i < n - 1; i++){

    min = i;for(j = i + 1; j < n; j++)

    if(strlen(redovi[j]) < strlen(redovi[min])) min = j;

    if(min != i){

    razmeni(&redovi[min], &redovi[i]);}

    }}

    68

  • 8/8/2019 Programski jazik

    70/226

    Glava 7

    Rekurzija

    Funkcija1 moze da poziva samu sebe, neposredno ili posredno. Ova pojava se zoverekurzija. Ovakav pristup se cesto koristi prilikom resavanja problema koji imajuprirodnu rekurzivnu definiciju, tj. kod kojih se problem dimenzije n moze jednos-tavno svesti na problem dimenzije n-1 ili neke druge manje dimenzije. Rekurzija je

    analogna matematickoj indukciji.Ono sto je potencijalni problem kod razumevanja rekurzije je to sto se u jednom

    trenutku mogu izvrsavati vise poziva jedne iste funkcije. Na primer, ako funkcijaf() prilikom svog izvrsavanja pozove samu sebe, tada se zapocinje novi poziv istefunkcije. Prethodni poziv ceka da se zavrsi tekuci, a zatim nastavlja sa radom. Pozivrekurzivne funkcije koji je zapocet, a cije izvrsavanje jos nije zavrseno nazivamoaktivni poziv. Svaki poziv funkcije izvrsava se nezavisno od svih ostalih aktivnihpoziva u tom trenutku, zahvaljujuci cinjenici da svaki od aktivnih poziva ima svojesopostvene kopije formalnih parametara i lokalnih podataka. Kada se neki od pozivazavrsi, njegove kopije nestaju iz memorije, ali kopije ostalih poziva i dalje postoje umemoriji. Posledica ovog pristupa je da kada rekurzivna funkcija promeni vrednosti

    svojih lokalnih podataka, ove promene ne uticu na ostale aktivne pozive, zato stooni imaju svoje lokalne kopije istih podataka.

    Kreiranje i odrzavanje lokalnih kopija se jednostavno i efikasno ostvaruje zah-valjujuci tome sto su parametri funkcije i lokalne nestaticke promenljive smestenena sistemskom steku u pitanju je struktura podataka u kojoj se novi podaci uveksmestaju na vrh a prilikom uklanjanja podataka takodje se uklanja podatak sa vrha,tj. podatak koji je poslednji dodat (LIFO struktura last in, first out). Prilikompozivanja bilo koje funkcije najpre se na stek smeste njeni argumenti (one vrednostikoje su predate prilikom poziva) a zatim se na vrh steka smeste i lokalne promenljive.Nakon toga se zapocne izvrsavanje tela funkcije. Ako se tom prilikom pozove nekadruga funkcija (ili ta ista, ako je rekurzija u pitanju) tada se na vrh steka dodaju

    argumenti ovog poziva, kao i lokalne promenljive te funkcije, itd. Kada se funkci- jski poziv zavrsi, tada se sa vrha steka skidaju njegove lokalne promenljive, kao iparametri poziva, nakon cega na vrhu steka ostaju lokalne promenljive prethodnogpoziva itd.

    1Tekst preuzet sa www.matf.bg.ac.rs/milan

    69

  • 8/8/2019 Programski jazik

    71/226

    Milena VujosevicJanicic 7.1 Osnovni primeri

    Lokalni staticki podaci (promenljive deklarisane kao static unutar funkcije) sene kreiraju na steku, vec u statickoj zoni memorije, i zajednicki su za sve pozive.Zato se promene vrednosti ovih promenljivih u jednom pozivu vide i iz drugih ak-tivnih poziva iste funkcije. Zato treba biti oprezan prilikom koriscenja statickihpromenljivih u rekurzivnim funkcijama (obicno se to i ne radi).

    Svaka rekurzivna funkcija mora imati izlaz iz rekurzije kao i rekurzivni poziv

    kojim se problem svodi na problem nizeg reda. Izlaz iz rekurzije je najcesce jednos-tavan, ali ne mora uvek da bude tako.

    7.1 Osnovni primeri

    Primer 7.1 Racunanje faktorijela prirodnog broja.

    #include

    unsigned long faktorijel_iterativno(int n){

    long f = 1;int i;for (i = 1; i

  • 8/8/2019 Programski jazik

    72/226

    Milena VujosevicJanicic 7.1 Osnovni primeri

    printf("f = %d\n",f);}

    Primer 7.2 Racunanje sume prvih n prirodnih brojeva.

    #includeunsigned suma(unsigned n){

    if(n==0)return 0;

    elsereturn (n + suma(n-1));

    /* Najefikasniji nacin za resavanje ovog problema jereturn (n*(n+1))/2; */

    }

    main(){

    int s,n;printf("Unesite n\n");scanf("%d", &n);s = suma(n);printf("s = %d\n",s);

    }

    Primer 7.3 Iterativna i rekurzivna varijanta racunanja sume niza.

    int suma_niza_iterativno(int a[], int n){

    int suma = 0;int i;for (i = 0; i

  • 8/8/2019 Programski jazik

    73/226

  • 8/8/2019 Programski jazik

    74/226

    Milena VujosevicJanicic 7.1 Osnovni primeri

    int s = 1;for (i = 0; i

  • 8/8/2019 Programski jazik

    75/226

    Milena VujosevicJanicic 7.1 Osnovni primeri

    {p = stepen(n, k/2);if(k%2 == 0) s = p*p;

    else s = p*p*n;}

    return s;

    }*/

    main(){

    printf("Stepen je: %d\n", stepen(2, 8));printf("------------------\n");printf("Stepen je: %d\n", stepen2(2, 8));

    }/* Izlaz iz programa:Racunam stepen(2, 8)

    Racunam stepen(2, 7)Racunam stepen(2, 6)Racunam stepen(2, 5)Racunam stepen(2, 4)Racunam stepen(2, 3)Racunam stepen(2, 2)Racunam stepen(2, 1)Racunam stepen(2, 0)Stepen je: 256------------------Racunam stepen2(2, 8)

    Racunam stepen2(4, 4)Racunam stepen2(16, 2)Racunam stepen2(256, 1)Stepen je: 256*/

    Primer 7.6 Fibonacijevi brojevi se definisu rekurentno na sledeci nacin:

    f(0) = 1, f(1) = 1, f(n) = f(n-1) + f(n-2)

    Napisati funkciju koja izracunava n-ti Fibonacijev broj.

    #include

    #include

    /* Rekurzivna implementacija - obratiti paznju na neefikasnost funkcije */int Fib(int n){

    printf("Racunam Fib(%d)\n",n); /* Ilustracije radi! */

    74

  • 8/8/2019 Programski jazik

    76/226

    Milena VujosevicJanicic 7.1 Osnovni primeri

    if((n==0)||(n==1))return 1;

    elsereturn(Fib(n-1)+Fib(n-2));

    /* Alternativni zapis:return (n == 0 || n == 1) ? 1 : Fib(n-1) + Fib(n-2); */

    }

    /* Iterativna verzija bez niza */int Fib_iterativno(int n){

    /* Promenljiva pp cuva pretposlednji, a p poslednji element niza */int pp = 1, p = 1;int i;for (i = 0; i

  • 8/8/2019 Programski jazik

    77/226

    Milena VujosevicJanicic 7.1 Osnovni primeri

    Racunam Fib(1)Fib(5) = 8

    Kako se izvrsava program za vrednost 5:_______________________________________________________________

    Fib(5)?=> 8 = 5+3

    / \/ \

    / \Fib(4)? Fib(3)?

    => 5=3+2 => 3=2+1/ \ / \

    Fib(3)? Fib(2)? Fib(2)? Fib(1)?=> 3=2+1 => 2=1+1 => 2=1+1 |

    / \ / \ / \ 1Fib(2)? Fib(1) Fib(1) Fib(0) Fib(1) Fib(0)=> 2=1+1 | | | | |/ \ 1 1 1 1 1

    Fib(1) Fib(0)| |1 1

    _______________________________________________________________

    */

    Primer 7.7 U slucaju da se rekurzijom problem svodi na vise manjih podproblemakoji se mogu preklapati, postoji opasnost da se pojedini podproblemi manjih dimenz-ija resavaju veci broj puta. Na primer,

    fibonacci(20) = fibonacci(19) + fibonacci(18)fibonacci(19) = fibonacci(18) + fibonacci(17)tj. problem fibonacci(18) se resava dva puta. Problemi manjih dimenzija ce seresavati jos veci broj puta. Resenje za ovaj problem je kombinacija rekurzije sa tzv.dinamickim programiranjem podproblemi se resavaju samo jednom, a njihovaresenja se pamte u memoriji (obicno u nizovima ili matricama), odakle se koristeako tokom resavanja ponovo budu potrebni.

    #include

    #include

    #define MAX 50

    /* Niz koji cuva resenja podproblema. */int f[MAX];

    76

  • 8/8/2019 Programski jazik

    78/226

    Milena VujosevicJanicic 7.1 Osnovni primeri

    /* Funkcija izracunava n-ti fibonacijev broj */int fibonacci(int n){

    /* Ako je podproblem vec resen, uzimamo gotovo resenje! */

    if(f[n] != 0)return f[n];

    /* Izlaz iz rekurzije */if(n < 2)

    return f[n] = 1;else

    /* Rekurzivni pozivi */return f[n] = fibonacci(n - 1) + fibonacci(n - 2);

    }

    /* Test program */int main(){

    int n, i;

    /*Inicijalizuje se niz*/for(i=0; i

  • 8/8/2019 Programski jazik

    79/226

  • 8/8/2019 Programski jazik

    80/226

    Milena VujosevicJanicic 7.1 Osnovni primeri

    diskove velicine n, n-1, ..., 2, 1 redom */void init_tower(Tower * tower, char * name, int n){

    int i;strcpy(tower->name, name);tower->n = n;

    for(i = 0; i < n; i++)tower->s[i] = n - i;

    }

    /* Funkcija prikazuje sadrzaj na datoj kuli */void print_tower(Tower * tower){

    int i;

    printf("%s: ", tower->name);for(i = 0; i < tower->n; i++)

    printf("%d ", tower->s[i]);putchar(\n);

    }

    /* Funkcija premesta jedan disk sa vrha prve kule na vrh druge kule */void move(Tower *from, Tower * to){

    /* Proveravamo da li je potez ispravan */if(from->n == 0 || (to->n > 0 && from->s[from->n - 1] >= to->s[to->n - 1]))

    {

    printf("Ilegal move: %d from %s to %s!!\n",from->s[from->n - 1],from->name,to->name );

    exit(1);}

    else{

    /* Prikaz opisa poteza */printf("Moving disc %d from %s to %s\n",

    from->s[from->n - 1],

    from->name,to->name);

    /* Premestanje diska */to->s[to->n++] = from->s[--from->n];

    79

  • 8/8/2019 Programski jazik

    81/226

    Milena VujosevicJanicic 7.1 Osnovni primeri

    }}

    /* Rekurzivna funkcija koja premesta n diska sa kule x na kulu y. Kaopomocna kula koristi se kula z. */

    void hanoi(Tower *x, Tower *y, Tower * z, int n)

    {/* Izlaz iz rekurzije */if(n == 0)

    return;

    /* Rekurzivno premestamo n - 1 disk sa x na z, pomocu kule y */hanoi(x, z, y, n - 1);

    /* Premestamo jedan disk sa x na y */move(x,y);

    /* Prikaz stanja kula nakon poteza */print_tower(x);print_tower(y);print_tower(z);

    /* Premestamo n - 1 disk sa z na y, pomocu kule x */hanoi(z, y, x, n - 1);

    }

    /* Test program */

    int main(){

    Tower x, y, z;int n;

    /* Ucitavamo dimenziju problema */scanf("%d", &n);

    /* Inicijalizujemo kule. Kula x ima n diskova, ostale su prazne */init_tower(&x, "X", n);init_tower(&y, "Y", 0);

    init_tower(&z, "Z", 0);

    /* Prikaz kula na pocetku */print_tower(&x);print_tower(&y);

    80

  • 8/8/2019 Programski jazik

    82/226

    Milena VujosevicJanicic 7.2 Binarna pretraga

    print_tower(&z);

    /* Poziv funkcije hanoi() */hanoi(&x, &y, &z, n);

    return 0;

    }

    7.2 Binarna pretraga

    Primer 7.9 Rekurzivna varijanta algoritma binarne pretrage.

    #include

    /* Funkcija proverava da li se element x javlja unutar nizacelih brojeva a.Funkcija vraca poziciju na kojoj je element nadjen odnosno

    -1 ako ga nema.

    !!!!! VAZNO !!!!!Pretpostavka je da je niz a uredjen po velicini

    */

    int binary_search(int a[], int l, int d, int x){

    /* Ukoliko je interval prazan, elementa nema */if (l > d)

    return -1;

    /* Srednja pozicija intervala [l, d] */int s = (l+d)/2;

    /* Ispitujemo odnos x-a i srednjeg elementa */if (x == a[s])

    /* Element je pronadjen */return s;

    else if (x < a[s])/* Pretrazujemo interval [l, s-1] */return binary_search(a, l, s-1, x);

    else/* Pretrazujemo interval [s+1, d] */return binary_search(a, s+1, d, x);

    }

    main()

    81

  • 8/8/2019 Programski jazik

    83/226

    Milena VujosevicJanicic 7.3 MergeSort algoritam

    {int a[] = {3, 5, 7, 9, 11, 13, 15};int x;int i;

    printf("Unesi element kojega trazimo : ");

    scanf("%d",&x);i = binary_search(a, 0, sizeof(a)/sizeof(int)-1, x);

    if (i==-1)printf("Elementa %d nema\n", x);

    elseprintf("Pronadjen na poziciji %d\n", i);

    }

    7.3 MergeSort algoritam

    Primer 7.10 Sortiranje niza celih brojeva ucesljavanjem - MergeSort algoritam.

    #include #include #include

    #define MAX 100

    /* sortiranje ucesljavanjem */void merge_sort (int a[], int l, int d){

    int s;int b[MAX]; /* pomocni niz */int i, j, k;

    /* Izlaz iz rekurzije */if (l >= d)

    return;

    /* Odredjujemo sredisnji indeks */s = ( l + d ) / 2 ;

    /* rekurzivni pozivi */ merge_sort (a, l, s); merge_sort (a, s + 1, d);

    /* Inicijalizacija indeksa. Indeks i prolazikrozi levu polovinu niza, dok indeks j

    82

  • 8/8/2019 Programski jazik

    84/226

    Milena VujosevicJanicic 7.3 MergeSort algoritam

    prolazi kroz desnu polovinu niza. Indeksk prolazi kroz pomocni niz b[] */

    i = l ;j = s + 1;k = 0 ;

    /* "ucesljavanje" koriscenjem pomocnog niza b[] */while(i

  • 8/8/2019 Programski jazik

    85/226

    Milena VujosevicJanicic 7.4 QuickSort algoritam

    putchar(\n);

    return 0;}

    7.4 QuickSort algoritamPrimer 7.11 Sortiranje niza celih brojeva - QuickSort algoritam.

    /* Funkcija menja mesto i-tom i j-tom elementu niza a */void swap(int a[], int i, int j){

    int tmp = a[i];a[i] = a[j];a[j] = tmp;

    }

    /* Funkcija particionise interval [l, r] niza a, tako da levo od pivotabudu svi elementi manji od njega, a desno svi veci od njega.Ovi podnizovi ne moraju biti sortirani.Funkcija vraca poziciju pivota.

    */int partition(int a[], int l, int r){

    int last, i;

    /* Srednji element uzimamo za pivot i postavljamo ga na pocetak */swap(a, l, (l + r)/2);

    /* Niz organizujemo tako da pivot postavimo na pocetak, zatim da izanjega budu svi elementi manji od njega, pa zatim svi elementi kojisu veci od njega tj.p i v o t < < < < > > > >

    */

    /* last je pozicija poslednjeg elementa niza za koji znamo da je manji od pivota. U pocetku takvih elemenata nema */

    last = l;for (i = l+1; i

  • 8/8/2019 Programski jazik

    86/226

    Milena VujosevicJanicic 7.4 QuickSort algoritam

    /* Zahtevanu konfiguraciju < < < < pivot > > > > dobijamo takosto zamenimo mesto pivotu i poslednjem elementu manjem od njega */

    swap(a, l, last);

    /* Pivot se sada nalazi na poziciji last */return last;

    }

    /* Funkcija sortira deo niza brojeva a izmedju pozicija l i r*/void quick_sort(int a[], int l, int r){

    int i, last;

    /* Ukoliko je interval [l, r] prazan nema nista da se radi */if (l >= r)

    return;

    /* Particionisemo interval [l, r] */int pivot = partition(a, l, r);

    /* Rekurzivno sortiramo elemente manje od pivota */quick_sort(a, l, pivot-1);/* Rekurzivno sortiramo elemente vece pivota */quick_sort(a, pivot+1, r);

    }

    main()

    {int a[] = {5, 8, 2, 4, 1, 9, 3, 7, 6};int n = sizeof(a)/sizeof(int);int i;

    quick_sort(a, 0, n-1);

    for (i = 0; i < n; i++)printf("%d ", a[i]);

    printf("\n");}

    85

  • 8/8/2019 Programski jazik

    87/226

    Glava 8

    Pokazivaci na funkcije

    Binarne instrukcije koje cine funkciju su takode negde u memoriji, i imaju svojuadresu. Zato je moguce je definisati pokazivac na funkciju. Na primer, deklaracija:

    int (*fp)(int);

    definise promenljivu f, koja je tipa pokazivac na funkciju koja prihvata argumenttipa int, i vraca vrednost tipa int. Ova promenljiva sadrzi adresu neke funkcijetog tipa. Na primer, ako je deklarisana funkcija:

    int f(int a);

    Tada je moguce dodeliti:

    fp = &f; /* Operator adrese nije neophodan. */

    Promenljiva fp sadrzi adresu funkcije f. Funkcija f se sada moze pozivati derefer-enciranjem pokazivaca fp:

    (*fp)(3);

    Zagrade oko izraza *fp su neophodne zbog prioriteta operatora. Dereferenciranjempokazivaca na funkciju dobija se funkcija, koja se onda poziva na uobicajen nacin.

    Primer 8.1 Program demonstrira upotrebu pokazivaca na funkcije.

    #include

    int kvadrat(int n){

    return n*n;

    }

    int kub(int n){

    return n*n*n;}

    86

  • 8/8/2019 Programski jazik

    88/226

    Milena VujosevicJanicic Pokazivaci na funkcije

    int parni_broj(int n){

    return 2*n;}

    /* Funkcija izracunava sumu brojeva f(i) za i iz intervala [1, n].int (*f) (int) u argumentu funkcije sumiraj je pokazivacna funkciju sa imenom f, koja kao argument prima promenljivutipa int i vraca kao rezultat vrednost tipa int

    */int sumiraj(int (*f) (int), int n){

    int i, suma=0;for (i=1; i

  • 8/8/2019 Programski jazik

    89/226

    Milena VujosevicJanicic Pokazivaci na funkcije

    tackama datog intervala sa datim korakom.

    #include #include

    /*

    Zaglavlje math.h sadrzi deklaracije razih matematickih funkcija. Izmedjuostalog, to su sledece funkcije: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);double sinh(double x);double cosh(double x);

    double tanh(double x);double exp(double x);double log(double x);double log10(double x);double pow(double x, double y);double sqrt(double x);double ceil(double x);double floor(double x);double fabs(double x);

    */

    /* Funkcija tabeliraj() prihvata granice intervala a i b, korak h, kao ipokazivac f koji pokazuje na funkciju koja prihvata double argument, ivraca double rezultat. Za tako datu funkciju ispisuje njene vrednosti uintervalu [a,b] sa korakom h */

    void tabeliraj(double a, double b, double h, double (*f)(double)){

    double x;

    printf("-----------------------\n");

    for(x = a; x

  • 8/8/2019 Programski jazik

    90/226

    Milena VujosevicJanicic 8.1 Funkcijaqsort iz standardne biblioteke

    /* Funkcija main */int main(){

    double a, b, h;

    /* Unosimo granice intervala */

    printf("Uneti granice intervala: ");scanf("%lf%lf", &a, &b);

    /* Unosimo korak */printf("Uneti korak: ");scanf("%lf", &h);

    /* Testiramo funkciju tabeliraj() za sin(), cos() i exp() */printf("sin(x)\n");tabeliraj(a, b, h, &sin);printf("cos(x)\n");

    tabeliraj(a, b, h, &cos);printf("exp(x)\n");tabeliraj(a, b, h, &exp);

    return 0;}

    8.1 Funkcija qsort iz standardne biblioteke

    Prototip funkcije qsort iz stdlib.h je:

    void qsort(void *niz, int duzina_niza, int velicina_elementa_niza,int (*poredi)(const void*, const void*) )

    Ova funkcija sortira nizniz[0], niz[1], ..., niz[duzina_niza - 1]elemenata velicine velicina_elementa_niza koriscenjem funkcije poredi koja uporedujedva elementa niza.

    Posto je void* tip niza niz to obezbeduje mogucnost koriscenja ove funkcije zanizove razlicitih tipova podataka. Da bi funkcija qsort znala sa kakvim elementimabarata, potrebno joj je proslediti i velicinu jednog elementa u nizu (ovo je kljucnoza korak u kome se vrisi razmena elemenata niza funkcija qsort mora da zna

    koliko bajtova zauzima jedan element niza kako bi mogla adekvatno da vrsi kopiranjememorije).

    Funkcija poredi vrsi poredenje dva elementa niza. Kada ova funkcija vracapozitivnu vrednost ako je prvi element veci od drugog, 0 ako su jednaki i negativnuvrednost ako je prvi element manji, tada ce se niz sortirati u rastucem poretku.Modifikacijom ove funkcije niz se moze sortirati u opadajucem poretku (ukoliko

    89

  • 8/8/2019 Programski jazik

    91/226

    Milena VujosevicJanicic 8.1 Funkcijaqsort iz standardne biblioteke

    vraca pozitivnu vrednost ako je prvi manji, 0 ako su jednaki i negativnu vrednostako je prvi veci).

    Kvalifikator const

    Kljucna rec const u programskom jeziku C sluzi za definisanje konstanti. Ako

    napisemo:const int a = 2;

    tada se u daljem toku programa promenljivoj a ne moze dodeljivati vrednost. Zarazliku od konstanti definisanih define direktivom ova konstanta ima jasno definisantip koji prevodilac proverava prilikom upotrebe.

    Treba naglasiti, medjutim, da ako se napise:

    const int * p = &a;

    tada se const ne odnosi na promenljivu p, vec na podatak tipa int na koji ppokazuje. Dakle, nije pokazivac konstantan, vec on pokazuje na konstantan podatak.

    Na primer:

    int b;p = &b;

    je dozvoljeno, ali:

    *p = 4;

    nije dozvoljeno, zato sto je p pokazivac na konstantan int (odnosno, kroz pokazivacp nije moguce menjati vrednost koja se nalazi na adresi na koju on ukazuje). Ovose moze razumeti tako sto se deklaracija procita sa desna u levo:

    const int * p; /* p je pokazivac na int koji je konstantan*/

    Slicno bi bilo i ako napisemo:

    int const * p; /* p je pokazivac na konstantan int. */

    Medutim, ako napisemo:

    int * const p; /* p je konstantan pokazivac na int. */

    Kombinacija ovoga je:

    const int * const p; /* p je konstantan pokazivac na int

    koji je konstantan.*/Dakle, u ovom poslednjem slucaju konstantni su i pokazivac i ono na sta on pokazuje.

    90

  • 8/8/2019 Programski jazik

    92/226

    Milena VujosevicJanicic 8.1 Funkcijaqsort iz standardne biblioteke

    Upotreba qsort

    Primer 8.3 Upotrebom qsort funkcije iz standardne biblioteke izvrsiti sortiranjeniza celih i niza realnih brojeva.

    /* Ilustracija upotrebe funkcije qsort iz stdlib.hSortira se niz celih brojeva.

    */

    #include #include

    /* const znaci da ono na sta pokazuje a (odnosno b)nece biti menjano u funkciji */

    int poredi(const void* a, const void* b){/* Skracen zapis za

    int br_a = *(int*)a;

    int br_b = *(int*)b;

    return br_a-br_b;*/return *((int*)a)-*((int*)b);}

    int poredi_float(const void* a, const void* b){

    float br_a = *(float*)a;float br_b = *(float*)b;

    if (br_a > br_b) return 1;else if (br_a < br_b) return -1;else return 0;

    }

    main(){int i;int niz[]={3,8,7,1,2,3,5,6,9};float nizf[]={3.0,8.7,7.8,1.9,2.1,3.3,6.6,9.9};

    int n=sizeof(niz)/sizeof(int);qsort((void*)niz, n, sizeof(int), poredi);for(i=0; i

  • 8/8/2019 Programski jazik

    93/226

    Milena VujosevicJanicic 8.1 Funkcijaqsort iz standardne biblioteke

    n=sizeof(nizf)/sizeof(float);qsort((void*)nizf, n, sizeof(float), poredi_float);for(i=0; i0 ukoliko je prva rec veca, 0 ako su jednakei

  • 8/8/2019 Programski jazik

    94/226

    Milena VujosevicJanicic 8.2 Funkcija bsearch iz standardne biblioteke

    for (i=0; i

  • 8/8/2019 Programski jazik

    95/226

    Milena VujosevicJanicic 8.2 Funkcija bsearch iz standardne biblioteke

    u rastucem redosledu u odnosu na dati kljuc. Funkcija bsearch vraca pokazivac napronadeni element ili NULL ukoliko element sa datom vrednoscu kljuca ne postoji.

    Primer 8.5 Binarno pretrazivanje - koriscenje ugrad ene bsearch funkcije.

    /* Funkcija ilustruje koriscenje ugradjene funkcije bsearch */#include

    int poredi(const void* a, const void *b){return *(int*)a-*(int*)b;}

    main(){int x=-1;int niz[]={1,2,3,4,5,6,7,8,9,10,11,12};

    int* elem=(int*)bsearch((void*)&x,(void*)niz,sizeof(niz)/sizeof(int),sizeof(int),poredi);

    if (elem==NULL)printf("Element nije pronadjen\n");

    elseprintf("Element postoji na poziciji %d\n",elem-niz);

    }

    Primer 8.6 Sa ulaza se unose reci. Program broji pojavljivanja svake od kljucnihreci programskog jezika C. Na kraju se reci ispisuju opadajuce po broju pojavljivanja.

    #include #include

    /* Svaka kljucna rec se odlikuje imenom i brojem pojavljivanja */typedef struct _keyword{

    char word[20];int num;

    } keyword;

    /* Kreiramo niz struktura sortiranih leksikografskipo imenu kljucne reci, kako bismo ubrzali pronalazak reci */

    94

  • 8/8/2019 Programski jazik

    96/226

  • 8/8/2019 Programski jazik

    97/226

    Milena VujosevicJanicic 8.2 Funkcija bsearch iz standardne biblioteke

    /* Funkcija numerickog poredjenja za qsort */int numcmp(const void* a, const void* b){

    return ((*(keyword*)b).num-(*(keyword*)a).num);}

    main(){

    char word[80];int i;

    /* Broj kljucnih reci */int num_of_keywords=sizeof(keywords)/sizeof(keyword);

    /* Citamo reci */while (getword(word,80)!=-1){

    /* Trazimo rec u spisku kljucnih reci binarnom pretragom *//* Prvi argument funkcije bsearch treba da bude pokazivacna rec koju trazimo. Posto je word tipa niza karaktera, tadauzimanjem adrese od word dobijamo istu vrednost kao i word,tj nema razlike izmedju word i &word. Zbog toga se u funkcijiporedjenja koristi dreferenciranje na sledeci nacin

    strcmp((char*)a, (*(keyword*)b).word); }Da je word tipa char*, tada bi poziv funkcije bsearchsa argumentom &word povlacilo da funkcija poredjenjakoristi dereferenciranje na sledeci nacin

    strcmp(*(char**)a, (*(keyword*)b).word); }

    */keyword* k=(keyword*)bsearch((void*)word,

    (void*)keywords,num_of_keywords,sizeof(keyword),cmp);

    /* Ukoliko je pronadjena uvecavamo broj pojavljivanja */if (k!=NULL)

    (*k).num++;}

    /* Sortiramo niz na osnovu broja pojavljivanja */qsort((void*)keywords, num_of_keywords, sizeof(keyword), numcmp);

    /* Vrsimo ispis */for (i=0; i

  • 8/8/2019 Programski jazik

    98/226

    Milena VujosevicJanicic 8.3 Funkcijelsearch i lfind

    printf("%s %d\n", keywords[i].word, keywords[i].num);}

    8.3 Funkcije lsearch i lfind

    Funkcije za linearnu pretragu standardne biblioteke su funkcije lsearch i lfind.Funkcija lsearch ima sledece argumente

    void *lsearch(const void *kljuc, void *niz, int *duzina_niza,int velicina_elementa_niza,int (*comp)(const void *, const void *));

    Ova funkcija ima iste argumente kao i funkcija bsearch() jedina razlika je u tomesto se kao treci argument ne predaje duzina niza vec adresa celobrojne promenljiveu kojoj se nalazi duzina niza. Ovo je zato sto funkcija lsearch() ukoliko linearnompretragom ne pronade element koji se trazi, umece trazeni element na kraj niza,a duzinu niza uvecava za jedan (sto cini tako sto promenljivoj pozivajuce funkcije

    pristupa preko pokazivaca i menja je). Takode, posto postiji mogucnost umetanjaelementa u niz, kao kljuc pretrage potrebno je koristiti kljuc koji je istog tipa kao stosu to elementi niza. Funkcija za uporedjivanja elemenata na koju pokazuje pokazi-vac comp treba da zadovoljava ista pravila kao i kod funkcije bsearch. Medjutim,s obzirom da se kod linearne pretrage koristi iskljucivo poredenje na jednakost, do-voljno je da funkcija za uporedjivanje vraca 0 ako su objekti koji se uporedjuju

    jednaki, a razlicito od nule u suprotnom.Funkcija lfind:

    void *lfind(const void *kljuc, void *niz, int *duzina_niza,int velicina_elementa_niza,int (*comp)(const void *, const void *));

    funkcionise isto kao i lsearch, s tom razlikom sto ne umece novi element u slucajuneuspesne pretrage, vec vraca NULL (funkcija lsearch u slucaju neuspesne pretrageumece trazeni element na kraj i vraca njegovu adresu). Za funkciju lfind moguce jekoristiti kljuc pretrage koji nije istog tipa kao elementi niza, u tom slucaju potrebno

    je adekvatno definisati funkciju poredenja.

    8.4 Pokazivaci

    Primer 8.7 Razlicite deklaracije:

    int *p; pokazivac na intint **p; pokazivac na pokazivac na tip int

    int* p[10]; niz od 10 elemenata tipa pokazivaca na intint *p[10]; niz od 10 elemenata tipa pokazivaca na int

    97

  • 8/8/2019 Programski jazik

    99/226

    Milena VujosevicJanicic 8.4 Pokazivaci

    int p[5][10]; pet nizova od po 10 elemenata tipa intint (*p)[10]; pokazivac na niz od deset celobrojnih vrednosti

    int* p(); funkcija bez argumenata koja vraca pokazivac na intint *p(); funkcija bez argumenata koja vraca pokazivac na int

    int (*p)(); pokazivac na funkciju bez argumenata koja vraca intint *(*p)(); pokazivac na funkciju bez argumenata koja vraca pokazivac na intint* (*p)(); pokazivac na funkciju bez argumenata koja vraca pokazivac na int

    Razlika izmedu int** t i int (*t)[5]

    int x;int (*t)[5];int aa[4][5];t = aa;x=t[2][2]; /*Da je t tipa int** ova dodela ne bi bila moguca!*/

    98

  • 8/8/2019 Programski jazik

    100/226

    Glava 9

    Dinamicka alokacija memorije

    Do sada smo memoriju za podatke rezervisali na dva nacina1:

    Staticka alokacija podaci se kreiraju staticki prilikom pokretanja programai ostaju u memoriji do kraja njegovog izvrsavanja. Ovakvu alokaciju imajuglobalne promenljive (promenljive definisane van svake funkcije ili bloka) kao istaticke lokalne promenljive (deklarisane kljucnom recju static unutar funkcijeili bloka).

    Automatska alokacija podaci se kreiraju automatski prilikom ulaska u funkcijuili blok, i nestaju kada se iz funkcije/bloka izade. Ovakvo ponasanje imajusve lokalne promenljive koje nisu deklarisane kao static. Prostor za ovepromenljive se rezervise na programskom steku.

    Glavni nedostatak oba ova pristupa je to sto programer u vreme pisanja programamora da predvidi koliko ce mu prostora biti potrebno za podatke. Cesto tako nestonije moguce, jer dimenzije problema mogu varirati. Drugi nedostatak je to sto jezivotni vek svakog podatka jasno definisan gornjim pravilima. Programer moze zeletida nakon kreiranja nekog objekta u memoriji on ostane tu dokle god je potreban,te da ga kasnije ukloni kada vise za njim nema potrebe.

    Svi ovi problemi resavaju se dinamickom alokacijom memorije. Pored statickezone i steka, u memoriji postoji i odredeni prostor koji se naziva hip (eng. heap). Uovom prostoru se po potrebi mogu kreirati objekti proizvoljne velicine. Taj prostorse kasnije moze (i treba) osloboditi, kada programer vise nema potrebu da koristitaj prostor.

    U programskom jeziku C, ovo se moze ostvariti pozivom funkcije standardnebiblioteke malloc() koja je deklarisana u zaglavlju stdlib.h:

    void * malloc(int n);

    Ova funkcija alocira na hipu kontinualni prostor od n bajtova, i vraca adresu pocetkatog prostora ili vraca vrednost NULL ukoliko zahtev ne moze da se ispuni. Jedini nacinda se ovom prostoru pristupi je preko pokazivaca (jer ne posto ji ime promenljive kaokod statickih i automatskih promenljivih).

    Osim funkcije malloc() postoje i druge funkcije za alokaciju, na primer:1Tekst preuzet sa sajta www.matf.bg.ac.rs/~milan

    99

    http://www.matf.bg.ac.rs/~milanhttp://www.matf.bg.ac.rs/~milanhttp://www.matf.bg.ac.rs/~milanhttp://www.matf.bg.ac.rs/~milan
  • 8/8/2019 Programski jazik

    101/226

    Milena VujosevicJanicic Dinamicka alokacija memorije

    void * calloc(int n, int s);

    Ova funkcija alocira prostor za n susednih elemenata velicine s bajtova (zapravoalocira n*s bajtova). Ova funkcija jos i inicijalizuje rezervisani prostor na vrednost0, za razliku od malloc() funkcije koja prostor ostavlja neinicijalizovan. Funkcija

    void * realloc(void *p, int n);

    vrsi realokaciju prostora na koji pokazuje pokazivac p za koji je memorija prethodnobila dinamicki alocirana. Alocira se n bajtova, kopira se stari sadrzaj u novi prostor,a