38
Izradili: Duje Senta Antonio Prcela 9. ožujka 2015. Sveučilište u Splitu Fakultet elektrotehnike, strojarstva i brodogradnje Programiranje 2 Priručnik za laboratorijske vježbe

Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

  • Upload
    others

  • View
    32

  • Download
    2

Embed Size (px)

Citation preview

Page 1: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

Izradili: Duje Senta Antonio Prcela 9. ožujka 2015.

Sveučilište u Splitu Fakultet elektrotehnike, strojarstva i brodogradnje

Programiranje 2

Priručnik za laboratorijske

vježbe

Page 2: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili
Page 3: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

Sadržaj

I. Općenito o C-u ............................................................................................................................................ 1

II. Uvod u leksički pretprocesor ...................................................................................................................... 1

III. Usporedba sintaksi C-a i VB.Net-a .......................................................................................................... 3

Vježba 1. ............................................................................................................................................................. 5

Vježba 2. ............................................................................................................................................................. 8

Vježba 3. ...........................................................................................................................................................11

Vježba 4. ...........................................................................................................................................................13

Vježba 5. ...........................................................................................................................................................15

Vježba 6. ...........................................................................................................................................................20

Vježba 7. ...........................................................................................................................................................21

Vježba 8. ...........................................................................................................................................................24

Vježba 9. ...........................................................................................................................................................26

Vježba 10. .........................................................................................................................................................28

Vježba 11. .........................................................................................................................................................30

Vježba 12. .........................................................................................................................................................33

Page 4: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

1

I. Općenito o C-u

Programski jezik C spada u proceduralne programske jezike kojeg su razvili Dennis Ritchie i Ken Thompson u

Bellovim laboratorijima 1976.g. C je jezik opće namjene, što znači da se u njemu može napraviti apsolutno sve:

od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

igara. C, kao jezik, ni u čemu ne ograničava. Omogućuje i uključivanje naredbi pisanih strojnim jezikom (engl.

assembler), zbog čega je zajedno s mogućnošću direktnog pristupa pojedinim bitovima, bajtovima ili cijelim

blokovima memorije, pogodan za pisanje sistemskih programa. Zbog tih karakteristika C je među popularnijim

programskim jezicima i rabe ga mnogi programeri. Kao jedan od najvažnijih jezika u povijesti komercijalne

računalne industrije, C je do danas ostao jedini programski jezik prilagođen za sve računalne platforme, od malih

sustava pa do mrežnih superračunala. Programi napisani u njemu vrlo su bliski načinu rada hardvera te u načelu

zahtijevaju od programera dobro razumijevanje rada procesora, memorije te ulazno-izlaznih sklopova. Korištenje

C-a je određeno standardom, a trenutni standard koji se koristi je C11.

II. Uvod u leksički pretprocesor

Pojam "pretprocesor" se koristi za oznaku prve faze obrade izvornog koda. On vrši leksičku obradu izvornog koda

na tri načina:

1. Umeće u izvorni kod datoteke koje su navedene u direktivi #include

2. Vrši supstituciju teksta prema direktivi #define

3. Vrši selekciju koda, koji će se prevesti, pomoću direktiva #if, #elif, #else i #endif

Koriste se dvije varijante direktive #include:

#include <ime_datoteke> //primjer 1

U gornjem primjeru (primjer 1) je prikazano kada se datoteka traži u direktoriju u kojem su smještene datoteke s

deklaracijama standardnih funkcija. Dok se u donjem primjeru (primjer 2) uključuje datoteka koja se nalazi u

direktoriju gdje je izvorni kod (u direktoriju programa gdje se nalazi datoteka *.c).

#include "ime_datoteke" //primjer 2

Leksička supstitucija teksta, makro (engl. macro), se definira pomoću direktive #define na dva načina:

#define identifikator tekst_za_supstituciju

Neki primjeri supstitucije:

#define GODINA 20

#define ANTE "Ante"

#define NEW_LINE printf("\n");

#define ISPIS printf

#define ZBROJ(arg1, arg2) arg1 + arg2

Page 5: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

2

Primjer koda sa supstitucijom: Ispis:

#include <stdio.h>

#define GOD 20 #define ANTE "Ante" #define NEW_LINE printf("\n"); #define ISPISI printf #define POST(a,b) (float)((a)*(100))/(b)

int main(int argc, char *argv[]) { ISPISI("%s ima %d godina.\n", ANTE, GOD); NEW_LINE ISPISI("Imao je na ispitu %f posto.", POST(3,5)); return 0;

}

Ante ima 20 godina.

Imao je na ispitu 60 posto.

Tablica T1 Primjer supstitucije

Leksička definicija Izvorni kod Supstitucija

#define MNOZI(a,b) ((a)*(b)) y = MNOZI(2+5,broj); y = ((2+5)*(broj));

#define MNOZI(a,b) a*b y = MNOZI(2+5,broj); y = 2+5*broj;

Tablica T2 Primjer makroa

Razlog zagrada u prvoj definiciji (Tablica T2) je zbog prioriteta operatora, jer da je makro napisan na način kao u

drugoj definiciji zbog prioriteta operatora * nad +, makro ne bi vratio očekivani rezultat.

Page 6: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

3

III. Usporedba sintaksi C-a i VB.Net-a

Osnovna razlika koda napisanog u C-u s onim napisanim u VB.NET-u je taj što je C vrlo osjetljiv na velika i mala

slova (case-sensitive). Nije isto je li napisano pozivFunkcije(); ili PozivFunkcije();, u ovom slučaju bi se

pozvale dvije različite funkcije.

C programski jezik: Visual Basic .NET

#include <stdio.h>

int main(int argc, char *argv[]) { int cijeli_broj = 0; char znak = 0; printf("Hello world!"); printf("\n");

/*komentar u C-u*/ return 0; }

Module Module1

Sub Main()

Dim cijeli_broj As Integer Dim znak as Char Console.Write("Hello world!") Console.WriteLine()

'komentar u VB.Net-u End Sub End Module

Tablica T3 Usporedba sintakse C i VB.net

Kao što se može vidjeti iz priložene tablice (Tablica T3), postoje značajne razlike sintaksi. Prvo se može uočiti da

se u C-u imena ključnih riječi pišu malim slovima. Sljedeće je to što se svaka naredba mora zatvoriti s točka-

zarezom ; inače se javlja greška pri prevođenju koda. Varijable prilikom deklaracije moraju imati pridruženu

inicijalnu vrijednost, inače sadrži nedefiniranu vrijednost. Pristup sadržaju neinicijalizirane varijable je strogo

zabranjen te može dovesti do greške u prevođenju ili izvršavanju programa.

U C-u ne postoje procedure, samo funkcije. U gornjem primjeru se može vidjeti funkcija main. Kao i kod VB.NET-

a, main je početna funkcija svakog programa, od nje program započinje s radom. Funkcija main() po

standardima ANSI C te ISO/IEC C11 ima povratnu vrijednost isključivo tipa int, dok ostale funkcije mogu imati

povratnu vrijednost bilo kojeg tipa. Poželjno je da main() vraća vrijednost nula (return 0;) ako je program

uspješno završio s radom, te bilo koju drugu vrijednost u slučaju da je došlo do greške prilikom izvršavanja

programa.

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

int main(void)

int prije main-a, a i bilo koje druge funkcije, govori da funkcija vraća cijelobrojnu vrijednost, dok void unutar

zagrada govori da funkcija ne prima nikakve argumente. U varijabli argc je zapisano broj argumenata koji se

nalaze u nizu stringova u argv. Program može imati minimalno jedan argument, što reprezentira naziv programa.

Page 7: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

4

Funkcije vraćaju vrijednost na sljedeći način:

