-
Izradili: Duje Senta Antonio Prcela 9. oujka 2015.
Sveuilite u Splitu Fakultet elektrotehnike, strojarstva i brodogradnje
Programiranje 2
Prirunik za laboratorijske
vjebe
-
Sadraj
I. Openito o C-u ............................................................................................................................................ 1
II. Uvod u leksiki pretprocesor ...................................................................................................................... 1
III. Usporedba sintaksi C-a i VB.Net-a .......................................................................................................... 3
Vjeba 1. ............................................................................................................................................................. 5
Vjeba 2. ............................................................................................................................................................. 8
Vjeba 3. ...........................................................................................................................................................11
Vjeba 4. ...........................................................................................................................................................13
Vjeba 5. ...........................................................................................................................................................15
Vjeba 6. ...........................................................................................................................................................20
Vjeba 7. ...........................................................................................................................................................21
Vjeba 8. ...........................................................................................................................................................24
Vjeba 9. ...........................................................................................................................................................26
Vjeba 10. .........................................................................................................................................................28
Vjeba 11. .........................................................................................................................................................30
Vjeba 12. .........................................................................................................................................................33
-
1
I. Openito 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 ope namjene, to znai da se u njemu moe napraviti apsolutno sve:
od rjeavanja zadataka, do pisanja pogonskih programa (engl. driver), operacijskih sustava, tekst procesora ili
igara. C, kao jezik, ni u emu ne ograniava. Omoguuje i ukljuivanje naredbi pisanih strojnim jezikom (engl.
assembler), zbog ega je zajedno s mogunou direktnog pristupa pojedinim bitovima, bajtovima ili cijelim
blokovima memorije, pogodan za pisanje sistemskih programa. Zbog tih karakteristika C je meu popularnijim
programskim jezicima i rabe ga mnogi programeri. Kao jedan od najvanijih jezika u povijesti komercijalne
raunalne industrije, C je do danas ostao jedini programski jezik prilagoen za sve raunalne platforme, od malih
sustava pa do mrenih superraunala. Programi napisani u njemu vrlo su bliski nainu rada hardvera te u naelu
zahtijevaju od programera dobro razumijevanje rada procesora, memorije te ulazno-izlaznih sklopova. Koritenje
C-a je odreeno standardom, a trenutni standard koji se koristi je C11.
II. Uvod u leksiki pretprocesor
Pojam "pretprocesor" se koristi za oznaku prve faze obrade izvornog koda. On vri leksiku obradu izvornog koda
na tri naina:
1. Umee u izvorni kod datoteke koje su navedene u direktivi #include
2. Vri supstituciju teksta prema direktivi #define
3. Vri selekciju koda, koji e se prevesti, pomou direktiva #if, #elif, #else i #endif
Koriste se dvije varijante direktive #include:
#include //primjer 1
U gornjem primjeru (primjer 1) je prikazano kada se datoteka trai u direktoriju u kojem su smjetene datoteke s
deklaracijama standardnih funkcija. Dok se u donjem primjeru (primjer 2) ukljuuje datoteka koja se nalazi u
direktoriju gdje je izvorni kod (u direktoriju programa gdje se nalazi datoteka *.c).
#include "ime_datoteke" //primjer 2
Leksika supstitucija teksta, makro (engl. macro), se definira pomou direktive #define na dva naina:
#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
-
2
Primjer koda sa supstitucijom: Ispis:
#include
#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
Leksika 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 nain kao u
drugoj definiciji zbog prioriteta operatora * nad +, makro ne bi vratio oekivani rezultat.
-
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 sluaju bi se
pozvale dvije razliite funkcije.
C programski jezik: Visual Basic .NET
#include
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 moe vidjeti iz priloene tablice (Tablica T3), postoje znaajne razlike sintaksi. Prvo se moe uoiti da
se u C-u imena kljunih rijei piu malim slovima. Sljedee je to to se svaka naredba mora zatvoriti s toka-
zarezom ; inae se javlja greka pri prevoenju koda. Varijable prilikom deklaracije moraju imati pridruenu
inicijalnu vrijednost, inae sadri nedefiniranu vrijednost. Pristup sadraju neinicijalizirane varijable je strogo
zabranjen te moe dovesti do greke u prevoenju ili izvravanju programa.
U C-u ne postoje procedure, samo funkcije. U gornjem primjeru se moe vidjeti funkcija main. Kao i kod VB.NET-
a, main je poetna funkcija svakog programa, od nje program zapoinje s radom. Funkcija main() po
standardima ANSI C te ISO/IEC C11 ima povratnu vrijednost iskljuivo tipa int, dok ostale funkcije mogu imati
povratnu vrijednost bilo kojeg tipa. Poeljno je da main() vraa vrijednost nula (return 0;) ako je program
uspjeno zavrio s radom, te bilo koju drugu vrijednost u sluaju da je dolo do greke prilikom izvravanja
programa.
int main(int argc, char *argv[])
int main(void)
int prije main-a, a i bilo koje druge funkcije, govori da funkcija vraa 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 moe imati minimalno jedan argument, to reprezentira naziv programa.
-
4
Funkcije vraaju vrijednost na sljedei nain:
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 &
- Slui 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). Poto se radi o unosu, mora se koristiti adresni operator & da bi se
vrijednost spremila na memorijsku adresu koja je dodijeljena varijabli.
Primjer koritenja:
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 poetnog elementa niza znakova
Gore navedena funkcija ima nedostatak to na standardnom ulazu moe biti unesena vea koliina teksta nego
to varijabla moe spremiti pa se program srui (prelijevanje meuspreminka). Da bi se sprijeilo ruenje
programa u takvim uvjetima uvedena je funkcija scanf_s(), koja nije dio ANSI C-a i podrana je samo u
Windows OS-u. Primjer koritenja:
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 krai od N
znakova */
Komentari u C-u se mogu pisati na dva naina:
// komentar koda - koritenjem dvostruke kose crte, za samo jedan red komentara.
/* tekst se nalazi
u dvije linije */ - unutar oznaka za komentar koji se eli pisati u vie redaka.
-
5
Vjeba 1.
U programskom jeziku C postoje etiri vrste osnovnih primitivnih varijabli (tablica 1.1). Osnovni operatori koji
postoje u C-u su preteno isti kao i kod ostalih programskih jezika (tablica 1.2).
Razred varijabli Oznaka Veliina Raspon vrijednosti
Cjelobrojni tip podataka
int
short
long
4 byte
2 byte
8 byte
Znakovni tip podataka char 1 byte
Realni tip podataka
float
double
4 byte
8 byte
Kardinalni tip podataka (mogu biti cjelobrojni i znakovni
tipovi)
unsigned char
unsigned int
unsigned long
1 byte
4 byte
8 byte
Tablica 1.1 Primitivne varijable u C-u
Razredi operatora Oznaka Naziv Napomena
Matematiki operatori
+ - * / = % ++ --
zbrajanje oduzimanje mnoenje dijeljenje operator pridruivanja modulus inkrement dekrement
- s desna na lijevo pridruuje vrijednost - ostatak cjelobrojnog dijeljenja
Operatori za rad s bitovima
& | ^ !
logiko AND logiko OR logiko XOR logiko NOT
Operatori indirekcije & *
adresni operator pokazivaki operator
Uvjetni operatori
> <
== != >=
-
6
Ime varijable ujedno oznaava i adresu varijable. Koja je to adresa? Brigu o tome vodi prevoditelj. Adresa
varijable se moe odrediti pomou posebnog operatora & koji se naziva adresni operator. Koristi se kao unarni
operator koji se zapisuje ispred imena varijable.
Primjer koda: Ispis:
#include
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 mogue prebaciti u drugi tip pomou eksplicitne pretvorbe (poznato kao cast operator).
Primjenjuje se tako da se ispred varijable koja se pretvara napie novi tip. Sljedei primjer (tablica 1.4.) e
pretvoriti cijeli broj y u broj s pominim 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 odreeni broj puta. Prva treina zagrade
(do prvog toka-zareza ;) govori koju varijablu uzeti i odakle krenuti. Druga treina zagrade je uvjet koji treba
bit zadovoljen da bi krenulo u iduu iteraciju petlje. Zadnji dio zagrade je operacija kojom se mijenja varijabla,
najee korak kojim se mijenja varijabla. Napomena: nije potrebno pisati sva tri dijela zagrade. Moe se npr.
korak poveavati unutar petlje.
Primjer koda: Ispis:
for(int i=0; i
-
7
ZADACI
1. Napisati program koji definira etiri varijable (char, int, float, double). Ispisati sve etiri varijable, zajedno s
njihovim adresama i izraunati 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 treu
izraunati kao sumu prve dvije. Ispisati sva tri znaka kao znak i kao ASCII vrijednosti.
3. Napisati program koji rauna sumu, produkt, razliku i kvocijent dva cijela broja. Ispisati sve rezultate na ekran.
4. Napisati program koji rauna 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 najvie dvije printf() naredbe.
-
8
Vjeba 2.
Cilj ove vjebe je upoznavanje s naredbom selekcije "if" koja slui za uvjetno izvravanje dijela koda. Provjera
uvjeta se skoro pa uvijek koristi u programima (gotovo je nemogue zamislit program bez ijedne provjere nekog
uvjeta).
Razlikuje se:
1. uvjetna naredba: if
2. uvjetno grananje: if->else
3. viestruko 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 izvravaju ukoliko je uvjet zadovoljen */
}
else if (/*drugi uvjet*/) { /* naredbe ukoliko NE proe 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 pie 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
-
9
jednak 2 te ako je promijeni mu vrijednost u 20. U sluaju 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 pridrui broj 20,
2. Ako je broj jednak 2 onda varijabli broj pridrui broj 10,
3. Ako ni to nije ispunjeno, odlazi na else. Zadnji else nema nikakav uvjet, pa e se izvriti 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 pridrui varijabli broj broj 20,
2. Ako je broj jednak 2 onda pridrui 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 logikim operandima, niti je mogua usporedba dviju ili vie varijabli. Mogua 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 odreuje da se zavri s bilo kakvom daljnjom provjerom, preskae sve
preostale case-eve pa i tako preskoi default. Ako ne postoji break na kraju case-a, tada e switch nastavit
s provjerom sljedeeg uvjeta, u ovom primjeru case 2.
-
10
Ugnijeeni uvjeti:
Mogue je postavljati nove uvjete unutar uvjeta, tako da unutar jednog if naredbenog bloka moe 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 nain da ako je prva znamenka iza
decimalne toke >= 5 zaokruuje se na prvi vei. 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 rauna koliko ih je djeljivo s 3.
4. Napisati program koji unosi 10 znakova i rauna koliko ih je uneseno:
a) malim slovima;
b) koliko ih je = H.
5. Napisati program koji unosi bodove kolokvija za 5 uenika (izmeu 0 i 100) te rauna koliko je uenika
prolo (vie od 50) i koliki je prosjeni broj bodova.
-
11
Vjeba 3.
Kod programiranja se esto javlja potreba da se odreeni dio koda ponavlja vie puta, s time da taj broj
ponavljanja nije unaprijed poznat. U takvom sluaju se koristi while ili do->while petlja. Razlika izmeu ove
dvije petlje je u tome to while najprije provjerava je li uvjet zadovoljen, te onda kree s izvravanjem koda i
tako se vrti sve dok nije uvjet zadovoljen. Dok do->while petlja radi na nain da se uvijek ue jednom u petlju,
izvri kod unutar petlje, pa tek nakon toga provjeri je li uvjet zadovoljen i ovisno o tome se ulazi u sljedeu
iteraciju ili se zavrava 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, inae doi do realizacije beskonane 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
Sljedea while petlja prikazana u tablici 3.1 ne ispisuje nita, jer uvjet mora biti razliit od nule (true).
int broj = 0; while(broj) { printf("%d, ", broj); broj--; }
Tablica 3.2 Uvjet while petlje
Da se na poetku inicijalizira broj = 3, petlja bi se izvrila tri puta jer sve to je razliito 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 slue za prekid petlje (break) ili za direktan skok
u sljedeu iteraciju petlje (continue).
-
12
Generiranje sluajnih brojeva
Da bi raunalo nasumino generiralo brojeve, koristi se rand()funkcija definirana u zaglavlju .
Meutim ako se koristi samo funkcija rand() ona e uvijek generirati iste sluajne brojeve zbog ega se
najee koristi u kombinaciji s srand(). Funkcija srand() mijenja brojevnu bazu iz koje se generiraju brojevi,
pa su brojevi generirani pomou funkcije rand() zbilja sluajni. Primjer generiranja sluajnih 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 sluajnih brojeva. Funkcija time(NULL) vraa trenutno vrijeme u UNIX/POSIX obliku, koje rauna ukupan broj sekundi koje su prole 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 ili < od generiranog. Pogaanje traje sve dok se broj ne pogodi. Potrebno je ispisati iz
kojeg je puta broj pogoen.
4. Napisati program koji ispisuje sve primitivne brojeve od 0 100.
-
13
Vjeba 4.
Niz je imenovana i numerirana kolekcija istovrsnih objekata koji se nazivaju elementi niza. Elementi niza mogu
biti prosti skalarni tipovi i korisniki definirani tipovi podataka. Oznaavaju se imenom niza i cjelobrojnom
izrazom indeksom koji oznaava poziciju elementa u nizu. Indeks niza se zapisuje u uglatim zagradama iza
imena niza. Primjerice, x[3] oznaava 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] oznaava etvrti element niza. S
elementima niza se manipulira kao s obinim 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 statiki deklarirane nizove automatski se svi elementi postavljaju na vrijednost nula. Kod lokalno
deklariranih nizova ne vri se inicijalizacija poetnih 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 moe inicijalizirati listom konstanti, napisanom unutar vitiastih zagrada, koje redom odreuje poetnu
vrijednost elemenata niza.
int A[10]= {1,2,23,4,32,5,7,9,6};
Ako se inicijaliziraju svi potrebni elementi niza, tada nije nuno 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 moe 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.
-
14
ZADACI
1. Napisati program koji s tastature unosi dva cijela broja i matematiku operaciju (+, -, * ili /). Ovisno o operaciji je potrebno izraunati 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 rauna 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) trai najmanji element niza;
b) trai najvei element niza;
c) sortira niz od najmanjeg prema najveem elementu.
Napomena: najmanji i najvei element niza se ne smiju samo ispisati nakon sortiranja. Potrebno ih je pronai
prije sortiranja.
-
15
Vjeba 5.
U C-u ne postoji varijabla tipa string koja sprema tekst, nego se koristi niz znakova char varijable. Deklaracija i
inicijalizacija je mogua na vie naina, a specifikator formata za ispis i unos je %s. Poto se radi o nizu znakova,
potrebno je na kraju svakog stringa imati '\0' koji oznaava kraj stringa, inae e najvjerojatnije doi do ruenja
programa ili ispisa nepoeljnih 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 odreuje veliinu niza i na kraj niza dodaje '\0', dok je kod drugog
naina potrebno runo dodati '\0'. Kod treeg naina se kreira niz s 5 elemenata, kod kojeg svaki element ima
ASCII vrijednost -52, to je znak s brojem 204 iz proirene 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 koritenja adresnog operatora &. Razlog tome je to varijabla znakovi3 pokazuje na
adresu poetka niza.
Napomena: U ostatku teksta koristiti e se naziv "string" umjesto "niz znakova".
Unos stringa s tastature
Stringove je mogue unijeti na sljedee naine:
scanf(" %s", tekst);
gets(tekst);
Obratite pozornost na razliku izmeu koritenja razmaka u scanf i bez koritenja 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
-
16
Ako se u oba sluaja unese 123 pa pritisne enter, u prvom sluaju e biti mogue unijeti neku vrijednost u
varijablu tekst, dok e u drugom sluaju preskoiti unos u tekst te e odmah ispisati vrijednost varijable tekst
koja je samo nova linija (enter).
U ostatku teksta e se spomenuti samo nekoliko vanijih funkcija za rad za stringovima. One su ugraene u
datoteci zaglavlja , za detalje kako koja radi mogu se pogledi primjeri s prezentacija, potrait primjere
na internetu ili u Pomoi (CTRL+F1) Visual Studia (ili nekog drugog razvojnog okruenja).
Neke vanije funkcije unutar
1) strlen(znakovi1);
Funkcija strlen() vraa duinu stringa znakovi1. Duinu rauna od prvog elementa do '\0' (koji se ne rauna).
Budui da funkcija vraa neku vrijednost, poeljno je da se ta vrijednost ispie 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 (ukljuujui i '\0'). Lijevi argument je
odredina varijabla u koju se kopira string, a desna je izvorina iz koje e se uzimati svi elementi.
3) strcmp(prvi_string, drugi_string);
Funkcija strcmp() usporeuje dva stringa te vraa:
- 0 ako su oba stringa identina
- pozitivni broj ako je prvi_string vei od drugi_string (vei ASCII vrijednost prvog razliitog slova je
vea u prvi_string nego u drugi_string)
- negativni broj ako je prvi_string manji od drugi_string (manji ASCII vrijednost prvog razliitog slova
je manja u prvi_string nego u drugi_string)
Funkcija strcmpi() radi na slian nain, ali ne razlikuje velika i mala slova, to znai da e vratiti 0 za usporedbu
stringova abcd i ABCD.
-
17
Jo neke funkcije iz .
strlwr Pretvara sva slova iz stringa u mala slova
strupr Pretvara sva slova iz stringa u velika slova
strrev Obre znakove u stringu (npr.: abcde pretvara u edcba)
strchr Pronalazi prvo pojavljivanje odreenog znaka u stringu
strrchr Pronalazi zadnje pojavljivanje odreenog znaka u stringu
strncat Dodaje odreeni broj znakova iz jednog stringa u na kraj drugog stringa.
strncmp Usporeuje 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 .
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 prikae na ekranu.
getchar() uzima jedan znak s tastature - bez obzira koliko se unese, isto kao i gore navedena
funkcija getche() prikae 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 vraa
vrijednost 0 ako uvjet nije zadovoljen, a broj razliit 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 vraa ASCII vrijednost nekog znaka tolower vraa ASCII vrijednost malog slova za zadano slovo toupper vraa ASCII vrijednost velikog slova za zadano slovo
Tablica 5.3 Funkcije iz zaglavlja ctype.h
-
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 sljedee 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 vri 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
-
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 nain 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.
-
20
Vjeba 6.
Viedimenzionalnim nizovima se pristupa preko dva ili vie indeksa. Primjerice,deklaracijom int x[3][4]; definira
se dvodimenzionalni niz koji ima 3 x 4 = 12 elemenata. Deklaraciju se moe 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
sluaju nije potrebno razmiljati o tome kako je niz sloen u memoriji, jer se elementima pristupa preko dva
indeksa: prvi je oznaka retka, a drugi je oznaka stupca matrice.
Matrini 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
sloeni po redovima matrice; najprije prvi redak, zatim drugi, itd. Viedimenzionalni niz se moe inicijalizirani ve
u samoj deklaraciji, primjerom:
int x[3][4] = {{1, 21, 14, 8},{12, 7, 41, 2},{1, 2, 4, 3}};
Navoenje unutarnjih vitiastih zagrada je opcijski, pa se moe pisati i sljedea deklaracija:
int x[3][4] = {1, 21, 14, 8, 12, 7, 41, 2, 1, 2, 4, 3};
Ovaj drugi nain inicijalizacije se ne preporuuje, jer je tee uoiti raspored elemenata.
ZADACI
1. Napisati program koji unosi jednu matricu (A dimenzija 3x3) i iz te matrice rauna 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 rauna 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 pretraivanja 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.
-
21
Vjeba 7.
U C-u varijabla moe biti deklarirana na globalnoj i lokalnoj razini. Razlika izmeu 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
int x = 11; //Globalna varijabla
int main(void) { printf("x je jednak: %d\n", x); return 0; }
#include
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 greku "undeclared identifier" za zadnji printf.
Varijable unutar funkcije se briu nakon to funkcija zavri s radom, te se opet kreiraju pri ponovnom pozivanju
funkcije. Funkcije se najee koriste za odreenu 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 prosljeuju u funkciju te povratna vrijednost
funkcije.
2. Definicija funkcije - uz ime, argumente i povratnu vrijednost sadri kod s naredbama.
3. Poziv funkcije - mjesto u kodu gdje se poziva funkcija.
-
22
DIO KODA OPIS
#include
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 vraa njihov umnoak.
Takav pristup je posebno vaan ukoliko funkcija poziva druge funkcije. Kad se ne bi kod pisao na ovaj nain,
trebalo bi se voditi rauna o rasporedu funkcija u kodu. Poeljno je da se najprije deklariraju funkcije, te se iza
main funkcije napiu njihove definicije . Postoje funkcije koje mogu vratiti vrijednost (int, double, char, itd.),
te one koje ne vraaju vrijednost (void). Ukoliko funkcija vraa 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 nee izvriti.
Ukoliko je funkcija void tada se poziva na sljedei nain:
ime_funkcije(arg1, arg2);
Ukoliko funkcija vraa vrijednost rada tada se vrijednost moe 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
koritenje vrijednosti za ispis */
Nakon to se izae iz funkcije sve lokalne varijable se briu. Tako da kada se ponovo ue u funkciju, varijable
poprimaju poetne vrijednosti. Ukoliko je potrebno da varijabla sadri svoju vrijednost i nakon to izae iz
funkcije, to se moe napraviti koritenjem kljune rijei static. Ona omoguuje da kada se opet pozove
funkcija zadrava prethodnu vrijednost.
static int x = 0;
Osim static postoji i kljuna rije const koja se koristi za deklaraciju konstanti.
const broj = 123;
-
23
Neke funkcije iz zaglavlja Datoteka zaglavlja sadri matematike funkcije, kao npr.: potenciranje, korjenovanje, logaritmi, trigonometrija, itd. Neke od najee koritenih su definirane funkcije:
double exp(double X); //koristi se za raunanje eX
double sqrt(double X); //koristi se za raunanje double pow(double X, double Y); //koristi se za raunanje XY
Kao to se moe vidjeti, u zagradama se alju vrijednosti koje su tipa razliitog od int. Zbog toga, u sluaju 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); Takoer ne smije se zaboraviti da svaka od matematikih funkcija ima povratnu vrijednost, pa tu vrijednost treba negdje spremiti ili ispisati. Pri tome treba voditi rauna 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) rauna:
a) = + + b) = c) = +
d) =
Svi rezultati se raunaju 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 greku. 2. Napisati program koji sadri 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 obinoj f-ji rauna faktorijele. Rezultat je potrebno ispisati u glavnom programu i nije dozvoljeno koritenje globalnih varijabli.
4. Napisati f-ju kojom se priblino odreuje vrijednost ex (e = 2.718282), i rezultat usporediti s vrijednou koja se dobije pomou standardne funkcije exp() deklarirane u math.h. U rjeavanju problema koristiti razvoj u red:
= 1 +
1!+
2
2!+
3
3!+
4
4!
Npr. za x = 5, ispisati izraunate rezultate za 5, 10 i 50 ponavljanja. Zato se program ponaa "udno" za 50 ponavljanja?
-
24
Vjeba 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 sluaja i pravila rekurzije. Jedan od najeih problema koji se koristi za opis rekurzivne funkcije su
faktorijeli. Pri rjeavanju problema pomou rekurzivne funkcije treba voditi rauna o dvije stvari:
1. Prvo treba provjerit temeljni sluaj rekurzije.
2. Odradi pravilo rekurzivnog poziva.
unsigned int my_fact(unsigned int x)
{
if(x < 2) // Temeljni sluaj 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. Vraanje iznosa
//1. POVRAT
my_fact(3); { return 3 * my_fact(2); { return 2 * 1; //vracena jedinica i mnoi se s 2. } }
//2. POVRAT
my_fact(3); { return 3 * 2; //vraa iznos 6 u glavni program }
Tablica 8.1 Simulacija rada rekurzivne funkcije faktorijela za izraun 3!.
-
25
ZADACI
1. Napisati program koji trai je li neki broj element niza. U programu treba napraviti f-ju trai koja uzima tri
argumenta (niz, broj elemenata niza i vrijednost koja se trai), a treba vratiti 1 ako broj postoji ili 0 ako broj ne
postoji.
2. Napisati program koji rauna produkt svih elemenata matrice dimenzija 3x3. Program ne smije sadravati ni
jednu globalnu varijablu, unos i proraun napraviti u odvojenim funkcijama.
3. Napisati program koji sadri 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 pomou rekurzivne f-je rauna faktorijele.
5. Napisati program koji koritenjem rekurzivnih funkcija trai 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 pomou
rekurzivne f-je. Rezultat se ispisuje u mainu.
-
26
Vjeba 9.
Struktura je skup jedne ili vie varijabli, grupiranih zajedno pod jednim imenom radi lakeg 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 obinih varijabli, koristiti drugi naini imenovanja.
struct Osoba {
int dan, mjesec, godina, niz[10];
char ime[15], prezime[15], spol;
};
Potrebno je naglasiti da se nakon zatvarajue vitiaste zagrade stavlja toka-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 vri pomou toka operatora:
scanf(" %d", &Marko.dan);
printf("%d\n", Marko.dan);
Kod deklaracije strukture mogue je odmah deklarirati i varijable tipa te strukture, tako da se nakon zagrade
napiu varijable:
struct Osoba {
int dan, mjesec, godina;
char ime[15], prezime[15], spol;
} Marko, Ana, Petra, Josip; /* Moe se deklarirati, ali nije preporuljivo.
Nije dozvoljena deklaracija globalnih varijabli i koritenje istih na kolegiju! */
Strukture se mogu deklarirati unutar neke funkcije (npr. main) ili pak izvan funkcija, razlika je u tome to u prvom
sluaju deklarirana struktura nije vidljiva ostalim funkcijama (sjetiti se dijela o lokalnim i globalnim varijablama!).
-
27
Niz struktura
struct Osoba nizOsoba[10];
Kreiran je niz od 10 varijabli tipa strukture Osoba. Pristup pojedinoj varijabli se vri na sljedei nain npr.:
nizOsoba[2].dan //Pristupa se treem 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 rauna koji je datum bio dan prije i koji e datum biti dan poslije.
Za pohranu datuma koristiti strukturu datum (dan, mjesec, godina). Proraun 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 roenja). U programu napraviti
funkciju koja pronalazi najstariju osobu, te funkciju koja pronalazi osobu prvu po abecedi.
-
28
Vjeba 10. Jedan od glavnih razloga zbog ega se C jezik smatra jezikom niske razine je taj to omoguuje indirektno
manipuliranje s podacima i izvrenjem programa. Kako bi se pristupilo adresi varijabli koriste se posebni
operatori - adresni operator & i operator indirekcije *, te specijalni tip varijabli koje se nazivaju pokazivake
varijable ili pokazivai (engl. pointer).
Adresni operator &
Adresa varijable se moe odrediti pomou posebnog operatora & koji se naziva adresni operator. Koristi se kao
unarni operator koji se zapisuje ispred imena varijable.
#include 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 moe izgledati ovako:
Vrijednost y je 777
Adresa y je 0x0063FDF4
Tablica 10.1 Koritenje adresnog operatora
Ispis adrese je izvren u heksadecimalnom obliku s osam znamenki, jer je koriteno 32-bitno raunalo na kojem
je adresa odreena 32-bitnim kardinalnim brojem. Napomena: pri sljedeem izvravanju programa ispis adrese
ne mora biti isti jer operacijski sustav ne uitava program uvijek na isto mjesto u memoriji (time se mijenja i
adresa na kojoj se nalazi varijabla x).
Pokazivai
Varijable kojima je vrijednost adresa neke druge varijable ili funkcije nazivaju se pokazivai ili pointeri. Vrlo je
vano definirati na koji tip varijable pokazuje jer C prevoditelj mora znati kakav e tip podatka biti na adresi koju
oni sadre.
Deklaracija pokazivaa vri se slino deklaraciji varijable, s razlikom to ispred imena varijable (imena pokazivaa)
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 pokazivake varijable. Njihova vrijednost je neodreena, jer im nije
pridijeljena adresa neke varijable. Vano je znati da pokazivae prije upotrebe treba inicijalizirati, odnosno mora
im se pridijeliti vrijednost adrese postojee varijable. Pri tome, tip pokazivaa 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 */
-
29
Pokaziva p je inicijaliziran da pokazuje na varijablu suma. Daljnje koritenje
printf("%d", suma);
printf("%d", *p);
daje isti ispis, jer se indirekcijom pokazivaa 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 pokazivaa i ne smiju se koristiti [].
2. Napisati program koji u jednoj funkciji rauna sumu, produkt i razliku dva broja, a svi se rezultati ispisuju u
glavnom programu.
3. Zadatak s raunanjem dana prije i poslije rijeiti preko funkcija na nain da se sva tri datuma deklariraju u
mainu, a unos, i proraun dana prije i poslije u f-ji. Rezultate je potrebno ispisati u mainu, a ne u funkciji.
4. Napisati program koji za zadani string trai koliko se puta podstring pojavljuje u stringu. Podstring je potrebno
unijeti u f-ji. F-ja za pretraivanje treba vratiti broj ponavljanja. U funkciji za pretraivanje se moe koristiti f-ja
strncmp iz string.h.
-
30
Vjeba 11. U standardnoj biblioteci 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
optikim medijima. Komuniciranje s ureajima koji obavljaju ove operacije vri se sekvencijalno bajt po bajt, a
programski mehanizam kojim se vri ovakvi prijenos informacije naziva se tok (engl. stream). U jednom se
programu moe raditi s vie tokova. Svakom toku se pridjeljuje jedna struktura podataka imena FILE, koja je
definirana u . Temeljna namjena te strukture je da slui kao memorijski ulazno/izlazni
meuspremnik (engl. I/O buffer) pri prijenosu podataka.
Tokovi se dijele u etiri grupe:
standardni ulaz (vri unos znakova s tipkovnice),
standardni izlaz (vri ispis na ekran),
standardna dojava greke (obino se vri ispis na ekran),
datoteni tok (vri itanje ili pisanje podataka u datoteku).
1. Funkcije fopen() i fopen_s()
Da bi se moglo koristiti neku datoteku potrebno je od operacijskog sustava zatraiti dozvolu pristupa toj
datoteci. Taj proces se zove otvaranje datoteke. Isto tako se za kreiranje nove datoteke mora zatraiti dozvola od
operacijskog sustava. Tu funkciju obavlja standardna funkcija fopen(). Ona pored komunikacije s operacijskim
sustavom kreira datoteni tok koji sadri memorijski meuspremnik za efikasno itanje ili spremanje podataka
na disk.
Prototip funkcije fopen() je:
FILE *fopen(const char *ime_datoteke, const char *mod);
Moe se koristiti i sigurna verzija fopen_s()
errno_t fopen_s(FILE **fp, const char *ime_datoteke, const char *mod);
koja vraa poruku o greci u strukturu tipa errno_t umjesto vrijednosti NULL ukoliko doe do greke otvaranja datoteke. Modovi otvaranja datoteke su opisani u tablici 11.1.
Mod Opis
"r" Otvori datoteku za itanje, ako datoteka ne postoji fopen() vraa NULL.
"w" Otvori datoteku za pisanje, ako ne postoji datoteka zadanog imena, kreira se nova.
"a" Otvori datoteku za dopunu sadraja, 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 zapie slovo 'b' to oznaava da se datoteku treba otvoriti u binarnom modu.
Tablica 11.1 Modovi za nain otvaranja datoteke.
-
31
Dobra je praksa da se uvijek provjeri je li datoteka otvorena bez greke. Primjerice, za otvoriti datoteku imena "hello.txt" u koju e se neto upisati koriste se sljedee naredbe:
FILE *fp;
fp = fopen("hello.txt", "w");
if(fp == NULL)
printf("Greska pri otvaranju datoteke");
2. fclose() funkcija Zatvaranje datoteke se vri funkcijom fclose() iji je prototip:
int fclose(FILE *fp);
U koliko se ne pozove funkcija fclose() datoteka se automatski zatvara kada se doe do kraja programskog bloka u kojem je otvorena.
3. feof() funkcija Za detektiranje kraja datoteke predviena je posebna funkcija:
int feof(FILE *fp);
koja vraa vrijednost razliitu od nule ako je dosegnut kraj datoteke. Nakon toga vie nije mogue 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!
-
32
6. fscanf() funkcija
Za formatirano itanje sadraja datoteke koristi se fscanf() funkcija, koja je poopeni 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 moe biti standardni ili datoteni tok koji se dobije kada se datoteka otvori s atributom "r", "r+" ili "w+". String 'fmt' slui za specifikaciju formata po kojem se uitava vrijednost varijabli, ije adrese se koriste kao argumenti funkcije. Tri toke oznaavaju 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 slina 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 proita neto 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 roenja) i trai
koliko se osoba zove Ana. itanje datoteke i brojenje je potrebno napraviti u odvojenim f-jama.
4. Napisati program koji iz datoteke proita 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, ).
-
33
Vjeba 12.
Programski jezik C omoguuje da se pri potrebi za vrijeme izvravanja programa rezervira dodatna memorija za
pohranu varijabli. Taj postupak se naziva alokacija, a koristan je npr. ukoliko prije pokretanja programa nije
poznata veliina niza. Dinamiko alociranje memorije omoguuje da se tijekom rada programa rezervira
odreeni dio memorije za odreenu varijablu.
Dinamika alokacija se radi sa sljedeim naredbama koje su definirane u :
malloc() - alocira odreeni broj bajtova u memoriji.
calloc() - alocira odreeni broj bajtova u memoriji, te svaki bajt postavi na nulu.
realloc() - koristi se za promjenu veliine ranije alociranog prostora u memoriji.
free() - oslobodi rezervirani dio memorije.
Za alociranje je potrebno koristiti pokazivae. Din. alociranje memorije za niz brojeva s 10 elemenata:
int *nizBrojeva = (int *)malloc(10 * sizeof(int));
Ako pokaziva ima vrijednost NULL znai da alokacija nije uspjela, pa je poeljno da se nakon svake alokacije
provjeri je li uspjela ili ne. Isto ne smije se zaboraviti koristiti funkciju free() na kraju programa, inae e nakon
zatvaranja programa ostati alociran blok memorije kojem operacijski sustav, a ni program, vie ne mogu
pristupiti, te jedino preostaje ponovno pokretanje raunala 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
-
34
ZADACI
1. Napisati program koji unosi bodove kolokvija svih studenata i rauna prosjeni 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
dinamiki 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 rauna 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 pomou nizova simulira rad reda (podaci se skidaju spoetka, a stiu na kraj). Red mora
biti cirkularan, a dimenzija se unosi s tastature.
-
35
Reference:
[1] Ivo Mateljan: Programiranje C jezikom, Sveuilite u Splitu, 2005.
[2] Predavanja i prezentacije kolegija Programiranje 2:
- doc. dr. sc. Linda Vickovi
- dipl. ing. Ivica Crnjac