int inkrement(int x) { x++; return x; //x je varijabla tipa int }

Funkcija printf()

- funkcija koja se koristi za formatirani ispis teksta i/ili varijabli na ekranu.

printf("Pozdrav! "); // ispis teksta

printf("\n"); // prelazak u novi red

printf("%d", x); // ispis vrijednosti varijable x tipa int

postoji još:

%s – ispis stringa (niza znakova)

%c – ispis varijable tipa char

%e – ispis tipa double

%f – ispis varijable tipa float

Adresni operator &

- Služi da bi se pristupilo adresi neke varijable. Navodi se ispred imena varijable.

Funkcija scanf() & scanf_s()

- koristi se za formatirani unos podataka s standardnog ulaza (stdin), te se koriste isti specifikatori formata

kao kod printf-a (%d, %e, %c…). Pošto se radi o unosu, mora se koristiti adresni operator & da bi se

vrijednost spremila na memorijsku adresu koja je dodijeljena varijabli.

Primjer korištenja:

scanf(" %d", &x); //spremi unos s tastature na adresu varijable x

Za unos stringa preko scanf() se ne koristi adresni operator:

scanf(" %s", txt); //’txt’ je adresa početnog elementa niza znakova

Gore navedena funkcija ima nedostatak što na standardnom ulazu može biti unesena veća količina teksta nego

što varijabla može spremiti pa se program sruši (prelijevanje međuspreminka). Da bi se spriječilo rušenje

programa u takvim uvjetima uvedena je funkcija scanf_s(), koja nije dio ANSI C-a i podržana je samo u

Windows OS-u. Primjer korištenja:

char txt[N] = {0}; // deklariran je niz znakova „txt“ od N elemenata scanf_s(" %s", txt, N); /* unos se sprema u „txt“ ako je unos kraći od N

znakova */

Komentari u C-u se mogu pisati na dva načina:

// komentar koda… - korištenjem dvostruke kose crte, za samo jedan red komentara.

/* tekst se nalazi

u dvije linije */ - unutar oznaka za komentar koji se želi pisati u više redaka.

Page 8: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

5

Vježba 1.

U programskom jeziku C postoje četiri vrste osnovnih primitivnih varijabli (tablica 1.1). Osnovni operatori koji

postoje u C-u su pretežno isti kao i kod ostalih programskih jezika (tablica 1.2).

Razred varijabli Oznaka Veličina Raspon vrijednosti

Cjelobrojni tip podataka

int

short

long

4 byte

2 byte

8 byte

<-2147483648, 2147483647>

<-32768, 32767>

<-9,223e+15, 9,223e+15>

Znakovni tip podataka char 1 byte <-128, 127>

Realni tip podataka

float

double

4 byte

8 byte

<+-1.175494351e-38 , +-3.402823466e+38>

<+-2.2250738585072014e-308,

+-1.7976931348623158e+308>

Kardinalni tip podataka (mogu biti cjelobrojni i znakovni

tipovi)

unsigned char

unsigned int

unsigned long

1 byte

4 byte

8 byte

<0,255>

<0,65535>

<0, 18,466e+15>

Tablica 1.1 – Primitivne varijable u C-u

Razredi operatora Oznaka Naziv Napomena

Matematički operatori

+ - * / = % ++ --

zbrajanje oduzimanje množenje dijeljenje operator pridruživanja modulus inkrement dekrement

- s desna na lijevo pridružuje vrijednost - ostatak cjelobrojnog dijeljenja

Operatori za rad s bitovima

& | ^ !

logičko AND logičko OR logičko XOR logičko NOT

Operatori indirekcije & *

adresni operator pokazivački operator

Uvjetni operatori

> <

== != >= <=

veće od manje od jednako različito veće ili jednako manje ili jednako

- ukoliko se koristi = onda će doći do pridruživanja

vrijednosti, a ne do usporedbe.

Logički operatori && || !

uvjetno AND uvjetno OR logičko NOT

Tablica 1.2 – Osnovni operatori C-a

Page 9: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

6

Ime varijable ujedno označava i adresu varijable. Koja je to adresa? Brigu o tome vodi prevoditelj. Adresa

varijable se može odrediti pomoću posebnog operatora & koji se naziva adresni operator. Koristi se kao unarni

operator koji se zapisuje ispred imena varijable.

Primjer koda: Ispis:

#include <stdio.h>

int main(void) { int cijeli_broj = 5; printf("Adresa varijable je: %d\n", &cijeli_broj); printf("Vrijednost varijable je: %d", cijeli_broj);

return 0; }

Adresa varijable je: 24883681

Vrijednost varijable je: 5

Tablica 1.3 Primjer ispisa vrijednosti i adrese varijable

Varijable je moguće prebaciti u drugi tip pomoću eksplicitne pretvorbe (poznato kao „cast“ operator).

Primjenjuje se tako da se ispred varijable koja se pretvara napiše novi tip. Sljedeći primjer (tablica 1.4.) će

pretvoriti cijeli broj y u broj s pomičnim zarezom i spremiti u varijablu x:

Primjer koda: Ispis:

int y = 12; float x = (float)y; printf("%f", x);

12.000000

Tablica 1.4 Primjer eksplicitne pretvorbe varijable

for petlja

For petlja se upotrebljava kada se kod unutar te petlje treba ponoviti određeni broj puta. Prva trećina zagrade

(do prvog točka-zareza „;“) govori koju varijablu uzeti i odakle krenuti. Druga trećina zagrade je uvjet koji treba

bit zadovoljen da bi krenulo u iduću iteraciju petlje. Zadnji dio zagrade je operacija kojom se mijenja varijabla,

najčešće korak kojim se mijenja varijabla. Napomena: nije potrebno pisati sva tri dijela zagrade. Može se npr.

korak povećavati unutar petlje.

Primjer koda: Ispis:

for(int i=0; i<5; i++) { printf("%d,", i); }

0,1,2,3,4

Tablica 1.5 Primjer for petlje

Page 10: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

7

ZADACI

1. Napisati program koji definira četiri varijable (char, int, float, double). Ispisati sve četiri varijable, zajedno s

njihovim adresama i izračunati koliko su bajtova u memoriji sve te varijable zajedno zauzele.

2. Napisati program koji definira tri varijable tipa znak. Prvoj dodijeliti znak 0, drugoj dodijeliti znak 9, a treću

izračunati kao sumu prve dvije. Ispisati sva tri znaka kao znak i kao ASCII vrijednosti.

3. Napisati program koji računa sumu, produkt, razliku i kvocijent dva cijela broja. Ispisati sve rezultate na ekran.

4. Napisati program koji računa sumu prvih 50 brojeva.

5. Napisati program koji na ekran ispisuje:

E E E E E

D D D D

C C C

B B

A

U programu je dozvoljeno koristiti najviše dvije printf() naredbe.

Page 11: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

8

Vježba 2.

Cilj ove vježbe je upoznavanje s naredbom selekcije "if" koja služi za uvjetno izvršavanje dijela koda. Provjera

uvjeta se skoro pa uvijek koristi u programima (gotovo je nemoguće zamislit program bez ijedne provjere nekog

uvjeta).

Razlikuje se:

1. uvjetna naredba: if

2. uvjetno grananje: if->else

3. višestruko grananje: if -> else if -> else if ->… -> else

switch -> case

Sintaksa if naredbe s primjerima je prikazana u tablici 2.1.

Sintaksa za if->else...if->else:

if (/*uvjet*/) { /* naredbe koje se izvršavaju ukoliko je uvjet zadovoljen */

}

else if (/*drugi uvjet*/) { /* naredbe ukoliko NE prođe prvi uvjet, a drugi bude zadovoljen */

} else { /* naredbe ukoliko nije zadovoljen ni prvi ni drugi uvjet */ }

Sintaksa za switch->case->..->default:

switch (X) //varijabla koja će se provjeravati { case const: /* umjesto const se piše konstanta s kojom će se usporediti varijabla X */ /* dio koda koji se izvodi ako je uvjet zadovoljen */ break; /* nakon što se odradi kod, prekida se switch. Ako nema break, program će nastaviti provjeriti ostale case-eve */ case... ... default: /* ako nije nijedan case ispunjen, odradit će se naredbe unutar default-a */ break; }

Tablica 2.1 Sintaksa if-a i switch-case

U tablici 2.2 su prikazana dva primjera za zadatka koji provjerava varijablu I. Lijevi primjer je s if a desni s

switch-case. Ako je I jednak 1 tada će nova vrijednost od I biti 20, ako I nije jednak 1 tada provjeri je li

Page 12: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

9

jednak 2 te ako je promijeni mu vrijednost u 20. U slučaju da nijedan uvjet nije ispunjen ne mijenja se vrijednost

od varijable I.

if -> else if -> else switch -> case

if (broj == 1) { broj = 20; } else if (broj == 2) { broj = 10; } else break;

switch (broj) { case 1: broj = 20; break; case 2: broj = 10; break; default: break; }

Tablica 2.2 Primjer zadatka s if...else-if & switch-case

Opis za if:

1. Ako je broj jednak 1 onda varijabli broj pridruži broj 20,

2. Ako je broj jednak 2 onda varijabli broj pridruži broj 10,

3. Ako ni to nije ispunjeno, odlazi na else. Zadnji else nema nikakav uvjet, pa će se izvršiti ako nisu

ispunjeni uvjeti prethodnih blokova.

Opis za switch: Provjerava se uvjet za varijablu I. Ukoliko nije udovoljen nijedan uvjet prelazi se na default

(koji je jednak kao i else).

1. Ako je broj jednak 1 onda pridruži varijabli broj broj 20,

2. Ako je broj jednak 2 onda pridruži varijabli broj broj 10,

3. Još ostaje default koji govori ono isto kao i else: ako broj nije bio ispunio prethodne uvjete onda

prekini s radom programa (break).

Kod switch-a nema provjere s logičkim operandima, niti je moguća usporedba dviju ili više varijabli. Moguća je

jedino usporedba varijable s konstantom. Unutar svakog case-a ili default-a, iza naredbi se nalazi break koji

prekida daljnje provjere. Taj break, koji određuje da se završi s bilo kakvom daljnjom provjerom, preskače sve

preostale case-eve pa i tako preskoči default. Ako ne postoji break na kraju case-a, tada će switch nastavit

s provjerom sljedećeg uvjeta, u ovom primjeru case 2.

Page 13: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

10

Ugniježđeni uvjeti:

Moguće je postavljati nove uvjete unutar uvjeta, tako da unutar jednog if naredbenog bloka može bit drugi if

naredbeni blok.

Primjer:

if(broj > 0 && broj < 50)

{

if (broj%2 == 0)

printf("Broj je izmedju 1 i 49, te je paran.\n");

else

printf("Broj je izmedju 1 i 49, te nije paran.\n");

}

ZADACI

1. Napisati program koji pretvara uneseni realni broj u cijeli na način da ako je prva znamenka iza

decimalne točke >= 5 zaokružuje se na prvi veći. Program mora raditi i za pozitivne i za negativne

brojeve.

2. Napisati program koji unosi 10 brojeva ali na ekran ispisuje samo neparne. Broj se ispisuje čim je unesen.

3. Napisati program koji unosi 10 brojeva i računa koliko ih je djeljivo s 3.

4. Napisati program koji unosi 10 znakova i računa koliko ih je uneseno:

a) malim slovima;

b) koliko ih je = H.

5. Napisati program koji unosi bodove kolokvija za 5 učenika (između 0 i 100) te računa koliko je učenika

prošlo (više od 50) i koliki je prosječni broj bodova.

Page 14: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

11

Vježba 3.

Kod programiranja se često javlja potreba da se određeni dio koda ponavlja više puta, s time da taj broj

ponavljanja nije unaprijed poznat. U takvom slučaju se koristi while ili do->while petlja. Razlika između ove

dvije petlje je u tome što while najprije provjerava je li uvjet zadovoljen, te onda kreće s izvršavanjem koda i

tako se vrti sve dok nije uvjet zadovoljen. Dok do->while petlja radi na način da se uvijek uđe jednom u petlju,

izvrši kod unutar petlje, pa tek nakon toga provjeri je li uvjet zadovoljen i ovisno o tome se ulazi u sljedeću

iteraciju ili se završava rad petlje. Kod obje vrste while petlji mora se obratiti pozornost da se negdje unutar

while petlje mijenja vrijednost varijable koja se provjerava u uvjetu, inače doći do realizacije beskonačne petlje

(primjeri obiju vrsta petlji se nalaze u tablici 3.1).

while primjeri: do->while primjeri:

int broj = 5; while (broj != 0) { printf("%d, ", broj); broj--; } //ispisuje: 5, 4, 3, 2, 1,

int broj = 5; do { printf("%d, ", broj); broj--; } while(broj!= 0); //ispisuje: 5, 4, 3, 2, 1,

int broj = -5; while(broj != 0) { printf("%d, ", broj); broj++; } //ispisuje: -5, -4, -3, -2, -1,

int broj = -5; do { printf("%d, ", broj); broj++; }while(I != 0); //ispisuje: -5, -4, -3, -2, -1,

Tablica 3.1 Primjeri while i do while petlji

Sljedeća while petlja prikazana u tablici 3.1 ne ispisuje ništa, jer uvjet mora biti različit od nule (true).

int broj = 0; while(broj) { printf("%d, ", broj); broj--; }

Tablica 3.2 Uvjet while petlje

Da se na početku inicijalizira broj = 3, petlja bi se izvršila tri puta jer sve što je različito od nule, pa i negativni

brojevi, u uvjetu se tretira kao istina.

Naredbe za upravljanje petljama

Postoje dvije naredbe koje se mogu koristiti unutar programa, a služe za prekid petlje (break) ili za direktan skok

u sljedeću iteraciju petlje (continue).

Page 15: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

12

Generiranje slučajnih brojeva

Da bi računalo nasumično generiralo brojeve, koristi se rand()funkcija definirana u zaglavlju <stdlib.h>.

Međutim ako se koristi samo funkcija rand() ona će uvijek generirati iste slučajne brojeve zbog čega se

najčešće koristi u kombinaciji s srand(). Funkcija srand() mijenja brojevnu bazu iz koje se generiraju brojevi,

pa su brojevi generirani pomoću funkcije rand() zbilja slučajni. Primjer generiranja slučajnih brojeva je prikazan

u tablici 3.3.

int broj = 5; srand((unsigned)time(NULL)); broj = rand();

U ovom primjeru, srand() uzima trenutno vrijeme te na osnovu njega generira bazu od koje će krenuti generiranje slučajnih brojeva. Funkcija time(NULL) vraća trenutno vrijeme u UNIX/POSIX obliku, koje računa ukupan broj sekundi koje su prošle od 1.1.1970 (Koordinirano svjetsko vrijeme – UTC).

int i = 0, randBr = 0, min = 11, max = 100; srand((unsigned)time(NULL)); for(i=0; i<25; i++) { randBr = rand() % (max - min) + min; printf("%d, ", randBr ); }

Ovakav princip se koristi ako se želi generirat 25 brojeva koji se nalaze u nekom rasponu, od 11 do 100 (uključujući 11 ali ne i 100). U gornjoj for petlji će se ispisati sve brojeve od 11 do 100, uključujući 11 ali ne uključujući broj 100.

Jednadžba koja ispisuje sve u rasponu od 11 do 100, uključujući 11 i 100:

randBr = (min + rand() / (RAND_MAX / (max - min + 1) + 1) );

Tablica 3.3 Generiranje slučajnih brojeva

Za one koji žele znati više: RAND_MAX je definiran u <stdlib.h> te mu je vrijednost ovisna o standardnim

bibliotekama različitih platformi. Najmanja garantirana vrijednost može biti 32767.

ZADACI

1. Napisati program koji računa aritmetičku sumu brojeva. Nije unaprijed poznato koliko će se brojeva unijeti,

program prestaje s radom kad se unese 0, ali nju ne treba računati za prosjek.

2. Napisati program koji uneseni cijeli broj razbija na dekadske znamenke. Potrebno je ispisati svaku znamenku

posebno i to u obrnutom redoslijedu. Npr. broj 4893 je potrebno ispisati kao 3 9 8 4

3. Napisati program koji generira slučajni broj i korisnik pogađa o kojem se broju radi. Program svaki put treba

javiti je li uneseni broj > ili < od generiranog. Pogađanje traje sve dok se broj ne pogodi. Potrebno je ispisati iz

kojeg je puta broj pogođen.

4. Napisati program koji ispisuje sve primitivne brojeve od 0 – 100.

Page 16: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

13

Vježba 4.

Niz je imenovana i numerirana kolekcija istovrsnih objekata koji se nazivaju elementi niza. Elementi niza mogu

biti prosti skalarni tipovi i korisnički definirani tipovi podataka. Označavaju se imenom niza i cjelobrojnom

izrazom – indeksom – koji označava poziciju elementa u nizu. Indeks niza se zapisuje u uglatim zagradama iza

imena niza. Primjerice, x[3] označava element niza x indeksa 3.

Sintaksa deklaracije elementa jednodimenzionalnog niza je:

Tip_podatka ime_Niza [ brojElemenata ];

Prvi element niza ima indeks 0, a n-ti element ima indeks n-1. Prema tome, x[3] označava četvrti element niza. S

elementima niza se manipulira kao s običnim skalarnim varijablama, uz uvjet da je prethodno deklariran tip

elemenata niza. Primjerice, deklaracijom:

int A[10];

definira se A kao niz od 10 elementa tipa int.

Inicijalizacija nizova

Za globalno i statički deklarirane nizove automatski se svi elementi postavljaju na vrijednost nula. Kod lokalno

deklariranih nizova ne vrši se inicijalizacija početnih vrijednosti elemenata niza. To mora obaviti programer. Za

inicijalizaciju elemenata niza na neku vrijednost često se koristi for petlja, primjerice kod:

for (int i = 0; i < 10; i++)

A[i] = 1;

sve elemente niza A postavlja na vrijednost 1.

Niz se može inicijalizirati listom konstanti, napisanom unutar vitičastih zagrada, koje redom određuje početnu

vrijednost elemenata niza.

int A[10]= {1,2,23,4,32,5,7,9,6};

Ako se inicijaliziraju svi potrebni elementi niza, tada nije nužno u deklaraciji navesti dimenziju niza već to obavlja

sam prevodilac.

int A[]= {1,2,23,4,32,5,7,9,6,3};

Ovaj izraz je potpuno ekvivalentan prethodnoj deklaraciji.

Niz se može i parcijalno inicijalizirati. U deklaraciji int A[10]= {1,2,23}; prva tri elementa imaju vrijednost

1, 2 i 23, a ostale elemente prevodilac postavlja na vrijednost nula.

Page 17: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

14

ZADACI

1. Napisati program koji s tastature unosi dva cijela broja i matematičku operaciju (+, -, * ili /). Ovisno o operaciji

je potrebno izračunati i ispisati rezultat. 2. Napisati program koji unosi 20 rezultata ocjena s kolokvija (sprema ih u niz). Ocjene mogu biti od 1-5 i ako se

unese krivi broj unos se ponavlja. Kada su ocjene unesene program računa histogram ocjena u 5 grupa (koliko je

bilo kojih ocjena) i ispisuje ga na ekran.

3. Napisati program koji za uneseni niz od 10 cijelih brojeva:

a) traži najmanji element niza;

b) traži najveći element niza;

c) sortira niz od najmanjeg prema najvećem elementu.

Napomena: najmanji i najveći element niza se ne smiju samo ispisati nakon sortiranja. Potrebno ih je pronaći

prije sortiranja.

Page 18: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

15

Vježba 5.

U C-u ne postoji varijabla tipa string koja sprema tekst, nego se koristi niz znakova char varijable. Deklaracija i

inicijalizacija je moguća na više načina, a specifikator formata za ispis i unos je %s. Pošto se radi o nizu znakova,

potrebno je na kraju svakog stringa imati '\0' koji označava kraj stringa, inače će najvjerojatnije doći do rušenja

programa ili ispisa nepoželjnih znakova.

char znakovi1[] = "test" ;

char znakovi2[] = {'t', 'e', 's', 't', '\0'};

char znakovi3[5] = {0};

scanf(" %s", znakovi3);

printf("%s\n", znakovi1);

printf("%s\n", znakovi2);

printf("%s\n", znakovi3);

Prva deklaracija i inicijalizacija automatski određuje veličinu niza i na kraj niza dodaje '\0', dok je kod drugog

načina potrebno ručno dodati '\0'. Kod trećeg načina se kreira niz s 5 elemenata, kod kojeg svaki element ima

ASCII vrijednost -52, što je znak s brojem 204 iz proširene ASCII tablice. Tek nakon scanf() mijenja se vrijednost

var. znakovi3 s onim što se unese s tastature te se na kraju unesenog stringa automatski doda '\0'. Pri tome se

unos u niz znakova radi bez korištenja adresnog operatora &. Razlog tome je što varijabla znakovi3 pokazuje na

adresu početka niza.

Napomena: U ostatku teksta koristiti će se naziv "string" umjesto "niz znakova".

Unos stringa s tastature

Stringove je moguće unijeti na sljedeće načine:

scanf(" %s", tekst);

gets(tekst);

Obratite pozornost na razliku između korištenja razmaka u scanf i bez korištenja razmaka:

/*prvi slucaj s razmakom*/ int broj = 0; char tekst[50] = {0}; scanf("%d ", &broj); //ima razmak! gets(tekst); printf("%d\n", broj); printf("%s\n", tekst);

/*drugi slucaj bez razmaka*/ int broj = 0; char tekst[50] = {0}; scanf("%d", &broj); //nema razmak! gets(tekst); printf("%d\n", broj); printf("%s\n", tekst);

Nakon unosa „123“ pa „abc“ se ispisuje:

123 abc

Nakon unosa „123“ odmah se ispisuje:

123

Tablica 5.1 Primjeri unosa s razmakom i bez razmaka

Page 19: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

16

Ako se u oba slučaja unese „123“ pa pritisne enter, u prvom slučaju će biti moguće unijeti neku vrijednost u

varijablu tekst, dok će u drugom slučaju „preskočiti“ unos u tekst te će odmah ispisati vrijednost varijable tekst

koja je samo nova linija (enter).

U ostatku teksta će se spomenuti samo nekoliko važnijih funkcija za rad za stringovima. One su ugrađene u

datoteci zaglavlja <string.h>, za detalje kako koja radi mogu se pogledi primjeri s prezentacija, potražit primjere

na internetu ili u Pomoći (CTRL+F1) Visual Studia (ili nekog drugog razvojnog okruženja).

Neke važnije funkcije unutar <string.h>

1) strlen(znakovi1);

Funkcija strlen() vraća dužinu stringa znakovi1. Dužinu računa od prvog elementa do '\0' (koji se ne računa).

Budući da funkcija vraća neku vrijednost, poželjno je da se ta vrijednost ispiše ili spremi u neku varijablu jer je

puno efikasnije pristupati varijabli nego pozivati funkciju.

char neki_string[] = "abcdefg987" ;

x = strlen(neki_string);

printf("Duzina stringa neki_string je: %d \n" , x);

ili:

printf("Duzina stringa neki_string je: %d \n" , strlen(neki_string));

ISPIS:

Duzina stringa neki_string je: 10

2) strcpy(destinacija, izvor);

Funkcija strcpy() uzima sve znakove iz jednog stringa te ih sprema u novi (uključujući i '\0'). Lijevi argument je

odredišna varijabla u koju se kopira string, a desna je izvorišna iz koje će se uzimati svi elementi.

3) strcmp(prvi_string, drugi_string);

Funkcija strcmp() uspoređuje dva stringa te vraća:

- 0 ako su oba stringa identična

- pozitivni broj ako je prvi_string „veći“ od drugi_string („veći“ – ASCII vrijednost prvog različitog slova je

veća u prvi_string nego u drugi_string)

- negativni broj ako je prvi_string „manji“ od drugi_string („manji“ – ASCII vrijednost prvog različitog slova

je manja u prvi_string nego u drugi_string)

Funkcija strcmpi() radi na sličan način, ali ne razlikuje velika i mala slova, što znači da će vratiti 0 za usporedbu

stringova „abcd“ i „ABCD“.

Page 20: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

17

Još neke funkcije iz <string.h>.

strlwr Pretvara sva slova iz stringa u mala slova

strupr Pretvara sva slova iz stringa u velika slova

strrev Obrće znakove u stringu (npr.: “abcde“ pretvara u “edcba“)

strchr Pronalazi prvo pojavljivanje određenog znaka u stringu

strrchr Pronalazi zadnje pojavljivanje određenog znaka u stringu

strncat Dodaje određeni broj znakova iz jednog stringa u na kraj drugog stringa.

strncmp Uspoređuje n znakova od dva stringa, povratna vrijednost je ista kao kod strcmp.

Tablica 5.2 funkcije iz zaglavlja string.h

Funkcije za unos znaka s tastature

Deklarirane su u zaglavlju <conio.h>.

getch() – uzima jedan znak s tastature, ali ga ne prikazuje na ekranu (ako koristite putty, onda vam je ovo

poznato kod unosa šifre).

getche() – uzima jedan znak s tastature te ga odmah i prikaže na ekranu.

getchar() – uzima jedan znak s tastature - bez obzira koliko se unese, isto kao i gore navedena

funkcija getche() prikaže unos, ali "čeka" dok se pritisne enter nakon čega program nastavlja s radom. Obje

funkcije uzimaju znak odmah prilikom unosa.

Primjer:

char a, b, c;

a = getch();

b = getche();

c = getchar();

printf("%c %c %c \n", a,b,c);

Tijekom unosa “abcde“ na konzolnom prozoru će se prikazati “bcde“, a funkcija printf će ispisati: “a b c“.

Tablica 5.3. prikazuje još neke od funkcija za rad sa znakovima. Kod svake od ovih funkcija vrijedi pravilo da vraća

vrijednost 0 ako uvjet nije zadovoljen, a broj različit od 0 ako je uvjet zadovoljen. Primjeri s ovim funkcijama su

prikazani u tablici 5.4.

Funkcije za rad s znakovima: isalnum – testira je li neki znak dekadska znamenka ili slovo. isalpha – testira je li neki znak slovo. islower – testira je li znak malo slovo. isupper – testira je li znak veliko slovo. isdigit – testira je li neki znak dekadska znamenka ili slovo. isascii – testira je li znak definiran u ASCII tablici. toascii – vraća ASCII vrijednost nekog znaka tolower – vraća ASCII vrijednost malog slova za zadano slovo toupper – vraća ASCII vrijednost velikog slova za zadano slovo

Tablica 5.3 Funkcije iz zaglavlja ctype.h

Page 21: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

18

Primjer: Ispisuje:

char a = 'a', b = 'B', c = '1', d = 'f';

printf("isalnum 'a': %d \n", isalnum(a)); printf("isalpha 'B': %d \n", isalpha(b)); printf("isnum '1': %d \n", isdigit(c)); printf("isupper 'f': %d \n", isupper(d));

isalnum 'a': 2

isalpha 'B': 1

isnum '1': 4

isupper 'f': 0

Tablica 5.4 Primjeri ispisa

Pretvaranje tipova podataka

Za pretvorbu jednog tipa podataka u drugi mogu se koristiti sljedeće funkcije:

atof() – pretvara niz znakova (ascii) u realan broj;

atoi() – pretvara niz znakova (ascii) u cijeli broj;

itoa() – pretvara cijeli broj u niz znakova.

Deklaracije funkcija:

double atof(const char *string);

int atoi(const char *string);

char *itoa(int x, char *string, int baza);

string - adresa niza znakova u koji se spremaju znamenke broja

x - broj koji se pretvara u string

baza - brojevna baza (heksadecimalno: 16; decimalno: 10;…) po kojoj se vrši pretvorba (u opsegu od 2-36) povratna vrijednost je pokazivač na string.

Primjer:

char tekst[] = "12ab34cd56";

int broj;

broj = atoi(tekst);

printf("Tekst pretvoren u broj: %d \n" , broj);

Ispisuje:

Tekst pretvoren u broj: 12

Page 22: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

19

ZADACI

1. Napravi program koji uzima znakove s tastature (sa ili bez prikaza tih znakova na ekranu) sve dok se ne unese

znak ESC. Tada se izlazi iz programa.

2. Napravit program koji iz unesenog stringa stvara novi (u novoj varijabli), na način da iz prvog prebaci sve

znakove osim brojeva.

3. Napraviti program koji uneseni string mijenja u 3 koraka i rezultat svakog ispisati. Smije se koristiti samo jedan

string.

a) U stringu trebaju ostati samo slova.

b) Iz tog stringa treba izbaciti sve samoglasnike (velika i mala slova).

c) Sva velika slova pretvoriti u mala i obrnuto.

4. Napravi program koji unesenu dekadsku vrijednost pretvara u heksadecimalnu, s tim da je znamenke potrebno

ispisati svaku u svom redu i to u pravom rasporedu.

Page 23: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

20

Vježba 6.

Višedimenzionalnim nizovima se pristupa preko dva ili više indeksa. Primjerice,deklaracijom int x[3][4]; definira

se dvodimenzionalni niz koji ima 3 x 4 = 12 elemenata. Deklaraciju se može čitati i ovako: definirana su 3 niza od

kojih svaki ima po 4 integer elementa. Dvodimenzionalni nizovi se često koriste za rad s matricama. U tom

slučaju nije potrebno razmišljati o tome kako je niz složen u memoriji, jer se elementima pristupa preko dva

indeksa: prvi je oznaka retka, a drugi je oznaka stupca matrice.

Matrični prikaz niza je:

x[0][0] x[0][1] x[0][2] x[0][3]

x[1][0] x[1][1] x[1][2] x[1][3]

x[2][0] x[2][1] x[2][2] x[2][3]

Memorijski raspored elemenata dvodimenzionalnog niza, koji opisuju neku matricu, je takvi da su elementi

složeni po redovima matrice; najprije prvi redak, zatim drugi, itd. Višedimenzionalni niz se može inicijalizirani već

u samoj deklaraciji, primjerom:

int x[3][4] = {{1, 21, 14, 8},{12, 7, 41, 2},{1, 2, 4, 3}};

Navođenje unutarnjih vitičastih zagrada je opcijski, pa se može pisati i sljedeća deklaracija:

int x[3][4] = {1, 21, 14, 8, 12, 7, 41, 2, 1, 2, 4, 3};

Ovaj drugi način inicijalizacije se ne preporučuje, jer je teže uočiti raspored elemenata.

ZADACI

1. Napisati program koji unosi jednu matricu (A dimenzija 3x3) i iz te matrice računa matricu B = 5*A. Matricu B

je potrebno ispisati.

2. Napisati program koji unosi jednu matricu (A dimenzija 3x3) i iz te matrice stvara matricu B = AT. Matricu B je

potrebno ispisati.

3. Napisati program koji unosi dvije matrice (A i B dimenzija 3x3), a zatim računa matricu C = A + B i matricu D =

A * B. Matrice C i D je potrebno ispisati.

4. Napisati program koji unosi 5 imena i zatim:

a) pronalazi indeks imena prvog po abecedi, te ispisuje indeks i ime;

b) pronalazi indeks imena zadnjeg po abecedi, te ispisuje indeks i ime;

c) sortira imena po abecedi i ispisuje ih.

Pri tome rezultati pretraživanja ne smiju razlikovati velika i mala slova, tj. bez obzira je li ime uneseno velikim ili

malim slovom treba biti na ispravnom mjestu po abecedi.

Page 24: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

21

Vježba 7.

U C-u varijabla može biti deklarirana na globalnoj i lokalnoj razini. Razlika između ove dvije razine je to što je

globalna varijabla dostupna "cijelom programu" tj. svim funkcijama, a lokalna samo u funkciji ili petlji u kojem je

deklarirana. Primjer deklaracije varijabli na globalnoj i lokalnoj razini nalazi se u tablici 7.1.

GLOBALNA LOKALNA

#include <stdio.h>

int x = 11; //Globalna varijabla

int main(void) { printf("x je jednak: %d\n", x); return 0; }

#include <stdio.h>

int main(void) { int i = 5;

for(int j = i; j > 0; j--) printf("j je: %d\n", j );

printf("i je: %d \n", i); printf("konacni j je: %d", j); return 0; }

Tablica 7.1 Deklaracija varijabli na globalnoj i lokalnoj razini

U gornjem primjeru za deklariranje lokalne varijable, varijabla 'i' je lokalna i dostupna samo unutar main-a, dok

je varijabla 'j' vidljiva samo unutar for petlje pa će prevodilac javiti grešku "undeclared identifier" za zadnji printf.

Varijable unutar funkcije se brišu nakon što funkcija završi s radom, te se opet kreiraju pri ponovnom pozivanju

funkcije. Funkcije se najčešće koriste za određenu radnju koja se često koristi, pa se ne mora iznova pisati nego

samo pozvati.

Funkcija se kreira u tri koraka:

1. Deklaracija – ime funkcije, broj i tip argumenata koji se prosljeđuju u funkciju te povratna vrijednost

funkcije.

2. Definicija funkcije - uz ime, argumente i povratnu vrijednost sadrži kod s naredbama.

3. Poziv funkcije - mjesto u kodu gdje se poziva funkcija.

Page 25: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

22

DIO KODA OPIS

#include <stdio.h>

int pravokut(int, int);

Deklaracija funkcije ‘pravokut’ iznad main-a.

int main(void) { int kv = 0, x = 2, y = 3; kv = pravokut(x, y); printf("x*y je: %d \n", kv); return 0; }

Varijabla ‘kv’ prima povratnu vrijednost funkcije.

Ispisuje se: x*y je: 6

int pravokut(int a, int b) { return a * b; }

Definicija funkcije povratnog tipa integer, prima argumente tipa integer i vraća njihov umnožak.

Takav pristup je posebno važan ukoliko funkcija poziva druge funkcije. Kad se ne bi kod pisao na ovaj način,

trebalo bi se voditi računa o rasporedu funkcija u kodu. Poželjno je da se najprije deklariraju funkcije, te se iza

main funkcije napišu njihove definicije . Postoje funkcije koje mogu vratiti vrijednost (int, double, char, itd.),

te one koje ne vraćaju vrijednost (void). Ukoliko funkcija vraća vrijednost, potrebno je tu vrijednost vratiti

naredbom return. Na mjestu gdje je return funkcija se prekida, a sav kod koji se eventualno nalazi iza

return neće izvršiti.

Ukoliko je funkcija void tada se poziva na sljedeći način:

ime_funkcije(arg1, arg2);

Ukoliko funkcija vraća vrijednost rada tada se vrijednost može ili spremiti u varijablu ili direktno koristiti:

x = ime_funkcije(arg1, arg2); //spremanje vrijednosti u varijablu

printf("%[neki format ispisa]", ime_funkcije(arg1, arg2)); /*direktno

korištenje vrijednosti za ispis */

Nakon što se izađe iz funkcije sve lokalne varijable se brišu. Tako da kada se ponovo uđe u funkciju, varijable

poprimaju početne vrijednosti. Ukoliko je potrebno da varijabla sadrži svoju vrijednost i nakon što izađe iz

funkcije, to se može napraviti korištenjem ključne riječi static. Ona omogućuje da kada se opet pozove

funkcija zadržava prethodnu vrijednost.

static int x = 0;

Osim static postoji i ključna riječ const koja se koristi za deklaraciju konstanti.

const broj = 123;

Page 26: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

23

Neke funkcije iz zaglavlja <math.h> Datoteka zaglavlja <math.h> sadrži matematičke funkcije, kao npr.: potenciranje, korjenovanje, logaritmi, trigonometrija, itd. Neke od najčešće korištenih su definirane funkcije:

double exp(double X); //koristi se za računanje eX

double sqrt(double X); //koristi se za računanje √𝑋 double pow(double X, double Y); //koristi se za računanje XY

Kao što se može vidjeti, u zagradama se šalju vrijednosti koje su tipa različitog od int. Zbog toga, u slučaju da je X varijabla tipa int, potrebno je koristiti cast operator, npr.:(double)X, pa će poziv jednoj od gornjih funkcija izgledati ovako:

sqrt((double)varijabla); Također ne smije se zaboraviti da svaka od matematičkih funkcija ima povratnu vrijednost, pa tu vrijednost treba negdje spremiti ili ispisati. Pri tome treba voditi računa o tipu argumenta i povratnoj vrijednosti.

double rezultat = 0; int parametar = 25; rezultat = sqrt((double)parametar);

Povratna vrijednost je tipa double pa se mora spremiti u varijablu istog tipa.

ZADACI

1.Napisati program koji unese 3 broja i zatim po želji korisnika (ovisno o tome koje se slovo unese) računa:

a) 𝑟𝑒𝑧 = 𝑥 + 𝑦 + 𝑧 b) 𝑟𝑒𝑧 = 𝑥 ∗ 𝑦 ∗ 𝑧 c) 𝑟𝑒𝑧 = 𝑥 ÷ 𝑦 + 𝑧

d) 𝑟𝑒𝑧 = √𝑥 ÷ 𝑦 − 𝑧

Svi rezultati se računaju preko f-ija (jedna za svaki primjer), s tim da je za primjer pod “d” potrebno provjeriti je li izraz ispod korijena >= 0, i ako nije treba javiti grešku. 2. Napisati program koji sadrži dvije varijable: globalnu varijablu X i lokalnu varijablu Y(lokalna za f-ju main) i dodijeliti im neke vrijednosti. Iz glavnog programa treba pozvati f-ju koja ispisuje vrijednosti obije varijable.

3. Napraviti program koji u “običnoj” f-ji računa faktorijele. Rezultat je potrebno ispisati u glavnom programu i nije dozvoljeno korištenje globalnih varijabli.

4. Napisati f-ju kojom se približno određuje vrijednost ex (e = 2.718282), i rezultat usporediti s vrijednošću koja se dobije pomoću standardne funkcije exp() deklarirane u math.h. U rješavanju problema koristiti razvoj u red:

𝑒𝑥 = 1 + 𝑥

1!+

𝑥2

2!+

𝑥3

3!+

𝑥4

4!…

Npr. za x = 5, ispisati izračunate rezultate za 5, 10 i 50 ponavljanja. Zašto se program ponaša "čudno" za 50

ponavljanja?

Page 27: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

24

Vježba 8.

U programiranju i matematici često se koriste rekurzivne funkcije. Direktna rekurzija nastaje kada se u definiciji

funkcije poziva ta ista funkcija, a indirektna rekurzija nastaje kada jedna funkcija poziva drugu funkciju, a ova

ponovo poziva funkciju iz koje je pozvana. Definicija rekurzivne funkcije u pravilu se sastoji od dva dijela:

temeljnog slučaja i pravila rekurzije. Jedan od najčešćih problema koji se koristi za opis rekurzivne funkcije su

faktorijeli. Pri rješavanju problema pomoću rekurzivne funkcije treba voditi računa o dvije stvari:

1. Prvo treba provjerit temeljni slučaj rekurzije.

2. Odradi pravilo rekurzivnog poziva.

unsigned int my_fact(unsigned int x)

{

if(x < 2) // Temeljni slučaj za brojeve manje od 2

return 1; // jer je: 0! == 1! == 1

else

return x * my_fact(x-1); /* Pravilo rekurzivnog poziva pr.: 3! =

3 * 2! */

}

1. Pozivanja rekurzije

my_fact(3); { return 3 * my_fact(2); { return 2 * my_fact(1); { return 1; //x je manji od 2 } } } 2. Vraćanje iznosa

//1. POVRAT

my_fact(3); { return 3 * my_fact(2); { return 2 * 1; //vracena jedinica i množi se s 2. } }

//2. POVRAT

my_fact(3); { return 3 * 2; //vraća iznos 6 u glavni program }

Tablica 8.1 Simulacija rada rekurzivne funkcije faktorijela za izračun 3!.

Page 28: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

25

ZADACI

1. Napisati program koji traži je li neki broj element niza. U programu treba napraviti f-ju traži koja uzima tri

argumenta (niz, broj elemenata niza i vrijednost koja se traži), a treba vratiti 1 ako broj postoji ili 0 ako broj ne

postoji.

2. Napisati program koji računa produkt svih elemenata matrice dimenzija 3x3. Program ne smije sadržavati ni

jednu globalnu varijablu, unos i proračun napraviti u odvojenim funkcijama.

3. Napisati program koji sadrži f-je my_strlen i my_strcpy, koje rade isto što i f-je strlen i strcpy. Ispravnost

funkcija provjeriti usporedbom sa stvarnim f-jama strlen i strcpy.

4. Napisati program koji pomoću rekurzivne f-je računa faktorijele.

5. Napisati program koji korištenjem rekurzivnih funkcija traži minimalni, odnosno maksimalni element niza

brojeva.

6. Napraviti program koji uneseni dekadski broj pretvara u binarni, oktalni ili heksadecimalni. Dekadski broj, kao i

brojevna baza (2, 8, 16) u koju se radi pretvorba se unose u programu, a pretvorbu je potrebno realizirati pomoću

rekurzivne f-je. Rezultat se ispisuje u mainu.

Page 29: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

26

Vježba 9.

Struktura je skup jedne ili više varijabli, grupiranih zajedno pod jednim imenom radi lakšeg rukovanja. Varijable

strukture su članovi ili polja strukture koje definira korisnik. Kao i ostale varijable, strukture mogu biti povratna

vrijednost neke funkcije. U daljnjem tekstu će se koristit prvo veliko slovo za ime strukture, dok se u programu

mogu, kao i kod običnih varijabli, koristiti drugi načini imenovanja.

struct Osoba {

int dan, mjesec, godina, niz[10];

char ime[15], prezime[15], spol;

};

Potrebno je naglasiti da se nakon zatvarajuće vitičaste zagrade stavlja točka-zarez. Definiranjem strukture se ne

kreira nova varijabla, niti se rezervira prostor u memoriji. Tek kada se deklariraju varijable tipa neke strukture

rezervira se prostor u memoriji. Primjer s gornjom strukturom:

struct Osoba Marko; /* U memoriji je rezervirano mjesto za varijablu tipa struct Osoba, a varijabla se zove Marko */

Pristup pojedinim elementima strukture se vrši pomoću točka operatora:

scanf(" %d", &Marko.dan);

printf("%d\n", Marko.dan);

Kod deklaracije strukture moguće je odmah deklarirati i varijable tipa te strukture, tako da se nakon zagrade

napišu varijable:

struct Osoba {

int dan, mjesec, godina;

char ime[15], prezime[15], spol;

} Marko, Ana, Petra, Josip; /* Može se deklarirati, ali nije preporučljivo.

Nije dozvoljena deklaracija globalnih varijabli i korištenje istih na kolegiju! */

Strukture se mogu deklarirati unutar neke funkcije (npr. main) ili pak izvan funkcija, razlika je u tome što u prvom

slučaju deklarirana struktura nije vidljiva ostalim funkcijama (sjetiti se dijela o lokalnim i globalnim varijablama!).

Page 30: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

27

Niz struktura

struct Osoba nizOsoba[10];

Kreiran je niz od 10 varijabli tipa strukture Osoba. Pristup pojedinoj varijabli se vrši na sljedeći način npr.:

nizOsoba[2].dan //Pristupa se trećem elementu niza i to varijabli 'dan'.

Struktura unutar strukture

Definiranje strukture ‘Motor’ Def. strukture ‘Motor’ unutar strukture ‘Auto’.

struct Motor { int kubik, snagaKw; };

struct Auto { int godina; char proizvodac[15], model[15]; struct Motor motorizacija; };

//Deklaracija i pristupanje motoru

struct Auto Lancia; Lancia.Motor.snagaKw = 1750;

Tablica 9.1 Primjeri definicija struktura

ZADACI

1. Napisati program koji unosi dva proizvoljna vremena (sat, minute, sekunde) i zbraja ih. Za pohranu

vremena koristiti strukturu, a zbrajanje i ispis napraviti u odvojenim funkcijama.

2. Napisati program koji za uneseni datum računa koji je datum bio dan prije i koji će datum biti dan poslije.

Za pohranu datuma koristiti strukturu datum (dan, mjesec, godina). Proračun i ispis dana prije/poslije

napraviti u funkciji dan_prije / dan_poslije.

3. Napisati program koji unosi podatke o 5 osoba (ime, prezime, datum i sat rođenja). U programu napraviti

funkciju koja pronalazi najstariju osobu, te funkciju koja pronalazi osobu prvu po abecedi.

Page 31: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

28

Vježba 10. Jedan od glavnih razloga zbog čega se C jezik smatra jezikom niske razine je taj što omogućuje indirektno

manipuliranje s podacima i izvršenjem programa. Kako bi se pristupilo adresi varijabli koriste se posebni

operatori - adresni operator & i operator indirekcije *, te specijalni tip varijabli koje se nazivaju pokazivačke

varijable ili pokazivači (engl. pointer).

Adresni operator &

Adresa varijable se može odrediti pomoću posebnog operatora & koji se naziva adresni operator. Koristi se kao

unarni operator koji se zapisuje ispred imena varijable.

#include <stdio.h> int main(void) { int y = 777; printf("\n Vrijednost y je %d", y); printf("\n Adresa y je %#p", &y); //# je za ispisivanje u heks. obliku return 0; }

Ispis programa može izgledati ovako:

Vrijednost y je 777

Adresa y je 0x0063FDF4

Tablica 10.1 Korištenje adresnog operatora

Ispis adrese je izvršen u heksadecimalnom obliku s osam znamenki, jer je korišteno 32-bitno računalo na kojem

je adresa određena 32-bitnim kardinalnim brojem. Napomena: pri sljedećem izvršavanju programa ispis adrese

ne mora biti isti jer operacijski sustav ne učitava program uvijek na isto mjesto u memoriji (time se mijenja i

adresa na kojoj se nalazi varijabla x).

Pokazivači

Varijable kojima je vrijednost adresa neke druge varijable ili funkcije nazivaju se pokazivači ili pointeri. Vrlo je

važno definirati na koji tip varijable pokazuje jer C prevoditelj mora znati kakav će tip podatka biti na adresi koju

oni sadrže.

Deklaracija pokazivača vrši se slično deklaraciji varijable, s razlikom što ispred imena varijable (imena pokazivača)

obvezno zapisuje znak indirekcije '*'. Primjerice,

int *p = NULL; /* p je pokazivac na objekt tipa int */

unsigned *q = NULL; /* q je pokazivac na objekt tipa unsigned */

Ovim deklaracijama definirane su dvije pokazivačke varijable. Njihova vrijednost je neodređena, jer im nije

pridijeljena adresa neke varijable. Važno je znati da pokazivače prije upotrebe treba inicijalizirati, odnosno mora

im se pridijeliti vrijednost adrese postojeće varijable. Pri tome, tip pokazivača mora biti jednak tipu varijable. To

se ostvaruje adresnim operatorom '&'.

int suma = 777; /* deklaracija i inicijalizacija varijable suma */

int *p = NULL; /* deklaracija pokazivaca na objekt tipa int */

p = &suma; /* p inicijaliziran na adresu varijable suma */

Page 32: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

29

Pokazivač ‘p’ je inicijaliziran da pokazuje na varijablu ‘suma’. Daljnje korištenje

printf("%d", suma);

printf("%d", *p);

daje isti ispis, jer se indirekcijom pokazivača dobiva vrijednost na koju on pokazuje, a to je vrijednost varijable

suma.

ZADACI

1. Napisati program koji prvo unosi, a zatim ispisuje elemente nekog polja brojeva i polja znakova zajedno s

adresom svakog elementa. Sve unose i ispise je potrebno napraviti preko pokazivača i ne smiju se koristiti [].

2. Napisati program koji u jednoj funkciji računa sumu, produkt i razliku dva broja, a svi se rezultati ispisuju u

glavnom programu.

3. Zadatak s računanjem dana prije i poslije riješiti preko funkcija na način da se sva tri datuma deklariraju u

mainu, a unos, i proračun dana prije i poslije u f-ji. Rezultate je potrebno ispisati u mainu, a ne u funkciji.

4. Napisati program koji za zadani string traži koliko se puta podstring pojavljuje u stringu. Podstring je potrebno

unijeti u f-ji. F-ja za pretraživanje treba vratiti broj ponavljanja. U funkciji za pretraživanje se može koristiti f-ja

strncmp iz string.h.

Page 33: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

30

Vježba 11. U standardnoj biblioteci <stdlib.h> implementiran je niz funkcija koje se koriste za sve ulazno izlazne

operacije: unos s tipkovnice, ispis na ekran te čitanje i pisanje informacija koje se pohranjuju na magnetskim i

optičkim medijima. Komuniciranje s uređajima koji obavljaju ove operacije vrši se sekvencijalno bajt po bajt, a

programski mehanizam kojim se vrši ovakvi prijenos informacije naziva se tok (engl. stream). U jednom se

programu može raditi s više tokova. Svakom toku se pridjeljuje jedna struktura podataka imena FILE, koja je

definirana u <stdio.h>. Temeljna namjena te strukture je da služi kao memorijski ulazno/izlazni

međuspremnik (engl. I/O buffer) pri prijenosu podataka.

Tokovi se dijele u četiri grupe:

• standardni ulaz (vrši unos znakova s tipkovnice),

• standardni izlaz (vrši ispis na ekran),

• standardna dojava greške (obično se vrši ispis na ekran),

• datotečni tok (vrši čitanje ili pisanje podataka u datoteku).

1. Funkcije fopen() i fopen_s()

Da bi se moglo koristiti neku datoteku potrebno je od operacijskog sustava zatražiti dozvolu pristupa toj

datoteci. Taj proces se zove otvaranje datoteke. Isto tako se za kreiranje nove datoteke mora zatražiti dozvola od

operacijskog sustava. Tu funkciju obavlja standardna funkcija fopen(). Ona pored komunikacije s operacijskim

sustavom kreira datotečni tok koji sadrži memorijski međuspremnik za efikasno čitanje ili spremanje podataka

na disk.

Prototip funkcije fopen() je:

FILE *fopen(const char *ime_datoteke, const char *mod);

Može se koristiti i ‘sigurna’ verzija fopen_s()

errno_t fopen_s(FILE **fp, const char *ime_datoteke, const char *mod);

koja vraća poruku o grešci u strukturu tipa errno_t umjesto vrijednosti NULL ukoliko dođe do greške otvaranja datoteke. Modovi otvaranja datoteke su opisani u tablici 11.1.

Mod Opis

"r" Otvori datoteku za čitanje, ako datoteka ne postoji fopen() vraća NULL.

"w" Otvori datoteku za pisanje, ako ne postoji datoteka zadanog imena, kreira se nova.

"a" Otvori datoteku za dopunu sadržaja, ako ne postoji datoteka zadanog imena, kreira se nova.

"r+" Otvori datoteku za čitanje i pisanje . Ako ne postoji datoteka zadanog imena, kreira se nova.

"w+" Isto kao "r+"

"a+" Otvori datoteku za čitanje i dopunu. Ako ne postoji datoteka zadanog imena, kreira se nova.

"b" Ako se iza slova w, r ili a još zapiše slovo 'b' to označava da se datoteku treba otvoriti u binarnom modu.

Tablica 11.1 Modovi za način otvaranja datoteke.

Page 34: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

31

Dobra je praksa da se uvijek provjeri je li datoteka otvorena bez greške. Primjerice, za otvoriti datoteku imena "hello.txt" u koju će se nešto upisati koriste se sljedeće naredbe:

FILE *fp;

fp = fopen("hello.txt", "w");

if(fp == NULL)

printf("Greska pri otvaranju datoteke");

2. fclose() funkcija Zatvaranje datoteke se vrši funkcijom fclose() čiji je prototip:

int fclose(FILE *fp);

U koliko se ne pozove funkcija fclose() datoteka se automatski zatvara kada se dođe do kraja programskog bloka u kojem je otvorena.

3. feof() funkcija Za detektiranje kraja datoteke predviđena je posebna funkcija:

int feof(FILE *fp);

koja vraća vrijednost različitu od nule ako je dosegnut kraj datoteke. Nakon toga više nije moguće čitanje iz datoteke. 4. Funkcije za rad s datotekama

getc() , putc() – upravljaju sa znakovima fscanf(), fprintf() – upravljaju sa formatirano zapisanim znakovima fgets(), fputs() – upravljaju sa nizom znakova na razini retka

5. fprintf() funkcija

Kada je datoteka otvorena, koristi je se kao tok. Primjerice, naredbama

fprintf(fp, "Hello World!\n"); fprintf(fp, "Hello World drugi put!");

u prethodno otvorenoj datoteci "hello.txt" biti će zapisane dvije linije teksta:

Hello World! Hello World drugi put!

Page 35: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

32

6. fscanf() funkcija

Za formatirano čitanje sadržaja datoteke koristi se fscanf() funkcija, koja je poopćeni oblik scanf() funkcije za dobavu podataka iz ulaznih tokova. Prototip fscanf() funkcije je:

int fscanf(FILE *fp, const char *fmt, ...);

Parametar fp je pokazivač ulaznog toka, koji može biti standardni ili datotečni tok koji se dobije kada se datoteka otvori s atributom "r", "r+" ili "w+". String 'fmt' služi za specifikaciju formata po kojem se učitava vrijednost varijabli, čije adrese se koriste kao argumenti funkcije. Tri točke označavaju proizvoljan broj argumenata, uz uvjet da svakom argumentu mora pripadati po jedan specifikator formata u stringu 'fmt'.

7. fscanf_s() funkcija

int fscanf_s(FILE *fp, const char *fmt, ...);

Funkcija slična fscanf(), samo sa dodatnom kontrolom sigurnosti.

ZADACI

1. Napisati program koji kopira jednu datoteku u drugu. Nazivi obije datoteke se unose u glavnom programu, a

kopiranje se radi u funkciji.

2. Napisati program koji iz datoteke znak, po znak čita znamenke sve dok ne pročita nešto što nije broj ili se

dostigne kraj datoteke. Te znamenke je potrebno pretvoriti u broj koji je bio zapisan u datoteci i ispisati ga na

ekran.

3. Napisati program koji iz datoteke čita maks. 100 podataka o osobama (ime, prezime i godinu rođenja) i traži

koliko se osoba zove Ana. Čitanje datoteke i brojenje je potrebno napraviti u odvojenim f-jama.

4. Napisati program koji iz datoteke pročita 1 cijeli redak i onda ga riječ po riječ ispisuje na ekran, a svaka je riječ

u svom retku.

- Datoteke potrebne za ove zadatke je potrebno napraviti u nekom tekst. editoru (npr. Notepad, …).

Page 36: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

33

Vježba 12.

Programski jezik C omogućuje da se pri potrebi za vrijeme izvršavanja programa rezervira dodatna memorija za

pohranu varijabli. Taj postupak se naziva alokacija, a koristan je npr. ukoliko prije pokretanja programa nije

poznata veličina niza. Dinamičko alociranje memorije omogućuje da se tijekom rada programa rezervira

određeni dio memorije za određenu varijablu.

Dinamička alokacija se radi sa sljedećim naredbama koje su definirane u <stdlib.h>:

malloc() - alocira određeni broj bajtova u memoriji.

calloc() - alocira određeni broj bajtova u memoriji, te svaki bajt postavi na nulu.

realloc() - koristi se za promjenu veličine ranije alociranog prostora u memoriji.

free() - oslobodi rezervirani dio memorije.

Za alociranje je potrebno koristiti pokazivače. Din. alociranje memorije za niz brojeva s 10 elemenata:

int *nizBrojeva = (int *)malloc(10 * sizeof(int));

Ako pokazivač ima vrijednost NULL znači da alokacija nije uspjela, pa je poželjno da se nakon svake alokacije

provjeri je li uspjela ili ne. Isto ne smije se zaboraviti koristiti funkciju free() na kraju programa, inače će nakon

zatvaranja programa ostati alociran blok memorije kojem operacijski sustav, a ni program, više ne mogu

pristupiti, te jedino preostaje ponovno pokretanje računala da bi se taj blok memorije oslobodio.

int *nizBrojeva = (int *)malloc(x * sizeof(int));

if(nizBrojeva == NULL)

{

printf("Alokacija memorije nije uspjela!\n");

return -1;

}

Pristup elementima je isto kao i kod nizova!

for(int i = 0; i<x; i++)

scanf(" %d", &niz[i]); //Unos elemenata u alociran niz

Dinamička alokacija niza struktura:

struct Auto *niz_Auta = (struct Auto *)malloc(n * sizeof(struct Auto));

if(niz_Auta == NULL)

{

printf("Alokacija memorije nije uspjela!\n");

return -1;

}

Page 37: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

34

ZADACI

1. Napisati program koji unosi bodove kolokvija svih studenata i računa prosječni broj bodova, nakon što su

ocjene unesene, uz uvjet da unaprijed nije poznato koliko je bilo studenata.

2. Napisati program koji neki dekadski broj pretvara u string koji se sastoji od znamenki tog broja. String se

dinamički alocira ovisno o tome koliko znamenki ima broj.

3. Napisati program koji čita imena N (unosi se u programu) studenata iz datoteke, a zatim za svakog studenta

pita koliko je bodova dobio iz svakog od kolokvija(ukupno 3) i zatim računa ukupni broj bodova i ocjenu, prema

tablici:

Bodovi Ocjena

50 - 60% => 2

61 – 74% => 3

75 – 87% => 4

88 -100% => 5

4.Napisati program koji pomoću nizova simulira rad reda (podaci se skidaju spočetka, a stižu na kraj). Red mora

biti cirkularan, a dimenzija se unosi s tastature.

Page 38: Programiranje 2 - racunarstvo550.xyz. semestar/Programiranje 2... · od rješavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili

35

Reference:

[1] Ivo Mateljan: “Programiranje C jezikom“, Sveučilište u Splitu, 2005.

[2] Predavanja i prezentacije kolegija Programiranje 2:

- doc. dr. sc. Linda Vicković

- dipl. ing. Ivica Crnjac