You are on page 1of 2009

_________________________________________________________

ZBIRKA ZADATAKA
IZ
PROGRAMSKOG JEZIKA C
V 1.0 05/08/2015
_________________________________________________________
ETF Beograd
ETF Podgorica
ETF Sarajevo
FER Zagreb
FSB Split
FTN Kosovska Mitrovica
MAT FAK Beograd
PMF Ni
PMF Srbsko Sarajevo
FTN aak
UN Singidunum Beograd
VT aak
VT Ni
_____________________________________________________________

Sakupio i obradio:
jjanko2015@gmail.com
SADRAJ
_________________________________________________________________
C reference card ANSI
Slubeni podsetnik FER Zagreb
1.ETF Beograd
2.ETF Podgorica
3.ETF Sarajevo
4.FER Zagreb
5.FSB Split
6.FTN Kosovska Mitrovica
7.MAT FAK Beograd
8.PMF Ni
9.PMF Srbsko Sarajevo
10.FTN aak
11.UN Singidunum Beograd
12.VT aak
13.VT Ni
_________________________________________________________________
Napomena:

Zbirka predstavlja skup vebi iz programskog jezika C


Nedostaju vebe sa FTN NS i ELFAK Ni
Za bri pristup pojedinoj stavki u sadraju kliknuti na bukmark
Za bolje razumevanje pogledati predavanja na odgovarajuem fakultetu tj. koli
C Reference Card (ANSI) Constants Flow of Control
long (suffix) L or l statement terminator ;
Program Structure/Functions float (suffix) F or f block delimeters { }
type fnc(type 1 ,. . . ) function declarations exponential form e exit from switch, while, do, for break
type name external variable declarations octal (prefix zero) 0 next iteration of while, do, for continue
main() { main routine hexadecimal (prefix zero-ex) 0x or 0X go to goto label
declarations local variable declarations character constant (char, octal, hex) 'a', '\ooo', '\xhh' label label :
statements newline, cr, tab, backspace \n, \r, \t, \b return value from function return expr
} special characters \\, \?, \', \" Flow Constructions
type fnc(arg 1 ,. . . ) { function definition string constant (ends with '\0') "abc. . . de" if statement if (expr ) statement
declarations local variable declarations else if (expr ) statement
statements Pointers, Arrays & Structures else statement
return value; declare pointer to type type *name while statement while (expr )
} statement
declare function returning pointer to type type *f()
comments for statement for (expr 1 ; expr 2 ; expr 3 )
/* */ declare pointer to function returning type type (*pf)() statement
main(int argc, char *argv[]) main with args generic pointer type void * do statement do statement
exit(arg ) terminate execution null pointer NULL while(expr );
object pointed to by pointer *pointer
C Preprocessor address of object name &name
switch statement switch (expr ) {
case const 1 : statement 1 break;
include library file #include <filename> array name[dim] case const 2 : statement 2 break;
include user file #include "filename" multi-dim array name[dim 1 ][dim 2 ]. . . default: statement
replacement text #define name text Structures }
replacement macro #define name(var ) text struct tag { structure template
Example. #define max(A,B) ((A)>(B) ? (A) : (B)) declarations declaration of members ANSI Standard Libraries
undefine #undef name }; <assert.h> <ctype.h> <errno.h> <float.h> <limits.h>
quoted string in replace # create structure struct tag name <locale.h> <math.h> <setjmp.h> <signal.h> <stdarg.h>
concatenate args and rescan ## member of structure from template name.member <stddef.h> <stdio.h> <stdlib.h> <string.h> <time.h>
conditional execution #if, #else, #elif, #endif member of pointed to structure pointer -> member
is name defined, not defined? #ifdef, #ifndef Example. (*p).x and p->x are the same
Character Class Tests <ctype.h>
name defined? defined(name ) single value, multiple type structure union alphanumeric? isalnum(c)
line continuation char \ bit field with b bits member : b alphabetic? isalpha(c)
control character? iscntrl(c)
Data Types/Declarations Operators (grouped by precedence) decimal digit? isdigit(c)
character (1 byte) char structure member operator name.member printing character (not incl space)? isgraph(c)
integer int structure pointer pointer ->member lower case letter? islower(c)
float (single precision) float printing character (incl space)? isprint(c)
increment, decrement ++, --
float (double precision) double printing char except space, letter, digit? ispunct(c)
plus, minus, logical not, bitwise not +, -, !, ~
short (16 bit integer) short space, formfeed, newline, cr, tab, vtab? isspace(c)
indirection via pointer, address of object *pointer , &name
long (32 bit integer) long upper case letter? isupper(c)
cast expression to type (type) expr
positive and negative signed hexadecimal digit? isxdigit(c)
size of an object sizeof
only positive unsigned convert to lower case? tolower(c)
pointer to int, float,. . . *int, *float,. . . multiply, divide, modulus (remainder) *, /, % convert to upper case? toupper(c)
enumeration constant enum add, subtract +, -
constant (unchanging) value const String Operations <string.h>
declare external variable extern left, right shift [bit ops] <<, >> s,t are strings, cs,ct are constant strings
register variable register comparisons >, >=, <, <= length of s strlen(s)
local to source file static comparisons ==, != copy ct to s strcpy(s,ct)
no value void up to n chars strncpy(s,ct,n)
bitwise and &
structure struct concatenate ct after s strcat(s,ct)
create name by data type typedef typename bitwise exclusive or ^
up to n chars strncat(s,ct,n)
size of an object (type is size_t) sizeof object bitwise or (incl) | compare cs to ct strcmp(cs,ct)
size of a data type (type is size_t) sizeof(type name) logical and && only first n chars strncmp(cs,ct,n)
pointer to first c in cs strchr(cs,c)
Initialization logical or ||
pointer to last c in cs strrchr(cs,c)
initialize variable type name=value conditional expression expr 1 ? expr 2 : expr 3 copy n chars from ct to s memcpy(s,ct,n)
initialize array type name[]={value 1 ,. . . } assignment operators +=, -=, *=, . . . copy n chars from ct to s (may overlap) memmove(s,ct,n)
initialize char string char name[]="string " expression evaluation separator , compare n chars of cs with ct memcmp(cs,ct,n)
pointer to first c in first n chars of cs memchr(cs,c,n)
Unary operators, conditional expression and assignment oper-
put c into first n chars of cs memset(s,c,n)
ators group right to left; all others group left to right.

c 1999 Joseph H. Silverman Permissions on back. v1.3



1 2 3
C Reference Card (ANSI) Standard Utility Functions <stdlib.h> Integer Type Limits <limits.h>
absolute value of int n abs(n) The numbers given in parentheses are typical values for the
Input/Output <stdio.h> absolute value of long n labs(n) constants on a 32-bit Unix system.
quotient and remainder of ints n,d div(n,d) CHAR_BIT bits in char (8)
Standard I/O
retursn structure with div_t.quot and div_t.rem CHAR_MAX max value of char (127 or 255)
standard input stream stdin
quotient and remainder of longs n,d ldiv(n,d) CHAR_MIN min value of char (128 or 0)
standard output stream stdout
returns structure with ldiv_t.quot and ldiv_t.rem INT_MAX max value of int (+32,767)
standard error stream stderr
pseudo-random integer [0,RAND_MAX] rand() INT_MIN min value of int (32,768)
end of file EOF
set random seed to n srand(n) LONG_MAX max value of long (+2,147,483,647)
get a character getchar()
terminate program execution exit(status) LONG_MIN min value of long (2,147,483,648)
print a character putchar(chr )
pass string s to system for execution system(s) SCHAR_MAX max value of signed char (+127)
print formatted data printf("format ",arg 1 ,. . . )
Conversions SCHAR_MIN min value of signed char (128)
print to string s sprintf(s,"format ",arg 1 ,. . . )
convert string s to double atof(s) SHRT_MAX max value of short (+32,767)
read formatted data scanf("format ",&name 1 ,. . . )
convert string s to integer atoi(s) SHRT_MIN min value of short (32,768)
read from string s sscanf(s,"format ",&name 1 ,. . . )
convert string s to long atol(s) UCHAR_MAX max value of unsigned char (255)
read line to string s (< max chars) gets(s,max)
convert prefix of s to double strtod(s,endp) UINT_MAX max value of unsigned int (65,535)
print string s puts(s)
convert prefix of s (base b) to long strtol(s,endp,b) ULONG_MAX max value of unsigned long (4,294,967,295)
File I/O
same, but unsigned long strtoul(s,endp,b) USHRT_MAX max value of unsigned short (65,536)
declare file pointer FILE *fp
Storage Allocation
pointer to named file fopen("name ","mode ")
allocate storage malloc(size), calloc(nobj,size) Float Type Limits <float.h>
modes: r (read), w (write), a (append) FLT_RADIX radix of exponent rep (2)
change size of object realloc(pts,size)
get a character getc(fp) FLT_ROUNDS floating point rounding mode
deallocate space free(ptr)
write a character putc(chr ,fp) FLT_DIG decimal digits of precision (6)
Array Functions
write to file fprintf(fp,"format ",arg 1 ,. . . )
search array for key bsearch(key,array,n,size,cmp()) FLT_EPSILON smallest x so 1.0 + x 6= 1.0 (105 )
read from file fscanf(fp,"format ",arg 1 ,. . . )
sort array ascending order qsort(array,n,size,cmp()) FLT_MANT_DIG number of digits in mantissa
close file fclose(fp)
FLT_MAX maximum floating point number (1037 )
non-zero if error ferror(fp) Time and Date Functions <time.h> FLT_MAX_EXP maximum exponent
non-zero if EOF feof(fp)
processor time used by program clock() FLT_MIN minimum floating point number (1037 )
read line to string s (< max chars) fgets(s,max,fp )
Example. clock()/CLOCKS_PER_SEC is time in seconds FLT_MIN_EXP minimum exponent
write string s fputs(s,fp)
current calendar time time() DBL_DIG decimal digits of precision (10)
Codes for Formatted I/O: "%-+ 0w.pmc"
- left justify time2 -time1 in seconds (double) difftime(time2 ,time1 ) DBL_EPSILON smallest x so 1.0 + x 6= 1.0 (109 )
+ print with sign arithmetic types representing times clock_t,time_t DBL_MANT_DIG number of digits in mantissa
space print space if no sign structure type for calendar time comps tm DBL_MAX max double floating point number (1037 )
0 pad with leading zeros tm_sec seconds after minute DBL_MAX_EXP maximum exponent
w min field width tm_min minutes after hour DBL_MIN min double floating point number (1037 )
p precision tm_hour hours since midnight DBL_MIN_EXP minimum exponent
m conversion character: tm_mday day of month
h short, l long, L long double tm_mon months since January
c conversion character: tm_year years since 1900
d,i integer u unsigned tm_wday days since Sunday
c single char s char string tm_yday days since January 1
f double e,E exponential tm_isdst Daylight Savings Time flag
o octal x,X hexadecimal convert local time to calendar time mktime(tp)
p pointer n number of chars written convert time in tp to string asctime(tp)
g,G same as f or e,E depending on exponent convert calendar time in tp to local time ctime(tp)
convert calendar time to GMT gmtime(tp)
Variable Argument Lists <stdarg.h> convert calendar time to local time localtime(tp)
declaration of pointer to arguments va_list name; format date and time info strftime(s,smax,"format ",tp)
initialization of argument pointer va_start(name ,lastarg ) tp is a pointer to a structure of type tm
lastarg is last named parameter of the function
access next unamed arg, update pointer va_arg(name ,type) Mathematical Functions <math.h>
call before exiting function va_end(name ) Arguments and returned values are double
trig functions sin(x), cos(x), tan(x)
inverse trig functions asin(x), acos(x), atan(x)
arctan(y/x) atan2(y,x)
hyperbolic trig functions sinh(x), cosh(x), tanh(x) c 1999 Joseph H. Silverman
May 1999 v1.3. Copyright
exponentials & logs exp(x), log(x), log10(x)
Permission is granted to make and distribute copies of this card pro-
exponentials & logs (2 power) ldexp(x,n), frexp(x,*e) vided the copyright notice and this permission notice are preserved on
division & remainder modf(x,*ip), fmod(x,y) all copies.
powers pow(x,y), sqrt(x) Send comments and corrections to J.H. Silverman, Math. Dept., Brown
rounding ceil(x), floor(x), fabs(x) Univ., Providence, RI 02912 USA. hjhs@math.brown.edui

4 5 6
Programiranje i programsko inenjerstvo slubeni podsjetnik verzija 2013.b

Izvadak iz ASCII tablice Prioritet operatora


Znak Opis Dekadska vrijednost OPERATORI PRIDRUIVANJE
LF sljedei red, novi red 10 poziv funkcije()
Space blank, praznina 32 []
L D

Vii prioritet
0 znamenka nula 48 referenciranje .
A veliko slovo A 65 postfiks ++ --
a malo slovo a 97 ! ~ ++ -- sizeof & *
prefiks ++ -- D L
unarni + -
Prikaz realnih brojeva
(cast) D L
IEEE 754 jednostruka IEEE 754 dvostruka
preciznost preciznost * / % L D
K = BE + 127 K = BE + 1023 binarni + - L D
denormalizirani broj: K = 0 denormalizirani broj: K = 0 << >> L D
ili NaN: K = 255 ili NaN: K = 2047 < <= > >= L D

Nii prioritet
najvei pozitivan broj najvei pozitivan broj == != L D
3.4 1038 1.8 10308 & L D
najmanji pozitivan broj najmanji pozitivan broj ^ L D
1.4 10-45 4.9 10-324
| L D
2-24 6 10-8 2-53 1.1 10-16 && L D
|| L D
math.h ? : D L
double fabs (double x); x = *= /= %= += -=
double sin (double x); D L
&= ^= |= <<= >>=
double cos (double x); , L D
double tan (double x);

double asin (double x); Izgled konverzijskih specifikacija kod


double acos (double x); funkcije printf
double atan (double x);
double sinh (double x); %[znak][irina][.preciznost]tip
double cosh (double x); [znak] Objanjenje
double tanh (double x);
double exp (double x); ex nita desno pozicioniranje
double log (double x); ln x tiska - predznak, a umjesto +
praznina
predznaka je praznina
double log10 (double x); log x
- lijevo pozicioniranje
double pow (double x, double y); xy
+ rezultat uvijek poinje s + ili -
double sqrt(double x); x
0 ispisuje vodee nule
double fmod(double x, double y); x mod y
# konverzija na alternativan nain:
double ceil (double x); x ne utjee na c s d i u
double floor(double x); x ispisuje vodeu 0 za o
ispisuje vodee 0x ili 0X za x ili X
stdlib.h ispisuje dec. toku i kad nema
int abs (int x); x decimala za e E F
long labs (long x); x ispisuje pratee 0 za g G
void exit (int status);
void srand (unsigned int seed);
int rand (void); vraa broj iz intervala [0, RAND_MAX]
void *malloc (size_t size); vraa NULL u sluaju pogreke
void free (void *block);
void *realloc(void *block, size_t size); vraa NULL u sluaju pogreke

string.h
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t maxlen);
char *strcat(char *dest, const char *src);
char *strncat(char *dest, const char *src, size_t maxlen);
size_t strlen(const char *s);
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t maxlen);
char *strchr(const char *s, int c);
Programiranje i programsko inenjerstvo slubeni podsjetnik verzija 2013.b
char *strrchr(const char *s, int c);
char *strstr(const char *string, const char *substring);
char *strpbrk(const char *string, const char *setofcharacters);

ctype.h
int toupper(int ch);
int tolower(int ch);
int isdigit(int c); provjerava je li znak znamenka (0-9)
int isalpha(int c); provjerava je li znak slovo (A-Z ili a-z)
int isalnum(int c); provjerava je li znak slovo (A-Z ili a-z) ili znamenka (0-9)
int isprint(int c); provjerava moe li se znak ispisati (0x20-0x7E)
int iscntrl(int c); provjerava je li znak kontrolni (0x7F ili 0x00-0x1F)
int isspace(int c); provjerava je li znak praznina
int islower(int c); provjerava je li znak malo slovo (a-z)
int isupper(int c); provjerava je li znak veliko slovo (A-Z)

stdio.h
int getchar(void); vraa uitani znak ili EOF
int putchar(int ch); vraa ispisani znak ili EOF (kod pogreke)
int scanf(const char *format, arg1, arg2, ...,arg n);
vraa broj uitanih argumenata (0n) ili EOF (kraj datoteke)

Tipovi formatskih specifikacije za scanf: %d,%i,%o,%u,%x,%c,%s,%e,%f,%g,%p,%[],%[^].


Prefiksi: h(za short) l(long, double) L(long double), npr. %hd, %ld, %lf, %Lf

int printf(const char *format, arg1, arg2, ...,arg n); vraa broj ispisanih znakova

Tipovi formatskih specifikacije za printf: %d,%i,%o,%u,%x,%X,%c,%s,%e,%f,%g,%G,%e,%E,%p.

int puts(const char *s); vraa EOF u sluaju pogreke


char *gets(char *string); vraa NULL ako kao prvi znak proita kraj datoteke (CTRL+Z (windows) ili
CTRL+D(unix)) ili ako je nastupila pogreka

FILE *fopen(const char *filename, const char *mode);

mode: "w","a","r","w+","a+","r+" Napomena: U Windows op. sustavu za binarne datoteke treba na kraj dodati b

int fclose(FILE *fp); vraa 0 ako je operacija uspjela ili EOF u sluaju pogreke
int fgetc(FILE *stream); vraa proitani znak ili EOF (pogreka ili kraj datoteke)
int fscanf (FILE *stream, const char *format, arg1, arg2, ..., arg n);
vraa broj uitanih argumenata ili EOF(pogreka ili kraj datoteke)
char *fgets(char *s, int n, FILE *stream);
vraa NULL u sluaju pogreke ili kraja datoteke
int fputc(int c, FILE *stream);
vraa ispisani znak ili EOF u sluaju pogreke
int fprintf (FILE *stream, const char *format, arg1, arg2, ..., arg n);
vraa broj ispisanih znakova ili EOF u sluaju pogreke
int fputs(char *s, FILE *stream);
vraa nenegativni broj ili EOF u sluaju pogreke
size_t fread(void *ptr, size_t size, size_t n, FILE *stream);
vraa broj uitanih objekata. (0..n)
size_t fwrite(void *ptr, size_t size, size_t n, FILE *stream);
vraa broj ispisanih objekata. U sluaju pogreke taj je broj < n.
int fseek(FILE *stream, long offset, int whence);
vraa 0 ako je pozicioniranje uspjelo ili broj razliit od 0 u sluaju pogreke
whence: SEEK_SET pozicioniranje u odnosu na poetak datoteke
SEEK_CUR - pozicioniranje u odnosu na trenutnu poziciju u datoteci
SEEK_END - pozicioniranje u odnosu na kraj datoteke

long ftell(FILE *stream); vraa trenutnu poziciju u datoteci ili -1 u sluaju pogreke
ELEKTROTEHNIKI FAKULTET
UNIVERZITETA U BEOGRADU

PROGRAMIRANJE 2
MATERIJAL ZA VEBE NA TABLI I PRIPREMU ISPITA

verzija: 26.06.2008.

Detaljna objanjenja vezana za bilo koji deo gradiva vezanog za


teoriju dostupna su u belekama sa predavanja, kao i u knjizi koja
opisuje jezik C dovoljno precizno:
Laslo Kraus Programski jezik C.

Vie zadataka se moe pronai u odgovarajuoj zbirci prof. Krausa:


Laslo Kraus, Zbirka zadataka iz programskog jezika C.

Sve ove knjige su dostupne u skriptarnici ili u biblioteci fakulteta.

Zadaci koji su tipa ispitnih pitanja su priloeni u celosti, ukljuujui i


obrazloenje reenja tamo gde je to potrebno.

U materijal je ukljueno i nekoliko ispitnih zadataka, koji su reeni u


potpunosti i komentarisani do odgovarajueg stepena opirnosti.

Materijal e biti stalno doraivan. Nove verzije e redovno biti


dodavane na Internet stranicu predmeta:

http://rti.etf.rs/ir1p2

Sugestije, primedbe i uoene greke poslati putem elektronske pote


na adresu oo1p2@etf.rs.

Ove materijale treba koristiti iskljuivo kao podsetnik


a nipoto kao jedini izvor znanja.

Nemojte NIKAD uiti programski kod napamet.

Svako ponavljanje bez razumevanja programskog koda


je tetno i na ispitu e biti kanjavano oduzimanjem poena.
Elektrotehniki fakultet Univerziteta u Beogradu Programiranje 2

SADRAJ
Predstavljanje realnih brojeva 3
Standard za aritmetiku realnih brojeva 3
Zaokruivanje 5
Zadatak Z12 6
Zadatak IZ3 6
Zadatak IZ4 7
Zadatak IZ5 8
Zadatak IZ34A (integralni ispit, 09.10.1998. godine) 9
Zadatak Z14 9
Programski jezik C 10
Zadatak C5 10
Zadatak C10 11
Operatori: prioritet i redosled primene 12
Zadatak C15 13
Zadatak C20 14
Zadatak C25 15
Zadatak C30 16
Zadatak C35 17
Zadatak C40 17
Zadatak C45 18
Zadatak C47 19
Zadatak C48 19
Zadatak C50 20
Zadatak C55 21
Zadatak C57 22
Zadatak C60 22
Zadatak C65 23
Zadatak C70 24
Zadatak C75 25
Zadatak C80b 26
Zadatak C90 27
Zadatak C95 28
Zadatak C100 29
Zadatak C104 30
Zadatak C110 32
Zadatak C115 33
Zadatak C120 34
Zadatak C122 37
Zadatak C125 41
Zadatak CI-2007-Jan-2 42
Zadatak CI-2006-Okt-1 43
Zadatak CI-2007-Okt-2 44
Zadatak CI-2006-Sep-2 45
Zadatak CI-2006-Jan-1 46
Zadatak CI-2006-Jan-2 48
Zadatak CI-2006-Sep-1 49
Zadatak C2008-A1 50
Zadatak C2008-S11 50
Zadatak C2008-S12 51
Zadatak C2008-S21 51
Zadatak C2008-S22 52

Materijal za vebe na tabli i pripremu ispita Strana 2/52


Elektrotehniki fakultet Univerziteta u Beogradu Programiranje 2

PREDSTAVLJANJE REALNIH BROJEVA


Standard za aritmetiku realnih brojeva
Raznolikost predstavljanja realnih brojeva u raunarima.
Problem portabilnosti numerikog softvera.
Standard za binarnu aritmetiku realnih brojeva u pokretnom zarezu:
ANSI/IEEE Std 754-1985.
(IEEE The Institute of Electrical and Electronics Engeneers
ANSI American National Standard Institute)

Standard specificira:
1. Osnovni i proireni format realnih brojeva
2. Operacije +, , *, /, ostatka (rem), kvadratnog korena( ) i komparaciju realnih brojeva
3. Konverzije: celi brojevi realni brojevi
4. Konverzije: realni brojevi realni brojevi (razliiti formati brojeva)
5. Konverzije: osnovni format realnih brojeva decimalni niz znakova
6. Rukovanje kodovima greaka

Osnovna osobina standarda: niz bitova, generisan kao rezultat aritmetike operacije, moe nositi
dvojaku informaciju:
1. ispravno obavljena operacija niz bitova je rezultat operacije
2. detektovana je neka greka niz bitova je binarno kodirani signal greke
(tzv. NaN = Not a Number)
Postoje dva tipa NaNa:
1. signalni NaN (signal NaN) signalizira neispravnu operaciju kad god se pojavi u ulozi
operanda
2. tihi (mirni) NaN (quiet NaN) za skoro sve aritmetike operacije ne signalizira neispravnost

U skladu sa IEEE standardom, realni brojevi se u memorijske rei smetaju na sledei nain:

memorijska re s eeeeeee mmmmmmmmmmm


broj bita u datom polju 1 k p
smisao polja znak eksponent mantisa

Ukupan broj bita: n = 1 + k + p

Vrednost tako predstavljenog realnog broja se rauna na sledei nain:

R = (1)s2EM

gde vrednosti s, E i M imaju sledea tumaenja:


s predstavlja znak datog broja (s=0 broj je pozitivan; s=1 broj je negativan)
E predstavlja celobrojni eksponent, ija se vrednost rauna u kdu sa vikom, kao E = e-v,
gde je
o e vrednost neoznaenog celog broja ija se vrednost dobija na osnovu bita eee...e,
polja eksponent
o v se naziva viak, a predstavlja celobrojnu vrednost koja se rauna: v=2k-1-1, gde je k
broj bita polja eksponent
M predstavlja vrednost mantise sa skrivenim bitom (videti objanjenje u nastavku)

Materijal za vebe na tabli i pripremu ispita Strana 3/52


Elektrotehniki fakultet Univerziteta u Beogradu Programiranje 2

U zavisnosti vrednosti bita polja eksponent, postoje etiri razliita naina tumaenja sadraja
memorijske rei u kojoj je smeten realan broj.

1. Kada biti polja eksponent nisu sve 0 ili sve 1 (e0000...0 i e1111...1), vrednost
eksponenta E se nalazi u opsegu [Emin, Emax] i tada memorijska re sadri uobiajen realni
broj sa normalizovanom mantisom. Vrednost mantise M se rauna dodavanjem skrivenog
bita vrednosti 1 i decimalnog zareza ispred niza bita polja mantisa: M=1.mmmmm...m.
Skriveni bit se podrazumeva pa zbog toga nije potrebno posebno ga skladititi u memorijskoj
rei.
2. Kada su biti polja eksponent sve 0 (e=0000...0), ali biti polja mantisa nisu sve 0
(m0000...0), tada memorijska re sadri realan broj sa nenormalizovanom mantisom.
Vrednost eksponenta E se u ovom specijalnom sluaju rauna kao E=e-v+1. Vrednost
mantise M se rauna dodavanjem skrivenog bita vrednosti 0 i decimalnog zareza ispred niza
bita polja mantisa: M=0.mmmm...m. Kao i u prethodnom sluaju, ovaj skriveni bit se
podrazumeva. Smisao realnih brojeva sa nenormalizovanom mantisom je proirenje opsega za
realne brojeve veoma male apsolutne vrednosti.
3. Kada su biti polja eksponent i mantisa sve 0 (e=0000...0, m=0000...0), tada memorijska
re sadri realan broj ija je vrednost 0. Treba primetiti da zbog znaka (bit s), standard
dozvoljava postojanje pozitivne i negativne nule (+0 i -0) ali izmeu njih ne pravi razliku (tj.
imaju istu vrednost).
4. Kada su biti polja eksponent sve 1 (e=1111...1), vrednost eksponenta E je vea od Emax i
razlikuju se dva sluaja:
a. vrednosti bita polja mantisa su sve 0 (m=0000...0) : realni broj ima vrednost (u
zavisnosti od vrednosti bita s)
b. vrednosti bita polja mantisa nisu sve 0 (m0000...0) : radi se o NaN-u, koji oznaava
matematiki nedefinisanu vrednost

Pozitivni realni brojevi, manji od najmanjeg realnog broja (minREALl) koji je mogue predstaviti sa
zadatim brojem bita se zaokruuju na vrednost 0 (tzv. potkoraenje, eng. underflow), dok se
pozitivni realni brojevi vei od najveeg realnog broja (maxREAL) zaokruuju na vrednost + (tzv.
prekoraenje, eng. overflow). Slino vai za negativne realne brojeve.
0
- [ ] | [ ] +
-maxREAL -minREAL minREAL maxREAL

Standardni formati realnih brojeva

IEEE Standard uvodi 4 formata realnih brojeva (format se odnosi na broj bitova pojedinih polja):
(1) jednostruki (2) jednostruki proireni (3) dvostruki (4) dvostruki proireni

FORMAT w k p v Emax Emin


jednostruki 32 8 23 +127 +127 -126
jednostruki proireni 43 11 32 nedef. +1023 -1022
dvostruki 64 11 52 +1023 +1023 -1022
dvostruki proireni 79 15 64 nedef. +16383 -16382

Materijal za vebe na tabli i pripremu ispita Strana 4/52


Elektrotehniki fakultet Univerziteta u Beogradu Programiranje 2
Jednostruki format

1 k=8 p = 23
s e e e e e e e e mmmmmmmmmmmmmmmmmmmmmmm
31 30 23 22 0

Opseg brojeva:
1. Najmanji nenormalizovani: e=0 R = (1)s2-126(0.000001)
2. Najvei nenormalizovani: e=0 R = (1)s2-126(0.111111)
3. Najmanji normalizovani: e=1 R = (1)s2-126(1.000000)
4. Najvei realan broj: e=254 R = (1)s2127(1.111111)

minREAL = (1)s2-1262-23 = (1)s2-149 (1)s1.410-45

maxREAL = (1)s 2127(1.111...1) (1)s2128 = (1)s3.41038

Zaokruivanje
Zbog ogranienog broja bita polja mantisa, najee nije mogue prezicno smetanje realnog broja u
memorijsku re, ve se pristupa zaokruivanju. Podrazumeva se da je posmatrani broj, pre smetanja
u memorijsku re, beskonano precizan, pa se zaokruivanje vri sa ciljem da se uklopi u odredini
format. Skoro sve operacije nad realnim brojevima daju najpre beskonano precizan rezultat koji se
potom zaokruuje prema odredinom formatu.
1. Osnovni nain zaokruivanja: prema najblioj vrednosti.
2. Ako su dve zaokruene vrednosti podjednako udaljene od beskonano precizne vrednosti
bira se ona vrednost kod koje je bit najmanjeg znaaja 0.
3. Ako je apsolutna vrednost beskonano precizne vrednosti:
|R| 2Emax(22p), vri se zaokruivanje na (1)s()
p i Emax se odreuju iz odredinog formata.

U praksi, ovo znai sledee (desno od vertikalne crte se nalaze biti koji se odbacuju):

1 2 3 4
binarna x.xx | 0zzz...zzz x.xx | 1yyy...yyy x.x0 | 100...00 x.x1 | 100...00
predstava broja (makar jedan y je 1)
vrednost na koju x.xx x.xx + 0.01 x.x0 x.x1 + 0.01
se zaokruuje

Ako se paljivije pogleda, ovakav nain zaokruivanja odgovara uobiajenom nainu zaokruivanja
realnih brojeva.

Gubitak tanosti ima za posledicu da kod raunarskog sabiranja realnih brojeva ne vai uvek zakon
asocijativnosti.

Primer1: decimalni raunar sa 4 znaajne cifre:


R=123.4, r=0.049 R+r=123.449 123.4
Z1 = ((R+r)+r)+r = 123.4
Z2 = ((r+r)+r)+R = 123.4+0.147 = 123.547 123.5 Z1

Opte pravilo: poeti sumiranje od brojeva manje apsolutne vrednosti.

Materijal za vebe na tabli i pripremu ispita Strana 5/52


Elektrotehniki fakultet Univerziteta u Beogradu Programiranje 2

Zadatak Z12
Za smetanje realnih brojeva koriste se 8 bitova od kojih 3 bita predstavljaju eksponent u kodu sa
vikom. Mantisa se smeta sa skrivenim bitom. Za brojeve vee od nule odrediti najmanju i najveu
vrednost koja se moe predstaviti na gornji nain.

Zadatak IZ3
Napomena: ovaj zadatak ilustruje razliku izmeu savremenog IEEE standarda za reprezentaciju
realnih brojeva i standarda VAX koji mu je prethodio.
Format predstave realnih brojeva je seeeemmmmm s je bit za znak broja, eeee su bitovi za
eksponent broja (kd sa vikom), a mmmmm su bitovi normalizovane mantise (sa skrivenim bitom).
U raunaru A predstava realnih brojeva je sa vikom 8, a u raunaru B sa vikom 7. U raunaru A
mantisa je 0.5MA<1, a u raunaru B mantisa je 1MB<2. Izgled jednog broja u raunaru B, u
skladu sa opisanim formatom, je 3DF16. Kako je predstavljen realan broj iste vrednosti u raunaru A?
A) 3DF16
B) 3FF16
C) 3FE16
Reenje
Prvi nain: Mogue je rei, da je predstava realnih brojeva u raunaru B u skladu sa duhom IEEE
standarda, imajui u vidu da je viak 7 = 24-1 -1, a mantisa je oblika MB = 1.mmmmm.
Zbog toga, broj 3DF16 = 1|1110|111112 predstavlja maxREAL, kad je raunar B u pitanju.

Mogue je zakljuiti, da je predstava realnih brojeva u raunaru A u skladu sa starom (VAX)


predstavom brojeva (8 = 24-1, MA = 0.1mmmmm).

Kako je maxREALIEEE = 2maxREALVAX, moe se zakljuiti da ovaj broj nije mogue predstaviti u
raunaru A, jer je maxREALVAX dva puta manji od posmatranog broja.

Drugi nain:
B: 3DF16 = 1|1110|111112 EB = eeeeB 7 = 7 MB = 1.mmmmmB = 1.111112

XB = 1.11111227 = 111111002 XA = XB = 0.111111228

MA = 0.1mA mA = 111112

EA = eA + 8 = 1610 = 100002 a to nije mogue predstaviti u polju eA koje je irine 4 bita.

Odgovor: N

Materijal za vebe na tabli i pripremu ispita Strana 6/52


Elektrotehniki fakultet Univerziteta u Beogradu Programiranje 2

Zadatak IZ4
Format predstave realnih brojeva pomou rei irine 10 bita je: bit najvee teine za znak broja,
etiri bita za eksponent u kdu sa vikom 7, i pet bitova najmanje teine za normalizovanu mantisu
sa skrivenim bitom (1M<2). Rezultat sabiranja brojeva iji je izgled A=16068 i B=05158 je:
A) 16338
B) 15668
C) 17668
Reenje
A: 1|1100|00110 B: 0|1010|01101
SA=1 A <0 SB=0 B >0
EA=127=5 EB=107=3
MA=1.00110 MB=1.01101

EA > EB B = MB2EB = MB2EBEA2EA = MB222EA = MB2EA; MB = MB / 22

MB = 0.01011|01 |MA| > |MB| A + B = (MA MB)2EA = MA+B2EA

MA = 1.00110
MB = 0.01011

MA+B = 0.11011 ovde se mora izvriti normalizacija.

MA+B = 1.1011021

A + B = MA+B2EA = 1.10110212EA = 1.101102EA-1 = MA+B2EA+B

SA+B = 1 MA+B = 1.10110 EA+B = EA 1 = 4 eA+B = 4 + 7 = 11

s = 1, eeee = 1011, mmmmm = 10110

(A + B) : 1|1011|10110 = 1|101|110|110 =15668

Odgovor: B

Materijal za vebe na tabli i pripremu ispita Strana 7/52


Elektrotehniki fakultet Univerziteta u Beogradu Programiranje 2

Zadatak IZ5
U nekom raunaru, celi brojevi su predstavljeni u drugom komplementu pomou rei irine 10 bita,
a za predstavljanje realnih brojeva je takoe predvieno 10 bita, i to tako da bit najvee teine
odreuje znak broja, sledea 4 bita su za eksponent broja u kdu sa vikom 7, a preostalih 5 za
normalizovanu mantisu sa skrivenim bitom (1M<2). Ako je izgled realnog broja na lokaciji X: 39716,
a izgled celog broja na lokaciji J: 31016, koji e biti izgled lokacije realne promenljive Y nakon izvrene
operacije Y=X+J? Raunanje obavljati upotrebljavajui realne brojeve.
A) 3FA16
B) 3E516
C) 3BA16
Reenje
X: 1|1100|10111 J: 1100010000
J = 0011110000 = 1.11127
SX = 1, X<0 SJ = 1, J<0
MX = 1.10111 MJ = 1.11100
EX = 12 7 = 5 EJ = 7

EJ > EX
X = MX2-227
MX = 0.01101|11 0.01110

Y = (MJ + MX) 2Ej

MJ= 1.11100
+MX= 0.01110

MY =10.01010 = 1.00101 21

Y = MY 2EY+1 = -1.00101 28

s = 1, e = 8 + 7= 1510 = 11112, eeee = 1111, mmmmm = 00101

Y: 1|1111|00101 = 3E516

Odgovor: B

Materijal za vebe na tabli i pripremu ispita Strana 8/52


Elektrotehniki fakultet Univerziteta u Beogradu Programiranje 2

Zadatak IZ34A (integralni ispit, 09.10.1998. godine)


Realni brojevi se predstavljaju sa 11 bita formatom seeeeemmmmm gde je s bit za predznak
broja, eeeee (5) biti eksponenta u kodu sa vikom 8, a mmmmm (5) biti normalizovane mantise sa
skrivenim bitom 0.5<=M<1. Celi brojevi predstavljaju se sa 10 bita u drugom komplementu. Ceo broj
I ima izgled 17716 a ceo broj J ima izgled 32516. Najpre se izvri celobrojno sabiranje N=I+J. Zatim se
izvri konverzija brojeva I i J u realne brojeve, i sabiranjem tih realnih brojeva dobije broj B. Kolika e
biti apsolutna vrednost razlike brojeva N i B? (Napomena: Sva zaokruivanja vre se prema pravilima
IEEE standarda, a svi koraci u sabiranju realnih brojeva vre se na irini odreenoj formatom
mantise.)
A) 4 B) 8 C) 2.125
Reenje
Prvo emo izvriti celobrojno sabiranje.
I = 17716 = 01 0111 0111
J = 32516 = 11 0010 0101
I+J= 100 1001 1100
Poto u memoriji imamo samo 10 bita sa predstavljanje celih brojeva, jedanaesti bit koji je generisan
u procesu sabiranja otpada i dobijamo 00100111002 = 9C16 = 15610 kao reenje.
Realno sabiranje se vri tako to prvo celobrojne vrednosti konvertujemo u realne, uz potrebna
zaokruivanja, a potom dobijene realne vrednosti saberemo.
I: J: 11 0010 0101, to znai da je J<0.
0101110111 = 0.1011101112 0.1011112 s -J: 00 1101 1011 = 0.1101101128 0.11011128
9 9

Sada je potrebno svesti ova dva broja na isti eksponent i pri tome izvriti zaokruivanja, ako se za
tim ukae potreba:
J = (-1)0.11011128 = (-1)0.011011128 (-1)0.01110028.
Poto su brojevi razliitog znaka, oduzimamo mantisu manjeg od mantise veeg broja:
MI: 0.101111
-MJ: - 0.011100
MI-MJ: 0.100110
Traeni broj izgleda ovako: 0.10011028, to je jednako pozitivnom celom broju 00100110002 = 9816
= 15210.
Odavde se moe zakljuiti da je apsolutna razlika ova dva zbira jednaka 4.
Napomena: Kada se vri konverzija iz celobrojnog u realni broj, vri se zaokruivanje na po
vrednosti najblii realni broj koji se moe predstaviti u memoriji datog raunara. Konverzija u
obrnutom smeru podrazumeva ili zaokruivanje poetnog realnog broja na po vrednosti najblii celi
broj ili prosto odsecanje razlomljenog dela realnog broja. Ako nije posebno naglaeno, podrazumeva
se prvi pristup.

Odgovor: A

Zadatak Z14
Brojevi sa pokretnom takom u raunaru imaju binarni oblik seeeeeemmmmmmmmm, gde je s
bit za znak broja, m su bitovi normalizovane mantise sa skrivenim bitom (0.5M<1), e su bitovi
eksponenta u kodu sa vikom 25. Nai zbir brojeva x i y iji su oblici u raunaru zadati u brojnom
sistemu sa osnovom q. Rezultate proveriti pretvaranjem zadatih vrednosti i rezultata u decimalni
brojni sistem.

Materijal za vebe na tabli i pripremu ispita Strana 9/52


Elektrotehniki fakultet Univerziteta u Beogradu Programiranje 2

PROGRAMSKI JEZIK C
Zadatak C5
Sledei program za odreivanje reenja linearne jednaine Ax+B=0, za A<>0, napisan na
programskom jeziku C, sadri vie greaka. Ispraviti sve greke!
main main predstavlja funkciju treba da stoji main()
Float _x,a,b C je CaseSensitive jezik (razlikuje mala i velika slova)
deklaracija treba da stoji unutar programskog bloka
{
scanf('%f %f',a,b); niz znakova u jeziku C se ogranicava parom znakova "
scanf zahteva adresu, a ne vrednost; Prevodilac za jezik C ne
prijavljuje ovo kao gresku.
_x=-b/a;
printf('%f',_X) _X nije dobro, jer smo deklarisali _x
}

Reenje:
Ispravljeni program izgleda ovako:
#include <stdio.h> /* na poetku svakog programa dolaze direktive */
main()
{
float _x,a,b; /* _x ne smeta (Promenljiva moze sadrzati znak _ ) */
scanf("%f %f",&a,&b);
_x=-b/a;
printf("%f",_x); /* svaka naredba jeziku C zavrava se znakom tacka-zarez; */
}

Komentar:
Neispravno napisan program je testiran i kompajliran u programskom paketu Visual Studio.net.
Poruke kompajlera su sledee:
Compiling...
c5.c
c5.c(5) : error C2061: syntax error : identifier 'Float'
c5.c(5) : error C2059: syntax error : ';'
c5.c(7) : error C2143: syntax error : missing ';' before '{'
c5.c(7) : error C2449: found '{' at file scope (missing function header?)
c5.c(8) : error C2015: too many characters in constant
c5.c(14) : error C2059: syntax error : '}'
Na poetku svakog programa koji neto uitava ili ispisuje mora postojati direktiva include sa
parametrom <stdio.h>. Ovo predstavlja uputstvo prevodiocu da iz datoteke stdio.h treba da
proita osobine bibliotekih funkcija za ulaz i izlaz podataka.

Materijal za vebe na tabli i pripremu ispita Strana 10/52


Elektrotehniki fakultet Univerziteta u Beogradu Programiranje 2

Zadatak C10
Sastaviti program na programskom jeziku C za ispisivanje tablice ASCII kodova za sve tampajue
znake.
Reenje
ASCII kod sa brojem 32 je blanko simbol ili razmak. Prva 32 ASCII koda (od 0 do 31) i svi ASCII
kodovi vei ili jednaki 127 predstavljaju specijalne simbole koji se koriste u razliite svrhe i najee
nemaju neko jasno slovno znaenje. Koristili su se za iscrtavanje DOS prozora, i na taj nain simulirali
grafiku u tekstualnom reimu rada. Konkretno, prozori razvojnog okruenja Turbo C su napravljeni na
ovaj nain! ASCII kodovi izmeu 32 i 126 su tampajui znaci, i ima ih ukupno 95.
Znaci se prikazuju po kolonama. U jednoj koloni se prikazuje po 19 znakova, a u jednom redu se
prikazuje po 5 znakova (5x19=95). Prikazaemo sve ASCII kodove od 32 do 126.
Program za prikazivanje tablice ASCII kodova moe se realizovati na vie naina.
I nain
#include <stdio.h>
main()
{
char c;
int i;
printf ("\t\tTablica ASCII kodova \n \n");
for(c = ' '; c < ' ' + 19; c++)
{
for(i = 0; i < 95; i += 19)
printf("%3d%c ", c+i, c+i);
putchar('\n');
}
}

II nain ovako NE TREBA raditi!!!


#include <stdio.h>
main()
{
char c=' ';
int i;

printf ("\t\tTablica ASCII kodova \n \n");


linija:
i=0;
znak:
printf("%3d %c ", c+i, c+i);
i=i+19;
if (i<95) goto znak;
printf("\n");
c=c+1;
if (c<' '+19) goto linija;
}

Komentar:
U drugom reenju se koristi skok sa proizvoljnim odreditem: goto. Korienje naredbe goto treba
izbegavati (bilo koji algoritam koji sadri goto moe se ostvariti na neki drugi nain, to i pokazuje prvo
reenje). Glavni razlog za izbegavanje naredbe goto je taj to ta naredba ima veliki stepen slobode u izboru
odredita skoka tako da omoguava sastavljanje nestrukturiranih, vrlo nepreglednih programa, koji jako esto
sadre mnogo greaka uzrokovanih upravo loom strukturom.

Materijal za vebe na tabli i pripremu ispita Strana 11/52


Elektrotehniki fakultet Univerziteta u Beogradu Programiranje 2

Operatori: prioritet i redosled primene


SMER
PRIORITET BROJ OPERANADA OPERATORI
GRUPISANJA
15 2 [] () . ->
14 1 ! - ++ -- + - * & (tip) sizeof
13 2 * / %
12 2 + -
11 2 << >>
10 2 < <= > >=
9 2 == !=
8 2 &
7 2 ^
6 2 |
5 2 &&
4 2 ||
3 3 ?:
2 2 = += -= *= /= %= &= ^= |= <<= >>=
1 2 ,

Primeri
Relacijski operatori Operatori za dodelu vrednosti
Izraz Objanjenje (rezultat) Izraz Objanjenje
5 > 7 0 y = a * x + b
10 <= 20 1 d *= e + f d = (d*(e+f))
8 == 13 > 5 8==(13>5) -> 8==1 -> 0 d = d * e + f d = ((d*e)+f)
14 > 5 < 3 (14>5)<3 -> 1<3 -> 1 a=b=c=d+5 c=d+5,b=c,a=b
a < b < 5 (a<b)<5 -> (0/1)<5 -> 1 a = b++ + c=d<<3,u=b,b=b+1,a=u+(3*c)
a+5 >= c-1.0/e (a+5)>=(c-(1.0/e)) 3*(c=d<<3)
a = b++ + 3*c greka !
= d<<3

Redosled raunanja i boni efekti


((a<<5)+4/b)*(d-=c-2) * ++e
Standard garantuje da e se pre mnoenja izraunati vrednosti operanada u zagradama. Standard ne
precizira kojim e se redom raunati (prvo levi ili prvo desni operand) implementaciona zavisnost.
Ako rezultat zavisi od redosleda izraunavanja operanada - lo stil pisanja izraza.
Boni efekti: uzgredna promena vrednosti jedne ili vie promenljivih. Rezultat zavisi od redosleda
izraunavanja operanada ako se bar jedna promenljiva, koja podlee uticaju nekog bonog efekta,
koristi na vie od jednog mesta u izrazu. Operatori koji proizvode bone efekte su ++, -- i svi
operatori dodele vrednosti.
Izraz Objanjenje
a=b*c + b++ u=b*c, v=b, b++, a=u+v
v=b, b++, u=b*c, a=u+v
a=b*c+(b=d/e) u=b*c, v=(b=d/e), a=u+v
v=(b=d/e), u=b*c, a=u+v
a[i] = ++i Indeksiranje je bin.op.
u=i, ++i, v=i, a[u]=v
i++, v=i, u=i, a[u]=v

Materijal za vebe na tabli i pripremu ispita Strana 12/52


Zadatak C15
Odrediti emu su ekvivalentni sledei izrazi (koristiti zagrade da bi se eksplicitno odredio redosled
izraunavanja)
1. x+=y-=m
2. n%=y+m
3. m++ - --j
4. x=j * j++
5. ++j==m!=y*2

Odgovor:
1. x=(x+(y=(y-m))
2. n=(n % (y+m))
3. m-(j-1); m=m+1; j=j-1
4. x=j * j++ ; ovo zavisi od toga kojim se redom racuna, sa leva na desno ili obrnuto
Odgovor: implementaciono zavisno
5. ((j+1)==m)!=(y*2); j=j+1

Primer Boni efekti (autor: Jelica Proti)


Sledei primer ilustruje manifestovanje bonih efekata u 8 razliitih izraza, za razliite prevodioce
jezika C. Inicijalna vrednost promenljive j je 5.
izraz VS 6.0 VS .NET 2003 TC 2.0 GNU GCC ARM C
1. j * j++ 25 25 30 25 30
2. j++ * j 25 25 30 25 30
3. ++j * j 36 36 36 36 36
4. j * ++j 36 36 36 36 36
5. (j=3) * (j++) 9 9 9 9 9
6. (j=3) * (++j) 16 16 12 12 12
7. (j++) * (j=3) 9 9 15 9 15
8. (++j) * (j=3) 9 9 18 9 18
Pitanje: zato VS dobija 16 kao rezultat u primeru 6?
Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C20
Sastaviti program na programskom jeziku C koji uitava srednje temperature po mesecima za 12
meseci i na osnovu njih izrauna i ispie srednju temperaturu za celu godinu.
Reenje:
#include <stdio.h>
#define BROJ_MESECI 12
main()
{
enum meseci {JAN=1,FEB,NAR,APR,MAJ,JUN,JUL,AVG,SEP,OKT,NOV,DEC};
enum meseci mesec=JAN;
/*
Moguce je umesto gornje dve linije napisati samo jednu:
enum meseci {JAN=1,FEB,NAR,APR,MAJ,JUN,JUL,AVG,SEP,OKT,NOV,DEC} mesec=JAN;
*/
float temperature[BROJ_MESECI];
float srednja_temp=0;

while (1)
{
printf("Temperatura za mesec %2d: ",mesec);
scanf("%f",&temperature[mesec - 1]); /* niz u C-u uvek ide od 0 */
srednja_temp+=temperature[mesec - 1];
if (mesec==DEC) break;
mesec++;
}

srednja_temp/=BROJ_MESECI;
printf("Srednja temperatura je %.2f\n",srednja_temp);
}

/*
Jasno je da nam niz nije potreban za racunanje srednje vrednosti
dovoljno je da mesecnu temperaturu ucitavamo u neku pomocnu (float)
promenljivu i da nju dodajemo na srednja_temp
*/

Komentar
Prikaz nekih vrednosti adresa i niza temperature:
&temperature,p: 22FC(SS):0FCC
&temperature[0],p: 22FC(SS):0FCC - adresa clana 0
&temperature[1],p: 22FC(SS):0FD0 - adresa clana 1
temperature: { 3.0,8.0,12.0,15.0,20.0,26.0,29.0,30.0,26.0,20.0,13.0,7.0 }
- prikaz celog niza
temperature[0]: 3.0 - vrednost clana sa indeksom 0
Ovakav prikaz se moe dobiti pomou Watch prozora razvojnog okruenja Turbo C. Najpre se navodi izraz ija
se vrednost posmatra, a onda nain kako ona treba da bude ispisana. Uz pomo ovog dodatka, moe se isti
izraz posmatrati na vie naina.
izraz,d kao broj
izraz,c kao karakter
izraz,p kao pokaziva (adresa)

Materijal za vebe na tabli i pripremu ispita Strana 14 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C25
Sastaviti program na programskom jeziku C za odreivanje broja velikih slova, malih slova i cifara
u tekstu koji se iz proizvoljnog broja redova uitava preko glavne ulazne jedinice. Tekst se zavrava
znakom za kraj datoteke.
Reenje
#include <stdio.h>
#include <ctype.h> /* treba za funkcije vezane za ispitivanje slova */
main()
{
int znak, vel_sl=0, mal_sl=0,cifra=0;

printf("Unesite zeljeni tekst \n");

while ((znak=getchar())!=EOF)
{
vel_sl += isupper(znak) != 0; /* ctype.h */
mal_sl += islower(znak) != 0; /* ctype.h */
cifra += isdigit(znak) != 0; /* ctype.h */
}
printf("Velikih slova ima %d\n",vel_sl);
printf("Malih slova ima %d\n",mal_sl);
printf("Cifara ima %d\n",cifra);
}

Komentar
U zaglavlju ctype.h se nalaze prototipovi funkcija za ispitivanje znakova. U ovom programu su upotrebljene
sledee funkcije:
- isupper(znak): ispituje da li je zadovoljen uslov (znak>='A') && (znak<='Z')
- islower(znak) : ispituje da li je zadovoljen uslov (znak>='a') && (znak<='a')
- isdigit(znak) : ispituje da li je zadovoljen uslov (znak>='0')&&(znak<='9')
Sve is_ funkcije vraaju 0 za logiku neistinu, a razliito od 0 (ne obavezno 1) za logiku istinu

Materijal za vebe na tabli i pripremu ispita Strana 15 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C30
Sastaviti program na programskom jeziku C koji uitava decimalan pozitivan celi broj u obliku niza
znakova i ispisuje njegovu vrednost u binarnom obliku. Pretpostaviti da se za interno predstavljanje
celih brojeva koristi 16 bitova.
Reenje
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
main()
{
char dec[10];
short int bin, i;

printf("Unesite decimalan broj: ");


scanf("%s",dec); /* ucitava string sa standardnog ulaza (dec=&dec[0]) */
/*
atoi vraca 0 ukoliko nije uspela konverzija.
Ukoliko je strlen(dec)=0 onda se drugi deo USLOVA (iza && operatora)
nece ni proveravati. Po postavci zadatka ocekuje se pozitivan broj,
i takav uslov se jednostavno, ovim putem, moze proveriti.
*/
if (strlen(dec) && (bin=atoi(dec)))
{
printf("Binarni broj: ");
i=-1;
while (++i<16)
{
putchar((bin & 0x8000) ? '1' : '0');
/*
0x8000 ima jedinicu na najvisem 15-om bitu
Gornja naredba ce ispisati 15-i bit broja bin!
Najpre ispisujemo najvise bitove, jer takav prikaz zelimo na ekranu
bit15 bit14 ... bit2 bit1 bit0
*/
bin <<= 1 ; /* bin = bin shl 1 ; pomeramo bin ulevo za 1 bit */
if (i%4 == 3)
putchar(' '); /* prikaz razmaka izmedju svake polovine bajta */
}
printf("\n");
}
else
printf("Neispravan broj ili nula\n");
}

Komentar
16-bitni binarni broj moe da ima najveu vrednost 65535, ukoliko se tretira kao unsigned, odnosno 32767,
ukoliko se tretira kao signed. To konkretno znai da je za ovaj 16-bitni prikaz dovoljno koristiti niz brojeva
char dec[6] (5 za cifre i 1 za terminator). Sa druge strane, ako se u ovom zadatku unese neki broj vei od
65535/32767 rezultat nee biti ispravan (bie prikazano samo najniih 16-bitova zadatog broja ako je short int
na datom raunaru dui od 16 bita).
Funkcija atoi se moe koristiti i za konverziju negativnih vrednosti.
Treba imati na umu i sledeu injenicu: ako se unese vie od 10 znakova nepredvidiv je ishod izvravanja
ovog programa, jer niz 'dec' ima dodeljeno svega 10 znakova (bajtova) u memoriji i nita preko toga! Ostatak
memorije pripada drugim podacima ili drugom programskom kodu, tako da se upisivanjem van granica niza
moe izazvati nepredvidivo ponaanje.

Materijal za vebe na tabli i pripremu ispita Strana 16 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C35
Koja od datih konstrukcija na programskom jeziku C predstavlja ekvivalent iskaza na programskom
jeziku Pascal: if (a>b) then begin a:=1; b:=1 end
A) if (a>b) { a=1; b=1; }
B) if (a>b) a=1, b=1;
C) if (a>b) a=1; b=1;

Komentar
Odgovor e biti A ili V (A i B), zavisno od toga kako se definie ekvivalentnost dva iskaza.
A) Ovo je upravo prepisana selekcija sa Pascala na C.
B) Ukoliko je ispunjen uslov bie izvrena jedna instrukcija u then grani, pri emu se ona sastoji od
2 izraza. Efekat izvravanja ova dva izraza je u ovom sluaju identian sluaju pod A).
C) b=1 se izvrava u svakom sluaju, to ne vai za originalni segment.

Zadatak C40
ta ispisuju sledei programi?
a) b)
#include <stdio.h> #include <stdio.h>
main() main()
{ {
int x; int x=0,i;
for (x=0;x<100;x++) for (i=0;i<5;i++)
{ switch (i)
/* ako x nije deljivo sa dva {
vrati se na pocetak tela ciklusa */ case 1: x+=1;
if (x%2) /* ukoliko je i=1 izvrsava se deo
continue; iza case 1: i case 2: */
/* do ovde dolazi samo ako je case 2: x+=2; break;
x deljivo sa 2 (x mod 2 = 0) */ /* Ako je i=2 izvrsava se samo deo
printf("%d\n",x); iza case 2: (zbog break;) */
} case 4: x+=3;
} /* Ako je i=4 izvrsava se samo deo
A) Sve cele brojeve od 0 .. 99 iza case 4: */
}
B) Sve parne brojeve od 0 .. 99 printf("d=%d\n",x);
C) Sve neparne brojeve od 0 .. 99 }
A) 5
Odgovor
B) 6
B C) 9
Odgovor
N
Komentar
Najpre je x=0;
Za i=0, x se ne menja (x=0);
Za i=1, x+=1; x+=2; => x=3;
Za i=2, x+=2; => x=5;
Za i=3, x se ne menja;
Za i=4, x+=3; => x=8;

Materijal za vebe na tabli i pripremu ispita Strana 17 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C45
Sastaviti program na programskim jeziku C koji formira sluajan celobrojni niz sastavljen od
jednocifrenih brojeva i izvri ureivanje niza po neopadajuem redosledu vrednosti brojeva.
Reenje:
Za sortiranje brojeva postoji niz algoritama. Vie detalja o ovoj oblasti se moe pronai u knjizi
Strukture podataka profesora Tomaevia. Ovde je predstavljen najjednostavniji algoritam pod
nazivom Selection sort, odnosno sortiranje metodom izbora. Ideja je sledea: u i-tom prolazu se
odabere i-ti (u ovom sluaju) najmanji broj, pa se smesti na i-to mesto.
#include <stdio.h>
#include <stdlib.h>
#define DIM 50

main()
{
int n,a[DIM],i,j,b;
for (;;)
{
printf("\n\n Duzina niza (max %d): ",DIM); scanf("%d", &n);
if ((n <= 0) || (n > DIM)) break;
/* break prekida for ciklus. Ovo je ciklus sa izlazom u sredini */
printf("\nPocetni niz: \n\n");
for (i=0;i<n;i++)
printf("%d%c", a[i] = rand()/((double)RAND_MAX+1.0)*10,
(i % 30 == 29 || i == n-1) ? ('\n') : (' '));
/* Generisace se slucajni brojevi u intevalu od 0 .. 10.
rand() generise slucajan broj od 0 .. RAND_MAX
(RAND_MAX je u slucaju TurboC-a 32767 ) */

/* sledi sortiranje */
for (i = 0; i < n-1; i++)
for (j = i+1; j < n; j++)
if (a[i] > a[j]) b = a[i],a[i] = a[j],a[j] = b; /* zamena 2 promenljive */

printf("\nSortirani niz:\n\n");
for (i = 0; i < n; i++)
printf("%d%c", a[i], (i % 30 == 29 || i == n-1) ? ('\n') : (' '));

/* Deo (i%30==29 || i==n-1) ? ('\n') : (' ') predstavlja karakter


koji treba da se napise iza broja (Clana) niza. Ukoliko se nalazimo
na kraju niza (poslednji element i==n-1), ispisujemo znak za novi red.
Takodje, radi jasnijeg prikaza posle svakog 30-tog clana niza ispisujemo
isto znak za novi red. U svakom drugom slucaju ispisuje se blanko (razmak).*/
}
}
Primer sortiranja 10 sluajnih brojeva:
Prolaz 1: a: { 2, 4, 1, 6, 5, 0, 1, 8, 6, 7 }
Prolaz 2: a: { 0, 4, 2, 6, 5, 1, 1, 8, 6, 7 }
Prolaz 3: a: { 0, 1, 4, 6, 5, 2, 1, 8, 6, 7 }
Prolaz 4: a: { 0, 1, 1, 6, 5, 4, 2, 8, 6, 7 }
Prolaz 5: a: { 0, 1, 1, 2, 6, 5, 4, 8, 6, 7 }
Prolaz 6: a: { 0, 1, 1, 2, 4, 6, 5, 8, 6, 7 }
Prolaz 7: a: { 0, 1, 1, 2, 4, 5, 6, 8, 6, 7 }
Prolaz 8: a: { 0, 1, 1, 2, 4, 5, 6, 6, 8, 7 }
Prolaz 9: a: { 0, 1, 1, 2, 4, 5, 6, 6, 7, 8 }

Materijal za vebe na tabli i pripremu ispita Strana 18 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C47
Koji od programskih segmenata na programskom jeziku C daju isti izlaz kao dati programski
segment na programskom jeziku Pascal?
j:= -2;
for i:= -2 to j*j do
begin write(j:3); j:=j+1 end;
A) for (i=j=-1;i<=j*j;i++,j++) printf(" %3d ",j);
B) i=-2; while (printf(" %3d ",i),i++ -4);
C) i=j=-2; while (i++ == 4 ? 0 : 4) printf(" %3d ",j++);

Obrazloenje:
U programskom jeziku Pascal se interval for ciklusa odreuje neposredno po ulasku u ciklus i ne
menja se u toku izvravanja ciklusa, dok se u programskom jeziku C uslov kod for ciklusa rauna pre
svakog ponavljanja.
Ovaj programski segment na programskom jeziku Pascal ispisuje -2,-1,0,1,2,3,4.
Programski segment (A) na programskom jeziku C je logiki neispravan, jer i nikada nee prestii
vrednost j*j. Dodirna taka im je za i==0,j==0 i i==1,j==1, ali posle toga zbog obostranog
inkrementiranja i e biti uvek manje od j*j. U realnosti, u nekom trenutku e doi do prekoraenja
opsega celih brojeva, i j*j e postati manje od i, za vrednost j takvu da vrednost izraza j*j
prekorauje maksimalni celi broj.
Programski segment (B) na programskom jeziku C je logiki ispravan i ispisuje iste vrednosti kao i
dati programski segment na programskom jeziku Pascal. Zadnji ispisani broj je 4, tada se ne postie
uslov za ulaz u petlju (i-4 == 0, to predstavlja logiku neistinu), a kao boni efekat i=5.
Programski segment (C) na programskom jeziku C je logiki ispravan. Meutim, on ne ispisuje iste
vrednosti kao i programski segment na programskom jeziku Pascal. Ispisuje jedan broj manje (tj. sve
od -2 do 3). Iz ciklusa se izlazi kada je i==4. Broj koji se ispisao pre toga je bio 3, a boni efekat je
bio j=4.

Zadatak C48
Data su tri segmenta programa na programskom jeziku C:
I
for (i=x=y=0; ; ++i)
{x++; if (i==n) break; y++; }
printf(%ld %ld,x,y);

II
x=0, y=0;
for (i=0; i<=n; i++)
{x=x+1; if (i<n) continue; y=y+1;}
printf(%ld %ld,x,y);

III
x=i=0;
while (i<=n)
{ i++; ++x; y=x>n;}
printf(%ld %ld,x,y);
Ako su sve promenljive celi brojevi koja dva segmenta daju isti izlaz za n>0?
A) I i II B) II i III C) I i III
Obrazloenje:
I uvek ispisuje x=n+1, y=n,a II i III uvek ispisuju x=n+1, y=1 (n ne utie na vrednost y).

Materijal za vebe na tabli i pripremu ispita Strana 19 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C50
Napisati na programskom jeziku C program koji analizira tekst koji se unosi sa standardnog ulaza,
prepoznaje realne brojeve po formatu cc...c.ddd...d i ispisuje ih po formatu c.ddE+ee, a sve
ostale uitane znake ispisuje bez izmene.
Reenje
#include <stdio.h>
#include <ctype.h>
#define DECIMALNA_TACKA '.'
#define ZNAK_ZA_KRAJ '!'

main()
{
int c, j, broj_cifara;
double vrednost, decimala;

do
{
/* sve dok se ne pojavi neka cifra, ispisuju se karakteri sa ulaza */
while (! ( isdigit(c = getchar()) || (c==ZNAK_ZA_KRAJ) ) )
putchar(c);
if (c == ZNAK_ZA_KRAJ)
break; /* Ukoliko je nadjen znak ! onda se prekida glavna petlja */

vrednost = 0.;
broj_cifara = 0;
/* sve dok se ne naidje na tacku, dodaje se vrednosti pritisnuta cifra na kraj */
while ( isdigit(c) )
vrednost = vrednost * 10 + (c-'0'), c = getchar();
if (c == DECIMALNA_TACKA)
/* sve dok se unose cifre, dodaju se na kraj decimalnog dela */
{
c=getchar();
while ( isdigit(c) )
{
broj_cifara++;
decimala = c - '0';
for (j=0; j < broj_cifara; j++)
decimala/=10;
vrednost += decimala;
c = getchar();
}
}
ungetc(c,stdin);
printf("%1.2E",vrednost);
} while (c != ZNAK_ZA_KRAJ); /* '!' je trenutno znak za kraj */
}

Obrazloenje
Iz programa se izlazi ukoliko se bilo gde u liniji upie znak '!'
Od unete cifre, broj koji ona predstavlja dobija se kada se od njenog ASCII koda oduzme ASCII
kod znaka '0'.
Pitanje
ta e se dobiti na izlazu za sledei red?
123.123.123
Odgovor:
1.23E+02.1.23E+02

Materijal za vebe na tabli i pripremu ispita Strana 20 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C55
ta ispisuje sledei program?
a)
/*C55a*/
#include <stdio.h>
main()
{
int a[]={1,0}, *p;
p=a;
printf("%d, ", *p++);
printf("%d\n", *p);
}
A) 1, 2 B) 1, 0 C) 0, 0
Komentar
Odgovor je B. Prioritet * i ++ je isti, ali je asocijativnost ove grupe operatora sdesna ulevo.
b)
/*C55b, J.Protic*/ printf("\n");
#include <stdio.h> for (p=&a[0], i=0; p+i<a+4; p++, i++)
main() printf("%d", *(p+i));
{ printf("\n");
int a[]={0, 1, 2, 3, 4}; for (p=a+4, i=0; i<=4; i++)
int i, *p; printf("%d", p[-i]);
for (p=a, i=0; p<=&a[4]; p++) printf("\n");
printf("%d", *p); }

Reenje
01234
02
43210

c)
/*C55c, L.Kraus, primer, modifikacija J.Protic, I.Tartalja, dopuna A.Bosnjakovic*/
#include <stdio.h>
#include <stdlib.h>
main()
{
int **a, n, i, j;
printf("N="); scanf("%d", &n);
a = calloc(n, sizeof(int*)); /*alocira memoriju za n pokazivaca na vrste*/
for (i=0; i<n; i++)
{
*(a+i)= calloc(n, sizeof(int));
/*alocira memoriju za n elemenata vrste koji su tipa int*/
for (j=0; j<n; j++) *(*(a+i)+j) = rand()/((double)RAND_MAX + 1) * 10;
/* C55c.c(44) : warning C4244: '=' : conversion from 'double ' to 'int ', possible loss
of data */
}
for (i=0; i<n; printf("\n"), i++)
for (j=0; j<n; j++)
printf("%d", *(*(a+i)+j));
for (i=n-1; i>=0; i--) printf("%d", *(*(a+i)+n-1-i));
putchar('\n');
}
A) sadraj matrice vrstu po vrstu, a potom sporednu dijagonalu, sleva-udesno
B) sadraj matrice vrstu po vrstu, a potom glavnu dijagonalu, sdesna-ulevo
C) sadraj matrice vrstu po vrstu, a potom sporednu dijagonalu, sdesna-ulevo
Odgovor:
A
Materijal za vebe na tabli i pripremu ispita Strana 21 od 52
Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C57
Da bi se uitani znakovni niz (string) precizno ispisao unatrag (samo znaci koji su unoeni sa
standardnog ulaza), koja naredba se moe staviti umesto ***?
scanf(%s%, string1); a = string1; *** while (a>string1) putchar(*(--a));
A) while (*a) a++;
B) for (; *a; a++);
C) while (*a++);
Odgovor
V (A i B)
Komentar
Umesto *** mora da stoji naredba koja e postaviti pointer a tako da pokazuje na NULL (\0)
karakter pointera string1, jer se u narednoj while petlji pointer a najpre dekrementira pa se tek
tada ispisuje odgovarajui znak. Odgovor C nije dobar jer postavlja (zbog bonog efekta) pointer a
na znak iza \0 karaktera.

Zadatak C60
Napisati program na programskom jeziku C koji uitava jedan znakovni niz (string) S1 i jedan ceo
broj M, a zatim formira novi znakovni niz S2 samo od onih znakova na ijim su pozicijama
odgovarajui bitovi broja M jednaki 1. Smatrati da se ceo broj predstavlja u 16-bitnoj lokaciji, a da
znakovni niz moe imati najvie 16 znakova. Na kraju, program ispisuje novi znakovni niz S2.

Reenje
/* C60.c, 9.4.1994., II parcijalni ispit */
#include <stdio.h>

main()
{
short int M, maska;
char S1[17], *s1, S2[17], *s2;

printf("Unesi string S1 i broj M:\n");


scanf("%s%d", S1, &M);
s1 = S1;
s2 = S2;
maska = 1;
while (maska && *s1)
{
if (M & maska) {*s2 = *s1; s2++; };
s1++; maska<<=1;
}
*s2 = '\0';
printf("Novi string S2: %s\n", S2);
}

Komentar
U ovom programu promenjiva maska slui da ispitamo gde se nalaze jedinice u broju M koji zadaje korisnik.
Broj bitova broja M (16) odgovara broju znakova stringa S1. Na osnovu pozicije tih jedinica odreuju se
znakovi koji e biti u stringu S2. Svaki od stringova S1 i S2 zauzima ukupno 17 bajtova u memoriji 16 za
same znakove i 1 za zavrni nulti znak.
Uslov (maska && *s1) je neophodan da bi se dobio ispravan niz s2.

Materijal za vebe na tabli i pripremu ispita Strana 22 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C65
Koji od sledeih izraza je ekvivalentan izrazu ar[1][2], ako je data sledea deklaracija:
int ar[][3]={{0,1,2}, {3,4,5}}
A) *(int*) ( ((char*)ar + (1*3*4)) + (2*4) )
B) *(ar[1]+2)
C) *((*ar+1)+2)

Odgovor
B
Obrazloenje

A) zavisi od implementacije tipa int, u prikazanom sluaju je u redu


C) bilo bi ispravno da stoji *(*(ar+1)+2), ovako je u pitanju *(ar[0]+3)
Materijal za vebe na tabli i pripremu ispita Strana 23 od 52
Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C70
Napisati program na programskom jeziku C koji uitava dva znakovna niza, izvri nadovezivanje
drugog na prvi, okrene naopako dobijeni niz i ispie ga na standardnom izlaznom ureaju.
Reenje
#include <stdio.h>
#include <string.h>
main()
{
int n;
char c, *d, *p, *prvi, *drugi;
printf(Maksimalna duzina: );
scanf(%d\n, &n);
p = calloc(2*n+1, sizeof(char)) ;
d = calloc(n+1, sizeof(char));
if ((NULL == d) || (NULL == p))
printf(Nije moguca alokacija!\n);
else
{
prvi = p; drugi = d;
while ((*p = getchar()) != \n) p++;
*p = \0;
while ((*d = getchar()) != \n) d++;
*d = \0;
p = prvi; d = drugi;
/* konkatenacija */
while (*p) p++;
while (*p++=*d++);
/* okretanje */
p = prvi;
for (d=p+(strlen(p)-1); p < d; p++, d--)
c=*p, *p=*d, *d=c;
printf(%s\n, prvi);

free(p); free(d);
}

Komentar
Za string p se alocira dvostruko vie memorije zbog nadovezivanja nizova. OBAVEZNO treba proveriti da li je
uspela alokacija memorije.
Nakon alokacije memorije, vri se uitavanje stringova, znak po znak, korienjem biblioteke funkcije
getchar(). Zatim se vri konkatenacija, tako to se drugi string nadovee na prvi.
Okretanje dobijenog niza u datom reenju radi se tako to prvi lan menja mesto sa poslednjim, drugi sa
pretposlednjim, itd.
S obzirom na to da postoji dinamika alokacija memorije, svu alociranu memoriju OBAVEZNO treba osloboditi
kada ona vie nije potrebna (u ovom sluaju pre zavretka programa).

Materijal za vebe na tabli i pripremu ispita Strana 24 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C75
Napisati program na programskom jeziku C koji ponavlja sledeu sekvencu operacija:
1. uitava informaciju o tipu podataka sa kojim e raditi (ceo broj ili znak);
2. uitava duinu niza podataka;
3. uitava niz podataka zadatog tipa i duine u dinamiki alociranu memoriju;
4. ispisuje u heksadecimalnom obliku sadraj uitanih podataka, bajt po bajt.
Reenje
#include <stdio.h>
#include <stdlib.h>

main()
{
void *blok_p, *bajt_p;
int lnt, n;
char o, *format_p;

while(1)
{
o = 0;
while (o != 'c' && o != 'Z' && o != 'k')
{
printf("Tip brojeva: (c)eli/(z)naci, ili (k)raj?");
scanf("%c", &o);
switch(o)
{
case 'c' :
lnt = sizeof(int);
format_p = "%d";
break ;
case 'z' :
lnt = sizeof(char) ;
format_p = "%c" ;
break ;
case 'k' :
break ;
default: printf("Neispravan unos! Ponovite.\n");
}
}

if (o == 'k') break ;
printf("Broj podataka?");
scanf("%d", &n);
blok_p = malloc(lnt*n) ;
printf("Podaci:\n");
for (bajt_p=blok_p; bajt_p<(char*)blok_p+n*lnt; (char*)bajt_p+=lnt)
/*konverzija tipa, pretvaramo generiki pokazivac u pokaziva na char */
{ printf("?"); scanf(format_p, bajt_p); }
printf("Bajtovi:\n");
for (bajt_p = blok_p; bajt_p<(char*)blok_p+n*lnt; ((char*)bajt_p)++)
printf("%x", *(char *)bajt_p);
printf("\n");
free(blok_p);
}
}

Komentar
Bajt_p i blok_p su generiki pokazivai; poto kod njih nije odreen tip pokazivanih podataka, takav
pokaziva ne moe se koristiti za pristup podacima, ve samo za uvanje informacije o adresi nekog podatka.
Pre pristupa nekom podatku, neophodno je generiki pokaziva, upotrebom operatora za konverziju tipa,
pretvoriti u pokaziva na eljeni tip podataka. Posledice su nepredvidive ako pokazivani podatak nije tipa koji
je naznaen u operatoru za konverziju tipa.

Materijal za vebe na tabli i pripremu ispita Strana 25 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C80b
Sastaviti program na jeziku C za uitavanje imena gradova uz njihovo ureivanje po abecednom
redosledu i ispisivanje rezultata. U svakom redu se uitava po jedno ime sve dok se ne uita prazan
red.
/* program za sortiranje imena gradova */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAX_GRAD 100


#define MAX_DUZ 30

main()
{
char *adrese[MAX_GRAD], *adresa;
int znak, br_grad = 0, duz, i;

do
{
adresa = calloc(MAX_DUZ, sizeof(char));
for (duz = 0; duz < MAX_DUZ - 1; duz++)
if ((znak = getchar()) != '\n')
*(adresa + duz) = znak;
else
break;
*(adresa + duz) = '\0';
if (!duz)
{
free(adresa); break;
}
adresa = realloc(adresa, duz + 1);
for (i = br_grad - 1; i >= 0; i--)
if (strcmp(adrese[i], adresa) > 0)
adrese[i + 1] = adrese[i];
else
break;
adrese[i+1] = adresa;
} while (br_grad++ < MAX_GRAD);

for (i = 0; i < br_grad; i++)


printf("%s\n", adrese[i]);
}

Komentar:
Ova tema je detaljno obraena u knjizi profesora Krausa. Savetuje se studentima da detaljno proue primere
iz knjige.

Materijal za vebe na tabli i pripremu ispita Strana 26 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C90
Napisati program koji ispisuje redom binarne vrednosti brojeva koji su zadati putem komandne
linije. Glavnu obradu izdvojiti u potprogram, a potprogram smestiti u posebnu datoteku.
raspak.h
/* limits.h - implementation dependent values
limits.h sadrzi vrednosti koje se ticu maksimalnih i minimalnih velicina podataka,
kao i broja bitova koriscenih za neke tipove podataka, a koje su zavisne od konkretnog
ostvarenja programskog jezika C */

#include <limits.h>

#define NUM_BITS( Type ) ( sizeof( Type ) * CHAR_BIT )

void raspak( unsigned, int [] );

raspak.c
#include "raspak.h"
void raspak( unsigned k, int bit[] )
{
int i = NUM_BITS( unsigned );
while ( i ) bit [ --i ] = k & 1, k >>= 1;
}

c90.c
/*
Napisati program koji ispisuje binarne vrednosti brojeva koji
su zadati na komandnoj liniji. Glavnu obradu izdvojiti u potprogram
*/

#include <stdio.h>
#include <stdlib.h>
#include "raspak.h"

static const BITS_IN_GROUP =4;

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


{
int i, j;
int niz[ NUM_BITS( unsigned ) ];
for( i = 1;i < argc; i++ )
{
raspak( atoi( argv[ i ] ), niz );
printf("Bitovi broja %s: ", argv[i]);
for( j =0; j < NUM_BITS( unsigned ); j++ )
{
printf( "%d", niz[ j ] );
if ( j % BITS_IN_GROUP == BITS_IN_GROUP -1 )
putchar ( ' ' );
}
putchar( '\n' );
}
return 0;
}

Komentar
raspak.h definiciona datoteka u kojoj su deklarisani svi potrebni tipovi podataka, simbolike konstante,
definicije makroa, kao i prototipovi korienih funkcija.
raspak.c sadri funkciju za rad sa binarnim brojevima (to je ono to se trai u zadatku).
c90.c ovde je smeten je glavni program, koji koristi definicije iz raspak.h i poziva funkciju ija je
implementacija u raspak.c

Materijal za vebe na tabli i pripremu ispita Strana 27 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C95
Navesti tip identifikatora x u sledeim definicijama:

char **x; - pokaziva na pokaziva na char


int (*x)[10]; - (pokaziva na) niz od 10 int
int *x[10]; - niz od 10 pokazivaa na int
int *x(); - funkcija koja vraa pokaziva na int
int (*x)(); - (pokaziva na) funkciju koja vraa int
char ( * ( * x() )[] ) ();
___
funkcija koja vraa
____________
pokaziva na
_______________________
niz
_____________________________
pokazivaa na
_______________________________________
funkciju koja vraa
______________________________________________
char
char ( * ( * x[3] )() ) [5];
____
niz od tri
______________
pokazivaa na
________________________
funkciju koja vraa
________________________________
pokaziva na
________________________________________
niz od 5
________________________________________________
char
Obrazloenje
Deklaracije se itaju poev od identifikatora ka spoljanjosti. Operatori () i [] imaju prioritet 15 i smer
grupisanja s leva udesno, dok operator * ima prioritet 14 i smer grupisanja s desna ulevo (videti tablicu
prioriteta). Zbog toga, kada se deklarie (definie) pokaziva na niz ili funkciju, moraju da se upotrebe
zagrade. Ovo znai da se prvo uoi identifikator, a zatim se, ako postoje obuhvatajue zagrade, unutar tih
zagrada ita po sledeem pravilu: prvo se itaju modifikatori desno od identifikatora, i to redom s leva udesno;
zatim se itaju modifikatori levo od identifikatora, i to redom sdesna ulevo. Postupak se ponavlja dok se ne
obrade sve obuhvatajue zagrade, ako postoje. Na kraju se ita tip podatka koji stoji na poetku deklaracije.
char *((*x)[](char **));
pokaziva na niz funkcija koje kao argument primaju pokaziva na pokaziva na karakter, a vraaju pokaziva
na karakter. Ova definicija NIJE VALJANA jer u C-u nije dozvoljeno praviti niz funkcija, pa samim
tim ni pokaziva na niz funkcija.

Materijal za vebe na tabli i pripremu ispita Strana 28 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C100
Napisati funkciju na programskom jeziku C koja realizuje algoritam QuickSort. Funkcija treba da
sortira niz podataka proizvoljnog tipa. Kriterijum sortiranja definisan je funkcijskim parametrom.
Reenje
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
void swap( void **p1, void **p2 )
{
void *temp = *p1;
*p1 = *p2;
*p2 = temp;
}
/* rekurzivna varijanta */
void quicksort(void *v[], int left, int right, int (*comp)(const void *, const void * ))
{
int i, last;
if( left >= right ) return;
last = left;
for ( i = left + 1; i <= right; i++ )
if ( ( *comp )( v[ i ], v[ left ] ) < 0)
swap( &v[ ++last ],&v[ i ] );
swap( &v[ left ], &v[ last ] );
quicksort( v, left, last - 1, comp );
quicksort( v, last + 1, right, comp );
}
#define MAX_STR 20
#define MAX_DIM 10

void main()
{
char *niz[ MAX_DIM ];
int i,n;
for ( i = 0; i< MAX_DIM; i++ )
{
niz[ i] = calloc( MAX_STR, 1 );
if ( ( niz[ i ] == NULL )
|| ( fgets( niz[ i ], MAX_STR, stdin ) == NULL )
|| ( *( niz[ i ] ) == '\n' )
) break;
}
n = i - 1;
quicksort( niz, 0, n, strcmp );
for ( i = 0; i <= n; i++ ) fputs( niz[ i ], stdout );
}

Komentar
Funkcija swap ima dva argumenta; ovom funkcijom se postie da **p1 pokazuje tamo gde je pokazivao
**p2 i obrnuto. Funkcija quicksort se zasniva na algoritmu particijskog sortiranja, realizovana je
rekurzivno, i treba da uredi neureen niz.
Deklaracijom int (*comp)(const void*, const void*) definie se pokaziva na funkcije ija je
povratna vrednost tipa int i koje imaju dva argumenta tipa const void*. Tamo gde se u programskom
kodu nalazi (*comp)(v[i], v[left]) imamo indirektno adresiranje koje se primenjuje na promenljivu
comp, to je praktino poziv funkcije koja se u memoriji nalazi na adresi na koju pokazuje pokaziva comp. Da
bi ovo bilo ispravno, funkcija na koju comp pokazuje se mora slagati po tipu/tipovima argumenata navedenim
pored (*comp).

Materijal za vebe na tabli i pripremu ispita Strana 29 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C104
Napisati program u programskom jeziku C za rad sa kompleksnim brojevima. Preko argumenata
programa zadaju se dva kompleksna broja i to tako da se prvo navodi realan deo prvog broja, zatim
imaginarni deo prvog broja, zatim realni i imaginarni deo drugog kompleksnog broja, respektivno.
Ako korisnik ne unese taan broj argumenata potrebno je prekinuti izvravanje programa. Takoe
treba napisati potprogram koji proverava da li znakovni niz sadri broj i pomou tog potprograma
treba ispitati da li su svi navedeni argumenti zaista brojevi. Ako bar jedan argument nije broj,
potrebno je prekinuti izvravanje programa. Program treba da sadri i potprogram za sabiranje dva
kompleksna broja koji vraa kompleksni broj kao rezultat kao i potprogram za konjugovanje
kompleksnog broja koji nema povratnu vrednost. Glavni program treba da na standardnom izlazu
ispie sve argumente programa, zbir kompleksnih brojeva i konjugovane vrednosti oba kompleksna
broja. Ispis treba vriti pozivom odgovarajueg potprograma koji takoe treba napisati. Kompleksne
brojeve predstaviti strukturom.
Reenje
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>

#define TRUE 1
#define FALSE 0

/* istovremeno definisemo i strukturu sa imenom (SComplex) i tip podatka (TComplex) */


typedef struct SComplex
{
double Re, Im;
} TComplex;

/* parsiramo string da bismo utvrdili da li predstavlja realni broj */


int DaLiJeBroj(const char *pstr)
{
int bTacka = FALSE;
if (*pstr=='+' || *pstr=='-')
++pstr;

while(*pstr)
{
if (!isdigit(*pstr) && *pstr!='.')
return FALSE;
if (*pstr == '.')
{
if (bTacka)
return FALSE;
bTacka = TRUE;
}
pstr++;
}
return TRUE;
}

/* sabiramo dva broja i zbir vracamo kao rezultat funkcije */


TComplex Zbir(TComplex z1, TComplex z2)
{
TComplex cplx;
cplx.Re = z1.Re + z2.Re;
cplx.Im = z1.Im + z2.Im;
return cplx;
}

Materijal za vebe na tabli i pripremu ispita Strana 30 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C
/* konjugujemo kompleksni broj, operacija se obavlja na samom primerku strukture */
void Konjug(TComplex *pZ)
{
pZ->Im = - pZ->Im;
}

/* ispisujemo broj, u formatu x + jy */


void Ispis(TComplex z)
{
if (z.Im >= 0)
printf("%5.4f + j%5.4f", z.Re, z.Im);
else
printf("%5.4f - j%5.4f", z.Re, -z.Im);
}

/* glavni program, ulazne podatke zadajemo putem komandne linije */


int main(int argc, char *argv[])
{
TComplex z1, z2, zbir;
int i;

if (argc != 5)
{
printf("Unesite tacno cetiri argumenata pri startu programa!\n");
return -1;
}

printf("Uneli ste sledece argumente preko komandne linije:\n");


for (i=1; i < argc; i++)
printf("%d %s\n", i, argv[i]);

for (i=1; i < argc; i++)


{
if (!DaLiJeBroj(argv[i]))
{
printf("Uneli ste argument koji nije broj!\n");
return -1;
}
}

z1.Re = atof(argv[1]);
z1.Im = atof(argv[2]);

z2.Re = atof(argv[3]);
z2.Im = atof(argv[4]);

printf("\nPrvi broj: "); Ispis(z1);


printf("\nDrugi broj: "); Ispis(z2);
zbir = Zbir(z1, z2);
Konjug(&z1); Konjug(&z2);

printf("\nZbir: "); Ispis(zbir);


printf("\nKonjug(z1): "); Ispis(z1);
printf("\nKonjug(z2): "); Ispis(z2);
printf("\n\nHvala na paznji!\n");

return 0;
}

Komentar
Zadavanje argumenta putem komandne linije znai da glavni program ima dva argumenta. Argumenti
komandne linije su stringovi, te ih moramo konvertovati pre korienja. Ti argumenti omoguavaju prenoenje
parametara glavnom programu koji se zadaju u sastavu komande operativnog sistema za izvravanje
programa.

Materijal za vebe na tabli i pripremu ispita Strana 31 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C110
Date su sledee deklaracije:
typedef int CeoBroj;
typedef int *PokazivacNaCeoBroj;
typedef int NizCelihBrojeva[100];
CeoBroj *pokazA;
PokazivacNaCeoBroj pokazB;
NizCelihBrojeva niz;

struct {
int x,y;
} zapisA;

struct {
int x,y;
} zapisB, zapisC;
Koje od sledeih naredbi dodele su semantiki ispravne?
pokazA = pokazB; /* OK */
pokazA = niz; /* OK */
niz = pokazA; /* GREKA */

zapisB = zapisC; /* OK */
zapisA = zapisB; /* GREKA */

Obrazloenje
Prvi primer je ispravan zato to je mogua dodela izmeu dve promenljive koje su istog tipa
pokazA i pokazB su pokazivai na int. Drugi primer je ispravan jer pokazA sada pokazuje tamo
gde pokazuje niz. Tip imena niza je tip nepromenljivog pokazivaa na nulti lan, zato je trei primer
pogrean, jer se ne moe nepromenljivom pokazivau dodeliti nova vrednost.
U programskom jeziku C se koristi strukturna ekvivalencija tipova (typedef imena se pri tome
zamenjuju odgovarajuim tipom) osim u sluaju struktura i unija. Za strukture i unije koristi se
ekvivalencija po imenu. Svaka neimenovana struktura je poseban tip, ak i u sluaju da su sva polja
neke dve strukture meusobno identina.

Materijal za vebe na tabli i pripremu ispita Strana 32 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C115
Sastaviti program na programskom jeziku C za spajanje sadraja nekoliko sekvencijalnih tekst
datoteka u jednu izlaznu datoteku. Imena datoteka se zadaju kao parametri u komandnoj liniji. Ime
izlazne datoteke je prvi parametar. Ukoliko je prvi parametar "-", izlazna datoteka je stdout.
Reenje
#include <stdio.h>
#include <string.h>
main (int argc, char *argv[])
{
void prepis (FILE *, FILE*);
FILE *ulaz, *izlaz;
char *prog = argv[0];

izlaz = stdout;
if (argc > 1)
{
argc--;
if (strcmp(*++argv, "-") != 0)
if ((izlaz = fopen(*argv, "w")) == NULL)
{
fprintf(stderr,"%s:greska u otvaranju datoteke %s\n",prog,*argv);
exit(1);
}
}
while(--argc > 0)
if ((ulaz = fopen(*++argv, "r")) != NULL)
prepis(ulaz, izlaz), fclose(ulaz);
else
{
fprintf(stderr,"%s: ne postoji datoteka %s\n", progr, *argv);
exit(2);
}

fclose(izlaz);
exit (0);
}

void prepis(FILE *ulaz, FILE *izlaz)


{
int c;
while((c=getc(ulaz)) != EOF) putc(c, izlaz);
}

Komentar
Elementi char *argv[] (niz pod imenom argv iji su elementi pokazivai na char, gde operativni sistem
smeta stringove iz komandne linije) se mogu tretirati u kodu sa *argv zbog promocije niz se ne moe
inkrementirati kao to se to radi u datom primeru, ali ako se kao parametar funkcije navede neki niz, C to
automatski tretira kao pokaziva na tip podataka kome pripadaju elementi niza, a za pokazivae je
inkrementiranje dozvoljeno.

Materijal za vebe na tabli i pripremu ispita Strana 33 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C120
U binarnoj datoteci se nalaze zapisi o automobilima i vozaima. Svaki zapis sadri podatak o tipu
entiteta, samom entitetu i celobrojnu vrednost sledeeg zapisa u logiki organizovanoj listi. Prvi zapis
u datoteci je i prvi zapis liste, a poslednji zapis liste je zapis u ijem polju ukazatelja na sledei zapis
stoji 0. Svaki zapis u datoteci ima polje koje sadri broj logiki sledeeg zapisa u datoteci.
Napisati:
1. potprogram koji ita navedenu datoteku i formira listu zapisa u dinamiki dodeljenoj memoriji,
pri emu zapise povezuje u suprotnom smeru od smera u datoteci;
2. potprogram koji ispisuje na standardnom izlazu listu iz take a) i
3. glavni program koji poziva gornje potprograme
cz120.h
#include <stdio.h>

enum tip {AUTO=1, VOZAC};

struct automobil {enum tip t; char reg_br[10], boja[10], model[10]; };


struct vozac {enum tip t; char pol[2], br_dozvole[10], ime[10], prezime[10]; };

union zapis {struct automobil a; struct vozac v; };

struct element_dat {union zapis z; int b; };


struct element_lis {union zapis z; struct element_lis * s; };

void pisi_auto( struct element_lis *);


void pisi_vozac( struct element_lis *);
void formiraj_listu( FILE*, struct element_lis **);
void pisi_listu( struct element_lis *);
void kreiraj_datoteku(char*);

cz120.c
#include <stdio.h>
#include "cz120.h"

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


FILE *av_bin;
struct element_lis *lista;

if (argc > 2)
kreiraj_datoteku(argv[1]);
if (av_bin = fopen(argv[1],"rb"))
{
formiraj_listu(av_bin,&lista);
pisi_listu(lista);
}
}

pisi_av.c
#include <stdio.h>
#include "cz120.h"

void pisi_auto(struct element_lis *e)


{
printf("Registarski broj: %s; Boja: %s; Model: %s\n",
e->z.a.reg_br, e->z.a.boja, e->z.a.model);
}

void pisi_vozac(struct element_lis *e)


{
printf("Pol: %s; Ime i prezime: %s %s; Broj dozvole: %s\n",
e->z.v.pol, e->z.v.ime, e->z.v.prezime, e->z.v.br_dozvole);
}

Materijal za vebe na tabli i pripremu ispita Strana 34 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C
formlist.c
#include <stdlib.h>
#include <stdio.h>
#include "cz120.h"
void formiraj_listu(FILE *av_bin, struct element_lis **ppLista)
{
struct element_lis *preth=NULL;
struct element_dat bafer;
*ppLista = NULL;
bafer.b = 1;
while (bafer.b > 0)
{
fread(&bafer, sizeof(bafer), 1, av_bin);
fseek(av_bin, sizeof(bafer)*(bafer.b-1), SEEK_SET);
*ppLista = calloc(sizeof(struct element_lis), 1);
(*ppLista)->z=bafer.z;
(*ppLista)->s=preth;
preth = *ppLista;
};
}

pisilist.c
#include "cz120.h"
void pisi_listu(struct element_lis *lista)
{
while(lista)
{
switch (lista->z.a.t)
{
case AUTO: pisi_auto(lista); break;
case VOZAC: pisi_vozac(lista); break;
default: printf("Neispravan element liste!\n");
}
lista = lista->s;
}
}

kr_dat.c
#include "cz120.h"
void kreiraj_datoteku(char* filename)
{
struct element_dat bafer;
int izbor = 1;
FILE *file = fopen(filename, "wb");
while(izbor)
{
printf("Auto[1] ili vozac[2] ili kraj unosa[bilo sta]? \n");
scanf("%d", &izbor);
switch(izbor)
{
case AUTO:
printf("Unesite redom sledece podatke: boja, model, registarski broj, KLJUC: \n");
scanf("%s%s%s%d", bafer.z.a.boja, bafer.z.a.model, bafer.z.a.reg_br, &bafer.b);
bafer.z.a.t = AUTO; break;
case VOZAC:
printf("Unesite redom sledece podatke: ime, prezime, pol, broj dozvole: \n");
scanf("%s%s%s%s%d", bafer.z.v.ime, bafer.z.v.prezime, bafer.z.v.pol,
bafer.z.v.br_dozvole, &bafer.b);
bafer.z.v.t = VOZAC; break;
default: izbor = 0;
}
if (izbor)
fwrite(&bafer, sizeof(struct element_dat), 1, file);
}
fclose(file);}

Materijal za vebe na tabli i pripremu ispita Strana 35 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C
Komentar
Ovaj zadatak ilustruje korienje struktura i unija, kao i konstrukciju programskog sistema iz vie datoteka.
Shodno logikom ustrojstvu celog programskog sistema, programer treba da odlui koje e funkcije imati u
sistemu i kako e ih rasporediti po datotekama.
cz120.h definiciona datoteka u kojoj su deklarisani svi potrebni tipovi podataka, simbolike konstante,
definicije makroa, kao i prototipovi korienih funkcija.
cz120.c ovde se nalazi glavni program, koji poziva odgovarajue potprograme. U sluaju da datoteka sa
podacima ne postoji, glavni program poziva funkciju koja e je napraviti, a potom ita iz te datoteke u listu
zapisa, koju na kraju na standardnom izlazu.
pisi_av.c ovde su smetene funkcije pisi_auto() i pisi_vozac(), koje slue za ispis podataka o
automobilima i o vozaima.
formlist.c sadri funkciju koja izvrava itanje datoteke, koju smo formirali pozivom funkcije
kreiraj_datoteku(), i formiranje lista zapisa u dinamiki dodeljenoj memoriji.
pisilist.c ovde se nalazi funkcija za ispis ve formirane liste zapisa, koja zavisno od tipa zapisa poziva
jednu od funkcija pisi_auto() i pisi_vozac().
kr_dat.c ovde se nalazi funkcija kreiraj_datoteku() koja kreira binarnu datoteku u kojoj e se
nalaziti zapisi o automobilima i vozaima.

Materijal za vebe na tabli i pripremu ispita Strana 36 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C122
Potrebno je realizovati u programskom jeziku C skup funkcija za rad sa listom ije je ponaanje
isto kao ponaanje podatka tipa liste iz pseudojezika. Funkcije za rad sa listom treba da se zovu isto
kao u pseudojeziku (find_bolp, insert, move_forward...) i treba da budu realizovane u zasebnoj
implementacionoj .c datoteci. Takoe je potrebno napraviti odgovarajuu definicionu .h (header)
datoteku u kojoj e biti deklarisani svi potrebni tipovi podataka i prototipovi korienih funkcija.
Podaci se u listi skladite preko generikog pokazivaa (void *), a potrebno je obezbediti brisanje
podataka sadranih u listi kroz call-back mehanizam. Napraviti inicializacionu funkciju koja inicijalizuje
listu i koja postavlja odgovarajuu funkciju koja se poziva kroz call-back mehanizam pri unitavanju
liste. Pointer na ovu funkciju se prosleuje kao argument funkcije za inicijalizaciju liste. U listu je iz
tekstualne datoteke potrebno proitati podatke o studentima. Podaci su u fajl sloeni tako da je u
jednom redu ime i prezime studenta, u drugom broj indeksa u formatu Broj/GodinaUpisa i u treem
prosek studenta. Nakon itanja iz datoteke, upisati sve podatke o studentima iz liste u novu binarnu
datoteku i to tako da se upisuju samo podaci o studentima sa prosekom veim od 8.5.
pj_lista.h
#define TRUE 1
#define FALSE 0

typedef enum { lsBOLP = 0, lsEOLP, lsCURRENT } TListStatus;

struct SListElement /* element liste */


{
void *pData; /* pointer u kome se skladisti adresa podatka */
struct SListElement *pNext; /* pokazivac na sledeci element u listi */
};

struct SList
{
TListStatus lsStatus; /* status - trenutni polzaj u listi */
struct SListElement *pHead; /* pokazivac na glavu liste */
struct SListElement *pCurrent; /* pokazivac na tekuci element */
void (*destructor)(void *); /* pokazivac na funkciju koja ima argument tipa void* */
};

typedef struct SListElement TListElement;


typedef struct SList TList;

void initialize_list(TList *pList, void (*destructor)(void *));


void find_bolp(TList *pList);
int move_forward(TList *pList);
int insert(TList *pList, void *pData);
void *get(TList *pList);
void destroy_list(TList *pList);
int eolp(TList *pList);

pj_lista.c
#include <stdlib.h>
#include "pj_lista.h"

/* Argumenti: pList - pointer na promenljivau tipa Tlist, destructor - pointer na


funkciju koja se poziva u toku unistavanja liste za svaki njen podatak */
void initialize_list(TList *pList, void (*destructor)(void *))
{
pList->pHead = NULL;
pList->lsStatus = lsBOLP;
pList->pCurrent = NULL;
pList->destructor = destructor;
}

Materijal za vebe na tabli i pripremu ispita Strana 37 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

void find_bolp(TList *pList)


{
pList->lsStatus = lsBOLP;
pList->pCurrent = NULL;
}

int move_forward(TList *pList)


{
if (pList->lsStatus == lsEOLP)
return FALSE;

if (pList->lsStatus == lsBOLP)
{
pList->pCurrent = pList->pHead;
if (pList->pCurrent == NULL)
pList->lsStatus = lsEOLP;
else
pList->lsStatus = lsCURRENT;
}
else
{
pList->pCurrent = pList->pCurrent->pNext;

if (pList->pCurrent == NULL)
pList->lsStatus = lsEOLP;
}

return TRUE;
}

/* pList - pokazivac na tip Tlist, pData - podatak koji ce biti ubacen u listu. */
int insert(TList *pList, void *pData)
{
TListElement *pNewElem;

if (pList->lsStatus == lsEOLP)
return FALSE;

pNewElem = (TListElement *)calloc(1, sizeof(TListElement));

if (pNewElem == NULL)
return FALSE;

pNewElem->pData = pData;
pNewElem->pNext = NULL;

if (pList->lsStatus == lsBOLP)
{
pNewElem->pNext = pList->pHead;
pList->pHead = pNewElem;
pList->pCurrent = pNewElem;
pList->lsStatus = lsCURRENT;
}
else
{
pNewElem->pNext = pList->pCurrent->pNext;
pList->pCurrent->pNext = pNewElem;
pList->pCurrent = pNewElem;
}
return TRUE;
}

void *get(TList *pList)


{
if (pList->lsStatus == lsCURRENT)
return pList->pCurrent->pData;

Materijal za vebe na tabli i pripremu ispita Strana 38 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

return NULL;
}
void destroy_list(TList *pList)
{
TListElement *pElem, *pHelpElem;
for (pElem = pList->pHead; pElem != NULL; )
{
pHelpElem = pElem->pNext;
if (pList->destructor)
(*pList->destructor)(pElem->pData); /* na ovom mestu pointer na funkciju */
/* se dereferencira i zatim se poziva ta funkcija */
/* sa argumentom pElem->pData */
free(pElem);
pElem = pHelpElem;
}
}

int eolp(TList *pList)


{
return pList->lsStatus == lsEOLP;
}

cz122.c
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "pj_lista.h"

typedef struct { /* struktura u kojoj se cuvaju podaci o */


char strIme[256]; /* studentu */
int nGodUpisa;
int nBroj;
float fProsek;
} TStudent;

void UnistiStudenta(void *pStudent) /* funkcija neophodna za call-back */


{ /* pri unistavanju liste */
if (pStudent != NULL)
{
printf("UnistiStudenta %s\n", ((TStudent*)pStudent)->strIme);
free(pStudent);
}
}

void main()
{
FILE *f1, *f2;
TList list;
TStudent *pStudent;
char *pKrajLinije;

f1 = fopen("studenti.txt", "r"); /* otvaramo tekstualnu datoteku za citanje */


if (f1 == NULL)
{
printf("Datoteka ne postoji!\n"); /* otvaramo binarnu datoteku za upis */
return;
}

f2 = fopen("studenti.bin", "wb");
if (f2 == NULL)
{
printf("Datoteka za upis nece da se otovori!\n");
fclose(f1);
return;
}

Materijal za vebe na tabli i pripremu ispita Strana 39 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C
initialize_list(&list, UnistiStudenta);
/* identifikator funkcije je ujedno i pokazivac na funkciju */

while (!feof(f1))
{
pStudent = (TStudent *)calloc(sizeof(TStudent), 1);
fgets(pStudent->strIme, 255, f1);
/*
Funkcija fgets cita string sve do kraja linije, ali ukljucuje i kraj linije u string!
Zato cemo koristiti strchr funkciju koja vraca adresu prvog karaktera koji se zadaje kao
drugi argument funkcije u okviru stringa koji se zadaje kao prvi argument funkcije.
Ako karakter nije pronadjen strchr vraca NULL. Kada pronadjemo karakter za kraj linije,
prosto cemo ga izbaciti postavljajuci ga na '\0' sto oznacava kraj stringa.
*/
if ((pKrajLinije = strchr(pStudent->strIme, '\n')) != NULL)
*pKrajLinije = '\0';

fscanf(f1, "%d/%d \n", &pStudent->nBroj, &pStudent->nGodUpisa);


fscanf(f1, "%f \n", &pStudent->fProsek);
if (!insert(&list, (void *)pStudent))
{
destroy_list(&list);
printf("Greska pri ubacivanju u listu!\nProgram prekinut!\n");
return;
}
}

fclose(f1);
find_bolp(&list);
while (TRUE)
{
move_forward(&list);
if (eolp(&list))
break;
pStudent = (TStudent*)get(&list);
printf("Ime i prezime: %s\n", pStudent->strIme);
printf("Broj indeksa: %d/%02d\n", pStudent->nBroj, pStudent->nGodUpisa);
printf("Prosek: %4.2f\n", pStudent->fProsek);
if (pStudent->fProsek > 8.5)
{
if (fwrite(pStudent, sizeof(TStudent), 1, f2) == 1)
printf("Kandidat uspesno upisan u novi fajl...\n\n");
else
{
printf("Greska pri upisu! Program prekinut.\n");
break;
}
}
else
printf("Kandidat nije zadovoljio uslove za upis u novi fajl!\n\n");
}

fclose(f2);
destroy_list(&list);
printf("** KRAJ **\n");
}

Materijal za vebe na tabli i pripremu ispita Strana 40 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C125
Pod pretpostavkom da su zapisi u datoteci ureeni u leksikografski ureeno stablo, ta ispisuje
dati program za zadatu datoteku (prvi argument komandne linije) i zadati klju (drugi argument)?
#include <stdio.h>
#include <string.h>
struct tree_elem
{
char key[7];
unsigned long left, right;
};
void create(char* filename)
{
struct tree_elem buffer;
FILE *file = fopen(filename, "wb");
while (!ferror(file))
{
printf("\nKEY LEFT RIGHT: ");
scanf("%6s %lu %lu", buffer.key, &buffer.left, &buffer.right);
if (strcmp(buffer.key, "END") == 0) break;
fwrite(&buffer, sizeof(struct tree_elem), 1, file);
}
fclose(file);
}
void traverse( FILE *file, char key[], unsigned long node)
{
struct tree_elem buffer;
static int ukupno_aktivacija = 0;
int ova_akt;
printf("Pocetak aktivacije %d\n", ova_akt = ++ukupno_aktivacija);
if ( node == 0 )
{ printf("Kraj aktivacije %d\n", ova_akt); return; }
fseek( file, ( node - 1 ) * sizeof( struct tree_elem ), SEEK_SET);
fread( &buffer, sizeof(struct tree_elem ), 1, file );
if ( ferror( file ) ) return;
traverse( file, key, buffer.left );
if ( strcmp( key, buffer.key ) >= 0)
{
printf( "%s\n", buffer.key );
traverse( file, key, buffer.right );
}
printf("Kraj aktivacije %d\n", ova_akt);
}
void main( int argc, char *argv[] )
{
FILE *file; /* ovako odredjujemo da li kreiramo datoteku ili */
if (argc > 3) create(argv[1]); /* koristimo vec napravljenu nekom ranijom prilikom */
if ( ( file = fopen( argv[1], "rb" ) ) == NULL )
fprintf( stderr, "Greska pri otvaranju datoteke %s\n", argv[1] );
else
traverse( file, argv[2], 1 );
}
A) kljueve svih zapisa u datoteci u leksikografskom poretku
B) kljueve svih zapisa manjih do jednakih zadatom, u leksikografskom poretku
C) kljueve svih zapisa manjih do jednakih zadatom, u obrnutom leksikografskom poretku
Odgovor
B
Komentar
Promenljive ukupno_aktivacija i ova_akt slue za pojanjavanje rednog broja aktivacije posmatrane
rekurzivne funkcije traverse, i nemaju uticaja na sutinu zadatka.

Materijal za vebe na tabli i pripremu ispita Strana 41 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C
Zadatak CI-2007-Jan-2
Napisati potprogram unsigned in zbir (char *a, char *b) na programskom jeziku C
koji odreuje decimalnu vrednost zbira brojeva a i b. Odgovarajui stvarni argumenti su znakovni
nizovi (stringovi) od maksimalno 3 znaka i predstavljaju pozitivne cele brojeve u heksadecimalnom
brojnom sistemu. Pri tome, znak koji predstavlja cifru najvee teine je prvi u znakovnom nizu.
Napisati glavni program na programskom jeziku C koji sa standardnog ulaza uitava dva niza od po 3
znaka koji treba da predstavljaju heksadecimalne cifre, potom poziva potprogram zbir i na
standardnom izlazu ispisuje rezultat zbira ta dva broja.
#include <stdio.h>
unsigned int zbir (char *a, char *b)
{
Nemojte NIKAD
unsigned int vred_a = 0, vred_b = 0; programski kod
uiti napamet.
while (*a)
{
vred_a *= 16;
if (*a >= '0' && *a <= '9') vred_a += (*a - '0');
else if (*a >= 'a' && *a <= 'f') vred_a += (*a - 'a' + 10);
else if (*a >= 'A' && *a <= 'F') vred_a += (*a - 'A' + 10);
a++;
}
sscanf(b, "%x", &vred_b);
printf("%d\t%x\n", vred_a, vred_a); /* nije traeno u postavci */
printf("%d\t%x\n", vred_b, vred_b); /* nije traeno u postavci */
return vred_a + vred_b;
} Svako ponavljanje bez
razumevanja programskog koda
je tetno i na ispitu e biti
main()
{
char a[4], b[4];
printf("Unesite brojeve: ");
kanjavano oduzimanjem poena.
scanf("%s%s", a, b);
printf("Zbir ovih brojeva je %d\n", zbir(a, b));
}

Komentar
U funkciji zbir() su prikazana dva razliita pristupa dobijanja vrednosti broja zapisanog u heksadecimalnom
brojnom sistemu. Najpre se vri konverzija broja a, tako to se u ciklusu analizira znak po znak, sve dok se ne
doe do kraja znakovnog niza. Primetiti da nigde nije pretpostavljena duina nizova a i b, pa je ovo reenje
univerzalno (u onoj meri u kojoj opseg predstavljanja celih brojeva dozvoljava). Za praktine primene, ovom
reenju nedostaje provera da li znakovni nizovi a i b zaista predstavljaju cele brojeve u heksadecimalnom
zapisu. To se, meutim, nije trailo - pa nije ni prikazano u reenju. Nakon ciklusa za konverziju broja a, vri
se konverzija broja b pozivom funkcije sscanf(). Ova funkcija se ponaa slino scanf() odnosno fscanf(), s
tim to je izvor koji treba itati u datom formatu zadat znakovnim nizom koji se zadaje kao prvi argument. U
ovom sluaju radi se o nizu b. Naziv sscanf() zapravo potie string scanf. U ostalim aspektima, moe se
smatrati da se ova funkcija ponaa kao scanf().

Materijal za vebe na tabli i pripremu ispita Strana 42 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak CI-2006-Okt-1
Napisati program na programskom jeziku C koji izraunava broj osvojenih bodova na ampionatu
trka Formule 1. Podaci o vozaima i timovima se nalaze u tekst datoteci vozaci.txt prema sledeem
formatu: u svakom redu datoteke redom su zapisani prezime i ime vozaa i naziv tima za koji voza
vozi (svako polje po 30 karaktera najvie). Poznato je da ima tano 28 vozaa koji uestvuju u
trkama i da se na ampionatu vozi 20 trka. Podaci o rezultatima trka smeteni su tekst datoteci
trke.txt tako da se u svakom redu datoteke nalaze redni brojevi pozicija jednog vozaa po zavretku
svake trke (20 pozicija, za svaku trku po jedna). U sluaju da voza ne proe cilj (odustane od trke),
broj pozicije za tu trku je 0. Podaci u prvom redu datoteke trke.txt odgovaraju vozau iz prvog reda
datoteke vozaci.txt, itd. Bodovi za vozae za jednu trku se raunaju na sledei nain: prvih 8 vozaa
dobija 10, 8, 6, 5, 4, 3, 2 i 1 bod respektivno, ostali 0 bodova. Program treba da izrauna i na
standardnom izlazu ispie osvojene bodove tako da u jednom redu stoje prezime i ime vozaa,
osvojen broj bodova i naziv tima.
#include <stdio.h>
main() {
FILE *vozaci, *trke; Nemojte NIKAD
char prezime[31], ime[31], tim[31];
int v,p,pozicija,poena; programski kod
vozaci = fopen("vozaci.txt", "r"); uiti napamet.
trke = fopen("trke.txt", "r");
if( ! vozaci || ! trke ) {
if( ! vozaci ) printf("Neuspelo otvaranje datoteke vozaci.txt\n");
else fclose(vozaci);
if( ! trke ) printf("Neuspelo otvaranje datoteke vozaci.txt\n");
else fclose(trke);
exit(0);
}
for(v=0; v<28; v++) {
fscanf(vozaci, "%s %s %s", prezime, ime, tim);
poena = 0;
for(p=0; p < 20; p++) {
fscanf(trke, "%d", &pozicija);
switch(pozicija) {
case 1: poena += 10; break;
case 2: poena += 8; break;
case 3: poena += 6; break;
case 4: poena += 5; break;
case 5: poena += 4; break;
case 6: poena += 3; break;
case 7: poena += 2; break;
case 8: poena += 1; break;
}
}
printf("%s %s %d %s\n", prezime, ime, poena, tim);
}
Svako ponavljanje bez
fclose(vozaci);
fclose(trke);
} razumevanja programskog koda
je tetno i na ispitu e biti
kanjavano oduzimanjem poena.
Komentar
Provera da li su datoteke uspeno otvorene nije najjezgrovitije zapisana, ali je verovatno najpriblinija nainu
na koji se razmilja prilikom donoenja odluke. Najpre je izvreno otvaranje obe datoteke. Ako bilo koja od
njih nije uspeno otvorena, potrebno je prekinuti program, a prethodno prethodno ispisati koja zapravo nije
uspeno otvorena (mogue obe). Za onu koja je uspeno otvorena se ne vri ispisivanje ve njeno
zatvaranje. Iako obavetenje o nastalim grekama pri radu nije traeno u postavci, ovde je to prikazano iz
edukativnih razloga.

Materijal za vebe na tabli i pripremu ispita Strana 43 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak CI-2007-Okt-2
Napraviti program na programskom jeziku C koji obrauje datoteku koja sadri izvorni program na
programskom jeziku C. Potrebno je datoteku prepisati u novu datoteku, tako da se izostave svi
komentari i ouva ureenost teksta po redovima. Primer:
Ulazna datoteka Odgovarajua izlazna datoteka
#include <stdio.h> #include <stdio.h>
/* ispis proizvoda i kolicnika dva broja main()
*/ {
main() int a, b;
{ scanf("%d%d", &a, &b);
int a, b; printf("%d", a*b);
scanf("%d%d", &a, &b); printf("%d", a/b);
printf("%d", a*b); /* ispis a*b */ }
/* ispis a/b */ printf("%d", a/b);
}
Imena ulazne i izlazne datoteke se zadaju kao prvi i drugi parametar komandne linije i imaju
najvie 30 znakova. U sluaju da doe do greke pri otvaranju neke od datoteka, ispisati poruku o
greki i prekinuti izvravanje programa.
#include <stdio.h>
int main(int argc, char *argv[]) {
char znak;
enum StanjeObrade { VAN_K, POC_K, UNUTAR_K, KRAJ_K } stanje = VAN_K;
FILE *ul, *izl;
if (NULL == (ul = fopen(argv[1], "r"))) {
fprintf(stderr, "Doslo je do greske pri otvaranju %s\n", argv[1]);
return 1;
}
if (NULL == (izl = fopen(argv[2], "w"))) {
fclose(ul);
fprintf(stderr, "Doslo je do greske pri otvaranju %s\n", argv[2]);
return 2;
}

Nemojte NIKAD
while ((znak = fgetc(ul)) != EOF) {
switch(stanje) {

programski kod
case VAN_K:
if ('/' == znak) stanje = POC_K;

uiti napamet.
else fputc (znak, izl);
break;
case POC_K:
if ('*' == znak) stanje = UNUTAR_K;
else stanje = VAN_K, fputc('/', izl), fputc(znak, izl);
break;
case UNUTAR_K:
if ('*' == znak) stanje = KRAJ_K;
break;
case KRAJ_K:
if ('/' == znak) stanje = VAN_K;
else stanje = UNUTAR_K;
break;

}
}
Svako ponavljanje bez
fclose(ul);
fclose(izl);
razumevanja programskog koda
}
return 0; je tetno i na ispitu e biti
kanjavano oduzimanjem poena.
Komentar
Zadatak se bavi neto sloenijom obradom ulazne datoteke u odnosu na jednostavno prepisivanje podataka. U
programu se uvodi pojam "stanja" na osnovu kojeg se odluuje kako treba tretirati ulazni tekst. Na primer,
ako se trenutna obrada vri unutar komentara, nita se ne prepisuje u izlaznu datoteku i obrnuto. S obzirom
na to da se poetak i kraj komentara oznaava pomou dva karaktera (/ i *), uvodi se etiri stanja: van
komentara, poetak komentara, unutar komentara i kraj komentara. U stanju van komentara,
svi znaci se prepisuju, osim kada se pojavi znak /. Tada je potrebno proitati naredni znak i utvrditi da li je on
* (poinje komentar) ili nije (treba / poslati u izlaznu datoteku). Dakle, kada u stanju van komentara naie
znak /, potrebno je prei u novo stanje, u kojem se oekuje dolazak znaka *. Slino se vri izlazak iz
komentara.
stderr je izlazni ureaj koji se automatski stvara i koji slui kao "kanal" za ispis greaka. Njegovo korienje
nije zahtevano u postavci zadatka njegova uloga u ovom reenju je edukativna.

Materijal za vebe na tabli i pripremu ispita Strana 44 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak CI-2006-Sep-2
Napisati program koji jednu tekst datoteku prepisuje u drugu tekst datoteku, uz ouvanje
ureenosti teksta po linijama. Linije u kojima postoji neparan broj znakova razmaka se prepisuju tako
da sva slova budu mala, a ostale tako da sva slova budu velika. Linije ne mogu biti due od 80
znakova. Imena tekst datoteka se zadaju putem standardnog ulaza; ne mogu biti dua od 30
znakova. U sluaju da ne uspe otvaranje neke od datoteka, ispisati poruku korisniku u kojoj se
navodi sa kojom datotekom je dolo do problema i prekinuti izvrenje programa.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
main() {
char ime_ul_dat[30+1], ime_izl_dat[30+1], linija[80+1+1];
FILE *ul_dat, *izl_dat;
Nemojte NIKAD
int duz_lin, i, br_raz; programski kod
scanf("%s", ime_ul_dat); uiti napamet.
scanf("%s", ime_izl_dat);
ul_dat = fopen(ime_ul_dat, "r");
if (NULL == ul_dat) {
fprintf(stderr, "Doslo je do greske pri radu sa %s\n", ime_ul_dat);
exit(EXIT_FAILURE);
}
izl_dat = fopen(ime_izl_dat, "w");
if (NULL == izl_dat) {
fclose(ul_dat);
fprintf(stderr, "Doslo je do greske pri radu sa %s\n", ime_izl_dat);
exit(EXIT_FAILURE);
}
while (fgets(linija, 82, ul_dat) != NULL) {
duz_lin = strlen(linija);
br_raz = 0;
for (i = 0; i < duz_lin; i++)
br_raz += isspace(linija[i]) != 0;
for (i = 0; i < duz_lin; i++)
if (br_raz % 2)
linija[i] = tolower(linija[i]);
else
linija[i] = toupper(linija[i]);
fputs(linija, izl_dat);
}
fclose(ul_dat);
Svako ponavljanje bez
fclose(izl_dat); razumevanja programskog koda
je tetno i na ispitu e biti
}

kanjavano oduzimanjem poena.


Komentar
U postavci je reeno da imena datoteka nisu dua od 30 znakova. Zbog toga se kreiraju dva niza duine 31
znak, gde je namerno naglaeno da se rezervie prostor za jedan znak vie od maksimalne duine zbog znaka
za kraj znakovnog niza ('\0'). Za liniju se rezervie jedno mesto vie: pod pretpostavkom da niz moe imati
najvie 80 znakova, potrebno je jo jedno mesto za kraj znakovnog niza i jo jedno mesto za eventualni
znak za novi red koji e funkcija fgets() smestiti u niz linija. Kasnije u programu se funkciji fgets() zadaje
vrednost 82 kao jedan od argumenata. To je uputstvo da je za itanje rezervisano tano 82 znaka, od kojih
jedan mora biti znak za kraj znakovnog niza.
Simbol EXIT_FAILURE je definisan u zaglavlju stdlib.h i slui kao argument funkciji exit() za oznaavanje
prekida programa zbog greke. U postavci se to nije trailo, ali je u reenju prikazano iz edukativnih razloga.
Funkcija isspace() odreuje da li je dati znak razmak, a funkcije tolower() i toupper() konvertuju dati znak
u malo odnosno veliko slovo respektivno. Ni njihova upotreba nije traena u postavci. Osim iz edukativnih
razloga, ovde su prikazane jer poveavaju itljivost programa, pa se njihova upotreba preporuuje.

Materijal za vebe na tabli i pripremu ispita Strana 45 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak CI-2006-Jan-1
U cilju proglaenja najboljeg igraa(MVP) na odbojkakom turniru, organizacioni odbor turnira je
doneo sledeu odluku o nainu bodovanja uinka igraa: poen iz servisa vredi 1 poen, poen iz smea
vredi 0.5 poena, a blokada 0.2 poena. Podaci o uinku svih igraa za vreme celog turnira nalaze se u
tekstualnoj datoteci odbojka.txt. U jednom redu datoteke nalaze se podaci za jednog igraa. Za
svakog igraa se pamti njegovo ime i prezime (niz od tano 30 karaktera), visina (ceo broj), teina
(ceo broj), broj ostvarenih poena iz servisa na turniru (ceo broj), broj poena iz smea (ceo broj) i
broj blokada (ceo broj). Napisati program na programskom jeziku C koji iz datoteke odbojka.txt
ita podatke o igraima i pronalazi prvog igraa sa najveim brojem ostvarenih poena i na
standardnom izlazu ispisuje ime tog igraa i broj ostvarenih poena.
Reenje sa fgets
#include<stdio.h>
#include<string.h>
main() {

Nemojte NIKAD
double poen_serv = 1.0, poen_smec = 0.5, poen_blok = 0.2;
double max_poeni = 0.0, poeni;

programski kod
char ime_i_prez[31], max_ime_i_prez[31];
unsigned visina, tezina, br_serv, br_smec, br_blok;
FILE *ul_dat = fopen("odbojka.txt", "r");
uiti napamet.
if( ul_dat == NULL )
exit(0);

while (fgets(ime_i_prez, 31, ul_dat) != NULL) {


fscanf(ul_dat, "%d%d%d%d%d", &visina, &tezina, &br_serv, &br_smec, &br_blok);
poeni = poen_serv * br_serv + poen_smec * br_smec + poen_blok * br_blok;
if (max_poeni < poeni) {
max_poeni = poeni;
strcpy(max_ime_i_prez, ime_i_prez);
}
}
Svako ponavljanje bez
razumevanja programskog koda
je tetno i na ispitu e biti
fclose(ul_dat);
kanjavano oduzimanjem poena.
if (max_poeni > 0.0)
printf("MVP je %s, sa ostvarenih %lf poena\n", max_ime_i_prez, max_poeni);
}

Komentar
Ovaj zadatak je reen na dva veoma slina naina. U reenju prikazanom na ovoj strani koristi se funkcija
fgets() da proita ime i prezime igraa kao jednu celinu (tj. kao jedan red teksta) i smesti ih u znakovni niz
ime_i_prez.
Drugo reenje, prikazano na sledeoj strani, koristi funkciju fscanf() za itanje imena i prezimena kao dva
nezavisna znakovna niza, zbog ega je naknadno potrebno izvriti njihovo spajanje u jedan znakovni niz:
najpre se proita ime i smesti u znakovni niz ime_i_prez. Nakon toga se u poseban niz prezime smeta
proitano prezime. Zatim se na ranije proitano ime dodaje jedan znak razmaka a posle toga i proitano
prezime. Dodavanje jednog znakovnog niza na kraj drugog se vri funkcijom strcat().
Treba primetiti sledee. Oekivano da oba reenja daju isti rezultat u smislu itanja imena i prezimena. Ipak,
ne mora biti tako: ako ulazna datoteka sadri vie od jednog razmaka izmeu imena i prezimena, ti razmaci e
ostati nakon itanja kada se koristi funkcija fgets(). To se nee desiti kada se za itanje imena i prezimena
koristi funkcija fscanf() jer ona automatski ignorie sve razmake koji razdvajaju dva niza znakova.

Materijal za vebe na tabli i pripremu ispita Strana 46 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C
Resenje sa fscanf
#include<stdio.h>
#include<string.h>
main() {
double poen_serv = 1.0, poen_smec = 0.5, poen_blok = 0.2;
double max_poeni = 0.0, poeni;
char ime_i_prez[31], prezime[31], max_ime_i_prez[31]; Nemojte NIKAD
unsigned visina, tezina, br_serv, br_smec, br_blok;
FILE *ul_dat = fopen("odbojka.txt", "r"); programski kod
if( ul_dat == NULL ) uiti napamet.
exit(0);

while( fscanf(ul_dat, "%s", ime_i_prez) != EOF) {


fscanf(ul_dat, "%s", prezime);
strcat(ime_i_prez, " ");
strcat(ime_i_prez, prezime);
fscanf(ul_dat, "%d%d%d%d%d", &visina, &tezina, &br_serv, &br_smec, &br_blok);
poeni = poen_serv * br_serv + poen_smec * br_smec + poen_blok * br_blok;
if (max_poeni < poeni) {
max_poeni = poeni;
strcpy(max_ime_i_prez, ime_i_prez);
}
}

fclose(ul_dat);

if (max_poeni > 0.0)


printf("MVP je %s, sa ostvarenih %lf poena\n", max_ime_i_prez, max_poeni);
}

Komentar Svako ponavljanje bez


Videti komentar dat uz prethodno reenje zadatka. razumevanja programskog koda
je tetno i na ispitu e biti
kanjavano oduzimanjem poena.

Materijal za vebe na tabli i pripremu ispita Strana 47 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak CI-2006-Jan-2
Napisati potprogram double bin2dbl(char * num) na programskom jeziku C koji na osnovu
znakovnog niza (stringa) num koji predstavlja binarnu reprezentaciju realnog broja izraunava i kao
rezultat vraa brojnu vrednost tipa double, koja e se ispisati u decimalnom brojnom sistemu. String
num ima najvie 10 binarnih cifara ukljuujui i decimalnu taku koja moe a ne mora postojati.
Napisati glavni program na programskom jeziku C koji sa standardnog ulaza uitava string num,
poziva potprograma bin2dbl i na standardnom izlazu ispisuje dobijeni rezultat. (npr. za unos
1011.101 program treba da ispie rezultat 11.625).
#include <stdio.h>
#include <string.h>
double bin2dbl(char *num) {
unsigned num_length = strlen(num), i = 0;
double celi_deo = 0, razl_deo = 0;

/* ako prvi znak nije decimalna tacka, rauna se celi deo broja */
if (num[i] != '.') {
celi_deo = num[0] - '0';
/* dok se ne stigne do kraja broja ili do decimalne tacke */
while (++i < num_length && num[i] != '.')
celi_deo = celi_deo * 2 + (num[i] - '0');
}
Nemojte NIKAD
/* ako postoji razlomljeni deo, kree se od kraja */
if (i < num_length) programski kod
uiti napamet.
/* dok se ne stigne do decimalne tacke */
while (i < --num_length)
razl_deo = (razl_deo + num[num_length] - '0')/2;

return celi_deo + razl_deo;


}

main() {
char ul_num[11];
printf("Unesite binarni broj koji treba prevesti u decimalni brojni sistem: ");
scanf("%s", ul_num);
printf("%7.3lf\n", bin2dbl(ul_num));
} Svako ponavljanje bez
razumevanja programskog koda
je tetno i na ispitu e biti
kanjavano oduzimanjem poena.
Komentar
Traena funkcija izraunava vrednost realnog broja zapisanog u binarnom brojnom sistemu i od dobijene
vrednosti pravi podatak tipa double. Obrada se vri na sledei nain: ako niz ne poinje znakom '.', onda je u
pitanju celobrojni deo tog realnog broja. Pravi se ciklus koji se ponavlja sve dok se ne obrade svi znakovi u
nizu (sluaj kada je zadat ceo broj) ili dok se ne naie na decimalnu taku (realni broj sa razlomljenim delom).
Do nastavka funkcije se dakle stie u tri situacije: niz je poeo decimalnom takom ili obrada niza je zavrena
ili tokom obrade celobrojnog dela se stiglo do decimalne take. S obzirom na to da se u sluaju prve i tree
situacije postupa isto (odreuje se razlomljeni deo), najpre se eliminie druga situacija (zavrena obrada)
proverom da li je i manje od num_length. Ako je taj uslov ispunjen, u novom ciklusu se odreuje vrednost
razlomljenog dela, s tim to obrada ide od kraja niza, zbog prirode problema (krajnje desna pozicija je pozicija
cifre najmanje teine).
Ova funkcija nije prilagoena praktinoj upotrebi, jer bi to zahtevalo da se pre odreivanja vrednosti broja
izvri provera da li se dati znakovni niz zaista sastoji od cifara 0 i 1 i najvie jednog decimalnog zareza.
Preporuuje se pisanje funkcije koja to utvruje za samostalnu vebu.

Materijal za vebe na tabli i pripremu ispita Strana 48 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak CI-2006-Sep-1
Na programskom jeziku C napisati potprograme i glavni program koji vre obradu niza realnih
brojeva. Unos podataka, obrada, ispis rezultata i oslobaanje memorije se vri u potprogramima.
Potprogram za unos sa standardnog ulaza uitava broj elemenata niza realnih brojeva tipa float,
alocira potrebnu dinamiku memoriju sa smetanje tog niza i uitava elemente niza. Ovaj potprogram
treba da proveri uspenost poziva funkcije za dodelu dinamike memorije i u sluaju neuspeha
prekida izvravanje programa. Potprogram za obradu, ispis i oslobaanje memorije tampa sve
brojeve iz unetog niza koji su u opsegu +/- 10% od vrednosti aritmetike sredine niza. Nakon ispisa,
potprogram oslobaa dinamiki alociranu memoriju. Napisati glavni program koji redom poziva
opisane potprograme. Potprogrami sa glavnim programom smeju razmenjivati podatke samo preko
liste argumenata i povratne vrednosti.
#include <stdio.h>
#include <stdlib.h>
#define FAILURE 0
#define SUCCESS 1
int Unos(float **niz_Adr, int *br_el_Adr) {
float *niz;
int i, br_el;
printf("Unesite broj elemenata: "); Nemojte NIKAD
scanf("%d", &br_el);
niz = calloc(br_el, sizeof(float));
programski kod
if (NULL == niz) return FAILURE;
for (i = 0; i < br_el; i++)
uiti napamet.
scanf("%f", &niz[i]);
*niz_Adr = niz;
*br_el_Adr = br_el;
return SUCCESS;
}
void ObradaIspisDealociranje(float *niz, int br_el) {
float arit_sred = 0.0;
int i;
for(i = 0; i < br_el; i++) arit_sred += niz[i];
if (0 != br_el) arit_sred /= br_el;
printf("%f\n", arit_sred);
for(i = 0; i < br_el; i++)
if (niz[i] >= 0.9 * arit_sred && niz[i] <= 1.1 * arit_sred)
printf("%f\t", niz[i]);
printf("\n");
free(niz);
}
main() {
Svako ponavljanje bez
float *niz = 0; razumevanja programskog koda
int br_el;
if (Unos(&niz, &br_el)) je tetno i na ispitu e biti
else
ObradaIspisDealociranje(niz, br_el);
kanjavano oduzimanjem poena.
printf("Greska pri unosu\n");
niz = 0;
}

Komentar
U postavci se eksplicitno trai da glavni program komunicira sa potprogramima putem argumenata i povratnih
vrednosti. Takav pristup u pisanju programa se preporuuje ak i ako se posebno ne naglasi. Takoe, nije
navedeno - ali bi trebalo podrazumevati, meusobna komunikacija potprograma treba da se odvija na isti
nain.
Funkcija za unos i alokaciju memorije vraa vrednost celobrojnu vrednost - FAILURE odnosno SUCCES u
zavisnosti od uspeha. S obzirom na to da ta funkcija alocira memoriju za niz koji treba uitati dakle menja
vrednost pokazivaa, u potprogram se prenosi adresa pokazivaa na dati niz brojeva. U suprotnom nikakva
izmena ne bi bila vidljiva van potprograma. Kod dealokacije memorije, ne prosleuje se adresa pokazivaa jer
se ne oekuje da se promena vrednosti tog pokazivaa vidi sa mesta poziva (u ovom sluaju iz glavnog
programa). Ipak, u toj situaciji programer treba da vodi rauna da nakon poziva funkcije za dealokaciju
memorije postavi vrednost to pokazivaa na 0. U ovom zadatku to nije neophodno jer se taj pokaziva vie ne
koristi (kraj programa), ali je dobra praksa.

Materijal za vebe na tabli i pripremu ispita Strana 49 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C
Zadatak C2008-A1
ta ispisuje sledei program na programskom jeziku C, ukoliko je pozvan sa prog 3 5 7 8 ?
#include <stdio.h>
#include <stdlib.h>
union { struct { int a,b;} c; struct { int a,b,c;} d; } e;
void main(int argc, char* argv[])
{
int s=atoi(argv[1]), br = atoi(argv[2]);

for(e.c.a=0;e.c.a<br;e.c.a++)
for(e.d.a=0;e.d.a<5;e.d.a++)
for(e.c.a=0;e.c.a<5;e.c.a++)
for(e.c.b=0;e.c.b<5;e.c.b++) s++;

printf("%d", s);
}

A) 30 (B) 28 C) 628
Komentar
S obzirom na to da je kod elemenata unije memorijski prostor deljen, polja a i b strukture c dele iste lokacije
sa poljima a i b strukture d. Drugim reima, svaka promena nad poljima a i b strukture c istovremeno
predstavlja i promenu nad poljima a i b strukture d i obrnuto.
Na poetku promenljiva s dobija vrednost 3 a br 5. Dakle, spoljni ciklus (e.c.a) se na prvi pogled ponavlja 5
puta. Medjutim, vec naredni unutranji ciklus (e.d.a) se vri nad istim podatkom, tako da kada on bude
zavren, e.d.a e imati vrednost 5, a to automatski vai i za e.c.a. Sledei for ciklus se odvija ponovo nad
e.c.a. Na osnovu prethodnog zakljuka, kada on bude zavren, automatski e biti ispunjen uslov za prekid
prva dva ciklusa. Prema tome, "koristan efekat" u programu imaju naredna dva ugnedena ciklusa. Ukupan
broj izvravanja operacije s++ je zbog toga 25. Kako je poetna vrednost s bila 3, konana vrednost u
trenutku ispisivanja e biti 28.

Zadatak C2008-S11
Napisati program na programskom jeziku C koji sa standardnog ulaza ita znak po znak do kraja
linije. Znakovi se itaju jedan po jedan. U poetku se dinamiki alocira niz od 10 elemenata. Nadalje,
svaki put kada u nizu treba vie mesta, niz se proiri za jo 10 znakova.
#include<stdlib.h>
#include<stdio.h>

void main(){
char *p=NULL, c;
int i = 0;
while( (c=getchar()) != '\n') {
if (i%10 == 0) p = realloc( p, (i+10) * sizeof(char) );
p[i++] = c;
}
if (i%10 == 0) p = realloc( p, (i+1) * sizeof(char) );
p[i++] = '\0';
printf("%s\n",p);
free(p); Svako ponavljanje bez
} razumevanja programskog koda
je tetno i na ispitu e biti
kanjavano oduzimanjem poena.

Materijal za vebe na tabli i pripremu ispita Strana 50 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C2008-S12
Napisati segment programa na programskom jeziku C koji menja dimenziju kvadratne matrice sa
staroN na N. Ako se matrica smanji, tada elementi koji ostanu u novoj matrici treba da budu
neizmenjeni u odnosu na staru matricu. Ako se matrica povea, elementi koji su postojali u staroj
matrici treba da ostanu neizmenjeni.
if (N < staroN) {
for (j = 1; j < N; j++)
for (i = 0; i < N; i++) m[j*N+i] = m[j*staroN+i];
}
if (N != staroN) m = realloc(m,N*N*sizeof(unsigned int));
if (N > staroN){
for (j = staroN-1; j > 0; j--)
for (i = staroN-1; i >= 0; i--)
m[j*N+i] = m[j*staroN+i];
}

Zadatak C2008-S21
Napisati program na programskom jeziku C koji sa standardnog ulaza ita znak po znak do kraja
linije. Znakovi se itaju jedan po jedan. U poetku se dinamiki alocira niz od 10 elemenata. Nadalje,
svaki put kada u nizu vie nema mesta, niz se proiri za jo 10 znakova. U sluaju da realokacija
bude neuspena, zavriti itanje i ispisati ono to moe da stane u ve alocirani prostor.
Reenje
#include<stdlib.h>
#include<stdio.h>
Nemojte NIKAD
void main(){ programski kod
char *staro_p=NULL, *novo_p, c;
int i = 0; uiti napamet.
while( (c=getchar()) != '\n') {
if (i%10 == 0) {
novo_p = realloc( staro_p, (i+10) * sizeof(char) );
if (novo_p == NULL) {
printf("Neuspesno realociranje\n");
break;
}
else staro_p = novo_p;
};
staro_p[i++] = c;
}
if (i%10 == 0) {
novo_p = realloc( staro_p, (i+1) * sizeof(char) );
if (novo_p == NULL) {
printf("Neuspesno realociranje\n");
i--;
}
else staro_p = novo_p;
};
staro_p[i] = '\0';
printf("%s\n",staro_p);
Svako ponavljanje bez
free(staro_p); razumevanja programskog koda
} je tetno i na ispitu e biti
kanjavano oduzimanjem poena.

Materijal za vebe na tabli i pripremu ispita Strana 51 od 52


Elektrotehniki fakultet Univerziteta u Beogradu Programski jezik C

Zadatak C2008-S22
Napisati program na programskom jeziku C koji uita broj vrsta i broj kolona i potom uita matricu
tih dimenzija. Program potom uita broj kolone koju treba izbaciti i izbacuje tu kolonu iz matrice.
Zatim ita redni broj vrste na koji umee vrstu koju e uitati sa standardnog ulaza.
Reenje
#include<stdlib.h>
#include<stdio.h>

void main(){
unsigned int **m, **novo_m;
int M, N, i, j, k;
scanf("%d %d", &M, &N);
m = malloc(M * sizeof(unsigned int*));
for (j = 0; j < M; j++){
m[j] = malloc( N * sizeof(unsigned int) );
for (i = 0; i < N; i++)scanf("%u", &m[j][i] );
}

printf("Unesite broj kolone koju izbacujete: ");


scanf("%d", &k);
if ( k >= 0 && k < N) {
for (j = 0; j < M; j++){
for (i = k+1; i < N; i++)
m[j][i-1] = m[j][i];
m[j] = realloc( m[j], (N-1) * sizeof(unsigned int) );
}
N--;
}
Nemojte NIKAD
for (j = 0; j < M; j++){
for (i = 0; i < N; i++) programski kod
printf("%d ",m[j][i]);
printf("\n"); uiti napamet.
}
printf("\n\n");

printf("Unesite red broj na koji umecete vrstu: ");


scanf("%d", &k);
if ( k >= 0 && k < M) {
m = realloc( m, (M+1) * sizeof(unsigned int*) );
M++;
for( j = M-1; j > k; j--)
m[j] = m[j-1];
m[k] = malloc( N * sizeof(unsigned int) );
for( i = 0; i < N; i++)
scanf("%u", &m[k][i]);
}

Svako ponavljanje bez


for (j = 0; j < M; j++){
for (i = 0; i < N; i++)
printf("%u ",m[j][i]); razumevanja programskog koda
je tetno i na ispitu e biti
free(m[j]);
printf("\n");
} kanjavano oduzimanjem poena.
printf("\n\n");
free(m);
}

Komentar
Zbog itljivosti programa, u ovom reenju su izostavljene provere da li je alokacija (realokacija) uspeno
izvrena. Pri pisanju bilo kakvog programa ove provere NE SMEJU biti izostavljene. Izostavljanjem tih provera,
ponaanje programa u sluaju nedostatka prostora nije predvidivo i moe dovesti do katastrofalnih posledica.

Materijal za vebe na tabli i pripremu ispita Strana 52 od 52


Prvi as raunskih vebi iz Programiranja I

1. Koji od navedenih identifikatora nisu ispravni i zato?

aaa _1_
a12 Windows
12a vece-manje
_12a north&south

2. Koju vrijednost ima promenljiva b poslije izvravanja navedenih naredbi?

short int a=32767, b;


b=a+1; /* b = -32768 */

3. Koju e vrijednost imati realna promjenljiva B poslije datog niza naredbi? Na koji nain se u tu
promjenljivu moe upisati taan rezultat date operacije?

int A;
float B;
A=5;
B=5*A/7; /* B = 3 */

4. Koju e vrijednost uzeti promenljive s1 i s2 nakon izvrenja svake od datih naredbi? Koju e vrijednost
uzeti promenljiva s2 ako se u poslednjem izrazu izostavi spoljanji par zagrada u drugom sabirku?

int s1, s2, q=8;


s1=1;
s2=++s1+5; /* s1=2, s2 = 7 */
s1=!s2; /* s1 = 0, s2 = 7 */
s2+=(q%3)+((q<10)||(s1--)); /* s2 = 10, s1 = 0 */

5. Odrediti vrijednost promenljivih posle izvrenja svake od datih naredbi.

int t, a=3, b=7, i, j;


t=a&b; /* t = 3 */
i=(t==3); /* i = 1 */
j=(i==0) ? i : t; /* j = 3 */
Drugi as raunskih vebi iz Programiranja I

1. Napisati program koji za uneti prirodni broj rauna zbir njegovih cifara.

#include<stdio.h>
main()
{
int s=0,broj;
printf("Unesi prirodan broj\n");
scanf("%i",&broj);
while (broj!=0){
s+=broj%10;
broj/=10;
}
printf("Suma cifara prirodnog broja je: %d\n",s);
}

2. (Sa I kolokvijuma) Napisati program u programskom jeziku C koji uitava prirodan broj N i koji ispituje
da li je taj broj savren broj. Prirodan broj je savren ukoliko je jednak sumi svih svojih djelilaca koji su
manji od njega. Na izlazu tampati odgovarajuu poruku. Primjer: Broj 28 je djeljiv sa 1,2,4,7,14 i 28,
pa je zbir djelilaca manjih od njega 1+2+4+7+14=28, a to znai da je broj 28 savren.

#include<stdio.h>
main()
{
int N,i,suma=0;
printf("Uneti broj N: ");
scanf("%d",&N);
for(i=1; i<N; i++){
if(N%i==0){
suma+=i;
}
}
if(suma==N)
printf("Broj %d jeste savrsen broj\n",N);
else
printf("Broj %d nije savrsen broj\n",N);
}

3. Napisati program koji priblino rauna sumu reda:



1
n
n 1
2

Sumiranje vriti sve dok je opti lan sume vei od 10-4.

#include<stdio.h>
main()
{
int N=1;
float suma=0,op;
op=1.0/(N*N);
while(op>1e-4){
suma=suma+op;
N=N+1;
op=1.0/(N*N);
}
printf("Suma je %f",suma);
}
4. Napisati program koji rauna najvei zajedniki delilac (NZD) brojeva a i b pomou Euklidovog
algortima:
1. Ako je a=b, tada je NZD=a i to je kraj algoritma.
2. Od veeg broja oduzmemo manji i vraamo se na prvi korak.

#include<stdio.h>
void main()
{
int a, b;
puts("Unesi cijele brojeve");
scanf("%d %d",&a,&b);
while(a!=b) {
if (a>b)
a-=b;
else
b-=a;
}
printf("NZD je: %d\n",a);
}
Trei as raunskih vebi iz Programiranja I

1. Napisati program koji formira podniz datog niza koji se sastoji od onih elemenata koji su vei od datog
cijelog broja.

#define MAX 20
#include <stdio.h>
main()
{
int N,C,k=0,i,a[MAX],b[MAX];
printf("Unesi broj clanova niza:");
scanf("%d",&N);
printf("Unesi cijeli broj:"); scanf("%d",&C);
printf("Unesi clanove niza:");
for(i=0;i<N;i++){
scanf("%d",a+i);
if(a[i]>C)
b[k++]=a[i];
}
if(k>0){
printf("Elementi niza koji su veci od datog cijelog broja
su:\n");
for(i=0;i<k;i++) printf("%d ",b[i]);
}
}

2. Napisati program koji definie niz cijelih brojeva X i koji vri sumiranje elemenata tog niza korienjem
pomone pokazivake promjenljive. Prilagoditi program tako da eventualna izmjena broja elemenata
niza u njegovoj inicijalizaciji ne zahtijeva intervenciju na programu.

#include<stdio.h>
main(){
int X[]={-3,4,2,7,11,-9};
int *p, i, suma=0;
for(i=0; i < sizeof(X)/sizeof(X[0]); i++) {
p=&(X[i]); suma+=*(p+i); ili suma+=*p++, pri emu
suma+=*p; pre petlje mora p=&(X[0]); ili p=X.
}
printf("Dobijena suma je: %d\n",suma);
}
3. Napisati program koji uitava matricu cijelih brojeva A, dimenzija NxM, i koji tu matricu tampati
pratei strelice prikazane na slici. Npr., za matricu:

1 2 3 4
11 12 13 14
A
21 22 23 24

31 32 33 34
redosljed tampanja treba da bude: 1,11,21,31,32,22,12,2,3,13,23,33,34,24,14,4.

#include <stdio.h>
main(){
int i,j,n,m, a[20][20];
printf("Unesi dimenzije matrice a: ");
scanf("%d %d",&n,&m);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
scanf("%d",&a[i][j]);
for(j=0;j<m;j++)
if(j%2==0)
for(i=0;i<n;i++)
printf("%d ",a[i][j]);
else
for(i=n-1;i>=0;i--)
printf("%d ",a[i][j]);
}
etvrti as raunskih vjebi iz Programiranja I

1. Uitati string koji sadri manje od 20 karaktera sa tastature i sva mala slova u tom stringu
konvertovati u velika, a ostale karaktere ne menjati.

#include<stdio.h>
#include<string.h>
main()
{ char niz[20];
int i;
puts("Unesi neku rec");
scanf("%s",niz);
for (i=0;i<strlen(niz);i++){
if (niz[i]>='a' && niz[i]<='z')
niz[i]-='a'-'A';
}
printf("Novi string je: %s",niz);
}

2. Napisati program koji uitava string, koji predstavlja reenicu, i koji koristei funkciju
proverava da li je reenica ispravno zadata. Ispravno zadata reenica zadovoljava sljedee:
a) Reenica mora poeti velikim slovom i zavriti se takom.
b) Rijei su proizvoljni podstringovi koji mogu sadrati samo mala slova.
c) Rijei mogu biti razdvojeni jednim razmakom (SPACE), zarezom ili taka-zarezom.
U glavnom programu uitati string, pozvati funkciju i na izlazu ispisati obavjetenje da li je
reenica ispravno zadata.

#include <stdio.h>
#include <string.h>

int recenica(char *);

main(){
int p;
char s[20];
printf("\nUnesi string ");
gets(s);

p=recenica(s);

if(p==1)
printf("Nije");
else
printf("Jeste");
}
int recenica(char *s){

int i, duz, ind=0;

duz=strlen(s);

if ((s[0]<'A' || s[0]>'Z') || s[duz-1]!='.')


ind=1;

if(ind==0)
{
for(i=1;i<duz-1;i++){

if((s[i]<'a' || s[i]>'z') && s[i]!=' ' && s[i]!=',' && s[i]!=';')


ind=1;

if((s[i]==' '||s[i]==','||s[i]==';') && (s[i+1]==' '|| s[i+1]==','


|| s[i+1]==';'))
ind=1;
}
}

return ind;

3. Napisati program koji sadri funkciju koja odreuje i tampa srednju vrednost niza realnih
brojeva. Broj lanova, kao i lanovi niza se zadaju po startovanju programa.

#include<stdio.h>

float sred_niz(int,float *);

main()
{
int n,i;
float a[20];
puts("Uneti broj clanova niza");
scanf("%d",&n);
puts("Uneti elemente niza");
for(i=0;i<n;i++)
scanf("%f",a+i);
printf("Srednja vrednost ovog niza je: %f\n",sred_niz(n,a));
}

float sred_niz(int duzina,float *a)


{
int i;
float sum=0.0;
for(i=0;i<duzina;i++)
sum+=a[i];
return sum/duzina;
}
4. Napisati program u programskom jeziku C koji uitava prirodan broj N i koji tampa prvih N
savrenih brojeva. Prirodan broj je savren ukoliko je jednak sumi svih svojih djelilaca koji
su manji od njega. Program sadri funkciju koja odreuje da li je broj koji joj se prosleuje
kao argument savren.
Primjer: Broj 28 je djeljiv sa 1,2,4,7,14 i 28, pa je zbir djelilaca manjih od njega
1+2+4+7+14=28, a to znai da je broj 28 savren.

#include<stdio.h>

main(){
int N,k=0;
long i=1;
printf("Uneti N ");
scanf("%d",&N);
while(k<N){
if(savrsen(i)==1){
k=k+1;
printf("%d\n",i);
}
i=i+1;
}
}

int savrsen(long M){


long suma=0,i=1;
while(i<=M/2){
if(M%i==0)
suma+=i;
i+=1;
}
if(suma==M)
return 1;
else
return 0;
}
Peti as raunskih vebi iz Programiranja I

1. Napisati program koji na zadatom sortiranom nizu primjenjuje binarno pretraivanje uz pomo
odgovarajue rekurzivne funkcije.

#include <stdio.h>
#include <conio.h>

int binarno(int [], int, int, int);


int K;

main(){
int A[30], N, i, poz;
printf("Uneti duzinu niza");
scanf("%d",&N);
printf("Uneti elemente niza");
for(i=0;i<N;i++)
scanf("%d",A+i);
printf("Uneti element koji se trazi: ");
scanf("%d",&K);
poz = binarno(A,0,N-1,N/2);
if (poz == -1)
printf("Nema takvog elementa");
else
printf("Element se nalazi na poziciji %d!",poz);
getch();
}

int binarno(int X[], int fir, int last, int mid){


if (fir > last)
return -1;
else if (fir == last || fir == last-1) {
if (X[fir] == K || X[last] == K)
return (X[fir] == K) ? fir : last;
else
return -1;
}
if (X[mid] == K)
return mid;
else if (X[mid] < K)
return binarno(X,mid+1,last,(mid+1+last)/2);
else
return binarno(X,fir,mid-1,(fir+mid-1)/2);
}
2. Sortirati elemente niza celih brojeva u rastui poredak koristei sortiranje sa spajanjem (merge sort).

#include <stdio.h>
#include <conio.h>

void merge_sort(int [], int, int, int);


void combine(int [], int, int, int);
void swap(int [], int, int);

main(){
int A[30], N, i;
printf("Uneti duzinu niza");
scanf("%d",&N);
printf("Uneti elemente niza");
for(i=0;i<N;i++)
scanf("%d",A+i);
merge_sort(A,0,N-1,N/2);
printf("Sortirani niz je: ");
for(i=0;i<N;i++)
printf("%d ",A[i]);
getch();
}

void merge_sort(int X[], int fir, int last, int mid){


if (fir == last)
return;
else {
merge_sort(X,fir,mid,(fir+mid)/2);
merge_sort(X,mid+1,last,(mid+1+last)/2);
}
combine(X,fir,last,mid);
}

void combine(int X[], int fir, int last, int mid){


int i=mid+1,j;
while (i<=last){
j = i;
while (X[j]<X[j-1] && j>fir){
swap(X,j,j-1);
j--;
}
i++;
}
}

void swap(int X[], int p, int q){


int temp;
temp = X[p];
X[p] = X[q];
X[q] = temp;
}

Napomena: Slika uz ovaj program je preuzeta sa internet stranice http://en.wikipedia.org/wiki/Merge_sort


esti as raunskih vjebi iz Programiranja I

1. Sastaviti program koji od elemenata dinamikog niza formira druga dva dinamika niza, niz
nenegativnih i niz negativnih brojeva. Prikazati elemente tako dobijenih nizova.
#include<stdio.h>
#include<stdlib.h>
main()
{
int *a,*b,*c,i,j=0,k=0,duz,duz1=0;
puts("Uneti duzinu niza");
scanf("%d",&duz);
a=(int *)malloc(duz*sizeof(int));
if(a==NULL){
puts("Nema memorije"); exit(1);
}
puts("Elementi niza");
for(i=0;i<duz;i++){
scanf("%d",a+i);
if(a[i]>=0)
duz1++;
}
b=(int *)malloc(duz1*sizeof(int));
c=(int *)malloc((duz-duz1)*sizeof(int));
if((b==NULL)||(c==NULL)){
puts("Nema memorije"); exit(1);
}
for(i=0;i<duz;i++)
if(a[i]>=0)
b[j++]=a[i];
else
c[k++]=a[i];
free(a);
puts("Pozitivni brojevi su:");
for(i=0;i<duz1;i++)
printf("%d ",b[i]);
puts("Negativni brojevi su:");
for(i=0;i<duz-duz1;i++)
printf("%d ",c[i]);
free(b);
free(c);
}

2. Napisati program kojim se unose dva cijela broja a i b (a<b, ne treba provjeravati). Program treba da
generie niz svih sluajno rasporeenih brojeva iz intervala [a,b], pri emu se elementi niza ne smiju
ponavljati. Niz dinamiki alocirati.
#include <stdio.h>
#include <stdlib.h>
void generisi(int *, int, int);
int main()
{
int *X, a,b,i;
// ovom naredbog podeavamo generator sluajnih brojeva
srand (time(NULL));
printf("Unesite a i b:");
scanf("%d%d",&a,&b);
X=(int *)malloc((b-a+1)*sizeof(int));
if (X==NULL)
{
printf("Nema memorije!");
exit(1);
}
generisi(X,a,b);
printf("Generisani niz slucajnih brojeva je: ");
for (i=0;i<b-a+1;i++)
printf("%d ",X[i]);
free(X);

}
// I varijanta
void generisi(int *X, int a, int b)
{
int i, k=0, broj,ind;
while (k<b-a+1)
{
broj=a+rand()%(b-a+1);
ind=1;
for (i=0;i<k;i++)
if (X[i]==broj)
{
ind=0;
break;
}
if (ind)
X[k++]=broj;
}
}
// II varijanta
void generisi(int *X, int a, int b)
{
int i, t, poz;
for (i=0;i<b-a+1;i++)
X[i]=a+i;
for (i=0;i<b-a+1;i++)
{
poz=rand()%(b-a+1);
t=X[i];
X[i]=X[poz];
X[poz]=t;
}
}
Sedmi as raunskih vjebi iz Programiranja I

1. Svaki red fajla c:\broj.txt sadri po jedan cijeli broj. Sastaviti program koji tampa najmanji i najvei cijeli broj u
tom fajlu.

#include<stdio.h>
main()
{
FILE *fp;
int najmanji, najveci, broj;
fp=fopen("c:\\broj.txt","r");
if(fp==NULL){
printf("Greska pri otvaranju fajla");
exit(1);
}
fscanf(fp,"%d",&broj);
najmanji=broj;
najveci=broj;
while(fscanf(fp,"%d",&broj)!=EOF){
if(broj<najmanji)
najmanji=broj;
if(broj>najveci)
najveci=broj;}
fclose(fp);
printf("Najmanji je broj %d, a najveci %d\n", najmanji, najveci);
}

2. Svaki red fajla Brojevi.txt sadri po jedan prirodan broj. Napisati program koji formira fajl 2_9.txt prepisujui
samo one brojeve iz fajla Brojevi.txt koji nemaju drugih cifara osim 2 i 9. Primjeri takvih brojeva su 2, 9, 22, 29,
229 itd. Nakon datih obrada zatvoriti predmetne fajlove. Vodite rauna da li su fajlovi korektno otvoreni.

#include<stdio.h>
void main()
{
int broj, pom, cif, ind;
FILE *a, *b;
if((a=fopen("c:\\Brojevi.txt","r"))==NULL) {
puts("Greska pri otvaranju fajla"); exit(1); }
if((b=fopen("c:\\2_9.txt","w"))==NULL) {
puts("Greska pri otvaranju fajla"); exit(1); }
while(fscanf(a,"%d",&broj)!=EOF) {
ind=1; pom=broj;
while(pom!=0){
cif=pom%10;
if(cif!=2 && cif!=9)
ind=0;
pom/=10;
}
if(ind && broj!=0)
fprintf(b,"%d\n",broj);
}
fclose(a); fclose(b);
}
Osmi as raunskih vjebi iz Programiranja I

1. Elementi liste su celi brojevi. Sastaviti program koji vri sumiranje brojeva upisanih u vorovima liste
korienjem rekurzivne funkcije.

#include<alloc.h>

struct str {
int a;
struct str *sled; };

int sabiranje(struct str *);

main()
{
struct str *elem, *pom, *glava;
int i, n;
puts("Uneti broj elemenata liste");
scanf("%d",&n);
puts("Elementi liste");
for(i=0;i<n;i++){
elem=(struct str *) malloc(sizeof(struct str));
scanf("%d",&(elem->a));
elem->sled=NULL;
if(i==0){
pom=elem;
glava=elem;
}
else {
pom->sled=elem;
pom=elem;
}
}
printf("Zbir je %d ",sabiranje(glava));
}

int sabiranje(struct str *lista){


if(lista->sled==NULL)
return lista->a;
else
return lista->a + sabiranje(lista->sled);
}

2. Elementi liste su sortirani celi brojevi. Sastaviti program koji uitava ceo broj i smeta ga u sortiranu listu tako da
se ne narui sortiranost. Umetanje tog broja izvriti pomou funkcije, a ne u okviru glavnog programa.

#include<stdio.h>
#include<alloc.h>

struct str {
int a;
struct str *sled;
};

struct str *umetanje(struct str *,int);

main()
{
struct str *elem, *pom, *glava;
int i, n, broj;
puts("Uneti broj elemenata liste");
scanf("%d",&n);
puts("Elementi liste");
for(i=0;i<n;i++){
elem=(struct str *) malloc(sizeof(struct str));
scanf("%d",&(elem->a));
elem->sled=NULL;
if(i==0){
pom=elem;
glava=elem;
}
else {
pom->sled=elem;
pom=elem;
}
}
printf("Uneti neki broj ");
scanf("%d",&broj);
pom=umetanje(glava,broj);
for(i=0;i<=n;i++){
printf("%d ",pom->a);
pom=pom->sled;
}
}

struct str *umetanje(struct str *lista,int broj)


{
struct str *umet,*poc,*pom;
poc=lista;
umet=(struct str *)malloc(sizeof(struct str));
umet->a=broj;
if(broj<=lista->a){
umet->sled=lista;
return umet;
}
pom=lista;
lista=lista->sled;
while(lista!=NULL){
if(broj<=lista->a){
umet->sled=lista;
pom->sled=umet;
return poc;
}
else{
pom=lista;
lista=lista->sled;
}
}
umet->sled=NULL;
pom->sled=umet;
return poc;
}
Deveti as raunskih vjebi iz Programiranja I

1. Elementi liste su parovi; prvi u paru je cio broj k, a drugi je realan broj a, to znai da taj element liste
definie lan polinoma axk. Dakle, cijela lista zadaje jedan polinom p(x). Napisati program koji formira
datu listu, zatim uitava realan broj x, argument polinoma, a nakon toga rauna vrijednost polinoma p(x)
korienjem rekurzivne funkcije. tampati dobijenu vrijednost.

struct lista {
int k;
float a;
struct lista *next;
};

float polinom(struct lista *p, float x)


{
if(p->next==NULL)
return p->a*pow(x,p->k);
return p->a*pow(x,p->k)+polinom(p->next,x);
}

2. Elementi liste su rijei. Napisati funkciju koja odreuje da li su te rijei leksikografski ureene u rastui
poredak.

struct lista {
char rijec[20];
struct lista *next;
};

int uredjene(struct lista *p)


{
if(p->next==NULL)
return 1;
else {
if (strcmp(p->rijec,p->next->rijec)>0)
return 0;
else
return uredjene(p->next);
}
}

3. Elementi liste su cijeli brojevi. Napisati program kojim se od poetne liste formiraju dvije nove liste, lista
sa parnim i lista sa neparnim elementima. tampati dobijene liste.

#include <stdio.h>
#include <stdlib.h>

struct str
{
int a;
struct str *sled;
};

int main()
{
int n,i;
struct str *el, *pre, *glava, *lista, *glPar=NULL, *glNep=NULL, *prePar=NULL,
*preNep=NULL;
puts("Unijeti broj elemenata liste:");
scanf("%d",&n);

puts("Unesi elemente liste:");


for(i=0;i<n;i++)
{
el=(struct str *)malloc(sizeof(struct str));
scanf("%d",&(el->a));
el->sled=NULL;

if(i==0) glava=el;
else pre->sled=el;

pre=el;
}

lista=glava;

while(lista!=NULL){
if((lista->a)%2 == 0){
if(glPar==NULL) glPar=lista;
else prePar->sled=lista;
prePar=lista;
}
else{
if(glNep==NULL) glNep=lista;
else preNep->sled=lista;
preNep=lista;
}
lista=lista->sled;
}

if(prePar) prePar->sled=NULL;
if(preNep) preNep->sled=NULL;

puts("Lista sa parnim elementima:");


while(glPar!=NULL)
{
printf("%d ", glPar->a);
glPar=glPar->sled;
}

puts("\nLista sa neparnim elementima:");


while(glNep!=NULL)
{
printf("%d ", glNep->a);
glNep=glNep->sled;
}

}
4. Na osnovu uneene matrice susjedstva grafa sa 5 vorova provjeriti da li je taj graf usmjeren ili
neusmjeren.

#include <stdio.h>
void main()
{
int ms[5][5];
int i, j, ind=1;
puts("Uneti matricu susedstva grafa ");
for(i=0;i<5;i++)
for(j=0;j<5;j++)
scanf("%d",&ms[i][j]);
for(i=0;i<5;i++)
if(ms[i][i]==1)
ind=0;
if(ind)
for(i=0;i<5;i++) {
for(j=0;j<5;j++) /* for(j=i+1;j<5;j++) */
if(ms[i][j]!=ms[j][i])
ind=0;
if(ind==0)
break;
}
if(ind)
printf("\nNeusmjeren!\n");
else
printf("\nUsmjeren!\n");
}
Deseti as raunskih vjebi iz Programiranja I

1. Napisati funkciju koja odreuje broj vorova drveta (teinu drveta).

struct drvo {
int a;
struct drvo *left;
struct drvo *right;
};

int tezina(struct drvo *root)


{
if(root->left!=NULL && root->right!=NULL)
return 1 + tezina(root->left) + tezina(root->right);
else if(root->left!=NULL && root->right==NULL)
return 1 + tezina(root->left);
else if(root->left==NULL && root->right!=NULL)
return 1 + tezina(root->right);
else
return 1;
}

2. Napisati funkciju koja odreuje broj listova drveta.

int listovi(struct drvo *root)


{
if(root->left!=NULL && root->right!=NULL)
return listovi(root->left) + listovi(root->right);
else if(root->left!=NULL)
return listovi(root->left);
else if(root->right!=NULL)
return listovi(root->right);
else
return 1;
}

3. Svakom vrhu pridruena je jedna rije duine manje od 12 karaktera. Sastaviti potprogram koji odreuje
koliko puta se pojavljuje data rije.

struct drvo {
char rijec[12];
struct drvo *left;
struct drvo *right;
};

int brojrijeci(struct drvo *root, char *s)


{
int ind=0;
if(strcmp(root->rijec,s)==0)
ind=1;
if(root->left!=NULL && root->right!=NULL)
return ind + brojrijeci(root->right,s) + brojrijeci(root->left,s);
else if(root->left!=NULL)
return ind + brojrijeci(root->left,s);
else if(root->right!=NULL)
return ind + brojrijeci(root->right,s);
else
return ind;
}
4. Vri se obilazak binarnog drveta od korijena ka listovima i sabiraju se cijeli brojevi upisani u vorovima
drveta. Sastaviti potprogram koji pronalazi najveu takvu putanju.

struct drvo {
int n;
struct drvo *left;
struct drvo *right;
};

int max_path(struct drvo *root)


{
if(root->left==NULL && root->right==NULL)
return root->n;
else if(root->left!=NULL && root->right!=NULL)
return root->n + max(max_path(root->left),max_path(root->right));
else if(root->left!=NULL)
return root->n + max_path(root->left);
else
return root->n + max_path(root->right);
}

int max(int a, int b)


{
return (a > b) ? a : b;
}

5. Dato je binarno drvo u ijim su vorovima upisani cijeli brojevi. Odrediti redosljed tampanja tih brojeva
ukoliko koristimo:
a) Inorder obilazak (lijevo poddrvo, korijen, desno poddrvo);
b) Preorder obilazak (korijen, lijevo poddrvo, desno poddrvo);
c) Postorder obilazak (lijevo poddrvo, desno poddrvo, korijen).

a) 11, 4, 9, 7, 6, 2, 5, 3, 1
b) 2, 7, 4, 11, 9, 6, 5, 3, 1
c) 11, 9, 4, 6, 7, 1, 3, 5, 2
LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

... Zadaci iz C-a ...

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

1. Napraviti program koji ucitava koordinate dvije tacke u


trodimenzionalnom prostoru:
Tacke t i t su definirane kao trojke:
1 2

- t =(x , y , z ) ,
1 1 1 1
- t =(x , y , z ).
2 2 2 2
Kao izlaz program daje udaljenost izmedju tih tacki.

NAPOMENA: Za drugi korijen koristiti funkciju sqrt() koja je


definirana u datoteci math.h. Na primjer, naredba a=sqrt(9); ce
izracunati drugi korijen iz 9 i pridruziti izracunatu vrijednost
varijabli a.

RJEENJE:

// Ukljucujemo datoteke u kojima se nalaze funkcije koje cemo koristiti.


# include <stdio.h>
# include <math.h>
// Definisanje glavne funkcije main()
int main () {
// Definisanje potrebnih varijabli
float x1,y1,z1,x2,y2,z2,d;
// Unos kordinata x1,y1,z1 (printf - ispis poruke; scanf - unos varijabli)
printf("Unesi tacku a(x1,y1,z1): ");
scanf("%f,%f,%f", &x1, &y1, &z1);
// Unos kordinata x2,y2,z2
printf("Unesi tacku b(x2,y2,z2): ");
scanf("%f,%f,%f", &x2, &y2, &z2);
// Racunanje udaljenosti po formuli (sqrt - funkcija koja racuna drugi korjen)
d=sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)+(z2-z1)*(z2-z1));
// Ispis udaljenosti d
printf("Udaljenost izmedju tacki a i b je: %f", d);
// Kraj programa (getch() - stavljamo da bi zadrzali poruku u kojoj je
// rezultat. U suprotnom nam se nece prikazati poruka na ekranu, iako je
// program uspjesno izvrsen
getch();
// Return 0; - (umjesto 0 mozemo staviti bilo koji cio broj, jednostavno
// nekako je potrebno zavrsiti funkciju main() pa se obicno stavlja return 0;
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

2. Napravite C-program koji ucitava potronju elektricne


energije u KWh (velika tarifa(VT) i mala tarifa(MT)) i
pripadajuce cijene po KWh (cijena za malu tarifu i cijena za
veliku tarifu).
Kao izlaz program daje:
- ukupnu potronju u KWh;
- novcani iznos racuna;
- udio velike tarife i male tarife u ukupnoj potronji.
Na primjer, izlaz iz programa treba biti sljedeceg formata:
Ukupna potrosnja je 234.25 KWh.
Udio velike tarife u ukupnoj potrosnji je 25 %.
Udio male tarife u ukupnoj potrosnji je 75%.
Iznos racuna je 25.45 KM.

RJEENJE:

# include <stdio.h>
int main () {
// Definisanje potrebnih varijabli
float VT,MT,CV,CM,UKUPNO,RACUN,UDIOM,UDIOV;
// Unos male tarife, velike tarife, cijene male tarife i cijene velike tarife
printf("\n Unesi potrosnju po velikoj tarifi (KWh): ");
scanf("%f", &VT);
printf("\n Unesi potrosnju po maloj tarifi (KWh): ");
scanf("%f", &MT);
printf("\n Cijena za veliku tarifu po jednom Kwh: ");
scanf("%f", &CV);
printf("\n Cijena za malu tarifu po jednom Kwh: ");
scanf("%f", &CM);
// Racunanje ukupne potrosnje
UKUPNO=VT+MT;
// Racunanje cijene ukupne potrosnje (cijena po maloj tarifi + cijena po
// velikoj tarifi)
RACUN=VT*CV+MT*CM;
// Izracunava udio velike i male tarife u ukupnoj potrosnji (procenat)
UDIOM=(MT/UKUPNO)*100;
UDIOV=(VT/UKUPNO)*100;
// Ispis rezultata
printf ("\n Ukupna potrosnja elektricne energije je: %.f KWh", UKUPNO);
printf ("\n Ukupna cijena elektricne energije je: %.f KM", RACUN);
printf ("\n Udio velike tarife u potrosnji je: %.f procenata", UDIOV);
printf ("\n Udio male tarife u potrosnji je: %.f procenata", UDIOM);
// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

3. Napisati program koji ce izracunati presjek skupova S1 i S2.


Skupovi S1 i S2 definirani su intervalima realnih brojeva:
S1=[A, B]
S2=[C, D].
Na primjer, za slijedeci ulaz: A=3, B=9, C=7, D=11
program kao izlaz treba dati:

Rezultantni interval je REZ=[7, 9].

RJEENJE:

#include <stdio.h>
main() {
// Definisanje varijabli
float A,B,C,D,MAX,MIN;
// Unos skupova
printf("\n Unesi prvi skup X[A,B] A>B: ");
scanf("%f,%f", &A,&B);
printf("\n Unesi drugi skup Y[C,D] C>D: ");
scanf("%f,%f", &C,&D);

/* Logika zadatka je sljedeca: Prvo moramo pretpostaviti da je prvi broj


intervala veci ili jednak drugom, A>=B i C>=D, jer ako ovo ne vrijedi interval
nije matematicki ispravan (taj uslov nismo ispitivali da nebi komplikovali
zadatak). Presjek skupa ce biti neki interval [MIN,MAX].
Uslov da zadatak ima RJEENJE je da je B < C kao i D < A sto je i logicno jer
u suprotnom presjeka nema!
Broj MIN je ustvari jedan od brojeva A ili C (manji broj od ova 2 broja),
a MAX je manji broj od brojeva B i D. Ako je A=C ili B=D uzima se vrijednost
pod ELSE ali tada nam je svakako svejedno koja ce se uzeti vrijednost kao MIN
ili MAX jer je tada A=C odnosno B=D */

if (A>C) MAX=A; else MAX=C;


if (B<D) MIN=B; else MIN=D;
if ((B<C)||(A>D)) printf("\n Nema presjeka!"); else {
printf ("\n Presjek je: [%.f,%.f]", MAX, MIN); }
// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

4. Napisati program koji ucitava koeficijente a, b i c realnog


tipa. Ti koeficijenti definiraju funkciju f(x):
2
f(x)=ax +bx+c
Program zatim provjerava da li su ti keficijenti u rasponu -10 do
10. Ako nisu, program ispisuje poruku:
Koeficijenti a, b i c nisu u zadanom rasponu.
Ako koeficijenti a, b i c jesu u zadanom rasponu, program kao
izlaz daje vrijednost prve derivacije u tacki x. Tacka x se
takodjer unosi sa standardnog ulaza.
Na primjer, ako je ulaz a=1, b=2, c=1, x=1 program kao izlaz
daje: Prva derivacija u tacki x=1 je 4.

RJEENJE:

# include <stdio.h>
int main () {
// Definisanje varijabli
float a,b,c,x,izvod;
// Unos koeficijenata a,b,c
printf ("Unesi koef. (a,b,c) funkcije f(x)=ax2+bx+c (-10<(a,b,c)<10):");
scanf("%f,%f,%f", &a,&b,&c);
// Unos vrijednosti x
printf ("Unesi vrijednost x");
scanf("%f", &x);
// Ispit uslova
if (a>-10&&a<10&&b>-10&&b<10&&c>-10&&c<10){
// Izracunavanje izvoda po odredjenoj matematickoj formuli
izvod=2*a*x+b;
// Ispis izvoda
printf("Prva derivacija u tacki x=%.f je %.f", x, izvod);
// Ispis odgovarajuce poruke ukoliko uslov nije zadovoljen
} else printf ("Koeficijenti nisu iz odgovarajuceg intervala!");
// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

5. Napisati program koji ucitava tri cijela broja iz intervala


od 50 do 200. Ako svi uneseni brojevi nisu iz tog intervala,
program treba ispisati poruku "Svi brojevi nisu iz intervala 50
do 200 i zavriti program. Ako su brojevi unutar tog intervala
program treba ispisati ucitane brojeve po velicini od najmanjeg
prema najvecem.

RJEENJE:

#include <stdio.h>
main() {
// Definisanje varijabli
int x[3], i, j, p;
// Unos brojeva
printf("\n Unesi tri broja u rasponu od 50 do 200 (U formatu: a, b, c): ");
scanf("%d, %d, %d", &x[0], &x[1], &x[2]);
// Provjera jesu li brojevi iz odgovarajuceg intervala
if (x[0]>50&&x[1]>50&&x[2]>50&&x[0]<200&&x[1]<200&&x[2]<200) {
/* Sortiranje brojeva
Potrebne su nam dvije for petlje koje ce listati brojeve koji se nalaze u
nekom nizu. Ovaj tip sortiranja se uglavnom svodi na provjeru da li je prvi
broj manji od drugog ili treceg, i ako jeste, onda mijenja mjesto sa tim
brojem. Medjutim nakon ovoga nije zavrseno sortiranje. Ako npr. Unesemo
brojeve 3, 2, 1, nakon prvog prolaska imamo 2, 3, 1 nakon drugog 2, 1, 3 ali
jos uvijek nije zavrseno sortiranje, i zbog toga i postoji prva for petlja
koja ce to ponoviti jos jednom i dobivamo 1, 2, 3 i niz je sortiran, i sada ga
samo jos treba ispisati na ekran. */
for (i=0;i<2;i++)
for (j=0;j<2;j++)
if (x[j]>x[i]) {
p=x[i];
x[i]=x[j];
x[j]=p;
}
// Ispis sortiranih brojeva
printf("\n Sortirani brojevi: %d, %d, %d ", x[0], x[1], x[2]);
// Ako brojevi nisu iz intervala, ispis odgovarajuce poruke
} else { printf("\n Svi brojevi nisu iz intervala 50 do 200!!!");
}
// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

6. Napisati program koji ce ispisati brojeve djeljive sa 5, 7


ili 11, a manje ili jednake od nekog ucitanog broja n sa
tastature. Brojeve treba ispisati od najveceg prema najmanjem.
Obavezno koristiti for petlju. Na primjer, ako je korisnik za n
unio broj 20 onda program treba ispisati:
20
15
14
11
10
7
5

RJEENJE:

#include <stdio.h>
int main()
{
// Definisanje varijabli
int n, i;
// Unos nekog prirodnog broja
printf("Unesite broj: ");
scanf("%d", &n);
/* For petlja postavlja brojac i na vrijednost unesenog broja, i provjerava
se da li je taj broj djeljiv sa 5, 7 ili 11, i ako jeste printa ga na ekran i
umanjuje brojac za jedan, ako broj nije djeljiv sa ovim brojevima, onda se
samo brojac umanji na kraju for petlje bez printanja broja na ekranu. Isti se
postupak ponavlja i za broj manji za jedan, kao i broj manji za dva... sve
tako do broja 1 (mogli smo staviti i 4 jer brojevi ispod 5 svakako nisu
djeljivi sa ovim brojevima! */
for(i=n;i>0;i--)
{
if ((i % 5 == 0)||(i % 7 == 0)||(i % 11 == 0)) printf("\n Broj: %d", i);
}
// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

7. Napisati program koji ce izracunavati sumu prema slijedecoj


formuli: suma=1-1/2+1/3-1/4+...+1/n
Broj n se unosi sa tastature(standardnog ulaza). Program treba
ispisati vrijednost sume na standardnom izlazu (monitoru)
koristeci slijedecu poruku:
Koristeci <n> clanova suma je <suma>.
(Na mjestu <n> se treba nalaziti konkretno uneseni broj n, a na
mjestu <suma> se treba nalaziti konkretno izracunata suma.)
Zadatak rijeite koristeci while petlju.

RJEENJE:

#include <stdio.h>
int main()
{
// Definisanje varijabli
float i=1,n,suma=0;
// Unos prirodnog broja
printf ("\n Unesi broj n:");
scanf("%f", &n);
/* Racunanje sume
While petlja vrti podprogam u okviru while petlje sve dok je brojac i koji
je na pocetku 1, manji od unesenog broja n. Ako je uneseni broj 1 ne ulazi se
u petlju i na izlazu se ispisuje Suma je:1. Ako je broj veci od 1 onda se
racuna suma prema matematickoj formuli. Grupisali smo formulu datu u zadatku
tako da trazimo sume po dva broja (odnosno razlike), i zatim te razlike
brojeva sabiramo, ali moramo paziti jer moramo brojac i uvecati za 2 jer smo
u formuli ukljucili odmah 2 broja.
Ovaj nacin ima i dobru i losu stranu. Dobra strana je jer nemoramo uvoditi
nikakvu pomocnu varijablu i citav kod za racunanje sume se sastoji od dva
izraza, a losa strana je kad unesemo neparne brojeve sto necemo dobiti tacnu
sumu i tako kad unesemo broj 3 program ce izracunati 1-1/2+1/3=0.5 sto nije
tacno, a to smo dobili jer program nemoze grupisati clanove po 2 jer ih imamo
tri i zadnji ostaje sam i ne racuna se. Ali ovaj mali nedostatak mozemo
zanemariti jer se u ovakvim zadacima obicno unose veliki brojevi da se sve
svodi na preciznost nalazenja broja 0.69 pa nam je svejedno da li je zadnji
clan uracunat ili ne, ali eto ako zelimo ipak 100% precizno uraditi, zadatak
moze se uraditi i bez grupisanja sa mijenjanjem predznaka sume, ali to uradite
sami :) */
while ((i<n)&&(n>1)) {
suma=suma+(1/i-1/(i+1));
i=i+2;
}
// Ispis sume
if (n>1) printf ("\n Suma je: %f", suma); else if (n=1) printf ("Suma je: 1");
// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

8. Napraviti program koji sa standardnog ulaza ucitava cijeli


broj m koji predstavlja redni broj mjeseca u godini, te ucitava i
broj g koji predstavlja godinu, a na monitoru ispisuje naziv tog
mjeseca i broj dana u tom mjesecu. Pretpostaviti da je prestupna
svaka cetvrta godina, iako je pravilo o racunanju prestupnih
godina neto slozenije. Na primjer, ako su ulazne vrijednosti
m=2, g=2000 program treba ispisati:

februar, 2000. g., broj dana:29

Ili ako su ulazne vrijednosti m=5, g=2005 program treba ispisati:


maj, 2005. g., broj dana: 31

RJEENJE:

#include <stdio.h>
main() {
/* Deklarisanje varijabli
Definisanje dvodimenzionalne matrice 12 sa 9 (12 mjeseci, a broj 9 je ustvari
broj slova od kojih se sastoje mjeseci, najvise ima semptembar (9 slova). */
int m,g,d,i;
char mj[12][9]={{"Januar"},{"Februar"},{"Mart"},{"April"},
{"Maj"},{"Juni"},{"Juli"},{"August"},{"Septembar"},
{"Oktobar"},{"Novembar"},{"Decembar"}};
// U programu se uvodi i naredba goto koja skace sa linije na liniju
// programa.
pocetak:
// Unos mjeseca i godine
printf ("\n Unesi mjesec i godinu (m,g):"); scanf ("%d,%d", &m,&g);
// Ako se unese 1,3,5,7,8,10 ili 12 mjesec onda ima d=31 dan
if ((m==1)||(m==3)||(m==5)||(m==7)||(m==8)||(m==10)||(m==12)) d=31; else
// Ako se ipak unese 4,6,9 ili 11 mjesec onda ima d=30 dana
if ((m==4)||(m==6)||(m==9)||(m==11)) d=30; else
/* Ili ako se ipak unese mjesec 2 onda se provjerava jos i prijestupna godina
(svaka godina djeljiva sa 4), i u zavisnosti da li je prijestupna ili ne d=29
odnosno d=29 dana. Ako broj nije od 1 do 12 vraca se na pocetak programa*/
if ((m==2)) if ((g%4==0)) d=29; else d=28; else goto pocetak;
// Ispis mjeseca koji se nalazi zapisan u mj[] (m-1 jer nam je januar pod
brojem 0)
printf("%s , %d. g., broj dana: %d", mj[m-1], g, d);
// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

9. Napisati program koji ucitava realnu matricu dimenzija 10x10


te pronalazi najmanji element na glavnoj dijagonali.

RJEENJE:

#include <stdio.h>
main (){
// Deklarisanje varijabli
float A[10][10], MIN;
int i,j;
/* Unos matrice (koristimo 2 for petlje pri unosu (i su redovi a j su kolone).
Brojevi se unose po redovima.
*/
printf("\n Unesi matricu A[10][10]: \n");
for (i=0;i<10;i++)
for (j=0;j<10;j++)
{
printf(" [%d,%d]:", i+1, j+1);
scanf("%f", &A[i][j]);
}
/* Trazenje najmanjeg elementa na dijagonali!
Postupak je sljedeci. Elementi na dijagonali su tipa [i,j] gdje su i,j
jednaki. Tako dijagonalni elementi matrice 3x3 su [1,1], [2,2], [3,3]. Posto
nam trebaju samo elementi kada su (i,j) jednaki koristimo jednu for petlju. Na
pocetku stavimo da je najmanji element prvi element na poziciji [1,1], u C-u
je pozicija (0,0) ustvari pozicija (1,1) u realnom svijetu. I ulazimo u for
petlju. Ispituju se redom brojevi kod kojih su brojaci i i j jednaki. Ako
je neki od brojeva koji se ispitaju manji od MIN onda se taj broj pridruzi
varijabli MIN. */
MIN=A[0][0];
for (i=1,j=1;i<10;i++,j++) if (A[i][j]<MIN) MIN=A[i][j];
// Ispis najmanjeg broja na dijagonali
printf("\nNajmanji element na glavnoj dijagonali je: %.f", MIN);
// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

10. Napiite funkciju faktor () koja izracunava n! pri cemu je


prototip funkcije faktor (): double faktor (int n)
Zatim, napisati glavni program koji ucitava neki prirodni broj
n,1<n<10; a zatim izracunava n! pozivom funkcije faktor() i
rezultat ispisuje na standardni izlaz.

RJEENJE:

#include <stdio.h>
main (){
// Deklarisanje varijabli
int N;
double F;
// Deklarisanje prototipa funkcije
double faktor (int n);
//Unos prirodnog broja
printf("\nUnesi prirodan broj N: ");
scanf("%d", &N);
/* Pozivanje funkcije faktor() i pridruzivanje vrijednosti koju funkcija
izracuna varijabli F */
F=faktor(N);
// Ispis faktorijele
printf("Faktorijela od %d je: %g", N, F);
// Kraj programa
getch();
return 0;
}

/* Funkcija koja racuna vrijednost faktorijele. Funkcija prima prirodan broj N


a vraca realan broj (double) kao rezultat. */
double faktor (int n) {
int i;
double fak=1;
/* Racunanje faktorijele se vrsi tako da se broj od kojeg trazimo faktorijelu
pomnozi sa svakim cijelim brojem manjim od sebe a koji je veci od 1. Na
pocetku je fak=1 jer ako bi bilo 0 dobili bi uzastopno mnozenje sa 0 i nebi
dobili ispravan rezultat */
for (i=n;i>1;i--) fak=fak*i;
// Vracanje izracunate faktorijele
return fak;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

11. Napisati program koji ucitava broj elemenata (n) nekog


cjelobrojnog polja (Polje) a zatim i elemente tog polja
(maksimalno 100). Program nakon toga pronalazi maksimalni element
unesenog polja i ispisuje ga na standardni izlaz.
Na primjer, ako su ulazni podaci: n=4, Polje=(2,5,20,4) program
ce ispisati vrijednost broja 20.

RJEENJE:

# include <stdio.h>
main (){
// Definisanje varijabli
int n, i, niz[100], max;
// Unos broja elemenata
printf("\nUnesi broj elemenata: ");
scanf("%d", &n);
// Unos niza od N elemenata (pomocu for petlje)
for (i=0;i<n;i++)
{
printf ("\nUnesi elemenat broj %d: ", i+1);
scanf("%d", &niz[i]);
}
// Postavljanje vrijednosti max na vrijednost prvog clana niza
max=niz[0];
/* For petlja vrti brojeve od 2 broja (prvi je ukljucen u liniju iznad) i
provjerava se da li je i-ti broj veci od max i ako jeste varijabli max se
pridruzuje vrijednost tog elementa*/
for (i=1;i<n;i++)
if (max<niz[i]) max=niz[i];
// Ispis najveceg elementa niza
printf("Najveci element niza je: %d", max);
// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

12. Napisati program koji ucitava 5 realnih elemenata dva polja


A i B a zatim izracunava elemente treceg polja C (koji takodjer
ima 5 elemenata) pri cemu se i-ti element polja C dobiva prema
slijedecoj formuli:
C[i]=2*A[i]+B[i], i=1,2,n
Na kraju program na standardni izlaz ispisuje elemente sva tri
polja: A, B i C.

RJEENJE:

# include <stdio.h>
main (){
// Definisanje varijabli
float A[5], B[5], C[5];
int i;
/* Unos elemenata prvog polja (pomocu for petlje, i+1 zbog realnosti, da nam
ne ispisuje se na ekranu "Unesi element 0") */
for (i=0;i<5;i++){
printf("\nUnesi %d element prvog polja: ",i+1);
scanf("%f", &A[i]);
}
// Unos elemenata drugog polja
for (i=0;i<5;i++){
printf("\nUnesi %d element drugog polja: ",i+1);
scanf("%f", &B[i]);
}
// Racunanje clanova matrice C po formuli C=2*A+B (pomocu jedne for petlje).
for (i=0;i<5;i++) C[i]=2*A[i]+B[i];
// Ispis elemenata polja A
printf("\nElementi prvog polja A: ");
for (i=0;i<5;i++) printf("%.f ", A[i]);
// Ispis elemenata polja B
printf("\nElementi drugog polja B: ");
for (i=0;i<5;i++) printf("%.f ", B[i]);
// Ispis elemenata polja C
printf("\nElementi treceg polja C: ");
for (i=0;i<5;i++) printf("%.f ", C[i]);
// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

13. Napisati program koji ucitava broj elemenata nekog polja


(maksimalno 100) a zatim i elemente tog polja. Program zatim
pronalazi najmanji element i na standardni izlaz ispisuje sve
elemente koji su manji od dvostruke vrijednosti pronadjenog
najmanjeg elementa.

RJEENJE:

# include <stdio.h>
main (){
// Definisanje varijabli
int n, i, niz[100], min;
// Unos broja elemenata
printf("\nUnesi broj elemenata: ");
scanf("%d", &n);
// Unos niza od N elemenata (pomocu for petlje)
for (i=0;i<n;i++){
printf ("\nUnesi elemenat broj %d: ", i+1);
scanf("%d", &niz[i]);
}
// Postavljanje vrijednosti min na vrijednost prvog clana niza
min=niz[0];
/* For petlja vrti brojeve od drugog broja (prvi je ukljucen u liniju iznad) i
provjerava se da li je i-ti broj manji od min i ako jeste varijabli min se
pridruzuje vrijednost tog elementa. */
for (i=1;i<n;i++)
if (min>niz[i]) min=niz[i];
/* For petlja vrti sve brojeve i za svaki broj se vrsi provjera da li je manji
od dvostruke vrijednosti nadjenog najmanjeg broja, i ako je taj broj zaista
manji od 2*min ispisuje se na ekran, a ako nije ide se na iduci broj. */
for (i=0;i<n;i++)
if (niz[i]<min*2) printf("\n %d", niz[i]);
// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

14. Napisati funkciju koja kao argument prima cijeli broj a


vraca broj koji se dobije tako da se iz argumenta izbace cifre
2,3,8 i 9.
Prototip funkcije je: int izbaci2389(int x)
Nakon toga, napiite glavni program koji ucitava neki cjeli broj,
poziva funkciju izbaci2389 i ispisuje rezultat na standardnom
izlazu.

RJEENJE:

# include <stdio.h>
main (){
// Definisanje prototipa funkcije
int izbaci2389(int x);
// Definisanje varijabli
int N, X;
// unos prirodnog broja
printf("\nUnesi prirodan broj: ");
scanf("%d", &N);
// Poziv funkcije i pridruzivanje rezultata varijabli X
X=izbaci2389(N);
// Ispis prepravljenog broja
printf("\nPrepravljeni broj: %d", X);
// Kraj programa
getch();
return 0;
}

// Funkcija za izbacivanje cifri 2,3,8,9 iz prirodnog broja


int izbaci2389(int x)
{
int t=1, y=0, ost;
/* While petlja se izvrsava dok je x>0. Uzima se ostatak dijeljenja broja sa
10 (npr. od broja 129, ostatak je 9), zatim se varijabli x odbije zadnja cifra
dijeljenjem sa 10 (do odbijanja dolazi jer radimo sa int brojevima pa nema
decimalnog zareza (npr 129/10=12). Zatim provjerimo dali je dobijeni ostatak
ost jednak 2,3,8 ili 9 i ako jest vracamo se na pocetak petlje i vrsimo isti
postupak za broj koji smo dobili odbijanjem zadnje cifre (i sve tako dok ne
odbijemo sve cifre, tj. dok ne dobijemo broj 0). Ako varijabla ost ipak je
razlicita od 2,4,8,9 onda se varijabli y doda vrijednost ost pomnozena sa t. U
programu varijabla t nam ustvari broji koja je decimala u pitanju. Kad je t=1
radimo sa jedinicama, kad je t=10 radimo sa deseticama... Tako npr. broj 1234
mozemo rastaviti kao 4*1+3*10+2*100+1*1000 gdje su nam brojevi 1,10,100,1000
ustvari nase t. */
while (x>0){
ost=x%10;
x=x/10;
if ((ost==2)||(ost==3)||(ost==8)||(ost==9)) continue;
y=y+ost*t;
t=t*10;
}
return y;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

15. Napisati funkciju koja kao argument uzima potronju u KWh


za veliku i malu tarifu te na standardnom izlazu ispisuje racun
za utroenu elektricnu energiju.
Pretpostaviti da je cijena za veliku tarifu po utroenom KWh 0.10
KM, a cijena za malu tarifu po utroenom KWh je 0.05 KWh.
Prototip funkcije je: void racun(float vt, float mt) gdje :
* vt oznacava potronju za veliku tarifu
* mt oznacava potronju za malu tarifu
Nakon toga, napiite glavni program koji ucitava potronju za
veliku tarifu i malu tarifu, te na standardnom izlazu ispisuje
racun za tu potronju.

RJEENJE:

# include <stdio.h>
main (){
// Definisanje prototipa funkcije
void racun(float vt, float mt);
// Definisanje varijabli
float vt, mt;
// Unos potrosnje po velikoj i maloj tarifi
printf("Unesi potrosnju za veliku tarifu: ");
scanf("%f", &vt);
printf("Unesi potrosnju za malu tarifu: ");
scanf("%f", &mt);
// Poziv void funkcije (funkcija ne vraca rezultat), sa argumentima vt i mt
racun(vt, mt);
// Kraj programa
getch();
return 0;
}
// Funkcija koja kreira racun za utrosak energije na osnovu argumenata vt i mt
void racun(float vt, float mt)
{
float cijena;
// Racunanje ukupne cijene na osnovu argumenata vt i mt i zadatih cijena
cijena=vt*0.10+mt*0.05;
// Ispis rezultata
printf("\n--------------RACUN ZA UTROSENU EL. ENERGIJU-------------------- ");
printf("\nPotrosnja VT: %f KWh", vt);
printf("\nPotrosnja MT: %f KWh", mt);
printf("\n**************************************************************** ");
printf("\nUkupno: %f KM", cijena);
printf("\n**************************************************************** ");
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

16. Napisati funkciju koja kao argument uzima tri cijela broja
a, p i c. Funkcija vraca cijeli broj koji se dobije tako da se u
broju a iza p-te cifre s desne strane umetne cifra c.
Ako je p veci od ukupnog broja cifri izlaz iz funkcije treba biti
jednak ulazu. Ako se broj c sastoji od vie cifri onda se umece
samo zadnja cifra iz tog broja.
Prototip funkcije je: int umetni(int a, int p, int c)
Nakon toga, napiite program koji ucitava neki pozitivan cijeli
broj a, poziciju umetanja cifre p i broj koji definira cifru koja
se umece c, te poziva funkciju umetni() i ispisuje na standardnom
izlazu rezultirajuci broj.

RJEENJE:

# include <stdio.h>
main (){
// Definisanje prototipa funkcije
int umetni(int a, int p, int c);
// Definisanje varijabli
int a, p, c, rez;
// Unos brojeva a,p,c
printf("Unesi brojeve a, p, c: ");
scanf("%d,%d,%d", &a,&p,&c);
// Poziv funkcije umetni() i pridruzivanje rezultata varijabli rez
rez=umetni(a,p,c);
// Ispis rezultata
printf("Rezultat: %d", rez);
// Kraj programa
getch();
return 0;
}

// Funkcija koja umece broj c na p-tu poziciju u broju a s desna


int umetni(int a, int p, int c)
{
int t=1, ost, x=0,br=0;
// Broju c pridruzuje se samo njegova zadnja cifra
c=c%10;
/* Racuna se ostatak dijeljenja sa 10 (ost), broju a se "otkida" zadnja cifra.
Ukoliko su brojevi p i br (brojac) identicni na to mjesto treba ubaciti broj
c. t nam broji decimale (vidi 14. zadatak).
Varijabli x se dodaje ostatak ost pomnozen sa t.
X je trazeni broj koji funkcija vraca u glavni program. */
while (a>0){
ost=a%10;
a=a/10;
if (p==br) {x=x+c*t; t=t*10; p=1000;}
x=x+ost*t;
t=t*10;
br++;
}
return x;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

17. Napraviti program koji ce na monitoru ispisati prvih N


cijelih brojeva i njihove kvadrate u formatu:
1 na kvadrat je 1
2 na kvadrat je 4
3 na kvadrat je 9
..........................
Broj N se unosi sa tastature. Koristiti for petlju.

RJEENJE:

#include <stdio.h>

int main() {
// Definisanje varijabli
int n,i;

/* Unos broja n sa tastature */

printf("\nUnesi broj n: ");


scanf("%d", &n);

/* Ispis prvih n brojeva i njihovih kvadrata, krenuvsi od broja 1, i znaci


krece od 1 i ide sve do broja za jedan manji od unesenog */

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


printf("\n %d na kvadrat je %d \n", i, i*i);

// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

18. Napraviti program koji izracunava rjeenja sistema


linearnih jednadzbi:

a x + a x = b
11 1 12 2 1
a x + a x = b
21 1 22 2 2
(nepoznate su x i x )
1 2

Koeficijenti a , a , b , a , a , b se unose sa tastature. Ako


11 12 1 21 22 2
sistem jednadzbi nema rjeenje program ispisuje poruku RJEENJE
ne postoji.

RJEENJE:
#include <stdio.h>
int main() {
// Definisanje varijabli
float a11,a21,a12,a22,x1,x2,b1,b2;
/* Unos podataka (U dijelu %fx1%fx2=%f izmedju %fx1 i %fx2 nema plusa, u
suprotnom bi morali pri unosu operacije - (minus) upisivati +-) */
printf("\n Unesite 1 linearnu jednacinu a11x1+a12x2=b1 (x1, x2 nepoznate): ");
scanf("%fx1%fx2=%f", &a11, &a12, &b1);
printf("\n Unesite 2 linearnu jednacinu a21x1+a22x2=b2 (x1, x2 nepoznate): ");
scanf("%fx1%fx2=%f", &a21, &a22, &b2);
/* Izracunavanje x2 metodom supstitucije */
x2=(b2 * a11 - a21 * b1) / (a22 * a11-a21 * a12);
/* Izracunavanje x1 metodom uvrstavanja x2 u prvu jednacinu */
x1=(b1 - a12 * x2) / a11;
/* Provjerava se da li je sistem odredjen */
/* Ukoliko je sistem odredjen ispisuju se rjesenja, u suprotnom se ispisuje
poruka: RJEENJE ne postoji */
if ((a11*a22)==(a12*a21)) printf("\nRJEENJE ne postoji!!!");
else printf("\nRezultat je: x1=%.2f i x2=%.2f", x1, x2);
// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

19. Napisati program koji ucitava 4 cijela broja, a kao izlaz


daje dva najveca broja. Na primjer, ako korisnik kao ulaz unese
slijedece cijele brojeve:
23 5 45 33
rezultat izvodjenja programa treba biti:
Najveci broj je 45.
Drugi broj po velicini je 33.

Napomena: Tekstualne poruke vaeg programa trebaju biti iste kao


gore navedene.

RJEENJE:

#include <stdio.h>

int main() {
// Definisanje varijabli
int i,j,p,niz[4];
/* Unos brojeva niza (4 broja), pomocu for petlje koja ide od 1 do 4. */
printf("\n Unesite 4 cijela broja!");
for(i=1;i<=4;i++){
printf("\n %d broj: ", i);
scanf("%d",&niz[i]);
}

/* Proces sortiranja
Koristena je metoda bubblesort (spomenuta u jednom od zadataka ranije), to je
metoda preljevanja, provjerava se da li je j-ti clan manji od j+1-vog i ako
jeste mijenjaju se mjesta.
Npr. Unesemo 1,2,3,4. Nakon prvog prolaska imamo 2,1,3,4. Nakon drugog
prolaska 2,3,1,4. Nakon treceg prolaska imamo 2,3,4,1. I onda prva for petlja
proces ponavlja jos jednom. Pa imamo 3,2,4,1 zatim i 3,4,2,1 pa onda ostaje
isto jer je 2 vec vece od 1. Ali niz nije sortiran! Prva for petlja jos jednom
pokrece postupak i imamo 4,3,2,1. Proci ce se onako bezveze jos 2 puta kroz
petlju j i zatim se izlazi iz petlje, i ispisuju se rezultati*/

for(i=1;i<=3;i++)
for(j=1;j<=3;j++)
if (niz[j+1]>niz[j]) {
p=niz[j];
niz[j]=niz[j+1];
niz[j+1]=p;
}

/*Ispis rjesenja zadatka*/

printf("\n Najveci broj je %d", niz[1]);


printf("\n Drugi broj po velicini je %d", niz[2]);

// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

20. Napisati program koji ce sa tastature ucitati prirodan


broj, te ispitati da li je broj prost. Ako se unese broj koji
nije prirodan (n<=0), program ispisuje poruku Broj nije
prirodan i zavrava. Ako je broj prost program ispisuje poruku
Uneseni broj je prost. Ako broj n nije prost program ispisuje
poruku Uneseni broj je slozen. Ako je unesen broj n=1 program
ispisuje poruku: Broj 1 nije niti prost niti slozen.

Napomena:Pod prostim brojem podrazumijevamo prirodan broj koji se


ne moze napisati kao umnozak dvaju prirodnih brojeva manjih od
tog broja. Broj 1 nije niti prost niti slozen.

RJEENJE:
#include <stdio.h>

main () {

// Definisanje varijabli
int i,br, ispit;
// Unos jednog prirodnog broja
printf ("\n Unesi prirodan broj: ");
scanf ("%d", &br);
// Provjera da li je broj prirodan, i ako nije ispisuje
// se poruka da broj nije prirodan
if (br<=0) printf("\n Broj nije prirodan"); else
// Provjera da li je uneseni broj, broj 1, i ako jeste,
// ispisuje se odgovarajuca poruka
if (br==1) printf("\n Broj 1 nije ni prost ni slozen"); else
/* Ako je unesen prirodan broj veci od 1, provjerava se da li je broj prost
ili slozen, varijabla "ispit" kao rezultat. Djelimo broj br sa svakim brojem
manjim od polovine unesenog broja. Na pocetku je ispit=0 sto nam govori da
je broj neparan. Ulazi se u petlju i pocinje dijeljenje sa brojevima 2,3,4...
Ako se broj br uspije podijeliti sa nekim od brojeva varijabla ispit ce
automatski poprimiti vrijednost 1. U zavisnosti da li je broj br uspio se
podijeliti sa nekim brojem bez ostatka, zavisiti ce i cinjenica da li je broj
prost ili slozen. */
{
ispit=0; i=2;
while (i<br/2) {
if ((br % i == 0)) ispit=1;
i++;
}
// Ispis odgovarajuce poruke na izlazu (PROST ILI SLOZEN)
if (ispit) printf("\n Broj je slozen"); else printf("\n Broj je prost");}
// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

21. Napraviti program koji izracunava n! (n faktorijela). Broj n


se unosi sa tastature i treba biti u rasponu [1,20]. Ako broj n
nije u datom rasponu, program ispisuje poruku Uneseni broj nije
u datom rasponu i zavrava se program.
Napomena: n! je definirano kao n! = n (n-1) (n-2) ....321.

RJEENJE:

#include <stdio.h>

main () {

// Definisanje varijabli
int i;
float n,f;

// Unos prirodnog broja


printf("\n Unesi broj N u rasponu od [1,20]: ");
scanf("%f", &n);

/* Racunanje faktorijele, ukoliko je broj u rasponu [1,20]. Faktorijela se


racuna tako sto se uneseni broj pomnozi sa svakim brojem manjim od sebe, i sve
se to pridruzuje varijabli f. */
f=1;
if ((n>0) && (n<21)) {
for (i=0;i<n;i++) f=f*(n-i);

// Ispis rezultata
printf("\n Faktorijela od broja %.0f je: %0.f", n, f);

// Ispis poruke ukoliko broj n nije u odgovarajucem rasponu


} else printf ("\n Uneseni broj nije u datom rasponu!");

// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

22. Napisati program koji ce izracunati sumu kvadrata prvih n


prirodnih brojeva. Broj n se unosi sa tastature i treba biti u
intervalu [2,100]. Ako broj n nije u tom intervalu program
ispisuje poruku Broj nije u zadanom intervalu i zavrava. Na
primjer, ako se unese n=3, program ce izracunati sumu:
suma=12+22+32=14.

RJEENJE:
#include <stdio.h>
main () {
// Definisanje varijabli
int i,broj,suma;
// Unosenje prirodnog broja sa tastature u rasponu od [2,100]
printf("\n ULAZ: Broj \"N\" u rasponu od [2,100]: ");
scanf("%d", &broj);

/* Ukoliko se unese broj u tacnom intervalu [1,100] racunanje sume kvadrata.


Imamo varijablu suma (na pocetku 0), koja se krece sabirati redom sa:
1*1 + 2*2 + 3*3 + 4*4 ... I sve do unesenog broja.*/
suma=0;
if ((broj>1) && (broj<101)) {
for (i=1;i<=broj;i++) suma=suma+(i*i);

// Ispis sume kvadrata prvih n brojeva


printf("\n Suma kvadrata prvih %d brojeva: %d", broj, suma);

// Ispis odgovarajuce poruke ukoliko broj n nije u odgovarajucem rasponu


} else printf ("\n Uneseni broj nije u datom rasponu!");

// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

23. Napraviti program koji ce na ekranu ispisivati broj PI


prema formuli PI=1-1/3+1/5-1/7...1/i, a vrijednost eps unosimo sa
tastature i mora biti u intervalu 0.1 do 0.0001. Suma se racuna
sve dok je 1/i vece od eps.

RJEENJE:

#include <stdio.h>

main () {

// Definisanje varijabli
float eps,pi,n;

// Unos broja koji oznacava preciznost


printf("\n Unesi broj eps u rasponu od [0.0001,0.1]: ");
scanf("\n %f", &eps);

/* Provjera da li je broj eps iz odredjenog intervala, i ako jeste racunanje


broja pi. Radi lakseg sastavljanja formule (jer imamo i + naizmjenicno)
grupisacemo clanove po 2. i onda sve svodimo na operaciju sabiranja razlika 2
broja. Na kraju se brojac uvecava za 4 jer smo odmah po dva clana u formuli
koristili */
n=1; pi=0;
if ((eps>0.0001) && (eps<0.1)) {
while (1/n>eps) {
pi=pi+(4/n-4/(n+2));
n=n+4;
}

// Ispis broja PI
printf ("PI je: %f", pi);

// Ispis poruke ukoliko broj eps nije u odgovarajucem rasponu


} else printf ("\n Broj nije u trazenom rasponu!");
// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

24. Napisati C program koji ce ucitati dimenzije (RA x KA)


realne matrice A (maksimalno 10 x 10) , dimenzije (RB x KB)
realne matrice B (maksimalno 10 x 10), te ucitati elemente tih
matrica. Program zatim treba izracunati matricu C koja je
proizvod matrica A i B. Na kraju program treba ispisati sve tri
matrice: A, B i C.
* RA, RB oznacavaju broj redova matrica A i B, respektivno;
* KA, KB oznacavaju broj kolona matrica A i B, respektivno.
Prilikom unosa dimenzija matrica program treba provjeriti da li
su unesene dimenzije u dozvoljenim granicama, tj. da li je
RA<=10, RB<=10, KA<=10, KB<=10, te isto tako program treba
provjeriti da li se matrice mogu mnoziti, tj. da li je ispunjeno:
KA=RB

RJEENJE:
#include <stdio.h>
main(){
float A[10][10], B[10][10], C[10][10];
int RA, RB, KA, KB, i, j, k;
// Unos dimenzija prve i druge matrice
printf("\nUnos dim. matrica A[RA,KA], B[RB,KB], u obliku \"RA,KA,RB,KB\": ");
scanf("%d,%d,%d,%d", &RA, &KA, &RB, &KB);

// Ispit uslova: da li su dimenzije u intervalu od 1 do 10.


if ((RA<=10)&&(RA>0)&&(RB<=10)&&(RB>0)&&(KA<=10)&&(KA>0)&&(KB<=10)&&(KB>0)) {
// Ispit uslova: da li je broj kolona prve matrice i broj redova druge isti.
if (KA==RB){

/* Unos elemenata prve matrice A (pomocu 2 for petlje, objasnjeno u jednom od


prethodnih zadataka. */
printf("\nUnesi elemente matrice A[%d,%d]: \n", RA, KA);
for (i=0;i<RA;i++)
for (j=0;j<KA;j++){
printf("Unesi element [%d,%d]: ", i+1, j+1);
scanf("%f", &A[i][j]); }

// Unos elemenata druge matrice B


printf("\nUnesi elemente matrice B[%d,%d]: \n", RB, KB);
for (i=0;i<RB;i++)
for (j=0;j<KB;j++){
printf("Unesi element [%d,%d]: ", i+1, j+1);
scanf("%f", &B[i][j]); }

/* Racunanje matrice C po formuli C=A*B. Dvije for petlje identicne for


petljama pri unosu matrice ili ispisu, koje setaju po redovima i kolonama
matrica A,B,C. Prema matematickom postupku proizvod matrica A i B je:
C[1][1]=A[0][0] * B[0][0] + A[0][1] * B[1][0] + ... + A[0][n] * B[n][0] sto je
primjenjeno na formulu koja se nalazi unutar for petlje sa argumentom k.
Argument k se krece od 1 do broja kolona prve matrice, i predstavlja broj
sabiraka u formuli iznad. C[i][j] = 0; je uvedeno jer vrijednost C[i][j] nije
definisana, a moramo je koristiti u formuli unutar for petlje po k. */

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

for (i=0;i<RA;i++)
for (j=0;j<KB;j++) {
C[i][j]=0;
for (k=0;k<KA;k++) C[i][j]=C[i][j]+A[i][k]*B[k][j]; }
// Ispis matrice A
printf("\nMatrica A[%d,%d]: \n", RA, KA);
for (i=0;i<RA;i++){
printf("\n");
for (j=0;j<KA;j++) printf("%4.f ", A[i][j]); }
// Ispis matrice B
printf("\nMatrica B[%d,%d]: \n", RB, KB);
for (i=0;i<RB;i++){
printf("\n");
for (j=0;j<KB;j++) printf("%4.f ", B[i][j]); }
// Ispis matrice C
printf("\nMatrica C[%d,%d]: \n", RA, KB);
for (i=0;i<RA;i++){
printf("\n");
for (j=0;j<KB;j++) printf("%4.f ", C[i][j]); }
// Ispis poruka ukoliko podaci nisu regularni
} else printf("\n Matrice se nemogu pomnoziti!");
} else printf("\n Matrice nisu u odgovarajucem intervalu!");
// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

25. Napisati C program koji sa standardnog ulaza ucitava


elemente realne matrice dimenzija 5 x 5, te izracunava sumu
elemenata svake kolone i sumu elemenata svakog reda.
Za unos i pohranjivanje matrice koristite dvodimenzionalno polje,
dok za pohranjivanje suma po redovima i kolonama trebate
koristiti jednodimenzionalno polje.
Program takodjer treba pronaci:
* u kojoj koloni je najmanja suma,
* u kojem redu je najveca suma,
te ispisati na standardni izlaz unesenu matricu, redne brojeve i
sume pronadjene kolone, odnosno, reda.

RJEENJE:

#include <stdio.h>
main(){

// Definisanje varijabli
float MATRIX[5][5], SUMA[5], sumaR, sumaK;
int i,j, Kolona, Red;

// Unos elemenata matrice


printf("\nUnesi elemente matrice MATRIX[5,5]: \n");
for (i=0;i<5;i++)
for (j=0;j<5;j++){
printf("[%d,%d]: ", i+1, j+1);
scanf("%f", &MATRIX[i][j]); }

/* Postavljanje vrijednosti elemenata niza SUMA na 0 (jer vrijednosti niza


SUMA[] nisu definisane. */
for (i=0;i<5;i++) SUMA[i]=0;

/* Racunanje suma po redovima. Sabiramo sve brojeve prvog reda, znaci i se


ne mijenja, a j se uvecava za 1 sve do 5. I kada se sabere tih 5 brojeva, to
je suma prvog reda i zapisuje se u SUMA[0], zatim se isto ponavlja za ostale
redove, tako sto se samo i uvecava za 1 i prelazi time na iduci red. */
for (i=0;i<5;i++)
for (j=0;j<5;j++)
SUMA[i]=SUMA[i]+MATRIX[i][j];

/* Nalazenje najvece od izracunatih suma. Postavlja se da je prva suma


najveca, i zatim se provjerava da li od preostalih ima neka koja je veca, i
ako je veca, onda se ta suma postavlja da je najveca. Vrijednost i+1 nam
predstavlja broj reda u kojem je ta suma (na pocetku stavili smo da je i=1
jer ispred stoji da je sumaR=SUMA[0]. */
sumaR=SUMA[0]; Red=1;
for (i=1;i<5;i++) if (sumaR<SUMA[i]) {sumaR=SUMA[i]; Red=i+1;}

// Postavljanje vrijednosti elemenata niza SUMA na 0


for (i=0;i<5;i++) SUMA[i]=0;

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

/* Racunanje suma po kolonama... ista procedura, samo smo zamijenili mjesta


brojaca i, j unutar MATRIX[i][j]. */
for (i=0;i<5;i++)
for (j=0;j<5;j++)
SUMA[i]=SUMA[i]+MATRIX[j][i];

// Pronalazenje najmanje od izracunatih suma


sumaK=SUMA[0]; Kolona=1;
for (i=1;i<5;i++) if (sumaK>SUMA[i]) {sumaK=SUMA[i]; Kolona=i+1;}

// Ispis matrice MATRIX


printf("\nMatrica MATRIX[5,5]: \n");
for (i=0;i<5;i++){
printf("\n");
for (j=0;j<5;j++) printf("%.f ", MATRIX[i][j]); }

// Ispis rjesenja
printf("\nU %d koloni je najmanja suma koja iznosi %.f", Kolona, sumaK);
printf("\nU %d redu je najveca suma koja iznosi %.f", Red, sumaR);

// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

26. Program ucitava jednu rijec a i znak c koji se treba


prebrojati u toj rijeci. Nakon toga program poziva funkcije
duzina() i izbroji () i samogl(), te ispisuje duzinu unesene
rijeci a i broj pojavljivanja znaka c u toj rijeci, kao i broj
samoglasnika u rijeci.

RJEENJE:

#include <stdio.h>
// Funkcije duzina, izbroji i samogl
// Funkcija duzina prima pokazivac na prvo slovo nekog stringa, a zatim u
while petlji provjerava se koliko znakova ima rijec, kada se dodje do nultog
znaka, izlazi se iz petlje, rezultet je varijabla d koja se vraca iz
funkcije.
int duzina(char *string)
{
int d=0;
while (*string++!='\0') d++;
return d;
}

/* Slicno prvoj funkciji, samo funkcija pored pokazivaca na prvi znak stringa
prima i znak koji se broji. I umjesto da broji se broj clanova, umjesto d++
ide uslov (ako je slovo na koje pokazuje pokazivac nase slovo), b se uveca
za 1. Kada dodje while petlja do nultog znaka, izlazi se iz petlje a
varijabla b se vraca kao rezultat.
NAPOMENA: U gornjoj funkciji stoji u uslovu *string++ sto prebaca pokazivac na
iduci clan nakon sto while petlja napravi jedan krug, dok u drugoj funkciji
stoji u uslovu samo *string ali je poslije if petlje uvecan pokazivac za 1,
sto nam daje opet isti efekat. */
int izbroji(char *string, char c)
{
int b=0;
while (*string!='\0')
{
if (*string==c) b++;
string++;
}
return b;
}

/* Identicno funkciji izbroji() samo umjesto provjere *string==c ide uslov


da li je *string neki od samoglasnika, a ne znak koji unosimo. Funkcija
prima samo pokazivac bez znaka. */
int samogl (char *string)
{
int b=0;
while(*string!='\0')
{
if (*string=='a'||*string=='A'||*string=='E'||*string=='e'||*string=='I'||
*string=='i'||*string=='O'||*string=='o'||*string=='U'||*string=='u') b++;
string++;
}
return b;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

int main()
{
// Definisanje varijabli
char a[80],c;
// Unos rijeci bez razmaka i jednog slova koje ce se prebrojavati
printf("\nUnesite jednu rijec do 20 znakova (bez razmaka):");
scanf("%s",a);
printf("\nKoji znak treba prebrojati:");
scanf("\n%c",&c);
// Ispis rjesenja
printf("\nUnesena rijec sadrzi %d znakova!",duzina(a));
printf("\nBroj znakova %c je: %d",c,izbroji(a,c));
printf("\nBroj samoglasnika je: %d", samogl(a));
// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

27. Napisati program koji u realno polje temp ucitava 10


realnih vrijednosti koje predstavljaju temperature u 10
razlicitih dnevnih termina. Program zatim poziva funkcije
maxtemp() i prtemp() koje izracunavaju maksimalnu dnevnu
temperaturu i prosjecnu dnevnu temperaturu i ispisuje na
standardnom izlazu te vrijednosti.

RJEENJE:
#include <stdio.h>
main ()
{
// Definisanje varijabli
float temp[10], *p;
int i;
// Definisanje prototipa funkcija
float maxtemp(float *p);
float prtemp(float *p);
// Unos 10 temperatura u niz temp[];
for (i=0;i<10;i++)
{
printf("\nUnesi temperaturu br.%d: ",i+1);
scanf("%f", &temp[i]);
}
// Postavljanje pokazivaca p na prvi clan niza temp[];
p=temp;
// Isipis rezultata uz poziv funkcija
printf("\nMaksimalna temperatura je: %.1f", maxtemp(p));
printf("\nProsjecna temperatura je: %.1f", prtemp(p));
// Kraj programa
getch();
return 0;
}
/* Funkcija maxtemp() prima pokazivac na realan niz i pomocu for petlje (vidi
11. zadatak) pronalazi se najveci broj (temperatura i vraca se iz funkcije */
float maxtemp(float *p)
{
float max=*p;
int i;
for (i=0;i<10;i++) { if (max<*p) max=*p; p++; }
return max;
}
/* Funkcija prtemp() prima pokazivac na realan niz i pomocu for petlje se
saberu svi clanovi niza i na kraju (poslije for petlje) se podijeli sve sa 10
(broj temperatura), tj. vraca se vrijednost (pr/10) kao rezultat */

float prtemp(float *p)


{
float pr=0;
int i;
for (i=0;i<10;i++) { pr=pr+*p; p++; }
return (pr/10);
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

28. Modificirati prethodni program (27) tako da program ucitava


cijeli broj n a zatim se sa tastature unosi n vrijednosti za
temperature u polje temp. Pretpostaviti da je n<=10. U skladu s
tim potrebno je modificirati funkcije maxtemp() i prtemp() tako
da imaju slijedece prototipove:

float maxtemp(int n, float *p);


float prtemp(int n, float *p);

RJEENJE:

# include <stdio.h>
main ()
{
// Definisanje varijabli
float temp[10], *p;
int i, n;
// Definisanje prototipa funkcija
float maxtemp(int n, float *p);
float prtemp(int n, float *p);
// Unos broja n
printf("\nUnesi broj temperatura: ");
scanf("%d", &n);
// Unos n temperatura u niz temp[];
for (i=0;i<n;i++)
{
printf("\nUnesi temperaturu br.%d: ",i+1);
scanf("%f", &temp[i]);
}
// Postavljanje pokazivaca p na prvi clan niza temp[];
p=temp;
// Isipis rezultata uz poziv funkcija
printf("\nMaksimalna temperatura je: %.1f", maxtemp(n, p));
printf("\nProsjecna temperatura je: %.1f", prtemp(n, p));
// Kraj programa
getch();
return 0; }

/* Funkcija prima pokazivac na realan niz, i broj n i pomocu for petlje (vidi
11. zadatak) pronalazi se najveci broj (temperatura i vraca se iz funkcije */
float maxtemp(int n, float *p) {
float max=*p;
int i;
for (i=0;i<n;i++) { if (max<*p) max=*p; p++; }
return max; }
/* Funkcija prima pokazivac na realan niz i broj n i pomocu for petlje se
saberu svi clanovi niza i na kraju (poslije for petlje) se podijeli sve sa
brojem n (broj temperatura), tj. vraca se vrijednost (pr/n) kao rezultat */
float prtemp(int n, float *p){
float pr=0;
int i;
for (i=0;i<n;i++) { pr=pr+*p; p++; }
return (pr/n); }

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

29. Napisati funkciju s imenom adresa() koja kao argument uzima


dva stringa koji predstavljaju ime i prezime a kao rezultat vraca
se novi string koji se dobije tako da se string koji predstavlja
prezime promijeni u string koji predstavlja e-mail adresu
slijedeceg oblika: [prezime].[ime]@etf.unsa.ba
Prototip funkcije je: char *adresa(char *ime, char *prezime)
Na primjer, ako su argumenti ime=Marko, prezime=Markovic
funkcija adresa() vraca pokazivac na rezultirajuci string prezime
koji je promijenjen u novi string oblika:
Markovic.Marko@etf.unsa.ba.

Nakon toga, napisati glavni program koji ucitava ime i prezime


neke osobe i na standardnom izlazu ispisuje toj osobi pridruzenu
e-mail adresu koja se dobije pozivom funkcije adresa().

RJEENJE:
#include <stdio.h>
// Funkcija adresa()
char *adresa(char *ime, char *prezime)
{
// Definisanje varijabli potrebnih za rad u funkciji
char *p, POMOC[]="@etf.unsa.ba", *POM;
/* Pointer p pokazuje na pocetak prezimena, a POM pokazuje na pomocni niz
POMOC u kojem se nalazi string @etf.unsa.ba. */
p=prezime; POM=POMOC;

// Generisanje email adrese


// Ova while petlja pokazivac postavi iza zadnjeg znaka, tj. Na nulti znak.
while (*p!='\0') p++;
// Umjesto nultog znaka upise se . i predje se na iduci znak
*p='.'; p++;
// Poslije tacke se ubacaju karakteri iz niza na koji pokazuje pokazivac ime
while (*ime!='\0') { *p=*ime; ime++; p++; }
// Poslije imena se doda string na koji pokazuje pokazivac POM
while (*POM!='\0') { *p=*POM; POM++; p++; }
// Vracanje pokazivaca iz funkcije
return p;
}

// Glavni program
int main(){
// Definisanje varijabli
char *ime, *prezime, *c;
char U1[100], U2[100];
// Unos podataka ime i prezime
printf("\nUnesi ime:");
scanf("%s", &U1);
printf("\nUnesi prezime:");
scanf("%s", &U2);
// Postavljanje pokazivaca c na pocetak prezimena
c=U2;
// Postavljanje pokazivaca ime i prezime na stringove U1 i U2

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

ime=U1;
prezime=U2;
// Poziv funkcije adresa() i slanje pokazivaca ime i prezime u funkciju
prezime=adresa(ime, prezime);
// Ispis Email adrese
printf("\nGenerirana korisnikova Email adresa: %s", c);
// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

30. Napisati funkciju koja kao argument uzima znakovno polje


jmbg (jedinstveni maticni broj gradjanina) a kao izlaz vraca
strukturnu varijablu koja predstavlja datum rodjenja doticne
osobe. Prototip funkcije je: struct datum fdatum(char *jmbg) gdje
struct datum predstavlja strukturu definiranu kao:

struct datum
{
int dan;
int mjesec;
int godina;
};

Na primjer, ako je strukturna varijala drodj definirana kao:


struct datum drodj; te ako je ulaz u funkciju
jmbg=2405978234567 poziv funkcije drodj=fdatum(jmbg); treba
vratiti strukturnu varijablu koja predstavlja datum 24.05.1978.,
tj. funkcija vraca slijedece podatke strukturne varijable tipa
datum:

drodj.dan=24;
drodj.mjesec=5;
drodj.godina=1978;

Nakon toga napiite glavni program koji sa standardnog ulaza


ucitava jmbg kao znakovno polje a nakon poziva funkcije fdatum()
ispisuje datum rodjeja osobe sa doticnim jedinstvenim maticnim
brojem.

RJEENJE:
# include <stdio.h>

// Definisanje strukture datum


struct datum {
int dan;
int mjesec;
int godina;
};

/* Funkcija koja vraca datum kreiran od znakovnog polja u koje je upisan


maticni broj */

struct datum fdatum(char *jmbg){

// Definisanje varijable drodj kao strukturne varijable od datum


struct datum drodj;

// Definisanje pokazivaca koji pokazuje na strukturnu varijablu


struct datum *pd;
int i;

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

// Racunanje varijabli strukturne varijable


// Pretpostavka je da je korisnik ciji maticni broj unesete rodjen 1xxx godine
drodj.dan=0; drodj.mjesec=0; drodj.godina=1000;
// Racunanje jedinice dana
for (i=0;i<10;i++) if (*jmbg==49+i) drodj.dan=10*(1+i);
// Racunanje desetice dana i sabiranje sa jedinicom
for (i=0;i<10;i++) if (*(jmbg+1)==49+i) drodj.dan+=(1+i);
// Racunanje jedinice mjeseca
for (i=0;i<10;i++) if (*(jmbg+2)==49+i) drodj.mjesec=10*(1+i);
// Racunanje desetice mjeseca i sabiranje sa jedinicom
for (i=0;i<10;i++) if (*(jmbg+3)==49+i) drodj.mjesec+=(1+i);
// Racunanje stotice godine i sabiranje sa 1000
for (i=0;i<10;i++) if (*(jmbg+4)==49+i) drodj.godina+=100*(1+i);
// Racunanje desetice godine i sabiranje sa stoticom
for (i=0;i<10;i++) if (*(jmbg+5)==49+i) drodj.godina+=10*(1+i);
// Racunanje jedinice godine i sabiranje sa deseticom
for (i=0;i<10;i++) if (*(jmbg+6)==49+i) drodj.godina+=(1+i);
// Postavljanje pokazivaca na prvi znak strukturne varijable drodj
pd=&drodj;
// Funkcija vraca objekat koji se nalazi na adresi na koju pokazuje pd
return *pd;
}

// Glavni dio programa


main () {
struct datum drodj;
char jmbg[40], *p;

// Pretpostavka je da je uneseni maticni broj odgovarajuci


printf("Unesi maticni broj: ");
scanf("%s", &jmbg);

// Poziv funkcije fdatum i pridruzivanje rezultata strukturnoj varijabli drodj


drodj=fdatum(jmbg);

// Ispis rjesenja
printf("\nDatum rodjenja: %d.%d.%d", drodj.dan, drodj.mjesec, drodj.godina);

// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

31. Napisati program koji broji rijeci koje imaju n znakova u


tekstualnoj datoteci cije ime se unosi sa tastature. Na primjer,
ako u direktoriju(folderu) T11 na disku C: postoji datoteka
pismo.txt sa slijedecim sadrzajem:
Lijep pozdrav!
Sretnu i uspjesnu Novu godinu zeli Vam kompanija BHKOM.
Isto tako se nadamo da ce se dosadasnja uspjesna saradnja
nastaviti i u novoj 2006. godini.
Direktor: IVIC IVICA
program treba nakon unosa imena sa tastature i broja n:
Unesite broj znakova: 5
Unesite ime datoteke: C:\T11\pismo.txt
dati slijedeci izlaz:
Datoteka pismo.txt sadrzi 4 rijeci sa 5 znakova.
Napomene:
Rijeci sa pet znakova za gore navedenu datoteku su:
{Lijep, BHKOM, novoj, IVICA}.
Prilikom brojanja znakova ne uzimaju se u obzir znakovi
interpunkcije: tacka (.), zarez (,), usklicnik (!) i sl.
Prilikom rjeavanja zadatka obavezno napravite testnu datoteku
pismo.txt i pohranite je u direktorij T11, te tu datoteku
koristite za testiranje vaeg rjeenja.

RJEENJE:

# include <stdio.h>
main() {
// Definisanje varijabli
FILE *datoteka;
char dat[60], znak;
int znakovi, br=0, rez=0;
// Unos putanje do datoteke
printf("Unesi putanju do datoteke: ");
scanf("%s", &dat);
// Ispituje se da li datoteka postoji, ako postoji, ide se dalje u program u
// suprotnom se ispisuje error poruka i izlazi iz programa
if ( (datoteka = fopen (dat, "r")) == NULL) {
printf("Greska kod otvaranja datoteke %s !\n", dat);
getch();
exit(1); }
// Unos broja znakova
printf("Unesi broj znakova: ");
scanf("%d", &znakovi);

/* While petlja vrti se i uzima se znak po znak iz datoteke sve dok ne dodje
se do kraja datoteke i kada stignemo na kraj izlazi se iz programa. Ukoliko je
uneseni karakter razlicit od znakova ? ! . \n , \t i blanko znaka onda se
varijabla br uveca za jedan, u suprotnom se provjeri da li je broj br jednak
broju znakova koji smo unjeli, i ako jeste varijabla rez se uveca za jedan, i
onda se br postavi na 0. Kada stignemo do kraja datoteke izlazi se iz
petlje.*/

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

while((znak=fgetc(datoteka))!=EOF){
if ((znak=='?')||(znak=='!')||(znak==' ')
||(znak=='.')||(znak=='\n')||(znak==',')||(znak=='\t')) {
if (br==znakovi) rez++; br=0;} else br++;
}
/* Ukoliko zadnja rijec se sastoji od trazenog broja znakova, ona nece biti
uracunata jer smo izasli iz petlje, pa je potrebno dodati ovaj uslov iza
petlje da bi smo imali 100% tacan program*/
if (br==znakovi) rez++;
//Zatvaranje datoteke
fclose(datoteka);
// Izlaz iz programa
printf("Datoteka %s sadrzi %d rijeci sa %d znakova.", dat, rez, znakovi);
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

32. Napravite tekstualnu datoteku ORPodaci.txt (pomocu


programa Notepad ili slicnog) slijedeceg formata:
[prezime ] [ime] [brbod1] [brbod2]
gdje :
- kolona [prezime] zauzima 15 mjesta;
- kolona [ime] zauzima 10 mjesta;
- kolona [brbod1] zauzima 4 mjesta i predstavlja broj bodova na
prvom parcijalnom ispitu
- kolona [brbod2] zauzima 4 mjesta i predstavlja broj bodova na
drugom parcijalnom ispitu
- U datoteku ORPodaci.txt unesite podatke za 15 studenata.
- Spasite datoteku ORPodaci.txt u direktorij C:\T12.
- VAZNO: Prilikom kreiranja datoteke ORPodaci.txt budite
precizni u zauzimanju mjesta za pojedine kolone.

Zatim, napisati program koji ucitava sadrzaj tekstualne datoteke


ORPodaci.txt i na temelju te datoteke kreira novu datoteku pod
imenom Polozili.txt u kojoj se treba nalaziti sortiran (od
veceg prema manjem) spisak onih studenata koji su polozili oba
parcijalna ispita (to su oni studenti koji imaju na oba
parcijalna 10 ili vie bodova).
Datoteka Polozili.txt je slijedeceg formata:
[prezime ] [ime] [ukupno]
gdje :
- kolona [prezime] zauzima 15 mjesta;
- kolona [ime] zauzima 10 mjesta;
- kolona [ukupno] zauzima 4 mjesta i predstavlja ukupan broj
bodova sa oba parcijalna ispita.

RJEENJE:
#include <stdio.h>
#include <stdlib.h>

/* Definisanje strukture forma koja se sastoji iz varijabli prezime i ime tipa


char i prvi i drugi tipa integer */
struct forma {
char prezime[15];
char ime[10];
int prvi;
int drugi;
};

main(){

/* Definisanje varijabli:
Neo - pokazivac na fajl koji se cita
Trinity - pokazivac na fajl u koji se pise

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

podaci[15] - strukturni niz podaci u koji ce se upisati svi podaci koji se


ucitaju iz fajla, maksimalno 15...
Love - pomocna strukturna varijabla
i,j,k - potrebni projaci za sortiranje, i jos ponesta :) */
FILE *Neo, *Trinity;
struct forma podaci[15];
struct forma Love;
int i=0, j=0, k=0;

/* Otvaranje datoteke ORPodaci.txt i pridruzivanje pokazivacu Neo, ako ne


postoji datoteka izlazi se iz programa */
if ((Neo=fopen("C:\\T12\\ORPodaci.txt","r"))==NULL)
{
printf("Greska pri otvaranju datoteke");
exit(1);
}

/* Datoteka polozili.txt se kreira i pridruzuje pokazivacu Trinity */


Trinity = fopen ("c:\\T12\\Polozili.txt", "w");

/* Citanje podataka iz datoteke i upisivanje istih u strukturu podaci.


Varijabla i se vraca kao broj koji oznacava broj studenata koji su polozili
obe parcijale. podaci[i].prvi se automatski sabira sa podaci[i].drugi i ukupna
vrijednost postaje ustvari podaci[i].prvi!*/
while(fscanf(Neo,"%15s%10s%4d%4d",&podaci[i].prezime,&podaci[i].ime,&podaci[i]
.prvi,&podaci[i].drugi) != EOF )
{
if ((podaci[i].prvi>=10)&&(podaci[i].drugi>=10))
podaci[i].prvi+=podaci[i].drugi; else i--;
i++;
}

// Proces sortiranja... objasnjen u jednom od zadataka ranije...


for(j=0;j<i-1;j++)
for(k=j+1;k<i;k++)
if (podaci[k].prvi>podaci[j].prvi)
{
Love=podaci[j];
podaci[j]=podaci[k];
podaci[k]=Love;
}

// Upis podataka u datoteku na koju pokazuje pokazivac Trinity (Polozili.txt)


for (j=0; j<i; j++)
fprintf(Trinity,"%-15s%-10s%-4d\n",
podaci[j].prezime,podaci[j].ime,podaci[j].prvi);

// Zatvaranje datoteka...
fclose(Neo);
fclose(Trinity);

// Kraj programa...
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

33. Napisati funkciju okreni() koja kao argument uzima neki


string i okrece sadrzaj tog stringa naopako. Prototip funkcije
okreni() treba biti:
void okreni(char* p)
Zatim napravite glavni program koji sa standardnog ulaza ucitava
neki string, te ga ispisuje naopako.
Primjer:
Unesite string: Sarajevo
Naopako: ovejaraS

RJEENJE:
#include <stdio.h>
// Funkcija okreni
void okreni(char *p){
// Definisanje pomocnih varijabli
char pom;
int i=0, j=0, br=0;
// Brojanje slova rijeci, pointer odlazi na kraj rijeci.
while (*p!='\0') {br++; p++;}
/* Pointer je otisao na kraj rijeci, a nama treba u nastavku da je na
pocetku, pa cemo ga vratiti na pocetak tako sto ga pomaknemo za isti broj
mjesta nazad, za koji smo ga while petljom pomjerili naprijed! */
p=p-br;
// Glavni dio programa, ALGORITAM.
/* Recimo da smo unjeli rijec LOVE. Rijec koju trebamo dobiti kao rezultat je
EVOL. Znaci potrebno je zamjeniti zadnje slovo sa prvim, i drugo sa
predzadnjim. Brojac i nam predstavlja znak do kojeg smo dosli sprijeda, a
brojac j straga. Na pocetku ce biti i=0, j=3 (jer je br=3, nemojte se
zbuniti sto je 3 a ne 4, tu su ipak cetiri clana 0,1,2,3). Znaci nakon sto se
for petlja jednom izvrsi i se uveca za 1 i postaje 1, a j se umanji za 1 i
postane 2. Znaci u prvom slucaju pomocu pomocne varijable pom mijenjamo
znakove na 0 i 3 poziciji, drugi put ce se zamjeniti znakovi na 1 i 2
poziciji. I dobili smo trazenu rijec. Mozda zbunjuje uslov i<br/2; ali je
neophodan, broj permutacija je jednak polovini duzine rijeci, nacrtajte sebi
neki primjer i zakljucite to :). Ukoliko se uzme rijec sa neparnim brojem
slova onda se srednji clan ne pomjera nigdje, ostaje, sto je i logicno. Dok se
clanovi oko njega izmjenjaju simetricno. Funkcija nevraca nikakvu vrijednost,
ali promjene ostaju zapamcene zbog pristupa vrijednostima preko pointera! */
for (i=0,j=br-1;i<br/2;i++,j--){
pom=*(p+i);
*(p+i)=*(p+j);
*(p+j)=pom;
}
}
// Glavni program
main(){
// Definisanje varijabli i pointera
char NIZ[100];
char *t;
// Unos neke rijeci i zapisivanje iste u NIZ
printf("Unesi neku rijec: ");
scanf("%s", &NIZ);

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

// Postavljanje pokazivaca t na NIZ


t=NIZ;
// Pozivanje funkcije i slanje pokazivaca t u funkciju
okreni(t);
/* Ispis stringa NIZ preuredjenog funkcijom (printa se t, a t nam pokazuje
na NIZ). */
printf("%s", t);
// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

34. Napisati funkciju ubaci5() koja kao argument uzima neki


prirodni broj n i dva broja a i b, a zatim vraca se broj koji bi
nastao zamjenom cifri na mjestu a i b cifrom 5 (gledano s desne
strane). Funkcija ne treba nita ispisivati. Funkcija ubaci5()
treba imati prototip:
int ubaci5(int n,int a,int b);
Pretpostaviti da su a i b valjano unesene vrijednosti koje imaju
smisla. Primjeri ulaznih argumenata i vracenih vrijednosti:
Primjer1: za ulazne argumente n=123321, a=2, b=3 funkcija vraca
broj 123551.
Primjer 2: za ulazne argumente n=23455, a=3, b=5 funkcija vraca
broj 53555.

RJEENJE:

#include <stdio.h>
// Funkcija ubaci5();
int ubaci5(int n,int a,int b) {
// Definisanje varijabli
int c=0,t=1,o,i;
/* Brojac i krece od 1(prvi znak straga) i ide dok broj n koji smo primili
u funkciju ne postane 0. Svaki put kada for petlja se izvrsava ponovo, uzima
se ostatak dijeljenja sa 10, odnosno uzima se zadnja cifra broja n, i
pridruzuje varijabli o. Zatim se broj n podijeli sa 10, cime mu se odbije
zadnja cifra. Suma c se uvecava za t*o gdje t se mijenja kao
1,10,100,1000. Kada i bude jednako a ili b onda se umjesto t*o doda
t*5 i time se na a-to/b-to mjesto doda broj 5 umjesto broja koji je bio na
toj poziciji. Naredba continue; ce vratiti na pocetak for petlje kako se
nebi izvrsile i linije ispod, jer bi time dobili ubacivanje brojeva, a ne
zamjenu!!! Savjet: Probajte napisati recimo petocifren broj, i skontajte malo
na papiru prvo kako biste te zamjene uradili, skontajte ulogu varijabli o i
t!!! */
for (i=1;n>0;i++){
o=n%10;
n=n/10;
if (i==a) {c=c+t*5; t=t*10; continue;}
if (i==b) {c=c+t*5; t=t*10; continue;}
c=c+t*o;
t=t*10;}
return c;}
main(){
// Definisanje varijabli a,b,n
int n, a, b;
// Unos brojeva a,b,n
printf("Unesi prirodan bron n:"); scanf("%d", &n);
printf("Unesi brojeve a,b:"); scanf("%d,%d", &a, &b);
/* Poziv funkcije, slanje n,a,b u funkciju, a rezultat se
pridruzuje varijabli n, koja se printa u iducoj liniji. */
n=ubaci5(n,a,b);
printf("%d", n);
// Kraj programa.
getch();
return 0; }

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

35. Napisati program koji ucitava podatke iz ulazne formatirane


tekstualne datoteke gradovi.txt i kreira izlaznu datoteku
prosjeci.txt koja sadrzi spisak gradova s prosjecnom
temperaturom za prva tri mjeseca. Datoteka gradovi.txt je
sljedeceg formata:
[grad] [JAN] [FEB] [MAR]
gdje je:
[grad] kolona u kojoj su zapisani nazivi gradova i koja zauzima
15 mjesta;
[JAN], [FEB], [MAR] kolona u kojoj su zapisane cjelobrojne
prosjecne temperature za mjesec januar, februar i mart,
respektivno. Ove kolone zauzimaju po 10 mjesta.
Datoteka prosjeci.txt je slijedeceg formata:
[grad] [PRTEMP]
gdje je:
[grad] kolona u kojoj su zapisani nazivi gradova i koja zauzima
15 mjesta;
[PRTEMP] kolona u kojoj su zapisane prosjecne temperature
koristeci dva decimalna mjesta i maksimalno dva mjesta prije
decimalne tacke.
Primjer sadrzaja datoteke gradovi.txt:
TRAVNIK 0 1 2
ZENICA 2 3 4
TUZLA 2 5 5
SARAJEVO 0 3 1
Primjer sadrzaja datoteke prosjeci.txt:
TRAVNIK 1.00
ZENICA 3.00
TUZLA 4.00
SARAJEVO 1.33

RJEENJE:

#include <stdio.h>
main(){
// Definisanje varijabli
FILE *Neo, *Trinity;
char grad[15];
float JAN, FEB, MAR, PRO;
/* Provjera da li postoji datoteka gradovi.txt i ako ne postoji ispis greske,
u suprotnom se nastavlja program */
if ((Neo=fopen("C:\\gradovi.txt","r"))==NULL)
{
printf("Greska pri otvaranju datoteke");
return 0;
}
// Otvaranje datoteke prosjeci.txt
Trinity=fopen("C:\\prosjeci.txt","w");
/* Citanje podataka iz datoteke gradovi.txt izracunavanje prosjecne
temperature PRO i printanje u datoteku prosjeci.txt */

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

while(fscanf(Neo,"%15s%10f%10f%10f", &grad, &JAN, &FEB, &MAR) != EOF ) {


PRO=(JAN+FEB+MAR)/3;
fprintf(Trinity,"%-15s%2.2f\n", grad, PRO);
}
// Kraj programa
close(Neo);
close(Trinity);
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

36. Napisati funkciju izbacip() koja kao argument uzima neki


prirodni broj n, a zatim vraca broj koji bi nastao izbacivanjem
parnih cifri iz tog broja. Funkcija ne treba nita ispisivati.
Funkcija izbacip() treba imati prototip:
int izbacip(int n);
Na primjer, za argument 123420 funkcija treba vratiti broj 13.

RJEENJE:

// Funkcija izbacip() prima neki integer broj


int izbacip(int n){
/* Definisanje varijabli, t je tezisnica koja se svaki put kada dodajemo
neku cifru pomnozi sa 10, o je ostatak, i je brojac, a c je broj koji ce
funkcija vratiti kao rezultat */
int c=0,t=1,o,i;
/* i se uvecava za 1 i for petlja se vrti sve dok broj n bude jednak 0 */
for (i=1;n>0;i++){
/* Uzima se ostatak dijeljenja sa 10, odnosno zadnja cifra broja */
o=n%10;
// Odbije se zadnja cifra broja n dijeljenjem sa 10
n=n/10;
/* Ako je broj paran, vraca se na pocetak petlje i time se izbacaju parne
cifre */
if (o%2==0) continue;
// Dodavanje cifre na broj c
c=c+t*o;
// Mnozenje tezisnice sa 10
t=t*10;
}
// Vracanje varijable c
return c;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

37. Napisati funkciju ispis_preko_a() koja kao argment uzima


neko cjelobrojno polje i dva prirodna broja a i d, a zatim
ispisuje sve elemente polja koji su veci od broja a. Broj d
predstavlja broj elemenata polja. Funkcija treba imati slijedeci
prototip:
void ispis_preko_a(int *polje, int a, int d)
Na primjer, za ulazne argumente
int polje[]={4,5,7,20,8,10,2,-2}, a=6, d=8
trebaju se ispisati brojevi: 7, 20, 8, 10

RJEENJE:

// Funkcija prima pokazivac na polje, i dva cijela broja a,d


void ispis_preko_a(int *polje, int a, int d)
{
// Definisanje brojaca i
int i;
/* For petlja se vrti sve dok brojac i koji krece od 0 ne bude veci od broja
d koji je funkcija primila. */
for (i=0; i<d; i++){
/* Ako je broj a koji je primljen u funkciju manji od broja u polju do kojeg
smo dosli on se ispisuje na ekran.*/
if (a<polje[i]) printf("%d, ", polje[i]);
}
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

38. Napisati funkciju zamijeni() koja ce u jednodimenzionalnom


polju A velicine d zamijeniti i-ti element sa minimalnim
elementom u polju A. Elementi polja A su vec definirani u glavnom
programu. Funkcija treba imati prototip:
void zamijeni(int *A, int i, int d)
Na primjer, ako su elementi polja A:
int A[]={3, 7, 10, 20, 18, 4,10, 2, 20], a argumenti i i d imaju
slijedece vrijednosti i=3, d=9 funkcija zamijeni() promjeni polje
A u polje sa slijedecim elementima: 3, 7, 2, 20, 18, 4, 10, 2, 20
(na trece mjesto se stavlja minimalni element iz polja a to je 2)

RJEENJE:

// U funkciju se prima niz brojeva A, broj i, broj d.


void zamijeni(int *A, int i, int d)
{
// Definisanje brojaca j i varijable min
int j,min;
// Postavljanje vrijednosti min na prvi clan niza
min=A[0];
/* Trazenje najmanjeg elementa u nizu. Pretpostavili smo da je to prvi broj, i
sada trebamo ispitati da li postoji neki broj krenuvsi od drugog (j=1 umjesto
j=0 u for petlji) i ako postoji neki manji postavi se da je taj broj min. */
for (j=1; j<d; j++) if (min>A[j]) min=A[j];
/* Postavljanje na i-tu poziciju vrijednosti min (i=1 ide jer nam je i-ti
clan ustvari broj za jedan manje, jer nam je prvi clan nulti clan! */
A[i-1]=min;
// Ispis niza
for (j=0; j<d; j++) printf("%d ", A[j]);
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

39. Data je tekstualna datoteka c:\pismo.txt.


Napisati funkcije za:
a) ispis datoteke na standardni izlaz zadrzavajuci strukturu po
redovima;
b) prepis datoteke u novu mijenjajuci mala i velika slova;
c) ispisati datoteku u obrnutom redosljedu na izlaz (prva
postaje zadnja, druga postaje pretposljednja rijec...)
d) ispitati da li je neka rije palindrom (isto znacenje kada se
cita i u obrnutom smjeru)

RJEENJE:

# include <stdio.h>
// Ispis datoteke na standardni izlaz zadrzavajuci strukturu po redovima...
void ispis(FILE *datoteka){
char znak;
printf("\nSadrzaj datoteke je: \n\n");
while(fscanf(datoteka,"%c", &znak)!=EOF){
printf("%c", znak);
}
}

/* Ispitati da li je neka rijec palindrom (isto znacenje kada se cita i u


obrnutom smjeru) */
void palindrom(FILE *datoteka){
char znak[100];
char *p, *t;
int i, br=0, ispit=0;
printf("\n\nProvjera palindroma: \n");
while(fscanf(datoteka,"%s", &znak)!=EOF){
p=znak;
t=znak;
br=0;
while(*p!='\0') {p++; br++;} p--;
ispit=1;
for(i=0;i<(br/2);i++) if (*(p-i)!=*(t+i)) {ispit=0; break;}
if (ispit==1) {printf("\nPalindrom je: %s", znak); ispit=0;}
}
}

// Prepis datoteke u novu mijenjajuci mala i velika slova


void ispisunovu(FILE *datoteka){
FILE *datoteka1;
char znak;
datoteka1=fopen("c:\\pismo1.txt","w");
while(fscanf(datoteka,"%c", &znak)!=EOF){
if ((znak>64)&&(znak<91)) znak=znak+32; else
if ((znak>96)&&(znak<122)) znak=znak-32;
fprintf(datoteka1, "%c", znak);
}
fclose(datoteka1);
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

/* Ispisati datoteku u obrnutom redosljedu na izlaz (prva postaje zadnja,


druga postaje pretposljednja rijec...) */
void ispisobrnuto(FILE *datoteka){
char znak, matrix[1000][1000], pok[1000];
int i=0, j=0, br=0, k=0, niz[100];
printf("\n\nSadrzaj datoteke je (naopako): \n");
while(fscanf(datoteka,"%c", &znak)!=EOF){
if (znak==' ') {br++; j++; i=0; continue;}
if (znak=='\n') {br++; niz[k]=j; j++; k++; i=0; continue;}
matrix[j][i]=znak;
i++;
}
niz[k]=j;
j=0;
for (i=br;i>=0;i--) {
if((i==niz[k-j])&&(k-j!=-1)) { printf("\n"); j++;}
printf("%s ", matrix[i]);
}
}

main() {
// Definisanje pokazivaca na datoteku
FILE *datoteka;
// Otvaranje datoteke za citanje
datoteka=fopen("c:\\pismo.txt","r");
// Poziv funkcije za ispis datoteke na ekran...
ispis(datoteka);
fclose(datoteka);
// Otvaranje datoteke za citanje
datoteka=fopen("c:\\pismo.txt","r");
// Poziv funkcije za prepis datoteke u novu mijenjajuci mala i velika slova.
ispisunovu(datoteka);
fclose(datoteka);
// Otvaranje datoteke za citanje
datoteka=fopen("c:\\pismo.txt","r");
/* Poziv funkcije za ispis datoteke u obrnutom redosljedu na izlaz (prva
postaje zadnja, druga postaje pretposljednja rijec...) */
ispisobrnuto(datoteka);
fclose(datoteka);
// Otvaranje datoteke za citanje
datoteka=fopen("c:\\pismo.txt","r");
/* Poziv funkcije za ispitivanje da li je neka rijec palindrom (isto znacenje
kada se cita i u obrnutom smjeru) */
palindrom(datoteka);
fclose(datoteka);
// Kraj programa...
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

40. Napisati program koji cita vie linija teksta sa ulaza i


tampa koliko rijeci je duzine 2 3 4 i vie slova. tampu
realizovati pomocu funkcije STAM_REZ u datoteku ili na ekranu. Iz
datoteke rezultata dati izvjetaj o ukupnom broju rijeci i
prosjecnoj duzini rijeci.

RJEENJE:

#include <stdio.h>

// Funkcija koja kreira datoteku sa rezultatima


void STAM_REZ(char *tekst, int br){

// Definisanje pokazivaca na fajl


FILE *rezultati;

// Definisanje varijabli
int i,b=0,dva=0,tri=0,cetiri=0,vise=0, brojslova=0, prosjek=0;

// Otvaranje datoteke u koju cemo pisati podatke


rezultati=fopen("c:\\rezultati.txt","w");

// For petlja vrti se "br" puta...


for (i=0;i<br;i++){

/* Ukoliko znak do kojeg smo dosli nije ? ! . \n , \t ili blanko


brojac b se uvecava za 1, brojac b nam pokazuje koliko slova je u rijeci
izbrojano. */
if ((tekst[i]=='?')||(tekst[i]=='!')||(tekst[i]==' ')
||(tekst[i]=='.')||(tekst[i]=='\n')||(tekst[i]==',')||(tekst[i]=='\t')) {

/* Nakon sto naidjemo na neki od ovih znakova u uslovu ulazimo u petlju... i


imamo... ako je b>1 broj slova ce se sabrati sa brojem slova rijeci koja se
trenutno obradjuje, ako je b=2 onda se varijabla dva koja broji rijeci sa 2
slova uveca za 1. Ako je tri onda se varijabla tri uveca za 1... ako je preko
4 onda se varijabla vise uveca za 1... primjetite da se brojac vraca na 0
izlaskom iz uslova, nebitno da li je bilo b=0 ili 1 ili 2 ili ... */
if (b>1) brojslova=brojslova+b;
if (b==2) {dva++; b=0;} else
if (b==3) {tri++; b=0;} else
if (b==4) {cetiri++; b=0;} else
if (b>4) {vise++; b=0;} else b=0;
} else b++;
}

// Upis podataka u datoteku...


fprintf(rezultati,"Rijeci sa 2 slova: %d\n", dva);
fprintf(rezultati,"Rijeci sa 3 slova: %d\n", tri);
fprintf(rezultati,"Rijeci sa 4 slova: %d\n", cetiri);
fprintf(rezultati,"Rijeci sa preko 4 slova: %d\n", vise);
prosjek=brojslova/(dva+tri+cetiri+vise);
fprintf(rezultati,"PROSJEK: %d\n", prosjek);

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

/* Zatvaranje datoteke i izlaz iz funkcije... void funkcija ne vraca


nista!!! Izlaskom je sve sto se u njoj desavalo zaboravljeno, ali zato imamo
sve rezultate pohranjene u datoteci iz koje cemo po povratku u program citati
podatke.*/
fclose(rezultati);
}

// Glavni program
main(){

// Definisanje varijabli
int br=0, i=0, p=0, dva, tri, cetiri, vise, prosjek;
char tekst[1000];

// Definisanje pokazivaca na fajl


FILE *izvjestaj;

/* Unos teksta (koristio sam while petlju koja upisuje znak po znak, a ne %s
koja upisuje cijeli string odjednom, a zasto? pa jednostavno jos uvijek neznam
drugi nacin da izbjegnem situaciju kad upisete prvi razmak, a program to
shvati kao kraj stringa i racuna samo da je string prva rijec, a ostalo kao da
niste unjeli. Ovako se ucita sve sto unesete sa tastature, sto nam i treba. U
zadatku nije naznaceno sta ce biti prekid unosa, pa sam ja stavio tacku :) )*/
printf("Unesi tekst[i], (Tacka za kraj unosa!):");
while (tekst[i-1]!='.') { scanf("%c", &tekst[i]); i++; br++;}

/* Poziv funkcije u koju saljemo tekst koji smo unijeli kao i brojac br koji
je prebrojao broj unesenih karaktera, mogli smo i bez njega, al eto ja nekako
vise volim for petlje od while petlji :) */
STAM_REZ(tekst, br);

// Otvaranje datoteke za citanje i pridruzivanje pokazivacu izvjestaj.


izvjestaj=fopen("c:\\rezultati.txt","r");

// Citanje podataka iz datoteke... formati isti kao pri upisu :)


fscanf(izvjestaj,"Rijeci sa 2 slova: %d\n", &dva);
fscanf(izvjestaj,"Rijeci sa 3 slova: %d\n", &tri);
fscanf(izvjestaj,"Rijeci sa 4 slova: %d\n", &cetiri);
fscanf(izvjestaj,"Rijeci sa preko 4 slova: %d\n", &vise);
fscanf(izvjestaj,"PROSJEK: %d", &prosjek);

// Ispis izvjestaja na ekranu.


printf("\n\nIZVJESTAJ: ");
printf("\n\nUkupno rijeci: %d", dva+tri+cetiri+vise);
printf("\nProsjecna duzina rijeci: %d", prosjek);

// Zatvaranje datoteke i kraj programa


fclose(izvjestaj);
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

41. Program treba unjeti 2 broja i ispisati NZD... najveci


zajednicki djeljilac...

RJEENJE:

#include <stdio.h>
main() {
// Definicija varijabli
int i,a,b,min,nzd=1;
// Unos dva prirodna broja
printf("Unesi dva broja: ");
scanf("%d,%d", &a, &b);
// Pridruzuje se varijabli min manji od unesena 2 broja
if (a<=b) min=a; else min=b;
// I se stavlja da je jednako min, i umanjuje se sve do 1... prvi broj
// sa kojem uspiju podijeliti se oba broja je i NZD... izlazi se iz petlje kad
// se oba broja uspiju bodijeliti...
for (i=min;i>0;i--){
if (((a%i)==0)&&((b%i)==0)) {nzd=i; break;}
}
// Ispis NZD-a
printf("\nNajveci zajednicki sadrzilac je: %d" , nzd);
// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

42. Ispis sljedeceg znaka na ekranu...


+++++-+++++
++++---++++
+++-----+++
++-------++
+---------+
++-------++
+++-----+++
++++---++++
+++++-+++++
#include <stdio.h>
main() {
int k,i,j,a=11; // a predstavlja dimenzije znaka
for (k=0;k<a;k++) printf("+");
printf("-");
for (k=0;k<a;k++) printf("+");
printf("\n");
for (i=1;i<a;i++){
for (k=0;k<a-i;k++) printf("+");
for (k=a;k>a-i;k--) printf("-");
printf("-");
for (k=a;k>a-i;k--) printf("-");
for (k=0;k<a-i;k++) printf("+");
printf("\n");
}
for (i=2;i<a;i++){
for (k=a;k>a-i;k--) printf("+");
for (k=0;k<a-i;k++) printf("-");
printf("-");
for (k=0;k<a-i;k++) printf("-");
for (k=a;k>a-i;k--) printf("+");
printf("\n");
}
for (k=0;k<a;k++) printf("+");
printf("-");
for (k=0;k<a;k++) printf("+");
printf("\n");
// Svaki pokusaj pojasnjenja ovog zadatka je suvisan... ovo cete ili skontat
ili necete :) jednostavna igra sa for petljama... pokusajte uraditi preko
funkcija :)
// Kraj programa
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

43. Unesite broj clanova niza cijelih brojeva, a zatim i


clanove niza a zatim ih sortirajte od najveceg ka najmanjem i
ispisite sortirano na ekran.

RJEENJE:

# include <stdio.h>
main(){
// Definisanje varijabli
int n,i,j,niz[100],pom;
// Unos broja clanova niza
printf("\n Unesite broj clanova: "); scanf("%d", &n);
/* Unos niza */
for (i=0;i<n;i++){
printf("\n Unesi clan %d :", i+1);
scanf("%d", &niz[i]); }
/* Znaci imamo neki niz, recimo od 5 clanova: [1,3,4,2,5] i trebamo ga
sortirati od veceg ka manjem broju... na kraju treba izgledati [5,4,3,2,1].
Pri koristenju ove metode, koristimo dvije for petlje, od kojih je jedna (po
i brojacu, tu samo onako radi reda) :) dok druga petlja obavlja vecinu
posla. Mozete primjetiti da u uslovu stoji i<(n-1) kao i j<(n-1). Ako
pogledamo jedan niz od 5 clanova i ako bi mijenjali brojeve tako da mijanjamo,
prvi i drugi clan, zatim drugi i treci, pa 3 i 4, pa 4 i 5. Znaci imamo 4
izmjene iako imamo 5 clanova, i zbog toga u uslovu ide n-1 umjesto n!
Znaci program radi tako da se vanjska for petlja izvrsi n-1 puta a
unutrasnja se izvrsi (n-1)*(n-1) puta... u nasem slucaju od 5 clanova, znaci
16 puta. Mozda je ova metoda spora dosta jer se okrece 16 puta, sto bi se
moglo smanjiti, ali zbog jednostavnosti izgleda, prvo sam uzeo ovu metodu.
Dalje imamo uslov u unutrasnjoj petlji niz[j]<niz[j+1] koji bi u prijevodu
znacio, ako je j-ti clan manji od iduceg (j+1) onda im mijenja mjesta...
Graficki desavanja pri sortiranju naseg niza izgledaju ovako (uspravno
citajte).
1 - 3 3 3 3 4 4 4 4 4 4 4 4 5 5 5 5
3 - 1 4 4 4 3 3 3 3 3 5 5 5 4 4 4 4
4 - 4 1 2 2 2 2 5 5 5 3 3 3 3 3 3 3
2 - 2 2 1 5 5 5 2 2 2 2 2 2 2 2 2 2
5 - 5 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1
I na kraju smo dobili soritran niz... znaci 16 puta se vrtila unutrasnja
petlja po 4 puta je kretala od prvog do cetvrtog clana i vrsila izmjene po
uslovu u if petlji, i na kraju rezultat mora biti sortiran niz! Da smo htjeli
obrnuto da sortiramo od najmanjeg ka najvecem samo bi se promjenio znak < u
uslovu u if petlji u znak > ... :) */
for (i=0;i<(n-1);i++)
for (j=0;j<(n-1);j++)
if (niz[j]<niz[j+1]) {
pom=niz[j+1];
niz[j+1]=niz[j];
niz[j]=pom;
}
// Ispis niza i kraj programa...
printf("\n Ispis niza: ");
for (i=0;i<n;i++) printf("[%d]", niz[i]);
getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

44. Zadatak br. 43. (prethodni) na drugi nacin...

RJEENJE:

# include <stdio.h>
main(){
// Definisanje varijabli
int n,i,j,niz[100],pom;
// Unos broja clanova niza
printf("\n Unesite broj clanova: "); scanf("%d", &n);
/* Unos niza */
for (i=0;i<n;i++){
printf("\n Unesi clan %d :", i+1);
scanf("%d", &niz[i]); }

/* U prethodnom primjeru sam uradio zadatak metodom bubblesort, a ovaj sam


uradio koristeci metodu NALAZENJA NAJVECEG U NIZU/PODNIZU i stavljanje na
"vrh". Znaci samo se ove for petlje razlikuju u odnosu na prethodni zadatak :)
Imamo vanjsku petlju koja je identicna onoj iz prethodnog zadatka, i ona vrti
unutrasnju petlju n-1 puta. Sad, ako pogledate prethodni primjer primjetiti
cete na grafickom prikazu da nekoliko puta su se vrtile for petlje ali je niz
ostajao isti. Ovom metodom cemo izbjeci to, i uciniti da program radi jos
brze. Znaci svakim novim prolaskom kroz vanjsku petlju se PODNIZ unutar
unutrasnje petlje umanji za 1, i time dobijamo na vremenu. Ovo je malo teze
objasniti :) pa pogledajte graficki prikaz:

1 - 3 4 4 5 5 5 5 5 5 5
3 - 1 1 1 1 3 3 4 4 4 4
4 - 4 3 3 3 1 1 1 2 3 3
2 - 2 2 2 2 2 2 2 1 1 2
5 - 5 5 5 4 4 4 3 3 2 1

Vidite kako smo dosli do rezultata uz samo 11 permutacija, naspram onih 16 iz


prvog primjera. Znaci u prvom dijelu ovog grafickog prikaza, nadjen je najveci
broj niza i stavljen na vrh (broj 5). U drugom dijelu (primjetite da smo
smanjili broj okretanja sa 4 na 3 jer nas vise broj na vrhu ne interesuje, i
samo od preostalog niza od 4 clana trazimo najveci i stavljamo na vrh... i
tako do kraja. */

for (i=0;i<(n-1);i++)
for (j=i+1;j<n;j++)
if (niz[j]>niz[i])
{
pom=niz[i];
niz[i]=niz[j];
niz[j]=pom;
}

// Ispis niza i kraj programa...


printf("\n Ispis niza: ");
for (i=0;i<n;i++) printf("[%d]", niz[i]);

getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


LoVe dOts... ForEver... Autor: Murtic Nirmel
ETF - 2005/2006 www.etf.ba

45. Unosi se sa ulaza broj clanova. Zatim se unese IME, PREZIME


i broj bodova svakog clana. Na izlazu treba ispisati clanove
sortirane po broju bodova.

RJEENJE:

# include <stdio.h>
// Definisanje strukture
struct struktura {
char ime[100];
char prezime[100];
int bodovi;
};

main(){
// Definisanje varijabli
int n,i,j;
struct struktura spisak[100];
struct struktura pom;
// Unos broja clanova niza
printf("\n Unesite broj imena: "); scanf("%d", &n);
/* Unos imena, prezimena, bodova i direktan upis u strukturu*/
for (i=0;i<n;i++){
printf("\n Unesi %d ime:", i+1);
scanf("%s", &spisak[i].ime);
printf(" i prezime:");
scanf("%s", &spisak[i].prezime);
printf(" i bodove:");
scanf("%d", &spisak[i].bodovi);
}
/* Proces sortiranja */
for(i=0;i<(n-1);i++)
for(j=0;j<(n-1);j++)
if (spisak[j].bodovi<spisak[j+1].bodovi)
{
pom=spisak[j];
spisak[j]=spisak[j+1];
spisak[j+1]=pom;
}
// Ispis niza i kraj programa...
for (i=0;i<n;i++) printf("\n%d. [%s %s]: %d", i+1, spisak[i].prezime,
spisak[i].ime, spisak[i].bodovi);

getch();
return 0;
}

Email: matrix.bih@gmail.com ; MSN: nirmel_m@hotmail.com


Programiranje i programsko inenjerstvo, FER
Upute za rad s razvojnom okolinom M S Visual Studio 2008 - Pisanje i pokretanje programa pisanih u programskom jeziku C

Upute za rad s razvojnom okolinom MS Visual Studio 2008


Pisanje i pokretanje programa pisanih u programskom jeziku C

1.Instalacija razvojne okoline:

Preuzeti instalaciju razvojne okoline MS Visual Studio .NET 2008 Professional sa stranica
http://msdnaa.fer.hr/ i instalirati ga na vlastito raunalo. Dozvoljene su i verzije 2005 i 2010.

2.Pokretanje razvojne okoline:

Start Programs Microsoft Visual Studio 2008 Microsoft Visual Studio 2008
Prilikom pokretanja suelja obino se pojavi tzv. Start Page na koje se vidi lista nekoliko
zadnje kreiranih projekata, to se inae koristi za brzi pristup prethodno kreiranim projektima.

3. Stvaranje projekta (preduvjet za poetak pisanja programa)

Iz izbornika File, odaberite opciju New Project (slika 1).

Slika 1.

Odabirom opcije New Project pojavit e se dijalog kao na slici 2. U ovom dijalogu
odaberite:
tip projekta: Visual C++ Win32 Console Application
ime projekta: u polje Name umjesto <Enter name> upiite eljeno ime

1
Programiranje i programsko inenjerstvo, FER
Upute za rad s razvojnom okolinom M S Visual Studio 2008 - Pisanje i pokretanje programa pisanih u programskom jeziku C

lokaciju projekta: za polje Location odaberite kazalo u kojem e projekt biti


smjeten pritiskom na gumb Browse. Kazalo ispod kojeg e va novi projekt biti
kreiran mora postojati.
Ostale podatke nemojte mijenjati te pritisnite gumb OK.

Slika 2

Nakon toga pojavit e se dijalog kao na slici 3. Odaberite opciju Application


Settings.

Slika 3

2
Programiranje i programsko inenjerstvo, FER
Upute za rad s razvojnom okolinom M S Visual Studio 2008 - Pisanje i pokretanje programa pisanih u programskom jeziku C

Na dijalogu kao na slici 4 potrebno je ukljuiti opciju Empty project.


Nakon toga odaberite gumb Finish i novi projekt e biti kreiran.

Slika 4

U ovom je trenutku stvoren projekt koji jo uvijek ne sadri niti jednu datoteku s
programskim kodom.

4. Pisanje programa

Dodavanje programske datoteke u projekt:


pozicionirati se u tzv. Solution Explorera (u sluaju da nije vidljiv odabrati opciju
izbornika View Solution Explorer). Unutar Solution Explorera pod
nazivom projekta (u ovo primjeru smo projekt nazvali Vjezba1) nalaze se 3 stavke:
Source Files, Header Files i Resource Files.
desnim klikom mia na Source Files pojavit e se dijalog kao na slici 5 ime nam
je omogueno dodavanje nove datoteke u projekt. Potrebno je odabrati opciju Add
New item.

3
Programiranje i programsko inenjerstvo, FER
Upute za rad s razvojnom okolinom M S Visual Studio 2008 - Pisanje i pokretanje programa pisanih u programskom jeziku C

Slika 5
Nakon toga potrebno je odabrati da elite dodati C++ datoteku (slika 6) i dati joj ime
koje mora zavravati s ekstenzijom .c (u ovom primjeru tu emo datoteku nazvati
vjezba.c). Pritisnite gumb Open i datoteka e se stvoriti i postati dijelom projekta.

Slika 6
U novodobiveni prostor za pisanje programa koji je dobiven dodavanjem datoteke
vjezba.c potrebno je upisati program. Za vjebu upiite program sa slajda 21 prvog
predavanja (02-UvodProgramiranje).

4
Programiranje i programsko inenjerstvo, FER
Upute za rad s razvojnom okolinom M S Visual Studio 2008 - Pisanje i pokretanje programa pisanih u programskom jeziku C

Slika 7

5. Prevoenje programa

Potrebno je izvesti izgradnju izvrne datoteke odabirom opcije izbornika Build Build
ImeVaegProjekta (na slici 7 to je opcija Build Vjezba1)

Slika 8
U sluaju da va program nema greaka pojavit e se poruka kao na slici 8. U sluaju da se
Output prozor ne vidi, pokrenite opciju izbornika View Output.

5
Programiranje i programsko inenjerstvo, FER
Upute za rad s razvojnom okolinom M S Visual Studio 2008 - Pisanje i pokretanje programa pisanih u programskom jeziku C

Ako je program imao greaka na ovom prozoru e se pojaviti lista greaka gdje se dvoklikom
mia na pojedinu od njih moete pozicionirati na redak u kojem se ta pogreka nalazi.

Slika 9

6. Pokretanje programa

Ako je program bio bez greaka moete ga pokrenuti odabirom opcije Start Without
Debugging iz izbornika Debug (slika 9).

Slika 10

7. Rad na drugom programu

elite li testirati neki drugi program, a da pri tome sauvate ve napisani program,
moete koristiti jednu od ovih metoda:
zatvorite projekt koritenjem opcije File Close Solution, te
cjelokupni opisani postupak ponoviti s nekim drugim imenom
u ve postojee rjeenje koje sadri jedan projekt dodati jo jedan tako da
u Solution Exploreru desnom tipkom mia kliknete na Solution
ImeRjeenja (u ovom primjeru Solution 'Vjezba1') i odaberete
opciju Add New Project. Postupak dodavanja novog projekta je
slian ve opisanom postupku.

Ako imate vie otvorenih projekata, odabir koji projekt (program) elite pokrenuti obavlja se
tako da se na eljeni projekt klikne desnom tipkom mia i odaberete Set as
StartUpProject (slika 10).

6
Programiranje i programsko inenjerstvo, FER
Upute za rad s razvojnom okolinom M S Visual Studio 2008 - Pisanje i pokretanje programa pisanih u programskom jeziku C

Slika 11

7
Programiranje i programsko inenjerstvo
Sveuilite u Zagrebu - Fakultet elektrotehnike i raunarstva -Zavod za primijenjeno raunarstvo

Upute za instalaciju paketa MinGW i rad s prevodiocem GCC


Pisanje i izvravanje programa pisanih u programskom jeziku C

1. Instalacija paketa MinGW

Preuzeti i instalirati MinGW Installer alat sa stranica


http://sourceforge.net/projects/mingw/files/latest/download?source=files

Pokrenuti MinGW Installer alat te putem njega instalirati osnovne komponente paketa MinGW. U
lijevom polju potrebno je odabrati Basic Setup i zatim u desnom polju oznaiti stavku mingw32-base.

Nakon toga u izborniku odaberite Installation -> Apply Changes te u novootvorenom prozoru kliknite
na gumb Apply.

Nakon provedene instalacije potrebno je podesiti sistemsku varijablu PATH dodavanjem putanje do
direktorija bin paketa MinGW. Ako ste MinGW instalirali s inicijalnim (default) postavkama,
direktorij bin paketa MinGW e biti C:\MinGW\bin.

Sistemska varijabla PATH moe se podesiti u Control Panel-u:

1
Control Panel -> System and Security -> System
Potrebno je kliknuti na link koji se nalazi s lijeve strane -> Advanced system settings

U novootvorenom prozoru odabrati karticu (tab) Advanced te zatim kliknuti na gumb Environment
Variables kako je prikazano na slici:

2
Nakon toga potrebno je u listi System variables odabrati varijablu Path i kliknuti na gumb Edit

U novootvorenom prozoru, u polje Variable value, na kraj postojeeg teksta dodati

;C:\MinGW\bin\

3
Obratite panju na znak ; na poetku teksta koji se dodaje u varijablu Path.

Napomena:
Ako ste MinGW instalirali u drugom direktoriju (umjesto u C:\MinGW) tada u tekstu kojim se
dopunjava varijabla Path, zamijeniti C:\MinGW s putanjom do tog direktorija.
Navedeni tekst dodajte na kraj postojeeg sadraja varijable Path, vodei rauna o tome da
postojei sadraj varijable ne obriete!

Alternativni nain instalacije

Studenti koji imaju problema sa instalacijom najnovije inaice MinGW kolekcije na svoje Windows
raunalo mogu pokuati ovu alternativnu metodu:

1. Na raunalu kreirati direktorij u koji e se smjestiti MinGW datoteke (npr. C:\MinGW\)


2. Iz repozitorija datoteka preuzeti arhivu MinGW.zip i raspakirati je u gore kreirani direktorij
3. Postaviti PATH sistemsku varijablu kao to pie u uputama (ako se MinGW nalazi u
"C:\MinGW\" onda je u PATH potrebno nadodati ;C:\MinGW\bin\ )

4
2. Pisanje i pokretanje programa

Nakon to ste instalirali paket MinGW, u direktoriju C:\PPI (ili neki drugi direktorij po vaem
izboru) stvorite znakovnu datoteku (npr. koristei ureiva teksta Notepad) ppi.c. U znakovnu
datoteku upiite sljedei kod:

#include<stdio.h>

int main(void){
printf("Programiranje i programsko inzenjerstvo");
return 0;
}

Program ete prevesti pomou prevodioca GCC na sljedei nain:

1. Pokrenite command prompt (npr. Start menu -> Run pa upiite cmd) i pozicionirajte se u
direktorij C:\PPI.
2. Pokrenite prevodilac GCC naredbom
cc -ansi -pedantic-errors -Wall -o ppi.exe ppi.c
Prvo se navodi naziv programa koji obavlja prevoenje cc. Nakon toga navode se
parametri:
-ansi parametar kojim osiguravamo prevoenje sukladno ANSI standardu
-pedantic-errors parametar kojime zahtijevamo detaljno ispisivanje greaka u
programu
-Wall parametar kojime zahtijevamo detaljan ispis upozorenja
Zatim slijedi parametar o kojim se odreuje kako e se zvati izvrna datoteka, u naem
sluaju to je ppi.exe. Na kraju je naveden naziv datoteke s izvornim kodom, ppi.c.

Nakon prevoenja programa ppi.c, pokrenite izvrnu datoteku ppi.exe. Na zaslonu e se ispisati
tekst Programiranje i programsko inzenjerstvo.

5
Napomena:

Ako vam prilikom pokretanja prevodioca GCC sustav javi sljedeu greku

'cc' is not recognized as an internal or external command, operable program or batch file.

znai da sistemska varijabla Path nije ispravno podeena. Ako niste u mogunosti podesiti varijablu
Path, moete napraviti sljedee:s

1. Pozicionirajte se u direktorij bin unutar direktorija u kojeg ste instalirali MinGW. Ako ste
ostavili inicijalne postavke tada se to direktorij nalazi u C:\MinGW\bin
2. Sada moete pokrenuti GCC prevodilac, ali za naziv datoteke s izvornim kodom morate unijeti
cijelu putanju do te datoteke. Isto vrijedi i za naziv izvrne datoteke

Ako se datoteka s izvornim kodom nalazi u C:\PPI\ppi.c te ako u istom direktoriju (C:\PPI)
elimo stvoriti i datoteku s izvrnim kodom, GCC prevodilac treba pokrenuti :

cc -ansi -pedantic-errors -Wall -o C:\PPI\ppi.exe C:\PPI\ppi.c

Kao naziv datoteke s izvornim kodom naveden je C:\PPI\ppi.c, a kao naziv izlazne datoteke
navedena je datoteka C:\PPI\ppi.exe.
Program se pokree navoenjem apsolutnog ili relativnog puta do datoteke s izvrnim kodom, u
naem primjeru:

C:\PPI\ppi.exe

6
Programiranje i programsko inenjerstvo
Sveuilite u Zagrebu - Fakultet elektrotehnike i raunarstva -Zavod za primijenjeno raunarstvo

Koritenje znakovnog suelja u operacijskom sustavu Windows


Windows operacijski sustav za komunikaciju s korisnikom, osim grafikog korisnikog suelja (GUI -
graphical user interface), omoguava koritenje znakovnog (tekstualnog) korisnikog suelja (CLI -
command-line interface, command-line user interface, console user interface, CUI-character user
interface) u kojem se raunalom upravlja upisivanjem naredbe u naredbenom retku (command line).
Kod takvog naina komunikacije, raunalo prvo korisniku ispisuje obavijest (prompt) da je spremno
od njega prihvatiti naredbu, nakon ega korisnik koristei tipkovnicu upisuje naredbu. Znakovno
korisniko suelje vrlo je esto u upotrebi u znanosti, inenjerstvu i industriji, a podrano je od svih
danas vanih operacijskih sustava, kao to su Unix, Linux, Windows, itd.
U sklopu kolegija Programiranje i programsko inenjerstvo, znakovno suelje koristit e se prilikom
rada s datotekama u koje su pohranjeni izvorni i izvrni kodovi C programa, te radi prevoenja i
izvravanja C programa.

1 Pokretanje znakovnog suelja


Postoji vie mogunosti za pokretanje znakovnog suelja (tj. otvaranja prozora s znakovnim
sueljem). U nastavku je navedeno nekoliko mogunosti:
a) Start Svi programi (All Programs) Pomagala (Accessories) Naredbeni redak
(Command Prompt)
b) Start Svi programi (All Programs) Pomagala (Accessories) Pokreni (Run)
nakon ega se otvara prikazani
prozor u kojem je u okvir
potrebno upisati naredbu cmd te
pritisnuti gumb OK:

c) Start u okvir za pretraivanje (Search) upisati cmd, nakon ega se otvara prozor
prikazan pod b)
d) istovremeni pritisak tipki Windows i R (Win+R), nakon ega se otvara prozor prikazan pod b)
Nakon toga otvara se prozor s znakovnim sueljem:

1
2 Izvoenje programa i naredbi
Pokretanje naredbe ili programa obavlja se upisivanjem njegovog imena, argumenata (npr. naziv
datoteke) i opcija (parametri koji modificiraju djelovanje naredbe, a navode se iza znaka /), te
pritiskom na tipku Enter. Ne razlikuju se velika i mala slova u nazivima datoteka, naredbi i opcija.
Dakle, sasvim je svejedno je li upisano npr. HELP ili help.
Naredba se upisuje iza prompta, koji se pojavljuje kada je suelje spremno od korisnika prihvatiti
naredbu. Prompt obino zavrava znakom >.
U nastavku su navedeni primjeri koritenja pojedinih naredbi u njihovom osnovnom obliku. Popis
uobiajenih naredbi mogue je dobiti upisivanjem naredbe help. Za prikaz dodatnih informacija o
pojedinoj naredbi, potrebno je upisati help naziv_naredbe.
Program koji se izvodi moe biti prekinut istovremenim pritiskom na tipke Ctrl i C (Ctrl+C).
Izvoenje programa moe biti privremeno zaustavljeno pritiskom na tipku Pause ili kombinacijom tipki
Ctrl+S. Nastavak izvoenja na ovaj nain zaustavljenog programa obavlja se pritiskom na bilo koju
tipku, na primjer Enter.
Naredbom exit zavrava se rad s znakovnim sueljem i zatvara pripadni prozor.
Primjer:
help help (dobivanje uputa o radu programa help)

help tree (dobivanje uputa o radu programa tree; uz kratki opis naredbe dan je i opis
dozvoljenih opcija: /F i /A, pa je mogue, na primjer, zadati naredbu: tree /f)

3 Rad s datotekama i direktorijima

3.1 Datoteni sustav operacijskog sustava Windows


Podaci pohranjeni u vanjskoj (postojanoj) memoriji (npr. disk, CD, memory stick, ...) logiki su
organizirani u datoteke. Datoteka je imenovani skup podataka koji sainjavaju logiku cjelinu.
Datoteke su logiki grupirane u direktorije (mape, kazala), koji mogu sadravati proizvoljan broj
datoteka i drugih direktorija (poddirektorija). Direktoriji su organizirani hijerarhijski, u strukturu nalik
na stablo. Direktorij je zapravo datoteka koja sadri popis i podatke o karakteristikama drugih
datoteka.

2
Datoteni sustav raunala je dio operacijskog sustava koji slui za organiziranje, upravljanje i pristup
datotekama. Upravljanje datotekama jedna je od osnovnih zadaa operacijskog sustava. Operacijski
sustav, izmeu ostalog, vodi evidenciju o fizikom smjetaju datoteka na mediju za pohranu te nudi
suelje za otvaranje postojeih, stvaranje novih datoteka, itanje iz datoteke, pisanje u datoteku,
premjetanje, preimenovanje te brisanje datoteka i direktorija.

Datoteka je odreena (identificirana) imenom i apsolutnim putem (path) do direktorija u koji je


upisana. Ime datoteke/direktorija sastoji se od osnovnog dijela i nastavka, meusobno odvojenih
tokom. Nastavak nije obavezan dio imena datoteke/direktorija, ali se obino navodi uz ime datoteke
kako bi se njime sugerirao njezin tip i namjena. Na primjer, uobiajeno je datoteci koja sadri samo
tekst dodijeliti nastavak txt, datoteci koja sadri izvorni kod napisan u programskom jeziku C
dodijeliti nastavak c, a datoteci koja predstavlja izvrni program dodijeliti nastavak exe. Osim naziva,
datoteka ima i ostala svojstva kao to je npr. veliina, vrijeme nastanka i izmjene itd.
Datoteni sustav moe ukljuivati vie vanjskih jedinica za pohranu (najee tvrdih diskova). U
operacijskom sustavu Windows one mogu biti podijeljene u vie logikih jedinica (particija), obino
oznaenih slovima C:, D:, itd. U nastavku se pod pojmom disk misli na logiku jedinicu.

Svaki disk sadri jedan izvorni ili osnovni direktorij (root) koji je oznaen znakom \. Kako broj izvornih
direktorija ovisi o broju diskova, da bi se znalo o kojem se izvornom direktoriju radi, ispred znaka \
navodi se i oznaka diska, npr. C:\, D:\, itd. U nekim operacijskim sustavima (npr. Unix), postoji samo
jedan izvorni direktorij te se ne navodi oznaka diska.
Na slici je, u grafikom suelju operacijskog sustava Windows (pomou programa Windows Explorer),
prikazana stablasta struktura direktorija na disku C te, na desnoj strani, sadraj (direktoriji i datoteke)
direktorija \cygwin\lib:

3
Prikaz stablaste strukture direktorija u
znakovnom suelju omoguava naredba tree.
Ako je naredba zadana bez opcija, ispisuju se
samo nazivi direktorija. Navoenjem opcije /f,
biti e prikazane i datoteke (slika desno).
Operacijski sustav prati trenutnu poziciju
korisnika unutar datotenog sustava za vrijeme
dok koristi znakovno korisniko suelje. Ta se
trenutna pozicija naziva radni (working, current)
disk i radni direktorij. Informacija o radnom disku i
radnom direktoriju sastavni je dio prompta. Na
slici desno prompt predstavlja tekst
C:\cygwin\lib>, to znai da je radni disk C, a
radni direktorij je direktorij lib, koji je
poddirektorij direktorija cygwin smjetenog u
izvornom direktoriju.

Datoteci/direktoriju mogue je pristupiti


navoenjem puta do te datoteke/direktorija, tj.
navoenjem naziva direktorija kroz koje je
potrebno proi da bi se dolo do te
datoteke/direktorija, odvojene znakom \. Put
moe biti apsolutan ili relativan.

Apsolutni put zapoinje oznakom diska i izvornim


direktorijem, nakon ega se navode svi direktoriji
do direktorija u koji je smjetena datoteka. Na
primjer, ako se datoteka popis.txt nalazi u
direktoriju \users\ana na disku C, apsolutni put
do nje je C:\users\ana\popis.txt.

Relativni put ovisi o radnom direktoriju. Prilikom navoenja relativnog puta do datoteke mogue je
koristiti i posebne oznake:
. oznaava radni direktorij
.. oznaava direktorij nadreen radnom direktoriju
Na primjer, ako je radni direktorij C:\users\hrvoje (apsolutni put do tog direktorija), oznaka .
predstavlja oznaku za direktorij C:\users\hrvoje, oznaka .. predstavlja oznaku za direktorij C:\users, a
..\.. je oznaka za izvorni direktorij C:\. Relativni put do datoteke ije je ime popis.txt, a nalazi se u
direktoriju C:\users\ana je ..\ana\zivotopis.txt.
Veina naredbi kao argument prihvaa naziv jedne ili vie datoteka, odnosno direktorija. Ako se kod
navoenja naziva izostavi ime direktorija ili diska, podrazumijeva se da se radi o trenutno radnom
direktoriju i disku.
Kod nekih naredbi nije potrebno pisati puno ime datoteka ili direktorija, ve je mogue koristiti i
posebne znakove (tzv. metaznakove, wildcard):
* zamjenjuje neodreeni niz, bilo koju kombinaciju znakova
? zamjenjuje samo jedan, bilo koji znak.
Na primjer, niz ?.txt odreuje sve datoteke koje imaju ime duljine jednog znaka i nastavak txt.

4
Primjer:
tree \ (prikaz stablaste strukture direktorija radnog diska, poevi od izvornog direktorija,
bez prikaza datoteka)

3.2 Pregled sadraja direktorija (dir)


Naredbom dir ispisuje se sadraj direktorija. Imena koja u ispisu imaju oznaku <DIR> su direktoriji, a
ostalo su datoteke.
Primjer:
dir (pregled svih datoteka i direktorija u radnom direktoriju)

dir ppi (pregled direktorija ppi koji se nalazi u radnom direktoriju)


dir c:\tmp (pregled direktorija tmp na disku C:, navoenjem apsolutnog puta)
dir \tmp (pregled direktorija tmp na radnom disku, navoenjem apsolutnog puta)
dir c:\t*.* (pregled svih datoteka iji naziv poinje slovom t i imaju neki nastavak)

3.3 Promjena radnog direktorija (cd)


Za promjenu radnog direktorija koristi se naredba cd. Izvoenjem naredbe cd, navedeni direktorij
proglaava se radnim direktorijem. Direktorij ije je ime navedeno uz naredbu mora postojati. Ako se
naziv direktorija iza naredbe cd izostavi, naredba ispisuje apsolutni put do radnog direktorija.
Dozvoljeno je koristiti apsolutni i relativni put do direktorija.
Naredbom cd nije mogue promijeniti radni disk. Promjena radnog diska obavlja se navoenjem
naziva diska i dvotoke.
Primjer:
cd \users (direktorij users na radnom disku postaje radni direktorij)
cd .. (direktorij nadreen radnom postaje radni direktorij)
cd ..\ana (radni direktorij postaje direktorij ana, koji se nalazi u direktoriju
nadreenom radnom)
cd users (direktorij users, koji se nalazi u radnom direktoriju, postaje radni direktorij)
cd (ispis apsolutnog puta do radnog direktorija)
D: (disk D postaje radni disk)

3.4 Kreiranje direktorija (mkdir)


Naredbom mkdir stvara se novi direktorij, iji je naziv obavezno navesti. Stvaranjem direktorija on
ne postaje radnim. Da bi postao radni, potrebno je upotrijebiti naredbu cd.
Primjer:

5
mkdir c:\tmp (stvaranje direktorija tmp u izvornom direktoriju na disku C)
mkdir tmp (stvaranje direktorija tmp u radnom direktoriju)

3.5 Kopiranje datoteka (copy)


Naredbom copy obavlja se kopiranje datoteke (datoteka) u neku drugu datoteku unutar istog ili
nekog drugog direktorija. Naredba copy u jednostavnijem obliku ima dva argumenta: prvi argument
predstavlja ime datoteke iji se sadraj kopira (izvor), a drugi argument je ime kopije. U drugom
obliku, copy naredbi se moe predati vie datoteka kao izvor, a kao zadnji argument navodi se ime
jednog direktorija u koji se kopiraju sve navedene datoteke.
Primjer:
copy ppi.c ppi1.c (kopiranje datoteke ppi.c u datoteku ppi1.c u radnom direktoriju)
copy ppi.c \tmp (kopiranje datoteke ppi.c iz radnog direktorija u direktorij tmp na radnom
disku)
copy C:\*.* . (kopiranje svih datoteka izvornog direktorija u radni direktorij)

3.6 Promjena imena i premjetanje datoteka i direktorija (move)


Naredbom move obavlja se promjena imena jedne datoteke ili direktorija, odnosno premjetanje
direktorija ili datoteka u druge direktorije. Ako se kao izvor navedu nazivi vie datoteka ili koriste
posebni znakovi, za ciljno ime treba navesti naziv direktorija (slino kao kod naredbe cp) u koji e biti
premjetene izvorne datoteke.
Primjer:
move ana hrvoje (promjena naziva direktorija ana u hrvoje)
move ppi.c ppi.save (promjena naziva datoteke ppi.c u ppi.save)
move ppi* tmp (premjetanje datoteka ije ime poinje s ppi.c u direktorij tmp)

3.7 Ispis sadraja datoteke na zaslon (type)


Naredba type prikazuje na zaslonu sadraj datoteke (obino datoteke s nastavkom txt). Pokuaj
ispisa sadraja datoteke koja ne sadri samo tekst (npr. datoteke s nastavkom exe), rezultira ispisom
nerazumljivog niza znakova.
Primjer:
type ppi.c (ispisivanje sadraja datoteke ppi.c na zaslon)

3.8 Brisanje datoteke (del)


Naredbom del mogue je obrisati jednu ili vie datoteka (dozvoljena je upotreba posebnih znakova *
i ?). Ako se kao argument naredbe navede ime direktorija, obrisat e se sve datoteke u tom
direktoriju.
Primjer:
del ppi.exe (brisanje datoteke ppi.exe)
del x.* (brisanje svih datoteka s imenom x i bilo kojim nastavkom u radnom
direktoriju)
del \tmp (brisanje svih datoteka u direktoriju tmp)
del . (brisanje svih datoteka u radnom direktoriju)

6
3.9 Brisanje direktorija (rmdir)
Naredbom rmdir brie se navedeni direktorij. Ako nisu navedene dodatne opcije, direktorij je
mogue obrisati samo ako je prazan, tj. ako u njemu nema niti jedne datoteke ili direktorija.
Koritenjem opcije /s mogue je obrisati i direktorij koja nije prazan.
Primjer:
rmdir C:\tmp (brisanje praznog direktorija tmp u izvornom direktoriju)
rmdir /s vjezba (brisanje direktorija vjezba koji se nalazi u radnom direktoriju,
direktorij e biti obrisan i ako nije prazan)

4 Preusmjeravanje (redirekcija)
Prilikom izvoenja naredbi u znakovnom suelju podrazumijeva se da se ulazni podaci prihvaaju s
tipkovnice, a izlazni ispisuju na zaslonu. Tipkovnica predstavlja standardni ulaz, a zaslon standardni
izlaz. Meutim, ponekad je potrebno izlazne podatke preusmjeriti u datoteku, ili pak ulazne podatke,
umjesto s tipkovnice, preuzeti iz datoteke. To se postie koritenjem znakova za preusmjeravanje:
> preusmjerava izlaz u datoteku; ako datoteka ve postoji, brie se njen dotadanji sadraj
< preuzima ulazne podatke iz datoteke
>> preusmjerava izlaz u datoteku; ako datoteka ve postoji, podaci se dodaju na kraj datoteke

4.1 Preusmjeravanje izlaznih podataka u datoteku


Naredbom
dir C:\tmp > dir_tmp.txt
rezultat naredbe dir C:\tmp, koji bi se standardno pojavio na zaslonu, bit e zapisan u datoteku
dir_tmp.txt u radnom direktoriju. Ako datoteka nije postojala prije izvoenja naredbe, naredbom
e biti kreirana. Ako je datoteka postojala, njen stari sadraj e se izgubiti.
Naredbom
dir . >> dir_tmp.txt
rezultat naredbe dir . bit e nadodan na kraj datoteke dir_tmp.txt.

4.2 Preusmjeravanje ulaznih podataka iz datoteke


Preusmjeravanje ulaznih podataka naroito je korisno prilikom testiranja programa koji zahtijeva
puno ulaznih podataka, jer je umjesto njihovog stalnog upisivanja pomou tipkovnice mogue
koristiti podatke koji su unaprijed pripremljeni i pohranjeni u datoteku.
Naredbom
izracunaj.exe < podaci.txt
standardni ulaz usmjeren je iz datoteke podaci.txt, pa e program izracunaj.exe iz te
datoteke, umjesto s tipkovnice, uitati potrebne podatke. Ako program ispisuje rezultate, oni e biti
ispisani na zaslonu monitora.

4.3 Preusmjeravanje ulaznih i izlaznih podataka


Naredbom
izracunaj.exe < podaci.txt > rezultati.txt
postie se da se ulaz u program izracunaj.exe preusmjeri iz datoteke podaci.txt, a izlaz se
preusmjeri u datoteku rezultati.txt.

7
5 Editori teksta
Editori teksta su programi namijenjeni pisanju teksta u kojem nema posebnih znakova za
formatiranje (tzv. kontrolnih kdova). Za razliku od editora, programi za ureivanje teksta, osim slova
i uobiajenih znakova, ubacuju posebne znakove koji slue za formatiranje konanog teksta
(odreivanje rubova, odreivanje tipa i veliine slova i sl.). Za pisanje programa koriste se iskljuivo
editori.
Na vjebama se koristi editor Notepad. Editor je mogue pokrenuti na dva naina:
navoenjem samo naredbe notepad,
navoenjem naredbe notepad iza koje slijedi ime datoteke koju je potrebno editirati (notepad
ime_datoteke).
Ako je editor pokrenut na prvi nain, potrebno je naknadno navesti ime datoteke u koju se eli
spremiti upisani tekst. Meutim, kako je txt ponueni nastavak za naziv datoteke, esto se dogodi
da datoteka dobije dodatni nastavak txt, a treba paziti i na direktorij u koji e biti smjetena. Na
primjer, ako je datoteku potrebno nazvati ppi.c, mogue je da zapravo bude nazvana ppi.c.txt.
Zato je preporuka pokretati editor uz navoenje naziva datoteke (uz mogunost navoenja
apsolutnog ili relativnog puta):
notepad ppi.c (editorom se otvara datoteka ppi.c koja je smjetena u radnom
direktoriju)
notepad d:\vjezbe\p.c (editorom se otvara datoteka p.c koja je smjetena u direktoriju
\vjezbe na disku D)

8
Zadaci za vjebu
1) Obaviti sljedee:
1. Izvorni direktorij na disku C proglasiti radnim direktorijem (u nastavku vjebe radni disk i
direktorij promijeniti samo kada je to traeno u zadatku).
2. Na disku C u izvornom direktoriju kreirati direktorij vjezba.
3. Unutar direktorija vjezba, ne mijenjajui radni direktorij, kreirati direktorije osobno i ppi.
4. Uz koritenje relativnog puta proglasiti direktorij C:\vjezba\osobno radnim direktorijem,
te unutar njega kreirati direktorije txt i slike.
5. Uz koritenje apsolutnog puta proglasiti direktorij slike radnim direktorijem, a zatim u taj
direktorij kopirati nekoliko slika (moete ih prethodno potraiti koritenjem npr. programa
Windows Explorer). Prilikom kopiranja slika navesti apsolutni put do direktorija u kojem se
nalaze slike, a relativni put do direktorija u koji je potrebno kopirati slike.
6. Jednom naredbom proglasiti direktorij C:\vjezba\osobno\txt radnim direktorijem, uz
koritenje relativnog puta.
7. Provjeriti postoji li u radnom direktoriju datoteka nema.me.
8. Editorom Notepad u datoteku zivot.txt upisati neki tekst.
9. Kopirati datoteku zivot.txt u datoteke pom.txt i pom1.txt u radnom direktoriju.
10. Ispisati stablastu strukturu direktorija (bez datoteka) na disku C poevi od izvornog
direktorija. Privremeno zaustaviti te nakon toga nastaviti ispisivanje te strukture na zaslon.
11. Ispisati stablastu strukturu direktorija, ukljuujui datoteke, poevi od direktorija vjezba uz
koritenje relativnog puta. Usporediti dobivenu strukturu sa strukturom prikazanom u
grafikom suelju, koristei program Windows Explorer.
12. Pozvati program help bez argumenata, a izlaz programa preusmjeriti u datoteku
help.txt.
13. Ispisati sadraj radnog direktorija.
14. Prebaciti datoteku help.txt u nadreeni direktorij.
15. Ispisom sadraja radnog, a zatim i nadreenog direktorija, provjeriti je li kopiranje uspjeno
obavljeno.
16. Bez promjene radnog direktorija, na zaslon ispisati sadraj datoteke help.txt.
17. U radnom direktoriju obrisati sve datoteke ije ime zapoinje slovom p.
18. Proglasiti izvorni direktorij radnim direktorijem navoenjem relativnog puta.
19. Obrisati direktorij C:\vjezba\osobno\txt (navesti apsolutni put do direktorija).
20. Obrisati sve datoteke u direktoriju C:\vjezba\osobno\slike (navesti relativni put do
direktorija).
21. Obrisati direktorij osobno.

2) Napisati program koji e proitati dva cijela broja i ispisati vei broj. Izvorni kod pohraniti u
datoteci proba.c u direktoriju ppi kreiranom u 1. zadatku. Za editiranje koristiti editor Notepad
(naziv datoteke navesti prilikom pokretanja editora). Prevesti program pomou prevodioca GCC,
a izvrnu datoteku nazvati proba.exe. Izvesti program tako da se:
1) brojevi itaju s tipkovnice, a rezultat ispisuje na zaslon monitora
2) brojevi itaju s tipkovnice, a rezultat ispisuje u datoteku izlaz.txt
3) brojevi itaju iz datoteke ulaz.txt koja je prethodno pripremljena pomou editora, a
rezultat ispisuje na kraj datoteke izlaz.txt, bez unitavanja njenog prethodnog sadraja

9
Rjeenja
1)
1. cd c:\
2. mkdir vjezba
3. mkdir vjezba\osobno
mkdir vjezba\ppi
4. cd vjezba\osobno
mkdir txt
mkdir slike
5. cd c:\vjezba\osobno\slike
npr: copy c:\users\hrvoje\slike\*2013*.jpg .
6. cd ..\txt
7. dir nema.me
8. notepad zivot.txt
9. copy zivot.txt pom.txt
copy zivot.txt pom1.txt
10. tree \
privremeno zaustavljanje izvoenja: Pause (ili Ctrl+S)
nastavak izvoenja: bilo koja tipka
11. tree /f ..\..
12. help > help.txt
13. dir
14. move help.txt ..
15. dir .
dir ..
16. type ..\help.txt
17. del p*
18. cd ..\..\..
19. rmdir /s C:\vjezba\osobno\txt
20. del C:\vjezba\osobno\slike
21. rmdir /s C:\vjezba\osobno

2) cd c:\vjezba\ppi
notepad proba.c
U znakovnu datoteku proba.c upisati sljedei kod:
#include <stdio.h>
int main(void) {
int x,y;
printf("Upisite dva cijela broja: ");
scanf("%d %d", &x, &y);
if (x>y) {
printf("%d\n", x);
} else {
printf("%d\n", y);
}
return 0;
}

10
cc -ansi -pedantic-errors -Wall -o proba.exe proba.c
1) proba.exe
2) proba.exe > izlaz.txt
type izlaz.txt
3) notepad ulaz.txt
U znakovnu datoteku proba.c upisati dva cijela broja, npr:
10 5

proba.exe < ulaz.txt >> izlaz.txt


type izlaz.txt

11
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 02-UvodProgramiranje.pdf - do stranice: 25

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

1. vjebe uz predavanja

1. Napiite program koji na zaslon ispisuje poruku


Upisite jedan pozitivni cijeli broj:
i nakon toga preko tipkovnice uita jedan cijeli broj. Ako je broj ispravno upisan (tj.
uitan je pozitivan broj), na zaslon treba ispisati:
Zadnja znamenka broja xxxxx je x
inae, ako je uitan negativan broj ili nula, na zaslon ispisati
Broj xxxxx nije pozitivan broj

Uputa: kojim brojem n treba podijeliti broj m da bi se kao ostatak dijeljenja dobila zadnja
(krajnje desna) znamenka broja m? Postoji li u programskom jeziku C aritmetika
operacija kojom se izraunava ostatak cjelobrojnog djeljenja?

2. S tipkovnice uitati polumjer kruga (realni broj). Ako je uitani broj pozitivan, izraunati
opseg i povrinu kruga, te na zaslon ispisati:
zadani polumjer je: xxxxxx.xxxx
opseg kruga je: xxxxxx.xxxx
povrsina kruga je: xxxxxx.xxxx
inae (ako uitani broj nije pozitivan) na zaslon treba ispisati:
broj xxxxxx.xxxx nije ispravan polumjer kruga

3. S tipkovnice uitati cijeli broj i zatim na zaslon ispisati poruku:


ucitan je broj xxxxx
Ako je uitan negativan broj, ispisati:
broj je negativan
Nakon toga (bez obzira je li uitani broj negativan) ispitati parnost uitanog broja i
ispisati odgovarajuu poruku:
broj je paran
ili
broj je neparan

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 02-UvodProgramiranje.pdf - do stranice: 25

Rjeenja

1.
#include <stdio.h>
int main (void) {
int broj, zadnjaZnamenka;
printf("Upisite jedan pozitivan cijeli broj: ");
scanf("%d", &broj);

if (broj > 0) {
zadnjaZnamenka = broj % 10;

/* Druga mogucnost izracunavanja zadnje znamenke jest:


zadnjaZnamenka = broj - broj / 10 * 10;
U prethodnoj naredbi uocite cjelobrojno dijeljenje!
*/

printf("Zadnja znamenka broja %5d je %d\n", broj, zadnjaZnamenka);

} else {
printf("Broj %5d nije pozitivan broj\n", broj);
}

return 0;
}

2.
#include <stdio.h>
int main (void) {
float polumjer, opseg, povrsina;
scanf("%f", &polumjer);

if (polumjer > 0) {
opseg = 2 * polumjer * 3.14159;
povrsina = polumjer * polumjer * 3.14159;
printf("zadani polumjer je: %11.4f\n", polumjer);
printf("opseg kruga je: %11.4f\n", opseg);
printf("povrsina kruga je: %11.4f\n", povrsina);
} else {
printf("broj %11.4f nije ispravan polumjer kruga\n", polumjer);
}

return 0;
}

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 02-UvodProgramiranje.pdf - do stranice: 25

3.
#include <stdio.h>
int main (void) {
int broj, ostatak;
scanf("%d", &broj);
printf("ucitan je broj: %5d\n", broj);

if (broj < 0) {
printf("broj je negativan\n");
}

ostatak = broj % 2;
if (ostatak == 0) {
printf("broj je paran\n");
} else {
printf("broj je neparan\n");
}

return 0;
}

ili

#include <stdio.h>
int main (void) {
int broj;
scanf("%d", &broj);
printf("ucitan je broj: %5d\n", broj);

if (broj < 0) {
printf("broj je negativan\n");
}

if (broj % 2 == 0) {
printf("broj je paran\n");
} else {
printf("broj je neparan\n");
}

return 0;
}

3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 02-UvodProgramiranje.pdf - do stranice: 47

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

2. vjebe uz predavanja

1. Proitajte i zakljuite to bi sljedei program (kada bi bio ispravan) trebao raditi.

#include <stdio.h>;
int mein (void) {
integer xa; ya; xb; yb; xc; yc;
printf("Upisite koordinate vrha trokuta A >");
scan("%d %d", &xa, &ya);
printf("Upisite koordinate vrha trokuta B >");
scan("%d %d", &xb, &yb);
printf("Upisite koordinate vrha trokuta C >");
scan("%d %d", &xc, &yc);
xTezista = xa + xb + xc / 3;
yTezista = ya + yb + yc / 3;
printf("Teziste trokuta A(%d, %d), B(%d, %d), C(%d, %d) jest T(%d, %d)"
, xa, ya, xb, yb, xc, yc, xTezista, yTezista);
return 0
}
Zatim pomou copy-paste upiite program u datoteku na svom raunalu i pokuajte ga
prevesti. Prvo ispravite iskljuivo sintaktike pogreke. Nakon toga ispravite pogreke
povezivanja. Kada se program uspjeno prevede, testirajte program s razliitim ulaznim
podacima:
- za vrhove trokuta s koordinatama (0, 0), (3, 3) i (6, 0)
- za vrhove trokuta s koordinatama (0, 0), (1, 1) i (2, 0)
- za vrhove trokuta s koordinatama (0, 0), (1.5, 1.5) i (3, 0)
Ispravite sve logike pogreke.
Uputa: pri rjeavanju ovog zadatka korisno je posluiti se C prevodiocem, koji e otkriti
one sintaktike pogreke i pogreke povezivanja koje sami moda ne uspijete uoiti.

2. Napisati C program kojim e se s tipkovnice uitati pozitivni cijeli broj koji ima 5
znamenaka. Nije potrebno provjeravati je li korisnik upisao ispravan broj. Program treba
na zaslon ispisati prvu i posljednju znamenku uitanog broja.

3. Napisati C program kojim e se s tipkovnice uitati pozitivni cijeli broj koji ima 5
znamenaka. Nije potrebno provjeravati je li korisnik upisao ispravan broj. Program treba
na zaslon ispisati drugu i etvrtu znamenku.

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 02-UvodProgramiranje.pdf - do stranice: 47

Rjeenja

1. Sintaktike pogreke:
toka-zarez se ne smije stavljati iza pretprocesorskih naredbi
definicija varijabli xa, ya, xb, yb, itd. je neispravna. Varijable koje se odjednom
definiraju meusobno se odjeljuju zarezom, a ne tokom-zarezom. Tip integer ne
postoji.
varijable xTezista i yTezista nisu definirane
nedostaje toka-zarez iza naredbe return.

Pogreke povezivanja:
u stdio.h ne postoji funkcija scan (postoji scanf)
program mora sadravati funkciju main (a ne mein)

Logike pogreke:
koordinate teita se neispravno izraunavaju. X koordinate triju vrhova treba prvo
zbrojiti, a tek tada podijeliti s 3 (trenutno se na kvocijent z/3 dodaje vrijednost za x i y.
Isto vrijedi i za y koordinate.
nakon dodavanja zagrada program e ispravno raditi za koordinate vrhova (0, 0), (3,
3) i (6, 0), ali ne i za koordinate (0, 0), (1, 1) i (2, 0). Razlog je u cjelobrojnom
dijeljenju i tipu rezultata: 0+1+0 cjelobrojno podijeljeno s 3 daje 0, a ne 0.33333.
Potrebno je promijeniti tip svih varijabli: koordinate vrhova trokuta i teita trebaju biti
realni, a ne cijeli brojevi.

Program nakon ispravljanja svih pogreaka:


#include <stdio.h>
int main (void) {
float xa, ya, xb, yb, xc, yc;
float xTezista, yTezista;
printf("Upisite koordinate vrha trokuta A >");
scanf("%f %f", &xa, &ya);
printf("Upisite koordinate vrha trokuta B >");
scanf("%f %f", &xb, &yb);
printf("Upisite koordinate vrha trokuta C >");
scanf("%f %f", &xc, &yc);
xTezista = (xa + xb + xc) / 3;
yTezista = (ya + yb + yc) / 3;
printf("Teziste trokuta A(%f, %f), B(%f, %f), C(%f, %f) jest T(%f, %f)"
, xa, ya, xb, yb, xc, yc, xTezista, yTezista);
return 0;
}

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 02-UvodProgramiranje.pdf - do stranice: 47

2.
#include <stdio.h>
int main (void) {
int broj;
printf("Upisite 5-znamenkasti pozitivni cijeli broj: ");
scanf("%d", &broj);
printf("Prva znamenka: %d\n", broj/10000);
printf("Posljednja znamenka: %d\n", broj%10);
return 0;
}

3.
#include <stdio.h>
int main (void) {
int broj;
printf("Upisite 5-znamenkasti pozitivni cijeli broj: ");
scanf("%d", &broj);
printf("Druga znamenka: %d\n", broj%10000/1000);
printf("Cetvrta znamenka: %d\n", broj%100/10);
return 0;
}

3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 02-UvodProgramiranje.pdf - do stranice: 84

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

3. vjebe uz predavanja

1. Proitajte i zakljuite to bi sljedei program (kada bi bio ispravan) trebao raditi.


Napiite tekst programskog zadatka koji bi odgovarao programu. Nacrtajte dijagram toka.
Zatim pomou copy-paste upiite program u datoteku na svom raunalu i pokuajte ga
prevesti. Ispravite sve vrste pogreaka i testirajte s razliitim ulaznim podacima.

#definiraj PI 3,1415926
float main (void) {
int a;
float b;
printf("Upisite duljinu velike poluosi a>");
scanf("%f", &a);
printf("Upisite duljinu male poluosi b>");
scanf("%f", &b);
if (a > 0) {
if (b > 0) {
povrsina = A x B x pi;
printf("Povrsina elipse s poluosima a=%f i b=%f je %f", povrsina);
scanf("%f", &b);
} else {
printf("Duljina male poluosi mora biti veca od nule.\nKraj. ");
}
} else {
printf("Duljina velike poluosi mora biti veca od nule.\nKraj. ");
}
return O;
}

2. Napisati C program za pretvaranje vrijednosti temperature izraene u razliitim mjernim


jedinicama. Na poetku program treba ispisati poruku:
Program za konverziju Fahrenheit - Celsius i obrnuto.
Za F u C upisite 1, a za C u F bilo koji drugi cijeli broj >

Ako korisnik upie broj 1, tada ispisati poruku


Upisite temperaturu izrazenu u stupnjevima Fahrenheit >

te s tipkovnice uitati realni broj koji predstavlja temperaturu izraenu u stupnjevima


Fahrenheit, izraunati ekvivalentnu temperaturu izraenu u stupnjevima Celsius te ispisati
temperaturu izraenu u obje jedinice
xxxx.xxx st. F = xxxx.xxx st. C

Ako korisnik upie bilo koji drugi cijeli broj, tada ispisati poruku
Upisite temperaturu izrazenu u stupnjevima Celsius >

te s tipkovnice uitati jedan realni broj koji predstavlja temperaturu izraenu u stupnjevima
Celsius, izraunati ekvivalentnu temperaturu izraenu u stupnjevima Fahrenheit te ispisati
temperaturu izraenu u obje jedinice
xxxx.xxx st. C = xxxx.xxx st. F
1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 02-UvodProgramiranje.pdf - do stranice: 84

3. Nacrtati dijagram toka i napisati C program za zbrajanje ili mnoenje realnih brojeva. Na
poetku program treba ispisati poruku
Program za zbrajanje ili mnozenje.
Upisite dva realna broja >

i uitati dva realna broja koji predstavljaju operande.


Nakon toga program treba ispisati poruku
Upisite vrstu operacije (1-zbrajanje, 2-mnozenje) >

i uitati cijeli broj kojim se odreuje vrsta operacije. Ako je korisnik upisao broj 1, tada treba
izraunati i ispisati zbroj operanada, a ako je upisao broj 2, tada izraunati i ispisati
umnoak operanada. Ako za odabir vrste operacije korisnik nije upisan niti broj 1 niti broj 2,
tada treba ispisati poruku
Neispravan odabir operacije.

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 02-UvodProgramiranje.pdf - do stranice: 84

Rjeenja
1. Programski zadatak: napisati program kojim e se uitati duljine velike i male poluosi elipse.
Nakon uitavanja duljina obje osi, ispitati ispravnost unesenih podataka. Ako je velika poluos
neispravno zadana, ispisati poruku "Duljina velike poluosi mora biti veca od nule.", u sljedeem
retku na zaslonu ispisati "Kraj", te zavriti s izvravanjem programa. Ako je mala poluos
neispravno zadana, ispisati poruku "Duljina male poluosi mora biti veca od nule.", u sljedeem
retku na zaslonu ispisati "Kraj", te zavriti s izvravanjem programa.
Ako su duljine obje osi ispravno zadane, izraunati povrinu elipse i ispisati poruku " Povrsina
elipse s poluosima a=x.xxxxxx i b=x.xxxxxx je x.xxxxxx.
Dijagram toka:

uitaj a, b

Da
a>0

Ne
Da
ispii "neispravna
b>0
velika os, kraj"
Ne
ispii "neispravna izraunaj i ispii
mala os, kraj" povrinu elipse

Program nakon ispravljanja svih pogreaka:


#include <stdio.h>
#define PI 3.1415926
int main (void) {
float a;
float b;
float povrsina;
printf("Upisite duljinu velike poluosi a> ");
scanf("%f", &a);
printf("Upisite duljinu male poluosi b> ");
scanf("%f", &b);
if (a > 0) {
if (b > 0) {
povrsina = a * b * PI;
printf("Povrsina elipse s poluosima a=%f i b=%f je %f", a, b, povrsina);
} else {
printf("Duljina male poluosi mora biti veca od nule.\nKraj");
}
} else {
printf("Duljina velike poluosi mora biti veca od nule.\nKraj");
}
return 0;
}

3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 02-UvodProgramiranje.pdf - do stranice: 84

2.
#include <stdio.h>
int main (void) {
float cels, fahr;
int izbor;
printf("Program za konverziju Fahrenheit - Celsius i obrnuto.\n");
printf("Za F u C upisite 1, a za C u F bilo koji drugi cijeli broj >");
scanf("%d", &izbor);
if (izbor == 1) {
printf("Upisite temperaturu izrazenu u stupnjevima Fahrenheit >");
scanf("%f", &fahr);
cels = (fahr - 32.) * 5. / 9.;
printf("%8.3f st. F = %8.3f st. C\n", fahr, cels);
} else {
printf("Upisite temperaturu izrazenu u stupnjevima Celsius >");
scanf("%f", &cels);
fahr = cels * 9. / 5. + 32.;
printf("%8.3f st. C = %8.3f st. F\n", cels, fahr);
}
return 0;
}

3. U ovom rjeenju je prikazan samo dio dijagrama toka:

Ne
op = 1

Da
Ne
ispii zbroj op = 2

Da
ispii "neispravna
ispii umnoak
operacija"

#include <stdio.h>
int main (void) {
float x, y;
int operacija;
printf("Program za zbrajanje ili mnozenje.\nUpisite dva realna broja >");
scanf("%f %f", &x, &y);
printf("Upisite vrstu operacije (1-zbrajanje, 2-mnozenje) >");
scanf("%d", &operacija);
if (operacija == 1)
printf("Zbroj je %f\n", x + y);
else
if (operacija == 2)
printf("Umnozak je %f\n", x * y);
else
printf("Neispravan odabir operacije.\n");
return 0;
}

4
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 03-TipoviPodataka.pdf - do stranice: 30

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

4. vjebe uz predavanja

1. Dekadski broj 29 prikaite u obliku binarnog broja


2. Binarni broj 10011011 prikaite u obliku dekadskog broja (za prikaz ovog binarnog broja nije
koritena tehnika dvojnog komplementa)
3. Registar od 8 bitova koristi se za prikaz brojeva tehnikom dvojnog komplementa. Koja
dekadska vrijednost je prikazana u registru, ako je sadraj registra 00011011.
4. Registar od 8 bitova koristi se za prikaz brojeva tehnikom dvojnog komplementa. Koja
dekadska vrijednost je prikazana u registru, ako je sadraj registra 10011011.
5. Dekadski broj -14 prikazati kao binarni broj u registru od 5 bitova, koritenjem tehnike
dvojnog komplementa
6. Dekadski broj -14 prikazati kao binarni broj u registru od 10 bitova, koritenjem tehnike
dvojnog komplementa
7. Koji se najvei i najmanji broj (izraziti u dekadskom obliku) moe pohraniti u registru od 12
bita
a. ako se ne koristi tehnika dvojnog komplementa
b. ako se koristi tehnika dvojnog komplementa
8. Koliko najmanje bitova treba imati registar ako je u njega potrebno pohraniti dekadski broj 38
a. ako se ne koristi tehnika dvojnog komplementa
b. ako se koristi tehnika dvojnog komplementa
9. U binarnom brojevnom sustavu, uz primjenu tehnike dvojnog komplementa, koristei
registre veliine 5 bitova, obavite operacije:
a. 410 + 710
b. 1210 - 510
c. 710 + 1110
d. 1210 - 1610
Rezultate provjerite pretvorbom dobivenih binarnih rezultata u dekadske brojeve
10. Dekadski broj 110 pretvoriti u oktalni broj:
a. direktno (uzastopnim dijeljenjem s 8)
b. indirektno, grupiranjem znamenaka binarnog broja
11. Dekadski broj 94 pretvoriti u heksadekadski broj:
a. direktno (uzastopnim dijeljenjem sa 16)
b. indirektno, grupiranjem znamenaka binarnog broja
12. Heksadekadske brojeve F2C i 4E napisati u obliku binarnih i oktalnih brojeva
13. Oktalni broj 76431 napisati u obliku heksadekadskog broja

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 03-TipoviPodataka.pdf - do stranice: 30

14. Dekadski broj -9 pohraniti u registar od 5 bitova (tehnikom dvojnog komplementa). Rezultat
prikazati kao
a. binarni broj
b. heksadekadski broj
c. oktalni broj

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 03-TipoviPodataka.pdf - do stranice: 30

Rjeenja

1. 29 : 2 = 14 ostatak 1
14 : 2 = 7 ostatak 0
7 : 2 = 3 ostatak 1
3 : 2 = 1 ostatak 1
1 : 2 = 0 ostatak 1

Broj 29 je pozitivan, stoga nije potrebno izraunavati dvojni komplement.


Rjeenje: 11101
Provjera: 124 + 123 + 122 + 021 + 120 = 29

2. Prva znamenka jest jedinica, ali u zadatku pie da nije koritena tehnika dvojnog
komplementa. To znai da se radi o pozitivnom broju:
127 + 026 + 025 + 124 + 123 + 022 + 121 + 120 = 155

3. U zadatku pie da se za prikaz broja koristi tehnika dvojnog komplementa, ali prvi bit u
registru nije jedinica. To znai da je u registru prikazan pozitivan broj. Vrijednost odreujemo
na isti nain kao da se tehnika dvojnog komplementa uope ne koristi:
124 + 123 + 022 + 121 + 120 = 27

4. Za prikaz broja se koristi tehnika dvojnog komplementa, a prvi bit u registru jest jedinica.
To znai da je u registru prikazan neki negativan broj x. Izraunavanjem dvojnog
komplementa dobit e se broj koji je jednak po apsolutnoj vrijednosti, ali suprotnog
predznaka (dakle, pozitivan broj):

10011011 -> x
01100100 -> jedinini komplement
+ 1 dodaje se jedan kako bi se dobio dvojni komplement
= 01100101 -> -x
Dobiveni broj -x je pozitivan broj (prvi bit mu nije jedinica), stoga se lako moe odrediti o
kojem se dekadskom broju radi:
126 + 125 + 024 + 023 + 122 + 021 + 120 = 10110
Ako je -x=10110, onda je x=-10110.
Konano rjeenje jest: u registru je pohranjen dekadski broj -101

5. Negativni cijeli brojevi prikazuju se tehnikom dvojnog komplementa. Nije mogue direktno
odrediti binarni prikaz broja -14, stoga se prvo odreuje binarni prikaz pozitivnog broja 14
(uzastopnim dijeljenjem s 2). Voditi rauna o tome da registar ima 5 bitova!
+1410 = 011102
3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 03-TipoviPodataka.pdf - do stranice: 30

Binarni broj iste apsolutne vrijednosti, ali suprotnog predznaka dobije se izraunavanjem
dvojnog komplementa
01110
10001 -> jedinini komplement
+ 1 dodaje se jedan kako bi se dobio dvojni komplement
= 10010 -> dvojni komplement
Konano rjeenje: -14 prikazan u tehnici dvojnog komplementa u registru od 5 bitova jest
10010

6. Slino kao u prethodnom zadatku. Treba voditi rauna da se sada radi o 10-bitnom registru!
+1410 = 00000011102
Negativna vrijednost dobije se izraunavanjem dvojnog komplementa
0000001110
1111110001 -> jedinini komplement
+ 1 dodaje se jedan kako bi se dobio dvojni komplement
= 1111110010 -> dvojni komplement
Konano rjeenje: -14 prikazan u tehnici dvojnog komplementa u registru od 10 bitova jest
1111110010

7. a) Ako se ne koristi tehnika dvojnog komplementa, raspon brojeva koji se moe prikazati u
registru od n bitova jest [0, 2n-1]. Najvei broj koji se moe prikazati u 12-bitnom registru
jest 212-1 = 4095. Najmanji broj koji se moe prikazati jest 0.
b) Ako se koristi tehnika dvojnog komplementa, raspon brojeva koji se moe prikazati u
registru od n bitova jest [-2n-1, 2n-1-1]. Najvei broj koji se moe prikazati u 12-bitnom
registru jest 211-1 = 2047. Najmanji broj koji se moe prikazati jest -2048.

8. a) Ako se ne koristi tehnika dvojnog komplementa, raspon brojeva koji se moe prikazati u
registru od 5 bitova jest [0, 31], a u registru od 6 bitova [0, 63]. Potreban je registar od 6
bitova.
b) Ako se koristi tehnika dvojnog komplementa, raspon brojeva koji se moe prikazati u
registru od 6 bitova jest [-32, 31], a u registru od 7 bitova [-64, 63]. Potreban je registar
od 7 bitova.

9. a) 00100 -> 4
+ 00111 -> 7
= 01011 -> 11

4
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 03-TipoviPodataka.pdf - do stranice: 30

b) 01100 -> 12
+ 11011 -> -5
= 00111 -> 7

c) 00111 -> 7
+ 01011 -> 11
= 10010 -> -14
U ovom sluaju rezultat nije kakav bi se oekivao jer se u registru od 5 bitova, u tehnici
dvojnog komplementa, broj 18 ne moe prikazati.

d) 01100 -> 12
+ 10000 -> -16
= 11100 -> -4

10. a) 110 : 8 = 13 ostatak 6


13 : 8 = 1 ostatak 5
1 : 8 = 0 ostatak 1

Rjeenje: 156
Provjera: 182 + 581 + 680

b) 11010 = 11011102
Binarne znamenke grupirati po tri. PAZITI da se grupiranje obavi "s desna na lijevo":
1 101 1102 = 1568

11. a) 94 : 16 = 5 ostatak 14
5 : 16 = 0 ostatak 5

Rjeenje: 5E
Provjera: 5161 + 14160

b) 9410 = 10111102
Binarne znamenke grupirati po etiri. PAZITI da se grupiranje obavi "s desna na lijevo":
101 11102 = 5E16

5
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 03-TipoviPodataka.pdf - do stranice: 30

12. Svaka heksadekadska znamenka pretvara se u etiri binarne:


F 2 C16 = 1111 0010 11002
4 E16 = 0100 11102

Heksadekadski broj se lako pretvara u oktalni: heksadekadski broj treba napisati kao
binarni broj, zatim binarne znamenke grupirati u grupe po tri. PAZITI da se grupiranje obavi
"s desna na lijevo":
F 2 C16 = 1111 0010 11002 = 111 100 101 1002 = 74548
4 E16 = 0100 11102 = 01 001 1102 = 1168

13. Oktalni broj se lako pretvara u heksadekadski: oktalni broj treba napisati kao binarni broj,
zatim binarne znamenke grupirati u grupe po etiri. PAZITI da se grupiranje obavi "s desna
na lijevo":
7 6 4 3 18 = 111 110 100 011 0012 = 111 1101 0001 10012 = 7D1916

14. -910 = 101112 = 1716 = 278

6
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 03-TipoviPodataka.pdf - do stranice: 67

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

5. vjebe uz predavanja

1. Koje vrijednosti poprimaju varijable a, b nakon izvoenja sljedeeg programskog odsjeka:


char a;
short int b;
a = 120;
b = 32000;
a = a + 10;
b = b + 1000;
Svoje rjeenje provjerite tako da programski odsjeak, dopunjen naredbom za ispis
vrijednosti varijabli na zaslon i ostalim nunim naredbama, izvedete na svom raunalu.
2. Napisati sadraj registra u kojem je, prema IEEE 754 standardu za prikaz brojeva u
jednostrukoj preciznosti, pohranjen broj -17.7812510. Sadraj registra napisati u oktalnom i
heksadekadskom obliku.
3. U registru od 32 bita upisan je broj C2 B0 00 0016. Napisati koji je broj predstavljen u tom
registru, ako registar slui za pohranu varijable tipa float. Rezultat napisati u dekadskom
brojevnom sustavu.
4. U registru od 32 bita upisan je broj 43 00 20 0016. Napisati koji je broj predstavljen u tom
registru, ako registar slui za pohranu varijable tipa float. Rezultat napisati u dekadskom
brojevnom sustavu.
5. U registru od 32 bita upisan je broj 3 01 22 40 00 008. Napisati koji je broj predstavljen u tom
registru, ako registar slui za pohranu varijable tipa float. Rezultat napisati u dekadskom
brojevnom sustavu.
6. U registru od 32 bita upisan je broj 3 77 40 00 00 008. Napisati koji je broj predstavljen u tom
registru, ako registar slui za pohranu varijable tipa float.
7. U registru od 32 bita upisan je broj 7F C0 00 0016. Napisati koji je broj predstavljen u tom
registru, ako registar slui za pohranu varijable tipa float.
8. U registru od 32 bita upisan je broj 80 00 00 0016. Napisati koji je broj predstavljen u tom
registru, ako registar slui za pohranu varijable tipa float.
9. U registru od 32 bita upisan je broj 00 68 00 0016. Napisati koji je broj predstavljen u tom
registru, ako registar slui za pohranu varijable tipa float.
10. U registru od 32 bita upisan je broj 80 00 00 0116. Napisati koji je broj predstavljen u tom
registru, ako registar slui za pohranu varijable:
a. signed int i;
b. unsigned int j;
c. float x;
Rezultate napisati u dekadskom brojevnom sustavu.

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 03-TipoviPodataka.pdf - do stranice: 67

11. Napisati sadraje registara u kojima je, prema IEEE 754 standardu za prikaz brojeva u
jednostrukoj preciznosti, pohranjen sadraj varijabli x i y nakon obavljanja sljedeih naredbi:

float x, y;
x = 0.f;
y = -3.75f / x;

Sadraje registara napisati u heksadekadskom obliku.

12. Napisati sadraj registra u kojem je, prema IEEE 754 standardu za prikaz brojeva u
jednostrukoj preciznosti, pohranjen sadraj varijable x nakon obavljanja sljedeih naredbi:

float x;
x = 0.f;
x = x / x;

Sadraj registra napisati u heksadekadskom obliku.

13. to e se ispisati uz pomo sljedeih naredbi (napomena: u svim naredbama 0


predstavlja znamenku nula, a ne slovo O)
char c;
c = 'A' + '0';
printf("%d\n", c);
printf("%c\n", c);
printf("%c\n", 'D' - 'A' + '0');
printf("%d\n", 'D' - 'A' + '0');
printf("%d\n", '7' - '5');
printf("%d\n", '7' - 5);
printf("%c\n", '7' - 5);
printf("%d\n", '0' % 10);

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 03-TipoviPodataka.pdf - do stranice: 67

Rjeenja

1. Pri rjeavanju ovakvih zadataka treba se sjetiti koji se najvei/najmanji brojevi mogu prikazati
u varijablama odreenih tipova podataka.
2. Prvi bit za predznak se postavlja na P=1. Time je pitanje predznaka rijeeno (upamtiti: u
IEEE 754 formatu se ne koristi nita to podsjea na tehniku dvojnog komplementa!)

Sada treba odrediti karakteristiku i mantisu. Prvo pretvoriti broj u binarni oblik:
17.7812510 = 10001.110012
Normalizirati:
10001.110012 = 1.000111001 24
BE = 410 K = 4 + 127 = 13110 = 100000112
M = 1.000111001
U 32-bitni registar prepisati P, K, te M (ali BEZ SKRIVENOG BITA!):
1 10000011 00011100100000000000000
Grupirati po tri znamenke s desna na lijevo
11 000 001 100 011 100 100 000 000 000 0002 = 301434400008
Grupirati po etiri znamenke s desna na lijevo
1100 0001 1000 1110 0100 0000 0000 00002 = C18E400016

3. Varijable tipa float pohranjuju se prema IEEE 754 formatu jednostruke preciznosti
C2 B0 00 0016 = 1100 0010 1011 0000 0000 0000 0000 00002
Odrediti predznak: P = 1, stoga je broj negativan.
Odrediti binarni eksponent:
K = 100001012 = 13310 BE = 133 - 127 = 6

Odrediti mantisu (vratiti joj skriveni bit!):


"mantisa bez skrivenog bita" = .011000000000000000000002

M = 1.011000000000000000000002
Rezultat se dobije mnoenjem mantise s 2BE
1.011000000000000000000002 26 = 1011000.02 = 88.010
Ne zaboraviti negativni predznak (jer P=1)
Konani rezultat: -88.0

4. 128.12510

5. -12.62510
3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 03-TipoviPodataka.pdf - do stranice: 67

6. K = 255, u mantisi su svi bitovi postavljeni na nulu. Radi se o prikazu beskonanosti. Budui
da je predznak P=1, konano rjeenje jest: -.

7. K = 255, a u mantisi postoji jedan ili vie bitova koji su postavljeni na jedinicu. U registru je
prikazana vrijednost NaN (Not a Number).

8. K = 0, a u mantisi su svi bitovi postavljeni na 0. Radi se o prikazu broja 0. Budui da je


predznak P=1, konano rjeenje jest: -0.0.

9. K = 0, a u mantisi postoje bitovi koji su postavljeni na jedan. Radi se o prikazu


denormaliziranog broja.
00 68 00 0016 = 0000 0000 0110 1000 0000 0000 0000 00002
BE = -126 (kod denormaliziranog broja ne koristi se formula BE = K - 127)
M = 0.1101 (kod denormaliziranog skriveni bit nije 1, nego 0)
BE
Rezultat se dobije mnoenjem mantise s 2
0.11012 2-126 = 0.812510 2-126 9.55 10-39

10. 80 00 00 0116 = 1000 0000 0000 0000 0000 0000 0000 0001

a) Radi se o prikazu broja u tehnici dvojnog komplementa. Broj je negativan:


1000 0000 0000 0000 0000 0000 0000 0001
0111 1111 1111 1111 1111 1111 1111 1110
+ 1
= 0111 1111 1111 1111 1111 1111 1111 11112 = 214748364710
U registru je prikazan broj -2147483647

b) Radi se o prikazu broja u kojem se ne koristi tehnika dvojnog komplementa. Broj je


pozitivan, unato tome to je prvi bit jedinica:
1000 0000 0000 0000 0000 0000 0000 00012 = 214748364910

c) Radi se o prikazu broja u IEEE 754 formatu: -1.4 10-45

11. Rezultat operacije je -. Rjeenje jest: FF 80 00 0016

12. Rezultat operacije je NaN. Rjeenje jest (jedno od moguih, jer na predavanjima nismo
specificirali koje vrijednosti trebaju imati bitovi u mantisi kad se prikazuje NaN): 7F C0 00
0016
13. Ispravnost vlastitog rjeenja provjeriti izvoenjem programskog odsjeka na raunalu.

4
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 03-TipoviPodataka.pdf - do stranice: 102

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

6. vjebe uz predavanja

1. Odredite najveu moguu relativnu i najveu moguu apsolutnu pogreku koja se moe
oekivati pri pohrani broja 21022 u IEEE 754 formatu jednostruke preciznosti.

2. Gdje se (i zato) u sljedeem odsjeku programa nalaze sintaktike pogreke:


int thin, tall, short;
float which, while, when, why, who;
char single, double, triple;
signed long a777, 7b, _19;

3. Pronaite koje su konstante ispravno, a koje neispravno napisane. Za ispravno napisane


konstante odredite kojeg su tipa i koliko okteta zauzimaju u memoriji:
2 4u 7f 9.1 14.5U 0101u 12.1L 12.1e+22F
12.1e22 12.1Fe-22 12.1E11L 12.1E11u 0x22L 0xABC
0x2f 2F 0x2F.1F 021.1f

4. Napisati sadraj registra u kojem je, prema IEEE 754 standardu za prikaz brojeva u
dvostrukoj preciznosti pohranjen broj -0.2510. Sadraj registra napisati u heksadekadskom
obliku.
5. U registru od 64 bita upisan je broj C0 3D 80 00 00 00 00 0016. Napisati koji je broj
predstavljen u tom registru, ako registar slui za pohranu varijable double x. Rezultat
napisati u dekadskom brojevnom sustavu.
6. Napisati sadraj registra u kojem je, prema IEEE 754 standardu za prikaz brojeva u
dvostrukoj preciznosti pohranjen broj -. Sadraj registra napisati u heksadekadskom
obliku.
7. Napisati sadraj registra u kojem je, prema IEEE 754 standardu za prikaz brojeva u
dvostrukoj preciznosti pohranjena vrijednost NaN. Sadraj registra napisati u
heksadekadskom obliku.
8. Odredite najveu moguu relativnu i najveu moguu apsolutnu pogreku koja se moe
oekivati pri pohrani broja 21022 u IEEE 754 formatu dvostruke preciznosti.

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 03-TipoviPodataka.pdf - do stranice: 102

Rjeenja

1. Najvea mogue relativna pogreka ovisi iskljuivo o broju bitova mantise m. Vodite rauna
o tome da parametar m ukljuuje i skriveni bit. Kod prikaza prema IEEE 754 standardu
jednostruke preciznosti m = 24.
Najvea mogua relativna pogreka iznosi 2-24 6 10-8
Najvea mogua apsolutna pogreka ovisi o parametru m i konkretnom broju x koji se
prikazuje:
Najvea mogua apsolutna pogreka iznosi x 2-24 2 1022 6 10-8 = 1.2
1015

2. int thin, tall, short;


float which, while, when, why, who;
char single, double, triple;
signed long a777, 7b, _19;
U prvom retku se za ime varijable koristi kljuna rije short;
U drugom retku se za ime varijable koristi kljuna rije while;
U treem retku se za ime varijable koristi kljuna rije double;
U etvrtom retku ime varijable 7b zapoinje znamenkom (nije doputeno)

3. 2 signed int - 4 okteta


4u unsigned int - 4 okteta
7f pogreka: nedostaje toka
9.1 double - 8 okteta
14.5U pogreka: ne postoji tip unsigned double
0101u unsigned int u oktalnom obliku - 4 okteta
12.1L long double - 8 okteta
12.1e+22F float - 4 okteta
12.1e22 double - 8 okteta
12.1Fe-22 pogreka: F na pogrenom mjestu
12.1E11L long double - 8 okteta
12.1E11u pogreka: ne postoji tip unsigned double
0x22L long int u heksadekadskom obliku - 4 okteta
0xABC int u heksadekadskom obliku - 4 okteta
0x2f int u heksadekadskom obliku - 4 okteta
2F pogreka: nedostaje toka
0x2F.1F pogreka: ne moe se realni broj zapisati u heksadekadskom obliku
021.1F float, 0 na poetku nema nikakvo znaenje, ali nije pogreka - 4 okteta

4. BFD0000000000000

5. -29.5

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 03-TipoviPodataka.pdf - do stranice: 102

6. FFF0000000000000

7. Prikazano je jedno od moguih rjeenja. Bitno je da su svi bitovi karakteristike postavljeni na


1, te da je barem jedan bit mantise postavljen na 1
FFF8000000000000

8. Najvea mogua relativna pogreka iznosi 2-53 1.1 10-16


Najvea mogua apsolutna pogreka iznosi x 2-53 2.2 106

3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 03-TipoviPodataka.pdf - do stranice: 132

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

7. vjebe uz predavanja

1. Napisati C program koji e s tipkovnice uitati cijeli broj x, a zatim na zaslon ispisati tekst
Istina je ako je uitani broj u intervalu [1, 9] ili je u intervalu [80, 90].

2. Napisati C program koji e s tipkovnice uitati cijeli broj m, a zatim na zaslon ispisati tekst
Istina je ako je uitani broj neparan pozitivan broj.

3. Napisati C program koji e na zaslon ispisati tekst Istina je ako uvjet iz 1. zadatka
nije zadovoljen (napisati jedno rjeenje uz koritenje operatora negacije i jedno rjeenje
bez koritenja operatora negacije).

4. Napisati C program koji e na zaslon ispisati tekst Istina je ako uvjet iz 2. zadatka
nije zadovoljen (napisati jedno rjeenje uz koritenje operatora negacije i jedno rjeenje
bez koritenja operatora negacije).

5. Napisati C program koji e s tipkovnice uitati dva znaka u varijable c1 i c2 tipa char.
Ako su oba uitana znaka velika slova abecede (A-Z) i pri tome su oba znaka
samoglasnici, ispisati tekst Ucitani znakovi su "veliki" samoglasnici
(primijetite da unutar teksta treba dva puta ispisati i dvostruke navodnike).

6. Ispisati tekst Barem jedan od znakova nije veliki samoglasnik ako uvjet iz
5. zadatka nije zadovoljen (napisati jedno rjeenje uz koritenja operatora negacije i
jedno rjeenje bez koritenja operatora negacije).

7. Napisati C program koji e s tipkovnice uitati znak. Ako je uitani znak malo slovo
abecede ili znamenka, ispisati tekst Istina je.

8. Napisati C program koji e s tipkovnice uitati dva znaka. Ako oba uitana znaka
predstavljaju heksadekadske znamenke, ispisati poruku Upisan je ispravan
dvoznamenkasti heksadekadski broj.
9. to je rezultat evaluacije svakog od sljedeih izraza (treba odrediti tip podatka i
vrijednost):
12 / 2*3
15 / 2*3
15. / 2*3
15.f / 2*3
15.f / 2*3.
15 / 2*3.
12 / (2*3)
2 * 2+3
2 * 5%2
2 * (5%2)
(float)15/2/3

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 03-TipoviPodataka.pdf - do stranice: 132

(float)(15/2/3)
(float)(15/2)/3
(float)((15/2)/3)
3.5f * (double)4 + 3 * 5/(double)2

10. to e biti sadraj svake od definiranih varijabli nakon obavljanja sljedeeg


programskog odsjeka (za varijable tipa char treba navesti njihovu numeriku
vrijednost):
char c1, c2;
float f1, f2;
double f3, f4;
c1 = 132.f - (double)2;
f1 = -2147483648.0;
f2 = -2147483645.0;
f3 = -2147483645.0;
f4 = -2147483645.0f;
c2 = 126;

11. to e se ispisati programskim odsjekom:

int i;
i = !0 <= 101 % 100;
printf ("%d\n", i);
i = !1 && !200 || !0 && !100;
printf ("%d\n", i);
i = (!1 && !0 || 100) + 'a' - 'A';
printf ("%d\n", i);
i = 'a' - 'A' + 18;
printf ("%c %d\n", i, i);
i = 10;
printf ("%d\n", i==15);
printf ("%d\n", i);

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 03-TipoviPodataka.pdf - do stranice: 132

Rjeenja

1. #include <stdio.h>
int main (void) {
int x;
scanf("%d", &x);
if (x >= 1 && x <= 9 || x >= 80 && x <= 90) {
printf("Istina je");
}
return 0;
}

2. #include <stdio.h>
int main (void) {
int m;
scanf("%d", &m);
if (m > 0 && m % 2 != 0) {
printf("Istina je");
}
return 0;
}

3. if (!(x >= 1 && x <= 9 || x >= 80 && x <= 90)) {

ili
if ((x < 1 || x > 9) && (x < 80 || x > 90)) {

4. if (!(m > 0 && m % 2 != 0)) {

ili
if (m <= 0 || m % 2 == 0) {

5. #include <stdio.h>
int main (void) {
char c1, c2;
scanf("%c%c", &c1, &c2);
if ((c1 == 'A' ||
c1 == 'E' ||
c1 == 'I' ||
c1 == 'O' ||
c1 == 'U')
&&
(c2 == 'A' ||
c2 == 'E' ||
c2 == 'I' ||
c2 == 'O' ||
c2 == 'U')) {
printf("Ucitani znakovi su \"veliki\" samoglasnici");
}
return 0;
}

3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 03-TipoviPodataka.pdf - do stranice: 132

6. if (!((c1 == 'A' ||
c1 == 'E' ||
c1 == 'I' ||
c1 == 'O' ||
c1 == 'U')
&&
(c2 == 'A' ||
c2 == 'E' ||
c2 == 'I' ||
c2 == 'O' ||
c2 == 'U'))) {

ili

if ( c1 != 'A' &&
c1 != 'E' &&
c1 != 'I' &&
c1 != 'O' &&
c1 != 'U'
||
c2 != 'A' &&
c2 != 'E' &&
c2 != 'I' &&
c2 != 'O' &&
c2 != 'U') {

7. #include <stdio.h>
int main (void) {
char c;
scanf("%c", &c);
if (c >= 'a' && c <= 'z' || c >= '0' && c <= '9') {
printf("Istina je");
}
return 0;
}

8. #include <stdio.h>
int main (void) {
char c1, c2;
scanf("%c%c", &c1, &c2);
if ((c1 >= 'a' && c1 <= 'f' ||
c1 >= 'A' && c1 <= 'F' ||
c1 >= '0' && c1 <= '9')
&&
(c2 >= 'a' && c2 <= 'f' ||
c2 >= 'A' && c2 <= 'F' ||
c2 >= '0' && c2 <= '9')) {
printf("Upisan je ispravan dvoznamenkasti heksadekadski broj");
}
return 0;
}

4
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 03-TipoviPodataka.pdf - do stranice: 132

9. 12 / 2*3
-> 18, int

15 / 2*3
-> 21, int

15. / 2*3
-> 22.5, double

15.f / 2*3
-> 22.5, float

15.f / 2*3.
-> 22.5, double

15 / 2*3.
-> 21.0, double

12 / (2*3)
-> 2, int

2 * 2+3
-> 7, int

2 * 5%2
-> 0, int

2 * (5%2)
-> 2, int

(float)15/2/3
-> 2.5, float

(float)(15/2/3)
-> 2.0, float

(float)(15/2)/3
-> 2.333333, float

(float)((15/2)/3)
-> 2.0, float

3.5f * (double)4 + 3 * 5/(double)2


-> 14.0 + 7.5
-> 21.5, double

10. c1 = -126
c2 = 126
f1 = -2147483648.000000
f2 = -2147483648.000000
f3 = -2147483645.000000
f4 = -2147483648.000000

11. Svoje rjeenje provjerite obavljanjem navedenih naredbi u vlastitom C programu.


5
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 04-OstaliOperatori.pdf - do stranice: 37

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

8. vjebe uz predavanja
1. to e se ispisati sljedeim odsjekom programa:
char c, c1;
c = 'a' / 2*1.1;
printf("%d\n", c);

c1 = 1 + c++;
printf("%d %d\n", c, c1);
c1 = ++c + 12;
printf("%d %c %d %c\n", c, c, c1, c1);

2. to e se ispisati sljedeim odsjekom programa:

int i1 = 5, i2, j1 = 5, j2, k1, k2;


i2 = ++i1 + 3;
printf("%d %d\n", i1, i2);
j2 = j1++ + 3;
printf("%d %d\n", j1, j2);
k1 = i2++ * --j2;
printf("%d %d %d\n", i2, j2, k1);
i2++;
++j2;
k2 = ++i2 * j2++;
printf("%d %d %d\n", i2, j2, k2);

3. to e se ispisati sljedeim programskim odsjekom:


int i = 23, j = 13, k = 11, m;
printf("%d\n", i || j && k);
printf("%d\n", i | j & k);
m = i == j && k;
printf("%d %d\n", m, -!m < 0);
m = i ^ (j=13);
printf("%d %d\n", m, j);
j = 7;
m = 7;
m = i & ~(j==7);
printf("%d\n", m);
m = ~(~k | k);
printf("%d\n", m);

4. to e se ispisati sljedeim programskim odsjekom:


int i = 6;
printf("%d\n", i << 3);
printf("%d\n", i);

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 04-OstaliOperatori.pdf - do stranice: 37

5. to e se ispisati sljedeim odsjekom programa:


int i = 7;
if (i = 3 & 4)
printf("ISTINA JE %d\n", i);
else
printf("NIJE ISTINA %d\n", i);
if (i = 3 && 4)
printf("ISTINA JE %d\n", i);
else
printf("NIJE ISTINA %d\n", i);
printf("Jos jednom upozoravam, NIJE ISTINA\n");
printf("Program zavrsava\n");

6. to e se ispisati obavljanjem sljedeeg programskog odsjeka:


char x, y, z;
x = 2;
y = '1';
z = (y <= x) ? ( ++x ) : ( y += ++x );
printf("%d %c %d %c", x, y, y, z);

7. to e se ispisati obavljanjem sljedeeg programskog odsjeka:


int a = 3, b = 5, c = 9, d;
d = a + (b+=c);
printf("%d %d %d %d", a, b, c, d);

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 04-OstaliOperatori.pdf - do stranice: 37

Rjeenja

6.
Prvo se izraunava y <= x 0
Budui je rezultat "la", izraz ( ++x ) se uope ne izraunava!
Izraunava se samo ( y+= ++x ), a zatim se rezultat tog izraza pridruuje varijabli z.
Zbog prefiksnog oblika ++ operatora, varijabla x se prvo uveava za 1, a zatim se njena
vrijednost dalje koristi u izrazu. Uveana vrijednost varijable x je 3. y += 3 je isto to i y
= y + 3
Konano, x = 3, y = '4' (odnosno 52), z = '4' (odnosno 52)
Ispisat e se: 3 4 52 4

7.
Prvo se izraunava (b+=c) b=14, rezultat cijelog izraza (b+=c) je 14
d = a + 14, tj. d = 17
Ispisat e se:
3 14 9 17

Svoja rjeenja ostalih zadataka provjerite izvoenjem programa na vlastitim raunalima.

3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 33

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

9. vjebe uz predavanja
1. S tipkovnice u char varijablu c uitajte jedan znak. Ako je uitano veliko slovo,
ispisati poruku "To je veliko slovo". Ako je uitano malo slovo, ispisati poruku "To je
malo slovo". Ako je uitana znamenka (0-9), ispisati poruku "To je znamenka". Ako
nije uitano ni slovo ni znamenka, ispisati poruku "To je neki drugi znak".

2. S tipkovnice u char varijablu z1 uitajte znak. Ako uitani znak nije heksadekadska
znamenka (0-9, A-F, a-f), ispisati poruku "Nije dobra znamenka" i zavriti program.
Inae, ispisati dekadski ekvivalent uitane heksadekadske znamenke. Npr. ako je
uitan znak e, treba ispisati 14.

3. Rijeiti pomou petlje s ispitivanjem uvjeta na poetku. Izraunati i na zaslon ispisati


sumu:

1 1 1 1 1 1
- + - + ... + -
1 2 3 4 999 1000
4. Rijeiti pomou petlje s ispitivanjem uvjeta na poetku. S tipkovnice uitavati i
sumirati cijele brojeve dok god su oni djeljivi s 3 ili 7. Na kraju ispisati sumu uitanih
brojeva. Podrazumijeva se da se zadnji broj koji je uitan (onaj zbog kojeg se prekida
uitavanje) ne dodaje u sumu. Vodite rauna o tome da ve i prvi uitani broj moe
biti "neispravan".

5. Rijeiti pomou petlje s ispitivanjem uvjeta na poetku. S tipkovnice uitavati i


sumirati cijele brojeve dok god su oni djeljivi s 3 ili 7. Na kraju ispisati sumu uitanih
brojeva. Podrazumijeva se da se zadnji broj koji je uitan (onaj zbog kojeg se prekida
uitavanje) takoer dodaje u sumu. Vodite rauna o tome da ve i prvi uitani broj
moe biti "neispravan".

6. Rijeiti pomou petlje s ispitivanjem uvjeta na poetku. S tipkovnice uitati cijeli broj
n koji mora biti izmeu 0 i 16 (ukljuivo s granicama). Ako broj nije ispravan, ispisati
odgovarajuu poruku. Ako je broj ispravno upisan, uitati n binarnih znamenki i
ispisati dekadski ekvivalent uitanog binarnog broja (ne primjenjuje se tehnika
dvojnog komplementa, pa je dekadski ekvivalent sigurno pozitivan broj).

Npr., ako je korisnik upisao


4
1
1
0
1
program treba ispisati 13 (jer je 11012 = 1310).
Npr., ako je korisnik upisao
0
program treba ispisati 0.
1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 33

7. Rijeiti pomou petlje s ispitivanjem uvjeta na poetku. Nainite program za


izraunavanje n!. Vrijednost za n uitati s tipkovnice. Ako broj nije ispravan (mora biti
cijeli broj vei ili jednak 0), ispisati odgovarajuu poruku.

8. Rijeiti pomou petlje s ispitivanjem uvjeta na poetku. Nainite program za


pretvaranje nenegativnog (to znai pozitivnog ili nule) cijelog dekadskog broja u
heksadekadski oblik (uzastopnim dijeljenjem sa 16). Nije potrebno provjeravati je li
uitani broj nenegativan. Znamenke heksadekadskog broja smijete ispisati
"obrnutim" redoslijedom. Npr. za uneseni dekadski broj 725, program treba ispisati
5D2. Za uneseni broj 0, program treba ispisati 0.

9. Rijeiti pomou petlje s ispitivanjem uvjeta na poetku. Isto kao prethodni zadatak,
ali za uitani dekadski broj treba ispisati oktalni broj.

10. Rijeiti pomou petlje s ispitivanjem uvjeta na poetku. U varijablu tipa int s
tipkovnice uitati nenegativni cijeli broj (ne treba kontrola je li broj nenegativan). Na
zaslon ispisati binarni sadraj registra te varijable (binarne znamenke se moraju
ispisati ispravnim redoslijedom). Za izdvajanje bitova koristiti bitovni operator & i
operator za posmak bitova prema desno. Moe se pretpostaviti da se za pohranu
int tipa podatka koristi 32 bita.

Uputa:

ako se sadraj registra 01000000000000000000000000010010 posmakne za 31


mjesto u desno, koja binarna znamenka originalnog broja e se pojaviti na krajnjoj
desnoj poziciji?
ako se sadraj registra 01000000000000000000000000010010 posmakne za 30
mjesta u desno, koja binarna znamenka originalnog broja e se pojaviti na krajnjoj
desnoj poziciji?
ako se sadraj registra 01000000000000000000000000010010 posmakne za 29
mjesta u desno, koja binarna znamenka originalnog broja e se pojaviti na krajnjoj
desnoj poziciji? I tako dalje...
vrijednost "krajnje desnog bita" varijable x moe se dobiti operacijom x & 1

11. Rijeiti pomou petlje s ispitivanjem uvjeta na kraju (do-while). Usporediti s rjeenjem
u kojem se koristila petlja s ispitivanjem uvjeta na poetku. Izraunati i na zaslon
ispisati sumu:

1 1 1 1 1 1
- + - + ... + -
1 2 3 4 999 1000

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 33

12. Rijeiti pomou petlje s ispitivanjem uvjeta na kraju (do-while). Usporediti s rjeenjem
u kojem se koristila petlja s ispitivanjem uvjeta na poetku. S tipkovnice uitavati i
sumirati cijele brojeve dok god su oni djeljivi s 3 ili 7. Na kraju ispisati sumu uitanih
brojeva. Podrazumijeva se da se zadnji broj koji je uitan (onaj zbog kojeg se prekida
uitavanje) ne dodaje u sumu. Vodite rauna o tome da ve i prvi uitani broj moe
biti "neispravan".

13. Rijeiti pomou petlje s ispitivanjem uvjeta na kraju (do-while). Usporediti s rjeenjem
u kojem se koristila petlja s ispitivanjem uvjeta na poetku. S tipkovnice uitavati i
sumirati cijele brojeve dok god su oni djeljivi s 3 ili 7. Na kraju ispisati sumu uitanih
brojeva. Podrazumijeva se da se zadnji broj koji je uitan (onaj zbog kojeg se prekida
uitavanje) takoer dodaje u sumu. Vodite rauna o tome da ve i prvi uitani broj
moe biti "neispravan".

14. Napisati dva rjeenja. Jedno rjeenje pomou petlje s ispitivanjem uvjeta na poetku
i jedno rjeenje pomou petlje s ispitivanjem uvjeta na kraju. Usporediti rjeenja. S
tipkovnice uitati nenegativan cijeli broj N (N moe biti nula!). Na zaslon ispisati N
kvocijenata (moe biti niti jedan) u obliku realnih brojeva ukupne irine 7 znakova, s
pet decimala iza decimalne toke):
1 2 3 N
...
2 3 4 N+1
15. S tipkovnice uitavati cijele brojeve dok god ne bude upisan broj manji ili jednak nuli.
Na zaslon ispisati sumu uitanih pozitivnih brojeva podijeljenu s najveim do tada
uitanim pozitivnim brojem i pomnoenu s najmanjim do tada uitanim pozitivnim
brojem. Ako nije upisan niti jedan pozitivni broj, ispisati odgovarajuu poruku.
Primjer: ako korisnik utipka brojeve 2 5 3 2 2 -22, program treba ispisati
5.600000

16. Napiite program koji s tipkovnice uitava dva znaka te ispisuje sve znakove ASCII
tablice koji se nalaze izmeu ta dva znaka. Npr., ako se uitaju znakovi d i k,
program ispisuje defghijk.

3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 33

17. Nainite program koji e ispisati sljedeu tablicu:

A. a b c d e f .F
B. b c d e f g .G
C. c d e f g h .H
D. d e f g h i .I
... itd.
S. s t u v w x .X
T. t u v w x y .Y
U. u v w x y z .Z

Oekuje se da zadatak rijeite pomou dvije programske petlje, a ne npr. ovako:

printf("A. a b c d e f .F\n");
printf("B. b c d e f g .G\n");
printf("C. c d e f g h .H\n");
printf("D. d e f g h i .I\n");
... itd.

18. Nainite program kojim e se uitati lan niza a1 koji mora biti cijeli broj vei od 1.
Nije potrebno provjeravati ispravnost unesenog broja. Ispisati lanove niza a1, a2, a3,
..., an i ukupan broj lanova niza. lan niza ai (za i > 1) izraunava se na sljedei
nain:
ako je ai-1 paran, tada je ai = ai-1 / 2
ako je ai-1 neparan, tada je ai = 3 ai-1 + 1

Niz zavrava lanom an = 2

4
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 33

Rjeenja

1. #include <stdio.h>

int main (void) {


char c;
scanf("%c", &c);
if (c >= 'A' && c <= 'Z')
printf("To je veliko slovo\n");
else if (c >= 'a' && c <= 'z')
printf("To je malo slovo\n");
else if (c >= '0' && c <= '9')
printf("To je znamenka\n");
else
printf("To je neki drugi znak\n");

return 0;
}

Uoite da je sljedee rjeenje loe (objasnite zato), iako "program radi":

Loe rjeenje !!!

#include <stdio.h>

int main (void) {


char c;
scanf("%c", &c);
if (c >= 'A' && c <= 'Z')
printf("To je veliko slovo\n");
if (c >= 'a' && c <= 'z')
printf("To je malo slovo\n");
if (c >= '0' && c <= '9')
printf("To je znamenka\n");
if (! (c >= 'A' && c <= 'Z' ||
c >= 'a' && c <= 'z' ||
c >= '0' && c <= '9') )
printf("To je neki drugi znak\n");

return 0;
}

5
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 33

2. #include <stdio.h>

int main (void) {


char z1;
char dekadskiBroj;
scanf("%c", &z1);
if (z1 >= 'A' && z1 <= 'F' ||
z1 >= 'a' && z1 <= 'f' ||
z1 >= '0' && z1 <= '9' ) {
/* dobar znak */
if (z1 >= 'A' && z1 <= 'F')
dekadskiBroj = z1 - 65 + 10;
else if (z1 >= 'a' && z1 <= 'f')
dekadskiBroj = z1 - 97 + 10;
else
dekadskiBroj = z1 - 48;
printf("heksadekadski %c = dekadski %d\n", z1, dekadskiBroj);
}
else {
printf("Nije dobra znamenka\n");
}
return 0;
}
ili
#include <stdio.h>

int main (void) {


char z1;
scanf("%c", &z1);
if (z1 >= 'A' && z1 <= 'F')
printf("heksadekadski %c = dekadski %d\n", z1, z1 - 65 + 10);
else if (z1 >= 'a' && z1 <= 'f')
printf("heksadekadski %c = dekadski %d\n", z1, z1 - 97 + 10);
else if (z1 >= '0' && z1 <= '9')
printf("heksadekadski %c = dekadski %d\n", z1, z1 - 48);
else
printf("Nije dobra znamenka\n");
return 0;
}

3. #include <stdio.h>
int main (void) {
int i;
float suma, brojnik;
i = 1;
suma = 0.f;
while (i <= 1000) {
brojnik = i % 2 ? 1.f : -1.f;
suma += brojnik / i;
++i;
}
printf("Suma je: %f\n", suma);
return 0;
}

6
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 33

4. #include <stdio.h>
int main (void) {
int suma = 0, x;
scanf("%d", &x);
while (x % 3 == 0 || x % 7 == 0) {
suma += x;
scanf("%d", &x);
}
printf("Suma ucitanih brojeva je %d\n", suma);
return 0;
}

5. #include <stdio.h>
int main (void) {
int suma = 0, x;
scanf("%d", &x);
suma += x;
while (x % 3 == 0 || x % 7 == 0) {
scanf("%d", &x);
suma += x;
}
printf("Suma ucitanih brojeva je %d\n", suma);
return 0;
}

6. #include <stdio.h>
int main (void) {
int n, znamenka, dekadski = 0;
scanf("%d", &n);
if (n < 0 || n > 16) {
printf("Upisali ste neispravan broj\n");
}
else {
while (n > 0) {
scanf("%d", &znamenka);
dekadski = dekadski*2 + znamenka;
--n;
}
printf("%d\n", dekadski);
}
return 0;
}

7. #include <stdio.h>
int main (void) {
int n, fakt = 1;
scanf("%d", &n);
if (n < 0) {
printf("Upisali ste neispravan broj\n");
}
else {
while (n > 1) {
fakt *= n;
--n;
}
printf("%d\n", fakt);
}
return 0;
}

7
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 33

8. #include <stdio.h>
int main (void) {
int n, ostatak;
scanf("%d", &n);
if (n == 0) {
printf("0\n");
}
else {
while (n > 0) {
ostatak = n % 16;
if (ostatak < 10)
printf("%d", ostatak);
else
printf("%c", 'A' + ostatak - 10);
n = n / 16;
}
}
return 0;
}

9. #include <stdio.h>
int main (void) {
int n, ostatak;
scanf("%d", &n);
if (n == 0)
printf("0\n");
else
while (n > 0) {
ostatak = n % 8;
printf("%d", ostatak);
n = n / 8;
}
return 0;
}

10. #include <stdio.h>


int main (void) {
unsigned nt broj;
int kolikoPosmaknutiDesno, pomocna;
scanf("%u", &broj);
printf("Upisali ste broj %d\n", broj);
kolikoPosmaknutiDesno = 31;
while (kolikoPosmaknutiDesno >= 0) {
pomocna = broj >> kolikoPosmaknutiDesno;
/* sada se u varijabli pomocna, na poziciji nultog bita (najmanje
znacajnog bita) nalazi znamenka koja se u varijabli broj nalazi
na poziciji kolikoPosmaknutiDesno. Vrijednost tog bita,
0 ili 1, moze se dobiti tako da se obavi operacija:
pomocna & 000000000000000000000000000000012 */
printf("%d", pomocna & 1);
/* u sljedecem koraku posmaknuti za 30 mjesta,
u sljedecem za 29 mjesta itd. */
--kolikoPosmaknutiDesno;
}
printf("\n");
return 0;
}

8
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 33

Rjeenje 11. zadatka

#include <stdio.h> s petljom s ispitivanjem uvjeta na poetku


int main (void) {
int i; #include <stdio.h>
float suma, brojnik; int main (void) {
i = 1; int i;
suma = 0.f; float suma, brojnik;
do { i = 1;
brojnik = i % 2 ? 1.f : -1.f; suma = 0.f;
while (i <= 1000) {
suma += brojnik / i; brojnik = i % 2 ? 1.f : -1.f;
++i; suma += brojnik / i;
} while (i <= 1000); ++i;
printf("Suma je: %f\n", suma); }
return 0; printf("Suma je: %f\n", suma);
} return 0;
}

Tijelo petlje e se sigurno izvriti tono tisuu puta. Jednako je prikladno koristiti obje vrste petlji.
Napomena: u ovom zadatku bi najprikladnija vrsta petlje bila petlja s poznatim brojem ponavljanja,
koja za sada jo nije obraena na predavanjima i zato se ne koristi u rjeenju.

Rjeenje 12. zadatka

#include <stdio.h> s petljom s ispitivanjem uvjeta na poetku


int main (void) {
int suma = 0, x; #include <stdio.h>
do { int main (void) {
scanf("%d", &x); int suma = 0, x;
if (x % 3 == 0 || x % 7 == 0) scanf("%d", &x);
while (x % 3 == 0 || x % 7 == 0) {
suma += x; suma += x;
} while (x % 3 == 0 || x % 7 == 0); scanf("%d", &x);
}
printf("Suma ucitanih brojeva je %d\n", printf("Suma ucitanih brojeva je %d\n",
suma); suma);
return 0; return 0;
} }

Jedan dio tijela petlje se mora izvriti barem jednom (scanf), a drugi dio tijela petlje (sumiranje) se
moda nee trebati izvriti niti jednom. Jednako je (ne)prikladno koristiti obje vrste petlji.

s petljom s ispitivanjem uvjeta na poetku


Rjeenje 13. zadatka
#include <stdio.h> #include <stdio.h>
int main (void) { int main (void) {
int suma = 0, x;
int suma = 0, x; scanf("%d", &x);
do { suma += x;
scanf("%d", &x); while (x % 3 == 0 || x % 7 == 0) {
suma += x; scanf("%d", &x);
} while (x % 3 == 0 || x % 7 == 0); suma += x;
printf("Suma ucitanih brojeva je %d\n", }
suma); printf("Suma ucitanih brojeva je %d\n",
return 0; suma);
} return 0;
}

9
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 33

Cijelo tijelo petlje se mora izvriti barem jednom. U ovom zadatku oito je prikladnije koristiti petlju s
ispitivanjem uvjeta na kraju.

Rjeenje 14. zadatka


#include <stdio.h>
int main (void) {
int n, i = 1;
scanf("%d", &n);
while (i <= n) {
printf("%7.5f\n", (float)i/(i+1));
++i;
}
return 0;
}

#include <stdio.h>
int main (void) {
int n, i = 1;
scanf("%d", &n);
do {
if (i <= n) {
printf("%7.5f\n", (float)i/(i+1));
++i;
}
} while (i <= n);
return 0;
}

Mogue je da tijelo petlje nee trebati izvriti niti jednom. U ovom zadatku oito je prikladnije koristiti
petlju s ispitivanjem uvjeta na poetku.
Napomena: u ovom zadatku bi najprikladnija vrsta petlje bila petlja s poznatim brojem ponavljanja,
koja za sada jo nije obraena na predavanjima i zato se ne koristi u rjeenju.

Rjeenje 15. zadatka


#include <stdio.h>

int main (void) {


int suma = 0, najmanji, najveci, ucitani;
do {
scanf("%d", &ucitani);
if (ucitani > 0) {
if (suma == 0)
najmanji = najveci = ucitani;
suma += ucitani;
if (ucitani < najmanji)
najmanji = ucitani;
if (ucitani > najveci)
najveci = ucitani;
}
} while (ucitani > 0);
if (suma > 0)
printf("Rezultat je: %f\n", (float)suma / najveci * najmanji);
else
printf("Nije ucitan niti jedan pozitivan broj\n");
return 0;
}

10
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 33

Rjeenje 16. zadatka


#include <stdio.h>

int main(void) { Komentirajte: to e se dogoditi ako se


char c1, c2, c; umjesto znakova d i k s tipkovnice uitaju
scanf("%c %c", &c1, &c2); znakovi k i d ?
c = c1;
while (c <= c2) to e se dogoditi ako se umjesto znakova d
printf("%c", c++); i k s tipkovnice uitaju znakovi d i d ?
printf("\n");
return 0;
}

Rjeenje 17. zadatka Vanjska petlja mijenja vrijednost varijable i od 'A'


#include <stdio.h> do 'U'. Na poetku svakog retka se ispisuje
vrijednost varijable i (u formatu %c), a na kraju
int main(void) { retka ispisuje se slovo koje se u ASCII tablici
char i = 'A', j; nalazi "5 mjesta dalje" od slova koje se ispisalo
while (i <= 'U') {
printf("%c. ", i); na poetku retka, te na samom kraju znak za
j = i + 'a' - 'A'; skok u novi red.
while (j < i + 'a' - 'A' + 6) {
printf("%c ", j++); Unutarnja petlja mijenja vrijednost varijable j od
} "male verzije" slova koje je ispisano na poetku
printf(".%c\n", i++ + 5);
} retka, do slova koje se u ASCII tablici nalazi "6
return 0; mjesta dalje" od poetnog malog slova.
}

Rjeenje 18. zadatka Komentirajte:


#include <stdio.h> to se deava nakon
int main(void) { to se obavi naredba
int ai, brClanova = 0; kojom se ispisao lan
printf("Upisite cijeli broj veci od 1: "); niza 2?
scanf("%d", &ai);
while (ai >= 2) { to e se desiti ako
brClanova = brClanova + 1; korisnik kao prvi lan
printf ("Clan a%d = %d\n", brClanova, ai); niza unese broj 1?
/* izracunaj sljedeci clan */
if (ai % 2 != 0) /* prethodni clan je neparan */
ai = 3 * ai + 1;
else /* prethodni clan je paran */
ai = ai / 2;
}
printf ("Ukupno %d clanova.\n", brClanova);
return 0;
}

11
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 61

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

10. vjebe uz predavanja


1. Dopunsko objanjenje primjera s predavanja

Primjer: Napisati program koji e ispisivati prvih N Fibonaccijevih brojeva

Potrebno je uoiti da za raunanje lana niza fi, treba poznavati lanove niza fi-1 i fi-2. U
svakom koraku petlje u kojem se rauna lan niza fi, iskoristit e se lanovi fi-1 i fi-2, a
zatim e se pripremiti "nove" vrijednosti za fi-1 i fi-2, tako to e se stari lan fi-1 zapisati u
lan fi-2, a netom izraunati lan fi zapisati u lan fi-1.

U programu se lan fi uva u varijabli f, lan fi-1 u varijabli f1, a lan fi-2 u varijabli f0.
Naredbom za selekciju osigurava se da se lanovi poinju izraunavati prema opisanom
principu tek nakon to se obavi ispis lanova niza f0 i f1.

Djelovanje programa moe se lake shvatiti ako se ispie tablica koja pokazuje kako se
varijable mijenjaju u pojedinim koracima petlje. Prikazan je primjer za uitanu vrijednost
n==5:

f0 f1 f
i nakon koraka nakon koraka nakon koraka Ispis u koraku petlje
petlje petlje petlje
0 1 1 1 Fibonnaci (0) = 1
1 1 1 1 Fibonnaci (1) = 1
2 1 2 2 Fibonnaci (2) = 2
3 2 3 3 Fibonnaci (3) = 3
4 3 5 5 Fibonnaci (4) = 5
5 5 8 8 Fibonnaci (5) = 8

2. U varijablu tipa unsigned nt uitati nenegativni cijeli broj. Na zaslon ispisati binarni
sadraj registra te varijable (binarne znamenke se moraju ispisati ispravnim
redoslijedom). Za izdvajanje bitova koristiti operaciju broj & 2n, pri emu se n
mijenja od 31 do 0 (moe se pretpostaviti da se za pohranu int tipa podatka koristi
32 bita). Uputa: vrijednost tipa podatka unsigned treba se uitati po formatu %u

Primjer: ako je korisnik upisao broj 18, na zaslon treba ispisati


00000000000000000000000000010010

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 61

3. S tipkovnice uitati cijeli broj n koji mora biti izmeu 0 i 16 (ukljuivo s granicama).
Ako broj nije ispravan, ispisati odgovarajuu poruku. Nakon toga uitati n binarnih
znamenki i ispisati dekadski ekvivalent uitanog binarnog broja (ne primjenjuje se
tehnika dvojnog komplementa, pa je dekadski ekvivalent sigurno pozitivan broj).

Npr., ako je korisnik upisao


4
1
1
0
1
program treba ispisati 13.

Npr., ako je korisnik upisao


0
program treba ispisati 0.

Rijeiti pomou petlje s poznatim brojem ponavljanja. Je li bolje ovaj zadatak


rjeavati pomou petlje s poznatim brojem ponavljanja ili pomou petlje s
ispitivanjem uvjeta na poetku?

4. Isto kao prethodni zadatak, ali rijeiti pomou petlje s ispitivanjem uvjeta na kraju.
Zato takva vrsta petlje nije pogodna za rjeavanje ovog zadatka?

5. Nainite program koji e s tipkovnice uitati nenegativni cijeli broj iz intervala [0,
4294967295]. Uitani broj treba ispisati u oktalnom obliku. Npr. za uitani broj 250
treba ispisati 00000000372; za uitani broj 4294967295 treba ispisati 37777777777.
Zadatak rijeite tako da grupe od po tri bita pretvarate u oktalne znamenke. Za
odreivanje grupa po tri bita koristite operator posmaka u desno (za tri mjesta) i
bitovni operator &. Uputa: vrijednost tipa podatka unsigned treba se uitati po
formatu %u.

6. Isto kao prethodni zadatak, ali uitani dekadski broj treba pretvoriti u heksadekadski.

7. Napiite program koji uitava dva znaka te ispisuje sve znakove ASCII tablice koji se
nalaze izmeu ta dva znaka. Npr., ako se uitaju znakovi d i k, program ispisuje
defghijk.

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 61

8. Nainite program koji e ispisati sljedeu tablicu:


A. a b c d e f .F
B. b c d e f g .G
C. c d e f g h .H
D. d e f g h i .I
... itd.
S. s t u v w x .X
T. t u v w x y .Y
U. u v w x y z .Z

Oekuje se da zadatak rijeite pomou dvije ugnijeene petlje s poznatim brojem


ponavljanja (for), a ne npr. ovako:

printf("A. a b c d e f .F\n");
printf("B. b c d e f g .G\n");
printf("C. c d e f g h .H\n");
printf("D. d e f g h i .I\n");
... itd.

9. Prepravite program iz prethodnog zadatka tako da se na mjestima gdje bi se ispisao


"mali" samoglasnik, umjesto toga ispie znak '?'.

10. Nainite program za izraunavanje "m povrh n".

m! / ( n! (m - n)! )

Vrijednosti za m i n uitati s tipkovnice uz kontrolu jesu li te vrijednosti ispravno


zadane (cijeli brojevi vei ili jednaki 0, m je vei ili jednak n).

11. Ispiite sve pitagorine trojke iji su lanovi vei od 0 i manji ili jednaki 100. Ispis treba
izgledati ovako (objanjenje: oznaka 3^2 u sljedeem ispisu ima znaenje 32):

1. trojka: 3^2 + 4^2 = 5^2


2. trojka: 4^2 + 3^2 = 5^2
3. trojka: 5^2 + 12^2 = 13^2
4. trojka: 6^2 + 8^2 = 10^2
5. trojka: 7^2 + 24^2 = 25^2
... itd.
101. trojka: 80^2 + 60^2 = 100^2
102. trojka: 84^2 + 13^2 = 85^2
103. trojka: 84^2 + 35^2 = 91^2
104. trojka: 96^2 + 28^2 = 100^2

Uputa: zadatak moete rijeiti tako da pomou tri ugnijeene petlje testirate svaku
kombinaciju 3 cijela broja: 1 1 1; 1 1 2; 1 1 3; ... 1 1 99; 1 1 100; 1 2 1; 1 2 2; ...; 1 2
100; 1 3 1; ... Ispiite samo one kombinacije 3 cijela broja koji zadovoljavaju "uvjet
pitagorine trojke".

3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 61

Rjeenja

Rjeenje 2. zadatka
#include <stdio.h>
#include <math.h>
int main (void) {
unsigned int broj, dva_na_ntu;
int n;
scanf("%u", &broj);
printf("Upisali ste broj %u\n", broj);
for (n = 31; n >= 0; --n) {
dva_na_ntu = (unsigned int)pow(2, n);
/* ako u (broj & dva_na_ntu) postoji bit razlicit od 0,
tada ce (broj & dva_na_ntu) biti razlicit od 0, tj. true */
printf("%d", broj & dva_na_ntu ? 1 : 0);
}
printf("\n");
return 0;
}

Petlja s poznatim brojem ponavljanja je najpogodnija za ovaj sluaj jer je u trenutku kad
petlja zapoinje poznato koliko puta se tijelo te petlje treba obaviti.

Rjeenje 3. zadatka
#include <stdio.h>
int main (void) {
int n, i, znamenka, dekadski = 0;
scanf("%d", &n);
if (n < 0 || n > 16) {
printf("Upisali ste neispravan broj\n");
}
else {
for (i = 0; i < n; ++i) {
scanf("%d", &znamenka);
dekadski = dekadski*2 + znamenka;
}
printf("%d\n", dekadski);
}
return 0;
}

Petlja s poznatim brojem ponavljanja je najpogodnija za ovaj sluaj jer je u trenutku kad
petlja zapoinje poznato koliko puta se tijelo te petlje treba obaviti (uoite, to moe biti i
"nula puta", npr. ako u ovom sluaju korisnik za vrijednost varijable n upie nulu).

4
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 61

Rjeenje 4. zadatka
#include <stdio.h>
int main (void) {
int n, znamenka, dekadski = 0;
scanf("%d", &n);
if (n < 0 || n > 16) {
printf("Upisali ste neispravan broj\n");
}
else {
if (n > 0) {
do {
scanf("%d", &znamenka);
dekadski = dekadski*2 + znamenka;
--n;
} while (n > 0);
}
printf("%d\n", dekadski);
}
return 0;
}

Petlja s ispitivanjem uvjeta na kraju nije pogodna za rjeavanje ovog zadatka, jer je mogue da tijelo petlje
nee biti potrebno obaviti niti jednom (onda kada se za vrijednost varijable n uita 0). Zato je if naredbom
potrebno provjeriti treba li uope zapoeti s obavljanjem petlje.

Rjeenje 5. zadatka
#include <stdio.h>

int main(void) {
unsigned int a;
int i;
printf("Upisite nenegativni cijeli broj a: ");
scanf ("%u", &a); /* za unsigned se kod citanja koristi %u umjesto %d */
for (i = 10; i >= 0; --i) {
printf("%d", a >> 3*i & 0x7);
}
printf ("\n");
return 0;
}

5
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 61

Rjeenje 6. zadatka
#include <stdio.h>

int main(void) {
unsigned int a;
int i, broj;
printf("Upisite nenegativni cijeli broj a: ");
scanf ("%u", &a);
for (i = 7; i >= 0; --i) {
broj = a >> 4*i & 0xF;
if (broj <= 9) {
printf("%d", broj);
/* ili printf("%c", broj + '0'); */
}
else {
printf("%c", broj - 10 + 'A');
}
}
printf ("\n");
return 0;
}

Rjeenje 7. zadatka
#include <stdio.h>

int main(void) {
char c1, c2;
char i;
scanf("%c %c", &c1, &c2);
for (i = c1; i <= c2; ++i) Komentirajte: to e se dogoditi
printf("%c", i);
printf("\n"); ako se uitaju znakovi k i d
return 0;
}

Rjeenje 8. zadatka
#include <stdio.h>

int main(void) {
char i, j;
for (i = 'A'; i <= 'U'; ++i) {
printf("%c. ", i);
for (j = i + 32; j < i + 32 + 6; ++j) {
printf("%c ", j);
}
printf(".%c\n", i + 5);
}
return 0;
}

Vanjska petlja mijenja vrijednost varijable i od 'A' do 'U'. Na poetku svakog retka se ispisuje vrijednost varijable i
(naravno, u formatu %c), a na kraju retka ispisuje se slovo koje se u ASCII tablici nalazi "5 mjesta dalje" od slova koje se
ispisalo na poetku retka.

Unutarnja petlja mijenja vrijednost varijable j od "male verzije" slova koje je ispisano na poetku retka, do slova koje se u
ASCII tablici nalazi "6 mjesta dalje" od poetnog malog slova.

6
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 61

Rjeenje 9. zadatka
#include <stdio.h>

int main(void) {
char i, j;
for (i = 'A'; i <= 'U'; ++i) {
printf("%c. ", i);
for (j = i + 32; j < i + 32 + 6; ++j) {
printf("%c ", j=='a' || j=='e' || j=='i' || j=='o' || j=='u' ? '?' : j);
}
printf(".%c\n", i + 5);
}
return 0;
}

ili
for (j = i + 32; j < i + 32 + 6; ++j) {
if (j=='a' || j=='e' || j=='i' || j=='o' || j=='u')
printf("? ");
else
printf("%c ", j);
}

Rjeenje 10. zadatka


#include <stdio.h>

int main(void) {
int m, n, i;
double brojnik, naziv1, naziv2, mpovrhn;

/* unos vrijednosti za m i n */
printf ("Unesite m i n:");
scanf ("%d %d", &m, &n);
if (m < 0 || n < 0 || m < n)
printf("brojevi su neispravno zadani\n");
else {
brojnik = 1;
for (i = 1; i <= m; ++i)
brojnik *= i;

naziv1 = 1;
for (i = 1; i <= n; ++i)
naziv1 *= i;

naziv2 = 1;
for (i = 1; i <= m-n; ++i)
naziv2 *= i;

mpovrhn = brojnik/(naziv1*naziv2);
printf("%d povrh %d iznosi = %g\n", m, n, mpovrhn);
}
return 0;
}

7
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 61

Rjeenje 11. zadatka


#include <stdio.h>

int main(void) {
int i, j, k;
int n = 0;
for (i=1; i <= 100; ++i)
for (j=1; j <= 100; ++j)
for (k=1; k <= 100; ++k)
if (i*i + j*j == k*k) {
++n;
printf("%d. trojka: %d^2 + %d^2 = %d^2\n", n, i, j, k);
}
return 0;
}

8
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 89

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

11. vjebe uz predavanja


1. Napisati bolje rjeenje (bez break i continue) zadatka sa 65. stranice predavanja.

2. Korisnik uzastopno upisuje cijele brojeve u intervalu [1, 9]. Za svaki uitani broj
ispisati broj rijeima. Zanemariti brojeve koji su izvan doputenog intervala.
Uitavanje prekinuti kada se upie broj nula. Naputak: za odreivanje "naziva" broja
koristiti naredbu switch. Npr.
3
tri
7
sedam
77
zanemarujem
1
jedan
0

3. Korisnik uzastopno upisuje cijele brojeve u intervalu [1, 9]. Za svaki uitani broj
ispisati od kojih je sve brojeva iz tog intervala uitani broj manji. Zanemariti uitane
brojeve koji su izvan doputenog intervala. Uitavanje prekinuti kada se upie broj
nula. Naputak: koristiti naredbu switch s "propadanjem po labelama". Npr.
3
manji je od 4
manji je od 5
manji je od 6
manji je od 7
manji je od 8
manji je od 9
77
zanemarujem
9
8
manji je od 9
0

4. Napiite program koji e ispisati prvih 25 prostih brojeva (uzimajui u obzir definiciju
prema kojoj broj 1 nije primarni broj).

5. Napiite program koji e ispisati sve proste brojeve iz intervala [1000, 10000].

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 89

6. S tipkovnice uitavati cijele brojeve dok god se naizmjence upisuje jedan pozitivan,
jedan negativan, jedan pozitivan broj, itd. Upisivanje pozitivnog broja nakon
pozitivnog ili upisivanje negativnog broja nakon negativnog ili upisivanje nule smatra
se pogrekom. U sluaju takve pogreke program ispisuje sumu svih do tada
ispravno upisanih brojeva (upisanih prije pogreke) i prekida se njegovo izvravanje.
Prvi broj koji se upie s tipkovnice moe biti ili pozitivan ili negativan.

7. Napiite program za izraunavanje n! koji za realizaciju "petlje" koristi goto naredbu.


Napomena: ovaj zadatak slui za vjebu, a ne za demonstraciju naina na koji bi
trebalo rjeavati zadatke s programskim petljama! Programske petlje se u pravilu ne
smiju realizirati pomou naredbe goto!

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 89

Rjeenja

Rjeenje 1. zadatka
#include <stdio.h>

int main(void) {
int x;
do {
printf ("Upisite broj :\n");
scanf("%d", &x);
if (x > 100)
printf("Zanemarujem vrijednost\n");
else if (x >= 0)
printf ("Upisani broj je : %d\n", x);
else
printf("Nedopustena vrijednost\n");
} while (x > 0);
return 0;
}

Rjeenje 2. zadatka
#include <stdio.h>

int main(void) {
int broj;
do {
scanf("%d", &broj);
if (broj != 0)
switch (broj) {
case 1: printf("jedan\n");
break;
case 2: printf("dva\n");
break;
case 3: printf("tri\n");
break;
case 4: printf("cetiri\n");
break;
case 5: printf("pet\n");
break;
case 6: printf("sest\n");
break;
case 7: printf("sedam\n");
break;
case 8: printf("osam\n");
break;
case 9: printf("devet\n");
break;
default: printf("Zanemarujem\n");
break;
}
} while (broj != 0);
return 0;
}

3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 89

Rjeenje 3. zadatka
#include <stdio.h>
int main(void) {
int broj;
do {
scanf("%d", &broj);
if (broj != 0)
switch (broj) {
case 1: printf("manji je od 2\n");
case 2: printf("manji je od 3\n");
case 3: printf("manji je od 4\n");
case 4: printf("manji je od 5\n");
case 5: printf("manji je od 6\n");
case 6: printf("manji je od 7\n");
case 7: printf("manji je od 8\n");
case 8: printf("manji je od 9\n");
case 9: break;
default: printf("Zanemarujem\n");
break;
}
} while (broj != 0);
return 0;
}

Rjeenje 4. zadatka
#include <stdio.h>
#include <math.h>

int main (void) {


int testBroj = 1, pronadjenoProstih = 0;
int i, jestProst;
while (pronadjenoProstih < 25) {
++testBroj;
/* hipoteza: testBroj jest prost*/
jestProst = 1; /* true */
for ( i = 2; i <= pow(testBroj, 0.5); ++i)
if( testBroj % i == 0 ) {
/* oborena je hipoteza da je testBroj prost */
jestProst = 0; /* false */
break;
}
if (jestProst)
printf("%d. %d\n", ++pronadjenoProstih, testBroj);
}
return 0;
}

ili

4
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 89

#include <stdio.h>
#include <math.h>

int main (void) {


int testBroj = 1, pronadjenoProstih = 0;
int i;
while (pronadjenoProstih < 25) {
++testBroj;
i = 2;
while ( i <= pow(testBroj, 0.5) && testBroj % i != 0)
++i;
if( i > pow(testBroj, 0.5) )
/* petlja je uspjela proci kroz sve djeljitelje <= pow(testBroj, 0.5) */
printf("%d. %d\n", ++pronadjenoProstih, testBroj);
}
return 0;
}

Rjeenje 5. zadatka
#include <stdio.h>
#include <math.h>

int main (void) {


int testBroj;
int i, jestProst;
for (testBroj = 1000; testBroj <= 10000; ++testBroj) {
/* hipoteza: testBroj jest prost*/
jestProst = 1; /* true */
for ( i = 2; i <= pow(testBroj, 0.5); ++i)
if( testBroj % i == 0 ) {
/* oborena je hipoteza da je testBroj prost */
jestProst = 0; /* false */
break;
}
if (jestProst)
printf("%d\n", testBroj);
}
return 0;
}

Rjeenje 6. zadatka
#include <stdio.h>

int main(void) {
int suma = 0;
int gotovo = 0;
int prethodni = 0, novi;
do {
scanf("%d", &novi);
if (prethodni == 0 && novi != 0 || prethodni * novi < 0) {
suma += novi;
prethodni = novi;
}
else {
gotovo = 1;
}
} while (!gotovo);

printf("suma = %d\n", suma);


return 0;
}

5
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 05-KontrolneNaredbe.pdf - do stranice: 89

Rjeenje 7. zadatka
#include <stdio.h>

int main(void) {
int n, i = 1;
double f;
scanf("%d", &n);
f = 1.;
opet:
f *= i;
++i;
if (i <= n) goto opet;
printf("%d! = %f\n", n, f);
return 0;
}

6
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 06-Polja.pdf - do stranice: 81

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

13. vjebe uz predavanja


1. S tipkovnice, redak po redak, uitati lanove cjelobrojne matrice dimenzija 4 retka i 3
stupca. Ispisati matricu (u obliku dvodimenzijske tablice), te aritmetiku sredinu
vrijednosti lanova matrice.

2. Definirati i inicijalizirati trodimenzijsko cjelobrojno polje s dimenzijama koje sami


odaberite (npr. 3, 4, 5). Koristiti inicijalizator s vitiastim zagradama (svaki sloj unutar
svojih vitiastih zagrada, svaki redak sloja unutar svojih vitiastih zagrada). Ispiite
polje po slojevima, u sljedeem obliku:
x x x x x
x x x x x
x x x x x
x x x x x

x x x x x
x x x x x
x x x x x
x x x x x

x x x x x
x x x x x
x x x x x
x x x x x

3. Korisnik odabire dimenzije matrice koju eli uitati (brRed, brStup). Broj redaka koje
korisnik moe uitati ne smije biti manji od 1 niti vei od 20, a broj stupaca ne smije
biti manji od 1 niti vei od 10. U matricu treba uitati vrijednosti elemenata i ispisati
matricu. Nakon toga treba retke matrice posmaknuti prema gore: redak i dobiva
vrijednosti iz retka i+1, a posljednji redak matrice dobiva vrijednosti 0-tog retka. Npr.
ako je korisnik uitao: brRed=4, brStup=5, te elemente matrice:
1 2 3 4 5
2 1 3 7 1
8 1 1 4 3
4 2 2 3 3
nakon posmaka redaka, matrica treba izgledati ovako:
2 1 3 7 1
8 1 1 4 3
4 2 2 3 3
1 2 3 4 5

Nakon obavljenog posmaka redaka, ispisati novu matricu. Zadatak rijeite bez
upotrebe pomonog polja.

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 06-Polja.pdf - do stranice: 81

4. Korisnik odabire dimenzije matrice koju eli uitati (brRed, brStup). Broj redaka koje
korisnik moe uitati ne smije biti manji od 1 niti vei od 4, a broj stupaca ne smije biti
manji od 1 niti vei od 5. S tipkovnice se uitaju vrijednosti elemenata matrice. Nakon
toga u elemente u retku brRed zapisati sume stupaca, u elemente u stupcu brStup
zapisati sume redaka, a u element (brRed,brStup) sumu svih elemenata matrice.
Ispisati dobivenu matricu. Npr. ako je korisnik uitao:
brRed=4, brStup=5, te elemente matrice:
1 2 3 4 5
2 1 3 7 1
8 1 1 4 3
4 2 2 3 3
Nakon izrauna, ispis matrice izgleda ovako:
1 2 3 4 5 15
2 1 3 7 1 14
8 1 1 4 3 17
4 2 2 3 3 14
15 6 9 18 12 60
Zadatak rijeite bez upotrebe pomonog polja.

5. S tipkovnice upisati cijeli broj n iz intervala [5, 10]. Generirati kvadratnu matricu
dimenzija n x n kojoj su svi elementi glavne i sporedne dijagonale, elementi prvog i
zadnjeg retka, te prvog i zadnjeg stupca postavljeni na vrijednost 1, a svi ostali
elementi matrice postavljeni na vrijednost 8. Generiranu matricu ispisati na zaslon.
Npr. ako korisnik preko tipkovnice za n unese broj 7, na zaslon treba ispisati:

1 1 1 1 1 1 1
1 1 8 8 8 1 1
1 8 1 8 1 8 1
1 8 8 1 8 8 1
1 8 1 8 1 8 1
1 1 8 8 8 1 1
1 1 1 1 1 1 1

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 06-Polja.pdf - do stranice: 81

6. S tipkovnice, uz kontrolu, uitati broj redaka m i broj stupaca n cjelobrojne matrice.


Broj redaka mora biti iz intervala [3, 6], a broj stupaca iz intervala [4, 10]. Nakon toga
uitati lanove matrice. Jednodimenzijsko polje nps napuniti vrijednostima najmanjih
lanova matrice u pojedinim stupcima, a jednodimenzijsko polje npr napuniti
vrijednostima najmanjih lanova matrice u pojedinim retcima. Ispisati uitanu matricu,
a zatim lanove polja nps i lanove polja npr.

Primjer: ako je uitana matrica (m=4, n=5)


1 2 3 4 5
2 0 3 7 2
8 1 5 4 3
4 2 2 9 3
program treba ispisati:

matrica:
1 2 3 4 5
2 0 3 7 2
8 1 5 4 3
4 2 2 9 3

polje nps:
1 0 2 4 2

polje npr:
1 0 1 2

3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 06-Polja.pdf - do stranice: 81

Rjeenja

Rjeenje 1. zadatka

#include <stdio.h>

#define MAXRED 4
#define MAXSTUP 3

int main(void) {
int i, j, suma = 0;
int mat[MAXRED][MAXSTUP];
for (i = 0; i < MAXRED; ++i) {
/* u i-tom retku obavi sljedece */
for (j = 0; j < MAXSTUP; ++j) {
/* u j-tom stupcu i-tog retka obavi sljedece */
printf("Upisite clan matrice [%d][%d]->", i, j);
scanf("%d", &mat[i][j]);
suma+=mat[i][j];
}
}
for (i = 0; i < MAXRED; ++i) {
for (j = 0; j < MAXSTUP; ++j) {
printf("%5d", mat[i][j]);
}
printf("\n");
}
printf("Aritm. sredina je %f\n", (float)suma/(MAXRED*MAXSTUP));
return 0;
}

4
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 06-Polja.pdf - do stranice: 81

Rjeenje 2. zadatka

#include <stdio.h>

#define MAXSLOJ 3
#define MAXRED 4
#define MAXSTUP 5

int main(void) {
int i, j, k;
int tridim[MAXSLOJ][MAXRED][MAXSTUP] =
{
{ { 101, 102, 103, 104, 105},
{ 106, 107, 108, 109, 110},
{ 111, 112, 113, 114, 115},
{ 116, 117, 118, 119, 120 }
},
{ { 201, 202, 203, 204, 205},
{ 206, 207, 208, 209, 210},
{ 211, 212, 213, 214, 215},
{ 216, 217, 218, 219, 220 }
},
{ { 301, 302, 303, 304, 305},
{ 306, 307, 308, 309, 310},
{ 311, 312, 313, 314, 315},
{ 316, 317, 318, 319, 320 }
}
};

for (i = 0; i < MAXSLOJ; ++i) {


for (j = 0; j < MAXRED; ++j) {
for (k = 0; k < MAXSTUP; ++k)
printf("%d ", tridim[i][j][k]);
printf("\n");
}
printf("\n");
}

return 0;
}

5
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 06-Polja.pdf - do stranice: 81

Rjeenje 3. zadatka

#include <stdio.h>

#define MAXRED 20
#define MAXSTUP 10

int main(void) {
int i, j, m, n, pom;
int mat[MAXRED][MAXSTUP];
do {
printf("Upisite m i n:");
scanf("%d %d", &m, &n);
} while (m < 1 || m > 20 || n < 1 || n > 10);

printf("Upisite clanove matrice po retcima:");

for (i = 0; i < m; ++i)


for (j = 0; j < n; ++j)
scanf("%d", &mat[i][j]);

for (j = 0; j < n; ++j) {


/* u svakom stupcu j obavljaj sljedece */
pom = mat[0][j]; /* spasi j-ti clan iz 0-tog retka */

for (i = 0; i < m-1; ++i)


/* clan u i-tom retku postavi na clan iz (i+1)-vog retka */
mat[i][j] = mat[i+1][j];

mat[m-1][j] = pom; /* u zadnji redak stavi spaseni j-ti clan iz 0-tog retka */
}

printf("\n\nIspis nove matrice:\n");

for (i = 0; i < m; ++i) {


for (j = 0; j < n; ++j)
printf("%d ", mat[i][j]);
printf("\n");
}

return 0;
}

6
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 06-Polja.pdf - do stranice: 81

Rjeenje 4. zadatka

#include <stdio.h>

#define MAXRED 4
#define MAXSTUP 5

int main(void) {
int i, j, m, n;
int mat[MAXRED+1][MAXSTUP+1] = {0};
/* dimenzije su uvecane za 1 jer treba osigurati
prostor za dodatni redak i stupac */
do {
printf("Upisite m i n:");
scanf("%d %d", &m, &n);
} while (m < 1 || m > MAXRED || n < 1 || n > MAXSTUP);

printf("Upisite clanove matrice po retcima:");

for (i = 0; i < m; ++i)


for (j = 0; j < n; ++j)
scanf("%d", &mat[i][j]);

/* kontrolni ispis ucitane matrice */


for (i = 0; i < m; ++i) {
for (j = 0; j < n; ++j)
printf("%4d ", mat[i][j]);
printf("\n");
}

/* proci cemo kroz sve elemente i svaki element


pribrojiti u odgovarajuce elemente u dodatnom retku
i dodatnom stupcu. Clanovi matrice su inicijalizirani
na 0 pri definiciji (inace bi trebalo clanove retka m i
stupca n prvo postaviti na 0) */

for (i = 0; i < m; ++i)


for (j = 0; j < n; ++j) {
/* dodaj ga u zbroj odgovarajuceg retka */
mat[i][n] += mat[i][j];
/* dodaj ga u zbroj odgovarajuceg stupca */
mat[m][j] += mat[i][j];
/* dodaj ga u zbroj svih elemenata matrice */
mat[m][n] += mat[i][j];
}
printf("\n\nIspis nove matrice:\n");
for (i = 0; i <= m; ++i) {
for (j = 0; j <= n; ++j)
printf("%4d ", mat[i][j]);
printf("\n");
}

return 0;

7
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 06-Polja.pdf - do stranice: 81

Rjeenje 5. zadatka

#include <stdio.h>
#define MAXDIM 10

int main(void) {
int i, j, n;
int mat[MAXDIM][MAXDIM];

/* ucitavanje n */
do {
printf("Upisite n:");
scanf("%d", &n);
} while (n < 1 || n > MAXDIM);

/* generiranje matrice */
for (i = 0; i < n; ++i)
for (j = 0; j < n; ++j)
if (i == j || i == n-1-j || j == 0 || i == 0 || j == n-1 || i == n-1)
mat[i][j] = 1;
else
mat[i][j] = 8;

/* ispis matrice */
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j)
printf("%d ", mat[i][j]);
printf("\n");
}

return 0;
}

8
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 06-Polja.pdf - do stranice: 81

Rjeenje 6. zadatka
#include <stdio.h>

#define MAXRED 6
#define MAXSTUP 10

int main(void) {
int i, j, m, n;
int mat[MAXRED][MAXSTUP];
int nps[MAXSTUP], npr[MAXRED];

do {
printf("Upisite m[3,6] i n[4,10]: ");
scanf("%d %d", &m, &n);
} while (m < 3 || m > 6 || n < 4 || n > 10);

printf("Upisite clanove matrice po retcima: ");

for (i = 0; i < m; ++i)


for (j = 0; j < n; ++j)
scanf("%d", &mat[i][j]);

/* odredi najmanji clan u svakom stupcu */


for (j = 0; j < n; ++j) {
/* u svakom stupcu j obavi sljedece */
nps[j] = mat[0][j]; /* pretpostavi da je prvi clan u j-tom stupcu
najmanji clan tog stupca */
for (i = 1; i < m; ++i)
if (mat[i][j] < nps[j])
nps[j] = mat[i][j];
}

/* odredi najmanji clan u svakom retku */


for (i = 0; i < m; ++i) {
/* u svakom retku i obavi sljedece */
npr[i] = mat[i][0]; /* pretpostavi da je prvi clan u i-tom retku
najmanji clan tog retka */
for (j = 1; j < n; ++j)
if (mat[i][j] < npr[i])
npr[i] = mat[i][j];
}

printf("\nmatrica:\n");
for (i = 0; i < m; ++i) {
for (j = 0; j < n; ++j)
printf("%4d", mat[i][j]);
printf("\n");
}

printf("\npolje nps:\n");
for (j = 0; j < n; ++j)
printf("%4d", nps[j]);
printf("\n");

printf("\npolje npr:\n");
for (i = 0; i < m; ++i)
printf("%4d", npr[i]);
printf("\n");

return 0;
}

9
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 07-Pokazivaci.pdf - do stranice: 23

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

14. vjebe uz predavanja

1. to e se ispisati sljedeim programom:

#include <stdio.h>
int main (void) {
int a = 2, x = 10;
int *p = &a;
x += *p * 3;
printf ("%d %d\n", *p, x);
return 0;
}

2. to e se ispisati sljedeim programom:

#include <stdio.h>
int main (void) {
int a = 10, b = 20, *c = &a, *d = &b;
c = &b;
d = &a;
*c = *d + 5;
*d = *c + 3;
printf ("%d %d %d %d\n", a, b, *c+1, *d+1);
return 0;
}

3. to je neispravno u sljedeem programu:


#include <stdio.h>
int main (void) {
int a, b, *c = &a;
short x, y = 10, *z = &x;
c = &b;
z = &y;
*c = 20;
*z = 30;
c = &y;
printf ("%d %d\n", *c, *z);
return 0;
}

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 07-Pokazivaci.pdf - do stranice: 23

4. to e se ispisati sljedeim programom:

#include <stdio.h>
int main (void) {
int polje[4] = {3, 6, 9, 12};
int *p1, *p2, *p3;
p1 = &polje[0];
p2 = &polje[1];
p3 = &polje[3];
printf ("%d %d %d %d %d\n", *p1, *p2, *p3, *(p2 - 1), *p2 - 1);
return 0;
}

5. to e se ispisati sljedeim programom:

#include <stdio.h>
int main (void) {
int polje[4][2] = {3, 6, 9, 12, 15, 18, 21, 24};
int *p1, *p2, *p3;
p1 = &polje[0][0];
p2 = &polje[1][0];
p3 = &polje[3][1];
printf ("%d %d %d %d %d\n", *p1, *p2, *p3, *(p1 + 1), *p1 + 1);
return 0;
}

6. to e se ispisati sljedeim programom:

#include <stdio.h>
int main (void) {
int polje[3][2] = {3, 6, 9, 12, 15, 18};
int *p = polje[0];
int i1 = *p;
int i2 = (*p)++;
int i3 = *p;
int i4 = *++p;
int i5 = *p;
int i6 = *p++;
int i7 = *(p-1);
int i8 = *p;
printf ("%d %d %d %d %d %d %d %d\n", i1, i2, i3, i4, i5, i6, i7, i8);
return 0;
}

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 07-Pokazivaci.pdf - do stranice: 23

7. to e se ispisati sljedeim programom:

#include <stdio.h>
int main (void) {
int polje[3][2] = {1, 2, 3, 4, 5, 6};
int *p = &polje[1][1], i = 5;
printf ("%d\n", *(p + --i));
printf ("%d\n", *--p + --i);
return 0;
}

8. Izrazima zamijenite upitnike u printf naredbi kojom e se ispisati lanovi glavne dijagonale
matrice x. lanovima matrice mora se pristupati preko pokazivaa p:

#include <stdio.h>
int main(void) {
int x[4][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
int *p = &x[0][0];
printf("%d %d %d %d\n", ?, ?, ?, ?);
return 0;
}

9. S tipkovnice upisati cijeli broj n iz intervala [5, 10]. Generirati kvadratnu matricu dimenzija
n x n kojoj su svi elementi glavne i sporedne dijagonale, elementi prvog i zadnjeg retka, te
prvog i zadnjeg stupca postavljeni na vrijednost 1, a svi ostali elementi matrice postavljeni na
vrijednost 8. Generiranu matricu ispisati na zaslon. Elementima matrice pristupati
iskljuivo pomou pokazivaa. Npr. ako korisnik preko tipkovnice za n unese broj 7, na
zaslon treba ispisati:

1 1 1 1 1 1 1
1 1 8 8 8 1 1
1 8 1 8 1 8 1
1 8 8 1 8 8 1
1 8 1 8 1 8 1
1 1 8 8 8 1 1
1 1 1 1 1 1 1

Ovaj zadatak se od zadatka br. 5 iz prethodne vjebe razlikuje jedino u tome to se


elementima matrice mora pristupati pomou pokazivaa.

3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 07-Pokazivaci.pdf - do stranice: 23

10. S tipkovnice, uz kontrolu, uitati broj redaka m i broj stupaca n cjelobrojne matrice. Broj
redaka mora biti iz intervala [3, 6], a broj stupaca iz intervala [4, 10]. Nakon toga uitati
lanove matrice. Zatim jednodimenzijsko polje nps napuniti vrijednostima najmanjih lanova
matrice u pojedinim stupcima, a jednodimenzijsko polje npr napuniti vrijednostima najmanjih
lanova matrice u pojedinim retcima. Ispisati uitanu matricu, a zatim lanove polja nps i
lanove polja npr. lanovima svih polja mora se pristupati iskljuivo preko pokazivaa.

Primjer: ako je uitana matrica (m=4, n=5)


1 2 3 4 5
2 0 3 7 2
8 1 5 4 3
4 2 2 9 3
program treba ispisati:

matrica:
1 2 3 4 5
2 0 3 7 2
8 1 5 4 3
4 2 2 9 3

polje nps:
1 0 2 4 2

polje npr:
1 0 1 2

Ovaj zadatak se od zadatka br. 6 iz prethodne vjebe razlikuje jedino u tome to se elementima
matrice mora pristupati pomou pokazivaa.

4
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 07-Pokazivaci.pdf - do stranice: 23

Rjeenja

Rjeenje 3. zadatka

Neispravna je naredba
c = &y;
c je "pokaziva na short", a pridruuje mu se adresa varijable koja je tipa int.

Rjeenje 8. zadatka
Kad bi bilo doputeno lanovima polja pristupati pomou indeksa, tada bi se napisalo:
printf("%d %d %d %d\n", x[0][0], x[1][1], x[2][2], x[3][3]);

lanovima polja se takoer moe pristupiti preko pokazivaa. Pokaziva p sadri adresu
elementa x[0][0]. Do adrese elementa x[1][1] dolazimo tako da preskoimo sve
elemente u prvom retku (ima ih 1*4) i jedan element iz drugog retka, tj. adresi p pribrojimo
1*4+1. Do adrese elementa x[2][2] dolazimo tako da preskoimo sve elemente u prva
dva retka (ima ih 2*4) i dva elementa iz treeg retka, tj. adresi p pribrojimo 2*4+2. Itd.
printf("%d %d %d %d\n",
*(p+4*0+0), *(p+4*1+1),
*(p+4*2+2), *(p+4*3+3));
ili
printf("%d %d %d %d\n", *(p), *(p+5), *(p+10), *(p+15));

5
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 07-Pokazivaci.pdf - do stranice: 23

Rjeenje 9. zadatka

#include <stdio.h>
#define MAXDIM 10

int main(void) {
int i, j, n;
int mat[MAXDIM][MAXDIM];
int *p = &mat[0][0]; /* ili: int *p = mat[0] */

/* ucitavanje n */
do {
printf("Upisite n:");
scanf("%d", &n);
} while (n < 1 || n > MAXDIM);

/* generiranje matrice */
for (i = 0; i < n; ++i)
for (j = 0; j < n; ++j)
if (i == j || i == n-1-j || j == 0 || i == 0 || j == n-1 || i == n-1)
*(p + i*MAXDIM + j) = 1;
else
*(p + i*MAXDIM + j) = 8;

/* ispis matrice */
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j)
printf("%d ", *(p + i*MAXDIM + j));
printf("\n");
}

return 0;
}

esta pogreka pri rjeavanju ovog zadatka (i slinih zadataka) jest da se lanu matrice
mat[i][j] pokua pristupiti pomou izraza
*(p + i*n + j)
To je pogreno! Redak matrice mat sadri MAXDIM lanova, a ne n lanova. Izraz bi bio
dobar jedino u sluaju kada korisnik za n upie vrijednost jednaku MAXDIM.

6
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 07-Pokazivaci.pdf - do stranice: 23

Rjeenje 10. zadatka

#include <stdio.h>

#define MAXRED 6
#define MAXSTUP 10

int main(void) {
int i, j, m, n;
int mat[MAXRED][MAXSTUP], *pmat = &mat[0][0];
int nps[MAXSTUP], *pnps = &nps[0], npr[MAXRED], *pnpr = &npr[0];

do {
printf("Upisite m[3,6] i n[4,10]: ");
scanf("%d %d", &m, &n);
} while (m < 3 || m > 6 || n < 4 || n > 10);

printf("Upisite clanove matrice po retcima: ");

for (i = 0; i < m; ++i)


for (j = 0; j < n; ++j)
scanf("%d", pmat + i*MAXSTUP+j);

/* odredi najmanji clan u svakom stupcu */


for (j = 0; j < n; ++j) {
/* u svakom stupcu j obavi sljedece */

/* pretpostavi da je prvi clan u j-tom stupcu najmanji clan tog stupca */


*(pnps + j) = *(pmat + 0*MAXSTUP+j);

for (i = 1; i < m; ++i)


if (*(pmat + i*MAXSTUP+j) < *(pnps + j))
*(pnps + j) = *(pmat + i*MAXSTUP+j);
}

/* odredi najmanji clan u svakom retku */


for (i = 0; i < m; ++i) {
/* u svakom retku i obavi sljedece */

/* pretpostavi da je prvi clan u i-tom retku najmanji clan tog retka */


*(pnpr + i) = *(pmat + i*MAXSTUP+0);
for (j = 1; j < n; ++j)
if (*(pmat + i*MAXSTUP+j) < *(pnpr + i))
*(pnpr + i) = *(pmat + i*MAXSTUP+j);
}

printf("\nmatrica:\n");
for (i = 0; i < m; ++i) {
for (j = 0; j < n; ++j)
printf("%4d", *(pmat + i*MAXSTUP+j));
printf("\n");
}
printf("\npolje nps:\n");
for (j = 0; j < n; ++j)
printf("%4d", *(pnps + j));
printf("\n");

printf("\npolje npr:\n");
for (i = 0; i < m; ++i)
printf("%4d", *(pnpr + i));
printf("\n");

return 0;
}

7
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 07-Pokazivaci.pdf - do stranice: 23

este pogreke pri rjeavanju ovog zadatka (i slinih zadataka) jesu da se lanu matrice
mat[i][j] pokua pristupiti pomou izraza
*(pmat + i*n + j)

ili
*(pmat + i*MAXRED + j)

8
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 25

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

15. vjebe uz predavanja

U svim zadacima u kojima se trai definiranje funkcije, treba napisati odgovarajui glavni
program (tj. funkciju main) u kojem ete po potrebi definirati stvarne argumente, s tipkovnice
uitati njihove vrijednosti, pozvati funkciju i ispisati rezultat.
2
1. Napisati funkciju tipa int koja za zadani cijeli broj n (formalni argument je tipa int) vraa n .
2. Provjerite hoete li dobiti ispravan rezultat kada pomou funkcije iz 1. zadatka pokuate
izraunati 500002. Objasnite to se dogodilo.
3. Provjerite hoete li dobiti ispravan rezultat kada pomou funkcije iz 1. zadatka pokuate
2 2
izraunati 2.0 i 3.5 . Objasnite to se dogodilo.
4. Napisati funkciju tipa double koja za zadani cijeli broj n (formalni argument je tipa int) vraa
n2. Provjerite hoete li dobiti ispravan rezultat kada s tom funkcijom pokuate izraunati 22,
500002.
5. Koji je tip funkcije i to vraa funkcija f:
f (void) {
;
;
}
6. Napisati funkciju koja na zaslon ispisuje sve pozitivne parne brojeve izmeu 2 i zadanog
cijelog broja n (u obliku 2 4 6 8 ...). Kojeg je ta funkcija tipa?
7. Napisati funkciju koja na zaslon ispisuje tablicu mnoenja za zadanih m redaka i n stupaca.
Za ispis brojeva koristite format %5d. Npr. ispis za tablicu mnoenja od 3 retka i 4 stupca je:
1 2 3 4
1 1 2 3 4
2 2 4 6 8
3 3 6 9 12
8. Napisati funkciju tipa double naziva nfakt za raunanje n!. Napisati funkciju tipa double
naziva mpovrhn za raunanje m povrh n koja e za izraunavanje koristiti funkciju nfakt. U
glavnom programu (main funkciji) uitavati s tipkovnice cijele brojeve m i n dok god su
ispravno zadani, te izraunavati i ispisivati m povrh n. Prekinuti program kad se zadaju
pogrene vrijednosti za m i n.
9. Napisati funkciju koja na zaslon ispisuje prvih 20 Fibonaccijevih brojeva (svaki lan niza u
novi redak na zaslonu).
10. Napisati funkciju koja na zaslon ispisuje prvih n (n se zadaje kao argument funkcije)
Fibonaccijevih brojeva (svaki lan niza u novi redak na zaslonu).
11. Napisati funkciju tipa int koja vraa broj bajtova koji se koriste za pohranu podatka tipa int.
Napomena: razliiti prevodioci koriste razliiti broj bajtova, te se funkcija koja koristi sljedeu
naredbu return ne moe smatrati ispravnom:

return 4;

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 25

Rjeenja

Rjeenje 1. zadatka

#include <stdio.h>

int kvadrat(int n) {
int kv;
kv = n*n;
return kv;
}

int main(void) {
int arg, rez;
printf("Upisite cijeli broj: ");
scanf("%d", &arg);
rez = kvadrat(arg);
printf("%d na kvadrat jest %d\n", arg, rez);
return 0;
}

Rjeenje 2. zadatka

Ukoliko korisnik unese 50000, u varijablu kv nee se pohraniti ispravan rezultat (2500000000 se
ne moe pohraniti u varijablu kv jer se radi o broju koji prelazi doputeni raspon za tip int).
Funkcija e vratiti broj -1794967296

Rjeenje 3. zadatka

Koristi se ista funkcija, ali drugaiji glavni program, kojim se s tipkovnice uitava realni broj.
int main(void) {
float arg;
int rez;
printf("Upisite realni broj: ");
scanf("%f", &arg);
rez = kvadrat(arg);
printf("%f na kvadrat jest %d\n", arg, rez);

return 0;
}
Ukoliko korisnik unese 2.0, prilikom prijenosa stvarnog argumenta u formalni, obavit e se
konverzija u cijeli broj 2. Funkcija e vratiti cijeli broj 4.

Ukoliko korisnik unese 3.5, prilikom prijenosa stvarnog argumenta u formalni, obavit e se
konverzija u cijeli broj 3. Funkcija e vratiti cijeli broj 9.

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 25

Rjeenje 4. zadatka

#include <stdio.h>

double kvadrat(int n) {
double kv;
kv = (double)n*n;
return kv;
}

int main(void) {
int arg;
double rez;
printf("Upisite cijeli broj: ");
scanf("%d", &arg);
rez = kvadrat(arg);
printf("%d na kvadrat jest %f\n", arg, rez);
return 0;
}

Ovdje je eksplicitna konverzija u tip double stavljena radi toga da se mnoenje obavi u
double domeni. Inae, opet bi se dogodilo da se pri raunanju 500002 dobije negativan
cijeli broj, koji bi se kod pridruivanja varijabli kv pretvorio u realni broj (ali prekasno, jer bi
se kao rezultat dobio negativan realni broj). Testirajte: izbacite cast operator (double) iz
funkcije kvadrat.

Rjeenje 5. zadatka

Funkcija je tipa int, a rezultat funkcije je nedefiniran, odnosno vraa "smee" (vrijednost
koju nije mogue unaprijed odrediti).

Rjeenje 6. zadatka

#include <stdio.h>

void ispisiParne (int n) {


int i;
for (i = 2; i <= n; i += 2)
printf("%d ", i);
}

int main(void) {
int arg;
printf("Upisite cijeli broj: ");
scanf("%d", &arg);
ispisiParne(arg);
return 0;
}

3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 25

Rjeenje 7. zadatka

#include <stdio.h>

void ispisiTablicuMnozenja (int redaka, int stupaca) {


int i, j;
/* ispisi prvi red: "zaglavlje" tablice */
printf(" ");
for (j = 1; j <= stupaca; ++j)
printf("%5d", j);
printf("\n");

/* ispisi tablicu */
for (i = 1; i <= redaka; ++i) {
/* na pocetku svakog retka ispisi redni broj retka */
printf("%5d", i);

for (j = 1; j <= stupaca; ++j)


printf("%5d", i*j);
/* na kraju svakog retka tablice, skoci u novi redak na zaslonu */
printf("\n");
}
}

int main(void) {
int m, n;
printf("Upisite broj redaka: ");
scanf("%d", &m);
printf("Upisite broj stupaca: ");
scanf("%d", &n);
printf("\nTABLICA MNOZENJA:\n");
ispisiTablicuMnozenja(m, n);
return 0;
}

4
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 25

Rjeenje 8. zadatka

#include <stdio.h>

double nfakt (int n) {


int i;
double f;
for (f = 1, i = 1; i <= n; ++i) {
f *= i;
}
return f;
}

double mpovrhn (int m, int n) {


return nfakt(m) / ( nfakt(n) * nfakt(m-n) );
}

int main(void) {
int m, n, mn;
do {
printf ("Upisite m i n: ");
scanf("%d %d", &m, &n);
if (m >= 0 && n >= 0 && m >= n) {
mn = mpovrhn(m, n);
printf("%d povrh %d je: %d\n\n", m, n, mn);
}
} while (m >= 0 && n >= 0 && m >= n);
return 0;
}

Rjeenje 9. zadatka

#include <stdio.h>

void fibonacci (void) {


int i, f0 = 1, f1 = 1, f = 1;
for (i = 0; i < 20; ++i) {
if (i > 1) {
f = f1 + f0;
f0 = f1;
f1 = f;
}
printf ("%d\n", f);
}
}

int main(void) {
fibonacci();
return 0;
}

5
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 25

Rjeenje 9. zadatka - alternativno

U funkciji je definirano polje veliine 20 lanova. Tako se moglo postupiti zato jer je zadano
da treba ispisati tono 20 lanova niza.
#include <stdio.h>

void fibonacci (void) {


int i, fbroj[20];
fbroj[0] = fbroj[1] = 1;

for (i = 2; i < 20; ++i)


fbroj[i] = fbroj[i-1] + fbroj[i-2];
for (i = 0; i < 20; ++i)
printf ("%d\n", fbroj[i]);
}

int main(void) {
fibonacci();
return 0;
}

Rjeenje 10. zadatka

#include <stdio.h>

void fibonacci (int n) {


int i, f0 = 1, f1 = 1, f = 1;
for (i = 0; i < n; ++i) {
if (i > 1) {
f = f1 + f0;
f0 = f1;
f1 = f;
}
printf ("%d\n", f);
}
}

int main(void) {
fibonacci(30);
return 0;
}

Uoiti: zadatak se ne moe rijeiti pomou polja, kao prethodni zadatak, jer se ne zna
unaprijed koliko bi polje u funkciji trebalo biti veliko. Argument n se ne moe pri definiciji
polja koristiti kao dimenzija polja jer dimenzija polja pri definiciji mora biti cjelobrojni
konstantni izraz. Dakle, nije doputeno sljedee:

void fibonacci (int n) {


int i, fbroj[n];

6
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 25

Rjeenje 11. zadatka

#include <stdio.h>

int kolikoInt(void) {
return sizeof(int);
}

int main(void) {
int brojBajtovaZaInt;
brojBajtovaZaInt = kolikoInt();
printf("Ovaj prevodilac za tip int koristi bajtova: %d\n", brojBajtovaZaInt);
return 0;
}

7
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 35

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

16. vjebe uz predavanja

U svim zadacima u kojima se trai definiranje funkcije, treba napisati odgovarajui glavni
program (tj. funkciju main) u kojem ete po potrebi definirati stvarne argumente, s tipkovnice
uitati njihove vrijednosti, pozvati funkciju i ispisati rezultat.
1. Napisati funkciju koja za zadani cijeli broj n vraa n2, ali tako da rezultat vraa preko adrese
koju je dobila kao argument. Funkcija ne smije promijeniti stvarni argument n definiran u
pozivajuem programu. Kojeg je tipa funkcija?
2. Napisati funkciju koja sadraj neke cjelobrojne varijable n iz pozivajueg programa mijenja u
2
n . Dakle, funkcija treba promijeniti vrijednost neke cjelobrojne varijable koja je definirana u
pozivajuem programu. Kojeg je tipa funkcija?
3. Napiite funkciju tipa double koja za zadanu vrijednost tipa double vraa zadanu vrijednost
(tipa double) uveanu za 10.0. Hoete li dobiti ispravan rezultat ako funkciju pozovete sa
stvarnim argumentom tipa int?
4. Napiite funkciju koja zadanoj varijabli tipa double vrijednost uveava za 10.0. Dakle, funkcija
treba promijeniti vrijednost neke realne (double) varijable koja je definirana u pozivajuem
programu. Hoete li dobiti ispravan rezultat ako funkciju pozovete sa stvarnim argumentom
koji je pokaziva na varijablu tipa int?
5. Napiite funkciju koja za dvije zadane vrijednosti tipa int u pozivajui program vraa dvije
vrijednosti: prva vraena vrijednost je vea meu zadanim vrijednostima, a druga vraena
vrijednost je manja meu zadanim vrijednostima. Npr. ako se funkciji zadaju vrijednosti 2 i
3*2, funkcija u pozivajui program mora vratiti vrijednosti 6 i 2.
6. Napiite funkciju koja vrijednosti u zadanim varijablama x, y i z (tipa double) poredava po
veliini, od najvee prema najmanjoj. Drugim rijeima, oekuje se da e funkcija zamijeniti
vrijednosti u varijablama x, y i z tako da vrijednosti budu poredane od najvee prema
najmanjoj. Npr. ako se funkcija pozove za varijable x=2.0, y=4.0, z=3.0, nakon izvravanja
funkcije u varijablama x, y, z se moraju nalaziti vrijednosti x=4.0, y=3.0, z=2.0.
7. Napiite funkciju koja prima pokazivae na dvije varijable tipa int, te vraa pokaziva na onu
od njih koja ima veu vrijednost. Ako varijable imaju istu vrijednost, funkcija vraa pokaziva
na prvu varijablu.
8. Napiite funkciju koja prima pokazivae na dvije varijable tipa int, te vraa vrijednost
varijable koja ima veu vrijednost.

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 35

Rjeenja

Rjeenje 1. zadatka

#include <stdio.h>

void kvad2(int n, int *rez) {


*rez = n*n;
}

int main (void) {


int n, n2;
printf ("Upisite n: ");
scanf("%d", &n);
kvad2(n, &n2);
printf("n na kvadrat (preko adrese) je: %d\n", n2);
printf("Vrijednost varijable n se nije promijenila: %d\n", n);
return 0;
}

Funkcija kvad2 kao drugi argument dobija adresu varijable u koju e zapisati rezultat. Jedina
naredba u toj funkciji upravo to i radi: na adresu kamo pokazuje pokaziva rez, zapisuje n2.
Primijetite da pozivajui program za drugi stvarni argument predaje adresu varijable n2. Tip
funkcije je void, jer funkcija pomou naredbe return ne treba vratiti niti jednu vrijednost.

Ipak, uoite da e uvjet iz programa (da funkcija ne smije promijeniti stvarni argument) biti naruen
ukoliko se funkcija pozove na sljedei nain: kvad2(n, &n);

Rjeenje 2. zadatka

#include <stdio.h>

void kvad3(int *n) {


*n = *n * *n;
}

int main (void) {


int n;
printf ("Upisite n: ");
scanf("%d", &n);
kvad3(&n);
printf("n na kvadrat (promjena originalne varijable preko adrese) je: %d\n",
n);
return 0;
}

Funkcija kvad3 dobija adresu varijable u kojoj se nalazi cijeli broj iji kvadrat treba izraunati, ali se
na tu istu adresu takoer zapisuje i rezultat. Varijabla n iz pozivajueg programa e biti
promijenjena!

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 35

Rjeenje 3. zadatka

#include <stdio.h>

double uvecajZa10(double x) {
return x + 10.;
}

int main (void) {


double arg, rez;
printf("Upisite realni broj: ");
scanf("%lf", &arg);
rez = uvecajZa10(arg);
printf("%f uvecan za 10.0 jest %f\n", arg, rez);
return 0;
}

Sada treba testirati to e se dogoditi ako se funkcija pozove s cjelobrojnim argumentom?

int main (void) {


int arg, rez;
printf("Upisite cijeli broj: ");
scanf("%d", &arg);
rez = uvecajZa10(arg);
printf("%d uvecan za 10.0 jest %d\n", arg, rez);
return 0;
}

Ako se funkcija pozove s cjelobrojnim stvarnim argumentom, dobit e se ispravan rezultat jer se pri
prijenosu stvarnog u formalni argument obavlja implicitna konverzija (int double), a pri
pridruivanju rezultata funkcije varijabli rez obavlja se implicitna konverzija (double int).

3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 35

Rjeenje 4. zadatka

#include <stdio.h>

void uvecajZa10(double *x) {


*x = *x + 10.;
}

int main (void) {


double arg;
printf("Upisite realni broj: ");
scanf("%lf", &arg);
uvecajZa10(&arg);
printf("Uvecana varijabla jest %f\n", arg);
return 0;
}

Sada treba testirati to e se dogoditi ako se funkciji umjesto pokazivaa na varijablu tipa double
preda pokaziva na varijablu tipa int?

int main (void) {


int arg;
printf("Upisite cijeli broj: ");
scanf("%d", &arg);
uvecajZa10(&arg);
printf("Uvecana varijabla jest %d\n", arg);
return 0;
}

Prevodilac e dojaviti upozorenje, ali e program ipak uspjeti prevesti (ako se radi s gcc
prevodiocem, da bi prevoenje uspjelo u ovom primjeru, treba ispustiti opciju -pedantic-errors) .

Rezultat izvravanja programa nee biti ispravan. To se moglo oekivati: funkcija je dobila
adresu int varijable (pokazuje na neko podruje u memoriji od 4 bajta), a "misli" da je dobila
adresu double varijable (adresu koja pokazuje na podruje memorije veliine 8 bajta).

Prekrili smo pravilo koje smo definirali na predavanjima: pokaziva na objekte tipa x smije se
koristiti iskljuivo za pohranu adresa objekata tipa x.

Za vjebu, provjerite kakve ete rezultate dobiti ako u funkciji, umjesto tipa double koristite tip float.

4
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 35

Rjeenje 5. zadatka

#include <stdio.h>

void poredaj(int a, int b, int *veci, int *manji) {


if (a > b) {
*veci = a;
*manji = b;
}
else {
*veci = b;
*manji = a;
}
}

int main (void) {


int veci, manji;
poredaj(2, 3*2, &veci, &manji);
printf("veci i manji su: %d %d\n", veci, manji);
return 0;
}

Rjeenje 6. zadatka

#include <stdio.h>

void poredaj(double *x, double *y, double *z) {


double pom;
if (*x < *y) {
pom = *x;
*x = *y;
*y = pom;
}
if (*x < *z) {
pom = *x;
*x = *z;
*z = pom;
}
if (*y < *z) {
pom = *y;
*y = *z;
*z = pom;
}
}

int main (void) {


double a = 1.0, b = 2.0, c = 3.0;
poredaj(&a, &b, &c);
printf("poredani su: %f %f %f\n", a, b, c);
return 0;
}

5
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 35

Rjeenje 7. zadatka

#include <stdio.h>

int *vratiAdresuVeceg(int *x, int *y) {


if (*x >= *y)
return x;
else
return y;
}

int main (void) {


int a = 5, b = 2;
int *veci;
veci = vratiAdresuVeceg(&a, &b);
printf("veci od zadana dva broja je: %d\n", *veci);
return 0;
}

Rjeenje 8. zadatka

#include <stdio.h>

int vratiVrijednostVeceg(int *x, int *y) {


if (*x > *y)
return *x;
else
return *y;
}

int main (void) {


int a = 5, b = 2;
int veci;
veci = vratiVrijednostVeceg(&a, &b);
printf("veci od zadana dva broja je: %d\n", veci);
return 0;
}

6
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 64

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

17. vjebe uz predavanja

1. Napisati prototip (deklaraciju) za svaku funkciju koja se nalazi u rjeenjima prethodnih vjebi.
2. U modulu mat2.c napisati funkcije iji su prototipovi navedeni u nastavku
int binCoeff(int m, int n); /* izracunava "m povrh n" */
int factorial(int n); /* izracunava n! */
int iabsolute(int n); /* izracunava apsolutnu vrijednost */
float fabsolute(float x); /* izracunava apsolutnu vrijednost */
Prototipove navedenih funkcija smjestiti u datoteku s prototipovima mat2.h.
Funkciju main ("glavni program") smjestiti u modul glavni.c U glavnom programu treba
izraunati i na zaslon ispisati rezultate za:
factorial(0)
factorial(25)
factorial(26)
binCoeff(13, 3)
binCoeff(4, 4)
iabsolute(-5)
iabsolute(0)
iabsolute(-5.7f)
fabsolute(-5)
fabsolute(-5.7f)

Testirati prevoenje na dva naina:


tako da se oba modula prevedu i poveu samo jednim pozivom prevodioca
tako da se zasebno prevede svaki modul, a zatim se dobiveni objektni kd povee u
izvrni kd

koje datoteke su stvorene za vrijeme prevoenja na prvi, odnosno drugi nain?

3. to e se ispisati tijekom izvoenja sljedeeg programa:


#include <stdio.h>

void fun(void) {
int x = 5;
printf("%d\n", x);
x++;
}

int main (void) {


fun();
fun();
return 0;
}

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 64

4. to e se ispisati tijekom izvoenja sljedeeg programa:


#include <stdio.h>

void fun(void) {
static int x = 5;
printf("%d\n", x);
x++;
}

int main (void) {


fun();
fun();
return 0;
}

5. to e se ispisati tijekom izvoenja sljedeeg programa:


#include <stdio.h>

void fun(void) {
static int x = 5;
int y = 5;
printf("%d %d\n", ++x, --y);
}

int main (void) {


fun();
fun();
fun();
return 0;
}

6. to e se ispisati tijekom izvoenja sljedeeg programa:


#include <stdio.h>

int main (void) {


static int i = 5;
int prviPut = 1;
labela:
{
static int i = 10;
int j = 15;
printf("%d %d\n", i, j);
i++;
j++;
}
i++;
printf("%d\n", i);
if (prviPut) {
prviPut = 0;
goto labela;
}
return 0;
}

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 64

7. to e se ispisati tijekom izvoenja sljedeeg programa:


#include <stdio.h>

static int x = 25;

void fun1(void) {
static int x = 5;
printf("%d\n", ++x);
}

void fun2(void) {
int x = 10;
printf("%d\n", ++x);
}

void fun3(void) {
printf("%d\n", ++x);
}

int main (void) {


x++;
{
static int x = 15;
{
int x = 20;
printf("%d\n", x++);
}
printf("%d\n", x++);
}
printf("%d\n", x++);
fun1();
fun2();
fun3();

fun1();
fun2();
fun3();
return 0;
}

U zadacima u kojima se trai definiranje funkcije, treba napisati prototipove funkcija, te


odgovarajui glavni program (tj. funkciju main) u kojem ete po potrebi definirati stvarne
argumente, pozvati funkciju i ispisati rezultat.

3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 64

8. Napisati funkciju zbroji tipa int koja vraa zbroj dvaju zadanih cijelih brojeva i funkciju
mnozi tipa int koja vraa umnoak dvaju zadanih cijelih brojeva. Svaka od funkcija, osim to
izraunava rezultat i vraa ga u pozivajui program, na zaslon ispisuju koliko je puta bila
pozvana. Npr. ako se u glavnom programu obave naredbe:
printf("2*2=%d\n", mnozi(2,2));
printf("2+3=%d\n", zbroji(2,3));
printf("4+2=%d\n", zbroji(4,2));
printf("2*5=%d\n", mnozi(2,5));
printf("2*3=%d\n", mnozi(2,3));
na zaslonu se treba ispisati:

Funkcija mnozi do sada je pozvana 1 puta ispisano u funkciji mnozi


2*2=4 ispisano u glavnom programu
Funkcija zbroji do sada je pozvana 1 puta ispisano u funkciji zbroji
2+3=5 ispisano u glavnom programu
Funkcija zbroji do sada je pozvana 2 puta ispisano u funkciji zbroji
4+2=6 ispisano u glavnom programu
Funkcija mnozi do sada je pozvana 2 puta ispisano u funkciji mnozi
2*5=10 ispisano u glavnom programu
Funkcija mnozi do sada je pozvana 3 puta ispisano u funkciji mnozi
2*3=6 ispisano u glavnom programu

4
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 64

9. Slino kao prethodni zadatak, uz dodatak: svaka od funkcija mora ispisati ne samo koliko je
puta bila pozvana ona sama, nego i koliko puta je bila pozvana bilo koja od funkcija zbroji i
mnozi. Npr. ako se u glavnom programu obave naredbe:
printf("2*2=%d\n", mnozi(2,2));
printf("2+3=%d\n", zbroji(2,3));
printf("4+2=%d\n", zbroji(4,2));
printf("2*5=%d\n", mnozi(2,5));
printf("2*3=%d\n", mnozi(2,3));
na zaslonu se treba ispisati:

Funkcija mnozi do sada je pozvana 1 puta ispisano u funkciji mnozi


Funkcije zbroji i mnozi do sada su pozvane 1 puta ispisano u funkciji mnozi
2*2=4 ispisano u glavnom programu
Funkcija zbroji do sada je pozvana 1 puta ispisano u funkciji zbroji
Funkcije zbroji i mnozi do sada su pozvane 2 puta ispisano u funkciji zbroji
2+3=5 ispisano u glavnom programu
Funkcija zbroji do sada je pozvana 2 puta ispisano u funkciji zbroji
Funkcije zbroji i mnozi do sada su pozvane 3 puta ispisano u funkciji zbroji
4+2=6 ispisano u glavnom programu
Funkcija mnozi do sada je pozvana 2 puta ispisano u funkciji mnozi
Funkcije zbroji i mnozi do sada su pozvane 4 puta ispisano u funkciji mnozi
2*5=10 ispisano u glavnom programu
Funkcija mnozi do sada je pozvana 3 puta ispisano u funkciji mnozi
Funkcije zbroji i mnozi do sada su pozvane 5 puta ispisano u funkciji mnozi
2*3=6 ispisano u glavnom programu

5
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 64

10. to e se ispisati tijekom izvoenja sljedeeg programa:

datoteka s prototipovima proto.h modul modulA.c


void fun1(void); #include <stdio.h>
void fun2(void); #include "proto.h"
void fun3(void); extern int x = 20;
void fun4(void);
void fun2(void) {
x += 4;
printf("%d\n", x);
modul glavni.c }
#include <stdio.h>
#include "proto.h"
extern int x;
modul modulB.c
int main(void) { #include <stdio.h>
int x = 30; #include "proto.h"
x += 2;
printf("%d\n", x); void fun3(void) {
fun1(); static int x = 5;
fun2(); x += 5;
fun3(); printf("%d\n", x);
fun4(); }
fun3();
return 0; void fun4(void) {
} extern int x;
x += 6;
void fun1(void) { printf("%d\n", x);
x += 3; }
printf("%d\n", x);
}

Provjeriti rjeenje izvoenjem programa na vlastitom raunalu i pri tome testirati


prevoenje na dva naina:
tako da se svi moduli prevedu i poveu samo jednim pozivom prevodioca
tako da se zasebno prevede svaki modul, a zatim se dobiveni objektni kd povee u
izvrni kd

6
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 64

Rjeenja

Rjeenje 2. zadatka
modul glavni.c
#include <stdio.h>
#include "mat2.h"

int main(void) {
printf("%d\n", factorial(0));
printf("%d\n", factorial(25));
printf("%d\n", factorial(26)); /* zasto ovdje rezultat nece biti dobar?*/
printf("%d\n", binCoeff(13, 3));
printf("%d\n", binCoeff(4, 4));
printf("%d\n", iabsolute(-5));
printf("%d\n", iabsolute(0));
printf("%d\n", iabsolute(-5.7f));
printf("%3.1f\n", fabsolute(-5));
printf("%3.1f\n", fabsolute(-5.7f));
return 0;
}

modul mat2.c
#include "mat2.h"

int binCoeff(int m, int n) {


return factorial(m) / ( factorial(n) * factorial(m - n) );
}

int factorial(int n) {
int i, f = 1;
for (i = 2; i <= n; i++) {
f = f * i;
}
return f;
}

int iabsolute(int n) {
return n >= 0 ? n : -n;
}

float fabsolute(float x) {
return x >= 0.0f ? x : -x;
}

datoteka s prototipovima funkcija mat2.h

int binCoeff(int m, int n);


int factorial(int n);
int iabsolute(int n);
float fabsolute(float x);

7
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 64

Rjeenje 3. zadatka
Pri svakom pozivu funkcije varijabla x se ponovno inicijalizira. Ispisat e se:
5
5

Rjeenje 4. zadatka
Varijabla x se inicijalizira samo jednom, na poetku izvoenja programa, a njezina vrijednost ostaje
sauvana do kraja izvoenja programa (ne gubi se zavretkom funkcije). Ispisat e se:
5
6

Rjeenje 5. zadatka
Potrebno je uoiti koje su varijable definirane u programu, te na temelju smjetajnog razreda kojem
pripadaju odrediti njihovo podruje vaenja i trajnost.

Varijabla x je statika vrijabla. To znai da se njezina trajnost protee od poetka do zavretka


programa. Varijabla se inicijalizira samo jednom, na poetku izvoenja programa (ak i prije nego
se prvi puta pozove funkcija), te njena vrijednost ostaje sauvana do zavretka programa. Varijabla
x je definirana unutar funkcije, stoga se njezino podruje vaenja (tj. "podruje programa u kojem je
vidljiva") protee od mjesta u funkciji na kojem je definirana do kraja funkcije.

Varijabla y je automatska varijabla. Varijabla se inicijalizira svaki puta kad se pozove funkcija, a
njezina vrijednost se gubi u trenutku zavretka funkcije.

x-trajnost y-trajnost
x-vaenje y-vaenje
void fun(void) {
static int x = 5;
int y = 5;
printf("%d %d\n", ++x, --y);
}

int main (void) {


fun();
fun();
fun();
return 0;
}

8
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 64

Rjeenje 6. zadatka
Ovdje je vano uoiti da postoje dvije varijable naziva i. Na slici koja prikazuje podruja vaenja i
trajnosti, prva varijabla i (definirana na poetku glavnog programa) oznaena je oznakom i1, a
druga oznakom i2.

i1-trajnost i2-trajnost
i1-vaenje
#include <stdio.h>

int main (void) {


static int i = 5;
int prviPut = 1;
labela: i2-vaenje
{
static int i = 10;
int j = 15;
printf("%d %d\n", i, j);
i++;
j++;
}
i++;
printf("%d\n", i);
if (prviPut) {
prviPut = 0;
goto labela;
}
return 0;
}

Rjeenje 7. zadatka
Ovdje je vano uoiti da postoji 5 razliitih varijabli naziva x. Kad se odredi trajnost i podruje
vaenja svake od tih varijabli, zadatak je lako rijeiti.

9
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 64

Rjeenje 8. zadatka
#include <stdio.h>

int zbroji(int x, int y);


int mnozi(int x, int y);

int main (void) {


printf("2*2=%d\n", mnozi(2,2));
printf("2+3=%d\n", zbroji(2,3));
printf("4+2=%d\n", zbroji(4,2));
printf("2*5=%d\n", mnozi(2,5));
printf("2*3=%d\n", mnozi(2,3));
return 0;
}

int zbroji(int x, int y) {


static int brojPoziva = 0;
brojPoziva++;
printf("Funkcija zbroji do sada je pozvana %d puta\n", brojPoziva);
return x+y;
}

int mnozi(int x, int y) {


static int brojPoziva = 0;
brojPoziva++;
printf("Funkcija mnozi do sada je pozvana %d puta\n", brojPoziva);
return x*y;
}

10
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 64

Rjeenje 9. zadatka

#include <stdio.h>

int zbroji(int x, int y);


int mnozi(int x, int y);

int ukupniBrojPoziva = 0;

int main (void) {


printf("2*2=%d\n", mnozi(2,2));
printf("2+3=%d\n", zbroji(2,3));
printf("4+2=%d\n", zbroji(4,2));
printf("2*5=%d\n", mnozi(2,5));
printf("2*3=%d\n", mnozi(2,3));

return 0;
}

int zbroji(int x, int y) {


static int brojPoziva = 0;
brojPoziva++;
ukupniBrojPoziva++;
printf("Funkcija zbroji do sada je pozvana %d puta\n", brojPoziva);
printf("Funkcije zbroji i mnozi do sada su pozvane %d puta\n", ukupniBrojPoziva);
return x+y;
}

int mnozi(int x, int y) {


static int brojPoziva = 0;
brojPoziva++;
ukupniBrojPoziva++;
printf("Funkcija mnozi do sada je pozvana %d puta\n", brojPoziva);
printf("Funkcije zbroji i mnozi do sada su pozvane %d puta\n", ukupniBrojPoziva);
return x*y;
}

Rjeenje 10. zadatka

Ovdje je vano uoiti postojanje definicija triju razliitih varijabli x.

na poetku modula modulA.c definirana je eksterna varijabla x


na poetku funkcije main definirana je automatska varijabla x
na poetku funkcije fun3 definirana je statika varijabla x

Nakon to se odredi trajnost i podruje vaenja svake pojedine varijable, zadatak je lako rijeiti.

11
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 78

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

18. vjebe uz predavanja

U svim zadacima u kojima se trai definiranje funkcije, treba napisati odgovarajui glavni
program (tj. funkciju main) u kojem ete po potrebi definirati stvarne argumente, pozvati funkciju
i ispisati rezultat.

1. Napiite funkciju toApsDim koja vrijednosti elemenata cjelobrojnog jednodimenzijskog polja


mijenja u njihove apsolutne vrijednosti. Funkciju, glavni program i prototipove smjestite u tri
zasebne datoteke. Testirati prevoenje na dva naina:
tako da se oba modula prevedu i poveu samo jednim pozivom prevodioca
tako da se zasebno prevede svaki modul, a zatim se dobiveni objektni kd povee u
izvrni kd

2. Napiite funkciju koja u zadanom jednodimenzijskom realnom polju prebroji koliko lanova je
vee od 0.0, koliko lanova je manje od 0.0 i koliko lanova je jednako 0.0. Dobivene
vrijednosti funkcija mora vratiti u pozivajui program. Funkciju, glavni program i prototipove
smjestite u tri zasebne datoteke. Testirati prevoenje na dva naina:
tako da se oba modula prevedu i poveu samo jednim pozivom prevodioca
tako da se zasebno prevede svaki modul, a zatim se dobiveni objektni kd povee u
izvrni kd

3. to e se ispisati sljedeim programom:

#include <stdio.h>
int main (void) {
int a = 2, x = 10;
int *p = &a;
x += *p * 3;
printf ("%d %d\n", *p, x);
return 0;
}

4. to e se ispisati sljedeim programom:

#include <stdio.h>
void f (int *p) {
printf ("%d %d\n", *p, *p+1);
}
int main (void) {
int polje[6] = {1, 2, 3, 4, 5, 6};
int *pp;
pp = &polje[0];
f(pp++);
f(pp);
f(++pp);
return 0;
}

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 78

5. to e se ispisati sljedeim programom:

#include <stdio.h>
void f (int *p) {
static int i = 2;
printf ("%d\n", *(p + ++i));
}

int main (void) {


int polje[8] = {1, 2, 3, 4, 5, 6, 7, 8};
f(&polje[0]);
f(&polje[0]);
f(&polje[0]);
f(&polje[1]);
return 0;
}

6. to e se ispisati sljedeim programom:

#include <stdio.h>
void f (int *p) {
int i = 3;
printf ("%d\n", *(p + --i));
}
int main (void) {
int polje[6] = {1, 2, 3, 4, 5, 6};
f(&polje[0]);
f(&polje[1]);
f(&polje[2]);
return 0;
}

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 78

Rjeenja

Rjeenje 1. zadatka
glavni.c
#include <stdio.h>
#include "toapsdim.h"

#define MAXDIM 100

int main (void) {


int m;
int polje[MAXDIM];
int i;

printf ("Upisite m manji ili jednak %d: ", MAXDIM);


scanf("%d", &m);
printf ("Upisite elemente polja:\n");
for (i = 0; i < m; ++i)
scanf("%d", &polje[i]);

printf("\nSlijedi ispis ucitanog niza\n\n");


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

toApsDim(&polje[0], m);

printf("\nSlijedi ispis izmijenjenog polja\n\n");


for (i = 0; i < m; ++i)
printf("%d ", polje[i]);
return 0;
}

toapsdim.c
#include "toapsdim.h"

void toApsDim(int *polje, int n) { /* ili (int polje[], int n) */


int i;
for (i = 0; i < n; ++i)
if (*(polje + i) < 0)
*(polje + i) = - *(polje + i);
}

toapsdim.h
void toApsDim(int *polje, int n);

3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 78

Rjeenje 2. zadatka

funkcije.h
void prebroji(float *polje, int n,
int *vecihOdNula, int *manjihOdNula, int *jednakihNula);

funkcije.c
#include "funkcije.h"
void prebroji(float *polje, int n,
int *vecihOdNula, int *manjihOdNula, int *jednakihNula) {
int i;
*vecihOdNula = *manjihOdNula = *jednakihNula = 0;
for (i = 0; i < n; ++i)
if (*(polje + i) < 0.0)
(*manjihOdNula)++;
else if (*(polje + i) == 0.0)
(*jednakihNula)++;
else
(*vecihOdNula)++;
return;
}

test.c
#include <stdio.h>
#include "funkcije.h"

#define MAXDIM 100

int main (void) {


int m;
float polje[MAXDIM];
int i;
int vecih, manjih, jednakih;

printf ("Upisite m manji ili jednak %d: ", MAXDIM);


scanf("%d", &m);
printf ("Upisite elemente polja:\n");
for (i = 0; i < m; ++i)
scanf("%f", &polje[i]);

printf("\n\nSlijedi ispis ucitanog niza\n");


for (i = 0; i < m; ++i)
printf("%f\n", polje[i]);

prebroji(&polje[0], m, &vecih, &manjih, &jednakih);


printf("\nn>0 ima: %d n<0 ima: %d n==0 ima: %d\n",
vecih, manjih, jednakih);
return 0;
}

4
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 102

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

19. vjebe uz predavanja

U svim zadacima u kojima se trai definiranje funkcije, treba napisati odgovarajui glavni
program (tj. funkciju main) u kojem ete po potrebi definirati stvarne argumente, pozvati funkciju
i ispisati rezultat.

1. Napiite funkciju koja u zadanom nizu znakova (jednodimenzijskom polju znakova


terminiranom sa znakom '\0') pronalazi sve samoglasnike i ispisuje ih na zaslon. Npr. za
zadani niz Antigona, ispisuje Aioa.
2. Napiite funkciju koja iz zadanog niza znakova izbacuje sve samoglasnike. Npr. ako se
funkciji zada niz znakova Antigona, funkcija ga mora promijeniti u niz znakova ntgn.

3. to e se ispisati sljedeim programom:

#include <stdio.h>

void f (int *p) {


int i1 = *p;
int i2 = (*p)++;
int i3 = *p;
int i4 = *++p;
int i5 = *p;
int i6 = *p++;
int i7 = *(p-1);
int i8 = *p;
printf ("%d %d %d %d %d %d %d %d\n", i1, i2, i3, i4, i5, i6, i7, i8);
}

int main (void) {


int polje[3][2] = {3, 6, 9, 12, 15, 18};
f(&polje[0][0]);
return 0;
}

4. to e se ispisati sljedeim programom:

#include <stdio.h>

void f (int *p) {


printf ("%d %d\n", *p, *p+1);
}

int main (void) {


int polje[3][2] = {1, 2, 3, 4, 5, 6};
int *pp;
pp = &polje[0][0];
f(pp++);
f(++pp);
return 0;
}

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 102

5. to e se ispisati sljedeim programom:

#include <stdio.h>

void f (int *p) {


static int i = 2;
printf ("%d\n", *(p + ++i));
}

int main (void) {


int polje[3][2] = {1, 2, 3, 4, 5, 6};
f(&polje[0][0]);
f(&polje[0][0]);
f(&polje[0][0]);
return 0;
}

6. to e se ispisati sljedeim programom:

#include <stdio.h>

void f (int *p) {


static int i = 0;
i++;
printf ("%d\n", *(p + --i));
}

int main (void) {


int polje[3][2] = {1, 2, 3, 4, 5, 6};
f(&polje[0][0]);
f(&polje[1][0]);
f(&polje[1][1]);
return 0;
}

7. Napisati funkciju genmat koja u dvodimenzijskom cjelobrojnom polju definiranom s


dimenzijama 4 retka i 4 stupca (funkcija radi iskljuivo s poljima dimenzija 4x4) upisuje etiri
jedinice na glavnu dijagonalu.
U pozivajuem programu definirajte polje, sve lanove polja inicijalizirajte na nulu, pozovite
funkciju genmat, te na zaslon ispiite dobiveni rezultat. Ispis mora izgledati ovako:

1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
Nakon toga pokuajte napisati drugaiji glavni program: definirajte polje od 5 redaka i 5
stupaca, inicijalizirajte sve elemente polja na nulu, pozovite istu funkciju genmat i ispiite
svih 5x5 lanova polja. Moete li predvidjeti kako e izgledati ispis? Zato ispisana tablica ne
izgleda (to bi se moda moglo oekivati) ovako:

1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 0

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 102

8. Napisati funkciju tablica koja u dvodimenzijsko cjelobrojno polje definirano u pozivajuem


programu upisuje tablicu mnoenja od m redaka i n stupaca.
Funkcija mora biti u stanju baratati s poljem proizvoljnih dimenzija. Npr. u glavnom programu
moe se definirati polje dimenzija 20x10, a zatim pozvati funkciju tako da se polje napuni
tablicom mnoenja dimenzija 5x7; ista funkcija takoer mora na ispravan nain generirati npr.
tablicu mnoenja dimenzija 6x4 u polju koje je u glavnom programu definirano s dimenzijama
30x20.
U pozivajuem programu definirati polje, s tipkovnice uitati m i n (sigurno manji ili jednaki
15), pozvati funkciju tablica, te na zaslon ispisati dobivenu tablicu mnoenja. Npr. tablica
mnoenja od 3 retka i 4 stupca izgleda ovako:

1 2 3 4
2 4 6 8
3 6 9 12

9. Napiite funkciju transp za transponiranje cjelobrojne matrice od m redaka i n stupaca.


Funkcija mora transponirati matricu, ali takoer i zamijeniti vrijednosti u varijablama m i n
pozivajueg programa u kojima su evidentirane dimenzije matrice.
U funkciji definirajte, te za transponiranje koristite pomono polje. Ideja za koritenje
pomonog polja: prepisati elemente mat[i][j] iz zadane matrice u elemente pom[j][i]
pomone matrice, a zatim svaki element pom[i][j] upisati natrag u element mat[i][j].
Jednako kao u prethodnom zadatku, funkcija mora biti u stanju baratati s poljem proizvoljnih
dimenzija, uz ogranienje da zadano polje nikad nee imati dimenzije vee od 100x100.
Treba napomenuti da je ovakvo rjeenje (s pomonom matricom) dobro samo za vjebu.
Stoga nainite i bolju (tj. ispravnu) funkciju koja matricu transponira bez koritenja
pomonog polja! Primjer transponiranja matrice bez koritenja pomonog polja prikazan je na
predavanjima o dvodimenzijskim poljima.

3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 102

Rjeenja

Rjeenje 1. zadatka
#include <stdio.h>

void ispisSamoglasa (char niz[]);

int main (void) {


char niz[] = "Antigona";
ispisSamoglasa(niz);
printf("\n");
return 0;
}

void ispisSamoglasa (char niz[]) { /* ili bolje (char *niz) */


int i = 0;
while (niz[i] != '\0') {
if (niz[i] == 'a' || niz[i] == 'A' ||
niz[i] == 'e' || niz[i] == 'E' ||
niz[i] == 'i' || niz[i] == 'I' ||
niz[i] == 'o' || niz[i] == 'O' ||
niz[i] == 'u' || niz[i] == 'U')
printf("%c", niz[i]);
++i;
}
}

4
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 102

Rjeenje 2. zadatka
#include <stdio.h>

void izbaciSamoglase (char *niz);

int main (void) {


char niz[] = "Antigona";
printf("%s\n", niz);
izbaciSamoglase(niz);
printf("%s\n", niz);
return 0;
}

void izbaciSamoglase (char *niz) { /* ili (char niz[]) */


int i = 0, potroseno = 0;
while (*(niz + i) != '\0') {
if (*(niz + i) != 'a' && *(niz + i) != 'A' &&
*(niz + i) != 'e' && *(niz + i) != 'E' &&
*(niz + i) != 'i' && *(niz + i) != 'I' &&
*(niz + i) != 'o' && *(niz + i) != 'O' &&
*(niz + i) != 'u' && *(niz + i) != 'U')
*(niz + potroseno++) = *(niz + i);
++i;
}
*(niz + potroseno) = '\0';
/* VAZNO PITANJE: sto bi bio rezultat bez prethodne naredbe? */
}

Ovdje je vano uoiti da u ovoj funkciji nije mogue* koristiti pomoni niz jer nije poznata najvea
doputena duljina ulaznog niza (a taj je podatak potreban pri definiciji pomonog niza). Tek kad bi
zadatak glasio: napiite funkciju koja iz zadanog niza znakova izbacuje sve samoglasnike, pri emu
zadani niz sigurno nije dulji od 1000 znakova, tada bi postojala mogunost u funkciji koristiti
pomoni niz (tada bi se u funkciji mogao definirati pomoni niz duljine 1001 znaka).

* mogue je npr. uz koritenje funkcije malloc, meutim ta se funkcija ne razmatra na ovom predmetu

5
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 102

Rjeenje 7. zadatka

#include <stdio.h>

void genmat (int *polje) {


int i;
for (i = 0; i < 4; ++i)
*(polje + i + i*4) = 1;
}

int main (void) {


int mat[4][4] = {0};
int i, j;
genmat(&mat[0][0]);
for (i = 0; i < 4; ++i) {
for (j = 0; j < 4; ++j)
printf("%d ", mat[i][j]);
printf("\n");
}
return 0;
}

Rezultat:

1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

Slijedi poziv iste funkcije s poljem koje je definirano s dimenzijama 5x5:


int main () {
int mat[5][5] = {0};
int i, j;
genmat(&mat[0][0]);
for (i = 0; i < 5; ++i) {
for (j = 0; j < 5; ++j)
printf("%d ", mat[i][j]);
printf("\n");
}
return 0;
}

Rezultat:

1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
0 0 0 0 0

Zato? Funkcija genmat u prvom koraku for petlje upie vrijednost 1 na adresu *(polje+0+0), a time
zapravo upie jedinicu u element polja mat[0][0], to je u redu. Meutim, kada u drugom koraku for
petlje upie vrijednost 1 na adresu *(polje+1+1*4), zapravo je upisala jedinicu u element polja
mat[1][0]. Pojednostavljeno, funkcija (zato to je tako napisana) do prvog lana drugog retka dolazi
tako da se preskoi 4 lana polja (a to je istina samo onda kada se funkciji preda polje koje je
definirano tako da mu je broj stupaca jednak 4). Oito, ako funkcija mora baratati s poljima razliitih
dimenzija, mora imati informaciju o stvarnom broju stupaca polja (broju stupaca pri definiciji polja).

6
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 102

Rjeenje 8. zadatka

#include <stdio.h>

#define MAXRED 15
#define MAXSTUP 15

void tablica(int *polje, int m, int n, int brclanstup);

int main (void) {


int m, n;
int polje[MAXRED][MAXSTUP];
int i, j;

printf ("Upisite m i n koji su manji ili jednaki %d i %d: ", MAXRED, MAXSTUP);
scanf("%d %d", &m, &n);
/* ovdje bi, naravno, trebalo napraviti provjeru unesenih vrijednosti */
tablica(&polje[0][0], m, n, MAXSTUP);
printf("\nSlijedi ispis tablice mnozenja\n\n");
for (i = 0; i < m; ++i) {
for (j = 0; j < n; ++j)
printf("%5d", polje[i][j]);
printf("\n");
}
return 0;
}

void tablica(int *polje, int m, int n, int brclanstup) {


int i, j;
for (i = 0; i < m; ++i)
for (j = 0; j < n; ++j)
*(polje + i*brclanstup + j) = (i+1) * (j+1);
}

Vana napomena: esta pogreka koja se pronalazi u rjeenjima ovakvih zadataka jest da se u
funkciji umjesto formalnog argumenta brclanstup koristi simbolika konstanta MAXSTUP
definirana na poetku modula. Zato to ne valja? Zato jer bi tada funkcija ispravno radila samo s
onim poljima koja su definirana tako da im je broj stupaca jednak MAXSTUP. Npr, ako bi se u
glavnom programu definiralo jo jedno polje, drugaijih dimenzija, funkcija u tom polju ne bi mogla
generirati ispravnu tablicu mnoenja.

int polje2[10][10];
...
tablica(&polje2[0][0], 5, 6, 10);
...

Takoer, pogreno je koristiti globalnu ili statiku varijablu za "prijenos" informacije o broju stupaca
u funkciju.

7
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 102

Rjeenje 9. zadatka

#include <stdio.h>

#define MAXRED 20
#define MAXSTUP 20

void transp(int *polje, int *m, int *n, int brclanstup);

int main (void) {


int m, n;
int polje[MAXRED][MAXSTUP];
int i, j;
printf ("Upisite m i n koji su manji ili jednaki %d i %d: ", MAXRED, MAXSTUP);
scanf("%d %d", &m, &n);
printf ("Upisite elemente matrice po retcima:\n");
for (i = 0; i < m; ++i)
for (j = 0; j < n; ++j)
scanf("%d", &polje[i][j]);

printf("\nSlijedi ispis originalne matrice\n\n");


for (i = 0; i < m; ++i) {
for (j = 0; j < n; ++j)
printf("%d ", polje[i][j]);
printf("\n");
}
transp(&polje[0][0], &m, &n, MAXSTUP);

printf("\nSlijedi ispis transponirane matrice\n\n");


for (i = 0; i < m; ++i) {
for (j = 0; j < n; ++j)
printf("%d ", polje[i][j]);
printf("\n");
}

return 0;
}

/*Dimenzije pomocne matrice su 100x100, kako bi se osiguralo da se


i najveca moguca zadana matrica moze prepisati u pomocnu matricu. */
#define MAXDIMPOMOCNA 100

void transp(int *polje, int *pm, int *pn, int brclanstup) {


int pom[MAXDIMPOMOCNA][MAXDIMPOMOCNA];
int i, j;
int pomocna;
for (i = 0; i < *pm; ++i)
for (j = 0; j < *pn; ++j)
pom[j][i] = *(polje + i*brclanstup + j);
/* zamijeni *pm i *pn */
pomocna = *pm;
*pm = *pn;
*pn = pomocna;
for (i = 0; i < *pm; ++i)
for (j = 0; j < *pn; ++j)
*(polje + i*brclanstup + j) = pom[i][j];

8
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 102

/* BOLJA funkcija za transponiranje (bez pomocnog polja) */


void transp(int *polje, int *pm, int *pn, int brclanstup) {
int najvecaDim, i, j, pomClan, pomDim;
najvecaDim = *pm > *pn ? *pm : *pn;
for (i = 0; i < najvecaDim - 1; ++i) {
for (j = i+1; j < najvecaDim; ++j ) {
pomClan = *(polje + i*brclanstup + j);
*(polje + i*brclanstup + j) = *(polje + j*brclanstup + i);
*(polje + j*brclanstup + i) = pomClan;
}
}
pomDim = *pm;
*pm = *pn;
*pn = pomDim;
}

9
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 122

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

20. vjebe uz predavanja

1. Na vlastitom raunalu testirajte sve primjere vezane uz makro definicije s predavanja.

2. Napiite program koji e posluiti kao primjer kojim ete "dokazati" da sljedee macro
definicije nisu ispravno napisane:
#define ZBROJI(a, b) a + b
#define ODUZMI(a, b) (a)-(b)
#define PODIJELI(x, y) (x/y)
#define OPETPODIJELI(x, y) (x)/(y)

Koja pravila pisanja ove macro definicije ne zadovoljavaju? Zatim u svom programu ispravite
navedene macro definicije i ponovo izvedite program.

3. Napisati funkciju traziPrviSamoglas koja u zadanom nizu znakova pronalazi prvi samoglasnik
(malo ili veliko slovo) koji se pojavljuje u nizu. Funkcija u pozivajui program vraa pokaziva
na pronaeni samoglasnik, a ako u nizu nema niti jedan samoglasnik, vraa null pokaziva.
Napisati glavni program koji e pomou funkcije gets uitati niz znakova ne dulji od 80
znakova, te pomou funkcije traziPrviSamoglas pronai te na zaslon ispisati prvi samoglasnik
uitanog niza ili poruku "U nizu nema samoglasnika".

4. Definirati tip podatka tTocka kojim se opisuje jedna toka u pravokutnom koordinatnom
sustavu (x i y su vrijednosti tipa double). Napisati prototip funkcije udaljToc koja za dvije
toke zadane pomou tipa podatka tTocka izraunava udaljenost meu tokama (double).
Definiciju tipa tTocka i prototip funkcije udaljToc napisati u zaglavnoj datoteci geom.h.
Definiciju funkcije udaljToc napisati u modulu geom.c
Napisati glavni program koji e u varijable t1 i t2 tipa tTocka uitati koordinate dviju toaka,
zatim pomou funkcije udaljToc izraunati njihovu udaljenost, te izraunatu vrijednost ispisati
na zaslon.

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 122

Rjeenja

Rjeenje 2. zadatka

#include <stdio.h>

#define ZBROJI(a, b) a + b
#define ODUZMI(a, b) (a)-(b)
#define PODIJELI(x, y) (x/y)
#define OPETPODIJELI(x, y) (x)/(y)

int main(void) {
int c = ZBROJI(3, 2) * 5;
float z = ODUZMI(3.f, 2.f) * 5.f;
int d = PODIJELI(20, 2*5);
float w = 20.f / OPETPODIJELI(10.f, 2.f);

printf("ZBROJI(3, 2) * 5 = 25? dobije se: %d\n", c);


printf("ODUZMI(3.f, 2.f) * 5.f = 5.0? dobije se: %f\n", z);
printf("PODIJELI(20, 2*5) = 2? dobije se: %d\n", d);
printf("20.f / OPETPODIJELI(10.f, 2.f) = 4.0? dobije se: %f\n", w);

return 0;
}

Ispravne macro definicije:


#define ZBROJI(a, b) ((a) + (b))
#define ODUZMI(a, b) ((a)-(b))
#define PODIJELI(x, y) ((x)/(y))
#define OPETPODIJELI(x, y) ((x)/(y))

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 122

Rjeenje 3. zadatka

#include <stdio.h>

char *traziPrviSamoglas(char *niz) {


char *samoglas = NULL;
while (*niz) {
if (*niz == 'a' || *niz == 'A' ||
*niz == 'e' || *niz == 'E' ||
*niz == 'i' || *niz == 'I' ||
*niz == 'o' || *niz == 'O' ||
*niz == 'u' || *niz == 'U') {
samoglas = niz;
break;
}
++niz;
}
return samoglas;
}

int main (void) {


char niz[80+1];
char *samoglas;
gets(niz);
samoglas = traziPrviSamoglas(niz);
if (samoglas != NULL) {
printf("Prvi samoglasnik u nizu \"%s\" je znak \'%c\'\n", niz, *samoglas);
}
else {
printf("U nizu \"%s\" nema samoglasnika\n", niz);
}
return 0;
}

Funkcija se moe vrlo lako prepraviti tako da pronalazi posljednji samoglasnik u nizu.

3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 08-Funkcije.pdf - do stranice: 122

Rjeenje 4. zadatka

glavni.c
#include <stdio.h>
#include "geom.h"

int main(void) {
tTocka t1, t2;

printf("Upisite koordinate tocke t1:");


scanf("%lf%lf", &t1.x, &t1.y);
printf("Upisite koordinate tocke t2:");
scanf("%lf%lf", &t2.x, &t2.y);

printf("Udaljenost izmedju t1 i t2 je %f\n", udaljToc(t1, t2));


return 0;
}

geom.h
typedef struct {
double x;
double y;
} tTocka;

double udaljToc (tTocka t1, tTocka t2);

geom.c
#include <math.h>
#include "geom.h"

double udaljToc (tTocka t1, tTocka t2) {


return sqrt(pow(t2.x - t1.x, 2.) + pow(t2.y - t1.y, 2.));
}

4
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 09-UgradjeneFunkcije.pdf - do stranice: 38

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

21. vjebe uz predavanja

U svim zadacima u kojima se trai definiranje funkcije, treba napisati odgovarajui glavni
program (tj. funkciju main) u kojem ete po potrebi definirati stvarne argumente, pozvati funkciju
i ispisati rezultat.
1. Na svom raunalu testirajte primjere s predavanja vezane uz funkcije fabs i abs, te primjer
kojim je prikazana razlika izmeu funkcije exit i naredbe return.
2. S tipkovnice uitati cijeli broj n uz kontrolu da je 3 n 20. Na sluajan nain odabrati n
velikih slova (meu znakovima A-Z) i ispisati ih na zaslon.
3. Generirati 10 000 cijelih brojeva iz zatvorenog intervala [50,60]. Na zaslon ispisati frekvenciju
pojavljivanja svakog od brojeva.
50 se pojavio 1100 puta
51 se pojavio 987 puta
...
60 se pojavio 1083 puta
4. Napisati funkciju koja u zadano dvodimenzijsko cjelobrojno polje "ispaljuje zadani broj
hitaca". Element polja u kojeg pojedini hitac pogaa odabire se na sluajan nain (funkcija na
sluajan nain odabere redak elementa, a zatim na sluajan nain odabere stupac
elementa). Vrijednost elementa polja koji je "pogoen", funkcija uveava se za jedan.
Funkcija treba inicijalizirati generator pseudosluajnih brojeva samo pri prvom pozivu, a prije
nego pone "gaati" polje, mora elemente polja inicijalizirati na vrijednost 0.
U glavnom programu definirati polje maksimalnih dimenzija 10x10, s tipkovnice uitati m i n,
te "broj "hitaca h koje u polje dimenzija mxn funkcija treba "ispaliti". Pozvati funkciju te u
obliku tablice ispisati sadraj polja nakon to je "pogoeno" s h hitaca, a zatim u nastavku
programa to ponoviti (s istim argumentima).
to e se dogoditi ako funkciju prepravite tako da se generator pseudosluajnih brojeva
inicijalizira pri svakom pozivu funkcije? Zato se tada (u najveem broju sluajeva) dobiju
dva jednaka polja?

5. Napisati funkciju obrniNiz koja obre niz znakova. Npr. niz znakova "ABCDE" mijenja u niz
znakova "EDCBA". Uputa: 1. znak zamijeniti s n-tim znakom, 2. znak zamijeniti s n-1-vim
znakom, itd.
6. Napisati funkciju umetniZnak koja na poetak zadanog niza znakova umee zadani znak.
Funkcija moe raunati na to da je za niz u pozivajuem programu rezervirano dovoljno
memorije. U funkciji se ne smiju koristiti funkcije iz <string.h>.
7. Napisati funkciju umetniZnakove koja ispred svakog znaka zadanog niza umee zadani znak
(npr, ako se funkciji zada niz "Studeni" i znak 'X', funkcija mijenja niz u "XSXtXuXdXeXnXi").
Funkcija moe raunati na to da je za niz u pozivajuem programu rezervirano dovoljno
memorije. U funkciji se ne smiju koristiti funkcije iz <string.h>.
8. Napisati vlastitu funkciju myStrcpy koja obavlja isto to i funkcija strcpy definirana u string.h.
U funkciji se ne smiju koristiti funkcije iz <string.h>.
9. Napisati vlastitu funkciju myStrlen koja obavlja isto to i funkcija strlen definirana u string.h
(jedina razlika neka bude u tome to myStrlen vraa int, umjesto size_t). U funkciji se ne
smiju koristiti funkcije iz <string.h>.

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 09-UgradjeneFunkcije.pdf - do stranice: 38

10. Napisati vlastitu funkciju myStrcat koja obavlja isto to i funkcija strcat definirana u string.h. U
funkciji se ne smiju koristiti funkcije iz <string.h>.
11. Napisati funkciju koja kao rezultat vraa koliko puta se niz s2 pojavljuje unutar niza s1. U
glavnom programu pomou funkcije gets uitati dva niza, pozvati funkciju i ispisati rezultat. U
funkciji je doputeno koristiti funkcije iz biblioteke <string.h>.

12. to e biti sadraj nizova znakova s1, s2 i s3 nakon obavljanja odsjeka programa:

char s1[20] = "ef123f156xyz", s2[20]="ABCD", s3[20];


strcat(strcat(s2, "abc"), strcpy(s3, strstr(strchr(s1, '2'), "f1")));
13. Napisati macro MYTOUPPER koja obavlja isto to i funkcija toupper definirana u <ctype.h>.
Napisati glavni program koji e pomou funkcije gets uitati niz znakova (sigurno ne dulji od
40 znakova), te na zaslon ispisati uitani niz, ali tako da su sva mala slova pretvorena u
velika. Za pretvaranje malih slova u velika koristiti macro MYTOUPPER.
14. Napisati vlastitu funkciju myStrchr koja obavlja isto to i funkcija strchr definirana u
<string.h>. U funkciji se ne smiju koristiti funkcije iz <string.h>.
15. Napisati vlastitu funkciju myStrstr koja obavlja isto to i funkcija strstr definirana u
<string.h>. U funkciji se ne smiju koristiti funkcije iz <string.h>.
16. Napisati program kojim e se generirati 1000 sluajnih znakova ije su ASCII vrijednosti u
intervalu [32,126]. Na zaslon ispisati koliko dobivenih znakova je slovo, koliko dobivenih
znakova je znamenka, a koliko dobivenih znakova nije niti znamenka niti slovo. Za ispitivanje
znakova koristite ugraene macro definicije iz <ctype.h>.

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 09-UgradjeneFunkcije.pdf - do stranice: 38

Rjeenja

Rjeenje 2. zadatka
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main (void) {


int n, i, slucajni;
char ascii;
do {
printf("Upisite n:");
scanf("%d", &n);
}
while (n < 3 || n > 20);

srand ((unsigned) time(NULL));

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


slucajni = rand();
/* interval [a=0, b=RAND_MAX] preslikati u interval [c='A', d='Z'] */
ascii = (float) slucajni / (RAND_MAX+1) * ('Z'-'A'+1) + 'A';
/* moze i ovako: ascii = slucajni % ('Z' - 'A' + 1) + 'A'; */
printf("%c", ascii);
}
printf("\n");
}

Rjeenje 3. zadatka
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define DG 50
#define GG 60

int main (void) {


int i, slucajni, slucajni2;
int polje[GG-DG+1] = {0};

srand ((unsigned) time(NULL));


for (i = 0; i < 1000; ++i) {
slucajni = rand();
/* interval [a=0, b=RAND_MAX] preslikati u interval [c=DG, d=GG] */
slucajni2 = (float) slucajni / (RAND_MAX+1) * (GG-DG+1) + DG;
/* moze i ovako: slucajni2 = slucajni % (GG - DG + 1) + DG; */
polje[slucajni2-DG]++;
}
for (i = DG; i <= GG; ++i) {
printf("%d se pojavio %d puta\n", i, polje[i-DG]);
}
}

3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 09-UgradjeneFunkcije.pdf - do stranice: 38

Rjeenje 4. zadatka
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define MAXR 10
#define MAXS 10

void gadjaj(int *polje, int m, int n, int maxstup, int brojHitaca) {


static int generatorInicijaliziran = 0;
int i, j, redak, stupac;
if (! generatorInicijaliziran) {
srand ((unsigned) time(NULL));
generatorInicijaliziran = 1;
}

for (i = 0; i < m; ++i)


for (j = 0; j < n; ++j)
*(polje + i*maxstup + j) = 0;

for (i = 0; i < brojHitaca; ++i) {


/* slucajni redak */
redak = rand() % m;
/* slucajni stupac */
stupac = rand() % n;
*(polje + redak * maxstup + stupac) += 1;
}
}

void ispisiPolje(int *polje, int m, int n, int maxstup) {


int i, j;
for (i = 0; i < m; ++i) {
for (j = 0; j < n; ++j)
printf("%5d", *(polje + i*maxstup + j));
printf("\n");
}
}

int main (void) {


int m, n, brojHitaca;
int polje[MAXR][MAXS];
printf("Upisite m, n i broj hitaca -> ");
scanf("%d %d %d", &m, &n, &brojHitaca);

gadjaj(&polje[0][0], m, n, MAXS, brojHitaca);


ispisiPolje(&polje[0][0], m, n, MAXS);

printf("\n");

gadjaj(&polje[0][0], m, n, MAXS, brojHitaca);


ispisiPolje(&polje[0][0], m, n, MAXS);
return 0;
}

4
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 09-UgradjeneFunkcije.pdf - do stranice: 38

Funkcija e pri svakom pozivu ponovo inicijalizirati generator ako se blok naredbi

if (! generatorInicijaliziran) {
srand ((unsigned) time(NULL));
generatorInicijaliziran = 1;
}
zamijeni sa
srand ((unsigned) time(NULL));

Druga inicijalizacija generatora e se tada dogoditi vrlo vjerojatno s istim poetnim uvjetima-seed
(jer e se oba poziva funkcije vrlo vjerojatno obaviti unutar iste sekunde), stoga e i nizovi
generiranih pseudosluajnih brojeva biti jednaki.

Rjeenje 5. zadatka
#include <stdio.h>
#define MAX 20

void obrniNiz(char *niz);

int main (void) {


char niz[MAX+1];
printf ("Upisite niz znakova (ne dulji od %d znakova):", MAX);
gets(niz);
printf("%s\n", niz);
obrniNiz(niz);
printf("%s\n", niz);
/* VAZNO PITANJE: */
/* zasto funkciju nije moguce pozvati ovako: obrniNiz("Prosinac"); */
return 0;
}

void obrniNiz(char *niz) {


int i;
char pom;
int duljina = 0;
while (*(niz + duljina))
duljina++;
for (i = 0; i < duljina/2; ++i) {
pom = niz[i];
niz[i] = niz[duljina-1-i];
niz[duljina-1-i] = pom;
}
}

5
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 09-UgradjeneFunkcije.pdf - do stranice: 38

Rjeenje 6. zadatka
#include <stdio.h>
#include <string.h>

void umetniZnak(char *niz, char c);

int main (void) {


char niz[7+1+1];
strcpy(niz, "Studeni");
umetniZnak(niz, 'A');
printf("%s\n", niz);
/* VAZNO PITANJE: */
/* zasto funkciju nije moguce pozvati ovako: umetniZnak("Studeni", 'A'); */
return 0;
}

void umetniZnak(char *niz, char c) {


int i;
int duljina = 0;
while (*(niz + duljina))
++duljina;
niz[duljina+1] = '\0';
for (i = duljina; i > 0; --i)
niz[i] = niz[i-1];
niz[0] = c;
}

Rjeenje 7. zadatka
#include <stdio.h>
#include <string.h>

void umetniZnakove(char *niz, char c);

int main (void) {


char niz[7+1+7];
strcpy(niz, "Studeni");
umetniZnakove(niz, 'X');
printf("%s\n", niz);
/* VAZNO PITANJE: */
/* zasto funkciju nije moguce pozvati ovako: umetniZnakove("Studeni", 'A'); */
return 0;
}

void umetniZnakove(char *niz, char c) {


int i;
int duljina = 0;
while (*(niz + duljina))
++duljina;
*(niz + 2*duljina) = '\0';
for (i = duljina - 1; i >= 0; --i) {
*(niz + 2*i + 1) = *(niz + i);
*(niz + 2*i) = c;
}
}

6
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 09-UgradjeneFunkcije.pdf - do stranice: 38

Rjeenje 8. zadatka
#include <stdio.h>

char *myStrcpy(char *cilj, char *izvor);

int main (void) {


char ciljniNiz[20+1];
char *izvorniNiz = "Niz znakova";
myStrcpy(ciljniNiz, izvorniNiz);
printf("%s\n", ciljniNiz);
myStrcpy(ciljniNiz, "Ana");
printf("%s\n", ciljniNiz);
/* moze i ovako: objasnite zasto! */
printf("%s\n", myStrcpy(ciljniNiz, "Iva"));
/* VAZNO PITANJE: */
/* zasto funkciju nije moguce pozvati ovako: myStrcpy(" ", "Ana"); */
return 0;
}

char *myStrcpy(char *cilj, char *izvor) {


int i = 0;
while (*(izvor+i)) {
*(cilj+i) = *(izvor+i);
++i;
}
*(cilj+i) = '\0';
return cilj;
}

Rjeenje 9. zadatka
#include <stdio.h>

int myStrlen(char *niz);

int main (void) {


char niz[20+1] = "Ovo je niz";
char *konst = "Ovo je konstantni niz";
printf("%d\n", myStrlen(niz));
printf("%d\n", myStrlen(konst));
printf("%d\n", myStrlen("Ovo je jos jedan konstatni niz"));
return 0;
}

int myStrlen(char niz[]) {


int i = 0;
while (niz[i]) ++i;
return i;
}

7
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 09-UgradjeneFunkcije.pdf - do stranice: 38

Rjeenje 10. zadatka


#include <stdio.h>

char *myStrcat(char *cilj, char *izvor);

int main (void) {


char ciljniNiz[30+1] = "Prvi";
char ciljniNiz2[30+1] = "Pocetak";
char *izvorniNiz = "Drugi";
myStrcat(ciljniNiz, izvorniNiz);
printf("%s\n", ciljniNiz);
myStrcat(ciljniNiz, "Treci");
printf("%s\n", ciljniNiz);
/* moze i ovako: objasnite zasto! */
printf("%s\n", myStrcat(ciljniNiz, "Cetvrti"));
/* VAZNO PITANJE: */
/* zasto funkciju nije moguce pozvati ovako: myStrcat("ABC", "EFG") */
/* proucite sljedecu naredbu */
myStrcat(myStrcat(ciljniNiz2, "Sredina"), "Kraj");
printf("%s\n", ciljniNiz2);
return 0;
}

char *myStrcat(char cilj[], char *izvor) { /* takodjer moze char *cilj */


int i = 0, j = 0;
while (cilj[i])
++i;
while (izvor[j])
cilj[i++] = izvor[j++];
cilj[i] = '\0';
return cilj;
}

Rjeenje 11. zadatka


#include <stdio.h>
#include <string.h>

int brojPodnizova(char *s1, char *s2) {


char *pocetakPotrage = s1;
int brojac = 0;
while ((pocetakPotrage = strstr(pocetakPotrage, s2)) != NULL) {
++brojac;
++pocetakPotrage;
}
return brojac;
}

int main (void) {


char s1[40+1];
char s2[40+1];
printf("Upisite nizove s1 i s2\n");
gets(s1);
gets(s2);
printf("Niz %s se unutar niza %s pojavljuje %d puta\n",
s2,
s1,
brojPodnizova(s1, s2));
return 0;
}

8
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 09-UgradjeneFunkcije.pdf - do stranice: 38

Rjeenje 13. zadatka


#include <stdio.h>
#define MYTOUPPER(c) ((c) >= 'a' && (c) <= 'z' ? \
(c) - 'a' + 'A' : (c))

int main (void) {


char niz[40];
int i = 0;
gets(niz);
while (niz[i] != 0) {
putchar(MYTOUPPER(niz[i])); /* ili printf("%c", MYTOUPPER(niz[i])); */
++i;
}
return 0;
}

Rjeenje 14. zadatka


#include <stdio.h>

char *myStrchr(char *niz, char c) {


while (*niz != '\0') {
if (*niz == c)
return niz;
++niz;
}
return NULL;
}

int main (void) {


char *nadjen;
nadjen = myStrchr("Neki niz", 'k');
if (nadjen != NULL)
printf("Nasao sam:%c\n", *nadjen);
else
printf("Nisam nasao\n");

nadjen = myStrchr("Neki niz", 'K');


if (nadjen != NULL)
printf("Nasao sam:%c\n", *nadjen);
else
printf("Nisam nasao\n");

return 0;
}

9
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 09-UgradjeneFunkcije.pdf - do stranice: 38

Rjeenje 15. zadatka


#include <stdio.h>

char *myStrstr(char *niz, char *podniz) {


char *pocetakTraganja = niz;
while (*pocetakTraganja != '\0') {
int i = 0;
while (pocetakTraganja[i] == podniz[i] && podniz[i] != '\0')
++i;
if (podniz[i] == '\0')
return pocetakTraganja;
++pocetakTraganja;
}
return NULL;
}

int main (void) {


char *nadjen;
nadjen = myStrstr("Neki tekst i drugi tekst", "tek");
if (nadjen != NULL)
printf("Nasao sam:%s\n", nadjen);
else
printf("Nisam nasao\n");

nadjen = myStrstr("Neki tekst i drugi tekst", "Tekst");


if (nadjen != NULL)
printf("Nasao sam:%s\n", nadjen);
else
printf("Nisam nasao\n");

return 0;
}

Rjeenje 16. zadatka


#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>

int main (void) {


char slucajniZnak;
int i, slova = 0, znamenki = 0, ostalih = 0;

srand ((unsigned) time(NULL));


for (i = 0; i < 1000; ++i) {
slucajniZnak = rand() % (126 - 32 + 1) + 32;
if (isalpha(slucajniZnak))
++slova;
else if (isdigit(slucajniZnak))
++znamenki;
else
++ostalih;
}
printf("%d slova, %d znamenki, %d ostalih znakova\n",
slova, znamenki, ostalih);
return 0;
}

10
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 09-UgradjeneFunkcije.pdf - do stranice: 52

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

22. vjebe uz predavanja

1. Na svom raunalu testirajte sve primjere s predavanja.

2. Napisati program koji pomou funkcije getchar s tipkovnice uitava znakove u niz s1 dok god
ne bude uitan znak 'X' (znak 'X' se ne dodaje u niz s1). Zatim u niz s2 uitava znakove dok
se ne pojavi znak 'Y' (znak 'Y' se ne dodaje u niz s2). Osigurati da nizovi s1 i s2 budu
ispravno terminirani (tj. na kraju niza se nalazi znak '\0'). Nakon uitavanja, pomou funkcije
putchar ispisati nizove s1 i s2 na zaslon, svaki u svoj redak. Nizovi s1 i s2 sigurno nisu dulji
od 80 znakova.
Primjer: ako se preko tipkovnice unese: Ovo je
neki tekst.XA ovo
je nastavakYOstatak se ne ucitava

kao rezultat treba ispisati: Ovo je


neki tekst.
A ovo
je nastavak

3. Napisati program kojim e se u dvodimenzionalno znakovno polje uitati tekst s tipkovnice.


Svaki redak teksta treba uitati u zasebni redak polja. Uitavanje redaka teksta treba
prekinuti kad se uita prazan redak ili se doe do granice od najvie 10 dozvoljenih redaka.
Moe se raunati da niti jedan redak teksta nee biti dulji od 80 znakova. Za itanje teksta
koristiti funkciju gets iz <stdio.h>. Na kraju, pomou funkcije printf, na zaslon ispisati sve
uitane retke teksta, svaki redak teksta u svom retku na zaslonu.

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 09-UgradjeneFunkcije.pdf - do stranice: 52

Rjeenja

Rjeenje 2. zadatka
#include <stdio.h>

int main(void) {
char s1[80+1], s2[80+1], c;
int i;

i = 0;
while((c = getchar()) != 'X')
s1[i++] = c;
s1[i] = '\0';

i = 0;
while((c = getchar()) != 'Y')
s2[i++] = c;
s2[i] = '\0';

i = 0;
while (s1[i] != '\0')
putchar(s1[i++]);

printf("\n");

i = 0;
while (s2[i] != '\0')
putchar(s2[i++]);

return 0;
}

Rjeenje 3. zadatka
#include <stdio.h>

#define MAXRED 10
#define MAXSTUP 80

int main (void) {


char polje[MAXRED][MAXSTUP+1];
int i, ucitanoRedaka = 0;

while (ucitanoRedaka < 10) {


/* gets kao argument koristi adresu prvog clana odgovarajuceg
retka 2D polja */
gets(&polje[ucitanoRedaka][0]);
if (polje[ucitanoRedaka][0] == '\0')
/* ucitan je prazan redak, prekini ucitavanje */
break;
++ucitanoRedaka;
}
for (i = 0; i < ucitanoRedaka; ++i)
printf("%s\n", &polje[i][0]);
return 0;
}

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 09-UgradjeneFunkcije.pdf - do stranice: 77

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

23. vjebe uz predavanja

1. to e se ispisati sljedeim programskim odsjekom. Izvoenjem programa na svom


raunalu provjerite svoj odgovor. Ulazni podaci su 11 12 13 1e
int i, j, k, m;
scanf("%d %o %x %x", &i, &j, &k, &m);
printf("%d %d %d %d\n", i, j, k, m);

2. Na svom raunalu izvedite sljedei programski odsjeak, uz ulazne podatke 1 2 3.0 4.0
int i;
short j;
float x;
double y;
scanf("%d %d %f %f", &i, &j, &x, &y);
printf("%d %d %f %f\n", i, j, x, y);
Jesu li se printf naredbom ispisale ispravne vrijednosti? Objasnite zato. to treba
promijeniti u formatu scanf naredbe da bi odsjeak radio ispravno? Izvoenjem programa na
svom raunalu provjerite svoj odgovor.

3. Koje su vrijednosti svih definiranih varijabli nakon obavljanja sljedeeg odsjeka programa:
int rez1, rez2, rez3;
int a, b, c;
short d;
char e;
float x, y;
double z, w;
rez1 = scanf("%3d%d%d %hx%c", &a, &b, &c, &d, &e);
rez2 = scanf("%f%5f", &x, &y);
rez3 = scanf(" %lf %lf", &z, &w); 12345 6
a2m
ako su preko tipkovnice uneseni sljedei podaci: 11-10 .1+ 3

4. Koje su vrijednosti svih definiranih varijabli nakon obavljanja sljedeeg odsjeka programa:
int rez1, rez2;
int a, b;
char s1[10+1], s2[10+1], s3[10+1], s4[10+1];
rez1 = scanf("%3d %d", &a, &b);
rez2 = scanf("%s%s%4s %s", s1, s2, s3, s4);
ako su preko tipkovnice uneseni sljedei podaci:

12ab Marija
Marica Ana

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 09-UgradjeneFunkcije.pdf - do stranice: 77

5. Napisati program koji e pomou funkcije scanf iz <stdio.h> uitati dva niza znakova s1 i
s2, iji se sadraj unosi preko tipkovnice i to tako da se svaki niz utipka u svojem retku.
Oznaka kraja retka se ne uitava u niz znakova. Npr. sadraj ulaza moe izgledati ovako:

Dva psa.
Jedan macak.

Moe se raunati da niti jedan redak teksta nee biti dulji od 30 znakova. Program treba
formirati niz s3, iji sadraj nastaje spajanjem nizova s1 i s2, te dobiveni niz s3 ispisati na
zaslon. U navedenom primjeru na zaslon treba ispisati:

Dva psa.Jedan macak.

6. Preko tipkovnice se unose matini brojevi i datumi roenja osoba. Datum roenja sadri redni
broj dana, redni broj mjeseca i redni broj godine. Npr. sadraj ulaza moe izgledati ovako:

101 15.5.1989
1526 17.6.1987
17 9.12.1987
0

Za svaku osobu pomou funkcije scanf uitati matini broj, redni broj dana, redni broj
mjeseca i redni broj godine. Uitavanje se prekida kada se za matini broj upie 0. Nakon
zavrenog uitavanja, ispisati matine brojeve i godine roenja osoba. Za prikazani primjer
ulaza, izlaz treba izgledati ovako:

101. 1989.
1526. 1987.
17. 1987.

Moe se pretpostaviti da e korisnik unijeti podatke za najvie 100 osoba.

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 09-UgradjeneFunkcije.pdf - do stranice: 77

7. to e se ispisati sljedeim programom:

#include <stdio.h>

int main(void) {
printf("|%d|\n", 10);
printf("|%5d|\n", 10);
printf("|%1d|\n", 10);

printf("|%s|\n", "Ana");
printf("|%5s|\n", "Ana");
printf("|%2s|\n", "Ana");

printf("|%x|\n", 27);
printf("|%6x|\n", 27);

printf("|%o|\n", 9);
printf("|%6o|\n", 9);
printf("|%1o|\n", 9);

printf("|%f|%7.4f|%7.2f|\n", 23.127, 23.127, 23.127);


printf("|%e|%12.4e|%.2e|\n", 0.00021278, 0.00021278, 0.00021278);

return 0;
}

8. Napisati program koji e s tipkovnice proitati cijeli broj broj n (1 n 15). Program treba na
zaslon ispisati "tablicu mnoenja". Npr. za zadani n=12, ispis na zaslon treba izgledati ovako:

Tablica mnozenja 12x12


1 2 3 4 5 6 7 8 9 10 11 12
----+------------------------------------------------
1! 1 2 3 4 5 6 7 8 9 10 11 12
2! 2 4 6 8 10 12 14 16 18 20 22 24
3! 3 6 9 12 15 18 21 24 27 30 33 36
4! 4 8 12 16 20 24 28 32 36 40 44 48
5! 5 10 15 20 25 30 35 40 45 50 55 60
6! 6 12 18 24 30 36 42 48 54 60 66 72
7! 7 14 21 28 35 42 49 56 63 70 77 84
8! 8 16 24 32 40 48 56 64 72 80 88 96
9! 9 18 27 36 45 54 63 72 81 90 99 108
10! 10 20 30 40 50 60 70 80 90 100 110 120
11! 11 22 33 44 55 66 77 88 99 110 121 132
12! 12 24 36 48 60 72 84 96 108 120 132 144
----+------------------------------------------------

Npr. za zadani n=1, ispis na zaslon treba izgledati ovako:

Tablica mnozenja 1x1


1
----+----
1! 1
----+----

3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 09-UgradjeneFunkcije.pdf - do stranice: 77

Rjeenja

Rjeenje 5. zadatka
#include <stdio.h>
#include <string.h>
#define MAXNIZ 30

int main (void) {


char s1[MAXNIZ+1], s2[MAXNIZ+1], s3[2*MAXNIZ+1];
/* procitaj prvi niz. Citaj dok ne dodjes do \n */
scanf("%[^\n]", s1);
/* procitaj znak '\n' koji je preostao na ulazu */
getchar();
/* procitaj drugi niz. Citaj dok ne dodjes do \n */
scanf("%[^\n]", s2);
/* kopiraj s1 u s3 */
strcpy(s3, s1);
/* dodaj s2 na kraj s3 */
strcat(s3, s2);

printf("%s\n", s3);
return 0;
}

Rjeenje 6. zadatka
#include <stdio.h>
#define MAX 100

int main(void) {
int dan, mjesec;
int matBroj, matBrojevi[MAX], godine[MAX];
int brojUcitanih = 0, i;
char tocka;
do {
scanf("%d", &matBroj);
if (matBroj != 0) {
matBrojevi[brojUcitanih] = matBroj;
scanf("%d%c%d%c%d", &dan, &tocka, &mjesec, &tocka,
&godine[brojUcitanih]);
++brojUcitanih;
}
} while (matBroj != 0);
for (i = 0; i < brojUcitanih; ++i)
printf("%4d. %4d.\n", matBrojevi[i], godine[i]);
printf("\n");
return 0;
}

4
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 09-UgradjeneFunkcije.pdf - do stranice: 77

Rjeenje 8. zadatka
#include <stdio.h>

int main(void) {
int n, i, j;
do {
printf("Upisite vrijednost za n: ");
scanf ("%d",&n);
} while (n < 1 || n > 15 );

printf("Tablica mnozenja %dx%d\n", n, n);


printf(" ");
for (i = 1; i <= n; ++i) {
printf("%4d", i);
}
printf("\n");

printf("----+", i);
for (i = 1; i <= n; ++i) {
printf("----", i);
}
printf("\n");

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


printf("%4d!", i);
for (j = 1; j <= n; ++j) {
printf("%4d", i*j);
}
printf("\n");
}

printf("----+", i);
for (i = 1; i <= n; ++i) {
printf("----", i);
}
printf("\n");
return 0;
}

5
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 23

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

24. vjebe uz predavanja

1. Napisati program koji e sadraj tekstualne datoteke ulaz.txt prepisati na zaslon, ali tako
da se umjesto malih slova ispisuju velika. Za itanje znakova iz datoteke treba koristiti
funkciju fgetc. Pomou editora (npr. notepad) prirediti tekstualnu datoteku ulaz.txt,
pohraniti ju unutar nekog kazala (direktorija), npr. c:\tmp, te testirati program.
2. Napisati funkciju broji koja kao argument prima niz znakova koji predstavlja ime
tekstualne datoteke (tip podatka char *). Funkcija treba otvoriti tok podataka za itanje iz
datoteke sa zadanim imenom (tj. "otvoriti datoteku"), prebrojati samoglasnike (broje se i
"mali" i "veliki" samoglasnici), zatvoriti tok podataka (tj. "zatvoriti datoteku"), te u pozivajui
program vratiti broj samoglasnika. Ako funkcija ne uspije otvoriti datoteku, kao broj
samoglasnika vraa -1. Za itanje znakova iz datoteke treba koristiti funkciju fgetc. Pomou
editora (npr. notepad) prirediti jednu tekstualnu datoteku, te napisati glavni program kojim e
se testirati rad funkcije.
3. Slino kao u prethodnom zadatku. Funkcija broji kao argument prima tok podataka (tip
podatka *FILE) koji je ve otvoren za tekstualnu datoteku. Glavni program otvara tok
podataka za postojeu tekstualnu datoteku, predaje ga funkciji, a kad funkcija obavi brojanje,
glavni program ispisuje rezultat i zatvara tok podataka.
4. Prepraviti rjeenje zadatka 6. (ispis tablice mnoenja) iz prethodnih vjebi uz predavanja.
Tablicu mnoenja, umjesto na zaslon, treba zapisati u tekstualnu datoteku ije ime treba
uitati s tipkovnice. Editorom (npr. notepad) provjeriti sadraj dobivene datoteke.
5. Napisati program koji pomou funkcije fscanf ita realne brojeve iz tekstualne datoteke
brojevi.txt, te po zavretku itanja (kada se doe do kraja datoteke ili se pri itanju
dogodi pogreka) na zaslon ispisuje ili aritmetiku sredinu uitanih brojeva ili poruku "Nije
procitan niti jedan broj". Npr. za sadraj datoteke:
22 13.5 -2 1
11.0 -3.5

na zaslon treba ispisati: 7.000000

Npr. za sadraj datoteke


a11 4.5 22
4.2 11

na zaslon treba ispisati: Nije procitan niti jedan broj.

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 23

6. U tekstualnu datoteku osobe.txt editorom upisati podatke o osobama (matini broj, ime,
prezime i datum roenja). Primjer sadraja datoteke prikazan je ovdje:
952 Nikolina Medvedec 15.5.1989
101 Iva Vurnek 17.6.1987
412 Natalija Voras 11.6.1988
551 Anatolij Ozimec 24.2.1989
115 Franjo Zdilar 22.11.1986
471 Ivana Suhina 8.6.1988
Napisati program koji e na zaslon ispisati sve podatke o osobama iz datoteke osobe.txt
ije ime sadri niz znakova na. Za datoteku iz primjera, program treba na zaslon ispisati
sljedee:
952 Nikolina Medvedec 15.5.1989
551 Anatolij Ozimec 24.2.1989
471 Ivana Suhina 8.6.1988

7. U tekstualnoj datoteci mjerenja.txt nalaze se zapisi o mjerenjima temperature u obliku:


#ddd#NN#hh#x.x#hh#xx.x#hh#xx.x#...hh#xx.x#
U zapisu se nalazi redni broj dana u godini (ddd), broj mjerenja obavljenih tog dana (NN),
sat u kojem je obavljeno mjerenje (hh), izmjerena temperatura (x.x). Npr.
#175#4#3#-11.5#12#2.0#16#5.0#22#-2.5#
Prethodni zapis znai da su u danu s rednim broje 175 obavljena 4 mjerenja: u 3 sata
temperatura je bila -11.5 stupnjeva, u 12 sati 2 stupnja, u 16 sati 5 stupnjeva i u 22 sata -2.5
stupnja.
Za svaki zapis iz datoteke mjerenja.txt ispisati na zaslon redni broj dana i srednju
vrijednost izmjerenih temperatura za taj dan.

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 23

8. Ovaj zadatak je vaan za razumijevanje funkcije fgets. U predavanjima prvo paljivo proitati
to tono radi funkcija fgets.
Uz pretpostavku da je sadraj datoteke podaci.txt:
abcde
fghijk
lmnoprs
ABCDEFGH

to e biti sadraj datoteke izlaz.txt nakon obavljanja sljedeeg programa:

#include <stdio.h>
#include <stdlib.h>
#define MAXLIN 7

int main (void) {


FILE *du, *di;
char linija[MAXLIN];

du = fopen ("podaci.txt", "r");


di = fopen ("izlaz.txt", "w");
while (fgets(linija, MAXLIN, du) != NULL ) {
fputs (linija, di);
}
fclose (du);
fclose (di);

return 0;
}

3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 23

Rjeenja

Rjeenje 1. zadatka
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main (void) {


int c;
FILE *tokPod;
char *imeDat = "ulaz.txt";
tokPod = fopen(imeDat, "r");

if (tokPod == NULL) {
printf("Ne mogu otvoriti %s\n", imeDat);
exit(1);
}

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


putchar(toupper(c)); /* ili fputc(toupper(c), stdout); */

fclose(tokPod);
return 0;
}

Rjeenje 2. zadatka
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define MAXIMEDAT 64

int broji (char *ime) {


int broj;
char c;
FILE *ulTok;

ulTok = fopen (ime, "r");


if (ulTok != NULL) {
broj = 0;
while ((c = fgetc(ulTok)) != EOF) {
c = toupper(c);
if (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U')
++broj;
}
fclose(ulTok);
return broj;
}
else {
/* otvaranje ulaznog toka podataka nije uspjelo */
broj = -1;
}
return broj;
}

4
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 23

int main (void) {


char imedat[MAXIMEDAT+1];
int broj;
printf("Upisite ime datoteke>");
scanf("%s", imedat);
broj = broji(imedat);
if (broj == -1)
printf("Problemi kod otvaranja datoteke %s\n", imedat);
else
printf("U datoteci %s ima %d samoglasnika\n", imedat, broj);
return 0;
}

Rjeenje 3. zadatka
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define MAXIMEDAT 64

int broji (FILE *ulTok) {


int broj = 0;
char c;
while ((c = fgetc(ulTok)) != EOF) {
c = toupper(c);
if (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U')
++broj;
}
return broj;
}

int main (void) {


char imedat[MAXIMEDAT+1];
int broj;
FILE *ulaz;
printf("Upisite ime datoteke>");
scanf("%s", imedat);

ulaz = fopen (imedat, "r");


if (ulaz != NULL) {
broj = broji(ulaz);
printf("U datoteci %s ima %d samoglasnika\n", imedat, broj);
fclose(ulaz);
}
else {
printf("Problemi kod otvaranja datoteke %s\n", imedat);
}
return 0;
}

5
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 23

Rjeenje 4. zadatka
#include <stdio.h>

int main(void) {
int n, i, j;
char imeDat[64+1];
FILE *tok;

printf("Upisite ime datoteke: ");


scanf("%s", imeDat);
do {
printf("Upisite vrijednost za n: ");
scanf ("%d",&n);
} while (n < 1 || n > 15 );

tok = fopen(imeDat, "w");

fprintf(tok, "Tablica mnozenja %dx%d\n", n, n);


fprintf(tok, " ");
for (i = 1; i <= n; ++i) {
fprintf(tok, "%4d", i);
}
fprintf(tok, "\n");

fprintf(tok, "----+", i);


for (i = 1; i <= n; ++i) {
fprintf(tok, "----", i);
}
fprintf(tok, "\n");

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


fprintf(tok, "%4d!", i);
for (j = 1; j <= n; ++j) {
fprintf(tok, "%4d", i*j);
}
fprintf(tok, "\n");
}

fprintf(tok, "----+", i);


for (i = 1; i <= n; ++i) {
fprintf(tok, "----", i);
}
fprintf(tok, "\n");

fclose(tok);
return 0;
}

6
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 23

Rjeenje 5. zadatka
#include <stdio.h>

int main (void) {


float x, suma = 0.0f;
int brojac = 0;
FILE *ulTok;

ulTok = fopen ("brojevi.txt", "r");


while (fscanf(ulTok, "%f", &x) == 1 ) {
suma += x;
++brojac;
}
fclose (ulTok);
if (brojac > 0)
printf("%f\n", suma/brojac);
else
printf("Nije procitan niti jedan broj\n", suma/brojac);

return 0;
}

Rjeenje 6. zadatka
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main (void) {


FILE *ulTok;
char tocka;
int mbr;
char ime[15+1];
char prez[15+1];
short int dan;
short int mjesec;
short int godina;

ulTok = fopen ("osobe.txt", "r");

while (fscanf(ulTok, "%d%s%s%hd%c%hd%c%hd",


&mbr,
ime,
prez,
&dan,
&tocka,
&mjesec,
&tocka,
&godina) == 8)
if (strstr(ime, "na") != NULL)
printf("%d %s %s %d.%d.%d\n", mbr, ime, prez, dan, mjesec, godina);
fclose (ulTok);
return 0;
}

7
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 23

Rjeenje 7. zadatka
#include <stdio.h>

int main (void) {


FILE *du;

int dan, brojMj, sat, i;


float temp;
float suma;
char c;

du = fopen("mjerenja.txt", "r");

while (fscanf(du, "%c%d%c%d%c", &c, &dan, &c, &brojMj, &c) == 5) {


suma = 0.0f;
for (i = 0; i < brojMj; ++i) {
fscanf(du, "%d%c%f%c", &sat, &c, &temp, &c);
suma += temp;
}
printf("%3d: %f\n", dan, suma/brojMj);
/* sad procitati \n koji je ostao neprocitan */
fscanf(du, "%c", &c);
}

fclose(du);
return 0;
}

Rjeenje 8. zadatka

Nakon 1. itanja sadraj polja linija je: abcde\n\0


Nakon 2. itanja sadraj polja linija je: fghijk\0
Nakon 3. itanja sadraj polja linija je: \n\0
Nakon 4. itanja sadraj polja linija je: lmnopr\0
Nakon 5. itanja sadraj polja linija je: s\n\0
Nakon 6. itanja sadraj polja linija je: ABCDEF\0
Nakon 7. itanja sadraj polja linija je: GH\0
8. itanje e vratiti NULL
Sadraj datoteke izlaz.txt je: abcde
fghijk
lmnoprs
ABCDEFGH

8
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 44

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

25. vjebe uz predavanja

1. U tekstualnu datoteku ulaz.txt editorom su upisani podaci o osobama (matini broj i


prezime). Primjer sadraja datoteke prikazan je ovdje:
952 Medvedec
101 Vurnek
205 Habajec
412 Voras
551 Ozimec
115 Zdilar
104 Pugelnik
471 Suhina
Napisati program koji e sadraj datoteke ulaz.txt prepisati u novu binarnu datoteku
izlaz.bin. Jedan zapis datoteke izlaz.bin sadri: matini broj (long) i prezime (15+1
znak).
2. Napisati program koji e na zaslon ispisati matine brojeve i prezimena svih osoba u ijim se
prezimenima nalazi malo slovo a. Podaci o osobama se nalaze u postojeoj binarnoj datoteci
izlaz.bin koja je dobivena kao rezultat obavljanja programa iz prethodnog zadatka.
Napomena: kod rjeavanja ovog, a takoer i svih slinih zadataka s datotekama, nije
doputeno sve zapise "uitati u memoriju", npr. u jedno veliko polje, i onda po tom polju traiti
zapise koji zadovoljavaju neki uvjet. Umjesto toga, u memoriju uitati prvi zapis, provjeriti
treba li na zaslon ispisati podatke iz tog zapisa, zatim uitati drugi zapis, itd.
3. Svaki zapis datoteke slucajni.bin treba sadravati neki cijeli broj n (tipa int) koji moe
poprimiti vrijednosti iz intervala [2, 8], te n cijelih brojeva (tipa int) koji poprimaju vrijednosti iz
intervala [150, 160]. Napisati program koji e u novu binarnu datoteku slucajni.bin
upisati 20 zapisa koji se formiraju na sluajan nain. Za svaki zapis prvo treba na sluajan
nain odrediti n, a zatim na sluajan nain odrediti svaku od n vrijednosti koje ine ostatak
zapisa.
4. Napisati program koji e na zaslon ispisati sve zapise datoteke slucajni.bin koja je
nastala kao rezultat obavljanja programa iz prethodnog primjera. Npr. ispis moe izgledati
ovako:
6 153 160 155 159 152 152
5 160 152 150 153 160
2 160 159
4 152 152 155 151
5 155 155 158 159 153
3 151 158 151
2 150 153
2 158 156
4 150 151 153 152
3 156 153 154
8 150 154 157 155 155 155 158 156
4 153 159 155 157
8 155 150 159 152 152 154 152 160
3 153 156 158
7 157 158 160 160 155 158 157
2 151 159
3 156 152 159
7 157 157 152 153 152 155 151
8 160 158 159 157 154 156 159 152
5 157 159 160 153 157

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 44

5. Napisati program kojim e se u novu binarnu datoteku slova.bin redom upisati sva velika,
a nakon njih sva mala slova abecede.

6. Funkcijama fseek i ftell odrediti i ispisati na zaslon broj znakova u datoteci slova.bin iz
prethodnog zadatka.
7. Jednim pozivom funkcije scanf u varijablu s uitati vrijednosti svih njenih lanova:
struct str1 {
int stanje[2];
};
struct str2 {
struct str1 x;
float k;
} s;
8. Jednim pozivom funkcije scanf u varijablu w uitati vrijednosti svih njenih lanova:
struct str1 {
float stanje[2];
};
struct str2 {
struct str1 y;
int k;
char ime[10+1];
} w;
9. Jednim pozivom funkcije scanf u varijablu b uitati vrijednosti svih njenih lanova:
struct str1 {
float x;
int k;
};
struct str2 {
struct str1 z1;
struct str1 z2;
} b;

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 44

Rjeenja

Rjeenje 1. zadatka
#include <stdio.h>

int main (void) {


FILE *ulTok, *izTok;

long int mbr;


char prez[15+1];

ulTok = fopen ("ulaz.txt", "r");


izTok = fopen ("izlaz.bin", "wb");

while (fscanf(ulTok, "%ld%s",


&mbr,
prez) == 2) {
fwrite(&mbr, sizeof(mbr), 1, izTok);
fwrite(&prez, sizeof(prez), 1, izTok);
}
fclose (ulTok);
fclose (izTok);

return 0;
}

Rjeenje 2. zadatka
#include <stdio.h>
#include <string.h>

int main (void) {


FILE *ulTok;
long int mbr;
char prez[15+1];

ulTok = fopen ("izlaz.bin", "rb");

while (fread(&mbr, sizeof(mbr), 1, ulTok) == 1 &&


fread(&prez, sizeof(prez), 1, ulTok) == 1)
if (strchr(prez, 'a') != NULL)
printf("%d %s\n", mbr, prez);
fclose (ulTok);
return 0;
}

3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 44

Rjeenje 3. zadatka
#include <time.h>
#include <stdio.h>
#include <stdlib.h>

#define MIN_N 2
#define MAX_N 8
#define DG 150
#define GG 160
#define BROJ_ZAPISA 20

int main (void) {


FILE *izTok;
int i, j, n, polje[MAX_N];

izTok = fopen ("slucajni.bin", "wb");


/* inicijalizacija generatora sluc. brojeva */
srand ((unsigned) time(NULL));

for (i = 1; i <= BROJ_ZAPISA; ++i) {


/* odaberi slucajan n */
n = rand() % (MAX_N - MIN_N + 1) + MIN_N;
/* odaberi n slucajnih brojeva */
for (j = 0; j < n; ++j)
polje[j] = rand() % (GG - DG + 1) + DG;
fwrite(&n, sizeof(n), 1, izTok);

fwrite(polje, sizeof(int), n, izTok);


/* ili fwrite(polje, sizeof(int)*n, 1, izTok); */
}
fclose (izTok);
return 0;
}

Rjeenje 4. zadatka
#include <stdio.h>

#define MAX_N 8

int main (void) {


FILE *ulTok;
int i, n, polje[MAX_N];

ulTok = fopen ("slucajni.bin", "rb");

while (fread (&n, sizeof(n), 1, ulTok) == 1) {


fread (polje, sizeof(int), n, ulTok);
/* ili fread (polje, sizeof(int)*n, 1, ulTok); */
printf("%d ", n);
for (i = 0; i < n; ++i)
printf("%d ", polje[i]);
printf("\n");
}
fclose (ulTok);
return 0;
}

4
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 44

Rjeenje 5. zadatka
#include <stdio.h>

int main (void) {


FILE *izTok;
char c;
izTok = fopen ("slova.bin", "wb");
for (c = 'A'; c <= 'Z'; ++c) {
fwrite(&c, sizeof(c), 1, izTok);
}
for (c = 'a'; c <= 'z'; ++c) {
fwrite(&c, sizeof(c), 1, izTok);
}
fclose (izTok);
return 0;
}

Rjeenje 6. zadatka
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main (void) {


FILE *ulTok;
char c;
int brojZnakova, slucajnaPozicija, brojIspisanih = 0;

ulTok = fopen ("slova.bin", "rb");


fseek(ulTok, 0L, SEEK_END);
/* znak je velicine jednog bajta, stoga je broj znakova
jednak broju bajtova */
brojZnakova = ftell(ulTok);
printf("Broj znakova u datoteci jest: %d\n", brojZnakova);

fclose (ulTok);
return 0;
}

Rjeenje 7. zadatka
scanf("%d%d%f", &s.x.stanje[0], &s.x.stanje[1], &s.k);
/* ispis radi provjere */
printf("%d\n%d\n", s.x.stanje[0], s.x.stanje[1]);
printf("\n");
printf("%f\n", s.k);

5
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 44

Rjeenje 8. zadatka
scanf("%f%f%d%10s", &w.y.stanje[0], &w.y.stanje[1], &w.k, w.ime);
/* ispis radi provjere */
printf("%f\n%f\n", w.y.stanje[0], w.y.stanje[1]);
printf("\n");
printf("%d\n", w.k);
printf("\n");
printf("%s\n", w.ime);

Rjeenje 9. zadatka
scanf("%f%d%f%d", &b.z1.x, &b.z1.k, &b.z2.x, &b.z2.k);
/* ispis radi provjere */
printf("%f\n%d\n", b.z1.x, b.z1.k);
printf("\n");
printf("%f\n%d\n", b.z2.x, b.z2.k);

6
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 75

Napomene:
- Savjetuje se navedene zadatke rijeiti ubrzo nakon predavanja
- Savjetuje se ne gledati rjeenja prije nego se pokua samostalno rijeiti zadatke

26. vjebe uz predavanja

1. Napisati program kojim e se u novu binarnu datoteku slova.bin redom upisati sva velika,
nakon njih sva mala slova abecede, a nakon njih sve znamenke.
2. Na sluajan nain (funkcijom rand) odabirati pozicije u datoteci slova.bin iz prethodnog
zadatka, sa svake odabrane pozicije proitati jedan znak i ispisati ga na zaslon. Postupak
zavriti nakon to se na zaslon ispie 40 znakova ili veliki znak 'X'.

3. U tekstualnu datoteku ulaz.txt editorom su upisani podaci o osobama (matini broj, ime,
prezime i datum roenja). Primjer sadraja datoteke prikazan je ovdje:
952 Nikolina Medvedec 15.05.1989
101 Davor Vurnek 17.06.1987
205 Zoran Habajec 09.12.1987
412 Davor Voras 11.06.1988
551 Zvonimir Ozimec 24.02.1989
115 Franjo Zdilar 22.01.1986
104 Stipe Pugelnik 03.05.1987
471 Nina Suhina 08.06.1988
Napisati program koji e sadraj datoteke ulaz.txt prepisati u novu binarnu datoteku
izlaz.bin. Jedan zapis datoteke izlaz.bin sadri: matini broj (long), ime (15+1 znak),
prezime (15+1 znak), dan roenja (short), mjesec roenja (short), godinu roenja (short).
Koristiti strukture!
4. Napisati program koji e na zaslon ispisati matine brojeve, imena i prezimena svih osoba
koje roendan imaju u mjesecu lipnju. Podaci o osobama se nalaze u postojeoj binarnoj
datoteci izlaz.bin koja je dobivena kao rezultat obavljanja programa iz prethodnog
zadatka. Koristiti strukture!
Napomena: kod rjeavanja ovog, a takoer i svih slinih zadataka s datotekama, nije
doputeno sve zapise "uitati u memoriju", npr. u jedno veliko polje, i onda po tom polju traiti
zapise koji zadovoljavaju neki uvjet. Umjesto toga, u memoriju uitati prvi zapis, provjeriti
treba li na zaslon ispisati podatke iz tog zapisa, zatim uitati drugi zapis, itd.
5. Koristi se slijedna tekstualna datoteka ulaz.txt opisana u 3. zadatku. Napisati program koji
e na zaslon ispisati prezime i ime za svaki trei zapis iz datoteke, poevi od prvog zapisa
(tj. za prvi zapis, za etvrti zapis, za sedmi zapis, itd).
6. Rezultat ispisa na zaslon (standardni izlaz) iz prethodnog zadatka preusmjeriti u datoteku
c:/tmp/rezultat.txt
7. U direktnoj binarnoj datoteci bodovi nalaze se podaci o 10 studenata i bodovima koje su
dobili za zalaganje na nastavi. Svaki zapis sadri matini broj (int), prezime i ime (20+1 znak)
i broj bodova (int). Matini brojevi su u rasponu od 1-10, a redni broj zapisa odgovara
matinom broju. Napisati program kojim e se za jednog sluajno odabranog studenta za
10% poveati dotadanju vrijednost njegovih bodova. Ograniiti uveani broj bodova na
maksimalnih 500 bodova.

1
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 75

8. Napisati program koji na kraj datoteke mjerenja.txt koja je opisana u 7. zadatku iz 23. vjebi
uz predavanja, dodaje jedan novi zapis o mjerenjima temperature. Preko tipkovnice se
uitava redni broj dana, broj mjerenja (ne vie od 24) i parovi (sat, temperatura). Ukoliko u
datoteci ve postoji zapis o uitanom rednom broju dana, dojavljuje se odgovarajua poruka.
9. Uz pretpostavku da se dnevno mogu obaviti najvie 24 mjerenja temperature, prepiite
datoteku mjerenje.txt u odgovarajuu direktnu binarnu datoteku mjerenja.bin. Redni broj
zapisa u datoteci mjerenja.bin odgovara rednom broju dana.
10. Napiite program koji za redni broj dana uitan preko tipkovnice, ita zapis iz datoteke
mjerenja.bin i ispisuje vremena mjerenja i temperature izmjerene tog dana. Ukoliko mjerenje
za zadani dan ne postoji, ispisati odgovarajuu poruku.

2
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 75

Rjeenja

Rjeenje 1. zadatka
#include <stdio.h>

int main (void) {


FILE *izTok;
char c;
izTok = fopen ("slova.bin", "wb");
for (c = 'A'; c <= 'Z'; ++c) {
fwrite(&c, sizeof(c), 1, izTok);
}
for (c = 'a'; c <= 'z'; ++c) {
fwrite(&c, sizeof(c), 1, izTok);
}
for (c = '0'; c <= '9'; ++c) {
fwrite(&c, sizeof(c), 1, izTok);
}
fclose (izTok);
return 0;
}

Rjeenje 2. zadatka
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main (void) {


FILE *ulTok;
char c;
int brojZnakova, slucajnaPozicija, brojIspisanih = 0;

ulTok = fopen ("slova.bin", "rb");


fseek(ulTok, 0L, SEEK_END);
/* znak je velicine jednog bajta, stoga je broj znakova
jednak broju bajtova */
brojZnakova = ftell(ulTok);

srand((unsigned)time(NULL));
do {
/* slucajna pozicija u datoteci: [0, brojZnakova - 1] */
slucajnaPozicija = rand() % brojZnakova;
fseek(ulTok, slucajnaPozicija, SEEK_SET);
fread(&c, sizeof(c), 1, ulTok);
printf("%c", c);
++brojIspisanih;
} while (c != 'X' && brojIspisanih < 40);
printf("\n");
fclose (ulTok);
return 0;
}

3
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 75

Rjeenje 3. zadatka
#include <stdio.h>
int main (void) {
FILE *ulTok, *izTok;
char tocka;

struct {
long int mbr;
char ime[15+1];
char prez[15+1];
short int dan;
short int mjesec;
short int godina;
} osoba;

ulTok = fopen ("ulaz.txt", "r");


izTok = fopen ("izlaz.bin", "wb");

while (fscanf(ulTok, "%ld%s%s%hd%c%hd%c%hd",


&osoba.mbr,
osoba.ime,
osoba.prez,
&osoba.dan,
&tocka,
&osoba.mjesec,
&tocka,
&osoba.godina) == 8) {
fwrite(&osoba, sizeof(osoba), 1, izTok);
}
fclose (ulTok);
fclose (izTok);
return 0;
}

Rjeenje 4. zadatka
#include <stdio.h>

int main (void) {


FILE *ulTok;
struct {
long int mbr;
char ime[15+1];
char prez[15+1];
short int dan;
short int mjesec;
short int godina;
} osoba;

ulTok = fopen ("izlaz.bin", "rb");

while (fread(&osoba, sizeof(osoba), 1, ulTok) == 1) {


if (osoba.mjesec == 6)
printf("%d %s %s\n",
osoba.mbr,
osoba.ime,
osoba.prez);
}
fclose (ulTok);
return 0;
}

4
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 75

Rjeenje 5. zadatka
#include <stdio.h>

int main (void) {


FILE *ulTok;
long int mbr;
char ime[15+1];
char prez[15+1];
char datum[2+1+2+1+4+1];
int rbr = 0;

ulTok = fopen ("ulaz.txt", "r");

while (fscanf(ulTok, "%ld%s%s%s",


&mbr,
ime,
prez,
datum) == 4) {
if (rbr % 3 == 0)
printf("%s %s\n", ime, prez);
++rbr;
}
fclose (ulTok);
return 0;
}

Rjeenje 6. zadatka

Uz pretpostavku da je ime datoteke s izvrnim kodom svakitreci.exe:


svakitreci.exe > c:/tmp/rezultat.txt
Sadraj datoteke rezultat.txt moe se provjeriti pomou nekog editora, npr. notepad.

Rjeenje 7. zadatka
Zadatak ilustrira kako se na sluajan nain odabire redni broj zapisa, kako se ita odabrani zapis iz
direktne tekstualne datoteke, te kako se sadraj zapisa direktne tekstualne datoteke moe
promijeniti. Takoer ilustrira kako se ista datoteka moe koristiti i za itanje i za pisanje.

NAPOMENA: izmeu operacija itanja i pisanja u isti tok podataka mora se nalaziti barem jedan
poziv funkcije fseek nad tim tokom podataka (ak i u sluaju kad nam pomak znake nije potreban
jer se znaka ve nalazi na eljenoj poziciji). Izmeu operacija pisanja i itanja iz istog toka
podataka, mora se nalaziti barem jedan poziv funkcije fseek ili fflush. Funkcija fflush(tokPodataka)
prazni meuspremnike toka podataka. Ne pridravamo li se tih pravila, mogli bismo izvodei svoje
programe za vjebu dobiti posve pogrene rezultate. Na zavrnom ispitu se nee inzistirati na tom
detalju (nee se "oduzimati bodovi" u sluaju nepotovanja tih pravila)

Dakle, ako u programu za vjebu imamo pisanje pa itanje iz istog toka podataka
fwrite(..., tokPodataka);
/* ovdje negdje izmeu se mora nalaziti ili fflush(tokPodataka) ili fseek(tokPodataka, ...) */
fread(..., tokPodataka);

Ako u programu za vjebu imate itanje pa pisanje u isti tok podataka


fread(..., tokPodataka)
/* ovdje negdje izmeu se mora nalaziti fseek(tokPodataka, ...) */
fwrite(..., tokPodataka)

5
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 75

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main (void) {


FILE *dUlIzl;
struct {
int mbr;
char prezIme[20+1];
int brBod;
} zapis;
int mbr;
dUlIzl = fopen("bodovi", "r+b");

/* inicijaliziraj generator slucajnih brojeva */


srand((unsigned) time(NULL));
/* odaberi slucajni broj iz intervala [1,10] */
mbr = rand() % 10 + 1;

printf("(Kontrolni ispis)povecati bodove za mbr: %d\n", mbr);


/* Postavi kazaljku neposredno ISPRED odgovarajuceg zapisa */
fseek(dUlIzl, (long)sizeof(zapis)*(mbr-1), SEEK_SET);
/* Procitaj cijeli zapis u strukturu */
fread(&zapis, sizeof(zapis), 1, dUlIzl);
/* Povecaj broj bodova */
zapis.brBod *= 1.1;
if (zapis.brBod > 500)
zapis.brBod = 500;
/* VAZNO: ne zaboraviti zapisati promijenjene podatke natrag u datoteku!!! */
/* Postavi kazaljku neposredno ISPRED odgovarajuceg zapisa jer nakon
prethodnog citanja, kazaljka je bila neposredno IZA odgovarajuceg zapisa */
fseek(dUlIzl, -1L*(long)sizeof(zapis), SEEK_CUR);
/* Zapisi sadrzaj cijele strukture u datoteku */
fwrite(&zapis, sizeof(zapis), 1, dUlIzl);

fclose(dUlIzl);
return 0;
}

U ovom zadatku je fseek izmeu fread i fwrite ionako bio potreban, pa se nije moglo pogrijeiti u
odnosu na prethodnu napomenu.

6
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 75

Rjeenje 8. zadatka
Zadatak ilustrira kako se na kraj slijedne tekstualne datoteke moe dodati zapis.

#include <stdio.h>
#include <stdlib.h>

int main (void) {


FILE *di;
int dan, noviDan, i;
int sati[24];
float temp[24];
int brojMjerenja;
char ostatakRetka[512];
char c;

di = fopen("mjerenja.txt", "a+");
/* ucitati redni broj novog dana */
printf("Upisite redni broj novog dana>");
scanf("%d", &noviDan);

/* ako redni broj dana vec postoji, zavrsiti program */


while (fscanf(di, "%c%d%", &c, &dan) == 2) {
if (dan == noviDan) {
printf("Dan vec postoji\n");
exit(1);
}
/* preskociti ostatak retka */
fgets(ostatakRetka, 512, di);
}

/* ucitati broj mjerenja */


printf("Upisite broj mjerenja>");
scanf("%d", &brojMjerenja);

/* ucitati parove u polja sati i temp */


for (i=0; i < brojMjerenja; ++i) {
printf("Upisite %d. par sata i temperature>", i+1);
scanf("%d %f", &sati[i], &temp[i]);
}
/* ovdje bi se moglo provjeriti jesu li unesene "duple"
vrijednosti sati, ali to se nije trazilo */

/* zapisati redni broj dana i broj mjerenja */


/* fseek na kraj datoteke nije potreban jer je datoteka
otvorena u modu "a+" */
fprintf(di, "#%d#%d#", noviDan, brojMjerenja);

/* zapisati parove sat-temp */


for (i = 0; i < brojMjerenja; ++i) {
fprintf(di, "%d#%.1f#", sati[i], temp[i]);
}

/* zapisati "novi red" \n */


fprintf(di, "\n");

fclose(di);
return 0;
}

7
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 75

Rjeenje 9. zadatka
Zadatak ilustrira pisanje u direktnu tekstualnu datoteku iji zapis, izmeu ostalog, sadri polje.

#include <stdio.h>

int main (void) {


FILE *du, *di;
struct {
int rbrDan;
int brMjer;
int sati[24];
float temp[24];
} zapis;
int i;
char c;
float suma = 0.0f;

du = fopen("mjerenja.txt", "r");
di = fopen("mjerenja.bin", "wb");

while (fscanf(du, "%c%d%c%d%c", &c, &zapis.rbrDan, &c, &zapis.brMjer, &c)


== 5) {
for (i = 0; i < zapis.brMjer; ++i) {
fscanf(du, "%d%c%f%c", &zapis.sati[i], &c, &zapis.temp[i], &c);
}
/* procitaj \n s kraja retka */
fscanf(du, "%c", &c);
/* zapisati u dir. binarnu datoteku */
fseek(di, (long)sizeof(zapis)*(zapis.rbrDan-1), SEEK_SET);
fwrite(&zapis, sizeof(zapis), 1, di);
}
fclose(du);
fclose(di);

return 0;
}

8
Programiranje i programsko inenjerstvo, ZPR-FER-UNIZG
Vjebe uz predavanja 10-Datoteke.pdf - do stranice: 75

Rjeenje 10. zadatka


Zadatak ilustrira itanje iz direktne binarne datoteke iji zapis, izmeu ostalog, sadri polje. U
rjeenju zadatka treba uoiti da zapis direktne binarne datoteke moe biti "prazan". Uoiti na koji se
nain utvruje da je zapis "prazan".

#include <stdio.h>

int main (void) {


FILE *du;
struct {
int rbrDan;
int brMjer;
int sati[24];
float temp[24];
} zapis;
int i, rbrDan;
du = fopen("mjerenja.bin", "rb");

printf("Upisite redni broj dana>");


scanf("%d", &rbrDan);

fseek(du, (long)(rbrDan-1)*sizeof(zapis), SEEK_SET);


fread(&zapis, sizeof(zapis), 1, du);

if (zapis.rbrDan == rbrDan) {
printf("mjerenja za dan: %d\n", zapis.rbrDan);
for (i=0; i < zapis.brMjer; ++i) {
printf(" Sat: %2d Temperatura: %5.1f\n",
zapis.sati[i], zapis.temp[i]);
}
}
else {
printf("Nema podataka o mjerenju za zadani dan\n");
}
fclose(du);

return 0;
}

9
FAKULTET ELEKTROTEHNIKE, STROJARSTVA I BRODOGRADNJE
SVEUILITE U SPLITU

(UVOD U)
RAUNALA I PROGRAMIRANJE

Laboratorijske vjebe

Bonkovi Mirjana / Braovi Maja / Goi Ranko

Listopad, 2010.
KATEDRA ZA MODELIRANJE I INTELIGENTNE RAUNALNE SUSTAVE (KaMIS)

Laboratorij za robotiku i inteligentne sustave (LaRIS)

Predavanja: dr. sc. Mirjana Bonkovi, red. prof.


dr. sc. Ranko Goi, doc.
mr. sc. Ana Kuzmani Skelin

Laboratorijske vjebe: Maja Braovi, mag. ing.


Bruno Batarelo, dipl. ing.
Ante Deni, dipl. ing.

Dodatna literatura za kolegij (Uvod u) Raunala i programiranje:

1. Gottfried, B.: "Schaum's Outline Series: Programming with C", Second Edition, McGraw-Hill,
1996.
2. Vulin, R.: "Zbirka rijeenih zadataka iz C-a", kolska knjiga, Zagreb, 2003.
3. Parlante, N.: "Essential C", 2003, http://cslibrary.stanford.edu/101/EssentialC.pdf.
4. Materijali dostupni preko MIT OpenCourseWare projekta:
http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/.

2
VJEBA 1

Povijest programskog jezika C

Programski jezik C nastao je 1972. godine u Bell laboratorijima, kao rezultat rada raunalnog
znanstvenika Dennisa Ritchiea. On je prvi kreirao i primijenio programski jezik C.

Slika 1.1. Raunalni znanstvenici Ken Thompson (lijevo) i Dennis Ritchie (desno) [1].

Veina bitnih ideja i koncepata koji su koriteni prilikom razvijanja programskog jezika C dolo je iz
programskog jezika BCPL (engl. Basic Combined Programming Language), ali samo posredno, preko
programskog jezika B kojega je razvio Ken Thompson 1970. godine za prvi UNIX sustav na DEC PDP
raunalu (engl. Digital Equipment Corporation Programmed Data Processor).

Dennis Ritchie i Ken Thompson su 1983. godine nagraeni Turingovom nagradom (za teoretski rad
na podruju generikih operacijskih sustava te za implementaciju operacijskog sustava UNIX), to je
jedna od najveih poasti koju raunalni znanstvenici mogu dobiti.

Zato C?

Programski jezik C je inicijalno dizajniran za implementaciju sistemskog softvera (jezgra UNIX


sustava je gotovo u potpunosti napisana u C-u), ali danas se upotrebljava kao jezik ope namjene.
To znai da se pomou njega mogu implementirati ne samo operacijski sustavi, ve i raunalne igre,
driveri, razliite aplikacije i sl. Iako danas sve popularniji postaju objektno-orijentirani programski
jezici (npr. Java ili C#), C se jo uvijek esto koristi jer programeru omoguuje veu kontrolu nad
programom i obino se takvi programi izvravaju bre nego njihovi ekvivalenti napisani u nekom od
objektno-orijentiranih jezika.

C jezik bi se mogao nazvati jezikom nie razine sa stajalita objektno-orijentiranog programera, ali
sa stajalita programera koji pie programe u Asembleru (engl. Assembly language) ili (teoretski) u
strojnom jeziku (npr. 00010110 01010111 11111000 10000001), bio bi shvaen kao jezik vie

3
razine. Izrazi "jezik nie razine" te "jezik vie razine" su dosta relativni i obino jako vezani uz
kontekst u kojemu se koriste.

Kako do izvrne datoteke?

Proces stvaranja izvrne datoteke sastoji se od 3 koraka:

1. Programer napie izvorni kod programa (engl. source code). Datoteke u kojima se nalazi
izvorni kod imaju ekstenziju .c (ako su napisane u C-u), i moe ih biti vie od jedne.
2. Izvorni kod se prevodi u objektni kod pomou prevoditelja (engl. compiler). Prevoditelj u
objektni kod posebno prevede svaku datoteku u kojoj se nalazi izvorni kod. Datoteke u
kojima se nalazi objektni kod sadre kod razumljiv raunalu (strojni kod), te imaju ekstenziju
.obj ili .o.
3. Datoteke u kojima se nalazi objektni kod i biblioteke koje su specificirane u njemu se
povezuju u jedinstvenu datoteku pomou poveznika (engl. linker). Ta jedinstvena datoteka
naziva se izvrna datoteka, i ima ekstenziju .exe.

Slika 1.2. Proces kreiranja izvrne datoteke.

Vano je napomenuti da je prevoenje izvornog koda u strojni kod jednosmjeran proces, tj. strojni
kod se gotovo nikad u potpunosti ne moe uspjeno prevesti natrag u izvorni kod.

4
Ukratko o C programima

Opi oblik C programa izgleda ovako:

#include <stdio.h>
#include ...

int main()
{
Naredbe napisane u C-u...
return 0;
}

Sve naredbe koje zapoinju znakom # nazivaju se predprocesorske naredbe.


Naredba #include se koristi kada se u programu koji se pie trebaju koristiti unaprijed
isprogramirane funkcije (posebni dijelovi programskog koda o kojima e biti vie govora kasnije). Uz
ovu naredbu mora stajati parametar oblika <ime_datoteke.h>. Taj parametar definira ime datoteke
u kojoj se nalaze prototipovi ili deklaracije funkcija koje e se koristiti u programu. Takve datoteke
imaju ekstenziju .h (engl. header file), i esto se nazivaju standardnim bibliotekama.
U programima se najee koriste naredbe za ispis znakova na ekran, za unos znakova sa
tipkovnice, za otvaranje i zatvaranje tekstualnih datoteka, itd. Deklaracije svih ovih (i mnogih
drugih) funkcija nalaze se u datoteci standard input/output header, i zato se na poetku gotovo
svakog C programa nalazi naredba #include <stdio.h>.
Naravno, na poetku svakog C programa moe se nalaziti vie #include naredbi, a ne samo jedna.

U programskim jezicima esto se nailazi na koncept funkcije. Funkcija je dio programa koji ima
svoje ime, te koji moe primati odreene argumente i vratiti odreeni argument (ako funkcija vrati
nulu, to obino znai da su sve naredbe u njoj uspjeno izvrene). Funkcije se koriste kako bi se
poveala preglednost programa, te kako bi programeri mogli koristiti ve unaprijed isprogramirana
rjeenja za uestale probleme.

Funkcija main() je glavna funkcija u C jeziku. Jedina razlika izmeu ove funkcije i svih ostalih jest to
e se funkcija main() uvijek izvesti prije svih ostalih funkcija. Ostale se funkcije moraju pozvati iz
funkcije main() da bi se uope mogle izvriti.

Linija koda int main() kae da funkcija main() vraa cijeli broj (engl. integer).

Unutar vitiastih zagrada pie se kod programa. Na kraju programa se pomou naredbe return
moe specificirati vrijednost koju e funkcija vratiti. U ovome sluaju funkcija main() vraa nulu.

Nakon svake naredbe stavlja se toka zarez (';'). Ona oznaava kraj jedne naredbe i poetak druge.

Prvi program u C-u

Slijedei program je najmanji i najjednostavniji program koji se moe napisati u C-u. Program ne
radi nita.

5
#include <stdio.h>

int main()
{
return 0;
}

Ako nije potrebno da funkcija vraa neku vrijednost, onda bi se gornji program mogao napisati u
slijedeem (ekvivalentnom) obliku:

#include <stdio.h>

void main()
{
}

Program takoer ne radi nita.

Hello World!

Najjednostavniji program napisan u bilo kojem programskom jeziku (osim onih programa koji ne
rade nita), bio bi program koji na ekran ispisuje nekakav tekst. U raunarstvu se tradicionalno za
takav tekst uzima reenica "Hello World!".

Slijedei program na ekran ispisuje "Hello World!":

#include <stdio.h>

int main()
{
printf("Hello World!\n");
return 0;
}

Naredba printf("Neki tekst..."); se koristi za ispis teksta na ekran raunala. Tekst se pie unutar
navodnika, a ako se nakon teksta jo doda i znak '\n', to znai da e kursor nakon ispisa teksta na
ekran prijei u novu liniju.

Upotrebu naredbe printf() omoguuje predprocesorska naredba #include <stdio.h>. U biblioteci


<stdio.h> se nalazi prototip naredbe printf().

Varijable

Varijable su memorijske lokacije ija se vrijednost tijekom izvoenja programa moe promijeniti, tj.
varijable su imena koja koristimo za memorijske lokacije na kojima se nalaze vrijednosti s kojima

6
radimo.

Postoje razliiti tipovi varijabli:

char (engl. character) znakovni tip


int (engl. integer) cijeli broj
short krai oblik cijelog broja
long dui oblik cijelog broja
float (engl. floating point) realni broj
double realni broj dvostruke tonosti

Razliiti tipovi varijabli zauzimaju razliite koliine memorije.

Varijable moraju biti prijavljene prije upotrebe, i to najee na poetku funkcije, prije bilo koje
izvrne naredbe. Kae se da se varijable deklariraju. Deklaracijom se varijabli pridruuju ime i tip
(npr. odreuje se da li e varijabla sadravati znak ili broj), te se deklarira potrebna koliina
memorije (npr. 1 bajt za znak ili 4 bajta za cijeli broj).

Na primjer, ovako se deklarira cjelobrojna varijabla a:

int a;

Ovo znai da je deklariran memorijski prostor (imena 'a') u koji e se spremiti cijeli broj.

Primjeri deklaracije varijabli:

int varijabla1, varijabla2;


float varijabla3, varijabla4, varijabla5;
char varijabla6;

Za razliku od deklaracije varijable, definicija varijable bi varijabli pridruila i neku vrijednost. Na


primjer:

int varijabla1 = 5;
float varijabla2 = 2.3;
char varijabla3 = 'c';

int varijabla4 = varijabla1; // varijabla4 = 5

int varijabla5, varijabla6;


varijabla5 = varijabla6 = 7; // varijabla5 = 7, varijabla6 = 7

char a = 'A'; // a = A
char b = 65; // b = A --> u ASCII tablici, znak 'A' je predstavljen sa brojem 65

Imena varijabli sastoje se od slova i znamenki, pri emu prvi znak mora uvijek biti slovo. Znak
podcrte '_' (engl. underscore) uvaava se kao slovo, to je bitna stvar ako se eli poveati itljivost

7
programa.

Programeri varijablama obino daju imena u nekom od slijedeih formata:

int varijabla;
int druga_varijabla;
int trecaVarijabla;

Primjeri neispravnih imena varijabli:

int 1varijabla; // prvi znak ne smije biti broj


int prva varijabla; // nisu dozvoljeni razmaci
int $varijabla; // znak '$' nije dozvoljen samo slova, brojke ili '_'
int const; // const je kljuna rije (unaprijed rezervirana)

Operatori u C-u

Aritmetiki operatori: +, -, *, /, te modul operator % (ostatak dijeljenja).

Relacijski operatori: < (manje), > (vee), <= (manje ili jednako), >= (vee ili jednako), == (jednako),
!= (nije jednako). Relacijski operatori se koriste kod usporedbi.

Logiki operatori: && (i) i || (ili).

Operatori uveavanja (inkrementiranja) i umanjivanja (dekrementiranja): ++ i --. Njihova bitna


karakteristika je da mogu biti koriteni kao sufiks operatori (npr. varijabla++) ili kao prefiks
operatori (npr. ++varijabla).

Operator konverzije tipova: cast. Ako u programskom kodu naiemo na operator iji su operandi
razliitog tipa (npr. jedan je int, a drugi float), itav e izraz dobiti konanu vrijednost po tono
odreenim pravilima. Cast operator pretvara izraz bilo kojeg tipa u eljeni tip. Openita formula
glasi: (tip) izraz.

Primjer:

#include <stdio.h>

void main()
{
int x;
char y = 'A';
x = (int) y;
printf("x = %d\n", y);
}

8
ISPIS PROGRAMA:
x = 65

U gornjem primjeru, varijabli x se dodjeljuje ASCII vrijednost varijable y (odnosno znaka A), a to je
65.

Operatori za manipulaciju bitovima (bitznaajni operatori):


& binarno I (AND)
| binarno ILI (OR)
^ binarno ekskluzivno ILI (XOR)
~ jedinini komplement (NOT)
<< pomak u lijevo (SHIFT LEFT)
>> pomak u desno (SHIFT RIGHT)

Operatori dodjele vrijednosti. Veina binarnih operatora ima odgovarajui operator dodjele
vrijednosti po pravilu: izraz1 operator= izraz2. To je ekvivalentno izrazu: izraz1 = (izraz1) operator
(izraz2). Na primjer, a *= b je ekvivalentno izrazu a = a * b. a *= b je samo krai nain zapisa izraza
a = a * b.

Napomena: obratite pozornost na operator dodjele vrijednosti (=) i operator usporeivanja dviju
vrijednosti (==). Ovi operatori nisu jednaki! Mijeanje ovih dvaju operatora je jedna od najeih
greaka u programiranju! Ovakva se greka naziva logika greka, i prevoditelj vas na nju nee
upozoriti.

Operator '=' nekoj varijabli dodjeljuje neku vrijednost, npr. a = 3.

Operator '==' usporeuje dvije varijable i vraa nulu ili jedinicu, ovisno o tome jesu li te varijable
jednake.

Neke od najee koritenih funkcija u C-u

Neke od najee koritenih funkcija u C-u su:

printf("%d", argument) ispisuje znak ili niz znakova na ekran


scanf("%d", &argument) prihvaa znak ili niz znakova unesenih sa tipkovnice
getchar() prihvaa samo jedan znak sa tipkovnice
putchar() ispisuje samo jedan znak na ekran
toupper(c) pretvara mala slova u velika
tolower(c) pretvara velika slova u mala

9
DODATAK

Microsoft (MS) Visual Studio 2010 Express

Svi programi opisani u vjebama iz kolegija (Uvod u) Raunala i programiranje mogu se izvravati u
MS Visual Studio integriranoj razvojnoj okolini (engl. Integrated Development Environment ili IDE).
IDE je razvojna okolina unutar koje programeri piu i testiraju svoje programe.

Na linku http://www.microsoft.com/express/Downloads/ moe se pronai Microsoft Visual Studio


2010 Express. To je IDE koji se koristi u edukacijske i nekomercijalne svrhe.

Da biste instalirali MS Visual Studio Express 2010, slijedite ove upute:

1. Otiite na web stranicu http://www.microsoft.com/express/Downloads/.


2. Odaberite Visual C++ 2010 Express.
3. Odaberite engleski jezik.
4. Otvoriti e se prozor koji vas pita elite li skinuti aplikaciju sa interneta. Kliknite OK.
Napomena: program koji ste sauvali je samo aplikacija koja e pokrenuti skidanje MS
Visual Studio 2010 Express sa interneta.
5. Pokrenite skinutu aplikaciju i slijedite postupak instalacije.
6. Priekajte dok se aplikacija ne instalira (ovo e malo potrajati...).

Pokrenite aplikaciju. Pojaviti e se ovakav prozor:

10
Da biste mogli napisati i pokrenuti prvi program u C-u, slijedite ove upute:

1. Kliknite na File --> New --> Project.

2. Odaberite Win32 Console Application.

3. Odaberite ime novog projekta (npr. prviProjekt) i kliknite OK.

4. Otvoriti e se novi prozor imena Win32 Application Wizard. Pod Application Settings
odaberite Console application i Empty project, te deselektirajte Precompiled header.

11
5. Kliknite Finish. Otvoriti e se ovakav prozor:

6. Sa lijeve strane moete vidjeti nekoliko datoteka. Desnim klikom mia kliknite na datoteku
imena Source Files, te odaberite Add --> New Item. Odaberite C++ File (.cpp). Novoj datoteci
dodijelite neko ime (npr. mojPrviProgram). Kliknite Add. Otvoriti e se upravo kreirana
tekstualna datoteka.

12
7. U datoteku upiite slijedei programski kod:

#include <stdio.h>

void main()
{
printf("Hello World!\n");
getchar(); /* program eka unos znaka sa tipkovnice */
}

Na kraju programa nalazi se poziv funkcije getchar(). Ta funkcija eka na unos znaka sa
tipkovnice. Da se u programu ne nalazi ova linija koda, prozor sa tekstom Hello World! bi se
zatvorio im bi se program izvrio (gotovo trenutano), te ne biste uspjeli vidjeti rezultate
programa.

8. Kliknite Debug --> Build Solution, pa zatim Debug --> Start Debugging. Alternativno moete
pritisnuti F7 (Build Solution) i F5 (Start Debugging).

9. Va program e se izvriti. Otvoriti e se slijedei prozor:

10. Pritisnite Enter da bi zatvorili prozor.

13
VJEBA 2

Komentari u C-u

#include <stdio.h>

void main()
{
printf("Hello World!\n"); /* ispisuje "Hello World!" na ekran */
}

Prilikom prevoenja programa, prevoditelj zanemaruje sve to se nalazi unutar znakova '/*' i '*/'.
Oni oznaavaju poetak i kraj komentara.

/* ovo je komentar */

/*
i ovo je komentar
*/

Ovakva vrsta komentara se danas sve rijee koristi. Popularnost im je pala nakon to su u
programiranje uvedeni jednoredni komentari "uvezeni" iz programskog jezika C++.

// komentar

Gornji komentar je jednoredi komentar. Prednost ovakvih komentara je to programer ne mora


paziti na zavretak komentara, a nedostatak je taj to su ogranieni na jedan redak.

Komentari su posebno vani kod velikih programa (sa vie tisua linija koda), jer programski kod
postaje pregledniji i razumljiviji.

Escape nizovi

Kombinacije znakova koje zapoinju sa znakom '\' (engl. backslash), te iza kojih slijedi neki drugi
znak, slovo, ili niz brojeva (ako se koristi oktalni ili heksadecimalni zapis), nazivaju se escape nizovi.
Njihova zadaa jest da promijene znaenje odreenih znakova ili simbola (Tablica 2.1). Na primjer,
znak 'n' se tretira na jedan nain kada predstavlja ime varijable, a na drugi nain kada se ispred
njega nalazi znak '\'.

Escape nizovi koji se najee koriste u C-u:

Tablica 2.1. Escape nizovi

Znak Escape niz ASCII


zvono (upozorenje) \a 007

14
(engl. bell code, audible alert)
backspace \b 008
vodoravni tabulator \t 009
okomiti tabulator \v 011
novi red ili LF (engl. Line Feed) \n 010
nova stranica \f 012
CR (engl. Carriage Return) \r 013
navodnik \" 034
jednostruki navodnik (apostrof) \' 039
upitnik \? 063
backslash \\ 092
null znak \0 000

Znakovi pretvorbe

#include <stdio.h>

int main()
{
int a; // deklariramo cjelobrojnu varijablu a
a = 10; // varijabli a pridruujemo vrijednost 10
printf("%d\n", a); // na ekran ispisujemo vrijednost varijable a
return 0; // funkcija vraa nulu
}

U gornjem se primjeru koristi znak %d. Kada se ispred nekih odreenih slova (Tablica 2.2) nalazi
znak '%', onda slovo predstavlja znak pretvorbe (engl. conversion character). On oznaava tip ili
format znaka koji se ispisuje na ekran ili uitava sa tipkovnice (npr. int, float...).

Tablica 2.2. Znakovi pretvorbe

Znak pretvorbe Znaenje


c podatak je znak
d podatak je decimalna cjelobrojna vrijednost s predznakom
e podatak je realna vrijednost u eksponencijalnoj formi
f podatak je realna vrijednost bez eksponencijalne forme
g podatak je realna vrijednost
podatak se zapisuje u najkraoj moguoj formi (ili f ili e)
i podatak je decimalna cjelobrojna vrijednost s predznakom

15
podatak moe biti zapisan u dekadskom, oktalnom ili heksadecimalnom
brojevnom sustavu
o podatak je oktalna vrijednost, bez vodee nule
s podatak je niz znakova (engl. string)
null znak ('\0') se automatski dodaje na kraj stringa
u podatak je decimalna vrijednost bez predznaka
x podatak je heksadecimalna vrijednost, bez vodeeg 0x
[. . .] podatak je niz znakova koji moe sadravati razmake

Funkcija printf()

Funkcija printf() se koristi za ispis znakova na ekran raunala.

Primjer:

#include <stdio.h>

void main()
{
int a = 5;
float b = 5.1;

// na ekran ispisujemo vrijednost cjelobrojne varijable a


printf("Vrijednost varijable a = %d\n", a);

// na ekran ispisujemo vrijednost realne varijable b


printf("Vrijednost varijable b = %f\n", b);

// program eka na unos znaka sa tipkovnice


getchar();
}

Funkcija printf() dozvoljava koritenje ogranienja na minimalnu duljinu niza koji se upisuje (npr. niz
brojeva). Ako je niz vei od minimalne duljine, onda ogranienje nema nikakvog utjecaja na ispis
niza. U programerskim krugovima ta je situacija poznata pod imenom "override". Funkcija printf()
takoer dozvoljava specifikaciju tonosti nekog broja (npr. zaokruivanje broja na odreeni broj
decimala iza decimalne toke).

Primjer:

#include <stdio.h>

void main()
{

16
int a = 12345;
float b = 345.678;

printf("%3d\n", a);
printf("%10d\n\n", a);

printf("%6g\n", b);
printf("%13g\n\n", b);

printf("%13e\n", b);
printf("%16e\n\n", b);
printf("%.4f\n", b);
printf("%.30e\n", b);

getchar();
}

ISPIS PROGRAMA:

Funkcija scanf()

Funkcija scanf() se koristi za uitavanje znakova sa tipkovnice.

Primjer:

#include <stdio.h>

void main()
{
int a;
float b;

// sa tipkovnice se uitava cijeli broj i sprema se u varijablu a


scanf("%d", &a);

// sa tipkovnice se uitava realni broj i sprema se u varijablu b

17
scanf("%f", &b);

getchar();
}

Kada se ispred imena varijable nalazi znak &, onda &ime_varijable predstavlja adresu te varijable.
Da bi funkcija scanf() mogla nekoj varijabli promijeniti vrijednost, najprije mora znati na kojoj se
memorijskoj adresi ta varijabla nalazi.

Kao i funkcija printf(), funkcija scanf() omoguava postavljanje ogranienja na duljinu niza koji se
uitava sa tipkovnice.

Primjer:

#include <stdio.h>

void main()
{
int a, b, c;
scanf("%3d %3d %3d", &a, &b, &c);
printf("a = %d b = %d c = %d\n", a, b, c);
}

Unos: 1 2 3
Ispis: a = 1 b = 2 c = 3

Unos: 123 456 789


Ispis: a = 123 b = 456 c = 789

Unos: 123456789
Ispis: a = 123 b = 456 c = 789

Unos: 1234 5678 9


Ispis: a = 123 b = 4 c = 567
Napomena: preostala dva znaka e biti ignorirana, osim ako ih ne pokupi neka druga scanf()
funkcija.

18
ZADACI

Zadatak 2.1. Napiite program koji ispisuje zauzee memorije u bajtovima (engl. byte) za sve
standardne tipove programskog jezika C (char, int, short, long, float, double, unsigned short,
unsigned int, unsigned long). Koristite funkciju sizeof().

Rjeenje:

#include <stdio.h>

void main ()
{
printf("Sizeof(char) = %d", sizeof(char));
printf("\nSizeof(int) = %d", sizeof(int));
printf("\nSizeof(short) = %d", sizeof(short));
printf("\nSizeof(long) = %d", sizeof(long));
printf("\nSizeof(float) = %d", sizeof(float));
printf("\nSizeof(double) = %d", sizeof(double));
printf("\nSizeof(unsigned short) = %d", sizeof(unsigned short));
printf("\nSizeof(unsigned int) = %d", sizeof(unsigned int));
printf("\nSizeof(unsigned long) = %d\n", sizeof(unsigned long));

getchar();
}

ISPIS PROGRAMA:

Zadatak 2.2. Napiite program u kojem deklarirate integer i char varijablu. Objema pridijelite
vrijednost znakovne konstante (primjerice 'c'). Ispiite vrijednosti varijabli i veliinu memorije koju
zauzimaju. Kako komentirate rezultate?

Rjeenje:

#include <stdio.h>

void main()

19
{
int i = 'c';
char n = 'c' ;

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


printf("sizeof(char) = %d\n", sizeof(char));
printf("vrijednost (i) = %d\n", i);
printf("vrijednost (n) = %d\n", n);

printf("vrijednost (i) = %c\n", i);


printf("vrijednost (n) = %c\n", n);

getchar();
}

ISPIS PROGRAMA:

Zadatak 2.3. Napiite program koji ispisuje znakove 'z' i 'Z', s tim da su za prvi znak rezervirana 3
mjesta za ispis na ekran, a za drugi 5 mjesta.

Rjeenje:

#include <stdio.h>

void main()
{
printf("Slova:\n%3c\n%5c\n", 'z', 'Z');
getchar();
}

Zadatak 2.4. Primjer cjelobrojnog i realnog dijeljenja. Kako komentirate rezultate programa?

#include <stdio.h>

void main()
{
int a = 5;
int b = 2;

20
int d = 5/2; // cjelobrojno dijeljenje rezultat je 2
float c = a/b; // Iako je c float, vri se cjelobrojno dijeljenje jer su i a i b cijeli brojevi

printf("c = %f\n",c);
printf("Uzrok problema : 5/2 = %f\n", 5/2);
printf("Popravljeno : 5.0/2.0 = %f\n", 5.0/2.0);
printf("Moze i : 5/2.0 = %f i 5.0/2 = %f \n", 5/2.0, 5.0/2);
printf("Za varijable moramo uvesti cast-ing : %f\n", (float)a/(float)b);
getchar();
}

ISPIS PROGRAMA:

Zadatak 2.5. Napiite program za unos cijelog broja sa tipkovnice.

Rjeenje:

#include <stdio.h>

void main()
{
int x;

printf("Unesite cijeli broj: ");


scanf("%d", &x);

printf("Unijeli ste broj: %d\n", x);

getchar();
getchar();
}

Zadatak 2.6. Napiite program za unos cijelog broja sa tipkovnice. Neka program ispie kvadrat tog
broja.

Rjeenje:

#include <stdio.h>

21
void main()
{
int a, b;

printf("Unesite varijablu a.\n");


scanf("%d", &a); // sa tipkovnice se uitava varijabla a

b = a * a; // u varijablu b ide vrijednost kvadrata broja a

printf("Kvadrat broja a je %d.\n", b);

getchar();
getchar();
}

22
DOMAI RAD

Zadatak 2.7. Napiite program za unos dva realna broja. Neka program ispie rezultat njihovog
zbrajanja, oduzimanja, mnoenja i dijeljenja.

Zadatak 2.8. Napiite program za unos realnog broja. Neka program ispie kvadrat i korijen tog
broja. Napomena: funkcija za raunanje korijena je sqrt() (engl. square root) i definirana je u
biblioteci <math.h>.

Zadatak 2.9. Napiite program koji za proizvoljni radijus rauna opseg kruga.

23
DODATAK

ASCII tablica

Tablica 2.3. ASCII tablica

24
VJEBA 3

Naredbe kontrole toka

Naredbe kontrole toka svoje djelovanje zasnivaju na logikim izrazima. Najee se koriste u svrhu
grananja programa, tj. odabira jedne od nekoliko moguih radnji.

Jedna od najee koritenih naredbi za kontrolu toka je if-else konstrukcija.

If-else konstrukcija openito ima slijedeu sintaksu:

if (logiki izraz)
naredba1

if (logiki izraz)
naredba 1
else
naredba2

Slika 3.1. Grafiki prikaz grananja

Primjer (if-else konstrukcija): Programsko rjeenje za grananje prikazano na slici 3.1:

#include <stdio.h>

void main()
{
int a = 7;
int b = 3;

if (a > b)
printf("Vrijednost varijable a = %d.\n", a);
else
printf("Vrijednost varijable b = %d.\n", b);

getchar();

25
}

ISPIS PROGRAMA:
Vrijednost varijable a = 7.

Umjesto if-else konstrukcije ponekad se moe koristiti uvjetni operator. Uvjetni operator je
ternarni operator, jer ima tri elementa.

Opi oblik:

logiki_izraz ? izraz_1 : izraz_2;

Program bi u ovom sluaju ispitao vrijednost logikog izraza, te ako je ta vrijednost jednaka jedinici
izvrio bi se izraz 1, a ako je jednaka nuli izvrio bi se izraz 2.

Primjer (uvjetni operator): Program provjerava da li je varijabla a vea od nule. Ako jest, postavlja
varijablu b na jedinicu, a ako nije, postavlja varijablu b na nulu. Zatim ispisuje vrijednost varijable b.

#include <stdio.h>

void main()
{
int a = 7;
int b;

(a > 0) ? b = 1 : b = 0;

printf("b = %d \n", b);

getchar();
}

ISPIS PROGRAMA:
b=1

Programske petlje

Programske petlje se koriste kada se vie puta eli ponoviti ista naredba ili blok naredbi. U
programskom jeziku C postoje tri petlje: for, while i do-while.

Opi oblik programske petlje for:

for (inicijalizacija; uvjet; promjena vrijednosti)


{
blok naredbi
}

26
Primjer (for petlja): Program ispisuje brojeve od 0 do 9.

#include <stdio.h>
void main()
{
int a;

for (a = 0; a < 10; a++)


printf("%d\n", a);

getchar();
}

Opi oblik programske petlje while:

while (uvjet)
{
blok naredbi
}

Primjer (while petlja): Program ispisuje brojeve od 9 do 0.

#include <stdio.h>

void main()
{
int a = 9;

while (a > -1)


{
printf("%d\n", a);
a--;
}

getchar();
}

Opi oblik programske petlje do-while:

do
{
blok naredbi
} while (uvjet);

27
Primjer (do-while petlja): Program ispisuje brojeve od 0-9.

#include <stdio.h>

void main()
{
int a = 0;

do
{
printf("%d\n", a);
a++;
}
while (a < 10);

getchar();
}

Petlje for i while se ne moraju uope izvriti (ako uvjet nije ispunjen), ali petlja do-while je
specifina po tome to se ona uvijek izvri barem jedan put, pa tek nakon prvog izvravanja
provjerava uvjet.

28
ZADACI

Zadatak 3.1. Napiite program koji prihvaa i usporeuje bilo koja dva cijela broja unesena sa
tipkovnice. Neka se na ekran ispie rezultat usporedbe tih brojeva.

Rjeenje:

#include <stdio.h>

void main()
{
int a;
int b;

printf("Unesite prvi broj: ");


scanf("%d", &a);

printf("Unesite drugi broj: ");


scanf("%d", &b);

if (a > b)
printf("%d > %d \n", a, b);
else if (a < b)
printf("%d > %d \n", b, a);
else
printf("%d = %d \n", a, b);

getchar();
getchar();
}

Zadatak 3.2. Napiite program koji ispisuje sumu svih brojeva od 1 do 10.

Rjeenje:

#include<stdio.h>

void main()
{
int i;
int suma = 0;

for (i = 1; i <= 10; i++)


suma = suma + i;

29
printf("Suma je %d.\n", suma);

getchar();
}

Zadatak 3.3. Napiite program koji od korisnika trai da unese dvije varijable (tipa int), s tim da
druga varijabla mora biti manja od prve. Zahtjev za unos druge varijable se ponavlja (koristite while
petlju) sve dok korisnik ne unese cijeli broj koji je manji od prvog broja. Program zatim treba
ispisati: "Prva varijabla je (ispisati vrijednost), a druga je (ispisati vrijednost). Druga varijabla je
manja od prve."

Rjeenje:

#include <stdio.h>

void main()
{
int a;
int b;
int uvjet = 1;

printf("Upisite vrijednost prve varijable: ");


scanf("%d", &a);

while (uvjet) // ponavlja se sve dok je uvjet jednak jedinici


{
printf("Upisite vrijednost druge varijable tako da bude MANJA od prve: ");
scanf("%d", &b);

if (b < a)
uvjet = 0;
}

printf("Prva varijabla je %d, a druga je %d. Druga varijabla je manja od prve.\n", a, b);

getchar();
getchar();
}

Zadatak 3.4. Napiite program u kojem korisnik unosi tri cijela broja, a program ih sortira po veliini
(od najmanjeg prema najveem) iskljuivo koritenjem if naredbi. Ne koristite petlje!

Rjeenje:

#include <stdio.h>

30
void main()
{
int a, b, c;
int temp;

printf("Upisite 1. broj: ");


scanf("%d", &a);

printf("Upisite 2. broj: ");


scanf("%d", &b);

printf("Upisite 3. broj: ");


scanf("%d", &c);

// ako je a > b, b postaje a


if (a > b)
{
temp = a;
a = b;
b = temp;
}

// ako je a > c, c postaje a


if (a > c)
{
temp = a;
a = c;
c = temp;
}

// ako je b > c, c postaje b


if (b > c)
{
temp = b;
b = c;
c = temp;
}

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

getchar();
getchar();
}

Zadatak 3.5. Napiite program u kojem korisnik unosi ocjene ispita, sve dok se ne unese 0. Ocjene
izvan doputenog raspona ocjena od 1 do 5 se zanemaruju. Program treba ispisati koliko je na

31
ispitu bilo pozitivnih (prolaznih), a koliko negativnih (nedovoljnih) ocjena, te kolika je bila prosjena
ocjena ispita.

Rjeenje:

#include <stdio.h>

void main ()
{
int ocjena, brPoz = 0, brNeg = 0, suma = 0;
float prosjek;

do
{
printf("Unesite ocjenu: \n");
scanf("%d", &ocjena);

if ((ocjena < 0) || (ocjena > 5))


{
printf("NEPOSTOJECA OCJENA!\n");
}

else
{
suma += ocjena;

if (ocjena == 1)
brNeg++;

else if (ocjena > 1)


brPoz++;
}
} while (ocjena != 0);

prosjek = (float)suma/(brPoz + brNeg);

printf("\nBroj pozitivnih ocjena: %d\n", brPoz);


printf("Broj negativnih ocjena: %d\n", brNeg);
printf("--------------------------\n");
printf("Ukupno ocjena: \t\t%d\n", brPoz + brNeg);
printf("\nProsjecna ocjena iznosi %g.\n", prosjek);
getchar();
getchar();
}

32
Zadatak 3.6. to je rezultat izvoenja slijedeih programa? Ispiite sve meurezultate do cilja!

a) b) c)

#include <stdio.h> #include <stdio.h> #include <stdio.h>

void main() void main() void main()


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

d) e) f)

#include <stdio.h> #include <stdio.h> #include <stdio.h>

void main() void main() void main()


{ { {
int i = 5; int i = 5; int i = 5;
i = i + 2; int uvjet = 1;
if (--i > 4) int suma = 0;
if (i < 5) i = i + 3;
printf ("Izlaz A\n"); while (uvjet)
printf("%d\n", i); {
else } if (i-- > 2)
printf("Izlaz B\n"); uvjet = 0;
} suma = suma + i;
}

printf("%d\n", suma);
}

Rjeenja:

a) b) c)

0 4 5
1 3 4
2 2 3
3 1 2
4 0 1

d) e) f)

Izlaz B 4 4

33
DODATNI ZADACI

Zadatak 3.7. Napiite program koji pomou for petlje ispisuje kvadrate, kubove i korijene prvih 20
prirodnih brojeva. Napomena: funkcija za raunanje korijena je sqrt (engl. square root) i nalazi se u
standardnoj biblioteci <math.h>.

Zadatak 3.8. Napiite program koji generira i ispisuje deset sluajnih brojeva. Napomena: koristite
standardne biblioteke <stdlib.h> i <time.h>, te funkcije srand() i rand().

Zadatak 3.9. Napiite program za pogaanje broja generiranog od strane raunala. Broji se broj
pokuaja, a pri svakom pokuaju raunalo daje informaciju da li je broj vei, manji ili pogoen. Ako
je broj pogoen, izlazi se iz programa, uz ispis pogoenog broja te ukupnog broja pokuaja.

Napomena vezana uz zadatke 3.8 i 3.9: U programiranju ne postoje stvarno sluajni brojevi, ve
samo pseudosluajni. Generator pseudosluajnih brojeva e za istu ulaznu vrijednost uvijek
generirati iste pseudosluajne brojeve. Funkcija srand() postavlja inicijalnu vrijednost za generator
sluajnih brojeva koji je implementiran u funkciji rand(). Ako se ne koristi srand(), rand() e
izgenerirati uvijek isti niz pseudosluajnih brojeva [2].

DOMAI RAD

Zadatak 3.10. Napiite program u kojem korisnik unosi etiri cjelobrojne varijable, a program ih
sortira po veliini (od najvee prema najmanjoj) iskljuivo koritenjem if naredbi (biti e vam
potrebno est if naredbi). Ne koristite petlje!

Zadatak 3.11. a) Napiite program koji ispisuje cijelu ASCII tablicu. b) Napiite program u kojem
korisnik unosi neki znak (slovo ili broj) a program onda ispisuje sva ostala slova ili brojeve koji se u
ASCII tablici nalaze iza unesenog znaka. Na primjer, ako korisnik upie broj '7', program treba
ispisati '8 9'. Ako korisnik unese 'b', program treba ispisati ostatak abecede. Razlikujte mala i velika
slova! Ignorirajte sve unesene znakove koji ne predstavljaju slovo ili broj! Napomena: moete
koristiti funkcije isdigit(), isupper() i islower() za provjeru unesenih znakova, ali onda morate
ukljuite biblioteku <ctype.h>.

Zadatak 3.12. Napiite program koji ispisuje rjeenja kvadratne jednadbe. Neka korisnik unese
koeficijente kvadratne jednadbe. Podsjetnik:

2
ax bxc=0

b b2 4ac
x=
2a

34
VJEBA 4

Naredba switch-case

Ako u izvornom kodu postoji posebno dugaak lanac if-else naredbi, dobra je praksa takve naredbe
zamijeniti sa naredbom switch-case. Naredba switch-case je preglednije zapisana if-else naredba.
Najee se koristi za stvaranje izbornika (engl. menu) [3]. Na primjer, ako korisnik unese broj '1',
izvri se jedna naredba, a ako unese '2', izvri se neka druga naredba.

Opi oblik naredbe switch-case:

switch (izraz)
{
case 'vrijednost izraza 1':
...
break;
case 'vrijednost izraza 2':
...
break;
...
default: // izvrava se ako nijedan drugi uvjet nije zadovoljen
...
}

Primjer (switch-case naredba): Program dozvoljava unos jednoznamenkastog cijelog broja sa


tipkovnice, te obavijetava korisnika o tome je li uneseni broj paran, neparan ili jednak nuli.

#include <stdio.h>

void main()
{
int a;

printf("Unesite cijeli broj: ");


scanf("%d", &a);

switch (a)
{
case 0:
printf("Uneseni broj je jednak nuli.\n");
break;
case 1:
case 3:
case 5:
case 7:
case 9:

35
printf("Uneseni broj je neparan.\n");
break;
case 2:
case 4:
case 6:
case 8:
printf("Uneseni broj je paran.\n");
break;
default:
printf("Dozvoljen je unos samo jednoznamenkastih brojeva.\n");
break;
}

getchar();
getchar();
}

Primijetite da je nakon vie case naredbi izostavljena naredba break. To znai da e se za sve te
case naredbe izvriti isti blok programskog koda (prvi na koji program naie tijekom izvoenja).
Ovakva je situacija poznata pod imenom "propadanje" kroz switch-case naredbu (engl. fall-
through).

Naredbe break i continue

Naredba break se koristi za prekid izvravanja neke petlje. Slino, naredba continue se koristi za
prekid jedne iteracije neke petlje, te skok na iduu iteraciju.

Primjer (naredba break):

#include <stdio.h>

void main()
{
int i;

for (i = 0; i < 3; i++)


{
printf("Unutar petlje...\n");
break; // izlazak iz petlje
}

printf("Izasli smo iz for petlje!\n");

getchar();
}

36
ISPIS PROGRAMA:
Unutar petlje...
Izasli smo iz petlje!

Primjer (naredba continue):

#include <stdio.h>

void main()
{
int i;

for (i = 0; i < 3; i++)


{
printf("Prvi tekst...\n");
continue; // skae na provjeru uvjeta
printf("Drugi tekst...\n"); // ovaj se dio koda nikad ne izvri
}

getchar();
}

ISPIS PROGRAMA:
Prvi tekst...
Prvi tekst...
Prvi tekst...

Naredba goto

Naredba goto je naredba bezuvjetnog skoka. Izvravanjem naredbe goto program se grana na
zadanu programsku liniju [3].

Opi oblik:

#include <stdio.h>

void main()
{
ime_labele:
...programski kod...

goto ime_labele;
}

37
Primjer (goto naredba):

#include <stdio.h>

void main()
{
int i = 0;
start: // start je ime labele
printf("Beam me up, Scotty!\n");
if (i == 0)
{
i = 1;
goto start; // program skae na labelu start
}

getchar();
}

ISPIS PROGRAMA:
Beam me up, Scotty!
Beam me up, Scotty!

Veina programera izbjegava koritenje goto naredbe, budui da ona najee smanjuje
preglednost i razumljivost programskog koda. U programskim jezicima vie razine ova se naredba
gotovo nikad ne koristi, a neki je jezici ak i zabranjuju. Sve to se moe napraviti sa naredbom
goto, moe se napraviti i sa standardnim petljama u C-u.

End-of-File (EOF)

End-of-File (EOF) oznaava stanje u kojem se nae operacijski sustav kada na standardnom ulazu
ponestane znakova za itanje. EOF je implementiran kao cjelobrojna konstanta koja ovisi o
operacijskom sustavu, i na Windows-ima je definirana kao -1.

Ako koristite neki drugi operacijski sustav, na slijedei nain moete provjeriti vrijednost konstante
EOF:

#include <stdio.h>

void main()
{
printf("%d\n", EOF);
getchar();
}

38
Funkcija getchar()

Funkcija getchar() se koristi za itanje samo jednog znaka sa standardnog ulaza.

Prototip funkcije:

int getchar(void);

Primijetite da funkcija vraa cijeli broj, a ne znak!

Primjer:

#include <stdio.h>

void main()
{

int i;
int brojac = 0;

while ((i = getchar()) != EOF)


brojac++;

printf("Broj upisanih znakova: %d.\n", brojac);

getchar();
}

Da bi zaustavili unos znakova u gornjem programu, tj. da bi signalizirali operacijskom sustavu da


elite prestati sa unosom znakova, pozicionirajte se u novi redak i pritisnite Ctrl-Z (Windows) ili Ctrl-
D (Linux). Funkcija getchar() e onda znati da je dolo do EOF, i vratiti e -1.

Umjesto da pritiu Ctrl-Z ili Ctrl-D kada ele prekiniti unos znakova, programeri esto koriste
makro naredbe.

Primjer:

#include <stdio.h>

#define EOF '\n' // makro naredba koja EOF u programskom kodu zamjenjuje sa \n

void main()
{

int i;
int brojac = 0;

39
while ((i = getchar()) != EOF)
brojac++;

printf("Upisali ste %d znakova.\n", brojac);

getchar();
}

U ovome programu vie nije potrebno pritisnuti Ctrl-Z ili Ctrl-D za prekid unosa znakova, ve je
potrebno samo prijei u novu liniju, tj. stisnuti enter.

Napomena: jedna od estih greaka u programiranju jest dodjela vrijednosti koju vraa funkcija
getchar() nekoj znakovnoj varijabli, te onda usporeivanje te varijable sa EOF.

Primjer:

#include <stdio.h>

void main()
{

char i; // primijetite da je ovdje sada char, a ne int --> ovo se ne preporuuje


int brojac = 0;

while ((i = getchar()) != EOF)


brojac++;

printf("Broj upisanih znakova: %d.\n", brojac);

getchar();
}

Sada pretpostavimo da char varijabla moe sadravati jednu od 128 znakovnih konstanti (u ASCII
tablici je 128 znakova). Funkcija getchar() moe vratiti cjelobrojnu vrijednost bilo koje od tih 128
znakovnih konstanti, ali moe vratiti i -1 kada naie na EOF. Dakle, funkcija getchar() moe vratiti
ukupno 129 moguih cjelobrojnih vrijednosti.

U gornjem primjeru, kada se cjelobrojna vrijednost koju vraa funkcija getchar() (ukupno 129
moguih vrijednosti) pokua mapirati u char varijablu (ukupno 128 moguih vrijednosti), mora doi
do kolizije.

Ako se sluajno -1 konvertira u 65 (znak 'A' u ASCII tablici), program moe prestati sa itanjem
znakova iz datoteke ili sa standarnog ulaza kada naie na znak 'A', jer e pomisliti da je rije o
oznaci za EOF. Da je pak varijabla 'i' bila deklarirana kao unsigned char, EOF se nikada ne bi
konvertirao u negativnu vrijednost, pa bi program zaglavio u beskonanoj petlji.

Meutim, ovakve vas stvari trebaju zabrinjavati samo kada niste sigurni koliko memorije zauzimaju

40
int i char varijable. U dananje su vrijeme uglavnom i jedna i druga dovoljno velike da, bez kolizije
sa nekom drugom vrijednou, prihvate vrijednost koju vraa funkcija getchar(). Ipak, kada se radi o
usporeivanju te vrijednosti sa EOF, uvijek se preporuuje koristiti int varijablu umjesto char
varijable. Ako se pak ipak odluite za char, morate pripaziti da uvijek bude deklarirana kao char ili
signed char, a nikada unsigned char!

41
ZADACI

Zadatak 4.1. Napiite program koji oponaa rad jednostavnog kalkulatora koji podrava operacije
zbrajanja, oduzimanja, mnoenja i dijeljenja. Korisnik programu zadaje izraz, primjerice 9 * 5, a
program ispisuje rezultat tog izraza. Koristite naredbu switch-case.

Rjeenje:

#include <stdio.h>

void main()
{
int broj1 = 0, broj2 = 0;
float rezultat;
char operator1;

printf("Unesite izraz: \n");


scanf("%d %c %d", &broj1, &operator1, &broj2);

switch (operator1)
{
case '+':
rezultat = broj1 + broj2;
printf("%d %c %d = %.4f\n", broj1, operator1, broj2, rezultat);
break;

case '-':
rezultat = broj1 - broj2;
printf("%d %c %d = %.4f\n", broj1, operator1, broj2, rezultat);
break;

case '*':
rezultat = broj1 * broj2;
printf("%d %c %d = %.4f\n", broj1, operator1, broj2, rezultat);
break;

case '/':
if (broj2 == 0)
{
printf("Greska: dijeljenje sa nulom!\n");
break;
}

else
{
rezultat = (float)broj1 / broj2;

42
printf("%d %c %d = %.4f\n", broj1, operator1, broj2, rezultat);
break;
}

default:
printf("Nepoznata operacija!\n");
break;
}

getchar();
getchar();
}

Zadatak 4.2. Napiite program koji od korisnika trai da unese dva cijela broja, te zatim ispisuje tri
broja koja se nalaze izmeu njih. Ako je udaljenost brojeva manja od tri, program treba ispisati
odgovarajuu poruku.

Rjeenje:

#include <stdio.h>

void main ()
{
int x, y, i;

printf("Unesite dva cijela broja: ");


scanf("%d %d", &x, &y);

oznaka:
if (y >= x)
{
if ((y - x) < 4)
{
printf("Brojevi su nedovoljno udaljeni!\n");
}

else
{
printf("Brojevi unutar zadanih granica: ");
for (i = x + 1; i < x + 4; i++)
printf("%d ", i);
}
}

else
{

43
// ako je y > x zamijenimo im vrijednosti
int t = x;
x = y;
y = t;

goto oznaka;
}

getchar();
getchar();
}

Zadatak 4.3. Napiite program u kojem korisnik unosi deset cijelih brojeva (koristite for petlju), a
program vraa njihovu aritmetiku sredinu.

Rjeenje:

#include <stdio.h>

void main()
{
int broj = 0;
int brojac = 10;
int suma = 0;
int i;
float prosjek = 0;

for (i = 0; i < brojac; i++)


{
printf("Unesite broj: ");
scanf ("%d", &broj);
suma += broj;
}

prosjek = (float)suma/brojac;

printf("Prosjecna vrijednost ovih deset unesenih brojeva iznosi: %f\n", prosjek);

getchar();
getchar();
}

44
Zadatak 4.4. Napiite program koji, uz pomo petlji, na ekran ispisuje:

a) b)

* ABBB
** AABB
*** AAAB
**** AAAA

Rjeenje (a):

#include <stdio.h>

void main()
{
char znak = '*';
int i, j;

for (i = 4; i > 0; i--)


{
for (j = i-1; j < 4; j++)
{
printf("%c", znak);
}

printf("\n");
}

getchar();
}

Rjeenje (b):

#include <stdio.h>

void main()
{
char a = 'A';
char b = 'B';
int i, j, k;

for (i = 0; i < 4; i++)


{
for (j = i; j >= 0; j--)
printf("%c", a);

for (k = 3-i; k > 0; k--)

45
printf("%c", b);

printf("\n");
}

getchar();
}

Zadatak 4.5. Napiite program koji, uz pomo naredbe getchar(), broji ukupan broj rijei koje unese
korisnik. Prekid unosa znakova neka bude pritisak na tipku enter. Napomena: da bi izbjegli
viestruke praznine, za definiciju rijei uzmite znak ili niz znakova kojima prethodi praznina.

Rjeenje:

#include <stdio.h>

#define EOF '\n'

void main()
{

int znak, prethodniZnak = ' ';


int brojac = 0, i = 0;

while ((znak = getchar()) != EOF)


{
if ((znak != ' ') && (prethodniZnak == ' '))
brojac++;

prethodniZnak = znak;
}

printf("Broj upisanih rijeci: %d.\n", brojac);

getchar();
}

46
DODATNI ZADACI

Zadatak 4.6. Napiite program koji rauna n-tu faktorijelu. Napomena: n se unosi pomou scanf()
funkcije, i ne moe biti vei od 12.

Zadatak 4.7. Napiite program koji ispisuje sve vrijednosti funkcije y = 15 * x + 76, za sve cijele
parne brojeve x iz intervala [-7, 7].

Zadatak 4.8. Napiite program koji, pomou petlji, generira i ispisuje:

1
232
34543
4567654
567898765
67890109876
7890123210987
890123454321098
90123456765432109

DOMAI RAD

Zadatak 4.9. Napiite program koji zadanu vrijednost duljine u centimetrima pretvara u inche.
(x(in) = x(cm) / 2,54).

Zadatak 4.10. Napiite program koji za uitanu ocjenu ispisuje njezin opis. Na primjer, ako korisnik
unese 5, program ispisuje "Izvrstan". Ako korisnik unese broj izvan intervala [1,5], program treba
ispisati odgovarajuu poruku. Koristite switch-case naredbu.

Zadatak 4.11. Napiite program koji ispisuje sve parne brojeve iz intervala od 0 do 100.

47
VJEBA 5

Nizovi

Kolekcija varijabli istog tipa i zajednikog imena zove se polje ili niz (engl. array). Niz u memoriji
zauzima kontinuirani niz memorijskih lokacija [2], a deklaracijom niza rezervira se memorija
potrebna za njegove lanove. Nizovi mogu biti viedimenzionalni, a ime bilo kojeg niza predstavlja
adresu prvog elementa njegovog elementa.

Opi oblik glasi: tip ime_niza[izraz], gdje je izraz pozitivni cijeli broj.

Primjer deklaracije niza:

int x[100]; // niz od 100 cijelih brojeva


char text[80]; // niz od 80 znakova
float n[12]; // niz od 12 realnih brojeva

Primjer inicijalizacije niza:

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


float x[6] = {0, 0.25, 0, -0.50, 0, 0};
char boja[5] = {'P', 'L', 'A', 'V', 'A'};

Polja ili nizovi u programiranju su slini vektorima i matricama u matematici. Ako se eli pristupiti
lanu nekog niza, to se radi pomou indeksiranja.

Primjer:

#include <stdio.h>

void main()
{
int a[] = {1, 4, 7, 8, 17};

printf("%d ", a[0]); // ispisujemo vrijednost prvog lana niza


printf("%d", a[4]); // ispisujemo vrijednost posljednjeg lana niza

getchar();
}

ISPIS PROGRAMA:
1 17

48
Niz znakova

Niz znakova (engl. string) je polje koje se sastoji od niza znakova i koje zavrava oznakom kraja niza
'\0' (engl. string terminator).

Primjer (niz znakova): Program pohranjuje znakovni niz "Dalmacija" u jednodimenzionalni


znakovni niz X. Budui da rije "Dalmacija" ima devet slova, znakovni niz mora imati mjesta za
deset znakova. Oznaka kraja niza se rauna kao jedan znak.

Ovako to izgleda u memoriji:

D a l m a c i j a \0

X[0] = 'D'
X[1] = 'a'
X[2] = 'l'
X[3] = 'm'
X[4] = 'a'
X[5] = 'c'
X[6] = 'i'
X[7] = 'j'
X[8] = 'a'
X[9] = '\0'

Programski kod:

#include <stdio.h>

void main()
{
char X[10] = "Dalmacija";
printf("Znakovni niz glasi: %s.\n", X);
getchar();
}

ISPIS PROGRAMA:
Znakovni niz glasi: Dalmacija.

49
Viedimenzionalni nizovi

Viedimenzionalni nizovi su skupovi jednodimenzionalnih nizova. Primjer nekog


viedimenzionalnog niza bila bi matrica.

Grafiki prikaz dvodimenzionalnog niza:

Tablica 5.1. Grafiki prikaz dvodimenzionalnog niza

X stupac 0 stupac 1 stupac 2 stupac 3 stupac 4 stupac 5 stupac 6


redak 0 X[0][0] X[0][1] X[0][2] X[0][3] X[0][4] X[0][5] X[0][6]
redak 1 X[1][0] X[1][1] X[1][2] X[1][3] X[1][4] X[1][5] X[1][6]
redak 2 X[2][0] X[2][1] X[2][2] X[2][3] X[2][4] X[2][5] X[2][6]
redak 3 X[3][0] X[3][1] X[3][2] X[3][3] X[3][4] X[3][5] X[3][6]

Opi oblik:

tip_niza ime_niza [dimenzija_1] [dimenzija_2] ... [dimenzija_n]


tip_niza ime_ niza [broj_redaka] [broj_stupaca] ... [dodatne_dimenzije]

Primjer deklaracije niza:

float tablica[50][50];
char stranica[24][80];
static double zapisi [x][y][z];

Primjer inicijalizacije niza:

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

Primjer (dvodimenzionalni niz): Program ispisuje dvodimenzionalni niz od tri retka i etiri stupca.

#include <stdio.h>

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

for (i = 0; i < 3; i++)


for (j = 0; j < 4; j++)
printf("Niz [%d][%d] = %d\n", i, j, niz[i][j]);
getchar();

50
}

ISPIS PROGRAMA:

51
ZADACI

Zadatak 5.1. Napiite program koji jednodimenzionalni niz od sedam lanova inicijalizira na nulu.

Rjeenje:

#include <stdio.h>

void main()
{
int i;
int niz[7];

for (i = 0; i < 7; i++)


{
niz[i] = 0;
printf("niz[%d] = %d\n", i, niz[i]);
}

getchar();
}

Zadatak 5.2. Napiite program koji uitava niz od deset cijelih brojeva, te ih ispisuje na ekran
koritenjem for petlje.

Rjeenje:

#include <stdio.h>

void main()
{
int i = 0;
int a;
int niz[10];

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


{
printf("Unesite %d. broj: ", i+1);
scanf("%d", &a);
niz[i] = a;
}

printf("\n");

//ispisujemo originalni niz

52
for (i = 0; i < 10; i++)
printf("%d. broj: %d\n", i+1, niz[i]);

getchar();
getchar();
}

Zadatak 5.3. Napiite program koji uitava znakovni niz sa tipkovnice i zatim ga ispisuje na ekran.

Rjeenje:

#include <stdio.h>

void main()
{
char niz[80];

printf("Unesite znakovni niz: ");


scanf("%s", niz); // alternativno: gets(niz);

printf("Upisali ste niz: %s.\n", niz);

getchar();
getchar();
}

Zadatak 5.4. Napiite program u kojemu korisnik unosi niz od 10 cijelih brojeva. Program od tog
niza napravi dva druga niza: jedan koji sadri samo parne brojeve iz originalnog niza, te drugi koji
sadri samo neparne brojeve iz originalnog niza.

Rjeenje:

#include <stdio.h>

void main()
{
int i = 0;
int a;
int niz[10];
int parni[10];
int neparni[10];
int brojac_parni = 0;
int brojac_neparni = 0;

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

53
{
printf("Unesite %d. broj: ", i+1);
scanf("%d", &a);
niz[i] = a;
}

printf("\n");

// ispisujemo originalni niz


for (i = 0; i < 10; i++)
printf("%d. broj: %d\n", i+1, niz[i]);

// parne i neparne brojeve dijelimo u dva niza


for (i = 0; i < 10; i++)
{
if ((niz[i] % 2) == 0) // parni
{
parni[brojac_parni] = niz[i];
brojac_parni++;
}

else // neparni
{
neparni[brojac_neparni] = niz[i];
brojac_neparni++;
}
}

printf("\nNiz koji sadrzi parne brojeve: ");

// ispisujemo originalni niz


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

printf("\nNiz koji sadrzi neparne brojeve: ");

// ispisujemo originalni niz


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

getchar();
getchar();
}

Zadatak 5.5. Napiite program za zbrajanje matrica dimenzija 3x3. Matrice inicijalizirajte na
proizvoljne vrijednosti unutar programskog koda.

54
Primjer zbrajanja matrica [4]:


1 3 2 0 0 5 10 30 25 1 3 7
1 0 0 7 5 0 = 17 05 00 = 8 5 0
1 2 2 2 1 1 12 21 21 3 3 3

Rjeenje:

#include <stdio.h>

void main()
{
int A[3][3] = {{1, 3, 2}, {1, 0, 0}, {1, 2, 2}};
int B[3][3] = {{0, 0, 5}, {7, 5, 0}, {2, 1, 1}};
int C[3][3];
int i, j;

// zbrajanje matrica
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
C[i][j] = A[i][j] + B[i][j];

printf("Rezultat zbrajanja matrica:\n");

for (i = 0; i < 3; i++)


for (j = 0; j < 3; j++)
{
printf("[%d][%d] = %d", i, j, C[i][j]);
printf("\n");
}

getchar();
getchar();
}

ISPIS PROGRAMA:

55
Zadatak 5.6. Napiite program za mnoenje dviju matrica. Neka prva matrica ima dimenzije 2x3, a
druga 3x2. Matrice inicijalizirajte na proizvoljne vrijednosti unutar programskog koda.

Primjer mnoenja matrica [4]:


3 1
1 0 2
1 3 1
2 1 =
1 0
130221 110120 = 5 1
133211 113110 4 2
Rjeenje:

#include <stdio.h>

void main()
{
int A[2][3] = {{1, 0, 2}, {-1, 3, 1}};
int B[3][2] = {{3, 1}, {2, 1}, {1, 0}};
int C[2][2] = {{0, 0}, {0, 0}};
int i, j, k;

// mnozenje matrica
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
{
for (k = 0; k < 3; k++)
C[i][j] = C[i][j] + A[i][k] * B[k][j];
}

printf("Rezultat mnozenja matrica:\n");

for (i = 0; i < 2; i++)


for (j = 0; j < 2; j++)
{
printf("[%d][%d] = %d", i, j, C[i][j]);
printf("\n");
}

getchar();
}

ISPIS PROGRAMA:

56
Zadatak 5.7. Napiite program u kojem korisnik unosi elemente kvadratne matrice dimenzija 5x5.
Program treba ispisati sve elemente matrice koji se nalaze ispod glavne dijagonale, te zatim te
elemente prebaciti u jednodimenzionalni niz i onda ispisati i taj niz.

Rjeenje:

#include <stdio.h>

void main()
{
int i, j, k = 0;
int const n = 5;
int niz[n][n];
int novi_niz[10];

// korisnik unosi elemente matrice


for (i = 0; i < n; i++)
{
printf("Unesite %d elemenata %d. retka: ", n, i+1);

for (j = 0; j < n; j++)


scanf("%d", &niz[i][j]);
}

printf("\n");

// ispisujemo unesenu matricu


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

printf("\n");
}

printf("\n");

// ispisujemo elemente ispod glavne dijagonale matrice


for (i = 0; i < n; i++)
{
for (j = 0; j < i; j++)
{
printf("%d ", niz[i][j]);
novi_niz[k] = niz[i][j];
k++;
}

57
printf("\n");
}

printf("\n");

// ispisujemo novi niz


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

printf("\n");

getchar();
getchar();
}

58
DODATNI ZADACI

Zadatak 5.8. Napiite program koji uitava dva niza znakova i ispituje da li su ti nizovi jednaki. Kraj
uitavanja niza odreen je oznakom za prijelaz u novi redak ('\n').

Zadatak 5.9. Napiite program koji uitava redak teksta i pretvara mala slova u velika. Redak mora
biti ogranien na 80 znakova. Napomena: za pretvaranje malih slova u velika koristite funkciju
toupper() iz biblioteke <ctype.h>, a za unoenje retka funkciju gets().

DOMAI RAD

Zadatak 5.10. Napiite program koji uitava ime i prezime korisnika, dob i godinu roenja, te
ispisuje te informacije na ekran.

Zadatak 5.11. Napiite program u kojem korisnik unosi niz od deset cijelih brojeva, a program
ispisuje njihovu aritmetiku sredinu.

Zadatak 5.12. Napiite program za zbrajanje matrica. Elemente matrice unosi korisnik, a svaka
matrica moe imati najvie 20 redaka i stupaca. Napomena: zbrajati se mogu samo matrice istih
dimenzija.

59
VJEBA 6

Bubble sort algoritam

Bubble sort algoritam je algoritam za sortiranje lanova nekog niza. Ovo je jedan od
najjednostavnijih, ali ujedno i najsporijih, algoritama za sortiranje.

U slijedeem primjeru prikazan je nain rada bubble sort algoritma. Algoritam u svakom koraku
usporeuje dva susjedna broja, i u sluaju da je prvi broj vei od drugog, zamjenjuje im mjesta.
Napomena: podebljani brojevi su oni koji se trenutno usporeuju.

Ulazni niz brojeva: (0 8 1 3 2).

1. prolaz algoritma:
(0 8 1 3 2) --> (0 8 1 3 2) // 0 < 8 --> nema zamjene
(0 8 1 3 2) --> (0 1 8 3 2) // 8 > 1 --> zamjena
(0 1 8 3 2) --> (0 1 3 8 2) // 8 > 3 --> zamjena
(0 1 3 8 2) --> (0 1 3 2 8) // 8 > 2 --> zamjena

2. prolaz algoritma:
(0 1 3 2 8) --> (0 1 3 2 8) // 0 < 1 --> nema zamjene
(0 1 3 2 8) --> (0 1 3 2 8) // 1 < 3 --> nema zamjene
(0 1 3 2 8) --> (0 1 2 3 8) // 3 > 2 --> zamjena
(0 1 2 3 8) --> (0 1 2 3 8) // 3 < 8 --> nema zamjene

3. prolaz algoritma:
(0 1 2 3 8) --> (0 1 2 3 8) // 0 < 1 --> nema zamjene
(0 1 2 3 8) --> (0 1 2 3 8) // 1 < 2 --> nema zamjene
(0 1 2 3 8) --> (0 1 2 3 8) // 2 < 3 --> nema zamjene
(0 1 2 3 8) --> (0 1 2 3 8) // 3 < 8 --> nema zamjene

Iako je niz bio sortiran na kraju drugog prolaza algoritma, algoritam se je morao jo jednom izvriti
da bi "znao" da je niz sortiran. Drugim rijeima, algoritmu je potreban jedan prolaz bez ijedne
zamjene da bi bio siguran da je algoritam sortiran.

Analiza bubble sort algoritma

Pod analizom algoritma podrazumijeva se procjena vremena izvravanja tog algoritma. Vrijeme se
poistovjeuje s brojem operacija koje odgovarajui program treba obaviti [5], i izraava se kao
funkcija oblika O(n) (engl. Order(n)). Na primjer, za ulazni niz brojeva (0 8 1 3 2), n bi bio jednak pet.
Da bi bubble sort algoritam uspio sortirati taj niz, u najboljem sluaju bi mu bilo potrebno O(n)
operacija (u ovom sluaju 5), a u najgorem sluaju O(n2) operacija (u ovom sluaju 25). Kako se n
poveava, najgore vrijeme izvravanja algoritma eksponencijalno raste. Upravo zbog ovog

60
problema, bubble sort algoritam nije dobar za sortiranje nizova sa velikim brojem podataka. Drugi
algoritmi kao to su heap sort i mergesort imaju puno bolje vrijeme izvravanja u najboljem
sluaju O(n), u najgorem sluaju O(nlogn) ali su ipak neto kompliciraniji.

61
ZADACI

Zadatak 6.1. Napiite program koji u niz sprema maksimalno 20 cijelih brojeva koje unosi korisnik.
Program sortira brojeve po veliini i ispisuje sortirani niz. Koristite bubble sort algoritam.

Rjeenje:

#include <stdio.h>

void main ()
{
int niz[20];
int n;
int temp;
int i, j;

printf("Koliko brojeva zelite unijeti? ");


scanf("%d", &n);

if ((n <= 0) || (n > 20))


printf("Morate unijeti broj u rasponu od 1 do 20.\n");
else if (n == 1)
printf("Nije potrebno sortirati niz od samo jednog clana.\n");
else
{
printf("\nUpisite clanove niza:\t ");

for (i = 0; i < n; i++)


scanf("%d", &niz[i]);

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


for (j = i+1; j < n; j++)
{
if (niz[i] > niz[j])
{
temp = niz[i];
niz[i] = niz[j];
niz[j] = temp;
}
}

printf("\nSortirani niz:\t ");

for (i = 0; i < n; i++)


printf("%d ", niz[i]);
}

62
printf("\n");

getchar();
getchar();
}

ISPIS PROGRAMA:

Zadatak 6.2. Pomou for petlje unesite prosjene mjesene temperature za jednu godinu. Ispiite
maksimalnu, minimalnu i prosjenu godinju temperaturu.

Rjeenje:

#include <stdio.h>

void main()
{
float godina[12];
int i;
float prosjecnaTemperatura = 0;
float max, min;

for (i = 0; i < 12; i++)


{
printf("Temperatura za mjesec broj %d: \t", i+1);
scanf("%f", &godina[i]);
}

printf("\n");

for (i = 0; i < 12; i++)


{
printf("Temperatura za mjesec broj %d: \t %.2f\n", i, godina[i]);
}

for (i = 0; i < 12; i++)


prosjecnaTemperatura = prosjecnaTemperatura + godina[i];

63
prosjecnaTemperatura = prosjecnaTemperatura / 12;

printf("Prosjecna temperatura: \t %.2f\n", prosjecnaTemperatura);

max = godina[0];

for (i = 1; i < 12; i++)


{
if (max < godina[i])
max = godina[i];
}

min = godina[0];

for (i = 1; i < 12; i++)


{
if (min > godina[i])
min = godina[i];
}

printf("Maksimalna temperatura: \t %.2f\n", max);


printf("Minimalna temperatura: \t %.2f\n", min);

getchar();
getchar();
}

Zadatak 6.3. Napiite program koji uitava proizvoljan broj znakova, te ispisuje koliko ima slova,
brojeva i ostalih znakova. Kraj uitavanja niza odreen je oznakom za prijelaz u novi redak ('\n'). Za
unos znakova koristite funkciju getchar().

Rjeenje:

#include <stdio.h>

void main()
{
int slova = 0;
int brojevi = 0;
int ostaliZnakovi = 0;
int znak;

puts("Unesite neki niz znakova:");

while ((znak = getchar()) != '\n')


{

64
if ((znak >= 'a' && znak <= 'z') || (znak >= 'A' && znak <= 'Z'))
slova++;
else if (znak >= '0' && znak <= '9')
brojevi++;
else
ostaliZnakovi++;
}

printf("Slova: %d\n", slova);


printf("Brojevi: %d\n", brojevi);
printf("Ostali znakovi: %d\n", ostaliZnakovi);

getchar();
}

Zadatak 6.4. Zadatak je slian prethodnome. Napiite program koji uitava proizvoljni broj znakova,
te ispisuje koliko ima slova, brojeva i ostalih znakova. Koristite funkcije getchar(), isdigit(), isupper()
i islower(). Ukljuite biblioteku <ctype.h>.

Rjeenje:

#include <stdio.h>
#include <ctype.h>

void main()
{
int slova = 0;
int brojevi = 0;
int ostaliZnakovi = 0;
int znak;

puts("Unesite neki niz znakova:");

while ((znak = getchar()) != '\n')


{
if ((islower(znak)) || (isupper(znak)))
slova++;
else if (isdigit(znak))
brojevi++;
else
ostaliZnakovi++;
}

printf("Slova: %d\n", slova);


printf("Brojevi: %d\n", brojevi);
printf("Ostali znakovi: %d\n", ostaliZnakovi);

65
getchar();
}

66
DODATNI ZADACI

Zadatak 6.5. Napiite program koji za neku predefiniranu rije broji koliko ona ima samoglasnika, te
tu informaciju ispisuje na ekran.

Zadatak 6.6. Napiite program koji dozvoljava unos proizvoljnog broja znakova (koristite while
petlju i funkciju getchar() za unos znakova). Kraj unosa odreen je oznakom za prijelaz u novi redak
('\n'). Program treba ispisati ukupan broj unesenih znakova. Napomena: prazna mjesta se takoer
broje kao znakovi.

DOMAI RAD

Zadatak 6.7. Napiite program koji uitava niz od deset cijelih brojeva, te ih u obrnutom redoslijedu
sprema u novi niz. Program treba ispisati taj novi niz.

Zadatak 6.8. Napiite program koji uitava niz od deset cijelih brojeva, te ispisuje samo one koji su
parni. Ako u nizu ne postoji nijedan parni broj, program treba ispisati odgovarajuu poruku.

67
VJEBA 7

Funkcije

Funkcija je programski modul koji obavlja neke specifine, tono definirane zadae.
Svaki C program sastoji se od jedne ili vie funkcija, pri emu se jedna mora zvati main(). Od main()
funkcije program poinje obradu. Sve se ostale funkcije, posredno ili neposredno, pozivaju iz
funkcije main().
Funkcija izvede programiranu radnju svaki put kad je "pozvana" iz bilo kojeg dijela programa. Po
povratku iz funkcije programski tok nastavlja se tamo odakle je funkcija bila pozvana. U pravilu,
funkcija prihvaa skup argumenata (jedan ili vie), a vraa samo jednu vrijednost.

Opi oblik:

tip_povratne_informacije ime_funkcije (tip1 argument1, tip2 argument2, ...)


{
...
}

Napomena: lista argumenata moe biti i prazna, a tip povratne informacije moe biti void.

Argumenti se unutar funkcije nazivaju i formalnim argumentima, jer predstavljaju samo preslike
podataka koji su u funkciju poslani iz pozivnog dijela programa. Takoer, koristi se i naziv parametri.
Argumente koji su u funkciju poslani nazivamo stvarnim argumentima ili parametrima.

Informacija se iz funkcije vraa u pozivni dio programa preko naredbe return. Ta naredba takoer
vraa programski tok na mjesto odakle je funkcija pozvana.

Ako se iz funkcije main() poziva neka druga funkcija, onda se ta funkcija mora ili definirati prije
funkcije main(), ili se prije funkcije main() mora nalaziti prototip te funkcije (tijelo funkcije se onda
moe nalaziti poslije funkcije main()).

Kako funkcija prenosi podatke?

Kada se pozove neka funkcija, ona e napraviti kopije argumenata koji su joj predani, tj. od stvarnih
argumenata (parametara) e napraviti formalne. U isto vrijeme funkcija e osigurati memorijski
prostor za eventualnu povratnu vrijednost.

Prijenos argumenata u funkciju

Kada se alje neka varijabla kao stvarni argument u funkciju, njena vrijednost se preslika u formalni
argument u pozvanoj funkciji. Takav nain proslijeivanja argumenata funkciji nazivamo
proslijeivanjem preko vrijednosti (engl. call by value). Ovakav nain proslijeivanja ima svoje
prednosti i nedostatke. Prednost je u tome to argument kroz funkciju ne mijenja svoju vrijednost,

68
a nedostatak je u tome to se na ovaj nain preko argumenata ne moe prenijeti informacija natrag
iz funkcije.

Kada se alje niz kao stvarni argument u funkciju, njegova vrijednost se preslika u formalni
argument u pozvanoj funkciji. Kako je niz predstavljen poetnom adresom niza, preslikana
vrijednost poetne adrese pristupa istim podacima. Ovakav nain proslijeivanja argumenta
funkciji nazivamo proslijeivanjem preko adrese (engl. call by reference). Ovakav nain
proslijeivanja podrazumijeva da je svaka promjena argumenta u funkciji vidljiva i u dijelu
programa koji je funkciju pozvao.

Ukratko, ako se koristi proslijeivanje preko vrijednosti, stvarni argumenti ostaju nepromijenjeni.
Ako se pak koristi proslijeivanje preko adrese, stvarni argumenti mogu biti promijenjeni.

Slika 7.1. Grafiki prikaz prijenosa argumenata u funkciju.

69
ZADACI

Zadatak 7.1. Napiite program koji iz funkcije main() poziva funkciju zbroji() i prosljeuje joj dva
proizvoljna cijela broja. Funkcija zbroji() mora vratiti rezultat zbrajanja ta dva broja.

Rjeenje (1. nain):

#include <stdio.h>

int zbroji (int, int); // prototip funkcije zbroji()

void main()
{
int a;
int b;
int rezultat;

printf("Unesite 1. broj: ");


scanf("%d", &a);
printf("Unesite 2. broj: ");
scanf("%d", &b);

rezultat = zbroji(a, b);

printf("%d + %d = %d\n", a, b, rezultat);


getchar();
getchar();
}

int zbroji (int x, int y)


{
int z;
z = x + y;
return z;
}

Rjeenje (2. nain):

#include <stdio.h>

int zbroji (int x, int y) // definicija funkcije zbroji()


{
int z;
z = x + y;
return z;

70
}

void main()
{
int a;
int b;
int rezultat;

printf("Unesite 1. broj: ");


scanf("%d", &a);
printf("Unesite 2. broj: ");
scanf("%d", &b);

rezultat = zbroji(a, b);

printf("%d + %d = %d\n", a, b, rezultat);

getchar();
getchar();
}

Zadatak 7.2. Napiite program koji uitava niz od deset cijelih brojeva, te zatim proslijeuje taj niz
funkciji koja vraa aritmetiku sredinu lanova niza.

Rjeenje:

#include <stdio.h>

float aritmetickaSredina(int a[])


{
float aritmeticka_sredina = 0;
int brojac;

for (brojac = 0; brojac < 10; brojac++)


aritmeticka_sredina = aritmeticka_sredina + a[brojac];

aritmeticka_sredina = aritmeticka_sredina / 10;

return aritmeticka_sredina;
}

void main()
{
int niz[10], i;
float rezultat;

71
for (i = 0; i < 10; i++)
{
printf("Unesite %d. clan niza: \t", i+1);
scanf("%d", &niz[i]);
}

printf("\n");

rezultat = aritmetickaSredina(niz);

printf("Aritmeticka sredina clanova niza je %.4f.\n", rezultat);

getchar();
getchar();
}

Zadatak 7.3. Napiite program koji uitava malo slovo, te ga pretvara u veliko slovo pomou
funkcije malo_u_veliko().

Rjeenje:

#include <stdio.h>

int malo_u_veliko (char x)


{
int rezultat;

// velika i mala slova su u ASCII tablici udaljeni za 32 znaka


rezultat = x - 32;

return rezultat;
}

void main()
{
char maloSlovo, velikoSlovo;

printf("Unesite neko malo slovo: ");


scanf("%c", &maloSlovo);

if ((maloSlovo >= 'a') && (maloSlovo <= 'z'))


{
velikoSlovo = malo_u_veliko(maloSlovo);
printf("Veliko slovo: %c\n", velikoSlovo);
}

72
else
printf("Niste unijeli malo slovo.\n");

getchar();
getchar();
}

73
DODATNI ZADACI

Zadatak 7.4. Napiite program u kojem korisnik unosi broj sekundi, a program preraunave
sekunde u sate, minute i sekunde. Na primjer, ako korisnik unese 3670, program treba ispisati: 1
sat, 1 minuta i 10 sekundi.

DOMAI RAD

Zadatak 7.5. Napiite program u kojem korisnik unosi brojani iznos u kunama, a program
preraunava kune u eure (1 euro = 7.26 kuna). Preraunavanje se mora obaviti u posebnoj funkciji.

Zadatak 7.6. Napiite program koji za deset predefiniranih brojeva rauna aritmetiku sredinu, te
trai najvei broj u nizu.

74
VJEBA 8

Doseg funkcije

Kada govorimo o dosegu funkcije, govorimo o imenima varijabli koje koristimo. Doseg je dio
programa unutar kojeg se neka varijabla moe koristiti.

Varijable se mogu podijeliti na:

lokalne (automatske)
globalne (vanjske)
statike
registarske

Lokalne (automatske) varijable

Lokalne (automatske) varijable su prijavljene unutar neke funkcije i vidljive su jedino u toj funkciji.
Ako im se pokua pristupiti iz neke druge funkcije, program e javiti greku.
Dvije lokalne varijable u razliitim funkcijama s istim imenima nezavisne su jedna od druge.
Sve varijable su lokalne ako se to drugaije ne navede.
Lokalne varijable ne zadravaju vrijednost nakon to programski tok ode iz funkcije u kojoj je
varijabla definirana.

Globalne (vanjske) varijable

Suprotno lokalnim varijablama, globalne varijable nisu vezane za neku funkciju. Njihov doseg see
od mjesta definicije kroz ostatak programa. ak tovie, katkad povezuju ne samo funkcije nego i
cjelokupni program.
Promjena globalne varijable u bilo kojoj funkciji biti e vidljiva u svakom dijelu programa.
Inicijalizacija globalne varijable mora biti inicijalizirana konstantom, a nikako izrazom.

Statike varijable

Doseg statikih varijabli, kao i doseg lokalnih varijabli, see samo unutar funkcije u kojoj su
definirane. Ako programski tok izae iz funkcije, pa se opet vrati u nju, statika e varijabla dobiti
onu vrijednost koju je imala na izlazu iz funkcije. To znai da se statike varijable ne unitavaju
nakon izlaska programskog toka iz neke funkcije, ve ostaju sauvane u memoriji.
Statike varijable se oznaavaju sa kljunom rijei static.

Registarske varijable

Registarske varijable se najee koriste za ubrzavanje programskog koda. To su varijable koje se ne

75
moraju spremati i itati iz memorije, ve tijekom itavog izvoenja programa ostaju u registrima.
Oznaavaju se sa kljunom rijei register.

Lokalne varijable definirane unutar programskog bloka

Ako se lokalne varijable definiraju unutar nekog programskog pod-bloka, biti e dostupne samo u
tome pod-bloku. Pokuaj pristupa nekoj od njih izvan tog programskog bloka uzrokovati e greku.

Primjer 1.

#include <stdio.h>

void main()
{
int a = 0;

do
{
int b = 1;
...programski kod...
} while(...);

// da pokuamo ovdje ispisati vrijednost varijable b, program bi javio greku


// varijabla b ovdje vie ne postoji
}

Primjer 2.

#include <stdio.h>

void main ()
{
int brojac1 = 1; // deklariran u VANJSKOM bloku

do
{
int brojac2 = 0; // deklariran u UNUTARNJEM bloku
++brojac2;
printf("\nbrojac1 = %d brojac2 = %d", brojac1, brojac2);
} while (++brojac1 <= 8);

// brojac2 vise ne postoji

printf("\nbrojac1 = %d\n", brojac1);

getchar();

76
}

ISPIS PROGRAMA:

Primjer 3.

#include <stdio.h>

void main()
{
int brojac = 0; // deklariran u VANJSKOM bloku

do
{
int brojac = 0; // ovo je druga varijabla nazvana brojac
++brojac; // ovo se odnosi na UNUTARNJI brojac
printf("brojac = %d\n", brojac);
} while (++brojac <= 8); // ovo mijenja VANJSKI brojac

printf("brojac = %d\n", brojac);

getchar();
}

ISPIS PROGRAMA:

77
ZADACI

Zadatak 8.1. (Lokalne varijable) Prouite i objasnite kako radi slijedei program:

#include <stdio.h>

void test()
{
// funkcija test() ne vidi varijablu a
// ako se varijabla a pokua koristiti u ovoj funkciji, program e javiti greku

printf("Funkcija test(): ovdje ne postoji varijabla a\n");


}

void main()
{
int a; // a je lokalna varijabla u funkciji main()
a = 2;
printf("Funkcija main(): %d\n", a);
test();
getchar();
}

ISPIS PROGRAMA:
Funkcija main(): 2
Funkcija test(): ovdje ne postoji varijabla a

Zadatak 8.2. (Globalne varijable) Prouite i objasnite kako radi slijedei program:

#include <stdio.h>

int x = 7; // x je globalna varijabla, vidljiva u svim funkcijama

void test()
{
printf("Funkcija test(): %d\n", x);
}

void main()
{
printf("Funkcija main(): %d\n", x);
test();
getchar();
}

78
ISPIS PROGRAMA:
Funkcija main(): 7
Funkcija test(): 7

Zadatak 8.3. (Statike varijable) Prouite i objasnite kako radi slijedei program:

#include <stdio.h>

int brojac = 1; // globalna varijabla brojac

void test()
{
static int a = 0; // statika varijabla a
a = a + 2;
printf("%d. poziv funkcije test(). \t a = %d\n", brojac, a);
brojac++;
}

void main()
{
int i; // lokalna varijabla i
for (i = 0; i < 10; i++)
test();
getchar();
}

ISPIS PROGRAMA:

79
DODATNI ZADACI

Zadatak 8.4. Napiite program koji ispisuje prvih 10 znamenki Fibonaccijevog niza (koristite while
ili for petlju). Napomena: Fibonaccijev niz je niz brojeva koji zapoinje sa nulom i jedinicom, a svaki
slijedei broj je zbroj prethodna dva. Prvih nekoliko znamenki Fibonaccijevog niza: 0 1 1 2 3 5 8 13
21 34 55 89 144 ...

DOMAI RAD

Zadatak 8.5. Napiite program u kojem korisnik unosi dva cijela broja, a program ispisuje sve proste
brojeve koji se nalaze unutar zadanog intervala. Napomena: prosti brojevi ili prim-brojevi su svi
prirodni brojevi djeljivi bez ostatka samo sa brojem 1 i sami sa sobom, a vei od broja 1.

Zadatak 8.6. Napiite program koji rauna sumu svih brojeva od 1 do 100 koji su djeljivi sa 5.

80
VJEBA 9

Bitznaajni operatori

Bit je najmanja jedinica informacije, ili 0 ili 1, a bitznaajni operatori (engl. bitwise operators) se
koriste za manipulaciju bitovima (odnosno za programiranje na najnioj moguoj razini). Bitznaajni
operatori se najee koriste u kriptografiji i u saimanju podataka.

Bitznaajni operatori:
& binarno I (AND)
| binarno ILI (OR)
^ binarno ekskluzivno ILI (XOR)
~ jedinini komplement (NOT)
<< pomak u lijevo (SHIFT LEFT)
>> pomak u desno (SHIFT RIGHT)

Tablica 9.1. Tablica istine za &, ^ i | operatore

a b a&b a^b a|b


0 0 0 0 0
0 1 0 1 1
1 0 0 1 1
1 1 1 0 1

Tablica 9.2. Tablica istine za ~ operator

a ~a
0 1
1 0

Tablica 9.3. Primjeri primjene AND, OR i XOR operatora

Primjer (AND): Primjer (OR): Primjer (XOR):


0010 0010 0010
& 1010 | 1010 ^ 1010
0010 1010 1000

Jedinini komplement (~) je unarni operator koji se koristi za inverziju bitova nekog operanda
(jedinice postaju nule, a nule jedinice). Operand se najee predstavlja u oktalnoj ili u
heksadecimalnoj formi, iako ovo nije formalno pravilo [6].

81
Primjer:

a = 0110 1101 1011 0111 (dekadski brojevni sustav 28087)


~a = 1001 0010 0100 1000 (dekadski brojevni sustav 37448)

Bitznaajni pomak u lijevo odgovara mnoenju operanda sa potencijama broja dva. Na primjer,
ako operand pomaknemo za jedno mjesto u lijevo dobiti emo isti rezultat kao da smo ga
pomnoili sa 2.

Primjeri:

a = 0110 1101 1011 0111 (dekadski brojevni sustav 28087)


a << 6 = 0110 1101 1100 0000 (dekadski brojevni sustav 28096)

a = 0000 0010 (dekadski brojevni sustav 2)


a << 1 = 0000 0100 (dekadski brojevni sustav 4)
a << 2 = 0000 1000 (dekadski brojevni sustav 8)
a << 3 = 0001 0000 (dekadski brojevni sustav 16)
a << 4 = 0010 0000 (dekadski brojevni sustav 32)

Bitznaajni pomak u desno odgovara cjelobrojnom dijeljenju operanda sa potencijama broja dva.
Na primjer, ako operand pomaknemo za jedno mjesto u desno dobiti emo isti rezultat kao da smo
ga podijelili sa 2.

Primjeri:

a = 0110 1101 1011 0111 (dekadski brojevni sustav 28087)


a >> 6 = 0000 0001 1011 0110 (dekadski brojevni sustav 438)

a = 0100 0000 (dekadski brojevni sustav 64)


a >> 1 = 0010 0000 (dekadski brojevni sustav 32)
a >> 2 = 0001 0000 (dekadski brojevni sustav 16)
a >> 3 = 0000 1000 (dekadski brojevni sustav 8)
a >> 4 = 0000 0100 (dekadski brojevni sustav 4)

Maskiranje bitova

Bitznaajni operator I (AND) se najee koristi za maskiranje bitova. Maskiranje bitova je proces
vaan za raunalnu sigurnost, grafiku i kriptografiju.

Primjer:

a = 0110 1101 1011 0111 (dekadski brojevni sustav 28087)


maska = 0000 0000 0000 1111 (dekadski brojevni sustav 15)
rezultat = 0000 0000 0000 0111 (dekadski brojevni sustav 7)

82
#include <stdio.h>

void main()
{
unsigned n = 0x6db7; // dekadski brojevni sustav - 28087
unsigned maska = 0xF; // dekadski brojevni sustav 15

// koritenje znaka '#' uzrokuje pojavu znakova '0x' ispred keksadecimalnog broja
printf("Vrijednost od n (n = %#x), maskirana sa %#x, je: %#x\n", n, maska, n & maska);

getchar();
}

83
ZADACI

Zadatak 9.1. Napiite program u kojem korisnik unosi neki cijeli broj, a program ispisuje njegov
binarni ekvivalent.

Rjeenje:

#include <stdio.h>

void main()
{
int x, i, n, b;

printf ("Unesite jedan cijeli broj: ");


scanf ("%d", &x);

// sizeof(int) vraa broj bajtova koje zauzima int


// 8 * sizeof(int) vraa broj bitova koje zauzima int
n = 8 * sizeof(x);

printf ("Binarni kod je: ");

for (i = n-1; i >= 0; i--) // od MSB do LSB (od 31. do 0. bita)


{
b = (x & (01 << i)) != 0;
printf ("%d", b);
}

printf("\n");

getchar();
getchar();
}

Pretpostavimo da korisnik unese broj 2 (binarno 00000000 00000000 00000000 00000010).


Promotrimo to tono radi linija koda:

b = (x & (01 << i)) != 0;

U prvom prolazu for petlje, i = 31.

Dakle: b = (00000000 00000000 00000000 00000010 & (01 << 31)) != 0;

Kada se broj 01 pomakne za 31 mjesto ulijevo, ostaje samo 00.

Dakle: b = (00000000 00000000 00000000 00000010 & (00)) != 0;

84
Ako je bilo koji od operanada jednak nuli, rezultat logike operacije AND je takoer jednak nuli:
00000000 00000000 00000000 00000010 & 00 = 0.

Dakle: b = (0) != 0;

0 != 0 nije tono, pa je itav izraz jednak logikoj nuli. MSB bit ima vrijednost nula.

Napomena: != ima vei prioritet od =. Zato se u izrazu "b = (0) != 0;" prvo izvri usporedba (0) != 0,
pa se tek onda rezultat usporedbe dodijeli varijabli b.

U predzadnjem prolazu for petlje, i = 1.

Dakle: b = (00000000 00000000 00000000 00000010 & (01 << 1)) != 0;

Kada se broj 01 pomakne za 1 mjesto ulijevo, ostane 10.

Dakle: b = (00000000 00000000 00000000 00000010 & (10)) != 0;

Budui da je izraz (00000000 00000000 00000000 00000010 & (10)) != 0 istinit, bit sa teinskom
vrijednou jedan jednak je jedinici.

Zadatak 9.2. Napiite program u kojemu su definirana dva cjelobrojna niza. Elementi nizova mogu
biti samo binarne znamenke, tako da itavi niz zapravo predstavlja neki binarni broj. Pokaite
djelovanje AND, OR i XOR operatora nad lanovima tih nizova.

Rjeenje:

#include <stdio.h>

void main()
{
int a[4] = {1,1,0,1}; // 13
int b[4] = {1,0,1,0}; // 10
int rezultat[4];
int i;

// AND
for (i = 0; i < 4; i++)
rezultat[i] = a[i] & b[i];

// ispisujemo rezultat logickog AND


printf("Rezultat AND operacije: ");
for (i = 0; i < 4; i++)
printf("%d", rezultat[i]);

// OR

85
for (i = 0; i < 4; i++)
rezultat[i] = a[i] | b[i];

// ispisujemo rezultat logickog OR


printf("\nRezultat OR operacije: ");
for (i = 0; i < 4; i++)
printf("%d", rezultat[i]);

// XOR
for (i = 0; i < 4; i++)
rezultat[i] = a[i] ^ b[i];

// ispisujemo rezultat logickog XOR


printf("\nRezultat XOR operacije: ");
for (i = 0; i < 4; i++)
printf("%d", rezultat[i]);

getchar();
getchar();
}

Zadatak 9.3. Napiite program i definirajte neki cijeli broj u heksadecimalnom obliku. Korisnik
unosi redni broj bita iju vrijednost eli saznati, i program vraa nulu ili jedinicu, ovisno o tome koji
se bit nalazi na mjestu kojeg je specificirao korisnik.

Rjeenje:

#include <stdio.h>

void main ()
{
int x = 0x2; // dekadski isto 2
int n;

printf("Unesite oznaku bita ciju vrijednost zelite procitati: \n");


scanf ("%d", &n);

if ((n < 0) || (n >= 32))


printf("Odabrali ste nepostojeci bit!!!\n");
else
printf("Bit na %d. mjestu ima vrijednost: %d \n", n, ((x & (01 << n)) != 0));

getchar();
getchar();
}

86
DODATNI ZADACI

Zadatak 9.4. Napiite program u kojem korisnik unosi neki cijeli broj, a program ispisuje njegov
binarni ekvivalent. Binarni ekvivalent se sprema u niz binarni_ekvivalent[32]. Postavite sve bitove
binarnog ekvivalenta na nulu (koristite XOR operaciju).

DOMAI RAD

Zadatak 9.5. Napiite program koji za predefinirani cijeli broj ispisuje teinsku vrijednost svakog
bita koji je jednak jedinici. Na primjer, za cijeli broj 11 (binarno 1011), program bi trebao ispisati 1,
2 i 8.

1 0 1 1
2 1 0
23=8 2 =4 2 =2 2 =1

87
DODATAK

Pretvaranje iz dekadskog brojevnog sustava u binarni brojevni sustav

15610=? 2

Prvi nain (broj u dekadskom brojevnom sustavu se dijeli sa 2, a ostatak dijeljenja se zapisuje u
poseban stupac):

156 : 2 = 78 0
78 : 2 = 39 0
39 : 2 = 19 1
19 : 2 = 9 1
9:2=4 1
4:2=2 0
2:2=1 0
1:2=0 1

Rjeenje se dobije tako da se ostaci dijeljenja sa 2 napiu obrnutim redoslijedom. Rjeenje bi bilo:
1001 1100.

Drugi nain (promatraju se potencije broja 2):

156 128 = 28 1 (128 je najvea potencija broja 2 koja "stane" u broj 156)
28 64 = -36 0 (64 je idua nia potencija broja 2, ali 64 ne "stane" u 28)
28 32 = -4 0 (32 je idua nia potencija broja 2, ali 32 ne "stane" u 28)
28 16 = 12 1 (16 je idua nia potencija broja 2)
12 8 = 4 1 (8 je idua nia potencija broja 2)
44=0 1 (4 je idua nia potencija broja 2)
0 2 = -2 0 (2 je idua nia potencija broja 2)
0 1 = -1 0 (1 je idua nia potencija broja 2)

Napomena: ako je rezultat oduzimanja negativan, za binarnu znamenku se uzima nula. Ako je
rezultat pozitivan, uzima se jedinica.

Pretvaranje iz binarnog brojevnog sustava u dekadski brojevni sustav

100111002 =?10

MSB LSB
1 0 0 1 1 1 0 0
7 6 5 4 3 2 1
2 =128 2 =64 2 =32 2 =16 2 =8 2 =4 2 =2 2 0=1

112806403211618140201=1281684=156

88
Pretvaranje iz dekadskog brojevnog sustava u oktalni brojevni sustav

15610=? 8

156 najprije podijelimo sa najveom potencijom broja 8 koja "stane" u broj 156 (a to je 64).

156 : 64 = 2 (ostatak 28) 64=8


2

28 : 8 = 3 (ostatak 4) 8=81
4:1=4 (ostatak 0) 1=8
0

Rezultat: 234.

Pretvaranje iz oktalnog brojevnog sustava u dekadski brojevni sustav

234 8=? 10

2 1 0
28 38 48 =128244=156

Pretvaranje iz dekadskog brojevnog sustava u heksadecimalni brojevni sustav

15610=? 16

156 najprije podijelimo sa najveom potencijom broja 16 koja "stane" u broj 156 (a to je 16).

156 : 16 = 9 (ostatak 12) 16=16


1

12 : 1 = 12 (C) (ostatak 0) 1=16


0

Rezultat: 9C.

Pretvaranje iz heksadecimalnog brojevnog sustava u dekadski brojevni sustav

9C16=? 10

1 0
916 1216 =14412=156

89
VJEBA 10

MATLAB

MATLAB (engl. MATrix LABoratory) je aplikacija i programski jezik (slian C-u) za znanstvena
istraivanja. MATLAB korisniku prua velik broj funkcija, grupiranih tematski u toolbox-ove, te
namijenjenih rjeavanju problema vezanih za kontrolu i optimizaciju sustava, kao i za obradu
signala.

Neki od MATLAB-ovih toolbox-ova:


Partial Differential Equation Toolbox
Statistics Toolbox
Neural Network Toolbox
Aerospace Toolbox
Image Processing Toolbox
Fuzzy Logic Toolbox
...

Pokretanje MATLAB-a

Na Windows Desktop-u kliknite na Start --> All Programs --> Matlab --> Matlab. Otvoriti e se
osnovni prozor MATLAB-a (Slika 10.1) koji po default-u sadri naredbeni prozor (engl. Command
Window), prozor povijesti naredbi (engl. Command History), prozora tekuih datoteka (engl.
Current Directory) i prozor sa sadrajem radnog prostora (engl. Workspace).

Osnovne operacije

MATLAB koristi jednostavnu sintaksu. Naredbe u MATLABu se upisuju u posljednju, aktivnu liniju
naredbenog prozora koja poinje sa oznakom '>>'.

Nardbe (i operacije) koje se upisuju u komandnu liniju izvravaju se nakon pritiska na <enter>. Na
primjer:

>> (3^2+4*5)/ (9/2-8^3) <enter>

izraunava vrijednost izraza

3245
9 3 .
8
2

Pretraivanje i preureivanje prethodno izvrenih izraza radimo sa 'tipkama-strelicama': gore,


dolje, lijevo i desno. Na primjer, prethodni izraz pozivamo tipkom gore.

90
Slika 10.1. Osnovni prozor MATLAB-a

Primijetili ste da se rezultat ispisuje na pod nazivom ans (engl. answer). Ukoliko elimo vrijednosti
dodijeliti ime (ime konstante), ispred izraza napiemo ime i stavljamo znak jednakosti.

Primjer: pozovimo prethodni izraz i dodijelimo ga konstanti k:

>> k = (3^2+4*5)/ (9/2-8^3) <enter>


>> k =
-0.0571

Ukoliko ne elimo konstantu ispisati na ekran, na kraju izraza upisujemo toka-zarez ;.

>> k = (3^2+4*5)/ (9/2-8^3);


>>

Na taj nain konstanta k se ne ispisuje na ekranu, ali ostaje definirana u programu dok joj se ne
dodijeli nova vrijednost, odnosno izraz.

91
Matrice i operacije sa matricama

Rjeavanje nekih problema (pogotovo onih vezanih za matrice i openito za matematiku), puno je
jednostavnije i bre u Matlabu nego u nekim drugom programskim jezicima (npr. C-u).
Matrica je dvodimenzionalno polje brojeva, i usput osnovni podatak za rad u MATLAB-u. Matrica
dimenzija [1,1] naziva se skalar, a matrica koja sadri samo jedan stupac ili samo jedan redak
naziva se vektor.

Matrica se definira navoenjem njezinih redaka. Elementi redaka se razdvajaju zarezom ili praznim
mjestom. Dva retka se razdvajaju simbolom ; na kraju retka.

Primjer definiranja matrice u MATLAB-u:

A = [16 3 2 13; 5 10 11 8; 9 6 7 12; 4 15 14 1];

ili

A = [16, 3, 2, 13; 5, 10, 11, 8; 9, 6, 7, 12; 4, 15, 14, 1];

Ovime smo definirali matricu:


16 3 2 13
5 10 11 8
A=
9 6 7 12
4 15 14 1

Napomena: matrice je uobiajeno oznaavati velikim slovima.

Matrine operacije i funkcije

Nad matricama se primjenjuju matematike operacije kao to su zbrajanje (oznaka je +),


oduzimanje (-), mnoenje (*) i dijeljenje (mnoenje jedne matrice sa inverznom drugom matricom)
(/). Napomena: prilikom mnoenja ili dijeljenja matrica treba voditi rauna o uzajamnoj
usklaenosti veliine matrica.

MATLAB poznaje standardne matrine operacije i funkcije kao to su transponiranje, potenciranje,


nalaenje inverzne matrice i odreivanje determinante. Na primjer, slijedee naredbe

>> B'
>> B^2
>> inv(B)
>> det(B)

odreuju odgovarajuu transponiranu matricu B, kvadrat matrice B, inverznu matricu B (inverzna


matrica se moe odrediti i sa B^(-1)) i determinantu matrice B, respektivno.

92
Posebne operacije sa matricama

Ako su matrice A i B istih dimenzija, i ukoliko je binarna operacija, tada je . posebna operacija
koja se moe primijeniti na matrice.

Karakteristine posebne operacije (element sa elementom) su: mnoenje redaka (.*), dijeljenje
redaka (./) i potenciranje redaka (.^).

Primjer:

>> A = [2 4 6; 1 2 3];
>> B = [1 1 1; 2 2 2];
>> A.*B % A * B bi generiralo greku

U gornjem smo primjeru definirali matrice A i B, te izraunali njihov umnoak.

Izdvajanje stupaca (redaka) matrice

Indeksiranje matrica, odnosno izdvajanje vektora redka ili vektora stupca ili pojedinih elemenata
vri se koritenjem simbola dvotoke ':'. Prvi indeks se odnosi na redak, a drugi indeks na stupac.

Primjer:

>> D = [9 8 7; 6 5 4; 3 2 1]; % definiramo matricu D


>> e = D(:, 3) % izdvajamo trei stupac matrice D
>> f = D(1, :) % izdvajamo prvi redak matrice D
>> g = D(1:2, 2) % izdvajamo prva dva elementa drugog stupca
>> h = D(3, 2:3) % izdvajamo drugi i trei element treeg retka

Napomene

MATLAB razlikuje velika i mala slova.

Bilo koja linija napisana iza znaka '%' predstavlja komentar.

Informacije o pojedinim naredbama se mogu dobiti primjenom naredbe help. Na primjer:

>> help zeros

prikazuje opis naredbe zeros.

Varijable se iz MATLAB-ove memorije briu naredbama clear ime_varijable ili clear all. Naredbom
clc se isprazni komandni ekran.

93
Vektori

Matrica sa jednim retkom ili stupcem predstavlja vektor. Na primjer:

>> v1 = [1 2 3 4]; % matrica sa jednim retkom


>> v2 = [1; 2; 3; 4]; % matrica sa jednim stupcem

MATLAB omoguava definiranje vektora iji elementi imaju konstantan meusoban razmak. Na
primjer, definirajmo vektor na intervalu [0, 100] sa korakom 10.

>> x = 0 : 10 : 100;

Dakle, rezultat je [0 10 20 30 40 50 60 70 80 90 100] i u konkretnom primjeru, 0 je poetni element


vektora, 10 je srednji element koji predstavlja korak izmeu dva elementa vektora, dok je 100
zadnji element. Pa moemo zakljuiti da je sintaksa ovakvog definiranja vektora:

ime_vektora = prvi_element : korak : zadnji_element;

Ako se korak eksplicitno ne navede, po defaultu iznosi jedan.

Polinomi

Polinomi se definiraju preko vektora koeficijenata polinoma, od koeficijenta ispred najvieg stupnja
polinoma do slobodnog elementa. Na primjer, polinom 2x3 x 23 se u MATLAB-u definira na
slijedei nain:

>> a = [2 -1 0 3]

Napomena: primijetite da u zadanom polinomu koeficijent uz x ima iznos 0.

Korijeni polinoma se mogu odrediti primjenom naredbe roots. Na primjer:

>> roots([1 5 6])

pronalazi korijene polinoma x 2 5x6.

Inverzna naredba roots naredbe je poly. Naime, ukoliko znamo korijene polinoma, primjenom
naredbe poly, dobivamo koeficijente polinoma. Na primjer:

>> poly([-2 -3])

ime iz zadanih korijena x1 = -2 i x2 = -3 dobivamo polinom x 2 5x6.

94
Rjeavanje sustava linearnih jednadbi

Rjeavanje sustava jednadbi obavlja se preko operacija sa matricama.

Pretpostavimo da traimo rjeenje Ax=B sustava.

Ax=B se moe zapisati i na slijedei nain:

Rjeenje sustava Ax=B bilo bi jednako x =A1 B .

Na primjer, rjeenje sustava jednadbi x + 3y = 7 i 2x 5y = 8 bilo bi:

>> A = [1 3; 2 -5]
>> B = [7; -8]
>> X = inv(A)*B

Crtanje funkcija

MATLAB posjeduje razliite funkcije za grafiki prikaz dobivenih rezultata. Najee koritena
naredba za grafiki prikaz funkcija je plot, sa sintaksom:

plot(x, y, 'opcije')

Na primjer:

>> x = -1 : 0.01 : 1;
>> plot(x, exp(x)+1)

crta funkciju e x 1 za 1 x 1 u posebnom prozoru. Korak u definiranju vektora elemenata je u


ovom konkretnom sluaju 0.01, i s ovim odreujemo finou i preciznost prikaza funkcije.

Alternative MATLAB-u

Besplatne alternative MATLAB-u su Octave (http://sourceforge.net/projects/octave/files/) i Scilab


(http://www.scilab.org/products/scilab/download).

95
ZADACI

Zadatak 10.1. Definirajte matrice:


2 3 1 2 4 8 1 1 1
M= 1 5 6 N = 1 2 9 O= 2 2 2
7 4 1 2 3 2 3 3 3

Izdvojite:
a) posljednji stupac matrice M,
b) prva dva elementa drugog reda matrice N
c) drugi i trei element prvog stupca matrice O
d) drugi redak matrice M
e) prva dva elementa treeg stupca zbroja matrica M + N

Rjeenje:

>> M = [-2 3 1; 1 5 6; 7 4 1];


>> N = [2 4 8; -1 2 9; 2 3 2];
>> O = [1 1 1; 2 2 2; 3 3 3];

>> a = M(:, 3);


>> b = N(2, 1:2);
>> c = O(2:3, 1);
>> d = M(2, :);
>> E = M + N;
>> e = E(1:2, 3);

Zadatak 10.2. Rijeite sustav jednadbi:

1. x 2y=3
2. x y4z=7
3. 2x3yz=5

Rjeenje:

A = [1 2 0; -1 1 4; 2 3 -1];
B = [3; 7; 5];
x = inv(A) * B

ISPIS PROGRAMA:
15
-6
7

96
Zadatak 10.3. Rijeite sustav jednadbi:

4. x 1x 3=1
5. x 1 x 2=1
6. x 2 x 3=1
7. x 1 x 4=3

Rjeenje:

A = [-1 0 1 0; 1 -1 0 0; 0 1 1 0; 1 0 0 1];
B = [1; -1; 1; 3];
x = inv(A) * B

ISPIS PROGRAMA:
-0.50000
0.50000
0.50000
3.50000

Zadatak 10.4. Pronaite korijene polinoma y=3x 44x3 x3.

Rjeenje:

y = [-3 4 0 -1 3];
roots(y)

ISPIS PROGRAMA (Octave):


1.48680 + 0.00000i
0.34243 + 0.82767i
0.34243 0.82767i
-0.83832 + 0.00000i

Zadatak 10.5. Na istoj slici iscrtati grafove funkcija y 1=x 32x 24 i y 2=5x 23, na intervalu (-
5,5), sa korakom 0.01. Neka graf funkcije y 1 bude iscrtan utom bojom, a graf funkcije y 2 zelenom
bojom.

Rjeenje:

x = -5 : 0.01 : 5;
y1 = x.^3 + 2.*x 4;
y2 = -5.*x.^2 + 3;
plot(x, y1, 'y', x, y2, 'g')

97
ex
Zadatak 10.6. Nacrtajte graf funkcije y= 1 , na intervalu (-5,5), sa korakom 0.02.
1 x
1e

Rjeenje:

x = -5 : 0.02 : 5;
y = exp(x)./(1 + exp(1./(1 + x)));
plot(y)

ex
Zadatak 10.7. Nacrtajte graf funkcije y= 1 , na intervalu (-5,5), sa korakom 0.5. Neka graf
1e 1 x
bude zelene boje, i neka sve toke na grafu budu oznaeve kruiima. Napomena: dodatne opcije
za crtanje grafa funkcije objanjene su u dodatku.

Rjeenje:

x = -5 : 0.5 : 5;
y = exp(x)./(1 + exp(1./(1 + x)));
plot(y, '-og')

98
DOMAI RAD

Zadatak 10.8. Pronaite korijene polinoma y=7x 4 4x 26x3.

sinx cosx
Zadatak 10.9. Na istoj slici iscrtati grafove funkcija y 1= i y 2= , na intervalu (0,10), sa
x x
korakom 0.01. Neka graf funkcije y 1 bude iscrtan utom bojom, a graf funkcije y 2 zelenom bojom.

99
DODATAK VJEBI 10

Grafovi

U MATLAB-u se moe specificirati tip linije kojom se iscrtava graf, te se mogu prikazati oznake za
eljene toke na grafu.

Tablica 10.1. Tipovi linija u MATLAB-u [7]

Oznaka u MATLAB-u Tip linije


'-' solid line (default)
'--' dashed line
':' dotted line
'-.' dash-dot line
'none' no line

Tablica 10.2. Oznake toaka na grafovima u MATLAB-u [7]

Oznaka u MATLAB-u Tip toke


'+' plus sign
'o' circle
'*' asterisk
'.' point
'x' cross
'square' ili 's' square
'diamond' ili 'd' diamond
'^' upward-pointing triangle
'v' downward-pointing triangle
'>' right-pointing triangle
'<' left-pointing triangle
'pentagram' ili 'p' five-pointed star (pentagram)
'hexagram' ili 'h''' six-pointed star (hexagram)
'none' no marker (default)

100
Boje grafova

U MATLAB-u postoji osam predefiniranih boja za grafove. Sve su prikazane u tablici 10.3.

Tablica 10.3. Predefinirane boje grafova u MATLAB-u [7]

Oznaka u MATLAB-u Boja


r red
g green
b blue
c cyan
m magenta
y yellow
k black
w white

Na primjer, naredbom plot(x, y, '-.or') bi se iscrtao graf sa linijom tipa '-.' (engl. dash-dot line), a
toke na grafu bi bile oznaeve kruiima ('o'). I graf i kruii bi bili crvene boje ('r') [7].

101
POPIS OZNAKA I KRATICA

ASCII American Standard Code for Information Interchange


BCPL - Basic Combined Programming Language
CR Carriage Return
DEC - Digital Equipment Corporation
EOF - End-of-File
LF Line Feed
LSB Least Significant Bit
MATLAB MATrix LABoratory
MIT Massachusetts Institute of Technology
MSB Most Significant Bit
PDP - Programmed Data Processor

102
LITERATURA

[1] "Dennis Ritchie", http://en.wikipedia.org/wiki/Dennis_Ritchie, web stranica posjeena 15. rujna


2010.
[2] Lavicki-atovi, N.; Vrba, .: "Library funkcije za sluajne brojeve", 2004,
http://zvrba.net/writings/C-srand.pdf, web stranica posjeena 18. rujna 2010.
[3] Vulin, R.: "Zbirka rijeenih zadataka iz C-a", kolska knjiga, Zagreb, 2003.
[4] "Matrica (matematika)", http://hr.wikipedia.org/wiki/Matrica_(matematika), web stranica
posjeena 05. listopada 2010.
[5] Manger, R.; Marui, M.: "Strukture podataka i algoritmi", skripta, tree izdanje, Prirodoslovno
matematiki fakultet, Sveuilite u Zagrebu, Zagreb, 2007,
http://web.math.hr/nastava/spa/files/skripta.pdf, web stranica posjeena 20. rujna 2010.
[6] Gottfried, B.: "Schaum's Outline Series: Programming with C", Second Edition, McGraw-Hill,
1996.
[7] "LineSpec (Line Specification)", http://www.mathworks.com/help/techdoc/ref/linespec.html,
web stranica posjeena 23. rujna 2010.

103


C
I

, 2011.
, I

: ,
,
, -

: ,

,

: 100

:

.

.
2

.
, .
.
, . ,
, :
, , , .

. , DEV C/C++.
.
.
. :
, , , , -, ,
.
, :
, (
), , .

,
, 2011.

1 ....... 1
1.1 , ............................................. 1
1.2 ................................................................................................... 4
2 ..... 8
2.1 ..................................................................... 8
2.1 ........................ 15
3 ....................................................................... 27
4 FOR .................................................................................................. 40
5 WHILE ............................................................................................ 61
6 DO...WHILE .................................................................................. 73
7 ....................................................................................................... 79
7.1 BREAK ........................................................................................................ 79
7.2 CONTINUE ................................................................................................. 83
7.3 GOTO .......................................................................................................... 85
7.4 SWITCH ... CASE ....................................................................................... 88
8 .................................... 94
9 .................................................................................................... 105
9.1 ................................................................................. 123
10 ........................................................................................................... 129
10.1 ...................................... 129
10.2 ............................... 132
10.3 ................................................................................... 139
10.4 ............................................................................. 145
10.5 .............................................................. 151
11 .................................... .................................................................. 160
............................................................................................... 178
I

1.1 ,

1.1:
A Z, a z
( )
: 0 1 2 3 4 5 6 7 8 9
: (space), , ,
:
+ - * / = % & # ! ? ^ " ' ~ \
| < > ( ) [ ] { } : ; . , _

1.2:

/* ( */)
*/
# ( , , ...)
;
,
\
0
'' string
' char

1.3:
auto break case char continue const default
do double else enum extern float for
goto if int long register return short
sizeof static struct switch signed typedef union
unsigned void volatile while

1
I

1.4:

int
char
float
double
short int "" ;
int
.
long int "" ;
int
.
long double
unsigned int
unsigned short int ( )
unsigned long int
void

: tip_podatka ime_promenljive;
: int a;

: ime_promenljive = vrednost;
: a=5;

:
tip_podatka ime_promenljive = vrednost;
: int a=5;

: typedef tip_podatka ime_tipa;


typedef float duzina;

:
const tip_podatka ime_promenljive = vrednost_konstante;
: const double e=2.71828182845905;

: #define IME_KONSTANTE vrednost_konstante


: #define MAX 50

ja :
enum ime_nabrajanja { IME_KONSTANTE = vrednost,
IME_KONSTANTE = vrednost, }
: enum podaci {MIN=10, MAX=100, POZELJNO=30}

1.1. Ko :
a) /*Ovo je programski jezik C.*/
) /*Prva oblast /*Tipovi podataka i operatori*/ */
) /*Prva oblast
Tipovi podataka i operatori*/
) */Programski jezik C.*/

2
I

a) .
) , .
) .
) , /* */.

1.2. Ko :
) "x" ) broj ) float
) Ime_i_prezime ) a21 ) r
) a+b ) 3n

) , ".
) .
) , .
) .
) .
) , .
) , .
) .

1.3. :
) 543 ) 650L ) 03928
) 0123 ) 0xFFFFU ) 3ab22
) 0F75 ) 152UL ) 1.555

) , int.
) , 0, int.
) , 0 0, int.
) , long int, L ( l).
) , unsigned int, U ( u).
) , unsigned long int,
UL ( ul).
) , 8 9 .
) , a b .
) .

1.4. :
) 1.24 ) 211.25F ) 1ab.34
) .065 ) 1.65L ) 423.
) 1.342 ) 5,45 ) 2.E11

) , double.
) , double.
) , double.
) , float.
) , long double.
) , .
) , .

3
I

) , double.
) , double.

1.5. :
) int a, b, c; ) const double pi 3.14; ) typedef float duzina;
) int a=7; ) #define MAX =10 duzina a=5.2;
) char slovo=d; ) const int a=5;

K ), ), ), ), )

1.6. :
) ; ) 200 ;
) 80.5 kg; ) .

) const int nedelja=7;


) const double tezina=80.5;
) const int sala=200;
) enum meseci {N=31, FEB=29, MAR=31, APR=30, MAJ=31, JUN=30,
JUL=31, AVG=31, SEP=30, OKT=31, NOV=30, DEC=31};

1.2

1.5:

= =
+ +
- -
* *
/ / (
)
% %
++ ++ (=+1), 1

++ ++ (=+1), ,
1
-- -- (=-1), 1

-- -- (=-1), ,
1
+= += ( = + )

-= -= ( = - )

4
I

*= *= ( = * )


/= /= ( = / )


%= %= ( = % )

Ta 1.6: Ta 1.7:

> > && && (AND)
< < || x|| (OR)
>= >= ! ! (NOT)
<= <=
== ==
!= !=

Ta 1.8:

<< << ,
>> >> ,
& &
| |
^ ^
~ ~
<<= <<= =<<
>>= >>= =>>
&= &=

|= |=

Ta 1.9:

[]
()
. ()
-> ()
* () (
)
& ()
?: , (<)?:
,
sizeof , sizeof()
, sizeof(int)
(tip) ast , (double)

5
I

1.7. :
) 2+3*4 ) 9%3 ) 7*3/4
) 7/4 ) 7/4*3 ) 7.*3./4.
) 7%4 ) 7./4.*3.

) 24 ) 0 ) 5
) 1 ) 3 ) 5.25
) 3 ) 5.25

1.8. =5, b :
) b=++a ) b=a++ ) b=--a ) b=a--

) a=6, b=6 ) a=6, b=5 ) a=4, b=4 ) a=4, b=5

1.9. :
) a%=3; ) a*=10+b; ) a+=++b+20;

) a=a%3; ) a=a*10+b; ) a=a+b+1+20;

1.10. :
) 3+4. ) 5/4*3. ) 3.*5/4

) 3+4. 3.+4. 7.
) 5/4*3. (5/4)*3. 1*3. 1.*3. 3.
) 3.*5/4 (3.*5)/4 (3.*5.)/4 15./4 15./4. 3.75

1.11. y :
) int y; ) float y; ) float y;
float x=3.14; y=10/4; y=(float)10/4;
y=x;

) 3 ) 2 ) 2.5

1.12. :
) 5>7 ) 8==13>5 ) <b<5
) 10<=20 ) 14>5<3

) 5>7 0
) 10<=20 1
) 8==13>5 8==(13>5) 8==1 0
) 14>5<3 (14>5)<3 1<3 1
) <b<5 (<b)<5 (0 ili 1)<5 1

6
I

1.13. :
) (a AND b)<(c OR d) ) (x OR y)=z ) ab

) (a && b)<(c || d) ) (x || y)==z ) a != b

1.14.
int 16 :
) 0x1234 & 0x5678 ) ! 0x1234 ) 000001 << 5
) 0x1234 | 0x5678 ) 022222 & 055555 ) 03801 << 4
) 0x1234 ^ 0x5678 ) 022222 && 055555 ) 0xff56 >> 4
) ~ 0x1234

) 0x1230 ) 0 ) 000040
) 0x567 ) 000000 ) 08010 (!)
) 0x444 ) 1 ) 0xfff5
) 0xedcb

7
I

2.1

2.1: backslash \

\n
\t
\v
\b
\r
\f
\a
\
\
\\
\?
\ddd ddd
\0xdd dd

\0

2.2:

%c (char)
%i , (int),


%d o (int)
%u (unsigned int)
%o (int)
%x (int)
%hi, %hd, (short int) ,
%hu, %ho, %hx

8
I

%li, %ld, (long int) ,


%lu, %lo, %lx
%e, %f, %g float
%le, %lf, %lg double
%Le, %Lf, %Lg long double
%s
%p

2.3:

%c (char)
%d, %i o (int)
%u (unsigned int)
%o (unsigned int)
%x, %X (unsigned
int)
%hi, %hd, %hu, (short int)
%ho, %hx, %hX ,
%li, %ld, %lu, (long int)
%lo, %lx, %lX ,
%e, %f, %g float
%e, %f, %g double
%Le, %Lf, %Lg long double
%s
%p

2.4:

%- n , .
,
%+ +
%0 ,
,
% ()
%# ( o x )
0 0
%# ( e, f g )

2.1. : Od danas programiramo u jeziku


C.
#include <stdio.h>

main()
{
printf("Od danas programiramo u jeziku C.");
getche();
return 0;
}

9
I

#include<stdio.h>
-
.

main() .

{ .

printf(); , . .
.

getche(); , .
.

return 0; .
1 .

} . .

2.2. :
) )
#include <stdio.h> #include <stdio.h>

main() main()
{ {
printf("Pozdrav svima!"); printf("\nPozdrav svima!\n");
getche(); getche();
return 0; return 0;
} }

) )
#include <stdio.h> #include <stdio.h>

main() main()
{ {
printf("\nPozdrav\nsvima!\n"); printf("\nDobrodosli ");
getche(); printf("u jezik C\n\n");
return 0; getche();
} return 0;
}

) )
#include <stdio.h> #include <stdio.h>

main() main()
{ {
printf("\nDobrodosli \n\n\tu jezik C\n\n"); printf("\nABCDEF\n");
getche(); printf("A");
return 0; printf("BC");
} printf("DEF");
printf("\nA\nBC\nDEF\n");
getche();
return 0;
}

10
I

) )

) )

) )

2.3.
int a, b;
long int i, j;
double x, y;
char f;
:
) a, b, x
) i, f, j
) x, y, f
) i, f

) scanf("%d %d %lf ", &a, &b, &x);


) scanf("%ld %c %ld ", &i, &f, &j);
) scanf("%lf %lf %c ", &x, &y, &f);
) scanf("%ld %c ", &i, &f);

2.4. :
) ;
) ;
) , ;
) char.

11
I

) printf("%d", x);
) printf("%f %f", x, y);
) printf("%d %o %x", x, x, x);
) printf("%c", x);

2.5. .
#include <stdio.h>

main()
{
int ceo;
float realan;
printf("Unesite jedan ceo broj: ");
scanf("%d",&ceo);
printf("Unesite jedan realan broj: ");
scanf("%f",&realan);
printf("\nCeo broj: %d", ceo);
printf("\nRealan broj: %f", realan);
getche();
return 0;
}

2.6. .
#include <stdio.h>

main()
{
float a;
printf("Unesite jedan realan broj: ");
scanf("%f",&a);
printf("\nBroj zaokruzen na dve decimale je: %.2f", a);
getche();
return 0;
}

12
I

2.7.
, a .
#include <stdio.h>

main()
{
int a;
printf("Unesite ceo broj: ");
scanf("%d",&a);
printf("\nDecimalni oblik: %d", a);
printf("\nOktalni oblik: %o", a);
printf("\nHeksadecimalni oblik: %x", a);
getche();
return 0;
}

2.8.
.
#include <stdio.h>

main()
{
double a;
printf("Unesite jedan realan broj: ");
scanf("%lf",&a);
printf("\nOblik sa decimalnom tackom: %f", a);
printf("\nOblik sa eksponentom: %e", a);
printf("\nU naucnoj notaciji: %g", a);
getche();
return 0;
}

2.9. :
#include <stdio.h>

main()
{
const int a=987;
const double b=1.2345;
printf("%10d\n", a);
printf("%-10d\n\n", a);
printf("%10f\n", b);
printf("%-10f\n", b);
printf("%10.2f\n", b);
printf("%.2f\n", b);
getche();
return 0;
}
13
I

2.10.
.
#include <stdio.h>

main()
{
printf("%c\n%2c\n%3c\n%4c\n%5c", 'A', 'B', 'C', 'D', 'E');
getche();
return 0;
}

2.11. ,
SCII .
#include <stdio.h>

main()
{
char x, y, z;
printf("Unesite tri znaka:\n");
scanf("%c %c %c",&x,&y,&z);
printf("Promenljiva\t ASCII kod\n");
printf("%c\t\t %d\n",x, x);
printf("%c\t\t %d\n",y, y);
printf("%c\t\t %d\n",z, z);
getche();
return 0;
}

2.12. ,
ASCII ,
.
#include <stdio.h>

main()
{
char x;
char ch;
printf("Unesite znak: ");
scanf("%c",&x);
printf("\n\nZnak\tASCII kod\n");
printf("%c \t %d \n", x, x);
printf("%c \t %d \n", x+1, x+1);
printf("%c \t %d \n", x+2, x+2);
printf("%c \t %d \n", x+3, x+3);
getche();
return 0;
}

14
I

2.13. : char,
unsigned char, int, unsigned int, long, unsigned long, float, double.

#include <stdio.h>

main()
{
printf("\nTip CHAR = %d B memorije.", sizeof(char));
printf("\nTip UNSIGNED CHAR = %d B memorije.", sizeof(unsigned char));
printf("\nTip INT = %d B memorije.", sizeof(int));
printf("\nTip UNSIGNED INT = %d B memorije.", sizeof(unsigned int));
printf("\nTip LONG = %d B memorije.", sizeof(long));
printf("\nTip UNSIGNED LONG = %d B memorije.", sizeof(unsigned long));
printf("\nTip FLOAT = %d B memorije.", sizeof(float));
printf("\nTip DOUBLE = %d B memorije.", sizeof(double));
getche();
return 0;
}

2.1

2.5:
<stdlib.h>

abs(n) int,
n int.
labs(n) long int,
n long int.
rand() , int,
[0, RAND_MAX]. RAND_MAX

, 32767.
srand(n)
, rand(),
n. 1.
n unsigned int. .
* n

15
I

2.6: <math.h>

sin(x) sin x
cos(x) cos x
tan(x) tg x
asin(x) arc sin x, x [-1, 1]
acos(x) arc cos x, x [-1, 1]
atan(x) arc tg x, [-/2, /2]
atan2(x,y) arc tg x/y, [-, ]
sinh(x) sh x
cosh(x) ch x
tanh(x) th x
exp(x) ex
log(x) loge x, x>0
log10(x) log10 x, x>0
pow(x,y) xy, =0, >0; <0,
sqrt(x) ,
ceil(x)
floor(x)
fabs(x) |x|
ldexp(x,n) 2n
* ,y n

2.14. .

#include <stdio.h>

main()
{
int a, b, pomocna;
printf("Unesite prvi broj a= ");
scanf("%d", &a);
printf("Unesite drugi broj b= ");
scanf("%d", &b);
printf("\nPre zamene:\ta=%d, b=%d",a,b);
pomocna = a;

a = b;
b = pomocna;
printf("\nPosle zamene:\ta=%d, b=%d\n\n", a, b);
getche();
return 0;
}

16
I

2.15. .

:
#include <stdio.h>

main()
{
int a, b, c;
printf("Unesite prvi broj: ");
scanf("%d", &a);
printf("Unesite drugi broj: ");
scanf("%d", &b);
c = a + b;
printf("Zbir unetih brojeva je: %d\n", c);
getche();
return 0;
}

:
#include <stdio.h>

main()
{
int a, b;
printf("Unesite prvi broj: ");
scanf("%d", &a);
printf("Unesite drugi broj: ");
scanf("%d", &b);
printf("Zbir unetih brojeva je: %d\n", a+b);
getche();
return 0;
}

2.16. , , ,
, .

#include <stdio.h>

main()
{
int a, b;
printf("Unesite prvi broj: ");
scanf("%d", &a);
printf("Unesite drugi broj: ");
scanf("%d", &b);
printf("Zbir a+b je: %d\n", a+b);
printf("Razlika a-b je: %d\n", a-b);
printf("Proizvod a*b je: %d\n", a*b);
printf("Celobrojni kolicnik a/b je: %d\n", a/b);
printf("Realni kolicnik a/b je: %f\n", (float)a/(float)b);
printf("Ostatak pri deljenju a/b je: %d\n", a%b);
getche();
return 0;
}

17
I

2.17. .

#include <stdio.h>

main()
{
float a, b, o, p;
printf("Stranica a= ");
scanf("%f", &a);
printf("Stranica b= ");
scanf("%f", &b);
o=2*a+2*b;
p=a*b;
printf("\nObim: %.2f",o);
printf("\nPovrsina: %.2f",p);
getche();
return 0;
}

2.18. .

#include <stdio.h>
#define PI 3.14

main()
{
double r;
printf("Unesite poluprecnik kruga: ");
scanf("%lf", &r);
printf("Obim: %.3f\n", 2*r*PI);
printf("Povrsina: %.3f\n", r*r*PI);
getche();
return 0;
}

18
I

2.19.
. (: P=2*r**(r+h) , : V=r2**h)

#include <stdio.h>
#define PI 3.14

main()
{
double p,r,h,v;
printf("Unesite visinu valjka: ");
scanf("%lf",&h);
printf("Unesite poluprecnik valjka: ");
scanf("%lf",&r);
p = 2*r*PI*(r+h);
v = r*r*PI*h;
printf("Povrsina valjka: %.4f\n", p);
printf("Zapremina valjka: %.4f\n",v);
getche();
return 0;
}

2.20.
.
#include <stdio.h>

main()
{
int temp;
double fahr, celsius;
printf("\nUnesite T u stepenima F <ceo broj od 0 do 300>: ");
scanf("%d",&temp);
fahr=(double)temp;
celsius=(5.0/9.0)*(fahr-32.0);
printf("\n%d F = %.2f C\n\n", temp, celsius);
getche();
return 0;
}

19
I

2.21. AX+B=0,
(0).

#include <stdio.h>

main()
{
float X, A, B;
printf("A = ");
scanf("%f", &A);
printf("B = ");
scanf("%f",&B);

X=-B/A;
printf("Jednacina ima oblik %.2fX + %.2f = 0\n", A, B);
printf("Resenje X= %.2f\n", X);
getche();
return 0;
}

2.22. y = x + x 2 + x 3 .
: :

#include <stdio.h> #include <stdio.h>


#include <math.h> #include <math.h>

main() main()
{ {
float x, y; float x, y;
printf("Unesite x: "); printf("Unesite x: ");
scanf("%f", &x); scanf("%f", &x);
y=sqrt(x+ x*x + x*x*x); y=sqrt(x+ pow(x,2) + pow(x,3));
printf("\y = %.2f", y); printf("\y = %.2f", y);
getche(); getche();
return 0; return 0;
} }

2.23. z = a + bi
b. z = a 2 + b 2 .

#include <stdio.h>
#include <math.h>

main()
{
float a, b, m;
printf("a= "); scanf("%f",&a);
printf("b= "); scanf("%f",&b);
m=sqrt(a*a+b*b);
printf("Modul kompleksnog broja %.2f+%.2fi je %.2f ", a, b, m);
getche();
return 0;
}

20
I

2.24.
z1 = a + bi z 2 = c + di ,
z1 z 2 = (a + c) i(b + d ) .

#include <stdio.h>
#include <math.h>

main()
{
float a1,b1,a2,b2,rz,rr,iz,ir;
printf("a1 = "); scanf("%f",&a1);
printf("b1 = "); scanf("%f",&b1);
printf("a2 = "); scanf("%f",&a2);
printf("b2 = "); scanf("%f",&b2);
rz=a1+a2;
rr=a1-a2;
iz=b1+b2;
ir=b1-b2;
printf("\nz1 = %.2f + %.2fi \nz2 = %.2f + %.2fi
\n",a1,b1,a2,b2);

printf("\nz1+z2 = %.2f + %.2fi", rz, iz);
printf("\nz1-z2 = %.2f + %.2fi", rr, ir);
getche();
return 0;
}

2.25.
.
#include <stdio.h>
#include <math.h>

main()
{
double x1, x2, y1, y2, z1, z2, d;
printf("Unesite koordinate prve tacke <x1,y1,z1>: \n");
scanf("%lf %lf %lf",&x1,&y1,&z1);
printf("Unesite koordinate druge tacke <x2,y2,z2>: \n");
scanf("%lf %lf %lf",&x2,&y2,&z2);
d=sqrt(pow(x2-x1,2)+pow(y2-y1,2)+pow(z2-z1,2));
printf("\nRastojanje d = %.2f\n", d);
getche();
return 0;
}

21
I

2.26.
. :
( xB xC ) ( yB yC ) , ( xC x A ) ( yC y A ) , a = ( xA xB ) ( y A yB )
2 2
a= b=
2 2 2 2

a+b+c P = S ( S a )( S b )( S c )
S= ,
2
#include<stdio.h>
#include <math.h>

main()
{
double xA, yA, xB, yB, xC, yC, a, b, c, s, P;
printf("Koordinate temena trougla\n");
printf("- prvo teme <xA,yA>: "); scanf("%lf%lf",&xA,&yA);
printf("- drugo teme <xB,yB>: "); scanf("%lf%lf",&xB,&yB);
printf("- trece teme <xC,yC>: "); scanf("%lf%lf",&xC,&yC);
a=sqrt(pow(xB-xC,2)+pow(yB-yC,2));
b=sqrt(pow(xC-xA,2)+pow(yC-yA,2));
c=sqrt(pow(xA-xB,2)+pow(yA-yB,2));
s=(a+b+c)/2;
P=sqrt(s*(s-a)*(s-b)*(s-c));
printf("\nPovrsina trougla: %.2f\n", P);
getche();
return 0;
}

2.27. .

#include <stdio.h>

main()
{
int xyz, x, y, z;
printf("Unesite trocifreni broj: ");
scanf("%d",&xyz);
x=xyz/100;
y=(xyz/10)%10;
z=xyz%10;
printf("\nCifre broja %d su %d, %d, %d", xyz,x,y,z);
printf("\nSuma cifara je: %d", x+y+z);
getche();
return 0;
}

22
I

2.28. ,
500 ., 100 . 1 . .

#include<stdio.h>

main()
{
int n, n500, n100, n1;
printf("Unesite cenu proizvoda: ");
scanf("%d",&n);
n500=n/500;
n100=(n%500)/100;
n1=(n%500)%100;
printf("\nBr.novcanica od 500: %d",n500);
printf("\nBr.novcanica od 100: %d",n100);
printf("\nBr.novcanica od 1: %d",n1);
getche();
return 0;
}

2.29.
: : : .

#include<stdio.h>

main()
{
long sec, d, h, m, s;
printf("Unesite vreme u sekundama: ");
scanf("%ld",&sec);
s=sec%60;

m=sec/60;
h=m/60;
m=m%60;
d=h/24;
h=h%24;
printf("\n(d:h:m:s) %ld:%ld:%ld:%ld\n",d,h,m,s);
getche();
return 0;
}

2.30. ,
.

#include<stdio.h>
#define PI 3.141592

main()
{
double x;
int stepen,minut,sekund;
printf("Unesite ugao u radijanima: ");
scanf("%lf",&x);
x*=180/PI; /*konverzija u stepene*/
23
I

stepen=(int)x; /*zaokruzivanje broja stepeni*/


x-=stepen; /*izracunavanje koliko delova stepena je preostalo*/
x*=60; /*izracunavanje broja minuta*/
minut=(int)x; /*zaokruzivanje broja minuta*/
x-=minut; /*koliko delova minuta je ostalo*/
x*=60; /*izracunavanje broja sekundi*/
sekund=(int)x; /*zaokruzivanje broja sekundi*/
printf("\nstepena, minuta, sekundi [%d,%d,%d]\n", stepen, minut, sekund);
getche();
return 0;
}

2.31. a :
#include<stdio.h>

main()
{
int x, y;
int a=0, b=0;
printf("Na pocetku : \na = %d\nb = %d\n", a, b);
a++;
++b;
printf("\nPosle : a++; ++b; \na = %d\nb = %d\n", a, b);
x = ++a;
y = b++;
printf("\nPosle : x = ++a; \na = %d\nx = %d\n", a, x);
printf("\nPosle : y = b++; \nb = %d\ny = %d\n", b, y);
getche();
return 0;
}

24
I

2.32. :
#include<stdio.h>

main()
{
int a = 3, b = 3;
printf("\n a b \n");
printf("\n %d %d\n", a--, --b);
printf("\n %d% d\n", a--, --b);
printf("\n %d% d\n\n", a--, --b);
getche();
return 0;
}

2.33. :

#include<stdio.h>

main()
{
int x=1, y=2, z=3;
printf("Vrednost izraza x==1 je logicka %d.\n", x==1);
printf("Vrednost izraza y!=2 je logicka %d.\n", y!=2);
printf("Vrednost izraza x<=y je logicka %d.\n", x<=1);
printf("Vrednost izraza x>=z je logicka %d.\n", x>=1);
printf("Vrednost izraza x+y==z je logicka %d.\n", x+y==z);
printf("Vrednost izraza x>y*z je logicka %d.\n", x>y*z);
getche();
return 0;
}

2.34. :
#include<stdio.h>

main()
{
int a = 5<3, b = 5>3, c = 3==5, d = 3!=5;
printf("5<3 - %d\n5>3 - %d\n3==5 - %d\n3!=5 - %d\n", a, b, c, d);
printf("Konjunkcija : 3>5 && 5>3 - %d\n", a && b);
printf("Disjunkcija : 3>5 || 5>3 - %d\n", a || b);
printf("Negacija : !(3>5) - %d\n", !a);
getche();
return 0;
}

25
I

2.35.
.
#include<stdio.h>

main()
{
int x, y, n;
printf("Unesite dva heksadecimalna broja: ");
scanf("%i %i", &x, &y);
printf("Unesite broj pomeraja: ");
scanf("%d", &n);
printf("%#x & %#x = %#x\n", x, y, x&y);
printf("%#x | %#x = %#x\n", x, y, x|y);
printf("%#x ^ %#x = %#x\n", x, y, x^y);
printf("%#x << %d = %#x\n", x, n, x<<n);
printf("%#x >> %d = %#x\n", y, n, y>>n);
getche();
return 0;
}

26
I

3.1. .

:
#include <stdio.h>

main()
{
int broj;
printf("Unesite broj: ");
scanf("%d", &broj);
if (broj%2 == 0)
printf("\nUneti broj je paran.\n");
else
printf("\nUneti broj je neparan.\n");
getche();
return 0;
}

( ):
#include <stdio.h>

main()
{
int broj;
printf("Unesite broj: "); scanf("%d", &broj);
(broj%2 == 0) ? printf("\nUneti broj je paran.\n")
: printf("\nUneti broj je neparan.\n");
getche();
return 0;
}

27
I

3.2. ,
.

:
#include <stdio.h>

main()
{
int a;
printf("Unesite ceo broj: ");
scanf("%d", &a);
if(a < 0)
printf("\nBroj je negativan.\n");
else if(a > 0)
printf("\nBroj je pozitivan.\n");
else
printf("\nBroj je nula.\n");
getche();
return 0;
}

( ):
#include <stdio.h>

main()
{
int a;
printf("Unesite ceo broj: "); scanf("%d", &a);
if(a == 0)
printf("\nBroj je nula.\n");
else
(a > 0) ? printf("\nBroj je pozitivan.\n")
: printf("\nBroj je negativan.\n");
getche();
return 0;
}

3.3.
( , ).

:
#include <stdio.h>

main()
{
int a, b;
printf("Unesite broj a= ");
scanf("%d", &a);
printf("Unesite broj b= ");
scanf("%d", &b);
if(a == b)
printf("Brojevi su jednaki.\n");
28
I

else if (a > b)
printf("Broj a je veci od b.\n");
else
printf("Broj a je manji od b.\n");
getche();
return 0;
}

( ):
#include <stdio.h>

main()
{
int a, b;
printf("Unesite broj a= ");
scanf("%d", &a);
printf("Unesite broj b= ");
scanf("%d", &b);
if(a == b)
printf("Brojevi su jednaki.\n");
else
(a > b) ? printf("Broj a je veci od b.\n")
: printf("Broj a je manji od b.\n");
getche();
return 0;
}

3.4. .
#include <stdio.h>

main()
{
int a, b, c, max;
printf("Unesite tri cela broja: ");
scanf("%d%d%d", &a, &b, &c);
max=a;
if(b>max)
max=b;
if(c>max)
max=c;
printf("Najveci je %d\n", max);
getche();
return 0;
}

29
I

3.5. .

#include <stdio.h>

main()
{
double x, y, z, p;
printf("Unesite tri realna broja: ");
scanf("%lf%lf%lf", &x, &y, &z);
if(x>y)
{
p=x; x=y; y=p;
}
if(x>z)
{
p=x; x=z; z=p;
}
if(y>z)
{

p=y; y=z; z=p;
}
printf("Uredjeni brojevi: %.2f %.2f %.2f\n", x, y, z);
getche();
return 0;
}

3.6. k- n
1 0.
#include <stdio.h>

main()
{
int n,k;
printf(" Unesite broj: ");
scanf("%d",&n);
printf(" Unesite poziciju tog broja koju zelite da proverite: ");
scanf("%d",&n);
if((n & (1 << k))!=0)
printf(" Bit je 1\n");
else
printf(" Bit je 0\n");
getche();
return 0;
}

30
I

3.7. ( 100)
(0-50 , 51-60 , 61-70 , 71-80 , 81-90 , 91-100 ).

#include <stdio.h>

main()
{
int a;
printf("Unesite broj bodova: ");
scanf ("%d", &a);
if (a>90)
printf("Ocena je 10\n");
else if (a>80)
printf("Ocena je 9\n");
else if (a>70)
printf("Ocena je 8\n");
else if (a>60)
printf ("Ocena je 7\n");
else if (a>50)
printf("Ocena je 6\n");
else
printf("Ocena je 5\n");
getche();
return 0;
}

3.8. b
( ).

:
#include <stdio.h>

main()
{
int a, b, x;
printf("Unesite donju i gornju granicu opsega: ");
scanf("%d %d", &a, &b);
printf("Unesite ceo broj x= ");
scanf("%d", &x);
if((a <= x*x) && (x*x <= b))
printf("\nx*x=%d pripada oblasti [%d,%d]", x*x, a, b);
else
printf("\nx*x=%d ne pripada oblasti [%d,%d]", x*x, a, b);
getche();
return 0;
}

31
I

( ):
#include <stdio.h>

main()
{
int a, b, x;
printf("Unesite donju i gornju granicu opsega: ");
scanf("%d %d", &a, &b);
printf("Unesite ceo broj x= ");
scanf("%d", &x);
((a <= x*x) && (x*x <= b))
? printf("\nx*x=%d pripada oblasti [%d,%d]", x*x, a, b)
: printf("\nx*x=%d ne pripada oblasti [%d,%d]", x*x, a, b);
getche();
return 0;
}

3.9. .

:
#include <stdio.h>

main()
{
int x, y;
printf("Unesite dva cela broja: ");
scanf("%d %d", &x, &y);
if(x<y)
printf("\nRezultat = %d", y-x);
else
printf("\nRezultat = %d", x-y);
getche();
return 0;
}

( ):
#include <stdio.h>

main()
{
int x, y;
printf("Unesite dva cela broja: ");
scanf("%d %d", &x, &y);
printf("\nRezultat = %d", (x<y)? y-x : x-y);
getche();
return 0;
}

32
I

3.10.
1 , x<0

. y = sgn( x ) = 0 , x=0
1 , x>0

: ( ):
#include <stdio.h> #include <stdio.h>

main() main()
{ {
float x; float x;
int y; int y;
printf("Unesite x= "); printf("Unesite x= ");
scanf("%f", &x); scanf ("%f", &x);
if(x==0) y = (x>0)? 1 : (x<0)? -1 : 0;
y=0; printf("\ny= %d", y);
else if(x>0) getche();
y=1; return 0;
else }
y=-1;
printf("\ny= %d", y);
getche();
return 0;
}

3.11. .
:
2 x, -2<x 2 main()

y = 3 x 1, 5 x < 7 {
1/ x, ostalo
float x, y;
printf ("Unesite x= "); scanf("%f", &x);
if((x<=2) && (x>-2))
y=2*x;
else if((x<7) && (x>=5))
y=3*x-1;
else
y=1/x;
printf("\ny= %.2f", y);
getche();
return 0;
}

3.12. z y. z
min( x, y ), y>0
: z =
max( x , y ), y 0
2 2

#include <stdio.h>

main()
{
33
I

int x, y, z;
printf("Unesite x= "); scanf("%d", &x);
printf ("Unesite y= "); scanf("%d", &y);
if(y < 0)
{
if((x*x)<(y*y)) z=y*y;
else z=x*x;
}
else
{
if(x<y) z=x;
else z=y;
}
printf("\nz= %.d\n", z);
getche();
return 0;
}

3.13. , b c
.
e :
a+b+c
S= , P = S ( S a )( S b )( S c ) .
2

#include <stdio.h>

main()
{
float a,b,c,p,s;
printf("Unesi stranice trougla \na= "); scanf("%f",&a);
printf("b= "); scanf("%f",&b);
printf("c= "); scanf("%f",&c);
if (a+b>c && a+c>b && b+c>a)
{
s=(a+b+c)/2;
p=sqrt(s*(s-a)*(s-b)*(s-c));
printf("tranice formiraju trougao povrsine p= %.2f\n", p);
}
else printf("tranice ne formiraju trougao.\n");
getche();
return 0;
}

34
I

3.14.
.
.
( xB xC ) ( y B yC ) , b= ( xC xA ) ( yC yA )
2 2
: a =
2 2
,
a+b+c
c= ( x A xB ) ( y A y B ) P = S ( S a )( S b )( S c )
2 2
, S= ,
2
#include <stdio.h>
#include <math.h>
#define PI 3.141592

main()
{
double xa, ya, xb, yb, xc, yc, a, b, c, alfa, beta, gama;
printf("Unesite koordinate tacke A(x,y): ");
scanf("%lf%lf",&xa,&ya);
printf("Unesite koordinate tacke B(x,y): ");
scanf("%lf%lf",&xb,&yb);
printf("Unesite koordinate tacke C(x,y): ");
scanf("%lf%lf",&xc,&yc);
a = sqrt(pow(xb-xc,2) + pow(yb-yc,2));
b = sqrt(pow(xa-xc,2) + pow(ya-yc,2));
c = sqrt(pow(xa-xb,2) + pow(ya-yb,2));
printf("\nStranice:\n");
printf("a= %f\n", a);
printf("b= %f\n", b);
printf("c= %f\n", c);
if(a+b>c && a+c>b && b+c>a)
{
alfa = acos( (b*b+c*c-a*a) / (2*b*c) );
beta = acos( (c*c+a*a-b*b) / (2*c*a) );
gama = acos( (a*a+b*b-c*c) / (2*a*b) );
alfa *= 180/PI;
beta *= 180/PI;
gama *= 180/PI;
printf("\nUglovi:\n");
printf("Alfa = %.2f stepeni\n", alfa);
printf("Beta = %.2f stepeni\n", beta);
printf("Gama = %.2f stepeni\n", gama);
}
lse printf("Ne moze se kreirati trougao.\n");
getche();
return 0;
}

35
I

3.15. y = a1 x + b1 y = a2 x + b2 .
. 1, b1, a2 b2
#include <stdio.h>

main()
{
double a1, a2, b1, b2, x, y;
printf("Unesite koeficijente:\na1= "); scanf("%lf", &a1);
printf("b1= "); scanf("%lf", &b1);
printf("a2= "); scanf("%lf", &a2);
printf("b2= "); scanf("%lf", &b2);
printf("\nPrave:\ny=%.2fx+%.2f\ny=%.2fx+%.2f\n", a1, b1, a2, b2);
if(a1==a2)
{
if(b1==b2) printf("\nPrave su podudarne.");
else printf("\nPrave su paralelne.");
}
else
{
x=(b2-b1)/(a1-a2);
y=a1*x+b1;
printf("\nTacka preseka je x= %.2f, y= %.2f\n", x, y);
}
getche();
return 0;
}

(16)

( 15)

36
I

3.16. a x + b 0 < >,


0. b .
#include <stdio.h>

main()
{
char z;
double a, b, x;
printf("Unesite znak [<,>]: "); scanf("%c", &z);
printf("Unesite koeficijente:\na= "); scanf("%lf", &a);
printf("b= "); scanf("%lf", &b);
printf("\nNejednacina ima oblik: %.2fx+%.2f%c0\n", a, b, z);
x=-b/a;
if(a>0) printf("\nResenje x%c%.2f", z, x);
else printf("\nResenje .2f%c%x", z, x);
getche(); return 0;
}

3.17. : a1 x + b1 y = c1
a2 x + b2 y = c2 . a1, a2, b1, b2, c1 c2 .
: D = a1 b1
= a1b2 a2b1 , Dx =
c1 b1
= c1b2 c2b1
a2 b2 c2 b2
a1 c1
Dy = = a1c2 a2 c1 .
a2 c2
:
Dy
1) D 0 : x=
Dx
, y=
D D
2) D = Dx = Dy = 0 : ( )
3) : .

#include <stdio.h>

main()
{
double a1, b1, c1, a2, b2, c2, D, Dx, Dy, x, y;
printf ("Unesite koeficijente prve jednacine:\na1= ");
scanf("%lf", &a1);
printf("b1= "); scanf("%lf", &b1);
printf("c1= "); scanf("%lf", &c1);
printf("Unesite koeficijente druge jednacine:\na2= ");
scanf("%lf", &a2);
printf("b2= "); scanf("%lf", &b2);
printf("c2= "); scanf("%lf", &c2);
D = a1 * b2 - a2 * b1;
Dx = c1 * b2 - c2 * b1;
Dy = a1 * c2 - a2 * c1;
if(D != 0)
{
x=Dx/D;
y=Dy/D;
printf ("\nResenje sistema:\nx= %.2f\n", x);

37
I

printf ("y= %.2f\n", y);


}
else
if(Dx==0 && Dy==0)
printf ("Sistem ima beskonacno resenja.\n");
else printf ("Sistem nema resenja.\n");
getche();
return(0);
}

3.18. ax 2 + bx + c = 0 .
D = b 2 4ac :
1) 0 D>0: ( x1,2 = b d ),
2a
b
2) 0 D=0: ( x1,2 = ),
2a
3) 0 D<0: ( x1,2 = b i d ),
2a
c
4) =0 b0: , ( x = ),
b
5) =0 b=0: .

#include <stdio.h>
#include <math.h>

main()
{
double a, b, c, D, x1, x2;
printf("Unesite koeficijente:\na= "); scanf("%lf",&a);
printf("b= "); scanf("%lf",&b);
printf("c= "); scanf("%lf",&c);
if(a!=0)
{
D=b*b-4*a*c;
if(D>0)
{
x1=(-b+sqrt(D))/(2*a);
x2=(-b-sqrt(D))/(2*a);
38
I

printf("n\Resenja:\nx1=%.2f, x2=%.2f",x1,x2);
}
else if(D==0)
{
x1=(-b/(2*a));
printf("\nResenje:\nx1=x2=%.2f",x1);
}
else
{
x1=-b/(2*a);
x2=sqrt(-D)/(2*a);
printf("\nKompleksna resenja:\n");
printf("x1=%.2f+i%.2f, x2=%.2f-i%.2fi",x1,x2,x1,x2);
}
}
else
{
if(b!=0)
{
x1=-c/b;
printf("\nResenje:\nx=%.2f",x1);
}
else printf("Sistem nema resenja.");
}
getche();
return 0;
}

39
I

4 FOR

4.1. Pozdrav svima! FOR


.
#include <stdio.h>

main()
{
int i;
for(i=1; i<6; i++)
printf("Pozdrav svima!\n");
getche();
return 0;
}

4.2. FOR :
) ,
)
) .

) #include <stdio.h>

main()
{
int i;
for(i=1; i<=10; i=i+1)
printf("%d\n", i);
getche();
return 0;
} )

) #include <stdio.h>
)
main()
{
int i;
for (i=1; i<=10; i=i+2)
printf("%d\n", i);
getche();
return 0;
}

40
I

)
#include <stdio.h>

main()
{
int i;
for(i=10; i>=1; i=i-1)
printf("%d\n", i);
getche();
return 0;
}

4.3. i j FOR
:
#include <stdio.h>

main()
{
int i, j;
for(i=1; i<3; i++)
for(j=1; j<4; j++)
printf("i=%d, j=%d\n", i, j);
printf("\n");
for(i=1; i<4; i++)
for(j=1; j<3; j++)
printf("i=%d, j=%d\n", i, j);
getche();
return 0;
}

4.4. n n .

#include <stdio.h>

main()
{
int n, s, i;
printf("Unesite n= ");
scanf("%d", &n);
s=0;
for(i=1; i<=n; i++)
s+=i;
printf("Suma= %d\n", s);
getche();
return 0;
}

41
I

4.5. n n
.

#include <stdio.h>

main()
{
int n, i;
float a, s, ars;
s=0;
printf("n= ");
scanf("%d",&n);
printf(" Unesite %d brojeva:\n", n);
for(i=1; i<=n; i++)
{
scanf("%f",&a);
s+=a;
}
ars=s/n;
printf("\n Suma zadatih brojeva je %.2f", s);
printf("\n Aritmeticka sredina zadatih brojeva je %.2f", ars);
getche();
return 0;
}

4.6. n .

#include <stdio.h>

main()
{
int i,n;
long faktorijel=1;
printf("n= ");
scanf("%d",&n);
for(i=1;i<=n;i++)
faktorijel=faktorijel*i;
printf("Faktorijel = %ld\n", faktorijel);
getche();
return 0;
}

42
I

4.7. n : S =1!+2!+3!+...+n!.
#include <stdio.h>

main()
{
int i,n;
long f=1, s=0;
printf("n= ");
scanf("%d",&n);
for(i=1; i<=n; i++)
{
f*=i;
s+=f;
}
printf("\ns= %ld\n", s);
getche();
return 0;
}

4.8. , m n, :
) S = n ( n + m )( n + 2 m ) ... ( n + m m )
1 1 1 1
... ( 1)
m +1
) S = +
n + m n + 2m n + 3m n + mm
) #include <stdio.h> ) #include <stdio.h>

main() main()
{ {
int i, m, n; int i, m, n, znak;
long s; float s;
printf("n= "); printf("n= ");
scanf("%d",&n); scanf("%d",&n);
printf("m= "); printf("m= ");
scanf("%d",&m); scanf("%d",&m);
s=1; s=0;
for(i=0;i<=m;i++) znak=1;
s=s*(n+i*m); for(i=1;i<=m;i++)
printf("\ns= %ld\n", s); {
getche(); s=s+(float)znak/(n+i*m);
return 0; znak=-znak;
} }
printf("\ns= %.5f\n", s);
getche();
return 0;
}

) )

43
I

4.9. , n :
) S = + 2! +
1! 3!
+ ... +
n!
1 1 1 1 1 1 1 1 1
+ + + + + ... +
2 2 3 2 3 4 2 3 n +1
1+ 2 1+ 2 + 3 n 1 1 + 2 + 3 + .. + n
) S = 1 + ... ( 1)
2! 3! n!
cos (1) cos (1) + cos ( 2 ) cos (1) + cos ( 2 ) + ... + cos ( n )
) S = * *...*
sin (1) sin (1) + sin ( 2 ) sin (1) + sin ( 2 ) + ... + sin ( n )

) #include <stdio.h> ) #include <stdio.h>

main() main()
{ {
int i, n, fakt; int i, n, fakt, znak;
float s, q; float s, q;
printf("n= "); printf("n= ");
scanf("%d",&n); scanf("%d",&n);
s=0; s=0;
q=0; q=0;
fakt=1; fakt=1;
for(i=1; i<=n; i++) znak=1;
{ for(i=1; i<=n; i++)
fakt=fakt*i; {
q=q+1./(1+i); fakt=fakt*i;
s=s+fakt/q; q=q+i;
} s=s+znak*q/(float)fakt;
printf("\ns= %.5f\n", s); znak=-znak;
getche(); }
return 0; printf("\ns= %.5f\n", s);
} getche();
return 0;
}

) #include <stdio.h>
#include <math.h>

main()
{
int i, n;
float s, p, q;
printf("n= ");
scanf("%d",&n);
s=1;
p=0; ) )
q=0;
for(i=1; i<=n; i++)
{
p=p+cos(i);
q=q+sin(i);
s=s*p/(float)q;
}
printf("\ns= %.5f\n", s);
getche();
return 0;
}
)

44
I

4.10. , n , :
) S = sin ( x ) + sin 2 ( x ) + ... + sin n ( x )

( ) ( )
) S = cos ( x ) + cos x 2 + ... + cos x n

) #include <stdio.h> ) #include <stdio.h>


#include <math.h> #include <math.h>

main() main()
{ {
int i, n; int i, n;
float s, p, x; float s, p, x;
printf("n= "); printf("n= ");
scanf("%d",&n); scanf("%d",&n);
printf("x= "); printf("x= ");
scanf("%f",&x); scanf("%f",&x);
s=0; s=0;
p=1; p=1;
for(i=1; i<=n; i++) for(i=1; i<=n; i++)
{ {
p=p*sin(x); p=p*x;
s=s+p; s=s+cos(p);
} }
printf("\ns= %.5f\n", s); printf("\ns= %.5f\n", s);
getche(); getche();
return 0; return 0;
} }

) )

4.11. , n, :
1 1 1 1
S= ... #include <stdio.h>
2 2+ 2 2+ 2+ 2 2 + 2 + ... + 2
#include <math.h>

main()
{
n . int i, n;
float s, p;
printf("n= "); scanf("%d",&n);
s=1; p=0;
for(i=1; i<=n; i++)
{
p=sqrt(p+2);
s=s/(float)p;
}
printf("\ns= %.5f\n", s);
getche();
return 0;
}

45
I

4.12. n .

#include <stdio.h>

main()
{
int i, n;
float br, max;
printf("\nn= ");
scanf("%d",&n);
printf("\nUnesite 1. broj: ");
scanf("%f",&br);
max=br;
for(i=2; i<=n; i++)
{
printf("Unesite %d. broj: ",i);
scanf("%f",&br);
if(br>max) max=br;
}
printf("\nNajveci: %.2f", max);
getche();
return 0;
}

4.13. 6
.

#include <stdio.h>

main()
{
int i, s=0;
printf("Brojevi deljivi sa 6:\n");
for(i=1; i<=100; i++)
{
if(i%6 == 0)
{
s=s+i;
printf("\n%d", i);;
}
}
printf("\n\nSuma: %d\n", s);
getche();
return 0;
}

46
I

4.14. 2
, 1 .
#include <stdio.h>

main()
{
int a, b, c;
for(a=1; a<=9; a++)
for(b=3; b<=9; b++)
for(c=4; c<=9; c++)
if(b == a+2 && c == b+1)
printf("%d%d%d\n", a, b, c);
getche();
return 0;
}

4.15. .
.
#include <stdio.h>
#include <math.h>

main()
{
int a, b, c, broj;
printf("Amstrongovi brojevi:\n");
for(a=1; a<=9; a++)
for(b=0; b<9; b++)
for(c=0; c<9; c++)
{
broj=100*a+10*b+c;
if(broj == pow(a,3)+pow(b,3)+pow(c,3))
printf("\n%d", broj);
}
getche();
return 0;
}

4.16.
()= ()2-2, 1 A 9 , 0 B 9 , 0 C 9 . : 147=142-72.
#include <stdio.h>
main()
{
int a, b, c, broj;
for(a=1; a<=9; a++)
for(b=0; b<9; b++)
for(c=0; c<9; c++)
{
broj=100*a+10*b+c;
if(broj == ((10*a+b)*(10*a+b)-c*c))
printf("\n%d", broj);
}
getche(); return 0;
}

47
I

4.17.
.

#include <stdio.h>

main()
{
int a, b, c, broj, dvocif;
for(a=1;a<=9;a++)
for(b=0;b<9;b++)
for(c=0;c<9;c++)
{
broj=100*a+10*b+c;
dvocif=10*a+c;
if(broj%dvocif == 0)
printf("%d, ", broj);
}
getche();
return 0;
}

4.18.
5. .

#include <stdio.h>

main()
{
int a, b, c, s=0, br, n=0;
for(a=1; a<=9; a++)
for(b=0; b<9; b++)
for(c=0; c<9; c++)
{
br=100*a+10*b+c;
if (a+b+c == 5)
{
n++;
s+=br;
}
}
printf("Suma: %d\n", s);
printf("Ukupno brojeva: %d\n", n);
getche();
return 0;
}

48
I

4.19. n.
#include <stdio.h>

main()
{
int i, n;
printf("n= ");
scanf("%d",&n);
printf("\nDelioci:");
for(i=1; i<=n; i++)
{
if(n%i == 0)
printf("\n%d ", i);
}
getche();
return 0;
}

4.20. n .
. , 28=1+2+4+7+14.
#include <stdio.h>

main()
{
int n, i, suma=0;
printf("n= ");
scanf("%d",&n);
for(i=1; i<n; i++)
{
if(n%i==0)
suma+=i;
}
if(suma==n)
printf("Broj %d jeste savrsen broj.\n",n);
else
printf("Broj %d nije savrsen broj.\n",n);
getche();
return 0;
}

4.21. n
1.
#include <stdio.h>

main()
{
int i, br=0, n, ocena;
float s,srednja;
printf("Broj ucenika n= ");
scanf("%d",&n);
for(i=1; i<=n; i++)
49
I

{
printf("Unesi ocenu %d. ucenika: ",i);
scanf("%d",&ocena);
s+=ocena;
if(ocena==1) br++;
}
srednja=s/n;
printf("\nSrednja ocena: %.2f", srednja);
printf("\nBroj negativnih: %d", br);
getche();
return 0;
}

4.22. , .

n. (n=33):
0 sat 11 min 31 sec
1 sat 32 min 0 sec .

#include <stdio.h>

main()
{
int sat, min, sec, n;
printf("n= ");
scanf("%d",&n);
for(sat=0; sat<=23; sat++)
for(min=0; min<=59; min++)
for(sec=0; sec<=59; sec++)
{
if(n==(sat/10+sat%10+min/10+min%10+sec/10+sec%10))
printf("\n%d sat %d min %d sec", sat, min, sec);
}
getche();
return 0;
}

50
I

( 23)

( 22)

2x +1
4.23. y = xmin xmax
x2 1
dx.
#include <stdio.h>

main()
{
double xmin, xmax, dx, x, y;
printf("xmin= ");
scanf("%lf", &xmin);
printf("xmax= ");
scanf("%lf", &xmax);
printf("dx= ");
scanf("%lf", &dx);
printf("\n x y\n ===================\n");
for(x=xmin; x<=xmax; x+=dx)
{
y=(2*x+1)/(x*x-1);
printf ("%10.3f%10.3f\n", x, y);
}
getche();
return 0;
}

4.24. ( ) ( )
y = (1 + x ) 1 + x 2 ... 1 + x n xmin
xmax dx. n .

51
I

#include <stdio.h>

main()
{
double xmin, xmax, dx, x, y=1, p=1;
int i, n;
printf("n= ");
scanf("%d", &n);
printf("xmin= ");
scanf("%lf", &xmin);
printf("xmax= ");
scanf("%lf", &xmax);
printf("dx= ");
scanf("%lf", &dx);
printf("\n x y\n");
printf("===================\n");
for(x=xmin;x<=xmax;x+=dx)
{
for(i=1; i<=n; i++)
{
p*=x;
y*=(1+p);
}
printf("%10.6f %11.6f\n",x,y);
p=1;
y=1;
}
getche();
return 0;
}

4.25. 0 90
( ) . sin
.

#include <stdio.h>
#include <math.h>
#define PI 3.141592

main()
{
double dx=0, UgaoRad, UgaoSte;
printf("Unesite korak u stepenima: ");
scanf("%lf",&dx);
printf("\n x sin(x)");
printf("\n=======================\n");
for(UgaoSte=0; UgaoSte<=90; UgaoSte+=dx)
{
UgaoRad = (PI*UgaoSte)/180.0;
printf("%f \t%f\n",UgaoSte, sin(UgaoRad));
}
getche();
return 0;
}

52
I

4.26. n ,
n=5.
a) **********
) 0123456789
********** 0123456789
********** 0123456789
********** 0123456789
********** 0123456789

) )
#include <stdio.h> #include <stdio.h>
main() main()
{ {
int i, j, n; int i, j, n;
printf(" n= "); printf(" n= ");
scanf("%d", &n); scanf("%d", &n);
printf("\n"); printf("\n");
for(i=0; i<n; i++) for(i=0; i<n; i++) )
{ {
for(j=0; j<2*n; j++) for(j=0; j<2*n; j++)
printf("*"); printf("%d", j);
printf("\n"); printf("\n");
} }
getche(); getche();
return 0; return 0;
} }

4.27. m n
ASCII .
#include <stdio.h>

main()
{
int i, j, m, n, a;
printf(" m= ");
scanf("%d", &m);
printf(" n= ");
scanf("%d", &n);
printf(" ASCII= ");
scanf("%d", &a);
printf("\n");

for(i=0; i<m; i++)
{
for(j=0; j<n; j++)
printf("%c", a);
printf("\n");
}
getche();
return 0;
}

53
I

4.28. n ,
n=5.
) ) ) )

* * * * * ***** * *
* * * * * * * * * **
* * * * * * * * ** * *
* * * * * * * * *** * *
* * * * * ***** * **** *****

) ) ) )

* **** ***** * *****


* *** * * ** ****
* ** * * *** ***
* * ** **** **
* * ***** *

) #include <stdio.h> ) #include <stdio.h>

main() main()
{ {
int i, j, n; int i, j, n;
printf(" n= "); printf(" n= ");
scanf("%d", &n); scanf("%d", &n);
printf("\n"); printf("\n");
for(i=1; i<=n; i++) for(i=1; i<=n; i++)
{ {
for(j=1; j<=n; j++) for(j=1; j<=i; j++)
printf("* "); printf("* ");
printf("\n"); printf("\n");
} }
getche(); getche();
return 0; return 0;
} }

) ) ) )

54
I

) #include <stdio.h> ) #include <stdio.h>

main() main()
{ {
int i, j, n; int i, j, n;
printf(" n= "); printf(" n= ");
scanf("%d", &n); scanf("%d", &n);
printf("\n"); printf("\n");
for(i=1; i<=n; i++) for(i=1; i<=n; i++)
{ {
for(j=1; j<=n; j++) for(j=1; j<=i; j++)
{ {
if(i==1 || i==n) if(i==n)
printf("* "); printf("* ");
else if (j==1 || j==n) else if (j==1 || j==i)
printf("* "); printf("* ");
else printf(" "); else printf(" ");
} }
printf("\n"); printf("\n");
} }
getche(); getche();
return 0; return 0;
} }

) #include <stdio.h> ) #include <stdio.h>

main()
main()
{
{
int i, j, n;
int i, j, n;
printf(" n= ");
printf(" n= ");
scanf("%d", &n); scanf("%d", &n);
printf("\n"); printf("\n");
for(i=1; i<=n; i++)
for(i=1; i<=n; i++)
{ {
for(j=n; j>=i; j--)
for(j=n; j>=i; j--)
{
printf("* ");
if(i==1) printf("* ");
printf("\n");
else if(j==n || j==i)
}
printf("* ");
getche();
return 0; else printf(" ");
} }
printf("\n");
}
getche();
return 0;
}

) ) ) )

55
I

) #include <stdio.h> ) #include <stdio.h>

main() main()
{ {
int i, j, n, k; int i, j, n, k;
printf(" n= "); printf(" n= ");
scanf("%d", &n); scanf("%d", &n);
printf("\n"); printf("\n");
for(i=1; i<=n; i++) for(i=n; i>=1; i--)
{ {
for(k=n; k>i; k--) for(k=n; k>i; k--)
printf(" "); printf(" ");
for(j=1; j<=i; j++) for(j=1; j<=i; j++)
printf("* "); printf("* ");
printf("\n"); printf("\n");
} }
getche(); getche();
return 0; return 0;
} }

4.29. n ,
n=5.
#include <stdio.h>

main()
{
int n, i, j, k;
printf("n= "); scanf("%d", &n);
printf("\n");
for(i=1; i<=n; i++)
{
for(k=n; k>i; k--)
printf(" ");
for(j=0; j<i; j++)
printf("* ");
printf("\n");
}
for(i=n-1; i>0; i--)
{
for(k=n; k>i; k--)
printf(" ");
for(j=0; j<i; j++)
printf("* ");
printf("\n");
}
getche(); return 0;
}

56
I

4.30. n ( 1 9)
, n=5.
#include <stdio.h>

main()
{
int n, i, j, k, m;
printf("n= "); scanf("%d",&n);
printf("\n");
for(i=n; i>0; i--)
{
m=i;
for(k=n; k>i; k--)
printf(" ");
for(j=0; j<i; j++)
printf("%d ", m);
printf("\n");

}
for(i=2; i<=n; i++)
{
m=i;
for(k=n; k>i; k--)
printf(" ");
for(j=0; j<i; j++)
printf("%d ", m);
printf("\n");
}
getche();
return 0;
}

4.31. n ,
n=7. .

#include <stdio.h>

main()
{
int i, j, n;
printf("n= ");
scanf("%d", &n);
printf("\n");
for(i=1; i<=n; i++)
{
if(i%2==0) printf(" ");
if(i%4==3) printf(" ");
for(j=1; j<=n; j++)
printf("* ");
printf("\n");
}
getche();
return 0;
}

57
I

4.32. n ,
n=5.
#include <stdio.h>

main()
{
int n, i, j, nzv, nrz, kor=1;
printf(" n= ");
scanf("%d", &n);
printf("\n");
nzv=n,
nrz=n-1;
for(i=1; i<=2*n-1; i++)
{
for(j=1; j<=nrz; j++)
printf(" ");
for(j=1; j<=nzv; j++)
printf("* ");
printf("\n");
if(i==n) kor = -1;
nzv += kor;
nrz -= kor;
}
getche();
return 0;
}

4.33. n
, n=3.
#include <stdio.h>

main()
{
int n, i, j, nzv=0, kor=1;
char rep = ' ';
printf(" n= ");
scanf("%d", &n);
printf("\n");
for(i=1; i<=3*n; i++)
{
nzv+=kor;
for(j=1; j<=3*n; j++)
printf("%c", rep);
for(j=1; j<=nzv; j++)
printf("*");
printf("\n");
if(i==n) rep='*';
if(i==3*n/2+1) kor=-1;
if(i==2*n) rep = ' ';
}
getche();
return 0;
}

58
I

4.34. n
, n=7. je 2n-1.
#include <stdio.h>

main()
{
int i, j, n;
printf(" n= "); scanf("%d", &n);
printf("\n");
for(i=0;i<2*n-1;i++)
{
if(i==0 || i==n-1 || i==2*n-2)
printf("+");
else printf("-");
}
printf("\n");
for(j=0;j<n-2;j++)
{
for(i=0; i<2*n-1; i++)
{
if(i==0 || i==n-1 || i==2*n-2)
printf("|");
else printf(" ");
}
printf("\n");
}
for(i=0;i<2*n-1;i++)

{
if(i==0 || i==n-1 || i==2*n-2)
printf("+");
else printf("-");
}
printf("\n");
getche();
return 0;
}

4.35. n
, n=9.

#include <stdio.h>

main()
{
int i, j, n;
printf(" n= ");
scanf("%d", &n);
printf ("\n");
printf("+");
for(i=0;i<n-2;i++)
printf("-");
printf("+\n");
for(i=1; i<n-1; i++)
{
printf("|");
for(j=1; j<n-1; j++)
if(i==n/2 && j==n/2) printf("+");
59
I

else if(j==n/2 ) printf("|");


else if(i==n/2 ) printf("-");
else printf(" ");
printf("|\n");
}
printf("+");
for(i=0; i<n-2; i++)
printf("-");
printf("+\n");
getche();
return 0;
}

4.36. n
, n=7.
#include <stdio.h>

main()
{
int i, j, n;
printf(" n= ");
scanf("%d", &n);
printf("\n");

printf("+");
for(i=0; i<n-2; i++)
printf("-");
printf ("+\n");

for(j=0; j<n-2; j++)


{
printf("|");
for(i=0;i<n-2;i++)
{
if(i==j) printf("\\");
else printf(" ");
}
printf("|\n");
}

printf ("+");
for(i=0; i<n-2; i++)
printf ("-");
printf("+\n");

getche();
return 0;
}

60
I

4.37. n
, n=7.

#include <stdio.h>

main()
{
int n, i, j;
printf(" n= ");
scanf("%d", &n);
printf("\n");

printf("+");
for(i=0;i<n-2;i++)
printf("-");
printf("+\n");

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


{
printf("|");
for(j=1; j<n-1; j++)
if(i==n/2 && j==n/2) printf("X");
else if(i==j) printf("\\");
else if(i==n-1-j) printf("/");
else printf(" ");
printf("|\n");
}

printf("+");
for(i=0; i<n-2; i++)
printf("-");

printf("+\n");
getche();
return 0;
}

61
I

5 WHILE

5.1. Pozdrav svima!


WHILE .

#include <stdio.h>

main()
{
int i;
i=1;
while(i<=5)
{
printf("Pozdrav svima!\n");

i++;
}
getche();
return 0;
}

5.2. WHILE :
) ,
)
) .

) #include <stdio.h> ) #include <stdio.h>

main() main()
{ {
int i; int i;
i=1; i=2;
while(i<=10) while(i<=10)
{ {
printf("%d\n", i); printf("%d\n", i);
i++; i+=2;
} }
getche(); getche();
return 0; return 0;
} }

62
I

a)

) #include <stdio.h>

main()
{
int i;
i=10;
while(i<=10 & i>0)
{
printf("%d\n", i);
i--;
}
getche();
return 0;
)
}

5.3. 1 n. n
.

#include <stdio.h>

main()
{
int n, i=1, suma=0;
printf("n= ");
scanf("%d",&n);
while(i <= n)
{
suma+= i;
i++;
}
printf("Suma prirodnih brojeva od 1 do %d je: %d\n", n, suma);
getche();
return 0;
}

63
I

5.4. 1 n. n
.

#include <stdio.h>

main()
{
int i=1, suma=0, n;
printf(" n= ");
scanf("%d",&n);
while(i<=n)
{
suma=suma+i;
i=i+3;
}
printf(" Suma svakog treceg broja, od 1 do %d, je %d\n", n,suma);
getche();
return 0;
}

5.5. n :
1 1 1 1
S = 2 + 2 + 2 + ... +
( 2n + 1)
2
3 5 7

#include <stdio.h>
#include <math.h>

main()
{
int i=1, n;
float s=0;
printf(" n= "); scanf("%d", &n);
while(i<=n)

{
s+=1./pow(2*i+1,2);
i++;
}
printf("\n s= %f\n", s);
getche();
return 0;
}

5.6. s
n m (n<m).

#include <stdio.h>
#include <math.h>

main()
{
int i, n, m;
long s=0;
64
I

printf(" n= "); scanf("%d", &n);


printf(" m= "); scanf("%d", &m);
i=n;
while(i<=m)
{
if(i%2==0) s=s+pow(i,2);
else s=s+pow(i,3);
i++;
}
printf("\n s= %ld\n", s);
getche();
return 0;
}

5.7. :
) n ;
) n .
: f1=1, f2=1, fi=fi-1+fi-2, i=3, 4, 5, ...

) #include <stdio.h> ) #include <stdio.h>

main() main()
{ {
int i=3, n, fpp=1, fp=1, fn; int i=3, n, fpp=1, fp=1, fn,s=2;
printf(" n= "); printf(" n= ");
scanf("%d", &n); scanf("%d", &n);
printf("\n f1= 1\n f2= 1\n"); while(i<=n)
while(i<=n) {
{ fn=fp+fpp;
fn=fp+fpp; s=s+fn;
fpp=fp; fpp=fp;
fp=fn; fp=fn;
printf(" f%d= %d\n", i, fn); i++;
i++; }
} printf("\n s= %d\n", s);
getche(); getche();
return 0; return 0;
} }

65
I

5.8. n- . .

#include <stdio.h>

main()
{
int a, n, i=1, stepen=1;
printf(" a= ");
scanf("%d",&a);
printf(" n= ");
scanf("%d",&n);

while(i<=n)
{
stepen*=a;
i++;
}
printf("\n Broj %d na %d-ti stepen je: %d\n",a,n,stepen);
getche();
return 0;
}

5.9. .
0 STOP .
#include <stdio.h>
#define STOP 0

main()
{
int n=0;
float x, suma=0;
printf("\n Unesite niz realnih brojeva (0 za kraj):\n\n");
scanf("%f",&x);
while(x!=STOP)
{
suma += x;
n++;
scanf("%f",&x);
}
if (n==0)
printf("\n Nije zadat niz realnih brojeva.\n\n");
else
printf("\n Aritmeticka sredina zadatog niza je %.3f\n",suma/n);
getche();
return 0;
}

66
I

5.10. .
.
2 6.
#include <stdio.h>

main()
{
int i=0;
float x, suma=0, sredina;
printf("\n Unesite niz realnih brojeva (0 za kraj):\n\n");
while(1)
{
scanf("%f",&x);
if(x==0)
{
sredina=suma/i;
printf(" Aritmeticka sredina: %.3f\n", sredina);
}
if(x>=2 && x<=6)
{
suma+=x;
i++;
}
}
getche();
return 0;
}

5.11. m n (m>n).
. :
m m!
b=
( n )!
n n ! m

#include <stdio.h>

main()
{
int m=0, n, i, brojilac=1, imenilac=1;
while(m<1 || n<1 || n>m)
{
printf("\n Unesite m i n: ");
scanf("%d%d",&m,&n);
}
for(i=m;i>m-n;i--)
brojilac=brojilac*i;
for(i=1;i<=n;i++)
imenilac=imenilac*i;
brojilac=brojilac/imenilac;
printf("\n Binomni koeficijent b= %d \n ", brojilac);
getche();
return 0;
}

67
I

5.12. m n. .
, . n<m, m n.
m n.
#include <stdio.h>
#include <math.h>

main()
{
int m=0, n, pomoc, i;
float suma=0, koren;
printf("\n Unesite m i n [0<m<n]: ");
while(m<1 || n<1)
scanf("%d%d",&m,&n);
if(m>n)
{
pomoc=n;
n=m;
m=pomoc;
}
if(m%2==0) m++;
for(i=m;i<=n;i=i+2)
{
koren=sqrt(i);
suma+=koren;
}
printf("\n Suma korena je %.3f\n", suma);
getche();
return 0;
}

1 1 1 n 1 1
5.13. n : S = 1 + + ... + ( 1)
2 3 4 n
#include <stdio.h>

main()
{
int znak=1, i=1, n;
float suma=0;
printf("\n n= ");
scanf("%d",&n);
while(i<=n)
{
suma+=(float)znak/i;
i++;
znak=-znak;
}
printf("\n S= %.3f\n", suma);
getche();
return 0;
}

68
I


1 1 1 1
5.14. : S = 2
+ 2 + 2 + ... = 2
1 2 3 n =1 n
10-4.

#include <stdio.h>

main()
{
int n=1;
float suma=0, clan;
clan=1/(n*n);
while(clan>1e-4)
{
suma=suma+clan;
n++;
clan=1.0/(n*n);
}
printf("\n S= %.3f\n", suma);
getche();
return 0;
}

x x2 n x
n
5.15. : S = 1 + ... + ( 1) + ...
1! 2! n!
( )
. .

#include <stdio.h>

main()
{
double suma=1.0, x, eps, clan;
int n=1, i;
printf("\n x= ");
scanf("%lf",&x);
printf("\n eps= ");
scanf("%lf",&eps);
clan=x;

while(abs(clan)>=eps)
{
suma+=clan;
clan=x;
n++;
for(i=2;i<=n;i++)
clan=-clan*(-x/i);
}
printf("\n S= %lf", suma);
printf("\n Br.elemenata= %d\n", n);
getche();
return 0;
}

69
I

5.16. :
a ( a 1) a ( a 1) ... ( a n + 1)
S = 1 + ax + x 2 + ... + x n + ...
2! n!
( ).
.
#include <stdio.h>

main()
{
double suma=1.0, x, a, eps, clan;
int i=0;
printf("\n x= ");
scanf("%lf",&x);
printf("\n a= ");
scanf("%lf",&a);
printf("\n eps= ");
scanf("%lf",&eps);
clan=x;
while(fabs(clan)>=eps)
{
i++;
clan=clan*(a-i+1)*x/i;
suma=suma+clan;
}
printf("\n S= %lf\n", suma);
getche();
return 0;
}

5.17. (NZD) a b
:
- a=b, NZD=a ;
- b, .

#include <stdio.h>

main()
{
int a, b;
printf(" a= ");
scanf("%d",&a);
printf(" b= ");
scanf("%d", &b);
while(a!=b)
{
if(a>b) a-=b;
else b-=a;
}
printf("\n NZD=: %d\n",a);
getche();
return 0;
}

70
I

5.18. .
.

#include <stdio.h>

main()
{
int n, k, suma=0;
printf(" n= ");
scanf("%d", &n);
k=n;
while(k > 0)
{
suma+=k%10;
k /= 10;
}
if(k%suma==0)
printf("\n Broj %d jeste Nivenov\n", n);
else
printf("\n Broj %d nije Nivenov\n", n);
getche();
return 0;
}

5.19.
.

#include <stdio.h>

main()
{
int n, obrnuti=0;
printf(" n= ");
scanf("%d", &n);
while(n > 0)

{
obrnuti = obrnuti*10 + n%10;
n /= 10;
}
printf("\n Obruti: %d\n", obrnuti);
getche();
return 0;
}

5.20. . ,
28 : 2 2 7.
#include <stdio.h>

main()
{
int m, n, k;
printf(" n= ");

71
I

scanf("%d",&n);
printf("\n\n Prosti faktori:");
m=n/2;
for (k=2;k<=m;k++)
{
while(n%k==0)
{
printf("\n%3d", k);
n/=k;
}
}
getche();
return 0;
}

5.21. , b c 1 a 20 ,
1 b 20 . : a2+b2=c2.

#include <stdio.h>

main()
{
int a, b, c, zbir;
printf(" Pitagorini brojevi:\n");
for(a=1;a<=20;a++)
{
for(b=1;b<=20;b++)
{
zbir=a*a+b*b;
c=1;
while(c*c<=zbir)
{
if(c*c==zbir)
printf(" a=%2d b=%2d c=%2d\n", a,b,c);
c++;
}
}
}
getche();
return 0;
}

72
I

6 DO...WHILE

6.1. Pozdrav svima! DO


WHILE .
#include <stdio.h>

main()
{
int i;
i=1;
do
{
printf("Pozdrav svima!\n");
i++;
}
while(i<=5);
getche();
return 0;
}

6.2. DO WHILE :
) ,
)
) .

) #include <stdio.h>

main()
{
int i;
i=1;
do
{
printf("%d\n", i);
i++;
}
while(i<=10);
getche();
return 0; ) )
}

73
I

) )
#include <stdio.h> #include <stdio.h>

main() main()
{ {
int i; int i;
i=2; i=10;
do do
{ {
printf("%d\n", i); printf("%d\n", i);
i+=2; ) i--;
} }
while(i<=10); while(i<=10 & i>0);
getche(); getche();
return 0; return 0;
} }

6.3.
.

#include <stdio.h>

main()
{
int n;
do
{
printf(" n= ");
scanf("%d", &n);
}

while(n*n<=0 || n*n>100);
printf("\n Kvadrat broja %d [%d] pripada prvoj stotini.\n", n, n*n);
getche();
return 0;
}

6.4. 2
, 2.
#include <stdio.h>

main()
{
int stepen,granica;
printf(" Unesite granicu: ");
scanf("%d",&granica);
stepen=1;
do
{
printf(" %d\n",stepen);
stepen*=2;
}
while(stepen <= granica);
getche();
return 0;
}
74
I

6.5. =3.1415926... :
1 1 1
= 1 + + ...
4 3 5 7
.

#include <stdio.h>
#include <math.h>

main()
{
float znak=-1.0;
int i=1;
float clan=1.0, suma=1.0, eps;

printf(" eps= ");
scanf("%f", &eps);
do
{
clan=(float)znak/(2*i+1);
suma+=clan;
znak=-znak;
i++;
}
while(fabs(clan) > eps);
printf("\n Pi= %f", 4*suma);
getche();
return 0;
}

1 1 1
6.6. 1, 1+ , 1+ + , ...
2 2 3
.

#include <stdio.h>

main()
{
float a, i=0, s=0;
printf(" a= ");
scanf("%f",&a);
do

{
i++;
s=s+1/i;
}
while(s<a);
printf("\n S=%.3f", s);
getche();
return 0;
}

75
I

6.7.
1 x
. : yi +1 = yi + , ,
2 yi
y0 = x + 1 .
#include <stdio.h>
#include <math.h>

main()
{
float x, y, z, eps;
printf(" Unesite broj x= ");
scanf("%f", &x);
printf(" Unesite tacnost eps= ");
scanf("%f", &eps);
y=x+1;
do
{
z=y;
y=0.5*(y+x/y);
}
while(fabs(z-y) > eps);
printf("\n Koren iz %.3f je %.3f", x, y);
getche();
return 0;
}

6.8.
4. .
.
#include <stdio.h>

main()
{
int x, a, b, brojac=0;
do
{
printf(" Unesite granice opsega [cele brojeve od 1 do 100]: ");
scanf("%d%d",&a,&b);
}
while(a<1 || a>b || b<=a || b>100);
printf("\n Brojevi u opsegu od %d do %d deljivi sa 4:\n", a, b);
for(x=a;x<=b;x++)
{
if(x%4==0)
{
printf(" %d ", x);
brojac++;
}
if(brojac%10==0)
printf("\n");
}
getche();
return 0;
}

76
I

6.9.
64. ?

#include <stdio.h>

main()
{
int i=100,s=0,br=0;
do
{
if(i%64==0)
{
s+=i;
br++;
}
i++;
}
while (i<=999);
printf("\n Suma= %d", s);
printf("\n Brojeva= %d", br);
getche();
return 0;
}

6.10. m. 0 10.
. ,
. n
m.

77
I

#include <stdio.h>
#include<math.h>

main()
{
int m, n, k, br=0;
float x;
do
{
printf("\n m= ");
scanf("%d", &m);
}
while (m<=0 || m>=10);
printf ("\n Unesite cele brojeve [0 za kraj]:\n");
scanf("%d",&k);
do
{
n=log10 (k); /*Nadji prvu cifru.*/
/*Moze i ovako: n=k; while(n>9) n/=10;.....*/
n=k/pow(10,n); /*... n je prva cifra*/
if(n==m) br++;
scanf("%d",&k);
}
while(k!=0);
printf("\n %d brojeva ima prvu cifru %d ", br, m);
getche();
return 0;
}

78
I

7.1 BREAK

7.1. :
)
#include <stdio.h>

main()
{
int i;
for(i=1;i<=10;i++)
{
if(i==5) break;
printf(" i=%d \n",i); )
}
getche();
return 0;
}

) #include <stdio.h>

main()
{
int i, j;
for(i=1;i<=5;i++)
for(j=1;j<=10;j++)
{
if(j==3) break;
printf("i=%d j=%d\n",i,j);
}
getche();
return 0; )
}

79
I

7.2.
.

#include <stdio.h>

main()
{
int i;
while(1)
{
printf(" i= "); scanf("%d",&i);
if (i<0) break;
printf(" i*i= %d\n\n", i*i);
}
getche();
return 0;
}

7.3.
100 0 STOP .
#include <stdio.h>
#define STOP 0

main()
{
int i,x;
printf(" Unesite cele brojeve [100 njih ili 0 za kraj unosa]:\n\n");
for(i=0; i<=100; i++)
{
scanf("%d",&x);
if(x==STOP)
break;
printf("\n% d",x);
}
getche();
return 0;
}

80
I

7.4. ( ) 500,
3, 4, 5 7.
#include <stdio.h>

main()
{
int i;
for(i=1; i<=500; i++)
if(i%3==0 && i%4==0 && i%5==0 && i%7==0)
{
printf("%d\n", i);
break;
}
getche();
return 0;
}

n
1
7.5. n s = i
i =1
2
.

n ..
#include <stdio.h>

main()
{
int n, i;
float s;
while(1)
{
printf(" n= ");
scanf("%d", &n);
if(n <= 0) break;
s=0;
for(i=1; i<=n; i++)
s+=1./(i*i);
printf (" S= %.6f\n\n", s);
}
getche();
return 0;
}

7.6. n ,
.
1 n 1 n 2 2
s =
n i =1
ai d = ai si .
n i =1
.

81
I

#include <stdio.h>

main()
{
while(1)
{
double a, s, d;
int n,i;
printf("\n n= ");
scanf("%d", &n);
if(n <= 0) break;
printf(" Elementi: ");
s=0, d=0;
for(i=1; i<=n; i++)
{
scanf("%lf",&a);
s+=a;
d+=a*a;
}
s/=n;
d=sqrt(d/n-s*s);
printf(" s= %.4f\n", s);
printf(" d= %.4f\n", d);
}
getche();
return 0;
}

7.7. 1 100.
1 .
#include <stdio.h>

main()
{
int i,j,m;
float x;
for(i=1; i<=100; i=i+1)
{
x=i;
m=sqrt(x);
for(j=2; j<=m; j++)
if(i%j==0) break;
if(i==2 || i%j!=0)
printf(" %2d",i);
}
getche();
return 0;
}

82
I

7.2 CONTINUE

7.8. :
)
#include <stdio.h>

main()
{
int i;
for(i=1;i<=10;i++)
{
if(i==5) continue;
printf(" i=%d \n",i);
}
getche();
return 0;
} )

) #include <stdio.h>

main()
{
int i, j;
for(i=1;i<=4;i++)
for(j=1;j<=4;j++)
{
if(j==2) continue;
printf("i=%d j=%d\n",i,j);
}
getche();
return 0;
}
)

7.9. continue
.

#include <stdio.h>

main()
{
int i;
for(i=1;i<10; i++)
{
if((i%2)!=0) continue;
printf(" %d\n", i);
}
getche();
return 0;
}

83
I

7.10. :
)
#include <stdio.h>

main()
{
int i, x=0;
for(i=1; i<20; i++)
{
if(i%5==0) continue;
x++;
if(i==10) break;
printf("\n x=%d", x);
}
getche();
return 0;
}

) #include <stdio.h>

main()
{
int i,x=0;
for(i=1; i<20; i++)
{
if(i%8==0) continue;
x++;
if(i==8||i==12||i==16) break;
printf ("\n x=%d", x);
}
getche();
)
return 0;
}

7.11. 20 3.
#include <stdio.h>

main()
{
int i;
for(i=1; i<=20; i++)
{
if(i%3==0) continue;
printf(" %d\n", i);
}
getche();
return 0;
}

84
I

n
1
7.12. s = i
i =1
2
n.

n , n=0 .

#include <stdio.h>

main()
{
int n, i;
float s;
while(1)
{
printf ("\n n= ");
scanf("%d", &n);
if(n == 0) break;
if(n < 0) continue;
s=0;
for(i=1; i<=n; i++)
s+=1./(i*i);
printf (" s= %.6f\n", s);
}
getche();
return 0;
}

7.3 GOTO

7.13. , 5, 7 3
: #include <stdio.h>
main()
{
int opcija;
start: printf(" Birati opciju od 1 do 3: ");
scanf("%d", &opcija);
if(opcija<1 || opcija>3)
goto start;
else if(opcija==1)
goto Num1;
else if(opcija==2)
goto Num2;
else if(opcija==3)
goto Num3;
Num1: printf(" Izabrana je opcija A.\n");
goto End;
Num2: printf(" Izabrana je opcija B.\n");
goto End;
Num3: printf(" Izabrana je opcija C.\n");
goto End;
End:;
getche();
return 0;
}

85
I

7.14.
, .

#include <stdio.h>

main()
{
int i, n;
start: printf(" Unesite ceo broj od 0 do 10: ");
scanf("%d", &n);
if(n<0 || n>10)
goto start;
else if (n==0)
goto Loc0;
else
goto Loc1;
Loc0: printf("\n Izabran je broj 0 za KRAJ.\n\n");
goto End;
Loc1: for(i=0;i<n;i++)
printf("X");
printf("\n\n");
goto start;
End: ;
getche();
return 0;
}

86
I

7.15. goto .

#include <stdio.h>

main()
{
int i=1;
poc: printf(" %d", i);
i++;
if(i<=10)
goto poc;
getche();
return 0;
}

7.16. n .
#include <stdio.h>

main()
{
int n, a, p=1;
printf(" n= ");
scanf("%d",&n);
poc: a=n%10;
p=p*a;
n=n/10;
if(n!=0)
goto poc;
printf(" p= %d", p);
getche();
return 0;
}

7.17. . ,
28 : 2 2 7.
#include <stdio.h> else
{
main() f++;
{ goto poc;
int n, f=2; }
printf(" n= "); }
scanf("%d",&n); getche();
printf(" %d=1",n); return 0;
poc: if(n!=1) }
{
if(n%f==0)
{
printf("*%d",f);
n=n/f;
goto poc;
}

87
I

7.18. .
, ,
.

#include <stdio.h>

main()
{
float n, br=0, poz=0, neg=0, s=0, as;
poc: printf("\ Ucitaj broj: ");
scanf("%f",&n);
if(n!=0)
{
br++;
s=s+n;
if(n>0) poz++;
else neg++;
goto poc;
}
as=s/br;
printf("\n Ucitano: %.0f brojeva.", br);
printf("\n Pozitivnih: %.0f brojeva. ", poz);
printf("\n Negativnih: %.0f brojeva. ", neg);
printf("\n Aritmeticka sredina: %.3f", as);
getche();
return 0;
}

7.4 SWITCH ... CASE

7.19. 1 7 .
#include <stdio.h> case 5:
printf("\n petak");
main() break;
{ case 6:
int x; printf("\n subota");
printf(" n= "); break;
scanf("%d",&x); case 7:
switch(x) printf("\n nedelja");
{ break;
case 1: default:
printf("\n ponedeljak"); printf("\n GRESKA");
break; break;
case 2: }
printf("\n utorak"); getche();
break; return 0;
case 3: }
printf("\n sreda");
break;
case 4:
printf("\n cetvrtak");
break;

88
I

7.20. .

#include <stdio.h>

main()
{
char x;
printf(" Unesite slovo: ");

scanf("%c",&x);
switch (x)
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
case 'A':
case 'E':
case 'I':
case 'O':
case 'U':
printf(" %c je samoglasnik",x);
break;
default:
printf(" %c je suglasnik",x);
}
getche();
return 0;
}

7.21. :
#include <stdio.h>

main()
{
int a=6, b=4;
switch (a%b)
{
case 0:
a++;
b++;
case 1:
a++;
b++;
break;
case 2:
a--;
b--;
case 3:
a--;
b++;
break;
}
printf (" a=%d, b=%d", a, b);
getche();
return 0;
}
89
I

7.22. (+, -, *, /)
.
#include <stdio.h>

main()
{
float op1,op2;
char op;
printf(" Operator: ");
scanf ("%c", &op);
printf(" Operand1: ");
scanf ("%f", &op1);
printf(" Operand2: ");
scanf ("%f", &op2);
switch(op)
{
case '+':
printf("Vrednost: %.2f\n", op1 + op2);
break;
case '-':
printf("Vrednost: %.2f\n", op1 - op2);
break;
case '*':
printf("vrednost: %.2f\n", op1 * op2);
break;
case '/':
if (op2 == 0)
printf("Greska! Deljenje nulom!\n");
else
printf("\n Rezultat: %.2f\n", op1 / op2);
break;
default:
printf(" Greska! Pogresan operator\n");
}
getche();
return 0;
}

7.23. ,
, O = 2(a + b) , P = ab
d = a 2 + b 2 .
#include <stdio.h>
#include <math.h>

main()
{
int i;
float a, b, O, P, d;
printf("\n a= ");
scanf("%f", &a);
printf(" b= ");
scanf("%f", &b);
if(a>0 && b>0)
{
printf("\n\n Zelite da izracunate:");

90
I

printf("\n 1 - Obim\n 2 - Povrsinu\n 3 - duzinu dijagonale");


printf("\n Izaberite opciju: ");
scanf("%d",&i);
switch(i)
{
case 1:
O=2*(a+b);
printf("\n Obim= %.2f", O);
break;
case 2:
P=a*b;
printf("\n Povrsina= %.2f", P);
break;
case 3:
d=sqrt(a*a+b*b);
printf("\n Dijagonala= %.2f", d);
break;
default:
printf("Izabrali ste pogresan broj.");
break;
}
}
else printf ("GRESKA!!!");
getche();
return 0;
}

7.24.
. .
#include <stdio.h>

main()
{
int mesec, godina, BrDana;
printf(" Unesite godinu: ");
scanf("%d", &godina);
printf(" Unesite redni broj meseca u godini: ");
scanf("%d", &mesec);
switch(mesec)
{
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
BrDana=31;
break;
case 4: case 6: case 9: case 11:
BrDana=30;
break;
case 2:
BrDana=28+(godina%4==0 && godina%100!=0 || godina%400==0);
break;
default:
BrDana=0;
break;
}
if(BrDana!=0)
printf(" Mesec ima %d dana.\n", BrDana);
getche();
return 0;
}

91
I

7.25. .
.

#include <stdio.h>

main()
{
int dan, mesec, godina, d;
while (1)
{
printf(" Danasnji dan: ");
scanf("%d%d%d", &dan, &mesec, &godina);
if(dan==0 || mesec==0 || godina==0) break;
switch (mesec)
{
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
d=31;
break;
case 4: case 6: case 9: case 11:
d=30;
break;
case 2:
d=28+(godina%4==0 && godina%100!=0 || godina%400==0);
break;
}
if(dan<d) dan++;
else
{
dan=1;
if(mesec<12) mesec++;
else
{
mesec=1;
godina++;
}
}
printf(" Sutrasnji dan: %2.2d %2.2d %d\n\n", dan, mesec, godina);
}
getche();
return 0;
}

92
I

7.26. n n a {1, 2,3, 4} . 1


, 2 , 3 , 4 ,
. d.

#include <stdio.h>

main()
{
int i, n, a;
float x=0, y=0, d;
printf(" n= ");
scanf("%d", &n);
printf(" d= ");
scanf("%f", &d);
printf(" Unesite kod pravca kretanja");
printf("\n 1-sever, 2-istok, 3-jug, 4-zapad\n");
for(i=1;i<=n;i++)
{
printf (" Kod= ");
scanf ("%d", &a);
switch (a)
{
case 1:
y=y+d;
break;
case 2:
x=x+d;
break;
case 3:
y=y-d;
break;
case 4:
x=x-d;
break;
}
}
printf (" Polozaj: x= %2.2f y= %2.2f\n", x, y);
getche();
return 0;
}

93
I

8.1: <stdio.h>

getchar() ,
().
EOF (end of file)
. int.
MS-DOS
ctrl+Z.
putchar(c) ().
int.
EOF . int.
gets(s) ( \n)
() , s (
char[], char*). \n s \0.
,
, NULL,
.
puts(s) s ( char[], char*)
\0 (),
(\n) .
s \n, .
( int) - ,
EOF .
* gets(s) puts(s) .

8.2: <ctype.h>

isalnum(c) c ?
isalpha(c) c ?
islower(c) c ?
isupper(c) c ?
isdigit(c) c ?
isxdigit(c) c ?

94
I

isspace(c) c ?
isgraph(c) c , ?
isprint(c) c ( )?
ispunct(c) c ( )?
iscntrl(c) c ?
tolower(c) c , ,
.
toupper(c) c , ,
.
* logical, c int ( ).
, 1,
.

8.1. :

#include <stdio.h>

main()
{
putchar('\n');
putchar('a');
putchar('\n');
putchar(97); ( 2)
putchar('\n'); :
putchar('A'+ 10); ( 1)
putchar('\n');
putchar('a'+ 3);
getche();
return 0;
}


( 2)
:
Programski jezik C

8.2. :
) .
) EOF
.

) #include <stdio.h> ) #include <stdio.h>

main() main()
{ {
int c; int c;
c=getchar(); while(c!=EOF)
putchar(c); {
getche(); c=getchar();
return 0; putchar(c);
} }
getche();
return 0;
}

95
I

8.3. :
) (.) .
) EOF .

)
#include <stdio.h>

main()
{
int c, n=0;
c=getche();
while(c != '.')
{ )
:
c=getche(); Programski jezik C.
n++;
}
printf("\n Broj karaktera %d.\n", n);
getche();
return 0;
}

) #include <stdio.h>

main()
{
int c, n=0;
while((c=getchar()) != EOF)
n++;
printf("\n Broj karaktera: %d.\n",n);
getche(); )
return 0; :
} Programski jezik C.

8.4.
F.

: :
#include <stdio.h> #include <stdio.h>
#include <ctype.h>
main()
{ main()
int c, n=0; {
while((c=getchar()) != EOF) int c, n=0;
if(c>='0'&& c<='9') while((c=getchar()) != EOF)
n++; if(isdigit(c))
printf("\n Broj cifara: %d.\n", n); n++;
getche(); printf("\n Broj cifara: %d.\n",n);
return 0; getche();
} return 0;
}

96
I


:
Broj 1 i broj 156

8.5. (, ),
, F.

:
#include <stdio.h>

main()
{
int c, nk=0, nr=0, nb=0, ns=0;
while((c=getchar()) != EOF)
{
if ((c==' ') || (c=='\t') || (c=='\n')) nr++;
if (c>='0' && c<='9') nb++;
if ((c>='a' && c<='z') || (c>='A' && c<='Z')) ns++;
nk++;
}
printf(" Razmaci: %d\n", nr);
printf(" Cifre: %d\n", nb);
printf(" Slova: %d\n", ns);
printf(" Ukupno: %d\n",nk);
getche();
return 0;
}

:
#include <stdio.h>
#include <ctype.h>

main()
{
int c, nk=0, nr=0, nb=0, ns=0;
while((c=getchar()) != EOF)
{
if (isspace(c)) nr++;
if (isdigit(c)) nb++;
if (isalpha(c)) ns++;

nk++;
}
printf(" Razmaci: %d\n", nr);
printf(" Cifre: %d\n", nb);
printf(" Slova: %d\n", ns);
printf(" Ukupno: %d\n",nk);
getche();
return 0;
}

97
I

8.6. .
F.

#include <stdio.h>

main()
{
int c, sugl=0, samog=0;
while((c=getchar()) != EOF)
{
if((c>='a' && c<='z') || (c>='A' && c<='Z'))
if(c=='a' || c=='e' || c=='i' || c=='o' || c=='u'
|| c=='A' || c=='E' || c=='I' || c=='O' || c=='U')
samog++;
else
sugl++;;
}
printf("Samoglasnika: %d\n", samog);
printf("Suglasnika: %d\n", sugl);
getche();
return 0;
}
:
Programski jezik C

8.7. ,
. F.
:
#include <stdio.h>

main()
{
int c, veliko=0, malo=0, cifra=0;
while((c = getchar()) != EOF)
{
if(c >= 'A' && c <= 'Z') veliko++;
if(c >= 'a' && c <= 'z') malo++;
if(c >= '0' && c <= '9') cifra++;
} :
printf(" Velika: %d\n", veliko); 1 Programski jezik C 33
printf(" Mala: %d\n", malo);
printf(" Cifre: %d\n", cifra);
getche();
return 0;
}
:
#include <stdio.h>
#include <ctype.h>

main()
{
int c, veliko=0, malo=0, cifra=0;
while((c = getchar()) != EOF)
{
veliko += isupper(c) != 0;
malo += islower(c) != 0;
cifra += isdigit(c) != 0;
98
I

}
printf(" Velika: %d\n", veliko);
printf(" Mala: %d\n", malo);
printf(" Cifre: %d\n", cifra);
getche();
return 0;
}

8.8.
. F.
#include <stdio.h>

main()
{
int c, n=0, u=0;
float p;
while((c = getchar()) != EOF)
{
u++;
if(c=='A') n++;
}

p=(float)n/u*100;
:
printf("\n Ukupno znakova: %d", u); Slova A A A
printf("\n Ukupno slovo A: %d", n);
printf("\n U procentima: %.2f%\n", p);
getche();
return 0;
}

8.9. , : , ,
-. F.
#include <stdio.h>

main()
{
int c, razmak=0, n=0;
while((c=getchar())!=EOF)
switch(c)
{
case ' ':
razmak++;
break;
case '.':
case ',':
case ':':
case ';':
n++;
break; :
Razni znakovi: ; , .
default:
break;
}
printf("\nRazmaci: %d", razmak);
printf("\nOstali trazeni: %d", n);
getche();
return 0;
}

99
I

8.10. .
EOF.
#include <stdio.h>
#include <ctype.h>

main()
{
int c, n=0;
while((c=getchar()) != EOF)

{ :
if(isdigit(c)) break; Petak je 5-ti dan u sedmici.
n++;
}
printf("Broj znakova: %d\n", n);
getche();
return 0;
}

8.11. .
EOF.
#include <stdio.h>
#include <ctype.h>

main()
{
int c, n=0;
while((c=getchar()) != EOF)
{
if(isdigit(c)) continue;
:
n++; Ovo je broj 5, a ovo 33.
}
printf("Broj znakova koji nisu cifre: %d\n", n);
getche();
return 0;
}

8.12. ( ) .
F.
#include <stdio.h>

main()
{
int c;
int otv=0;
while((c=getchar()) != EOF)
{
switch(c)
{
case '(': :
otv++; Danas je petak ((osamnaesti).
break;

100
I

case ')':
otv--;
if (otv<0)
{
printf("Visak zatvorenih zagrada\n");
break;
}
}
}
if (otv==0)
printf("Zagrade su u redu\n");
else
printf("Visak otvorenih zagrada\n");
getche();
return 0;
}

8.13. .
F.
: :
#include <stdio.h>
#include <stdio.h>
main() #include <ctype.h>
{
int c; main()
while((c=getchar()) != EOF) {
{ int c;
if(c >= 'A' && c <= 'Z') while((c=getchar()) != EOF)
c = c -'A' + 'a'; putchar(tolower(c));
putchar(c); getche();
} return 0;
getche(); }
return 0;
}


:
Jezik C

101
I

8.14. .
F.

: :
#include <stdio.h> #include <stdio.h>
#include <ctype.h>
main()
{ main()
int c; {
while((c=getchar()) != EOF) int c;
{ while((c=getchar()) != EOF)
if(c >= 'a' && c <= 'z') putchar(toupper(c));
c = c -'a' + 'A'; getche();
putchar(c); return 0;
} }
getche();
return 0;
}


:
Jezik C

8.15. ,
. F.

#include <stdio.h>
#include <ctype.h>

main()
{
int c, prvi=0;
while((c=getchar()) != EOF)
{
if(isalpha(c))
{
if(prvi==0)
putchar(toupper(c));
else putchar(tolower(c));
}
else putchar(c);
prvi=1;
}
getche();
return 0;
}

102
I

8.16.
. / .
F.

#include <stdio.h>
#define NIJE_PRAZNO 'a'
#define PRAZNO ' '
#define HOR_TAB '\t'

main()
{
int c, predh_c=NIJE_PRAZNO;
while((c=getchar()) != EOF)
{
if(c==HOR_TAB)
c=PRAZNO;
if(c != PRAZNO || predh_c != PRAZNO)
putchar(c);
predh_c=c;
}
getche();
return 0;
}

8.17. ,
. F.
#include <stdio.h>
#define U_RECI 1
#define VAN_RECI 0

main()
{
int c, poz=VAN_RECI;
while((c=getchar()) != EOF)
{
if(c==' ' || c=='\n' || c=='\t')

{
if(poz==U_RECI)
{
putchar('\n');
poz=VAN_RECI;
}
}
else
{
poz=U_RECI;
putchar(c);
}
}
getche();
return 0;
}

103
I

8.18. , .
- ( ' ', '\n' '\t').

#include <stdio.h> case U_RECI:


#define U_RECI 1 switch(c)
#define VAN_RECI 0 {
case ' ':
main() case '\t':
{ case '\n':
int c, n=0, stanje=VAN_RECI; stanje=VAN_RECI;
while ((c=getchar()) != EOF) break;
{ default:
switch(stanje) break;
{ }
case VAN_RECI: break;
switch(c) }
{ }
case ' ': printf ("Broj reci: %d\n", n);
case '\t': getche();
case '\n': return 0;
break; }
default:
n++;
stanje=U_RECI;
break;
}
break;

104
I

9.1. ,
.

: ( ):
#include <stdio.h> #include <stdio.h>

/*Deklaracija i definicija funkcije*/ /*Deklaracija i definicija funkcije*/


int zbir(int a, int b) int zbir(int a, int b)
{ {
int rezultat; return (a+b);
rezultat=a+b; }
return rezultat;
} /*Glavni program*/
main()
/*Glavni program*/ {
main() /*Poziv funkcije*/
{ printf("\n%d\n", zbir(5,3));
int c; getche();
c=zbir(5,3); /*Poziv funkcije*/ return 0;
printf("\n%d\n", c); }
getche();
return 0;
}

9.2. , ,
.
x
z1 = x + y 2 , z 2 = x 3 z3 = ( x * y ) + ( 5 y ) , .
y
. .

105
I

#include <stdio.h> /*Funkcija kuba*/


float kub(float a)
/*Funkcija zbira*/ {
float zbir(float a, float b) return(a*a*a);
{ }
return(a+b);
} /*Glavni program*/
main()
/*Funkcija razlike*/ {
float razlika(float a, float b) float x, y, z1, z2, z3;
{ printf(" x= ");
return(a-b); scanf("%f", &x);
} printf(" y= ");
scanf("%f", &y);
/*Funkcija proizvoda*/ z1=zbir(x,kvadrat(y));
float proizvod(float a, float b) z2=razlika(kub(x),kolicnik(x,y));
{ z3=zbir(proizvod(x,y),razlika(5,y));
return(a*b); printf("\n z1=%.2f\n", z1);
} printf("\n z2=%.2f\n", z2);
printf("\n z3=%.2f\n", z3);
/*Funkcija kolicnika*/ getche();
float kolicnik(float a, float b) return 0;
{ }
if(b==0) return 0;
else return(a/b);
}

/*Funkcija kvadrata*/
float kvadrat(float a)
{
return(a*a);
}

9.3. ,
,
.
#include <stdio.h>

int max(int a, int b)


{
if(a==b) return 0;
else if(a>b) return a;
else return b;
}

main()
{
int a, b, c, d, m;
printf("Unesite cetiri broja:\n");
scanf("%d %d %d %d", &a, &b, &c, &d);
m=max(max(a,b),max(c,d));
if(m==0) printf("Zadati brojevi su isti.");
else printf("\nMaximum= %d\n", m);
getche();
return 0;
}

106
I

9.4. .

)
#include <stdio.h>

void fun1(int a)
{
scanf("%d", &a);
printf("\n a= %d\n", a);
}

main() a)
{
int x=0;
printf(" Unesite broj: "); ,
fun1(x); .
printf(" x= %d\n", x); .
getche(); .
return 0;
}

) )
#include <stdio.h> #include <stdio.h>

void fun2(int x) int fun3(int x)


{ {
x*=2; return ++x;
x++; }
}
main()
main() {
{ int x=3;
int x=3; printf(" x= %d\n", x);
fun2(x); printf(" f(x)= %d\n", fun3(x));
printf(" x= %d\n", x); getche();
getche(); return 0;
return 0; }
}

)
)

9.5.
r. ,
.
#include <stdio.h>
#define PI 3.14

double Povrsina(double r)
{
return(4*r*r*PI);
}

107
I

double Zapremina(double r)
{
return((4./3.)*r*r*r*PI);
}

void Ispis(double p, double v)


{
printf("\n Povrsina: %.2f", p);
printf("\n Zapremina: %.2f\n", v);
}

main()
{
double r, p, v;
printf(" r= ");
scanf("%lf", &r);
p=Povrsina(r);
v=Zapremina(r);
Ispis(p,v);
getche();
return 0;
}

9.6.
. :
a= ( xB xC ) ( yB yC ) b= ( xC xA ) ( yC y A ) c= ( x A xB ) ( y A y B )
2 2 2 2 2 2
, ,
a+b+c
S= , P = S ( S a )( S b )( S c ) . a, b c
2
.
#include <stdio.h>
#include <math.h>

double Stranica(double x1, double x2, double y1, double y2)


{
return(sqrt(pow(x1-x2,2)+pow(y1-y2,2)));
}

main()
{
double xA, yA, xB, yB, xC, yC, a, b, c, s, P;
printf("Koordinate temena trougla\n");
printf("- prvo teme <xA,yA>: ");
scanf("%lf%lf",&xA,&yA);
printf("- drugo teme <xB,yB>: ");
scanf("%lf%lf",&xB,&yB);
printf("- trece teme <xC,yC>: ");
scanf("%lf%lf",&xC,&yC);
a=Stranica(xB,xC,yB,yC);
b=Stranica(xC,xA,yC,yA);
c=Stranica(xA,xB,yA,yB);
s=(a+b+c)/2;
P=sqrt(s*(s-a)*(s-b)*(s-c));
printf("\nPovrsina trougla: %.2f\n", P);
getche();
return 0;
}

108
I

9.7. ,
. .
#include <stdio.h>

int ZbirKv(int a, int b)


{
int i, suma=0;
for(i=a; i<=b; i++)
suma+=i*i;
return suma;
}

int ZbirKvP(int a, int b)


{
int i, suma=0;
for(i=a; i<=b; i++)
{
if(i%2==0)
suma+=i*i;
}
return suma;
}

int ZbirKvN(int a, int b)


{
int i, suma=0;
for(i=a; i<=b; i++)
{
if(i%2 == 1)
suma += i*i;
}
return suma;
}

main()
{
int a, b;
printf(" Donja granica: "); scanf("%d", &a);
printf(" Gornja granica: "); scanf("%d", &b);
printf("\n Zbir kvadrata svih brojeva: %d", ZbirKv(a, b));
printf("\n Zbir kvadrata parnih brojeva: %d", ZbirKvP(a, b));
printf("\n Zbir kvadrata neparnih brojeva: %d", ZbirKvN(a, b));
getche();
return 0;
}

9.8. .
.

#include <stdio.h>
#include <math.h>

int Suma(int a)
{
int s=0;
while (a!=0)
{
109
I

s+=a%10;
a/=10;
}
return s;
}

main()
{
int i, d, g;
printf(" Donja granica= ");
scanf("%d", &d);
printf(" Gornja granica= ");
scanf("%d", &g);
for(i=d; i<=g; i++)
printf("\n%4d\t%3d", i, Suma(fabs(i)));
getche();
return 0;
}

9.9.
.
.
#include <stdio.h>

unsigned nzd (unsigned a, unsigned b)


{
unsigned c;
while(b != 0)
{
c=b;
b=a%b;
a=c;
}
return a;
}

unsigned nzs (unsigned a, unsigned b)


{
return a*b/nzd(a,b);
}

main()
{
unsigned a, b;
while(1)
{
printf ("\n a= "); scanf ("%u", &a);
printf (" b= "); scanf ("%u", &b);
if (a==0 || b==0) break;
printf (" nzd= %u", nzd(a,b));
printf ("\n nzs= %u", nzs(a,b));
printf ("\n\n");
}
getche();
return 0;
}

110
I

9.10. ,
n n!
Cn ,k = = , n k
k k !( n k ) !
.
#include <stdio.h>

long Fakt(int n)
{
long i, f=1;
for(i=1; i<=n; i++)
f *= i;
return f;
}

main()
{
int n, k, c;
printf(" n= ");
scanf("%d", &n);
printf(" k= ");
scanf("%d", &k);
c=Fakt(n)/(Fakt(k)*Fakt(n-k));
printf("\n c= %d", c);
getche();
return 0;
}

9.11. n S = 1! + 2! + 3! + ... + n!.


.
#include <stdio.h>

long Fakt(int n)
{
long i, f=1;
for(i=1; i<=n; i++)
f *= i;
return f;
}

main()
{
long n, s=0;
int i;
printf(" n= ");
scanf("%ld",&n);
for(i=1; i<=n; i++)
s+=Fakt(i);
printf("\n S= %ld\n", s);
getche();
return 0;
}

111
I

9.12. ( )
.
#include <stdio.h>

long Fakt(int n)
{
long i, f=1;
for(i=1; i<=n; i++)
f *= i;
return f;
}

main()
{
int a, b, c;
for(a=1; a<=9; a++)
for(b=0; b<=9; b++)
for(c=0; c<=9; c++)
{
if((a*100+b*10+c)==(Fakt(a)+Fakt(b)+Fakt(c)))
printf("\n %d", a*100+b*10+c);
}
getche();
return 0;
}

9.13. .
.

#include <stdio.h>

double Stepen(double x, int n)


{
int i, negative;
double s=1.0;
negative = n<0;
if(negative) n=-n;
for(i=0; i<n; i++)
s*=x;

if(negative) return(1/s);
else return(s);
}

main()
{
int n;
double x, s;
printf("\n Osnova: ");
scanf("%lf", &x);
printf("\n Stepen: ");
scanf("%d", &n);
s=Stepen(x,n);
printf("\n Rezultat= %.2f", s);
getche();
return 0;
}

112
I

9.14.
A p k
r= , A = (1 + k ) , ( ), k (, 6%
m

A 1
0.06), m . .
#include <stdio.h>

double Stepen(double x, int n)


{
int i;
double s=1.0;
for(i=0; i<n; i++)
s*=x;
return(s);
}

main()
{
int m;
double p, k, r, A;
printf("\n Iznos kredita: "); scanf("%lf", &p);
printf("\n Mesecna kamata: "); scanf("%lf", &k);
printf("\n Broj mesecnih rata: "); scanf("%d", &m);
A=Stepen(1+k,m);
r=(A*p*k)/(A-1);
printf("\n Mesecna rata= %.2f", r);
getche();
return 0;
}

9.15. 500.
.

#include <stdio.h>
-
int Prost(int broj)
,
{
int i; ,
for(i=2; i<broj; i++) , int
if(broj%i == 0) 1 , 0
return 0;
return 1; .
} int ()
0 1.
main()
{
int i;
for(i=1; i<=500; i++)
if(Prost(i) == 1)
printf("%d\t", i);
getche();
return 0;
}

113
I

9.16.
. (n) m,
1m<n m n . , NZD(m,n)
.

#include <stdio.h> int Ojler(int n)


{
int nzd (int a, int b) int br=0, m;
{ /*Prolazimo kroz sve prirodne brojeve m
int c; koji su manji od n, i za svaki koji je
while(b != 0) uzajamno prost sa n uvecavamo brojac*/
{ for(m = 1; m < n; m++)
c=b; if(nzd(n,m) == 1) br++;
b=a%b; /*Vracamo broj uzajamno prostih brojeva
sa brojem n*/
a=c;
return br;
}
}
return a;
}
main()
{
int n;
printf(" n= ");
scanf("%d", &n);
printf(" Euler(%d)= %d\n", n, Ojler(n));
getche();
return 0;

}

9.17. .
. ,
, ( 1,
0).

#include <stdio.h>
#include <math.h>

int SumaKubova(int n)
{
int suma=0 ;
for( ; n>0; n/=10)
suma += pow(n%10,3);
return suma;
}

114
I

int Amstrongov(int n)
{
if(n==SumaKubova(n))
return 1;
return 0;
}

main()
{
int i;
for(i=100; i<=999; i++)
if(Amstrongov(i))
printf("%d\t", i);
getche();
return 0;
}

9.18. .
. , ,
( 1, 0).
#include <stdio.h> main()
#include <math.h> {
int i;
int SumaCifara(int n) for(i=101; i<=200; i++)
{ if(Nivenov(i))
int suma=0 ; printf("%d\t", i);
for( ; n>0; n/=10) getche();
suma += n%10; return 0;
return suma; }
}

int Nivenov(int n)
{
if(n % SumaCifara(n) == 0)
return 1;
return 0;
}

9.19. C U0

t

R. uc ( t ) = U 0 1 e RC


ur ( t ) = U 0 uc ( t ) .
C , R U0
t 0 R*C R*C/10.

115
I

#include <stdio.h>
#include <math.h>

float R, C, U0;

float uc(float t)
{
return U0*(1-exp(-t/(R*C)));
}

float ur(float t)
{
return U0-uc(t);
}

main()
{
float t;
printf("\n R[kOhm]= ");
scanf("%f",&R);
printf("\n C[uF]= ");
scanf("%f",&C);
printf("\n U0[V]= ");
scanf("%f",&U0);
R*=1e3;
C*=1e-6;
printf("\n Vreme N a p o n n a ");
printf("\n [ms] kondenzatoru otporniku");
for(t=0; t<=R*C; t=t+R*C/10)
printf("\n%7.2f %9.3f %9.3f",t*1e3,uc(t),ur(t));
getche();
return 0;
}

sin ( x )
9.20. f1 ( x ) =
x
sin ( x )
2

f2 ( x ) = = ( f1 ( x ) ) . x 1 xmin
2

x
(xmin<1) x dx (dx <0.1).

#include <stdio.h>
#include <math.h>

float x, xmin, dx;

float f1(float x)
{
return sin(x)/x;
}

float f2(float x)
{
return f1(x)*f1(x);
}

main()
116
I

{
printf("\n xmin[xmin<1] = ");
scanf("%f",&xmin);
printf("\n dx[xkor<0.1] = ");
scanf("%f",&dx);
printf("\n x f1(x) f2(x)");
for(x=1; x>=xmin; x-=dx)
printf("\n%5.2f%9.5f%9.5f",x,f1(x),f2(x));
getche();
return 0;
}

9.21. :
y = f ( x ) f(x)
x1 x2
,
(
).
f ( xi ) + f ( xi + dx )
Pi = dx .
2
n
f ( x1 ) f ( x2 ) 0 x1 xi xi+1 x2 x
P = + + S dx
2 2
S y ( xi ) o xi x1+dx x2-dx.
f ( xi ) , i-
i+1- , f ( x2 ) f ( x2 ) .

y = a x sin ( b x ) 1 2. n
. a b , n .

#include <stdio.h>
#include <math.h>

float a, b;

float f(float x)
{
return(a*x*fabs(sin(b*x)));
}

main()
{
int n;
float x, x1, x2, dx, S, P;
printf(" Parametar a= "); scanf("%f",&a);
printf(" Parametar b= "); scanf("%f",&b);
printf(" Broj tacaka n= "); scanf("%d",&n);
printf(" Pocetak intervala x1= "); scanf("%f",&x1);
printf(" Kraj intervala x2= "); scanf("%f",&x2);
dx=(x2-x1)/n;
S=(f(x1)+f(x2))/2;

117
I

for(x=x1+dx; x<=x2-dx; x+=dx)


S+=f(x);
P=S*dx;
printf("\n Povrsina= %.4f",P);
getche();
return 0;
}

9.22. u ( t ) = e bt sin ( a t )
u
r ( u ) = r0 + ln 1 + .
10
a, b r0, t1 t2
t1 t2.
,
(u (t ))
2

f (t ) = t1 t2.
r (t )
#include <stdio.h>
#include <math.h>

float a, b, r0;

float u(float t)
{
return exp(-b*t)*sin(a*t);
}

float r(float t)
{
return r0+log(1+fabs(u(t)/10));
}

float f(float t)
{
return u(t)*u(t)/r(t);
}

main()
{
int n;
float t1, t2, t, dt, E;
printf(" Parametar a= "); scanf("%f",&a);
printf(" Parametar b= "); scanf("%f",&b);
printf(" Parametar r0= "); scanf("%f",&r0);
printf(" Vremenski interval [t1,t2]= "); scanf("%f%f",&t1,&t2);
printf(" Broj tacaka n= "); scanf("%d",&n);
dt=(t2-t1)/n;
E=f(t1)+f(t2);
for(t=t1+dt; t<=t2-dt; t+=dt)
E+=2*f(t);
E=2*E*dt;
printf("\n Energija= %.4f",E);
getche();
return 0;
}

118
I

9.23. x (n)

xi x1 x2 x3 x4
e x = i ! = 1 + 1! + 2! + 3! + 4! + ... , n
i =0
,
(
exp() ).
#include <stdio.h>
#include <math.h>

double Ekspon (double x, int n)


{
double ex=1, clan=1;
int i;
for(i=1; i<n; i++)
{
clan *= x/i;
ex += clan;
}
return ex;
}

main()
{
double x, ex, ext, apsgr;
int n;
printf (" x= ");
scanf ("%lf", &x);
printf (" n= ");
scanf ("%d", &n);
ex=Ekspon(x,n); /*Izracunata vrednost*/
ext=exp(x); /*Tacna vrednost*/
apsgr = fabs(ex-ext);
printf("\n Izracunato= %.4f", ex);
printf("\n Tacno= %.4f", ext);
printf("\n APSGR= %.4f", apsgr);
getche();
return 0;
}

n n n t n
9.24. S = + ... + ( 1)
k k + 1 k + 2 k +t
n
n, k t .
k
#include <stdio.h>

int Komb(int n, int m)


{
int i, p=1;
for(i=1; i<=m; i++)
p *= (n-i+1)/i;
return p;
}

119
I

main()
{
float s;
int n, k, i, t, znak=1;
printf (" n= ");
scanf ("%d", &n);
printf (" k= ");
scanf ("%d", &k);
printf (" t= ");
scanf ("%d", &t);
for(i=0; i<t; i++)
{
s += znak*Komb(n,k);
znak=-znak;
}
printf("\n S= %.2f", s);
getche();
return 0;
}

1 1 1
9.25. S = 1 + + ...
2!! 3!! 4!!
. :
n ( n 2 ) ... 3 n
dfakt ( n ) = n !! =
n ( n 2 ) ... 4 2 n

#include <stdio.h>

int DFakt(int n)
{
int p=1;
while(n>=2)
{
p=p*n;
n=n-2;
}
return p;
}

main()
{
int i=2, znak=1;
float s=1, clan=1, eps;
printf (" eps= ");
scanf ("%f", &eps);
printf("\n");
while(fabs(clan)>=eps)
{
clan=(float)znak/DFakt(i);
s=s+clan;
i++;
znak=-znak;
}
printf(" S= %.4f", s);
getche();
return 0;
}

120
I

9.26. b
ASCII 254. '' Da li zelite
novo crtanje?[D/N]:'' .

#include <stdio.h>

void Crtaj(int a,int b)


{
int i, j;
for(i=0; i<b; i++)
{
for(j=0; j<a; j++)
printf("%c",254);
printf("\n");
}
}

main()
{
int a, b, ch;
ch='D';
while(ch=='D')
{
printf(" a= ");
scanf("%d",&a);
printf(" b= ");
scanf("%d",&b);
Crtaj(a,b);
printf("\n\n Da li zelite novo crtanje?[D/N]: ");
ch=getchar();
ch=toupper(ch);
while(ch!='D'&& ch!='N')
{
ch=getchar();
ch=toupper(ch);
}
}
getche();
return 0;
}

9.27. .
.
6 2.

121
I

#include <stdio.h>
#define HLIN '-'
#define VLIN '|'
#define UGAO '+'
#define PRAZNO ' '

void Znakovi(int n, char c)


{
while(n>0)
{
n--;
putchar(c);
}
}

void Hokvir(int k)
{
putchar(UGAO);
Znakovi(k, HLIN);
putchar(UGAO);
putchar('\n');
}

void Vokvir(int k)
{
putchar(VLIN);
Znakovi(k, PRAZNO);
putchar(VLIN);
putchar('\n');
}

main()
{
int i, duzina, sirina;
do
{
printf(" Unesite duzinu okvira (od 1 do 20): ");
scanf("%d", &duzina);
}
while(duzina<1 || duzina>20);
do
{
printf(" Unesite sirinu okvira (od 1 do 20): ");
scanf("%d", &sirina);
}
while(sirina<1 || sirina>20);
Hokvir(duzina); /*Stampanje gornjeg dela okvira*/
for(i=0; i<sirina; i++)
Vokvir(duzina); /*Stampanje srednjeg dela okvira*/
Hokvir(duzina); /*Stampanje donjeg dela okvira*/
getche();
return 0;
}

122
I

9.28. ) .
. EOF.
) .
. EOF.

) #include <stdio.h> ) #include <stdio.h>

char UVeliko(char c) char UMalo(char c)


{ {
if ('a'<=c && c<='z') if ('A'<=c && c<='Z')
return c-'a'+'A'; return c-'A'+'a';
return c; return c;
} }

main() main()
{ {
int c; int c;
while((c=getchar()) != EOF) while((c=getchar()) != EOF)
putchar(UVeliko(c)); putchar(UMalo(c));
getche(); getche();
return 0; return 0;
} }

9.1

9.29. ,
n .
#include <stdio.h>

int Faktorijel(int n)
{
if(n == 1) return 1;
return n*Faktorijel(n-1);
}
main()
{
int n;
printf("n= ");
scanf("%d", &n);
printf("%d!= %d", n, Faktorijel(n));
getche();
return 0;
}

123
I

9.30. ,
.
#include <stdio.h>

int Stepen(int a, int k)


{
if(k==0)
return 1;
else
return a*Stepen(a,k-1);
}

main()
{
int a,k;
printf(" a= ");
scanf("%d", &a);
printf(" k= ");
scanf("%d", &k);
printf("\n %d^%d= %d", a, k, Stepen(a,k));
getche();
return 0;
}

9.31. n ,
n .
#include <stdio.h>

int Suma(int n)
{
if(n==0)
return 0;
else
return(n + Suma(n-1));
}

main()
{
int s,n;
printf(" n= ");
scanf("%d", &n);
s=Suma(n);
printf("\n s= %d\n",s);
getche();
return 0;
}

124
I

9.32. n ,
n.

#include <stdio.h>

void Stampaj(unsigned int n)


{
if(n == 0) return;
printf(" %d", n);
Stampaj(n-1);
}

main()
{
int n;
printf(" n= ");
scanf("%d",&n);
Stampaj(n);
getche();
return 0;
}

9.33.
. .
#include <stdio.h>

int NZD(int x, int y)


{
if(x%y == 0) return y;
return NZD(y, x%y);
}

main()
{
int n, m, t;
printf("\n Unesite dva cela broja: ");
scanf("%d %d",&n, &m);
if(n<m)
{
t=n;
n=m;
m=t;
}
printf("\n NZD(%d,%d) = %d\n", n, m,NZD(n,m));
getche();
return 0;
}

125
I

9.34. .
.

#include <stdio.h>
#include <stdlib.h>

int SaberiCifre(int x)
{
if(x<0) x=abs(x);
if(x<10) return x;
return(x%10 + SaberiCifre(x/10));
}

main()
{
int n;
printf("\n Unesite ceo broj: ");
scanf("%d",&n);
printf("\n Suma cifara broja %d je %d\n", n, SaberiCifre(n));
getche();
return 0;
}

9.35. n- ,
n. : f1=1, f2=1, fi=fi-1+fi-2, i=3, 4, 5, ...

#include <stdio.h>

int Fib(int n)
{
if((n==0)||(n==1))
return 1;
else
return(Fib(n-1)+Fib(n-2));
}

main()
{
int n;
printf(" n= ");
scanf("%d", &n);
printf(" Fib[%d]= %d", n, Fib(n-1));
getche();
return 0;
}

9.36.
.
n.
n=7 :

126
I

#include <stdio.h>

/*Rekurzivna funkcija za racunanje binomnog koeficijenta.*/


int BinKoefREK(int n, int k)
{
return (0<k && k<n) ? BinKoefREK(n-1, k-1)+BinKoefREK(n-1, k) : 1;
}

/*Iterativna funkcija za racunanje binomnog koeficijenta.*/


int BinKoefIT(int n, int k)
{
int i, j, b;
for(b=i=1, j=n; i<=k; b=b*j--/i++);
return b;
}

/*Glavni program.*/
main ()
{
int n, i, j, k;
printf("\n n= ");
scanf("%d", &n);
for(i=0; i<=n; i++)
{
for(j=0; j<n-i; j++)
printf (" ");
for(k=0; k<=i; k++)
printf ("%4d", BinKoefREK(i, k));
printf("\n");
}
getche();
return 0;
}

9.37. : , n ,
.
, , ,
.

, (n) .

#include <stdio.h>

void Prebaci(int n, int i, int j)


{
int k;
/*Odrediti pomocni stap k*/
switch(i+j)
{
case 3: k=3; break;
case 4: k=2; break;
case 5: k=1; break;
}
if(n==1)
printf(" Prebaceno sa %d na %d\n", i, j);
else
{
127
I

Prebaci(n-1,i,k);
Prebaci(1,i,j);
Prebaci(n-1,k,j);
}
return;
}

main()
{
int broj;
printf(" Unesite broj diskova: ");
scanf("%d", &broj);
Prebaci(broj, 1, 3);
getche();
return 0;
}

128
I

10

10.1

10.1. ) :
int a[15] = {1,2,3};
int b[] = {1,2,3};
) ?
) b
:
int [10];
int b [10] = {0};

) () a b . a 15
1, 2 3, . b 1, 2
3.

)
int a[17], b[3], i;
a[0]=1; a[1]=2; a[2]=3;
for(i=3;i<15;i++) a[i]=0;
b[0]=1; b[1]=2; b[2]=3;

) 10 ( ). b 10
.

10.2. :
#include <stdio.h>
#define MAX 10

main()
{
int i, n, niz[MAX];
printf(" n= ");
scanf("%d", &n);
for(i=0; i<n; i++)
{
printf(" %d. element niza: ", i+1);
129
I

scanf("%d", &niz[i]);
}
for(i=0; i<n; i++)
printf("\n %d. element niza: %d", i+1, niz[i]);
getche();
return 0;
}

10.3. :
#include <stdio.h>
#define MAX 5

main()
{
int i, j, niz[]={15,3,9,7,11};
printf("\nR.Br.\tIndeks\tVrednost\n");
for(i=0; i<MAX; i++)
printf("\n%d\t%d\t%d", i+1, i, niz[i]);
getche();
return 0;
}

10.4. n
.
#include <stdio.h>
#define MAX 100

main()
{
int niz[MAX], i,n;
printf(" n= ");
scanf("%d", &n);
printf(" Unesite %d elemenata: ",n);
for(i=0 ; i<n ; i++)
scanf("%d", &niz[i]);
printf("\n Uneti niz: ");
for(i=0 ; i<n ; i++)
printf(" %d", niz[i]);
getche();
return 0;
}

130
I

10.5. n .
#include <stdio.h>
#define MAX 100

main()
{
int niz[MAX];
int i,n;
printf(" n= ");
scanf("%d", &n);
printf(" Unesite %d elemenata: ",n);
for(i=0; i<n; i++)
scanf("%d", &niz[i]);
printf("\n Obrnuto: ");
for(i=n-1; i>=0; i--)
printf(" %d", niz[i]);
getche();
return 0;
}

10.6. :
) #include <stdio.h>
#define MAX 10

main()
{
int niz[MAX];
printf("\n Niz zauzima %d bajtova.", sizeof(niz));
getche();
return 0;
}

)
#include <stdio.h>

main()
{
int i, BrElem;
int niz[] = {1, 2, 3, 4, 5, 6};
BrElem = sizeof(niz)/sizeof(int);
for(i=0; i<BrElem; i++)
printf(" niz[%d]=%d\n",i, niz[i]);
getche();
return 0;
}

131
I

10.2

10.7. (
n) .

#include <stdio.h>
#define MAX 100

main()
{
int i, n, niz[MAX], suma=0;
printf(" Broj elemenata: ");
scanf("%d", &n);
printf(" Elementi niza: ");
for(i=0; i<n; i++)
{
scanf ("%d", &niz[i]);
suma+=niz[i];
}
printf(" SRV= %.2f\n", (float)suma/n);
getche();
return 0;
}

10.8. ( n)
3.
#include <stdio.h>
#define MAX 100

main()
{
int i, n, k=0, niz[MAX];
double suma=0;
printf(" Broj elemenata: ");
scanf("%d", &n);
printf(" Elementi niza: ");
for(i=0; i<n; i++)
{
scanf("%d", &niz[i]);
if(niz[i]%3 == 0)
{
suma+=niz[i];
k++;
}
}
printf(" SRV= %.3f\n", suma/k);
getche();
return 0;
}

132
I

10.9. ( n) :
) ;
) .

) #include <stdio.h>
#define MAX 100

main()
{
int i, n, niz[MAX], sumap=0, suman=0;
printf(" Broj elemenata: ");
scanf("%d", &n);
printf(" Elementi niza: ");
for(i=0; i<n; i++)
{
scanf("%d", &niz[i]);
if(niz[i]%2==0)
sumap += niz[i];
else
suman += niz[i];
}

)
#include <stdio.h>
#define MAX 100

main()
{
int i, n, niz[MAX], sumap=0, suman=0;
printf(" Broj elemenata: ");
scanf("%d", &n);
printf(" Elementi niza: ");
for(i=0; i<n; i++)
{
scanf("%d", &niz[i]);
if(i%2==0)
sumap += niz[i];
else
suman += niz[i];
}

10.10. , n, ,
n 1
A = ( A1 , A2 ,..., An ) B = ( B1 , B2 ,..., Bn ) s = Ai Bi
i=0
.

133
I

#include <stdio.h>
#define MAX 100

main()
{
int i, n;
double proizvod=0, niz1[MAX], niz2[MAX];
printf(" Broj elemenata: ");
scanf("%d", &n);
printf(" Elementi niza A: ");
for(i=0; i<n; i++)
scanf("%lf", &niz1[i]);
printf(" Elementi niza B: ");
for(i=0; i<n; i++)
scanf("%lf", &niz2[i]);
for(i=0; i<n; i++)
proizvod+=niz1[i]*niz2[i];
printf (" Skalarni proizvod= %.3f\n", proizvod);
getche();
return 0;
}

10.11. A = ( A1 , A2 ,..., An ) n
B = ( B1 , B2 ,..., Bm ) m C = ( A1 , A2 ,..., An , B1 , B2 ,..., Bm ) n+m.
.
#include <stdio.h>
#define MAX 100

main()
{
int i, n, m, nizA[MAX], nizB[MAX], nizC[MAX];
printf(" Broj elemenata niza A: ");
scanf("%d", &n);
printf(" Elementi niza A: ");
for(i=0; i<n; i++)
scanf("%d", &nizA[i]);
printf(" Broj elemenata niza B: ");
scanf("%d", &m);
printf(" Elementi niza B: ");
for(i=0; i<m; i++)
scanf("%d", &nizB[i]);
printf(" Elementi niza C: ");
for(i=0; i<(n+m); i++)
{
if (i<n) nizC[i]=nizA[i];
else nizC[i]=nizB[i-n];
printf("%d ",nizC[i]);
}
getche();
return 0;
}

134
I

10.12. n A = ( A1 , A2 ,..., An )
B = ( B1 , B2 ,..., Bn )
C = ( A1 + B1 , A2 + B2 ,..., An + Bn ) .
#include <stdio.h>
#define MAX 100

main()
{
int i, n, nizA[MAX], nizB[MAX], nizC[MAX];
printf(" Broj elemenata niza: ");
scanf("%d", &n);
printf(" Elementi niza A: ");
for(i=0; i<n; i++)
scanf("%d", &nizA[i]);
printf(" Elementi niza B: ");
for(i=0; i<n; i++)
scanf("%d", &nizB[i]);
printf(" Elementi niza C: ");
for(i=0; i<n; i++)
{
nizC[i]=nizA[i]+nizB[i];
printf("%d ",nizC[i]);
}
getche();
return 0;
}

10.13. (
(A )
3

5) Ci = i + 2 Ai Bi . .
3
#include <stdio.h>
#define MAX 5

main()
{
float nizA[MAX], nizB[MAX], nizC[MAX];
int i;
printf (" Elementi niza A: ");
for(i=0; i<MAX; i++)
scanf ("%f", &nizA[i]);
printf (" Elementi niza B: ");
for(i=0; i<MAX; i++)
scanf ("%f", &nizB[i]);
printf ("\n Elementi niza C: ");
for(i=0; i<MAX; i++)
{
nizC[i]=pow(nizA[i],3)/3+2*nizA[i]*nizB[i];
printf ("%.2f ", nizC[i]);
}
getche();
return 0;
}

135
I

10.14. (
5) : [0]+B[4],,A[4]+B[0]. .
#include <stdio.h>
#define MAX 5

main()
{
int nizA[MAX], nizB[MAX], nizC[MAX], i;
printf (" Elementi niza A: ");
for(i=0; i<MAX; i++)
scanf ("%d", &nizA[i]);
printf (" Elementi niza B: ");
for(i=0; i<MAX; i++)
scanf ("%d", &nizB[i]);
printf (" Elementi niza C: ");
for(i=0; i<MAX; i++)
{
nizC[i]=nizA[i]+nizB[MAX-1-i];
printf ("%d ", nizC[i]);
}
getche();
return 0;
}

10.15. A = ( A1 , A2 ,..., An ) n
B = ( B1 , B2 ,..., Bm ) m,
.
#include <stdio.h>
#define MAX 100

main()
{
int i, n, m, k=0, nizA[MAX], nizB[MAX], nizC[MAX];
printf(" Broj elemenata niza A: ");
scanf("%d", &n);
printf(" Elementi niza A: ");
for(i=0; i<n; i++)
scanf("%d", &nizA[i]);
printf(" Broj elemenata niza B: ");
scanf("%d", &m);
printf(" Elementi niza B: ");
for(i=0; i<m; i++)
scanf("%d", &nizB[i]);
printf("\n Elementi niza C: ");
for(i=0; i<n; i++)
if(nizA[i]%2==0)
136
I

{
nizC[k]=nizA[i];
k++;
}
for(i=0; i<m; i++)
if(nizB[i]%2==0)
{
nizC[k]=nizB[i];
k++;
}
for(i=0; i<k; i++)
printf("%d ",nizC[i]);
getche();
return 0;
}

10.16. n
i- i-
. i- i-
. .
#include <stdio.h>
#define MAX 100

main()
{
int i, n, nizA[MAX], nizB[MAX], nizC[MAX];
printf(" Broj elemenata niza: ");
scanf("%d", &n);
printf(" Elementi niza A: ");
for(i=0; i<n; i++)
scanf("%d", &nizA[i]);
printf(" Elementi niza B: ");
for(i=0; i<n; i++)
scanf("%d", &nizB[i]);
printf("\n Elementi niza C: ");
for(i=0; i<n; i++)
{
if (nizA[i]<nizB[i]) nizC[i]=nizA[i];
else if(nizA[i]>nizB[i]) nizC[i]=nizB[i];
else nizC[i]=0;
printf("%d ",nizC[i]);
}
getche();
return 0;
}

10.17. n
:
.
#include <stdio.h>
#define MAX 100

main()
{
int nizA[MAX], nizB[MAX], nizC[MAX];
int n, i, j=0 ,k=0;
printf(" Broj elemenata niza A: ");

137
I

scanf("%d", &n);
printf(" Elemneti A: ");
for(i=0; i<n; i++)
scanf ("%d", &nizA[i]);
for(i=0; i<n; i++)
{
if (nizA[i]<0)
{
nizB[j]=nizA[i];
j++;
}
else
{
nizC[k]=nizA[i];
k++;
}
}
printf("\n Elementi B: ");
for(i=0; i<j; i++)
printf ("%d ", nizB[i]);
printf("\n Elementi C: ");
for(i=0; i<k; i++)
printf ("%d ", nizC[i]);
getche();
return 0;
}

10.18. n
.
#include <stdio.h>
#define MAX 100

main()
{
float s=0, as, nizA[MAX], nizB[MAX];
int i, j=0, n;
printf(" Broj elemenata niza A: ");
scanf("%d", &n);
printf(" Elementi niza A: ");
for(i=0; i<n; i++)
{
scanf("%f", &nizA[i]);
s+=nizA[i];
}
as=s/n;
printf("\n Sredina= %.2f", as);
printf("\n Elementi niza B: ");
for(i=0; i<n; i++)
{
if (nizA[i]>as)
{
nizB[j]=nizA[i];
printf("%.2f ",nizB[j]);
j++;
}
}
getche();
return 0;
}

138
I

10.19. , n,
: 0=0, 1=0+1, 2=0+1+2, ...,
Bi=A0+A1+A2+...+Ai.
#include <stdio.h>
#define MAX 100

main()
{
int i, n, s=0, nizA[MAX], nizB[MAX];
printf(" Broj elemenata niza A: ");
scanf("%d", &n);
printf(" Elementi niza A: ");
for(i=0; i<n; i++)
{
scanf("%d", &nizA[i]);
s+=nizA[i];
nizB[i]=s;
}
printf("\n Elementi niza B: ");
for(i=0; i<n; i++)
printf("%d ",nizB[i]);
getche();
return 0;
}

10.3

10.20. :
#include <stdio.h>

void StampaNiz(int a[], int n)


{
int i;
for(i=0; i<n; i++)
printf("%d ",a[i]);
printf("\n");
printf("sizeof(a) - u okviru fje : %d\n", sizeof(a));
}

main()
{
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
printf("sizeof(a) - u okviru main : %d\n", sizeof(a));
StampaNiz(a, sizeof(a)/sizeof(int));
getche();
return 0;
}

139
I


.
(
),
'\0'.

10.21.
n 1
s = Ai Bi , n
i=0
.

#include <stdio.h>
#define MAX 100

double SkalPro(double a[], double b[], int n)


{
double zbir=0;
int i;
for(i=0;i<n;i++)
zbir+=a[i]*b[i];
return zbir;
}

main()
{
double nizA[MAX],nizB[MAX];
int i, n;
printf(" Broj elemenata niza: ");
scanf("%d",&n);
printf(" Elementi niza A: ");
for(i=0; i<n; i++)
scanf("%lf",&nizA[i]);
printf(" Elementi niza B: ");
for(i=0; i<n; i++)
scanf("%lf",&nizB[i]);
printf("\n A*B= %.2f", SkalPro(nizA,nizB,n));
getche();
return 0;
}

10.22.
. ,
.
#include <stdio.h>
#define MAX 100

int Razliciti(const int niz[], int n)


{
int i, j, brojac=0;
140
I

for(i=0; i<n; i++)


{
for(j=0; j<i && niz[j]!=niz[i]; j++);
if(j==i) brojac++;
}
return brojac;
}

main()
{
int niz[MAX], n, i;
printf(" Broj elemenata niza: ");

scanf("%d", &n);
printf(" Elementi niza: ");
for (i=0; i<n; i++)
scanf ("%d",&niz[i]);
printf ("\n Broj razl. elemenata je %d", Razliciti(niz,n));
getche();
return 0;
}

10.23.
: ( ),
( 5), ,

. .

#include <stdio.h>
#define MAX 100

/*Izracunavanje prosecne ocene*/


float Prosek(int x[], int n)
{
int i;
float suma =0;
for(i=0; i<n; i++)
suma+=x[i];
return(suma/n);
}

/*Izracunavanje proseka polozenih*/


float ProsekPolozenih(int x[], int n)
{
int i, j=0;
float suma=0;
for(i=0;i<n;i++)
if(x[i]>5)
{
suma+=x[i];
j++;
}
return(suma/j);
}

/*Izracunavanje broja polozenih na ispitu*/


int BrojPolozenih (int x[], int n)
{

141
I

int i, broj=0;
for(i=0; i<n; i++)
if(x[i]>5)
broj++;
return broj;
}

/*Izracunavanje broja nepolozenih na ispitu*/


int BrojNepolozenih (int x[], int n)
{
int i, broj=0;
for(i=0; i<n; i++)
if(x[i] == 5)
broj++;
return broj;
}

/*Izracunavanje broja studenata iznad proseka*/


int BrojNadprosecnih (int x[], int y[], int n, float m)
{
int i, j=0;
for(i=0; i<n; i++)
{
if(x[i] > m)
{
y[j]=i;
j++;
}
}
return j;
}

/*Glavni program*/
main()
{
int student[MAX], ocena[MAX];
int i, n;

printf(" Broj studenata: ");
scanf("%d",&n);
printf(" Ocene studenata [5 do 10]: \n");
for(i=0; i<n; i++)
{
printf(" Ocena studenta %d = ",i);
scanf("%d",&ocena[i]);
}
printf("\n Ukupno polozenih na ispitu: %d\n",
BrojPolozenih(ocena,n));
printf(" Ukupno nepolozenih na ispitu: %d\n",
BrojNepolozenih(ocena,n));
printf(" Prosek ocena na ispitu: %.2f\n", Prosek(ocena,n));
printf(" Prosek ocena polozenih na ispitu: %.2f\n",
ProsekPolozenih(ocena,n));
printf(" Broj studenata iznad proseka: %d\n",
BrojNadprosecnih(ocena, student, n, Prosek(ocena,n)));
getche();
return 0;
}

142
I

10.24. n
, .
: f1=1, f2=1, fi=fi-1+fi-2, i=3, 4, 5, ...

#include <stdio.h>
#define MAX 100

void Fibonaci(int niz[], int n)


{
int i;
for(i=0; i<n; i++)
if(i<2) niz[i]=1;
else niz[i]=niz[i-1]+niz[i-2];
}

void Prikazi(int niz[], int n)


{
int i;
for(i=0; i<n; i++)
printf("%d ", niz[i]);
}

main()
{
int niz[MAX], n;
printf(" Broj Fibonacijevih brojeva: ");
scanf("%d", &n);
printf("\n");
Fibonaci(niz, n);
Prikazi(niz, n);
getche();
return 0;
}

10.25.
n 1
s = A B , n
i=0
i i

.
#include <stdio.h>
#define MAX 100

float SkalPro (const float a[], const float b[], int n)


{
return (n>0) ? a[0]*b[0]+SkalPro(a+1,b+1,n-1) : 0;
}

main()
{
float nizA[MAX],nizB[MAX];
int i, n;
printf(" Broj elemenata niza: ");
scanf("%d",&n);
printf(" Elementi niza A: ");
for(i=0; i<n; i++)
scanf("%f",&nizA[i]);
printf(" Elementi niza B: ");
143
I

for(i=0; i<n; i++)


scanf("%f",&nizB[i]);
printf("\n A*B= %.2f", SkalPro(nizA,nizB,n));
getche();
return 0;
}

10.26. {1, 2, , n}.


n.

#include <stdio.h>
#define MAX 100

/*Funkcija koja ispisuje elemente niza*/


void IspisiNiz(int a[], int n)
{
int i;
for(i=1; i<=n; i++)
printf(" %d", a[i]);
printf("\n");
}

/*Funkcija koja proverava da li se x vec nalazi


u permutaciji na prethodnih 1...n mesta*/
int Koriscen(int a[], int n, int x)
{
int i;
for(i=1; i<=n; i++)
if(a[i]==x) return 1;
return 0;
}

/*Funkcija koja ispisuje sve permutacije od skupa {1,2,...,n}.


a[] - je niz u koji smesta permutacije,
m - oznacava da se na m-tu poziciju u permutaciji
smesta jedan od preostalih celih brojeva,
n - je velicina skupa koji se permutuje,
Funkciju pozivamo sa argumentom m=1 jer krecemo da
formiramo permutaciju od 1. pozicije.*/
void Permutacija(int a[], int m, int n)
{
int i;
/*Ako je pozicija na koju treba smestiti broj premasila
velicinu skupa, onda se svi brojevi vec nalaze u
permutaciji i ispisujemo permutaciju.*/
if(m>n) IspisiNiz(a,n);
for(i=1; i<=n; i++)
{
/*Ako se broj i nije do sada pojavio u permutaciji
od 1 do m-1 pozicije, onda ga stavljamo na poziciju m
i pozivamo funkciju da napravi permutaciju za jedan
vece duzine, tj. m+1. Inace nastavljamo dalje, trazeci
broj kojis e nije pojavio do sada u permutaciji.*/
if(! Koriscen(a,m-1,i))
{
a[m]=i;
Permutacija(a,m+1,n);
}
}
}

144
I

main()
{
int n, a[MAX];
printf("\n Unesite duzinu permutacije: ");
scanf("%d", &n);
if(n < 0 || n >= MAX)
{
printf("Duzina permutacije mora biti broj od 0 d %d!\n", MAX);
return 1;
}
printf(" Permutacije: \n");
Permutacija(a,1,n);
getche();
return 0;
}

10.4

10.27. , n,
, .
#include <stdio.h>
#define MAX 100

main()
{
double niz[MAX], max;
int n, i, imax=0;
printf(" Broj elemenata niza: ");
scanf("%d", &n);

printf (" Elementi niza: ");
for (i=0; i<n; i++)
scanf ("%lf", &niz[i]);
max=niz[0];
for(i=1; i<n; i++)
if(niz[i] > max)
{
max=niz[i];
imax=i;
}
printf ("\n MAX= %.2f", max);
printf ("\n Pozicija= %d", imax+1);
getche();
return 0;
}

145
I

10.28. , n,
, xmin xmax, xmax/2 xmin*2.

#include <stdio.h>
#define MAX 100

main()
{
int n, i;
float x[MAX], xmin, xmax;
printf(" Broj elemenata niza: ");
scanf("%d",&n);
printf(" Elementi niza: ");
for(i=0; i<n; i++)
scanf("%f",&x[i]);
xmin=x[0];
xmax=x[0];
for(i=1; i<n; i++)
{
if(x[i]<xmin) xmin=x[i];
if(x[i]>xmax) xmax=x[i];
}
printf("\n Elementi [xmin*2<x<xmax/2]: ");
for(i=0; i<n; i++)
if(x[i]<xmax/2 && x[i]>xmin*2) printf("\n %.2f ",x[i]);
getche();
return 0;
}

10.29. , n,
.
#include <stdio.h>
#define MAX 100

main()
{
int niz[MAX], i, n, min;
printf(" Broj elemenata niza: ");
scanf("%d", &n);
printf(" Elementi niza: ");
for(i=0; i<n; i++)
scanf ("%d",&niz[i]);
for(i=0; i<n; i++)
if(niz[i]%2==0)
{
min=niz[i];
break;
}
if(i==n) printf("\n Nema parnih brojeva!");
else
{
for(i=0; i<n; i++)
if(niz[i]%2==0 && niz[i]<min) min=niz[i];
printf("\n Najmanji parni element: %d", min);
}
getche();
return 0;
}

146
I

10.30. , n,

. 2.
#include <stdio.h>
#define MAX 100

main()
{
int niz[MAX], i, n, max;
printf(" Broj elemenata niza: ");
scanf("%d", &n);
printf(" Elementi niza: ");
for(i=0; i<n; i++)
scanf ("%d",&niz[i]);
max=niz[1];
printf("\n Parne pozicije: ");
for(i=0; i<n; i++)
if(i%2!=0 )
{
printf("%d ",niz[i]);
if(niz[i]>max) max=niz[i];
}
printf("\n MAX= %d", max);
getche();
return 0;
}

10.31.
. .
: f1=1, f2=1, fi=fi-1+fi-2, i=3, 4, 5, ...

#include <stdio.h>
#define MAX 100

main()
{
int i, j, n, pom=2, niz[MAX];
printf(" Broj elemenata niza: ");
scanf("%d", &n);
printf(" Elementi niza: ");
while(n>=3 && n<=MAX)
{
for(i=1; i<=n; i++)
{
scanf("%d", &j);
niz[i-1]=j;
}
for(i=2; i<n; i++)
{
if(niz[i]==(niz[i-1]+niz[i-2]))
pom++;
else
{
printf("\n Niz nije Fibonacijev!");
break;
}

147
I

}
if(pom==n)
printf("\n Niz jeste Fiboacijev!");
break;
}
getche();
return 0;
}

10.32. , n,
.
:
) ;
) .

) #include <stdio.h>
#define MAX 100

main()
{
int i, n, broj, nadjen=0, niz[MAX];
printf(" Broj elemenata niza: ");
scanf("%d", &n);
printf(" Elementi niza: ");
for(i=0; i<n; i++)
scanf("%d", &niz[i]);
printf(" Trazena vrednost: ");
scanf("%d", &broj);
for(i=1; i<n; i++)
if(niz[i] == broj)
{
nadjen=1;
printf ("\n Vrednost %d ima %d. element niza.", broj, i+1);
}
if(!nadjen)
printf ("\n Vrednost %d nije nadjena u nizu.", broj);
getche();
return 0;
}

)
#include <stdio.h>
#define MAX 100

/*Funkcija proverava da li se dati broj nalazi u datom nizu celih brojeva.


Funkcija vraca poziciju u nizu na kojoj broj pronadjen
odnosno -1 ukoliko trazenog broja nema.*/
int Trazi(int niz[], int n, int broj)
{
int i;
for(i=0; i<n; i++)
if(niz[i]==broj) return i;
return -1;
}
main()
{
int i, n, broj, niz[MAX];
printf(" Broj elemenata niza: ");
148
I

scanf("%d", &n);
printf(" Elementi niza: ");
for(i=0; i<n; i++)
scanf("%d", &niz[i]);
printf(" Trazena vrednost: ");
scanf("%d", &broj);
i=Trazi(niz, n, broj);
if(i==-1)
printf("\n Vrednost %d nije nadjena u nizu.", broj);
else
printf("\n Vrednost %d ima %d. element niza.", broj, i+1);
getche();
return 0;
}

10.33. , n,
.
. :
) ;
) ;
) .

:
a[0], a[1], , a[n-1] b. b
( ). , .
b , ,
. .

)
#include <stdio.h>
#define MAX 100

main()
{
int i, iSrednji, iMin=0, iMax;
int n, broj, nadjen=0, niz[MAX];
printf(" Broj elemenata niza: ");
scanf("%d", &n);
printf(" Elementi niza: ");
for(i=0; i<n; i++)
scanf("%d", &niz[i]);
printf(" Trazena vrednost: ");
scanf("%d", &broj);
iMax=n-1;
while(iMin<=iMax)
{
iSrednji = (iMin+iMax)/2;
if(broj==niz[iSrednji])
{
nadjen=1;
printf("\n Vrednost %d je %d. element.", broj, iSrednji+1);
break;
}
else if(broj<niz[iSrednji])
iMax=iSrednji-1;
else
iMin=iSrednji+1;

149
I

}
if(!nadjen)
printf ("\n Vrednost %d nije nadjena u nizu.", broj);
getche();
return 0;
}

)
#include <stdio.h>
#define MAX 100

/*Funkcija proverava da li se trazeni broj nalazi


unutar niza celih brojeva a.
Funkcija vraca poziciju na kojoj je element nadjen
odnosno -1 ako ga nema.*/
int Trazi(int niz[], int n, int broj)
{
/*Pretrazujemo interval [iMin, iMax]*/
int iMin=0, iMax=n-1;
/*Sve dok interval [iMin, iMax] nije prazan*/
while(iMax<=iMax)
{
/*Srednja pozicija intervala [iMin, iMax]*/
int iSrednji=(iMin+iMax)/2;
/* Ispitujemo odnos trazenog broja i srednjeg elementa*/
if(broj==niz[iSrednji])
return iSrednji; /*Element je pronadjen*/
else if(broj<niz[iSrednji])
iMax=iSrednji-1; /*Pretrazujemo interval [iMin,iSrednji-1]*/
else
iMin=iSrednji+1; /*Pretrazujemo interval [iSrednji+1,iMax]*/
}
return -1; /*Element je nadjen*/
}

main()
{
int i, n, broj, niz[MAX];
printf (" Broj elemenata niza: ");
scanf ("%d", &n);
printf (" Elementi niza: ");
for(i=0; i<n; i++)
scanf ("%d", &niz[i]);
printf (" Trazena vrednost: ");
scanf ("%d", &broj);
i=Trazi(niz, n, broj);
if(i==-1)
printf("\n Vrednost %d nije nadjena u nizu.", broj);
else
printf("\n Vrednost %d ima %d. element niza.", broj, i+1);
getche();
return 0;
}

150
I

)
#include <stdio.h>
#define MAX 100

/*Funkcija proverava da li se trazeni broj nalazi unutar niza celih brojeva a.


Funkcija vraca poziciju na kojoj je element nadjen odnosno -1 ako ga nema.*/
int Trazi(int niz[], int iMin, int iMax, int broj)
{
/*Ukoliko je interval prazan, elementa nema*/
if(iMin>iMax) return -1;
/*Srednja pozicija intervala [iMin, iMax]*/
int iSrednji=(iMin+iMax)/2;
/*Ispitujemo odnos trazenog broja i srednjeg elementa*/
if(broj==niz[iSrednji])
return iSrednji; /*Element je pronadjen*/
else if(broj<niz[iSrednji])
/*Pretrazujemo interval [iMin, iSrednji-1]*/
return Trazi(niz, iMin, iSrednji-1, broj);
else
/*Pretrazujemo interval [iSrednji+1, iMax] */
return Trazi(niz, iSrednji+1, iMax, broj);
return -1; /*Element je nadjen*/
}

main()
{
int i, n, broj, niz[MAX];
printf (" Broj elemenata niza: ");
scanf ("%d", &n);
printf (" Elementi niza: ");
for(i=0; i<n; i++)
scanf ("%d", &niz[i]);
printf (" Trazena vrednost: ");
scanf ("%d", &broj);
i=Trazi(niz, 0, n-1, broj);
if(i==-1)
printf("\n Vrednost %d nije nadjena u nizu.", broj);
else
printf("\n Vrednost %d ima %d. element niza.", broj, i+1);
getche();
return 0;
}

10.5

10.1:

[0] > [1] > ... > [i] > [i+1] > ... > [n-1]
[0] < [1] < ... < [i] < [i+1] < ... < [n-1]
[0] [1] ... [i] [i+1] ... [n-1]
[0] [1] ... [i] [i+1] ... [n-1]

151
I

10.34. n
.
#include <stdio.h>
#define MAX 100

main()
{
int a[MAX], i, n;
printf(" Broj elemenata niza: ");
scanf("%d", &n);
printf(" Elementi niza A: ");
for(i=0; i<n; i++)
scanf("%d",&a[i]);
printf("\n Elementi niza B: ");
for(i=n-1; i>=0; i--)
printf("%d ", a[i]);
getche();
return 0;
}

10.35. n
.

#include <stdio.h>
#define MAX 100

main()
{
int niz[MAX], i, n, pom;
printf(" Broj elemenata niza: ");
scanf("%d", &n);
printf(" Elementi niza: ");
for(i=0; i<n; i++)
scanf("%d",&niz[i]);
pom=niz[0];
for(i=0; i<n-1; i++)
niz[i]=niz[i+1];
niz[n-1]=pom;
printf("\n Novi niz: ");
for(i=0; i<n; i++)
printf("%d ", niz[i]);
getche();
return 0;
}

10.36. n
x .
#include <stdio.h>
#define MAX 100

void CitajNiz(int a[],int n)


{

152
I

int i;
for(i=0; i<n; i++)
scanf("%d",&a[i]);
}

void PisiNiz(int a[],int n)


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

void Rotiraj(int a[], int n)


{
int pom, i;
pom=a[0];
for(i=1; i<n; i++)
a[i-1]=a[i];
a[n-1]=pom;
}

main()
{
int i, x, n, a[MAX];
printf(" Broj elemenata niza: ");
scanf("%d",&n);
printf(" Elementi niza: ");
CitajNiz(a, n);
printf(" Broj mesta za rotaciju: ");
scanf("%d",&x);
for(i=0; i<x; i++)
Rotiraj(a, n);
printf("\n Rotirani niz za %d mesta: ", x);
PisiNiz(a, n);
getche();
return 0;
}

10.37. n
.
#include <stdio.h>
#define MAX 100

void CitajNiz(int a[],int n)


{
int i;
for(i=0; i<n; i++)
scanf("%d",&a[i]);
}

void PisiNiz(int a[],int n)


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

void Zameni(int a[], int n)


{
153
I

int i, pom;
for(i=0; i<n-1; i+=2)
{
pom=a[i];
a[i]=a[i+1];
a[i+1]=pom;
}
}

main()
{
int i, x, n, a[MAX];
printf(" Broj elemenata niza: ");
scanf("%d",&n);
printf(" Elementi niza: ");
CitajNiz(a, n);
Zameni(a, n);
printf("\n Novi niz: ");
PisiNiz(a, n);
getche();
return 0;
}

10.38. n
.
#include <stdio.h>
#define MAX 100

main()
{
int i, j, n, nadjeniIsti, a[MAX];
printf(" Broj elemenata niza: ");
scanf("%d", &n);
printf(" Elementi niza: ");
for(i=0; i<n; i++)
scanf ("%d", &a[i]);
printf("\n Novi niz: ");
for(i=0; i<n-1; i++)
{
nadjeniIsti=0;
for(j=i+1; j<n; j++)
if(a[i] == a[j])
{
nadjeniIsti=1;
break;
}
if(!nadjeniIsti)
printf ("%d ",a[i]);
}
printf ("%d ",a[n-1]);
getche();
return 0;
}

154
I

10.39. n
(Selection Sort). .
Selection Sort a[0],
a[1], a[2], , a[n-1] a[1], a[2], a[3], , a[n-1]
a[2];
.
#include <stdio.h>
#define MAX 100

main()
{
int i, j, n, pom, niz[MAX];
printf(" Broj elemenata niza: ");
scanf("%d", &n);
printf(" Elementi niza: ");
for(i=0; i<n; i++)
scanf ("%d", &niz[i]);
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(niz[i] > niz[j])
{
pom=niz[i];
niz[i]=niz[j];
niz[j]=pom;
}
printf(" Sortirani niz: ");
for(i=0; i<n; i++)
printf ("%d ",niz[i]);
getche();
return 0;
}

10.40. n
(Insert Sort). .
Insert Sort: k ,
(k+1)- k k+1
. k 0 n-2.

#include <stdio.h>
#define MAX 100

main()
{
int i, j, n, pom, niz[MAX];
printf(" Broj elemenata niza: ");
scanf("%d", &n);
printf(" Elementi niza: ");
for(i=0; i<n; i++)
scanf("%d", &niz[i]);
for(i=1; i<n; i++)
{
pom=niz[i];
for(j=i-1; j>=0; j--)
if (niz[j] > pom)
niz[j+1]=niz[j];
else break;
155
I

niz[j+1]=pom;
}
printf (" Sortirani niz: ");
for(i=0; i<n; i++)
printf ("%d ",niz[i]);
getche();
return 0;
}

10.41. n
(Bubble Sort). .
Bubble Sort: ,
. "", .
. [0],...,[n-2], .
n-1 .
,
.
#include <stdio.h>
#define MAX 100

main()
{
int i, j, n, pom, niz[MAX];
printf(" Broj elemenata niza: ");
scanf("%d", &n);
printf(" Elementi niza: ");
for(i=0; i<n; i++)
scanf("%d", &niz[i]);
for(i=n-1; i>0; i--)
for(j=0; j<i; j++)
if(niz[j] > niz[j+1])
{
pom=niz[j];
niz[j]=niz[j+1];
niz[j+1]=pom;
}
printf(" Sortirani niz: ");
for(i=0; i<n; i++)
printf("%d ",niz[i]);
getche();
return 0;
}

10.42.
. .
#include <stdio.h>
#define MAX 100

main()
{
int i, n, b, niz[MAX+1];
printf(" Broj elemenata niza: ");
scanf("%d", &n);
printf(" Elementi niza: ");
156
I

for(i=0; i<n; i++)


scanf("%d", &niz[i]);
printf(" Element koji treba umetnuti: ");
scanf("%d", &b);
for(i=n-1; i>=0 && niz[i]>b; i--)
niz[i+1]=niz[i];
niz[i+1]=b;
n++;
printf("\n Novi niz: ");
for(i=0; i<n; i++)
printf("%d ", niz[i]);
getche();
return 0;

}

10.43.
( ) .
#include <stdio.h> else
#define MAX 100 {
for(ic=0; ic<nc; ic++)
main() {
{ if(nizA[ia]<=nizB[ib])
int nizA[MAX], nizB[MAX], nizC[2*MAX]; {
int na, nb, nc, ia, ib, ic; nizC[ic]=nizA[ia];
printf(" Broj elemenata niza A: "); ia++;
scanf("%d", &na); }
printf(" Elemneti A: "); else
for(ia=0; ia<na; ia++) {
scanf ("%d", &nizA[ia]); nizC[ic]=nizB[ib];
printf(" Broj elemenata niza B: "); ib++;
scanf("%d", &nb); }
printf(" Elemneti B: "); }
for(ib=0; ib<nb; ib++) }
scanf("%d", &nizB[ib]); printf("\n Elementi niza C: ");
nc=na+nb; for(ic=0; ic<nc; ic++)
ia=0; printf("%d ", nizC[ic]);
ib=0; getche();
if(na==0) return 0;
{ }
for(ic=0; ic<nc; ic++)
nizC[ic]=nizB[ic];
}
else if (nb==0)
{
for(ic=0; ic<nc; ic++)
nizC[ic]=nizA[ic];
}

157
I

10.44.
, . ,
. .

#include <stdio.h>
#define MAX 100

void Sortiraj(int a[], int n)


{
int i, j, pom, min;
for(i=0; i<n-1; i++)
{
min=i;
for(j=i+1; j<n; j++)
if(a[j]<a[min])
min=j;
if(min!=i)
{
pom=a[i];
a[i]=a[min];
a[min]=pom;
}
}
}

main()
{
int a[MAX], i, j, n, indeks=-1, duzina=-1, brojac;
printf(" Broj elemenata niza: ");
scanf("%d", &n);
printf(" Elementi niza: ");
for(i=0; i<n; i++)
scanf("%d", &a[i]);
Sortiraj(a,n);
printf("\n Sortiran niz: ");
for(i=0; i<n; i++)
printf("%d ", a[i]);
for(i=0; i<n; i++)
{
brojac=1;
for(j=i+1; j<n && a[i]==a[j]; j++)
brojac++;
if(brojac > duzina)
{
duzina=brojac;
indeks=i;
}
}
printf("\n Najveci broj puta se pojavljuje broj %d i to %d puta.",
a[indeks], duzina);
getche();
return 0;
}

158
I

10.45.
. .
.
#include <stdio.h>
#define MAX 100

void Sortiraj(int a[], int n)


{
int i, j, pom, min;
for(i=0; i<n-1; i++)
{
min=i;
for(j=i+1; j<n; j++)
if(a[j]<a[min])
min=j;
if(min!=i)
{
pom=a[i];
a[i]=a[min];
a[min]=pom;
}
}
}
int BinarnaPretraga(int a[], int n, int x)
{
int s, l=0, d=n-1;
while(l<=d)
{
s=(l+d)/2;
if(a[s]==x) return s;
if(a[s]>x) d=s-1;
else l=s+1;
}
return -1;
}

main()
{
int a[MAX], n, i, zbir, drugi, nadjen =0;
printf(" Broj elemenata niza: ");
scanf("%d", &n);
printf(" Elementi niza: ");
for(i=0; i<n; i++) scanf("%d", &a[i]);
Sortiraj(a, n);
printf(" Vrednost zbir dva elementa: ");
scanf("%d", &zbir);
/*Uslov drugi>i stoji samo da bi se izbegla nepotreban ponavljanja u ispisu.*/
for(i=0; i< n; i++)
if((drugi=BinarnaPretraga(a, n, zbir-a[i])) != -1 && drugi>i)
{
printf("\n Trazeni zbir se moze formirati od elemenata: %d i %d",
a[i], a[drugi]);
nadjen++;
}
if(!nadjen) printf(" Trazeni zbir se ne moze dobiti!\n");
getche();
return 0;
}

159
I

11

11.1. , mxn.
.
#include <stdio.h>
#define MAX 100

main()
{
int i, j, m, n, mat[MAX][MAX];
printf(" Vrsta m= ");
scanf("%d", &m);
printf(" Kolona n= ");
scanf("%d", &n);
/*Citanje matrice sa tastature*/
for(i=0; i<m; i++)
for(j=0; j<n; j++)
{
printf(" element[%d][%d] = ",i,j);
scanf("%d", &mat[i][j]);
}
/*Prikaz matrice*/
printf("\n Uneta matrica:\n");
for(i=0; i<m; i++)
{
for(j=0; j<n; j++)
printf(" %d", mat[i][j]);
printf("\n");
}
getche();
return 0;
}

160
I

11.2. nxn
. .

#include <stdio.h>
#define MAX 100

main()
{
int i, j, n, s=0, mat[MAX][MAX];
printf(" n= ");
scanf("%d", &n);
printf(" Elementi:\n");
for(i=0; i<n; i++)
for(j=0; j<n; j++)
scanf("%d", &mat[i][j]);
for(i=0; i<n; i++)
for(j=0; j<n; j++)
s+=mat[i][j];
printf("\n suma= %d", s);
getche();
return 0;
}

11.3. mn,
. .
0 9.
#include <stdio.h>
#define MAX 100

main()
{
int i, j, m, n, s=0, nule=0, mat[MAX][MAX];
printf(" m= ");
scanf("%d",&m);
printf(" n= ");
scanf("%d", &n);
printf("\n Uneta matrica:\n");
for(i=0; i<m; i++)
for(j=0; j<n; j++)
scanf("%d",&mat[i][j]);
for(i=0; i<m; i++)
for(j=0; j<n; j++)
{
if(mat[i][j]%2==0) s+=mat[i][j];
if(mat[i][j]==0) nule++;
}
printf("\n Suma parnih elemenata: %d", s);
printf("\n Broj elemenata jednakih nuli: %d", nule);
getche();
return 0;
}

161
I

11.4. , a b, mn,
.
.
a11 a12 K a1n b11 b12 L b1n
a a22 K a2 n b21 b22 L b2 n
c = a + b = 21 + =
M M

am1 am 2 K amn bm1 bm 2 L bmn

a11 + b11 a12 + b12 K a1n + b1n c11 c12 L c1n


a + b a22 + b22 K a2 n + b2 n c21 c22 L c2 n
21 21 =
M M

am1 + bm1 am 2 + bm 2 K amn + bmn cm1 cm 2 L cmn

#include <stdio.h>
#define MAX 100

main()
{
int i, j, n, m, mat1[MAX][MAX], mat2[MAX][MAX];
printf(" m= ");
scanf("%d", &m);
printf(" n= ");
scanf("%d", &n);
printf("\n Elementi prve matrice: \n");
for(i=0; i<m; i++)
for(j=0; j<n; j++)
scanf("%d", &mat1[i][j]);
printf("\n Elementi druge matrice: \n");
for(i=0; i<m; i++)
for(j=0; j<n; j++)
scanf("%d", &mat2[i][j]);
printf("\n Zbir dve matrice:\n");
for(i=0; i<m; i++)
{
for(j=0; j<n; j++)
printf(" %d", mat1[i][j]+mat2[i][j]);
printf("\n");
}
getche();
return 0;
}

11.5. nxn,
, ,
. .
#include <stdio.h>
#define MAX 100

main()
{
int i, j, n, sgd=0, ssd=0, mat[MAX][MAX];
printf(" n= ");
scanf("%d", &n);

162
I

printf(" Elementi:\n");
for(i=0; i<n; i++)
for(j=0; j<n; j++)
{
printf(" element[%d][%d] = ", i, j);
scanf("%d", &mat[i][j]);
}
printf("\n Uneta matrica:\n");
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
printf(" %d",mat[i][j]);
printf("\n");
}
printf("\n Elementi glavne dijagonale: ");
for(i=0; i<n; i++)
{
printf("%d ",mat[i][i]);
sgd+=mat[i][i];
}
printf("\n Suma glavne dijagonale = %d", sgd);
printf("\n Elementi sporedne dijagonale: ");
for(i=0; i<n; i++)
{
printf("%d ",mat[i][n-i-1]);
ssd+=mat[i][n-i-1];
}
printf("\n Suma sporedne dijagonale = %d", ssd);
getche();
return 0;
}

163
I

11.6. nxn,
. .
#include <stdio.h>
#define MAX 100

main()
{
int i, j, n, s=0, mat[MAX][MAX];
printf(" n= ");
scanf("%d", &n);
for(i=0; i<n; i++)
for(j=0; j<n; j++)
{
printf(" element[%d][%d] = ", i, j);
scanf("%d", &mat[i][j]);
}
printf("\n Uneta matrica:\n");
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
printf(" %d", mat[i][j]);
printf("\n");
}
printf("\n Suma elememenata vrste:\n");
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
s+=mat[i][j];
printf(" %d", s);
}
getche();
return 0;
}

11.7. mxn,
.
.
#include <stdio.h>
#define MAX 100

main()
{
int i, j, n, m, vrsta, s=0, mat[MAX][MAX];
printf(" m= ");
scanf("%d", &m);
printf(" n= ");
scanf("%d", &n);
for(i=0; i<m; i++)
for(j=0; j<n; j++)
{
printf(" element[%d][%d] = ", i, j);
scanf("%d", &mat[i][j]);
}
printf("\n Uneta matrica:\n");
for(i=0; i<m; i++)
{
for(j=0; j<n; j++)
printf(" %d", mat[i][j]);
164
I

printf("\n");
}
printf("\n Redni broj vrste ciji zbir elemenata zelite: ");
scanf("%d",&vrsta);
for(j=0; j<n; j++)
s=s+mat[vrsta-1][j];
printf("\n Zbir elememenata %d. vrste: %d", vrsta, s);
getche();
return 0;
}

11.8. mxn,
:

#include <stdio.h>
#define MAX 100

main()
{
int i, j, m, n, a[MAX][MAX];
printf(" m= ");
scanf("%d", &m);
printf(" n= ");
scanf("%d", &n);
printf(" Matrica:\n");
for(i=0; i<m; i++)
for(j=0; j<n; j++)
scanf("%d", &a[i][j]);
165
I

printf("\n Elementi:\n");
for(j=0;j<n;j++)
{
if(j%2==0)
for(i=0; i<m; i++)
printf(" %d",a[i][j]);
else
for(i=m-1; i>=0; i--)
printf(" %d",a[i][j]);
}
getche();
return 0;
}

11.9. nxn,
( ) .
, ,
1. .

#include <stdio.h>
#define MAX 100

main()
{
int i, j, n;
float a[MAX][MAX], t;
printf(" n= ");
scanf("%d", &n);
printf(" Matrica:\n");
for(i=0; i<n; i++)
for(j=0; j<n; j++)
scanf("%f",&a[i][j]);
for(i=0; i<n; i++)
if(a[i][i]!=0)
{
t=a[i][i];
for(j=0; j<n; j++)
a[i][j]/=t;
}
else
{
for(j=0; j<n; j++)
a[i][j]=0;
a[i][i]=1;
}
printf("\n Nova matrica:\n");
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
printf(" %.2f",a[i][j]);
printf("\n");
}
getche();
return 0;
}

166
I

11.10. nxn,
,
2. .
.

#include <stdio.h>
#define MAX 100

main()
{
int i, j, n, x, a[MAX][MAX];
printf(" x= ");
scanf("%d",&x);
printf(" n= ");
scanf("%d", &n);
printf("\n Uneta matrica: \n");
for(i=0; i<n; i++)
for(j=0; j<n; j++)
scanf("%d",&a[i][j]);
for(i=0; i<n; i++)
for(j=0; j<n; j++)
{
if(i>j) a[i][j]+=x;
if(i<j) a[i][j]+=2*x;
}
printf("\n Nova matrica:\n");
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
printf(" %d",a[i][j]);
printf("\n");
}
getche();
return 0;
}

11.11. mxn,

.

#include <stdio.h>
#define MAX 100

main()
{
int i, j, n, m, k1, k2, pom, a[MAX][MAX];
printf(" m= ");
scanf("%d", &m);
printf(" n= ");
scanf("%d", &n);
for(i=0; i<m; i++)
for(j=0; j<n; j++)
{
printf(" element[%d][%d] = ", i, j);
scanf("%d", &a[i][j]);
}
printf("\n Zadata matrica:\n");
167
I

for(i=0; i<m; i++)


{
for(j=0; j<n; j++)
printf(" %d", a[i][j]);
printf("\n");
}
do
{
printf("\n Redni broj kolona za zamenu: ");
scanf("%d%d", &k1, &k2);
}
while(k1<1 || k1>n || k2<1 || k2>n);
for(i=0; i<n; i++)
{
pom=a[i][k1-1];
a[i][k1-1]=a[i][k2-1];
a[i][k2-1]=pom;
}
printf("\n Nova matrica:\n");
for(i=0; i<m; i++)
{
for(j=0; j<n; j++)
printf(" %d", a[i][j]);
printf("\n");
}
getche();
return 0;
}

168
I

11.12. nxn,
.
.
) ;
) , .
.

)
#include <stdio.h>
#define MAX 100

main()
{
int i, j, n, pom, mat[MAX][MAX];
printf(" n= ");
scanf("%d", &n);
printf("\n");
for(i=0; i<n; i++)
for(j=0; j<n; j++)
{
printf(" element[%d][%d] = ", i, j);
scanf("%d", &mat[i][j]);
}
printf("\n Zadata matrica: \n");
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
printf(" %d",mat[i][j]);
printf("\n");
}
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
{
pom=mat[i][j];
mat[i][j]=mat[j][i];
mat[j][i]=pom;
}
printf ("\n Transponovana matrica:\n");
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
printf(" %d",mat[i][j]);
printf("\n");
}
getche();
return 0;
}

)
#include <stdio.h>
#define MAX 100

void Citaj(int mat[MAX][MAX], int n)


{
int i, j;
for(i=0; i<n; i++)
for(j=0; j<n; j++)
{
printf(" element[%d][%d] = ", i, j);
scanf("%d", &mat[i][j]);
169
I

}
}

void Pisi(int mat[MAX][MAX], int n)


{
int i, j;
for (i=0; i<n; i++)
{
for(j=0; j<n; j++)
printf(" %d",mat[i][j]);
printf("\n");
}
}

void Transp(int mat[MAX][MAX], int n)


{
int i, j, pom;
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
{
pom=mat[i][j];
mat[i][j]=mat[j][i];
mat[j][i]=pom;
}
}

main()
{
int i, j, n, pom, mat[MAX][MAX];
printf(" n= ");
scanf("%d", &n);
printf("\n");
Citaj(mat,n);
printf("\n Zadata matrica: \n");
Pisi(mat,n);
Transp(mat,n);
printf ("\n Transponovana matrica:\n");
Pisi(mat,n);
getche();
return 0;
}

11.13. nxn,
.
, . .

#include <stdio.h>
#define MAX 100

main()
{
int i, j, n, a[MAX][MAX];
int maxv[MAX], minv[MAX], maxk[MAX], mink[MAX];
printf(" n= ");
scanf("%d", &n);
printf("\n");
for(i=0; i<n; i++)
for(j=0; j<n; j++)

170
I

{
printf(" element[%d][%d] = ", i, j);
scanf("%d", &a[i][j]);
}
printf("\n Zadata matrica: \n");
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
printf(" %d",a[i][j]);
printf("\n");
}
for(i=0; i<n; i++)
{
minv[i]=a[i][0];
maxv[i]=a[i][0];
mink[i]=a[0][i];
maxk[i]=a[0][i];
for(j=1; j<n; j++)
{
if(a[i][j]<minv[i]) minv[i]=a[i][j];
if(a[i][j]>maxv[i]) maxv[i]=a[i][j];
if(a[j][i]<mink[i]) mink[i]=a[j][i];
if(a[j][i]>maxk[i]) maxk[i]=a[j][i];
}
}
printf("\n Najveci u vrstama: ");
for(i=0; i<n; i++)
printf("%d ", maxv[i]);
printf("\n Najmanji u vrstama: ");
for(i=0; i<n; i++)
printf("%d ", minv[i]);
printf("\n Najveci u kolonama: ");
for(i=0; i<n; i++)
printf("%d ", maxk[i]);
printf("\n Najmanji u kolonama: ");
for(i=0; i<n; i++)
printf("%d ", mink[i]);
getche();
return 0;
}

11.14. , nxm, B
mxk, C .

a11 a12 K a1m b11 b12 L b1k


a a22 K a2 m b21 b22 L b2 k
c = a b = 21 =
M M

an1 an 2 K anm bm1 bm 2 L bmk

a11b11 + a12 b21 + K + a1m bm1 L a11b1k + a12 b2 k + K + a1m bmk c11 c12 L c1n
a b + a b + K + a b L a 21b1k + a 22 b2 k + K + a 2 m bmk c 21 c 22 L c 2 n
21 11 22 21 2 m m1
=
M M

a n1b11 + a n 2 b21 + K + a nm bm1 K a n1b1k + a n 2 b2 k + K + a nm bmk c m1 cm2 L c mn

171
I

#include <stdio.h>
#define MAX 100

void Citaj(int mat[MAX][MAX], int n, int m)


{
int i, j;
for(i=0; i<n; i++)
for(j=0; j<m; j++)
{
printf(" element[%d][%d] = ", i, j);
scanf("%d", &mat[i][j]);
}
}

void Pisi(int mat[MAX][MAX], int n, int m)


{
int i, j;
for (i=0; i<n; i++)
{
for(j=0; j<m; j++)
printf(" %3d",mat[i][j]);
printf("\n");
}
}

main()
{
int a[MAX][MAX], b[MAX][MAX];
int c[MAX][MAX], d[MAX][MAX];
int i, j, n, m, k, t;
printf(" Broj vrsta matrice A: ");
scanf("%d",&n);
printf(" Broj kolona matrice A: ");
scanf("%d",&m);
printf(" Broj kolona matrice B: ");
scanf("%d",&k);
printf("\n Matrica A:\n");
Citaj(a,n,m);
printf("\n Matrica B:\n");
Citaj(b,m,k);
for(i=0; i<n; i++)
for(j=0; j<k; j++)
{
c[i][j]=0;
for(t=0; t<m; t++)
c[i][j]=c[i][j]+a[i][t]*b[t][j];
}
printf("\n Matrica A:\n");
Pisi(a,n,m);
printf("\n Matrica B:\n");
Pisi(b,m,k);
printf("\n Matrica C:\n");
Pisi(c,n,k);
getche();
return 0;
}

172
I

11.15. A nxn,
.
#include <stdio.h>
#define MAX 100

main()
{
int i, j, n, k;
int a[40][40],b[40][40];
printf("\n n= ");
scanf("%d",&n);
printf("\n Matrice %dx%d\n", n,n);
for(i=0; i<n; i++)
for(j=0; j<n; j++)
scanf("%d",&a[i][j]);
for(i=0; i<n; i++)
for(j=0; j<n; j++)
{
b[i][j]=0;
for(k=0; k<n; k++)
b[i][j]+=a[i][k]*a[k][j];
}
printf("\n Matrica AxA:\n");
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
printf(" %4d ", b[i][j]);
printf("\n");
}
getche();
return 0;
}

11.16. A mxm n,
n- (n- ).

#include <stdio.h>
#define MAX 100

main()
{
int i, j, m, n, k, p;
int a[MAX][MAX], b[MAX][MAX], c[MAX][MAX];
printf("\n Stepen n= ");
scanf("%d",&n);
printf(" Dimanzija m= ");
scanf("%d",&m);
printf("\n Matrica %dx%d:\n", m,m);
for(i=0; i<m; i++)
for(j=0; j<m; j++)
{
scanf("%d",&a[i][j]);
b[i][j]=a[i][j];
}

173
I

/*Stepenovanje matrice mnozeci je sa samom sobom n-1 puta*/


for(p=1; p<n; p++)
{
for(i=0; i<m; i++)
for(j=0; j<m; j++)
{
c[i][j]=0;
for(k=0; k<m; k++)
c[i][j]+=a[i][k]*b[k][j];
}
/*Prenos matrice C u matricu B*/
for(i=0; i<m; i++)
for(j=0; j<m; j++)
b[i][j]=c[i][j];
}

/*Ispis matrice*/
printf("\n Rezultujuca matrica:\n");
for(i=0; i<m; i++)
{
for(j=0; j<m; j++)
printf("%6d ",c[i][j]);
printf("\n");
}
getche();
return 0;
}

11.17. A nxn ,
. .

#include <stdio.h>
#define MAX 100

main()
{
float a[MAX][MAX], z, xm;
int n, i, j, k, s=1;
printf("\n n= ");
scanf("%d",&n);
printf("\n Matrica %dx%d:\n",n,n);
for(i=0; i<n; i++)
for(j=0; j<n; j++)
scanf("%f",&a[i][j]);
/*Iteracija za svaku kolonu: svodjenje na nulu clanova ispod dijagonale*/
for(k=0; k<n-1; k++)
{
if(a[k][k]==0)
/*Potrebno je izvrsiti zamenu vrsti; nadji clan u k-toj koloni razlicit
od nule; ako ga nema, ispisi poruku*/
{
for(i=k+1; i<n-1 && a[i][k]==0; i++)
if(i==n-1 && a[i][k]==0)
{
printf("\n Matrica se ne moze svesti na gornju trouglastu.");
return 1;
}
/*Zameniti i-tu i k-tu vrstu*/

174
I

for(j=k; j<n; j++)


{
z=a[k][j];
a[k][j]=a[j][k];
a[j][k]=z;
}
s=-s;
}
/*Svodjenje na nulu clanova ispod dijagonale */
for(i=k+1; i<n; i++)
{
xm=a[i][k]/a[k][k];
for(j=k; j<n; j++)
a[i][j]-=xm*a[k][j];
}
}
if(a[n][n]==0)
{
printf("\n Matrica se ne moze svesti na gornju trouglastu.");
return 1;
}
a[n][n]=a[n][n]*s; /*Postavi ispravni predznak*/

/*Ispis rezultata*/
printf("\n Gornja trouglasta matrica:\n");
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
printf("%7.2f",a[i][j]);
printf("\n");
}
getche();
return 0;
}

k.

(k 0 n-2) .
,
(k-)
. ,
.

. (j k n-1)
. k (
), .
.

175
I

11.18. mxn,
.
.

#include <stdio.h>
#define MAX 100

main()
{
int mat[MAX][MAX], s[MAX], p;
int m, n, i, j, min;
printf(" m= ");
scanf("%d", &m);
printf(" n= ");
scanf("%d", &n);
for(i=0; i<m; i++)
for(j=0; j<n; j++)
{
printf(" element[%d][%d] = ", i, j);
scanf("%d", &mat[i][j]);
}

/*Ispisivanje zadate matrice*/


printf("\n Zadata matrica: \n");
for(i=0; i<m; i++)
{
for(j=0; j<n; j++)
printf(" %d",mat[i][j]);
printf("\n");
}

/*Racunanje zbirova elemenata po kolonama*/
for(j=0; j<n; j++)
for(s[j]=i=0; i<m; i++)
s[j]+=mat[i][j];

/*Uredjivanje kolona po velicinama zbirova*/


for(i=0; i<n-1; i++)
{
/*razenje najmanjeg zbira*/
for(min=i, j=i+1; j<n; j++)
if(s[j]<s[min]) min=j;
if(min != i)
{
p=s[i];
s[i]=s[min];
s[min]=p;
/*Zamena kolona*/
for(j=0; j<n; j++)
{
p=mat[j][i];
mat[j][i]=mat[j][min];
mat[j][min]=p;
}
}
}

/*Ispisivanje uredjene matrice*/


printf("\n Uredjena matrica:\n");
for(i=0; i<m; i++)

176
I

{
for(j=0; j<n; j++)
printf(" %d", mat[i][j]);
printf("\n");
}
printf("\n Suma po kolonama:\n");
for(j=0; j<n; j++)
printf("% d", s[j]);
getche();
return 0;
}

177

[1] Brian W. Kernighan, Dennis M. Ritchie: The C Programming Language, New Jersey, 1988.

[2] Laslo Kraus: Programski jezik C sa reenim zadacima, Akademska misao, Beograd, 2006.

[3] Laslo Kraus: Reeni zadaci iz programskog jezika C, Akademska misao, Beograd, 2005.

[4] Ivo Mateljan: Programiranje C jezikom, Split, 2005/2006.

[5] Jozo J. Dujmovi: Programski jezici i metode programiranja, Nauna knjiga, Beograd,
1990.

[6] B. S. Gottfired: Theory and Problems of Programming with C, Schaums outline series,
McGraw-Hill, 1996.

[7] Clovis Tondo, Scott Gimpel: Programski jezik C reenja zadataka, CET, Beograd, 2004.

[8] A.Hansen: Programiranje na jeziku C potpuni vodi za programski jezik C,


Mikroknjiga, Beograd, 2000.

[9] Igor urovi, Slobodan ukanovi, Vesna Popovi: Programski jezik C sa zbirkom
rijeenih zadataka, ETF Podogorica, Podgorica, 2006.

[10] Milan abarkapa: C osnovi programiranja, Krug, Beograd, 1996.

[11] Milan abarapa, Stanka Matkovi: C/C++ zbirka zadataka, Krug, Beograd, 2003.

[12] Milan abarkapa, Nevenka Spalevi: Metodika zbirka zadataka iz programiranja, Sova,
Novi Beograd, 1997.

[13] .., .., .., ..:


, , , 1988.

[14] .., ., .., , ,


, 1988.
Osnovi programiranja
Programski jezik C
Zadaci sa vezbi

Milena Vujosevic - Janicic 2005/2006


2

2
Sadrzaj

1 Programski jezik C 5
1.1 Zdravo svete! . . . . . . . . . . . . . . . . . . . . . . 5
1.2 Imena promenljivih . . . . . . . . . . . . . . . . . . . 6
1.3 Deklaracije . . . . . . . . . . . . . . . . . . . . . . . 6
1.4 Tipovi i velicina podataka . . . . . . . . . . . . . . . 6
1.5 Funkcije printf i scanf . . . . . . . . . . . . . . . . . . 7
1.6 Aritmeticki operatori . . . . . . . . . . . . . . . . . . 9
1.7 Operatori i izrazi dodeljivanja vrednosti . . . . . . . 11
1.8 Inkrementacija i dekrementacija . . . . . . . . . . . . 12
1.9 Relacioni i logicki operatori . . . . . . . . . . . . . . 13
1.10 Kontrola toka if, while, do - while, for . . . . . . . 14
1.10.1 if . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.10.2 Else-if . . . . . . . . . . . . . . . . . . . . . . 15
1.10.3 while . . . . . . . . . . . . . . . . . . . . . . . 17
1.10.4 do-while . . . . . . . . . . . . . . . . . . . . . 17
1.10.5 for . . . . . . . . . . . . . . . . . . . . . . . . 17
1.11 Switch . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.12 Uslovni izraz . . . . . . . . . . . . . . . . . . . . . . . 19
1.13 Simbolicke konstante . . . . . . . . . . . . . . . . . . 20
1.14 Enumeracija . . . . . . . . . . . . . . . . . . . . . . . 21
1.15 Funkcije . . . . . . . . . . . . . . . . . . . . . . . . . 22
1.16 Nizovi . . . . . . . . . . . . . . . . . . . . . . . . . . 25
1.17 Konstante . . . . . . . . . . . . . . . . . . . . . . . . 27
1.18 Konverzija . . . . . . . . . . . . . . . . . . . . . . . . 28
1.18.1 Automatska konverzija . . . . . . . . . . . . . 28
1.18.2 Eksplicitna konverzija . . . . . . . . . . . . . 28
1.18.3 Funkcije koje vrse konverziju . . . . . . . . . . 29
1.19 Operator sizeof() . . . . . . . . . . . . . . . . . . . 30
1.20 Znakovni ulaz i izlaz . . . . . . . . . . . . . . . . . . 31
1.21 Nizovi . . . . . . . . . . . . . . . . . . . . . . . . . . 36
1.22 Dvostruka for petlja . . . . . . . . . . . . . . . . . . 39
1.23 Formiranje HTML dokumenta . . . . . . . . . . . . . 40

3
4 SADRZAJ

1.24 Funkcije prenos parametara po vrednosti . . . . . 42


1.25 Break i continue . . . . . . . . . . . . . . . . . . . . . 45
1.26 Rad sa niskama karaktera . . . . . . . . . . . . . . . 45
1.27 Makroi . . . . . . . . . . . . . . . . . . . . . . . . . . 50
1.28 Bitski operatori . . . . . . . . . . . . . . . . . . . . . 53
1.29 Linearna i binarna pretraga . . . . . . . . . . . . . . 61
1.30 Razni zadaci . . . . . . . . . . . . . . . . . . . . . . . 63

4
Glava 1

Programski jezik C

1.1 Zdravo svete!


Primer 1.1.1 Program stampa poruku hello, world.
#include <stdio.h>

main()
/*iskazi f-je main su zatvoreni u zagrade */
{
/*poziv f-je printf da odstampa poruku*/
printf("hello, world\n");
}
Primer 1.1.2 Program stampa poruku hello, world
#include <stdio.h>

main()
{
printf("hello, ");
printf("world");
printf("\n");
}
Specijalni znaci:
\n novi red
\t tabulator
\\ kosa crta
\" navodnici
\a zvuk
\ jednstruki navodnik

5
6 Milena VujosevicJanicic

1.2 Imena promenljivih


Postoje ogranicenja: u imenu se mogu pojaviti slova i cifre, potcrta
se smatra slovom.
Velika i mala slova se razlikuju.
int x, X; /*To su dve razlicite promenljive!!!*/
Kljucne reci kao sto su if, else, for, while, se ne mogu koristiti za
imena promenljivih.

1.3 Deklaracije
Da bi se promenljiva mogla upotrebljavati ona se mora na pocetku
programa deklarisati. Prilikom deklaracije moze se izvrsiti i pocetna
inicijalizacija.

int broj; /*Deklaracija celog broja*/


int vrednost=5; /*Deklaracija i inicijalizacija celog broja*/

Kvalifikator const moze biti dodeljen deklaraciji bilo koje promenljive


da bi oznacio da se ona nece menjati
const double e=2.71828182845905

1.4 Tipovi i velicina podataka


Osnovni tipovi podataka:
int ceo broj
char znak, jedan bajt
float realan broj
double realan broj dvostruke tacnosti

char jedan bajt, sadrzi jedan znak


int celobrojna vrednost,2 ili 4 bajta
float realan broj, jednostruka tacnost
double dvostruka tacnost

Postoje kvalifikatori koje pridruzujemo osnovnim tipovima short(16)


i long(32):
short int kratak_broj;
long int dugacak_broj;
short kratak;
long dugacak;

6
1.5 Funkcije printf i scanf 7

Vazi

broj bajtova(short) <= broj bajtova(int) <= broj bajtova(long)

Postoje kvalifikatori signed i unsigned koji se odnose na oznacene


i neoznacene cele brojeve. Npr.
signed char: -128 do 127
dok je
unsigned char: od 0 do 255.
Float, double i long double.

Primer 1.4.1 Uvo enje promenljivih u program.


#include <stdio.h>

main()
{
/*deklaracija vise promenljivih
istog tipa */
int rez,pom1,pom2;
pom1=20;
pom2=15;
rez=pom1-pom2;

/*ispisivanje rezultata*/
printf("Rezultat je %d-%d=%d\n",pom1,pom2,rez);
}
Izlaz iz programa:
Rezultat je 20-15=5

Iskaz dodele:
pom1=20;
pom2=15;
Individualni iskazi se zavrsavaju sa ;

1.5 Funkcije printf i scanf


printf("%d\t%d\n", broj1, broj2);
uvek je prvi argument izmedju " "
%d ceo broj
\t tab izmedju
\n novi red
Svaka % konstrukcija je u paru sa argumentom koji sledi.

7
8 Milena VujosevicJanicic

Primer 1.5.1
#include <stdio.h>
main()
{
printf("Slova:\n%3c\n%5c\n", z , Z);
}
Izlaz iz programa:
Slova:
z
Z
%c je za stampanje karaktera
%3c je za stampanje karaktera na tri pozicije
Isto tako smo mogli i %3d za stampanje broja na tri pozicije ili %6d
za stampanje broja na 6 pozicija.
Pravila:
%d stampaj kao ceo broj
%6d stampaj kao ceo broj sirok najvise 6 znakova
%f stampaj kao realan broj
%6f stampaj kao realan broj sirok najvise 6 znakova
%.2f stampaj kao realan broj sa dve decimale
%6.2f stampaj kao realan broj sirok najvise 6 znakova a od toga 2
iza decimalne tacke
%c karakter
%s string
%x heksadecimalni broj
%% je procenat

Primer 1.5.2 Prikazuje unos celog broja koristeci scanf("%d", &x)


#include <stdio.h>

main()
{
int x;
printf("Unesi ceo broj : ");

/* Obratiti paznju na znak &


(operator uzimanja adrese)
pre imena promenljive u funkciji
scanf */
scanf("%d",&x);

8
1.6 Aritmeticki operatori 9

/* U funkciji printf nije


potrebno stavljati & */
printf("Uneli ste broj %d\n", x);
}

Primer 1.5.3 Program sabira dva uneta cela broja


#include <stdio.h>

main()
{
int a, b, c;
printf("Unesi prvi broj : ");
scanf("%d", &a);
printf("Unesi drugi broj : ");
scanf("%d", &b);
c = a + b;
printf("%d + %d = %d\n", a, b, c);
}
Ulaz:
Unesi prvi broj : 2 <enter>
Unesi drugi broj : 3 <enter>
Izlaz:
2 + 3 = 5

1.6 Aritmeticki operatori


+ - * /
% (samo za celobrojne vrednosti)
unarno + i -

Asocijativnost sleva na desno, prioritet kao u matematici.

Primer 1.6.1 Program ilustruje neke od aritmetickih operacija.


#include <stdio.h>
main()
{
int a, b;
printf("Unesi prvi broj : ");
scanf("%d",&a);

printf("Unesi drugi broj : ");

9
10 Milena VujosevicJanicic

scanf("%d",&b);

/* Kada se saberu dva cela broja, rezultat je ceo broj*/


printf("Zbir a+b je : %d\n",a+b);
/* Kada se oduzmu dva cela broja, rezultat je ceo broj*/
printf("Razlika a-b je : %d\n",a-b);
/* Kada se pomnoze dva cela broja, rezultat je ceo broj*/
printf("Proizvod a*b je : %d\n",a*b);
/* Kada se podele dva cela broja, rezultat je ceo broj!!!*/
printf("Celobrojni kolicnik a/b je : %d\n", a/b);
/* Rezultat je ceo broj, bez obzira sto ga ispisujemo kao realan*/
printf("Pogresan pokusaj racunanja realnog kolicnika a/b je : %f\n", a/b)
/* Eksplicitna konverzija, a i b pretvaramo u relane brojeve kako
bi deljenje bilo realno*/
printf("Realni kolicnik a/b je : %f\n", (float)a/(float)b);
/* Ostatak pri deljenju se moze izvrsiti samo nad celim brojevima*/
printf("Ostatak pri deljenju a/b je : %d\n", a%b);
}

Ulaz:
Unesi prvi broj : 2 <enter>
Unesi drugi broj : 3 <enter>
Izlaz:
Zbir a+b je : 5
Razlika a-b je : -1
Proizvod a*b je : 6
Celobrojni kolicnik a/b je : 0
Progresan pokusaj racunanja realnog kolicnika a/b je : 0.000000
Realni kolicnik a/b je : 0.666667
Ostatak pri deljenju a/b je : 2
Primer 1.6.2 Program ilustruje celobrojno i realno deljenje.
#include <stdio.h>

main()
{
int a = 5;
int b = 2;
int d = 5/2; /* Celobrojno deljenje - rezultat je 2 */
float c = a/b; /* Iako je c float, vrsi se celobrojno
deljenje jer su i a i b celi */

/* Neocekivani rezultat 2.000000 */

10
1.7 Operatori i izrazi dodeljivanja vrednosti 11

printf("c = %f\n",c);
printf("Uzrok problema : 5/2 = %f\n", 5/2);
printf("Popravljeno : 5.0/2.0 = %f\n", 5.0/2.0);
printf("Moze i : 5/2.0 = %f i 5.0/2 = %f \n", 5/2.0, 5.0/2);
printf("Za promenljive mora kastovanje : %f\n", (float)a/(float)b);

Izlaz iz programa:
c = 2.000000
Uzrok problema : 5/2 = 2.000000
Popravljeno : 5.0/2.0 = 2.500000
Moze i : 5/2.0 = 2.500000 i 5.0/2 = 2.500000
Za promenljive mora kastovanje : 2.500000

Zadatak 1 Sta ce biti ispisano nakon izvrsavanja sledeceg programa?


#include <stdio.h>
main()
{
int x=506, y=3, z=21, t=2;
printf("x=%d y=%d\n",x,y);
printf("z - t=%d\n", z-t);
printf("z / t =%d\n",z / t);
printf("-x=%d\n",- x);
printf("x %% y=%d\n", x%y);
}

1.7 Operatori i izrazi dodeljivanja vrednosti


i = i + 2;
ekvivalento je sa
i+=2;

Moze i za:
+ - * / % << >> ^ |
izraz1 op = izraz2
je ekvivalnetno sa
izraz1 = (izraz1) op (izraz2)

x*= y+1 je ekvivalento sa x = x * (y+1)

Takvo pisanje je krace i efikasnije.

11
12 Milena VujosevicJanicic

1.8 Inkrementacija i dekrementacija


Operatori ++ i --
x=++n; se razlikuje od x=n++;

y=(x++)*(++z);

Primer 1.8.1 Ilustracija prefiksnog i postfiksnog operatora ++


#include <stdio.h>
main()
{
int x, y;
int a = 0, b = 0;

printf("Na pocetku : \na = %d\nb = %d\n", a, b);

/* Ukoliko se vrednost izraza ne koristi, prefiksni i


postfiksni operator se ne razlikuju */
a++;
++b;
printf("Posle : a++; ++b; \na = %d\nb = %d\n", a, b);

/* Prefiksni operator uvecava promenljivu, i rezultat


je uvecana vrednost */
x = ++a;

/* Postfiksni operator uvecava promenljivu, i rezultat je


stara (neuvecana) vrednost */
y = b++;

printf("Posle : x = ++a; \na = %d\nx = %d\n", a, x);


printf("Posle : y = b++; \nb = %d\ny = %d\n", b, y);
}

Izlaz iz programa:
Na pocetku:
a = 0
b = 0
Posle : a++; ++b;
a = 1
b = 1
Posle : x = ++a;

12
1.9 Relacioni i logicki operatori 13

a = 2
x = 2
Posle : y = b++;
b = 2
y = 1

1.9 Relacioni i logicki operatori


Relacioni operatori:
> >= < <= isti prioritet
== != nizi prioritet

(3<5)
(a<=10)
a < 5 != 1 <=> (a < 5)!=1
Logicki operatori:
! unarna negacija (najvisi prioritet)
&& logicko i (visi prioritet od ili)
|| logicko ili izracunavaju se sleva na desno!

5 && 4 vrednost je tacno


10 || 0 vrednost je tacno
0 && 5 vrednost je 0
!1 vrednost je 0
!9 vrednost je 0
!0 vrednost je 1
!(2>3) je 1
a>b && b>c || b>d je isto sto i ((a>b) && (b>c)) || (b>d)
koja je vrednost ako je a=10, b=5, c=1, d=15?
Primer 1.9.1 Ilustracija logickih i relacijskih operatora.
#include <stdio.h>

main()
{
int a = 3>5, /* manje */
b = 5>3, /* vece */
c = 3==5, /* jednako */
d = 3!=5; /* razlicito */

printf("3>5 - %d\n5>3 - %d\n3==5 - %d\n3!=5 - %d\n", a, b, c, d);

13
14 Milena VujosevicJanicic

/*Lenjo izracunavanje: kako 3 nije vece od 5 to se vrednost


drugog poredjenja nece racunati jer je netacno u konjunkciji
sa proizvoljnim izrazom sigurno netacno. */
printf("Konjunkcija : 3>5 && 5>3 - %d\n", a && b);

/*Lenjo izravunavanje: tacno u disjunkciji sa proizvoljnim


izrazom daje tacno tako da se vrednost izraza 3>5 nece
izracunavati*/
printf("Disjunkcija : 5>3 || 3>5 - %d\n", b || a);
printf("Negacija : !(3>5) - %d\n", !a);

Izlaz iz programa:
3>5 - 0
5>3 - 1
3==5 - 0
3!=5 - 1
Konjunkcija : 3>5 && 5>3 - 0
Disjunkcija : 3>5 || 5>3 - 1
Negacija : !(3>5) - 1

1.10 Kontrola toka if, while, do - while, for


1.10.1 if
if (izraz)
iskaz1
else
iskaz2
Primer 1.10.1 Program ilustruje if i ispisuje ukoliko je uneti ceo
broj negativan
#include <stdio.h>

main()
{
int b;
printf("Unesi ceo broj:");
scanf("%d", &b);
if (b < 0)
printf("Broj je negativan\n");

14
1.10 Kontrola toka if, while, do - while, for 15

}
Else se odnosi na prvi neuparen if, voditi o tome racuna, ako
zelimo drugacije moramo da navedemo viticaste zagrade.
if (izraz)
if (izraz1) iskaz 1
else iskaz
ovo else se odnosi na drugo if a ne na prvo if!
if (izraz)
{
if (izraz1) iskaz 1
}
else iskaz
tek sada se else odnosi na prvo if!!!

1.10.2 Else-if
if (izraz1)
iskaz1
else if (izraz2)
iskaz2
else if (izraz3)
iskaz3
else if (izraz4)
iskaz4
else iskaz

npr if (a<5)
printf("A je manje od 5\n");
else if (a=5)
printf("A je jednako 5\n");
else if (a>10)
printf("A je vece od 10\n");
else if (a=10)
printf("A je jednako 10\n");
else printf("A je vece od pet i manje od 10\n");
Primer 1.10.2 Program ilustruje if-else konstrukciju i ispituje znak
broja.
#include <stdio.h>

15
16 Milena VujosevicJanicic

main()
{
int b;
printf("Unesi ceo broj : ");
scanf("%d", &b);
if (b < 0)
printf("Broj je negativan\n");
else if (b == 0)
printf("Broj je nula\n");
else
printf("Broj je pozitivan\n");
}

Ulaz:
Unesi ceo broj:-5
Izlaz:
Broj je negativan

Ulaz:
Unesi ceo broj:5
Izlaz:
Broj je pozitivan

Primer 1.10.3 Pogresan program sa dodelom = umesto poredjenja


==.
#include <stdio.h>

main()
{
int b;
printf("Unesi ceo broj : ");
scanf("%d", &b);

/* Obratiti paznju na = umesto == Analizirati rad programa*/


if (b = 0)
printf("Broj je nula\n");
else if (b < 0)
printf("Broj je negativan\n");
else
printf("Broj je pozitivan\n");
}

16
1.10 Kontrola toka if, while, do - while, for 17

Ulaz:
Unesi ceo broj:-5
Izlaz:
Broj je pozitivan

1.10.3 while
while(uslov) { ... }
Uslov u zagradi se testira i ako je ispunjen telo petlje se izvrsava.
Zatim se uslov ponovo testira i ako je ispunjen ponovo se izvrsava
telo petlje. I tako sve dok uslov ne bude ispunjen. Tada se izlazi iz
petlje i nastavlja sa prvom sledecom naredbom u programu.
Ukoliko iza while sledi samo jedna naredba nema potrebe za
zagradama.
while (i<j)
i=2*i;

1.10.4 do-while
Ovo je slicno paskalskom repeat-until izrazu.
do iskaz while (izraz)

Primer 1.10.4 Program ilustruje petlju do-while.


#include <stdio.h>

main()
{
int x;

x = 1;
do
{
printf("x = %d\n",x);
x++; /* x++ je isto kao i x=x+1 */
} while (x<=10);
}

1.10.5 for
Primer 1.10.5 Program ilustruje petlju - for.

17
18 Milena VujosevicJanicic

#include <stdio.h>

main()
{
int x;

/* Inicijalizacija; uslov; inkrementacija*/


for (x = 1; x < 5; x++)
printf("x = %d\n",x);

}
Izlaz:
1
2
3
4

1.11 Switch
switch (iskaz) {
case konstantan_izraz1: iskazi1
case konstantan_izraz2: iskazi2
...
default: iskazi
}

Primer 1.11.1 Voditi racuna o upotrebi break-a.


#include <stdio.h> /*
Upotreba switch-a
*/

main() {
char x;
scanf("%c",&x);

switch (x)
{
case a:
case e:
case i:
case o:
case u: printf(" x je samoglasnik");

18
1.12 Uslovni izraz 19

break;
case r: printf(" x je r");
break;
default: printf(" x je suglasnik");
}
}
Primer 1.11.2 Ilustracija switch konstrukcije.
#include<stdio.h>
main()
{
int n;
printf("Unesi paran broj manji od 10\n");
scanf("%d",&n);
switch(n) {
case 0:
printf("Uneli ste nulu\n");
break;
case 2:
printf("Uneli ste dvojku\n");
break;
case 4:
printf("Uneli ste cetvorku\n");
break;
case 6:
printf("Uneli ste sesticu\n");
break;
case 8:
printf("Uneli ste osmicu\n");
break;
defalut:
printf("Uneli ste nesto sto nije paran broj\n");
}
}
Ulaz:
Unesi paran broj manji od 10
2
Izlaz:
Uneli ste dvojku

1.12 Uslovni izraz


Slicno kao if.

19
20 Milena VujosevicJanicic

izraz1 ? izraz2 : izraz3

z = (a<b)? a : b; /*z=min(a,b)*/
max = (a>b)? a : b;

1.13 Simbolicke konstante


Primer 1.13.1 Konverzija centimetara u ince - while petlja.
#include <stdio.h>

/* Definicija simbolickih konstanti preko #define direktiva */


/* U fazi pretprocesiranja se vrsi doslovna zamena konstanti
njihovim vrednostima */

#define POCETAK 0
#define KRAJ 20
#define KORAK 10

main()
{
int a;
a = POCETAK;
while (a <= KRAJ)
{
printf("%d cm = %f in\n", a, a/2.54);
a += KORAK; /* isto sto i a = a + KORAK; */
}
}

Izlaz:
0 cm = 0.000000 in
10 cm = 3.937008 in
20 cm = 7.874016 in

Primer 1.13.2 Konverzija centimetara u ince - for petlja.


#include <stdio.h>
#define POCETAK 0
#define KRAJ 20
#define KORAK 10

main()

20
1.14 Enumeracija 21

{
int a;
for (a = POCETAK; a <= KRAJ; a += KORAK)
printf("%d cm = %f in\n", a, a/2.54);
}

Izlaz:
0 cm = 0.000000 in
10 cm = 3.937008 in
20 cm = 7.874016 in

Zadatak 2 Sta ce biti ispisano nakon izvrsavanja sledeceg programa?


#include <stdio.h>
#define EURO 85.90
main()
{
printf("4 eura ima vrednost %f dinara\n", 4*EURO);
printf("1 euro ima vrednost %.0f dinara\n",EURO);
}

1.14 Enumeracija
Izvesna alternativa za define
enum boolean {NO, YES};
enum meseci {JAN = 1, FEB, MAR, APR, MAJ, JUN,
JUL, AVG, SEP, OKT, NOV, DEC}
enum boje {CRVENA, ZELENA=5, PLAVA,
LJUBICASTA=10, ZUTA, CRNA}

koriscenje:

int x=0;
boje b;

x=CRVENA+3; /*x ce biti jednako tri*/

b=ZELENA;
x=b+CRNA; /* 5 + 12=17*/

b=0; /*Greska, ovako ne moze!!!*/

21
22 Milena VujosevicJanicic

1.15 Funkcije
Primer 1.15.1 sum - najjednostavnija funkcija koja sabira dva broja
/* Definicija funkcije */
int sum(int a, int b)
{
int c;
c = a + b;
return c;
/* Ovo je krace moglo da bude napisano
kao return a+b; */
}

main()
{

int c;
/* Poziv funkcije */
c = sum(3,5);
printf("%d\n", c);

/* Ovo smo krace mogli da napisemo kao


printf("%d\n", sum(3,5)); */
}

Primer 1.15.2 Deklaracija funkcije moze da stoji nezavisno od defini-


cije funkcije. Deklaracija je neophodna u situacijama kada se defini-
cija funkcije navodi nakon upotrebe date funkcije u kodu.
/* Deklaracija funkcije*/
int zbir(int, int);

main()
{
/* Poziv funkcije */
printf("%d\n", zbir(3,5));
}

/* Definicija funkcije */
int zbir(int a, int b)
{
return a+b;
}

22
1.15 Funkcije 23

Primer 1.15.3 power - funkcija koja stepenuje realan broj na celo-


brojni izlozilac
#include <stdio.h>

/* stepenuje x^k tako sto k puta pomnozi x */


float power(float x, int k)
{
int i;
float rezultat = 1;
for (i = 0; i<k; i++)
rezultat*=x;

return rezultat;
}

Primer 1.15.4 Verzija koja radi i za negativne izlozioce


float power(float x, int k)
{
int i;
float s = 1;
int negativan = (k<0);
float rezultat;

if (negativan)
k = -k;

for (i = 0; i<k; i++)


s*=x;

rezultat = negativan ? 1.0/s : s;


return rezultat;
}

main()
{
/* Poziv funkcije */
float s = power(2.0,8);
printf("%f\n", s);
}

Primer 1.15.5 Ilustracija lenjog izracunavanja logickih operatora.


Prilikom izracunavanja izraza - A && B, ukoliko je A netacno,

23
24 Milena VujosevicJanicic

izraz B se ne izracunava. Prilikom izracunavanja izraza - A k B,


ukoliko je A tacno, izraz B se ne izracunava.

#include <stdio.h>

/* Globalna promenljiva, vidljiva i iz funkcije main() i


iz funkcije izracunaj*/
int b = 0;

/* Funkcija ispisuje da je pozvana i uvecava promenjivu b.


Funkcija uvek vraca vrednost 1 (tacno)
*/
int izracunaj()
{
printf("Pozvano izracunaj()\n");
b++;
return 1;
}

main()
{
/* Funkcija izracunaj() ce biti pozvana
samo za parne vrednosti a */
int a;
for (a = 0; a < 10; a++)
if (a%2 == 0 && izracunaj())
printf("Uslov ispunjen : a = %d, b = %d\n", a, b);
else
printf("Uslov nije ispunjen : a = %d, b = %d\n", a, b);

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

/* Funkcija izracunaj() ce se pozivati samo


za neparne vrednosti a */
b = 0;
for (a = 0; a < 10; a++)
if (a%2 == 0 || izracunaj())
printf("Uslov ispunjen : a = %d, b = %d\n", a, b);
else
printf("Uslov nije ispunjen : a = %d, b = %d\n", a, b);
}

24
1.16 Nizovi 25

1.16 Nizovi
Deklaracija niza:
int niz[5]; /* niz od 5 elemenata tipa int*/
Pristupanje elementima niza:
niz[0] = 4;
niz[1] = 2 * niz[0]; /*niz[1] = 8*/
niz[2] = niz[0] * niz[1]; /*niz[2] = 32*/
niz[3] = 5;
niz[4] = 7;
Unos vrednosti elemenata niza sa tastature:
for(i=0; i<5; i++)
scanf("%d", &a[i]);
Stampanje elemenata niza
for(i=0; i<5; i++)
printf("%d ", a[i]);
Brojanje elemenata niza je od nule!
Pristupanje elementu niza, indeks moze da bude proizvoljan izraz
celobrojne vrednosti: niz[i*2]=5.
Primer 1.16.1 Program ilustruje koriscenje nizova. Ispisuje 10
unetih brojeva unazad.
#include <stdio.h>

main()
{
int a[10];
int i;
for (i = 0; i<10; i++)
{
printf("a[%d]=",i);
scanf("%d",&a[i]);
}

printf("Unazad : \n");

for (i = 9; i>=0; i--)


printf("a[%d]=%d\n",i,a[i]);
}

25
26 Milena VujosevicJanicic

Primer 1.16.2 Program pronalazi maksimum brojeva sa ulaza -


verzija sa nizom.
#include <stdio.h>
#define BR_ELEM 5
main()
{
int a[BR_ELEM];
int i;
int max;

/* Ucitavamo niz brojeva */


for (i = 0; i < BR_ELEM; i++)
scanf("%d",&a[i]);

/* Pronalazimo maksimum */
max = a[0];
for (i = 1; i < BR_ELEM; i++)
if (a[i]>max)
max = a[i];

/* Ispisujemo maksimum */
printf("Max = %d\n",max);
}

Primer 1.16.3 Program pronalazi maksimum brojeva sa ulaza -


verzija bez niza.
#include <stdio.h>
#define BR_ELEM 5

main()
{
int a, max, i;
scanf("%d",&a);
max = a;
for (i = 1; i < BR_ELEM; i++)
{
scanf("%d",&a);
if (a>max)
max = a;
}

printf("Max : %d\n", max);

26
1.17 Konstante 27

1.17 Konstante
Koji su tipovi konstanti?
Celobrojna konstanta 1234 je tipa int.
Da bi konstanta bila long navodi se iza nje slovo L ili l, npr 123456789L.
Ako zelimo da nam je konstanta unsigned onda na kraju pisemo U
ili u.
Moze i 1234567ul.

Konstante realnih brojeva sadrze decimalnu tacku(123.4) ili


eksponent(1e-2) ili i jedno i drugo. Njihov tip je double osim ako
nemaj sufiks f ili F kada je u pitanju float. L ili l oznacavaju long
double.
Oktalna konstanta pocinje sa 0, a heksadecimalna sa 0x. Npr
broj 31 ili 037 - oktalno ili 0x1f - heksadecimalno. I one mogu da
imaju U i L na kraju.
Znakovna konstanta je celobrojna vrednost napisana izme u 

jednostrukih navodnika. Vrednost date konstante je numericka vred-


nost datog znaka u racunarskom setu znakova. Npr mozemo da
pisemo 0 umesto 48.
!!!Razlikovati znakovne konstante i niske koje se navode izme u 

dvostrukih navodnika!
Posebni znaci su znak za kraj reda, tab i slicno.
Znakovna konstanta \0 predstavlja znak cija je vrednost nula,
treba ga razlikovati od 0 koja je znak cija je vrednost 48.
Konstantna niska: Ja sam niska
ili
/*prazna niska*/
Navodnici nisu deo niske vec se koriste da bi je ogranicili. Ako ih
zelimo unutar niske, oni se navode sa \".
Konstantna niska je polje znakova. Da bi se znalo gde je kraj
niske, fizicko memorisanje liste zahteva da postoji jedan znak vise
koji oznacava kraj, to je \0. Da bi se odredila duzina niske mora
se proci kroz celu nisku.
!!!Vazno:

Koja je razlika izme u x i x ?




Primer 1.17.1 Primer funkcije koja izracunava duzinu niske znakova.


#include <stdio.h>

27
28 Milena VujosevicJanicic

int strlen(char s[])


{
int i=0;

while (s[i] != \0)


++i;
return i;
}

int main()
{
printf("Duzina ove niske
je: %d \n",strlen("Duzina ove niske je:"));
return 0;
}

1.18 Konverzija
1.18.1 Automatska konverzija
Ako je jedan od operanada razlizlicit vrsi se konverzija, uvek u smeru
manjeg ka vecem tipu

Naredba dodele:
int i=5;
float f=2.3;
f=i; /* f ce imati vrednost 5.0*/

obrnuto:

int i=5;
float f=2.3;
i=f; /* i ce imati vrednost 2*/

1.18.2 Eksplicitna konverzija


(tip)<izraz>

float x;
x=2.3+4.2; /* x ce imati vrednost 6.5 */
x=(int)2.3+(int)4.2; /* x ce imati vrednost 6 */

28
1.18 Konverzija 29

x=(int)2.3*4.5; /* x ce imati vrednost 9.0 jer zbog prioriteta


operatora konverzije prvo ce biti izvrsena
konverzija broja 2.3 u 2 pa tek onda izvrseno
mnozenje. */
x=(int)(2.3*4.5) /* x ce imati vrednost 10.0 */
Primer 1.18.1 Kako izbeci celobrojno deljenje
int a,b;
float c;
a = 5;
b = 2;
c = a/b; /* Celobrojno deljenje, c=2*/
c = (1.0*a)/b; /* Implicitna konverzija: 1.0*a je realan
broj pa priliko deljenja sa b dobija se
realan rezultat c=2.5*/
c = (0.0+a)/b; /* Implicitna konverzija: (0.0+a) je realan
broj pa priliko deljenja sa b dobija se
realan rezultat c=2.5*/
c = (float)a/(float)b; /* Eksplicitna konverzija*/

1.18.3 Funkcije koje vrse konverziju


Primer 1.18.2
#include <stdio.h>
main()
{
int vrednost;
vrednost=A;
printf("Veliko slovo\n karakter=%3c\nvrednost=%3d\n",vrednost,vrednost);
vrednost=a;
printf("Malo\n karakter=%3c\nvrednost=%3d\n",vrednost,vrednost);
}

Izlaz (u slucaju ASCII):


Veliko slovo
karakter= A
vrednost= 65
Malo
karakter= a
vrednost= 97
Primer 1.18.3 Funkcija koja konvertuje velika slova u mala slova.
#include<stdio.h>

29
30 Milena VujosevicJanicic

/* Konvertuje karakter iz velikog u malo slovo */


char lower(char c)
{
if (c >= A && c <= Z)
return c - A + a ;
else
return c;
}

main()
{
char c;
printf("Unesi neko veliko slovo:\n");
scanf("%c", &c);
printf("Odgovarajuce malo slovo je %c\n", lower(c));
}

Primer 1.18.4 Konvertovanje niske cifara u ceo broj.


#include<stdio.h>

/* atoi: konvertuje s u ceo broj */


int atoi(char s[])
{
int i, n;
n = 0;
for (i = 0; (s[i] >= 0) && (s[i] <= 9); ++i)
n = 10 * n + (s[i] - 0);
return n;
}

main()
{
int n;
n = atoi("234");
printf("\nN je : %d\n",n);
}

1.19 Operator sizeof()


Primer 1.19.1 Demonstracija sizeof operatora. Sizeof operator
izracunava velicinu tipa odnosno promenjive.

30
1.20 Znakovni ulaz i izlaz 31

#include<stdio.h>
main()
{
int i;
float f;
int n[10];

printf("sizeof(int)=%d\n", sizeof(int));
printf("sizeof(long)=%d\n", sizeof(long));
printf("sizeof(short)=%d\n", sizeof(short));
printf("sizeof(signed)=%d\n", sizeof(signed));
printf("sizeof(unsigned)=%d\n", sizeof(unsigned));
printf("sizeof(char)=%d\n", sizeof(char));
printf("sizeof(float)=%d\n", sizeof(float));
printf("sizeof(double)=%d\n", sizeof(double));

printf("sizeof(i)=%d\n", sizeof(i));
printf("sizeof(f)=%d\n", sizeof(f));
printf("sizeof(n)=%d\n", sizeof(n));
printf("Broj elemenata niza n : %d\n", sizeof(n)/sizeof(int));

Izlaz iz programa(u konkretnom slucaju):


sizeof(int)=4
sizeof(long)=4
sizeof(short)=2
sizeof(signed)=4
sizeof(unsigned)=4
sizeof(char)=1
sizeof(float)=4
sizeof(double)=8
sizeof(i)=4
sizeof(f)=4
sizeof(n)=40
Broj elemenata niza n : 10

1.20 Znakovni ulaz i izlaz


Funkcija za citanje jednog znaka sa ulaza
c = getchar()
promenljiva c sadrzi jedan znak sa ulaza.

31
32 Milena VujosevicJanicic

Funkcija za stampanje jednog znaka na izlaz


putchar(c)
stampa sadrzaj promenljive c obicno na ekranu.

Konstanta EOF je celobrojna vrednost definisana u biblioteci <stdio.h>.


Ovu vrednost vrati funkcija getchar() kada nema vise ulaza. Naz-
vana je EOF kao End Of File, kraj datoteke. Ova vrednost mora da
se razlikuje od svake vrednosti koja moze da bude karakter. Zato
za c za koje je c=getchar() treba da koristimo tip dovoljno veliki
da moze da prihvati sve sto moze da vrati getchar(), dakle i EOF.
Zbog toga se za c koristi tip int.
Primer 1.20.1 Program cita jedan karakter i ispisuje ga - demon-
stracija putchar i getchar.
#include <stdio.h>

main()
{
int c; /* Karakter - obratiti paznju na int */
c = getchar(); /* cita karakter sa standardnog ulaza */
putchar(c); /* pise karakter c na standardni izlaz */

putchar(\n); /* prelazak u novi red */


putchar(a); /* ispisuje malo a */
putchar(97); /* ekvivalentno prethodnom */
}
Ulaz:
s
Izlaz iz programa:
s
s
aa
Primer 1.20.2 Program prepisuje standardni ulaz na standardni
izlaz. Ilustracija redirekcije standardnog ulaza i izlaza, pokrenuti
program sa :
./a.out <primer.c
./a.out >tekst.txt
./a.out <primer.c >kopija.c
#include <stdio.h>

32
1.20 Znakovni ulaz i izlaz 33

main()
{
/*Koristi se int a ne char zato sto zelimo
da razlikujemo kraj ulaza od vazecih znakova*/
int c;

/*Ucitava se prvi znak sa ulaza*/


c = getchar();

/*EOF predstavlja celobrojnu vrednost kraja datoteke.


To je konstanta definisana u <stdio.h>*/
while (c != EOF) {
putchar(c);
c = getchar();
}
}
Bilo koje dodeljivanje vrednosti je izraz koji ima vrednost a to je
vrednost leve strane posle dodeljivanja.
Primer 1.20.3 Program koji kopira ulaz na izlaz, skraceni kod.
#include <stdio.h>

main()
{
int c;

/* Obratiti paznju na raspored zagrada */


while ((c = getchar()) != EOF)
putchar(c);
}
Primer 1.20.4 Brojanje znakova na ulazu.
#include <stdio.h>

main()
{
long nc;

nc = 0;
while (getchar() != EOF)
++nc;
/* %ld odnosi se na tip long. */

33
34 Milena VujosevicJanicic

printf("%ld\n", nc);
}

Primer 1.20.5 Brojanje znakova na ulazu koriscenjem for petlje.


#include <stdio.h>

main()
{
double nc;

/*For petlja mora da ima telo pa makar


ono bilo przno*/
for (nc = 0; getchar() != EOF; ++nc)
;
printf("%.0f\n", nc);
}

Primer 1.20.6 Program broji linije i znakove na ulazu.


#include <stdio.h>
main()
{
int znak; /*prihvata znak sa ulaza */
long linije=0 ; /*brojac linija */
long br_znak=0; /*brojac znakova na ulazu */

while ( (znak=getchar() ) != EOF)


{
br_znak++;
if (znak==\n) linije ++;
}

printf("Prelazaka u novi red: %ld, karaktera: %ld \n",linije,br_znak);


}

Primer 1.20.7 Program broji blankove, horizontalne tabulatore i


linije na ulazu.
#include <stdio.h>
main()
{
int znak; /*prihvata znak sa ulaza */
int Blanks=0; /*brojac blankova */
int Tabs=0; /*brojac horizontalnih tabulatora */

34
1.20 Znakovni ulaz i izlaz 35

int NewLines=0; /*brojac linija */

/*UOCITI: blok naredbi while ciklusa NIJE OGRADJEN


viticastim zagradama jer postoji samo jedna if naredba! */
while( (znak=getchar())!=EOF )
if( znak== ) ++Blanks; /* brojimo blanko simbole */
else if( znak==\t ) ++Tabs; /* brojimo tab-ove */
else if( znak==\n ) ++NewLines; /* brojimo redove */

/*izdavanje rezultata na standardni izlaz*/


printf("Blankova: %d. Tabulatora: %d. Prelazaka u novi red: %d\n",
Blanks, Tabs, NewLines);

Primer 1.20.8 Program prepisuje ulaz na izlaz pri cemu vise blanko
znakova zamenjuje jednim.
#include <stdio.h>

main()
{
int znak; /*tekuci znak sa ulaza*/
int preth; /*znak koji prethodi tekucem */
preth=a; /* inicijalizujemo vrednost prethodnog
da bi prvi prolazak kroz petlju bio ispravan*/
while ( (znak=getchar() ) !=EOF)
{
if (znak != || preth != ) putchar(znak);
preth=znak;
}
}

Primer 1.20.9 Program vrsi prebrojavanje cifara unetih na ulazu.


#include <stdio.h>

main()
{
int c;
int br_cifara = 0;
while ((c = getchar()) != EOF)
if (0<=c && c<=9)
br_cifara++;

35
36 Milena VujosevicJanicic

printf("Broj cifara je : %d\n", br_cifara);


}
Primer 1.20.10 Program vrsi brojanje pojavljivanja karaktera 0, 1
i 2 (ilustruje switch).
#include <stdio.h>

main()
{
int c;
int br_0=0, br_1=0, br_2=0;

while ((c = getchar()) != EOF)


{
switch(c)
{
/* Obratiti paznju da nije
case 0: */
case 0:
br_0++;
break; /* Isprobati veziju bez break */
case 1:
br_1++;
break;
case 2:
br_2++;
break;
default:
}
}
printf("Br 0 : %d\nBr 1 : %d\nBr 2 : %d\n",br_0, br_1, br_2);
}

1.21 Nizovi
Primer 1.21.1 Program ilustruje inicijalizaciju nizova.
#include <stdio.h>

main()
{
/* Niz inicijalizujemo tako sto mu navodimo vrednosti

36
1.21 Nizovi 37

u viticasnim zagradama. Dimenzija niza se odredjuje


na osnovu broja inicijalizatora */
int a[] = {1, 2, 3, 4, 5, 6};

/* Isto vazi i za niske karaktera */


char s[] = {a, b, c};

/* Ekvivalentno prethodnom bi bilo


char s[] = {97, 98, 99};
*/

/* Broj elemenata niza */


int a_br_elem = sizeof(a)/sizeof(int);
int s_br_elem = sizeof(s)/sizeof(char);

/* Ispisujemo nizove */

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

for (i = 0; i < s_br_elem; i++)


printf("s[%d]=%c\n",i, s[i]);

}
Primer 1.21.2 Program uvodi niske karaktera terminisane nulom.
#include <stdio.h>

main()
{
/* Poslednji bajt niske karaktera se postavlja na \0 tj. 0 */
char s[] = {a, b, c, \0 };

/* Kraci nacin da se postigne prethodno */


char t[] = "abc";

/* Ispis niske s karakter po karakter*/


int i;
for (i = 0; s[i] != \0; i++)
putchar(s[i]);
putchar(\n);

37
38 Milena VujosevicJanicic

/* Ispis niske s koristeci funkciju printf */


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

/* Ispis niske t karakter po karakter*/


for (i = 0; t[i] != \0; i++)
putchar(t[i]);
putchar(\n);

/* Ispis niske t koristeci funkciju printf */


printf("%s\n", t);
}
Primer 1.21.3 Brojanje pojavljivanja svake od cifara. Koriscenje
niza brojaca.
#include <stdio.h>

/* zbog funkcije isdigit */


#include <ctype.h>

main()
{
/* Niz brojaca za svaku od cifara */
int br_cifara[10];
int i, c;

/* Resetovanje brojaca */
for (i = 0; i < 10; i++)
br_cifara[i] = 0;

/* Citamo sa ulaza i povecavamo odgovarajuce brojace */


while ((c = getchar()) != EOF)
if (isdigit(c))
br_cifara[c-0]++;

/* Ispis rezultata */
for (i = 0; i < 10; i++)
printf("Cifra %d se pojavila %d put%s\n",
i, br_cifara[i], br_cifara[i] == 1 ? "" : "a");
}
Primer 1.21.4 Brojanje reci
#include <stdio.h>

38
1.22 Dvostruka for petlja 39

#define IN 1 /* inside a word */


#define OUT 0 /* outside a
word */

/* count lines, words, and characters in input */

main()
{
int c, nl, nw, nc, state;

state = OUT;

/*Postavljaju se sve tri promenljive na nulu*/


/*Isto kao da smo napisali
nl = (nw = (nc = 0));*/

nl = nw = nc = 0;
while ((c = getchar()) != EOF) {
++nc;
if (c == \n)
++nl;
/*Operator || znaci OR*/
if (c == || c == \n || c == \t)
state = OUT;
else if (state == OUT) {
state = IN;
++nw;
}
}
printf("%d %d %d\n", nl, nw, nc);
}

1.22 Dvostruka for petlja


Primer 1.22.1 Dvostruka for petlja
#include<stdio.h>
int main()
{
int i,j;

for(i=1; i<=10; i++)

39
40 Milena VujosevicJanicic

{
for(j=1; j<=10; j++)
printf("%d * %d = %d\t", i, j, i*j);
printf("\n");
}
}

Primer 1.22.2 Trostruka for petlja


#include<stdio.h>
int main()
{
int i,j;

for(i=1; i<=10; i++)


for(j=1; j<=10; j++)
{
for(k=1; k<=10; k++)
printf("%d * %d * %d = %d\t", i, j, k, i*j*k);
printf("\n");
}
}
Koliko puta se izvrsi naredba stampanja
printf("%d * %d * %d = %d\t", i, j, k, i*j*k);

1.23 Formiranje HTML dokumenta


Primer 1.23.1 Prilikm pokretanja programa koristiti redirekciju:
a.out >primer.html
kako bi se rezultat rada programa upisao u datoteku primer.html.
/*Ovaj program formira html dokument*/
#include <stdio.h>
main()
{
printf("<html><head><title>Ova stranica
je napravljena u c-u</title></head>");
printf("<body><h3 align=center>
Rezultat </h3></body></html>");
}

Primer 1.23.2 Napisati program koji generise html dokument sa


engleskim alfabetom.

40
1.23 Formiranje HTML dokumenta 41

#include <stdio.h>
main()
{
int i;
printf("<HTML><head><title>Engleski alfabet</title><head>\n");
printf("<body><ul>");
for(i=0;i<=25;i++)
printf("<li> %c %c \n",A+i,a+i);
printf("</ul></body></HTML>\n"); }
Primer 1.23.3 Napisati program koji generise html dokument koji
prikazuje tablicu mnozenja za brojeve od 1 do 10.
#include<stdio.h>
main()
{
int i,j;
printf("<html><head><title>Mnozenje</title></head>");
printf("<body><h3 align=center> Rezultat </h3>");
printf("<table border=1>\n");

/* Prva vrsta sadrzi brojeve od 1 do 10*/


printf("<tr>");
printf("<th></th>");
for(i=1; i<=10; i++)
printf("<th> %d </th>\n", i);
printf("</tr>");

for(i=1; i<=10; i++)


{
printf("<tr>");

/* Na pocetku svake vrste stampamo broj


odgovarajuce vrste*/
printf("<th>%d</th>", i);

for(j=1; j<=10; j++)


printf("<td>%d\t</td>\n", i*j);

printf("</tr>");
}
printf("</table>");
printf("</body></html>");
}

41
42 Milena VujosevicJanicic

1.24 Funkcije prenos parametara po vred-


nosti
Primer 1.24.1 Funkcija koja proverava da li je broj prost i program
koji ispisuje sve proste brojeve manje od 100.
#include<stdio.h>
#include<math.h>

int prost(int p)
{
int i, koren, ind;
koren=sqrt(p);
ind=(p%2) || (p==2);
i=3;
while (ind && i<=koren)
{
ind=p%i;
i+=2;
}
return ind;
}

main()
{
int k;
for(k=2;k<=100;k++)
if (prost(k)) printf("%d ",k);
}
Primer 1.24.2
#include <stdio.h> /* Ilustruje vidljivost imena*/

int i=10;

void main() {
{
int i=3;
{
int i=1;
printf("%d\n", i);
}
printf("%d\n",i);
}

42
1.24 Funkcije prenos parametara po vrednosti 43

printf("%d\n",i);
}

Primer 1.24.3 Demonstracija prenosa parametara po vrednosti -


preneti parametri se ne mogu menjati
#include <stdio.h>
void f(int x)
{
x++;
}

main()
{
int x=3;
f(x);
printf("%d\n", x);
}

Primer 1.24.4 Demonstrira prenos nizova u funkciju - preneti niz


se moze menjati.
#include <stdio.h>
#include <ctype.h>

/* Funkcija ucitava rec sa standardnog ulaza i smesta je u niz karaktera s.


Ovo uspeva zbog toga sto se po vrednosti prenosi adresa pocetka niza,
a ne ceo niz */
void get_word(char s[])
{
int c, i = 0;
while (!isspace(c=getchar()))
s[i++] = c;
s[i] = \0;
}

main()
{
/* Obavezno je alocirati memoriju za niz karaktera */
char s[100];

get_word(s);
printf("%s\n", s);
}

43
44 Milena VujosevicJanicic

Primer 1.24.5 Funkcija za ispis niza brojeva - demonstrira prenos


nizova brojeva u funkciju.
#include <stdio.h>

/* Nizovi se prenose tako sto se prenese adresa njihovog pocetka.


Uglaste zagrade ostaju prazne!

Nizove je neophodno prenositi zajedno sa dimenzijom niza


(osim za niske karaktera, jer tamo vazi konvencija da
se kraj niza obelezava znakom \0)
*/
void print_array(int a[], int n)
{
int i;
for (i = 0; i < n; i++)
printf("%d ",a[i]);
putchar(\n);

/* Obratite paznju na ovo : */


printf("sizeof(a) - u okviru fje : %d\n", sizeof(a));
}

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

printf("sizeof(a) - u okviru main : %d\n", sizeof(a));


print_array(a, sizeof(a)/sizeof(int));
}

Primer 1.24.6 Funkcija za ispis niske karaktera - demonstrira prenos


niske karaktera u funkciju.
#include <stdio.h>

/* Uz nisku karaktera nije potrebno prenositi dimenziju


ukoliko se postuje dogovor
da se svaka niska zavrsava karakterom \0.*/
void print_string(char s[])
{
int i;
for (i = 0; s[i]!=\0; i++)
putchar(s[i]);

44
1.25 Break i continue 45

main()
{
print_string("Zdravo\n");
}

1.25 Break i continue


Primer 1.25.1 Funkcija uklanja beline, tabulatore ili znak za kraj
reda sa kraja stringa.
int trim(char s[])
{
int n;
for (n = strlen(s)-1; n >= 0; n--)
if (s[n] != && s[n] != \t && s[n] != \n)
break;
s[n+1] = \0;
return n;
}
Continue se re e koristi, on prouzrokuje da se pre e na sledecu
 

iteraciju u petlji.
Primer 1.25.2
for(i=0; i<n; i++)
{
if (a[i]==0) continue;
... /* obradi pozitivne elemente nekako*/
}

1.26 Rad sa niskama karaktera


Primer 1.26.1 string reverse - obrce nisku karaktera.
#include <stdio.h>

/* Ova funkcija racuna duzinu date niske karaktera.


Umesto nje, moguce je koristiti standardnu funkciju strlen
za cije je koriscenje potrebno ukljuciti zaglavlje
<string.h>
*/

45
46 Milena VujosevicJanicic

int string_length(char s[])


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

return i;
}

/* Funkcija obrce nisku karaktera */


void string_reverse(char s[])
{
int i, j;
for (i = 0, j = string_length(s)-1; i<j; i++, j--)
{
int tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}

/* Napomena : razlikovati prethodnu petlju od dve ugnjezdjene petlje:


for ( i = 0; ....)
for ( j = duzina(s)-1; ...
*/

main()
{
char s[] = "Zdravo svima";
string_reverse(s);
printf("%s\n", s);
}
/*
Izlaz:
amivs ovardZ
*/
Primer 1.26.2 strlen, strcpy, strcat, strcmp, strchr, strstr
- manipulacija niskama karaktera. Vezbe radi, implementirane su
funkcije biblioteke string.h

#include <stdio.h>

46
1.26 Rad sa niskama karaktera 47

/* Izracunava duzinu stringa */


int string_length(char s[])
{
int i;
/* Uslov s[i] je ekvivalentan uslovu
s[i]!=\0 ili uslovu s[i]! = 0*/
for (i = 0; s[i]; i++)
;
return i;
}

/* Kopira string src u string dest.


Pretpostavlja da u dest ima dovoljno prostora. */
void string_copy(char dest[], char src[])
{
/* Kopira karakter po karakter, sve dok nije iskopiran karakter \0 */
int i;
for (i = 0; (dest[i]=src[i]) != \0; i++)
;

/* Uslov != \0 se, naravno, moze izostaviti :

for (i = 0; dest[i]=src[i]; i++)


;
*/

/* Nadovezuje string t na kraj stringa s.


Pretpostavlja da u s ima dovoljno prostora. */
void string_concatenate(char s[], char t[])
{
int i, j;
/* Pronalazimo kraj stringa s */
for (i = 0; s[i]; i++)
;

/* Vrsi se kopiranje, slicno funkciji string_copy */


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

47
48 Milena VujosevicJanicic

/* Vrsi leksikografsko poredjenje dva stringa.


Vraca :
0 - ukoliko su stringovi jednaki
<0 - ukoliko je s leksikografski ispred t
>0 - ukoliko je s leksikografski iza t
*/
int string_compare(char s[], char t[])
{
/* Petlja tece sve dok ne naidjemo na prvi razliciti karakter */
int i;
for (i = 0; s[i]==t[i]; i++)
if (s[i] == \0) /* Naisli smo na kraj oba stringa,
a nismo nasli razliku */
return 0;

/* s[i] i t[i] su prvi karakteri u kojima se niske razlikuju.


Na osnovu njihovog odnosa, odredjuje se odnos stringova */
return s[i] - t[i];
}

/* Pronalazi prvu poziciju karaktera c u stringu s, odnosno -1


ukoliko s ne sadrzi c */
int string_char(char s[], char c)
{
int i;
for (i = 0; s[i]; i++)
if (s[i] == c)
return i;
/* nikako
else
return -1;
*/
/* Nije nadjeno */
return -1;
}

/* Pronalazi poslednju poziciju karaktera c u stringu s, odnosno -1


ukoliko s ne sadrzi c */
int string_last_char(char s[], char c)
{
/* Pronalazimo kraj stringa s */
int i;

48
1.26 Rad sa niskama karaktera 49

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


;

/* Krecemo od kraja i trazimo c unazad */


for (i--; i>=0; i--)
if (s[i] == c)
return i;

/* Nije nadjeno */
return -1;

/*
Koristeci string_length :

for (i = string_length(s) - 1; i>0; i--)


if (s[i] == c)
return i;

return -1;
*/
}

/* Proverava da li string str sadrzi string sub.


Vraca poziciju na kojoj sub pocinje, odnosno -1 ukoliko ga nema
*/
int string_string(char str[], char sub[])
{
int i, j;
/* Proveravamo da li sub pocinje na svakoj poziciji i */
for (i = 0; str[i]; i++)
/* Poredimo sub sa str pocevsi od poziciji i
sve dok ne naidjemo na razliku */
for (j = 0; str[i+j] == sub[j]; j++)
/* Nismo naisli na razliku a ispitali smo
sve karaktere niske sub */
if (sub[j+1]==\0)
return i;
/* Nije nadjeno */
return -1;
}

main()
{

49
50 Milena VujosevicJanicic

char s[100];
char t[] = "Zdravo";
char u[] = " svima";

string_copy(s, t);
printf("%s\n", s);

string_concatenate(s, u);
printf("%s\n", s);

printf("%d\n",string_char("racunari", n));
printf("%d\n",string_last_char("racunari", a));

printf("%d\n",string_string("racunari", "rac"));
printf("%d\n",string_string("racunari", "ari"));
printf("%d\n",string_string("racunari", "cun"));
printf("%d\n",string_string("racunari", "cna"));
}

/*
Izlaz:
Zdravo
Zdravo svima
4
5
0
5
2
-1*/

1.27 Makroi
#define ime tekst_zamene

Zamene se vrse samo na simbolima, a ne obavljaju se u niskama


nutar navodnika.
Moguce je definisati makroe sa argumentima tako da tekst zamene
bude razlicit za razlicita pojavljivanja makroa.

Primer 1.27.1 Demonstracija pretprocesorske direktive #define


#include<stdio.h>

50
1.27 Makroi 51

/* Racuna sumu dva broja */


#define sum(a,b) ((a)+(b))

/* Racuna kvadrat broja - pogresna verzija */


#define square_w(a) a*a

/* Racuna kvadrat broja */


#define square(a) ((a)*(a))

/* Racuna minimum tri broja */


#define min(a, b, c) (a)<(b)? ((a)<(c)? (a) : (c)) : ((b)<(c)? (b) : (c))

main()
{
printf("sum(3,5) = %d\n", sum(3,5));
printf("square_w(5) = %d\n", square_w(5));
printf("square_w(3+2) = %d\n", square_w(3+2));
printf("square(3+2) = %d\n", square(3+2));
printf("min(1,2,3) = %d\n", min(1,2,3));
printf("min(1,3,2) = %d\n", min(1,3,2));
printf("min(2,1,3) = %d\n", min(2,1,3));
printf("min(2,3,1) = %d\n", min(2,3,1));
printf("min(3,1,2) = %d\n", min(3,1,2));
printf("min(3,2,1) = %d\n", min(3,2,1));
}

Izlaz iz programa:
sum(3,5) = 8
square_w(5) = 25
square_w(3+2) = 11
square(3+2) = 25
min(1,2,3) = 1
min(1,3,2) = 1
min(2,1,3) = 1
min(2,3,1) = 1
min(3,1,2) = 1
min(3,2,1) = 1

Primer 1.27.2
#define max(A, B) ((A)>(B) ? (A) : (B))
na osnovu ovoga ce linija
x=max(p+q, r+s)

51
52 Milena VujosevicJanicic

biti zamenjena linijom


x=((p+q) > (r+s) ? (p+q) : (r+s));
Treba voditi racuna o sporednim efektima. Sledeca linija koda
pruzrokovace uvecanje vrednosti i ili j za dva.
max(i++, j++)
Tako e treba voditi racuna o zagradama. Sledeci makro prouzrokovace


neocekivane rezultate za upotrebu square(a+1)


#define square(x) x*x
Primer 1.27.3 Ilustacija beskonacne petlje:
#define forever for(;;);
Primer 1.27.4
#include <stdio.h>
#define max1(x,y) (x>y?x:y)
#define max2(x,y) ((x)>(y)?(x):(y))
#define swapint(x,y) { int z; z=x; x=y; y=z; }
#define swap(t,x,y) { \
t z; \
z=x; \
x=y; \
y=z; }

main()
{

int x=2,y=3;

printf( "max1(x,y) = %d\n", max1(x,y) );


/* max1(x,y) = 3 */

/* Zamena makroom se ne vrsi


unutar niski pod navodnicima*/
printf( "max1(x=5,y) = %d\n", max1(x,y) );
/* max1(x=5,y) = 3 */

printf( "max1(x++,y++) = %d\n", max1(x++,y++) );


/* max1(x++,y++) = 4 */

printf( "x = %d, y = %d\n", x, y );

52
1.28 Bitski operatori 53

/* x = 3, y = 5 */

swapint(x,y);

printf( "x = %d, y = %d\n", x, y );


/* x = 5, y = 3 */

swap(int,x,y);
printf( "x = %d, y = %d\n", x, y );
/* x = 3, y = 5 */
}

Izlaz:
max1(x,y) = 3
max1(x=5,y) = 3
max1(x++,y++) = 4
x = 3, y = 5
x = 5, y = 3
x = 3, y = 5

1.28 Bitski operatori


!!!Ne mesati sa logickim operatorima!!!

& bitsko AND


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

Primer 1.28.1 Demonstracija bitskih operatora


#include <stdio.h>

main()
{ printf("%o %o\n",255,15);
printf( "255 & 15 = %d\n", 255 & 15 );
printf( "255 | 15 = %d\n", 255 | 15 );
printf( "255 ^ 15 = %d\n", 255 ^ 15 );
printf( "2 << 2 = %d\n", 2 << 2 );
printf( "16 >> 2 = %d\n", 16 >> 2 );
}

53
54 Milena VujosevicJanicic

Izlaz iz programa je:


377 17
255 & 15 = 15
255 | 15 = 255
255 ^ 15 = 240
2 << 2 = 8
16 >> 2 = 4
Primer 1.28.2 print bits - stampa bitove u zapisu datog celog broja
x.
#include <stdio.h>

/* Funkcija stampa bitove datog celog broja x.


Vrednost bita na poziciji i je 0 ako i
samo ako se pri konjunkciji broja x sa maskom
000..010....000 - sve 0 osim 1 na poziciji i,
dobija 0.
Funkcija krece od pozicije najvece tezine
kreirajuci masku pomeranjem jedinice u levo
za duzina(x) - 1 mesto, i zatim pomerajuci
ovu masku za jedno mesto u levo u svakoj
sledecoj iteraciji sve dok maska ne postane 0.
*/

void print_bits(int x)
{
/* Broj bitova tipa unsigned */
int wl = sizeof(int)*8;

unsigned mask;
for (mask = 1<<wl-1; mask; mask >>= 1)
putchar(x&mask ? 1 : 0);

putchar(\n);
}

main()
{
print_bits(127);
print_bits(128);
print_bits(0x00FF00FF);
print_bits(0xFFFFFFFF);

54
1.28 Bitski operatori 55

Izlaz iz programa:
00000000000000000000000001111111
00000000000000000000000010000000
00000000111111110000000011111111
11111111111111111111111111111111

Primer 1.28.3 Program proverava da li se na k-tom mestu nalazi


1.
#include <stdio.h>

/* Pozicije brojimo kao u sledecem primeru:


poz: ... 10 9 8 7 6 5 4 3 2 1 0
bit: ... 0 0 0 1 1 1 0 0 1 1 0 */

main()
{
int n,k;
printf("Unesite broj i poziciju tog broja koju zelite da proverite:\n");
scanf("%d%d",&n,&k);
if ((n & (1 << k))!=0)
printf("Bit je 1\n");
else
printf("Bit je 0\n");
}

Primer 1.28.4 Program postavlja na k-to mesto 1


#include <stdio.h>

void print_bits(int x)
{
/* Broj bitova tipa unsigned */
int wl = sizeof(int)*8;

unsigned mask;
for (mask = 1<<wl-1; mask; mask >>= 1)
putchar(x&mask ? 1 : 0);

putchar(\n);
}

55
56 Milena VujosevicJanicic

main(){
int n,k;
printf("Unesite broj i poziciju tog broja koju zelite da promenite:\n")
scanf("%d%d",&n,&k);
printf("Binarno, une\v seni broj je\n");
print_bits(n);
printf("Novi broj je %d\n",(n |(1<<k)));
printf("Binarno, novi broj je\n");
print_bits((n |(1<<k)));
}

Izrazom a>>b vrsi se pomeranje sadrzaja operanda a predstavl-


jenog u binarnom obliku za b mesta u desno. Popunjavanje upraznjenih
mesta na levoj strani zavisi od tipa podataka i vrste racunara. Ako
se pomeranje primenjuje nad operandom tipa unsigned popunja-
vanje je nulama. Ako se radi o oznacenom operandu popunjavanje
je jedinicama kada je u krajnjem levom bitu jedinica, a nulama kada
je u krajnjem levom bitu nula.

Primer 1.28.5 sum of bits - izracunava sumu bitova datog neoznacenog


broja.
#include <stdio.h>

/* Pomocna funkcija - stampa bitove neoznacenog broja */


void print_bits(unsigned x)
{
int wl = sizeof(unsigned)*8;

unsigned mask;
for (mask = 1<<wl-1; mask; mask >>= 1)
putchar(x&mask ? 1 : 0);

putchar(\n);
}

int sum_of_bits(unsigned x)
{
int br;
for (br = 0; x; x>>=1)
if (x&1)
br++;

return br;

56
1.28 Bitski operatori 57

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

Izlaz iz programa:
Binarni zapis broja 127 je
00000000000000000000000001111111
Suma bitova broja 127 je 7
Binarni zapis broja 128 je
00000000000000000000000010000000
Suma bitova broja 128 je 1
Binarni zapis broja 0x00FF00FF je
00000000111111110000000011111111
Suma bitova broja 0x00FF00FF je 16
Binarni zapis broja 0xFFFFFFFF je
11111111111111111111111111111111
Suma bitova broja 0xFFFFFFFF je 32
Primer 1.28.6 get bits, set bits, invert bits - izdvajanje, postavl-
janje i invertovanje pojedinacnih bitova
#include <stdio.h>

/* Pomocna funkcija - stampa bitove neoznacenog broja */


void print_bits(unsigned x)
{
int wl = sizeof(unsigned)*8;

unsigned mask;
for (mask = 1<<wl-1; mask; mask >>= 1)

57
58 Milena VujosevicJanicic

putchar(x&mask ? 1 : 0);

putchar(\n);
}

/* Funkcija vraca n bitova broja x koji pocinju na poziciji p */


unsigned get_bits(unsigned x, int p, int n)
{
/* Gradimo masku koja ima poslednjih n jedinica
0000000...00011111
tako sto sve jedinice ~0 pomerimo u levo za n mesta
1111111...1100000
a zatim komplementiramo
*/
unsigned last_n_1 = ~(~0 << n);

/* x pomerimo u desno za odgovarajuci broj mesta, a zatim


konjunkcijom sa konstruisanom maskom obrisemo pocetne cifre */

return (x >> p+1-n) & last_n_1;


}

/* Funkcija vraca modifikovano x tako sto mu je izmenjeno n bitova


pocevsi od pozicije p i na ta mesta je upisano poslednjih n bitova
broja y */
unsigned set_bits(unsigned x, int p, int n, unsigned y)
{
/* Maska 000000...000111111 - poslednjih n jedinica */
unsigned last_n_1 = ~(~0 << n);

/* Maska 1111100..000111111 - n nula pocevsi od pozicije p */


unsigned middle_n_0 = ~(last_n_1 << p+1-n);

/* Brisemo n bitova pocevsi od pozicije p */


x = x & middle_n_0;

/* Izdvajamo poslednjih n bitova broja y i pomeramo ih


na poziciju p */
y = (y & last_n_1) << p+1-n;

/* Upisujemo bitove broja y u broj x i vracamo rezultat */


return x | y;
}

58
1.28 Bitski operatori 59

/* Invertuje n bitova broja x pocevsi od pozicije p */


unsigned invert_bits(unsigned x, int p, int n)
{
/* Maska 000000111...1100000 - n jedinica pocevsi od pozicije p */
unsigned middle_n_1 = ~(~0 << n) << p+1-n;

/* Invertujemo koristeci ekskluzivnu disjunkciju */


return x ^ middle_n_1;
}

main()
{
unsigned x = 0x0AA0AFA0;
print_bits(x);

print_bits(get_bits(x, 15, 8));


print_bits(set_bits(x, 15, 8, 0xFF));
print_bits(invert_bits(x, 15, 8));
}

Izlaz iz programa:
00001010101000001010111110100000
00000000000000000000000010101111
00001010101000001111111110100000
00001010101000000101000010100000
Primer 1.28.7 right rotate bits, mirror bits - rotiranje i simetrija
bitova.
#include <stdio.h>

/* Pomocna funkcija - stampa bitove neoznacenog broja */


void print_bits(unsigned x)
{
int wl = sizeof(unsigned)*8;

unsigned mask;
for (mask = 1<<wl-1; mask; mask >>= 1)
putchar(x&mask ? 1 : 0);

putchar(\n);
}

59
60 Milena VujosevicJanicic

/* Funkcija vrsi rotaciju neoznacenog broja x za n pozicija u desno */


unsigned right_rotate(unsigned x, int n)
{
int i;
int wl = sizeof(unsigned)*8;

/* Postupak se ponavlja n puta */


for (i = 0; i < n; i++)
{
/* Poslednji bit broja x */
unsigned last_bit = x & 1;

/* x pomeramo za jedno mesto u desno */


x >>= 1;

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

x |= last_bit<<wl-1;
}

return x;
}

/* Funkcija obrce binarni zapis neoznacenog broja x tako sto bitove


cita unatrag */
unsigned mirror(unsigned x)
{
int i;
int wl = sizeof(unsigned)*8;

/* Rezultat inicijalizujemo na poslednji bit broja x */


unsigned y = x & 1;

/* Postupak se ponavlja wl-1 puta */


for (i = 1; i<wl; i++)
{
/* x se pomera u desno za jedno mesto */
x >>= 1;
/* rezultat se pomera u levo za jedno mesto */
y <<= 1;

/* Poslednji bit broja x upisujemo na poslednje


mesto rezultata */

60
1.29 Linearna i binarna pretraga 61

y |= x & 1;
}
return y;
}

main()
{
unsigned x = 0xFAF0FAF0;
print_bits(x);
print_bits(mirror(x));
print_bits(right_rotate(x, 2));
}

Izlaz iz programa:
11111010111100001111101011110000
00001111010111110000111101011111
00111110101111000011111010111100

1.29 Linearna i binarna pretraga


Primer 1.29.1 Linearna pretraga
#include <stdio.h>

/* Funkcija proverava da li se dati element x nalazi


u datom nizu celih brojeva.
Funkcija vraca poziciju u nizu na
kojoj je x pronadjen
odnosno -1 ukoliko elementa nema.
*/
int linearna_pretraga(int niz[], int br_elem, int x)
{
int i;
for (i = 0; i<br_elem; i++)
if (niz[i] == x)
return i;
/* nikako else */

return -1;
}

main()
{

61
62 Milena VujosevicJanicic

/* Inicijalizacija niza moguca je


i na ovaj nacin*/
int a[] = {4, 3, 2, 6, 7, 9, 11};

/* Da bi smo odredili koliko clanova


ima niz mozemo koristiti operator
sizeof*/
int br_elem = sizeof(a)/sizeof(int);
int x;
int i;
printf("Unesite broj koji trazimo : ");
scanf("%d",&x);

i = linearna_pretraga(a, br_elem, x);


if (i == -1)
printf("Element %d nije nadjen\n",x);
else
printf("Element %d je nadjen na
poziciji %d\n",x, i);
}
Primer 1.29.2 Binarna pretraga niza
/* Binarna pretraga niza celih brojeva - iterativna verzija*/
#include <stdio.h>

/* Funkcija proverava da li se element x javlja unutar niza


celih brojeva a.
Funkcija vraca poziciju na kojoj je element nadjen odnosno
-1 ako ga nema.

!!!!! VAZNO !!!!!


Pretpostavka je da je niz a uredjen po velicini
*/

int binarna_pretraga(int a[], int n, int x)


{
/* Pretrazujemo interval [l, d] */
int l = 0;
int d = n-1;

/* Sve dok interval [l, d] nije prazan */


while (l <= d)
{

62
1.30 Razni zadaci 63

/* Srednja pozicija intervala [l, d] */


int s = (l+d)/2;

/* Ispitujemo odnos x i a[srednjeg elementa] */


if (x == a[s])
/* Element je pronadjen */
return s;
else if (x < a[s])
{
/* Pretrazujemo interval [l, s-1] */
d = s-1;
}
else
{
/* Pretrazujemo interval [s+1, d] */
l = s+1;
}
}

/* Element je nadjen */
return -1;
}

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

printf("Unesi element kojega trazimo : ");


scanf("%d",&x);
i = binarna_pretraga(a, sizeof(a)/sizeof(int), x);

if (i==-1)
printf("Elementa %d nema\n", x);
else
printf("Pronadjen na poziciji %d\n", i);
}

1.30 Razni zadaci


Primer 1.30.1 Obrtanje stringa i pretvaranje broja u string

63
64 Milena VujosevicJanicic

#include <stdio.h>
#include <string.h>

/* reverse: obrce string, npr string "1234" postaje "4321" */


void reverse(char s[])
{
int c, i, j;

for (i = 0, j = strlen(s)-1; i < j; i++, j--)


{
c = s[i];
s[i] = s[j];
s[j] = c;
}
}

/* itoa: konvertuje broj n u niz karaktera s */


void itoa(int n, char s[])
{
int i, sign;

if ((sign = n) < 0) /* sacuvaj znak */


n = -n; /* napravi da je n pozitivno */
i = 0;
do {
/* generisanje cifara u obrnutom smeru */
s[i++] = n % 10 + 0; /* izracunaj sledecu cifru */
} while ((n /= 10) > 0); /* izbaci cifru iz zapisa */
if (sign < 0)
s[i++] = -;
s[i] = \0;
reverse(s);
}

main()
{
int n=-44;
char nst[100];
itoa(n,nst);
printf("%s\n",nst);
}

Primer 1.30.2 btoi - konverzija iz datog brojnog sistema u dekadni.

64
1.30 Razni zadaci 65

#include <stdio.h>
#include <ctype.h>

/* Pomocna funkcija koja izracunava vrednost


koju predstavlja karakter u datoj osnovi
Funkcija vraca -1 ukoliko cifra nije validna.

Npr.
cifra B u osnovi 16 ima vrednost 11
cifra 8 nije validna u osnovi 6
*/

int digit_value(char c, int base)


{
/* Proveravamo obicne cifre */
if (isdigit(c) && c < 0+base)
return c-0;

/* Proveravamo slovne cifre za mala slova */


if (a<=c && c < a+base-10)
return c-a+10;

/* Proveravamo slovne cifre za velika slova */


if (A<=c && c < A+base-10)
return c-A+10;

return -1;
}

/* Funkcija izracunava vrednost celog broja koji je zapisan u datom


nizu karaktera u datoj osnovi. Za izracunavanje se koristi
Hornerova shema.
*/
int btoi(char s[], int base)
{
int sum = 0;

/* Obradjuju se karakteri sve dok su to validne cifre */


int i, vr;
for (i = 0; (vr = digit_value(s[i], base)) != -1; i++)
sum = base*sum + vr;

return sum;

65
66 Milena VujosevicJanicic

main()
{
char bin[] = "11110000";
char hex[] = "FF";

printf("Dekadna vrednost binarnog broja %s je %d\n", bin, btoi(bin, 2));


printf("Dekadna vrednost heksadekadnog
broja %s je %d\n", hex, btoi(hex, 16));
}
Primer 1.30.3 Ucitava linije sa ulaza i pamti najduzu liniju.
#include <stdio.h>
#define MAXLINE 1000 /* maximum input line length */

int getline(char line[], int maxline);


void copy(char to[], char from[]);

/* print the longest input line */


main()
{
int len; /* current line length */
int max; /* maximum length seen so far */
char line[MAXLINE]; /* current input line */
char longest[MAXLINE]; /* longest line saved here */

max = 0;
while ((len = getline(line, MAXLINE)) > 0)
if (len > max) {
max = len;
copy(longest, line);
}
if (max > 0) /* there was a line */
printf("%s", longest);
}

/* getline: read a line into s, return length */


int getline(char s[],int lim)
{
int c, i;

for (i=0; i < lim-1

66
1.30 Razni zadaci 67

&& (c=getchar())!=EOF && c!=\n;++i)


s[i] = c;
if (c == \n) {
s[i] = c;
++i;
}
s[i] = \0;
return i;
}

/* copy: copy from into to;


assume to is big enough */
void copy(char to[], char from[])
{
int i;

i = 0;
while ((to[i] = from[i]) != \0)
++i;
}

Primer 1.30.4 Konvertovanje stringa u broj u pokretnom zarezu.


#include <ctype.h>
#include <stdio.h>
#define MAXLINE 100

/* getline: get line into s, return length */


int getline(char s[], int lim)
{
int c, i;

i = 0;
while (--lim > 0 && (c=getchar()) != EOF && c != \n)
s[i++] = c;
if (c == \n)
s[i++] = c;
s[i] = \0;
return i;
}

/* atof: convert string s to double */


double atof(char s[])

67
68 Milena VujosevicJanicic

{
double val, power;
int i, sign;

/* skip white space */


for (i = 0; isspace(s[i]); i++)
;
/* Postavlja se znak broja*/
sign = (s[i] == -) ? -1 : 1;

/* Preskace se jedno mesto ukoliko je bio upisan znak u broj*/


if (s[i] == + || s[i] == -)
i++;

/* Racuna se vrednost broja dok se ne naidje na tacku */


for (val = 0.0; isdigit(s[i]); i++)
val = 10.0 * val + (s[i] - 0);

if (s[i] == .)
i++;

/* Racuna se vrednost broja iza tacke*/


for (power = 1.0; isdigit(s[i]); i++)
{
val = 10.0 * val + (s[i] - 0);
power *= 10;
}
return sign * val / power;
}

/* Program sabira brojeve u pokretnom zarezu koji se unose sa ulaza*/


main()
{
double sum;
char line[MAXLINE];

sum = 0;
while (getline(line, MAXLINE) > 0)
printf("\t%g\n", sum += atof(line));
}

Primer 1.30.5 Funkcija koja uklanja znak c kad god se pojavi u


stringu s.

68
1.30 Razni zadaci 69

#include <stdio.h>

void squeeze(char s[], char c)


{
int i,j;
for(i=j=0; s[i]!=\0;i++)
if(s[i]!=c) s[j++]=s[i];
s[j]=\0;
}

main()
{
char niz[20];
char c;

printf("Unesi karakter\n\n");
scanf("%c", &c);

scanf("%s", niz);
squeeze(niz, c);
printf("%s\n", niz);
}

69
Osnovi programiranja
Programski jezik C
Zadaci sa vezbi, drugi semestar

Milena Vujosevic - Janicic 2005/2006


2

2
Sadrzaj

1 Programski jezik C 7
1.1 Sortiranje . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2 Rekurzija . . . . . . . . . . . . . . . . . . . . . . . . 18
1.3 Zivotni vek i oblast vazenja promenjivih, staticke promenljive 21
1.4 Pokazivaci . . . . . . . . . . . . . . . . . . . . . . . . 24
1.5 Pokazivaci i argumenti funkcija . . . . . . . . . . . . 26
1.6 Pokazivaci i nizovi (polja) . . . . . . . . . . . . . . . 28
1.7 Alokacija memorije . . . . . . . . . . . . . . . . . . . 35
1.8 Niz pokazivaca . . . . . . . . . . . . . . . . . . . . . 37
1.9 Pokazivaci na funkcije . . . . . . . . . . . . . . . . . 39
1.10 Matrice . . . . . . . . . . . . . . . . . . . . . . . . . 40
1.11 Strukture . . . . . . . . . . . . . . . . . . . . . . . . 47
1.11.1 Operator typedef . . . . . . . . . . . . . . . . 50
1.12 qsort . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
1.13 Sortiranje genericka funkcija . . . . . . . . . . . . 59
1.14 qSort funkcija iz standardne biblioteke . . . . . . . . 66
1.15 Genericko sortiranje reci . . . . . . . . . . . . . . . . 68
1.16 Argumenti komandne linije . . . . . . . . . . . . . . . 71
1.17 Datoteke . . . . . . . . . . . . . . . . . . . . . . . . . 72
1.18 Liste . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
1.18.1 Red . . . . . . . . . . . . . . . . . . . . . . . 78
1.18.2 Kruzna lista . . . . . . . . . . . . . . . . . . . 86
1.18.3 Stek . . . . . . . . . . . . . . . . . . . . . . . 87
1.18.4 Dvostruko povezane liste . . . . . . . . . . . . 92
1.19 Drvo . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
1.20 Grafovi . . . . . . . . . . . . . . . . . . . . . . . . . . 112
1.21 Razno . . . . . . . . . . . . . . . . . . . . . . . . . . 117

3
4 SADRZAJ

4
Predgovor

Ovo je prateci materijal za vezbe koje drzim iz predmenta Osnovi


programiranja. On ne moze zameniti poha anje vezbi niti koriscenje
druge preporucene literature.
Veliki deo materijala cine zadaci i resenja mr Filipa Marica (raspolozivi
na www.matf.bg.ac.yu/~filip/pp/0405/index.pl). Tako e koriscen
je i materijal sa sajta koleginice Jelene Grmuse www.matf.bg.ac.yu/~jelenagr
i kolege Miroslava Marica www.matf.bg.ac.yu/~maricm. Tekstovi
i objasnjenja su uglavnom zasnovani na knjizi Programski jezik C,
autora Kerninghan & Ritchie
Zahvaljujem svojim studentima na aktivnom ucescu u nastavi
cime su mi pomogli u uoblicavanju ovog materijala.
Svi komentari i sugestije vezane za ovaj materijal bice veoma
dobrodosli.

Milena Vujosevic-Janicic
www.matf.bg.ac.yu/~milena

5
6 SADRZAJ

6
Glava 1

Programski jezik C

1.1 Sortiranje
Primer 1.1.1 U prvom prolazu se razmenjuju vrednosti a[0] sa onim
clanovima ostatka niza koji su veci od njega. Na taj nacin ce se posle
prvog prolaza kroz niz a[0] postaviti na najveci element niza.

#include<stdio.h>
#define MAXDUZ 100

int main()
{
/* Niz od maksimalno MAXDUZ elemenata*/
int a[MAXDUZ];

/* Dimenzija niza, pomocna i brojacke promenljive */


int n,pom,i,j;

printf("Unesite dimenziju niza\n");


scanf("%d",&n);

if (n>MAXDUZ)
{
printf("Nedozvoljena vrednost za n\n");
exit(1);
}

/* Unos clanova niza */


for(i=0; i<n; i++)
{
printf("Unesite %d. clan niza\n",i+1);

7
8 Milena VujosevicJanicic

scanf("%d",&a[i]);
}

/*Sortiranje*/
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(a[i]<a[j])
{
pom=a[i];
a[i]=a[j];
a[j]=pom;
}

/* Ispis niza */
printf("Sortirani niz:\n");
for(i=0; i<n; i++)
printf("%d\t",a[i]);

putchar(\n);

return 0;

}
Primer 1.1.2 sort2
Modifikacija prethodnog resenja radi dobijanja na efikasnosti. Ne
vrse se zamene svaki put vec samo jednom, kada se prona e odgo-


varajuci element u nizu sa kojim treba izvrsiti zamenu tako da u nizu


bude postavljen trenutno najveci element na odgovarajuce mesto.
#include<stdio.h>
#define MAXDUZ 100

int main()
{

/* Niz od maksimalno MAXDUZ elemenata*/


int a[MAXDUZ];

/* Dimenzija niza, indeks najveceg elementa


u i-tom prolazu,pomocna i brojacke promenljive */
int n,ind,pom,i,j;

printf("Unesite dimenziju niza\n");

8
1.1 Sortiranje 9

scanf("%d",&n);

if (n>MAXDUZ)
{
printf("Nedozvoljena vrednost za n\n");
exit(1);
}

/* Unos clanova niza */


for(i=0; i<n; i++)
{
printf("Unesite %d. clan niza\n",i+1);
scanf("%d",&a[i]);
}

/*Sortiranje - bez stalnih zamena vec se


pronalazi indeks trenutno najveceg clana niza*/
for(i=0; i<n-1; i++)
{
for(ind=i,j=i+1; j<n; j++)
if(a[ind]<a[j])
ind=j;

/* Vrsi se zamena onda kada na i-tom mestu


nije najveci element. Tada se na i-to mesto
postavlja najveci element koji se nalazio na
mestu ind. */
if(i != ind)
{
pom=a[ind];
a[ind]=a[i];
a[i]=pom;
}
}
/* Ispis niza */
printf("Sortirani niz:\n");
for(i=0; i<n; i++)
printf("%d\t",a[i]);

return 0;

9
10 Milena VujosevicJanicic

Primer 1.1.3 bbsort1


Algoritam sortiranja buble sort poredi dva susedna elementa niza i
ako su pogresno raspore eni zamenjuje im mesta. Posle pore enja
 

svih susednih parova najmanji od njih ce isplivati na kraj niza. Zbog


toga se ovaj metod naziva metod mehurica. Da bi se najmanji broj
nesortiranog dela niza doveo na svoje mesto treba ponoviti postupak.

#include<stdio.h>
#define MAXDUZ 100

int main()
{
/* Dimenzija niza, pomocna promenljiva
i brojacke promenljive */
int n,pom,i,j;

/* Niz od maksimalno MAXDUZ elemenata*/


int a[MAXDUZ];

printf("Unesite dimenziju niza\n");


scanf("%d",&n);

if (n>MAXDUZ)
{
printf("Nedozvoljena vrednost za n\n");
exit(1);
}

/* Unos clanova niza */


for(i=0; i<n; i++)
{
printf("Unesite %d. clan niza\n",i+1);
scanf("%d",&a[i]);
}

/*Sortiranje */
for(i=n-1; i>0; i--)
for(j=0; j<i; j++)
if(a[j]<a[j+1])
{
pom=a[j];
a[j]=a[j+1];
a[j+1]=pom;

10
1.1 Sortiranje 11

/* Ispis niza */
printf("Sortirani niz:\n");
for(i=0; i<n; i++)
printf("%d\t",a[i]);

/* Stampa prazan red */


putchar(\n);

/*Regularan zavrsetak rada programa */


return 0;

}
Primer 1.1.4 bbsort2
Unapredjujemo prethodni algoritam kako bismo obezbedli da se ne
vrse provere onda kada je niz vec sortiran nego da se u tom slucaju
prekine rad.
#include<stdio.h>
#define MAXDUZ 100

int main()
{
/* Dimenzija niza, pomocna promenljiva
i brojacke promenljive */
int n,pom,i,j;

/* Niz od maksimalno MAXDUZ elemenata*/


int a[MAXDUZ];

/* Promenljiva koja govori da li je izvrsena


zamena u i-tom prolazu kroz niz pa ako nije
sortiranje je zavrseno jer su svaka dva
susedna elementa niza u odgovarajucem poretku */
int zam;

printf("Unesite dimenziju niza\n");


scanf("%d",&n);

if (n>MAXDUZ)
{
printf("Nedozvoljena vrednost za n\n");

11
12 Milena VujosevicJanicic

exit(1);
}

/* Unos clanova niza */


for(i=0; i<n; i++)
{
printf("Unesite %d. clan niza\n",i+1);
scanf("%d",&a[i]);
}

/*Sortiranje */
for(zam=1,i=n-1; zam && i>0; i--)
for(zam=0,j=0; j<i; j++)
if(a[j]<a[j+1])
{
/* Zamena odgovarajucih clanova niza */
pom=a[j];
a[j]=a[j+1];
a[j+1]=pom;

/* Posto je u i-tom prolazu


izvrsena bar ova zamena zam
se postavlja na 1 sto
nastavlja sortiranje */
zam=1;
}

/* Ispis niza */
printf("Sortirani niz:\n");
for(i=0; i<n; i++)
printf("%d\t",a[i]);

return 0;

}
Primer 1.1.5 isort
Insert sort, u svakom trenutku je pocetak niza sortiran a sortiranje
se vrsi tako sto se jedan po jedan element niza sa kraja ubacuje na
odgovarajuce mesto.
#include<stdio.h>
#define MAXDUZ 100

12
1.1 Sortiranje 13

int main()
{
/* Dimenzija niza, pomocna
i brojacke promenljive */
int n,pom,i,j;

/* Niz od maksimalno MAXDUZ elemenata*/


int a[MAXDUZ];

printf("Unesite dimenziju niza\n");


scanf("%d",&n);

if (n>MAXDUZ)
{
printf("Nedozvoljena vrednost za n!\n");
exit(1);
}

/* Unos clanova niza */


for(i=0; i<n; i++)
{
printf("Unesite %d. clan niza\n",i+1);
scanf("%d",&a[i]);
}

/*Sortiranje*/
for(i=1; i<n; i++)
for(j=i; (j>0) && (a[j]>a[j-1]); j--)
{
pom=a[j];
a[j]=a[j-1];
a[j-1]=pom;
}

/* Ispis niza */
printf("Sortirani niz:\n");
for(i=0; i<n; i++)
printf("%d\t",a[i]);

putchar(\n);
return 0;
}

13
14 Milena VujosevicJanicic

Primer 1.1.6 Binarno pretrazivanje

#include<stdio.h>
#define MAXDUZ 100

int main()
{
/* Dimenzija niza,pomocna i brojacke
promenljive */
int n,pom,i,j;

/* Niz od maksimalno MAXDUZ elemenata*/


int a[MAXDUZ];

/* Elemet koji se trazi i pozicija


na kojoj se nalazi- ukoliko je u nizu*/
int x,pozicija;

/* Pomocne promenljive za pretragu */


int donji, gornji, srednji;

printf("Unesite dimenziju niza\n");


scanf("%d",&n);

/* Unos clanova niza */


for(i=0; i<n; i++)
{
printf("Unesite %d. clan niza\n",i+1);
scanf("%d",&a[i]);
}

/*Sortiranje*/
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(a[i]>a[j])
{
pom=a[i];
a[i]=a[j];
a[j]=pom;
}
/* Unos elementa binarne pretrage */
printf("Unesite element koji se trazi\n");
scanf("%d",&x);

14
1.1 Sortiranje 15

donji = 0;
gornji = n-1;
pozicija = -1;

while(donji<=gornji)
{
srednji = (donji + gornji)/2;
if(a[srednji] == x)
{
pozicija = srednji;
break;
}
else
if(a[srednji] < x)
donji = srednji + 1;
else
gornji = srednji -1;
}

/* Ispis rezultata */
if(pozicija == -1)
printf("Trazeni broj se ne nalazi u nizu!\n");
else
printf("Broj %d se nalazi na %d poziciji
sortiranog niza! \n",x,pozicija+1);

putchar(\n);

return 0;
}
Primer 1.1.7 Sabiranje dva velika broja, njihovo pore enje, unos i


ispis, mnozenje velikog broja cifrom.

#include<stdio.h>
#define MAXDUZ 1000

int unos_broja(int cifre[], int maxduz)


{
int brcifara=0;
char c;

15
16 Milena VujosevicJanicic

c=getchar();
while ( brcifara < maxduz && c >= 0 && c <= 9)
{
cifre[brcifara++]=c-0;
c=getchar();
}

return brcifara;
}

void obrni(int cifre[],int brcifara)


{
int i,pom;

for (i=0; i<brcifara/2; i++)


{
pom=cifre[i];
cifre[i]=cifre[brcifara-i-1];
cifre[brcifara-i-1]=pom;
}
}

void ispisi(int cifre[],int brcifara)


{ int i;
putchar(\n);
for (i=brcifara-1; i>=0; i--)
printf("%d",cifre[i]);
/* ili
putchar(cifre[i]+0);
*/
putchar(\n);
}

int jednaki(int cifre1[],int cifre2[],


int brcifara1, int brcifara2)
{
int i;
if (brcifara1 != brcifara2) return 0;

for (i=0; i<brcifara1; i++)


if (cifre1[i] != cifre2[i]) return 0;
return 1;

16
1.1 Sortiranje 17

int veci(int cifre1[], int brcifara1,


int cifre2[], int brcifara2)
{
int i;
if (brcifara1>brcifara2) return 1;
if (brcifara1<brcifara2) return 0;

for (i=brcifara1-1; i>=0; i--)


{
if (cifre1[i]<cifre2[i]) return 0;
if (cifre1[i]>cifre2[i]) return 1;
}

return 0;
}

int saberi(int cifre1[], int brcifara1,


int cifre2[], int brcifara2,
int cifre[])
{
int brcifara=0;
int i,pom,pamtim=0;

for(i=0; i<brcifara1 || i<brcifara2; i++)


{
pom =((i < brcifara1)? cifre1[i] : 0 )
+((i < brcifara2)? cifre2[i] : 0)
+ pamtim;

cifre[i] = pom%10;
pamtim = pom/10;
}
if (pamtim)
{
cifre[i]=pamtim;
brcifara=i+1;
}
else brcifara=i;

17
18 Milena VujosevicJanicic

return brcifara;
}

int pomnozic(int c,int cifre[],


int brcifara, int pcifre[])
{
int pbrcifara=0;
int i,pamtim=0;
for (i=0; i<brcifara; i++)
{
pcifre[i]=(cifre[i]*c+pamtim)%10;
pamtim=(cifre[i]*c+pamtim)/10;
}
pbrcifara=brcifara;
if (pamtim)
{
pcifre[pbrcifara]=pamtim;
pbrcifara++;
}

return pbrcifara;
}

int main()
{
int d1,d2,d;
int broj1[MAXDUZ], broj2[MAXDUZ], zbir[MAXDUZ];
d1=unos_broja(broj1,MAXDUZ);
d2=unos_broja(broj2,MAXDUZ);

obrni(broj1,d1);
obrni(broj2,d2);
d=saberi(broj1,d1,broj2,d2,zbir);
ispisi(zbir,d);
return 0;
}

1.2 Rekurzija
C funkcije se mogu rekurzivno koristiti, sto znaci da funkcija moze
pozvati samu sebe direktno ili indirektno.

18
1.2 Rekurzija 19

Primer 1.2.1 Stampanje celog broja.


#include<stdio.h>
void printb(long int n)
{
if(n<0)
{
putchar(-);
n=-n;
}
if(n/10)
printb(n/10);
putchar(n % 10 + 0);
}

int main()
{
long int b=-1234;
printb(b);
putchar(\n);
return 0;
}
Kad funkcija rekurzivno pozove sebe, svakim pozivom pojavljuje
se novi skup svih automatskih promenljivih, koji je nezavisan od
prethodonog skupa. Prva funkcija printb kao argument dobija broj
-12345, ona prenosi 1234 u drugu printb funkciju, koja dalje prenosi
123 u trecu, i tako redom do poslednje koja prima 1 kao argument.
Ta funkcija stampa 1 i zavrsava sa radom tako da se vraca na
prethodni nivo, na kome se stampa dva i tako redom.
Primer 1.2.2 Racunanje sume prvih n prirodnih brojeva.
#include<stdio.h>
int suma(int n)
{
if(n!=0)
return( n + suma(n-1) );
else return n;
}

main()
{
int S,n;
printf("Unesite n\n");

19
20 Milena VujosevicJanicic

scanf("%d",&n);
S=suma(n);
printf("S=%d",S);
putchar(\n);
}

Primer 1.2.3 Racunanje faktorijela prirodnog broja.


#include<stdio.h>
unsigned long fakt(int n)
{
if(n!=0)
return( n*fakt(n-1) );
else return 1;
}

main()
{
int n;
unsigned long f;
printf("Unesite n\n");
scanf("%d",&n);
f=fakt(n);
printf("f=%d",f);
putchar(\n);
}

Primer 1.2.4 Fibonacijevi brojevi.


#include<stdio.h>
int fibr(int n)
{
if((n==1)||(n==2))
return 1;
else return(fibr(n-1)+fibr(n-2));
}

int main()
{
int Fn,n;
printf("Unesite n\n");
scanf("%d",&n);
Fn=fibr(n);
printf("F[%d]=%d",n,Fn);

20
1.3 Zivotni vek i oblast vazenja promenjivih, staticke promenljive 21

putchar(\n);
return 0;
}

Primer 1.2.5 Iterativna i rekurzivna varijanta racunanja sume niza.


int suma_niza_iterativno(int a[], int n)
{
int suma = 0;
int i;
for (i = 0; i<n; i++)
suma+=a[i];
return suma;
}

int suma_niza(int a[], int n)


{
if (n == 1)
return a[0];
else
return suma_niza(a, n-1)+a[n-1];
}

Primer 1.2.6 Stepenovanje prirodnog broja


int stepenuj (int n, int k)
{
if (k == 0)
return 1;
else
return n*stepenuj(n, k-1);
}

1.3 Zivotni vek i oblast vazenja promenjivih, staticke


promenljive
Primer 1.3.1 Demonstracija zivotnog veka i oblasti vazenja promen-
jivih (scope).

#include <stdio.h>

/* Globalna promenjiva */
int a = 0;

21
22 Milena VujosevicJanicic

/* Uvecava se globalna promenjiva a */


void increase()
{
a++;
printf("increase::a = %d\n", a);
}

/* Umanjuje se lokalna promenjiva a.


Globalna promenjiva zadrzava svoju vrednost. */
void decrease()
{
/* Ovo a je nezavisna promenjiva u odnosu na globalno a */
int a = 0;
a--;
printf("decrease::a = %d\n", a);

void nonstatic_var()
{
/* Nestaticke promenjive ne cuvaju vrednosti kroz pozive funkcije */
int s=0;
s++;
printf("nonstatic::s=%d\n",s);
}

void static_var()
{
/* Staticke promenjive cuvaju vrednosti kroz pozive funkcije.
Inicijalizacija se odvija samo u okviru prvog poziva. */
static int s=0;
s++;
printf("static::s=%d\n",s);
}

main()
{
/* Promenjive lokalne za funkciju main */
int i;
int x = 3;

printf("main::x = %d\n", x);

22
1.3 Zivotni vek i oblast vazenja promenjivih, staticke promenljive 23

for (i = 0; i<3; i++)


{
/* Promenjiva u okviru bloka je nezavisna od spoljne promenjive.
Ovde se koristi promenjiva x lokalna za blok petlje koja ima
vrednost 5, dok originalno x i dalje ima vrednost 3*/
int x = 5;
printf("for::x = %d\n", x);
}

/* U ovom bloku x ima vrednost 3 */


printf("main::x = %d\n", x);

increase();
decrease();

/* Globalna promenjiva a */
printf("main::a = %d\n", a);

/* Demonstracija nestatickih promenjivih */


for (i = 0; i<3; i++)
nonstatic_var();

/* Demonstracija statickih promenjivih */


for (i = 0; i<3; i++)
static_var();
}

Izlaz iz programa:
main::x = 3
for::x = 5
for::x = 5
for::x = 5
main::x = 3
increase::a = 1
decrease::a = -1
main::a = 1
nonstatic::s=1
nonstatic::s=1
nonstatic::s=1
static::s=1
static::s=2
static::s=3

23
24 Milena VujosevicJanicic

Primer 1.3.2 Ilustracija statickih promenljivih.


#include <stdio.h>

void f()
{
static int a;
a++;
printf("%d\n",a);
}

main()
{
int i;
for (i=0; i<=10; i++)
f();
}

/* Izlaz iz programa 1 2 3 4 5 6 7 8 9 10 11*/

1.4 Pokazivaci
Pokazivac je promenljiva koja sadrzi adresu promenljive.

int x=1, y=1, z[10];


int *ip; /* ip je pokazivac na int,
odnosno *ip je tipa int*/

ip = &x; /* ip sada pokazuje na x */


y=*ip; /* y je sada 1 */
*ip = 0; /* x je sada 0 */

*ip+=10; /* x je sada 10*/


++*ip; /* x je sada 11*/
(*ip)++; /* x je sada 12,
zagrada neophodna zbog prioriteta
operatora*/

ip = &z[0]; /* ip sada pokazuje na z[0]*/

Primer 1.4.1 Ilustracija rada sa pokazivackim promenljivim.


#include <stdio.h>
main()

24
1.4 Pokazivaci 25

{
int x = 3;

/* Adresu promenjive x zapamticemo u novoj promeljivoj.


Nova promenljiva je tipa pokazivaca na int (int*) */
int* px;

printf("Adresa promenljive x je : %p\n", &x);


printf("Vrednost promenljive x je : %d\n", x);

px = &x;
printf("Vrednost promenljive px je (tj. px) : %p\n", px);
printf("Vrednost promenljive na koju ukazuje px (tj. *px) je : %d\n", *px);

/* Menjamo vrednost promenljive na koju ukazuje px */


*px = 6;
printf("Vrednost promenljive na koju ukazuje px (tj. *px) je : %d\n", *px);

/* Posto px sadrzi adresu promenljive x, ona ukazuje na x tako da je


posredno promenjena i vrednost promenljive x */
printf("Vrednost promenljive x je : %d\n", x);

Izlaz (u konkretnom slucaju):


Adresa promenljive x je : 0012FF88
Vrednost promenljive x je : 3
Vrednost promenljive px je (tj. px) : 0012FF88
Vrednost promenljive na koju ukazuje px (tj. *px) je : 3
Vrednost promenljive na koju ukazuje px (tj. *px) je : 6
Vrednost promenljive x je : 6
Pored pokazivaca na osnovne tipove, postoji i pokazivac na prazan
tip (void).
void *pp;
Njemu moze da se dodeli da pokazuje na int, ili na char ili na
proizvoljan tip ali je to neophodno eksplicitno naglasiti svaki put
kada zelimo da koristimo ono na sta on pokazuje.
Primer 1.4.2 Upotreba pokazivaca na prazan tip.
#include<stdio.h>

25
26 Milena VujosevicJanicic

main()
{
void *pp;
int x=2;
char c=a;

pp = &x;
*(int *)pp = 17; /* x postaje 17*/
printf("\n adresa od x je %p", &x);
printf("\n%d i %p",*(int*)pp,(int * )pp);

pp = &c;
printf("\n adresa od c je %p", &c);
printf("\n%c i %p",*(char*)pp,(char * )pp);

/*
adresa od x je 0012FF78
17 i 0012FF78
adresa od c je 0012FF74
a i 0012FF74
*/
Posebna konstanta koja se koristi da se oznaci da pokazivac ne
pokazuje na neko mesto u memoriji je NULL.

1.5 Pokazivaci i argumenti funkcija


C prosle uje argumente u funkcije pomocu vrednosti. To znaci da
sledeca funkcija nece uraditi ono sto zelimo:
void swap (int x, int y) /* POGRESNO!!!!!!!!*/
{
int temp;
temp = x;
x=y;
y=temp;
}
Zbog prenosa parametara preko vrednosti swap ne moze da utice
na argumente a i b u funkciji koja je pozvala swap. Ova swap
funkcija samo zamenjuje kopije od a i b.
Da bi se dobio zeljeni efekat, potrebno je da se proslede pokazivaci:

26
1.5 Pokazivaci i argumenti funkcija 27

/* Zameni *px i *py */


void swap (int *px, int *py)
{
int temp;
temp =*px;
*px = *py;
*py = temp;
}

a poziv funkcije swap izlgeda sada ovako


swap(&a, &b);

Primer 1.5.1 Demonstracija vise povratnih vrednosti funkcije ko-


risteci prenos preko pokazivaca.

/* Funkcija istovremeno vraca dve vrednosti - kolicnik i ostatak


dva data broja. Ovo se postize tako sto se funkciji predaju
vrednosti dva broja (x i y) koji se dele
i adrese dve promenljive na koje ce se smestiti rezultati */

void div_and_mod(int x, int y, int* pdiv, int* pmod)


{
printf("Kolicnik postavljam na adresu : %p\n", pdiv);
printf("Ostatak postavljam na adresu : %p\n", pmod);
*pdiv = x / y;
*pmod = x % y;
}

main()
{
int div, mod;
printf("Adresa promenljive div je %p\n", &div);
printf("Adresa promenljive mod je %p\n", &mod);

/* Pozivamo funkciju tako sto joj saljemo


vrednosti dva broja (5 i 2)
i adrese promenljvih div i mod na koje
ce se postaviti rezultati */
div_and_mod(5, 2, &div, &mod);

printf("Vrednost promenljive div je %d\n", div);


printf("Vrednost promenljive mod je %d\n", mod);

27
28 Milena VujosevicJanicic

Izlaz u konkretnom slucaju:


Adresa promenljive div je 0012FF88
Adresa promenljive mod je 0012FF84
Kolicnik postavljam na adresu : 0012FF88
Ostatak postavljam na adresu : 0012FF84
Vrednost promenljive div je 2
Vrednost promenljive mod je 1

1.6 Pokazivaci i nizovi (polja)


U C-u postoji cvrsta veza izme u pokazivaca i nizova. Bilo koja
operacija koja se moze ostvariti dopisivanjem indeksa niza moze se
uraditi i sa pokazivacima.
Deklaracija
int a[10];
definise niz a velicine 10 koji predstavlja blok od 10 uzastopnih
objekata nazvanih a[0], a[1], ..., a[9]. Notacija a[i] odgo-
vara i-tom elementu niza.
Ako je pa pokazivac na ceo broj
int *pa;
tada iskaz pa = &a[0];
podesava da pa pokaze na nulti element niza a, odnosno pa sadrzi
adresu od a[0].
Ako pa pokazuje na odre eni element polja, onda po definiciji
pa+1 pokazuje na sledeci element, pa+i pokazuje na i-ti element
posle pa. Stoga, ako pa pokazuje na a[0] tada
*(pa+1)
se odnosi na sadrzaj od a[1].
pa+i je adresa od a[i], a
*(pa+i)
je sadrzaj od a[i]. Dozvoljeno je upotrebljavati i sintaksu kao
kod nizova:
*(pa+i) <==> pa[i]
Ovo sve vazi bez obzira na tip ili velicinu elemenata u polju a.
Iskaz pa=&a[0] se moze napisati kao pa=a jer je ime niza
sinonim za lokaciju pocetnog elementa.

Primer 1.6.1 Veza izme u pokazivaca i nizova.




#include <stdio.h>

28
1.6 Pokazivaci i nizovi (polja) 29

void print_array(int* pa, int n);

main()
{
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int num_of_elements = sizeof(a)/sizeof(int);
int* pa;

/* Niz je isto sto i adresa prvog elementa */


printf("Niz a : %p\n", a);
printf("Adresa prvog elementa niza a (&a[0]) : %p\n", &a[0]);
/* Niz a : 0012FF5C
Adresa prvog elementa niza a (&a[0]) : 0012FF5C */

/* Moguce je dodeliti niz pokazivacu odgovarajuceg tipa */


pa = a;

printf("Pokazivac pa ukazuje na adresu : %p\n", pa);


/* Pokazivac pa ukazuje na adresu : 0012FF5C */

/* Nizu nije moguce dodeliti pokazivacku promenljivu


(nizove mozemo smatrati KONSTANTNIM pokazivacima na prvi element) */
/* a = pa; */

/* Pokazivace je dalje moguce indeksirati kao nizove */


printf("pa[0] = %d\n", pa[0]);
printf("pa[5] = %d\n", pa[5]);
/* pa[0] = 1
pa[5] = 6 */

/* Medjutim, sizeof(pa) je samo velicina pokazivaca, a ne niza */


printf("sizeof(a) = %d\n", sizeof(a));
printf("sizeof(pa) = %d\n", sizeof(pa));
/* sizeof(a) = 40
sizeof(pa) = 4 */

/* Pozivamo funkciju za stampanje niza i saljemo joj niz */


print_array(a, num_of_elements);
/* 1 2 3 4 5 6 7 8 9 10 */

/* Pozivamo funkciju za stampanje niza


i saljemo joj pokazivac na pocetak niza */
print_array(pa, num_of_elements);

29
30 Milena VujosevicJanicic

/* 1 2 3 4 5 6 7 8 9 10 */
}

/* Prosledjivanje niza u funkciju


void print_array(int pa[], int n);
je ekvivalentno prosledjivanju pokazivaca u funkciju
void print_array(int* pa, int n);
Izmedju ovih konstrukcija nema nikakve razlike!
*/
void print_array(int* pa, int n)
{
int i;
for (i = 0; i<n; i++)
printf("%d ", pa[i]);
putchar(\n);
}

Prilikom deklaracije treba praviti razliku izme u niza znakova i


pokazivaca:

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


char *pporuka = "danas je lep dan!";

poruka je niz znakova koji sadrzi dati tekst. Pojedine znake moguce
je promeniti ali se poruka uvek odnosi na isto mesto u memoriji.
pporuka je pokazivac, koji je inicijalizovan da pokazuje na kon-
stantnu nisku, on moze biti preusmeren da pokazuje na nesto drugo,
ali rezultat nece biti definisan ako pokusate da modifikujete sadrzaj
niske (jer je to konstantna niska).
Ako deklarisemo

char *pporuka1 = "danas je lep dan!";


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

tada ce pokazivaci pporuka1 i pporuka2 pokazivati na isto mesto u


memoriji, a pporuka3 na neko drugo mesto u memoriji.
Ako uporedimo (pporuka1==pporuka3) uporedice se vrednosti
pokazivaca. Ako uporedimo (pporuka1 < pporuka2) uporedice se
vrednosti pokazivaca. Ako dodelimo pporuka1=pporuka3 tada ce
pporuka1 dobiti vrednost pokazivaca pporuka3 i pokazivace na isto
mesto u memoriji. Nece se izvrsiti kopiranje sadrzaja memorije!!!

Primer 1.6.2 Vezba pokazivacke aritmetike.

30
1.6 Pokazivaci i nizovi (polja) 31

#include <stdio.h>

/* Funkcija pronalazi x u nizu niz date dimenzije,


bez koriscenja indeksiranja. Funkcija vraca pokazivac na
poziciju pronadjenog elementa. */

int* nadjiint(int* niz, int n, int x)


{
while (--n >= 0 && *niz!=x)
niz++;

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


}

main()
{
int a[]={1,2,3,4,5,6,7,8};
int* poz=nadjiint(a,sizeof(a)/sizeof(int),4);

if (poz!=NULL)
printf("Element pronadjen na poziciji %d\n",poz-a);
}
Primer 1.6.3
int strlen(char *s)
{
int n;
for(n=0; *s != \0; s++) n++;
return n;
}

Primer 1.6.4
/* Funkcija kopira string t u string s */
void copy(char* s, char* t)
{
while (*s++=*t++)
;
}

/* Ovo je bio skraceni zapis za sledeci kod


while(*t != \0)
{
*s=*t;

31
32 Milena VujosevicJanicic

s++;
t++;
}
*s = \0;

*/
Primer 1.6.5
/* Vrsi leksikografsko poredjenje dva stringa.
Vraca :
0 - ukoliko su stringovi jednaki
<0 - ukoliko je s leksikografski ispred t
>0 - ukoliko je s leksikografski iza t
*/
int string_compare1(char *s, char *t)
{
/* Petlja tece sve dok ne naidjemo
na prvi razliciti karakter */
for (; *s == *t; s++, t++)
if (*s == \0) /* Naisli smo na kraj
oba stringa, a nismo nasli razliku */
return 0;

/* *s i *t su prvi karakteri u kojima


se niske razlikuju.
Na osnovu njihovog odnosa,
odredjuje se odnos stringova */

return *s - *t;
}

/* Mozemo koristiti i sintaksu kao kod nizova */


int string_compare2(char *s, char *t) {
int i;
for (i = 0; s[i] == t[i]; i++)
if (s[i] == \0)
return 0;
return s[i] - t[i];
}
Primer 1.6.6 Pronalazi prvu poziciju karaktera c u stringu s, i
vraca pokazivac na nju, odnosno NULL ukoliko s ne sadrzi c.

32
1.6 Pokazivaci i nizovi (polja) 33

char* string_char(char *s, char c)


{
int i;
for (; *s; s++)
if (*s == c)
return s;

/* Nije nadjeno */
return NULL;
}

Primer 1.6.7 Pronalazi poslednju poziciju karaktera c u stringu s,


i vraca pokazivac na nju, odnosno NULL ukoliko s ne sadrzi c.
char* string_last_char(char *s, char c)
{
char *t = s;
/* Pronalazimo kraj stringa s */
while (*t++)
;

/* Krecemo od kraja i trazimo c unazad */


for (t--; t >= s; t--)
if (*t == c)
return t;

/* Nije nadjeno */
return NULL;
}

Primer 1.6.8
#include <stdio.h>

/* proverava da li se niska t nalazi unutar niske s*/


int sadrzi_string(char s[], char t[])
{
int i;
for (i = 0; s[i]; i++)
{
int j;
for (j=0, k=0; s[i+j]==t[j]; j++)
if (t[j+1]==\0)
return i;
}

33
34 Milena VujosevicJanicic

return -1;
}

/* Verzija funkcije strstr implementirane bez


koriscenja indeksiranja */
/* proverava da li se niska t nalazi unutar niske s*/
char* sadrzi_string_pok(char* s, char* t)
{
while(*s)
{
char *i, *j;
for (i = s, j = t; *i == *j; i++,j++)
if (*(j+1)==\0)
return s;
s++;
}
return NULL;
}

/* Cita liniju sa stadnardnog ulaza i


vraca njenu duzinu */
int getline(char* line, int max)
{
char *s=line;
int c;
while ( max-->0 && (c=getchar())!=\n && c!=EOF)
*s++ = c;

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

*s = \0;
return s - line;
}

main()
{
char rec[]="zdravo";
char linija[100];
while (getline(linija, 100))
if (sadrzi_string_pok(linija, rec))
printf("%s",linija);

34
1.7 Alokacija memorije 35

1.7 Alokacija memorije


void* malloc(size_t n) vraca pokazivac na n bajtova neinicijal-
izovane memorije ili NULL ukoliko zahtev ne moze da se ispuni.
Za njeno koriscenje neophodno je ukljuciti zaglavlje stdlib.h.
Osloba anje memorije - funkcija free.
Ne sme se koristiti nesto sto je vec oslobo eno, ne sme se dva
puta osloba ati ista memorija.
Primer 1.7.1
#include <stdio.h>
#include <stdlib.h>

main()
{
int n;
int i;
int *a;

printf("Unesi broj clanova niza : ");


scanf("%d", &n);

/* Kao da ste mogli da uradite


int a[n];
*/
a = (int*)malloc(n*sizeof(int));

/* Kad god se vrsi alokacija memorije mora se proveriti da li je ona


uspesno izvrsena!!! */
if (a == NULL)
{
printf("Nema slobodne memorije\n");
exit(1);
}

/* Od ovog trenutka a koristim kao obican niz */


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

/* Stampamo niz u obrnutom redosledu */

35
36 Milena VujosevicJanicic

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


printf("%d",a[i]);

/* Oslobadjamo memoriju*/
free(a);
}

Primer 1.7.2 Demonstracija funkcije calloc - funkcija inicijal-


izuje sadrzaj memorije na 0.

#include <stdio.h>
#include <stdlib.h>

main()
{
int *m, *c, i, n;

printf("Unesi broj clanova niza : ");


scanf("%d", &n);

/* Niz m NE MORA garantovano da ima sve nule */


m = malloc(n*sizeof(int));
if (m == NULL) {
printf("Greska prilikom alokacije memorije!\n");
exit(1);
}

/* Niz c MORA garantovano da ima sve nule */


c = calloc(n, sizeof(int));
if (c == NULL) {
printf("Greska prilikom alokacije memorije!\n");
free(m);
exit(1);
}
for (i = 0; i<n; i++)
printf("m[%d] = %d\n", i, m[i]);

for (i = 0; i<n; i++)


printf("c[%d] = %d\n", i, c[i]);

free(m);
free(c);
}

36
1.8 Niz pokazivaca 37

1.8 Niz pokazivaca


Primer 1.8.1
#include <stdio.h>
#include <stdlib.h>
main()
{
/* Niz od tri elemenata tipa int*/
int nizi[3];

/* Niz od tri elemenata tipa int*, dakle


niz od tri pokazivaca na int*/
int* nizip[3];

/* Alociramo memoriju za prvi element niza*/


nizip[0] = (int*) malloc(sizeof(int));
if (nizip[0] == NULL)
{
printf("Nema slobodne memorije\n");
exit(1);
}
/* Upisujemo u prvi element niza broj 5*/
*nizip[0] = 5;
printf("%d", *nizip[0]);

/* Alociramo memoriju za drugi element niza.


Drugi element niza pokazuje na niz od dva
elementa*/
nizip[1] = (int*) malloc(2*sizeof(int));
if (nizip[1] == NULL) {
printf("Nema slobodne memorije\n");
free(nizip[0]);
exit(1);
}

/* Pristupamo prvom elementu na koji pokazuje


pokazivac nizip[1]*/
*(nizip[1]) = 1;

/* Pristupamo sledecem elementu u nizu na koji pokazuje


nizip[1].
*/
*(nizip[1] + 1) = 2;

37
38 Milena VujosevicJanicic

printf("%d", nizip[1][1]);

/* Alociramo memoriju za treci element niza nizip. */


nizip[2] = (int*) malloc(sizeof(int));
if (nizip[2] == NULL) {
printf("Nema slobodne memorije\n");
free(nizip[0]);
free(nizip[1]);
exit(1);
}

*(nizip[2]) = 2;

printf("%d", *(nizip[2]));

free(nizip[0]);
free(nizip[1]);
free(nizip[2]);
}

Primer 1.8.2
#include <stdio.h>
#include <stdlib.h>
main()
{
/* Niz karaktera*/
char nizc[5];

/* Niz karaktera od cetiri elementa


(A, n, a, \0)*/
char nizcc[]="Ana";
printf("%s", nizcc);

/* Niz od tri pokazivaca. Prvi pokazuje na


nisku karaktera Kruska, drugi na nisku karaktera
Sljiva a treci na Ananas. */
char* nizcp[]={"Kruska", "Sljiva", "Ananas"};

printf("%s", nizcp[0]);
printf("%s", nizcp[1]);
printf("%s", nizcp[2]);
}

38
1.9 Pokazivaci na funkcije 39

1.9 Pokazivaci na funkcije


Primer 1.9.1 Program demonstrira upotrebu pokazivaca na funkcije.

#include <stdio.h>

int kvadrat(int n)
{
return n*n;
}

int kub(int n)
{
return n*n*n;
}

int parni_broj(int n)
{
return 2*n;
}

/* Funkcija izracunava sumu od 1 do n f(i),


gde je f data funkcija */
int sumiraj(int (*f) (int), int n)
{
int i, suma=0;
for (i=1; i<=n; i++)
suma += (*f)(i);

return suma;
}

main()
{
printf("Suma kvadrata brojeva od jedan do 3 je %d\n", sumiraj(kvadrat,3));
printf("Suma kubova brojeva od jedan do 3 je %d\n", sumiraj(kub,3));
printf("Suma prvih pet parnih brojeva je %d\n", sumiraj(parni_broj,5));
}
/*Izlaz:
Suma kvadrata brojeva od jedan do 3 je 14
Suma kubova brojeva od jedan do 3 je 36
Suma prvih pet parnih brojeva je 30
*/

39
40 Milena VujosevicJanicic

1.10 Matrice
Primer 1.10.1 Staticka alokacija prostora za matricu.
#include <stdio.h>

main()
{
int a[3][3] = {{0, 1, 2}, {10, 11, 12}, {20, 21, 22}};
int i, j;

/* Alternativni unos elemenata matrice


for(i=0; i<3; i++)
for(j=0; j<3; j++)
{
printf("a[%d][%d] = ", i, j);
scanf("%d", &a[i][j]);
}
*/

a[1][1] = a[0][0] + a[2][2];


/* a[1][1] = 0 + 22 = 22 */

printf("%d\n", a[1][1]); /* 22 */

/* Stampanje elemenata matrice*/


for(i=0; i<3; i++)
{
for(j=0; j<3; j++)
printf("%d\t", a[i][j]);
printf("\n");
}
}
Nama je potrebno da imamo vecu fleksibilnost, tj da se dimenzije
matrice mogu uneti kao parametri naseg programa. Zbog toga je
neophodno koristiti dinamicku alokaciju memorije.
Primer 1.10.2 Implementacija matrice preko niza.
#include <stdlib.h>
#include <stdio.h>

/* Makro pristupa clanu na poziciji i, j matrice koja ima


m vrsta i n kolona */

40
1.10 Matrice 41

#define a(i,j) a[(i)*n+(j)]

main()
{
/* Dimenzije matrice */
int m, n;

/* Matrica */
int *a;

int i,j;

/* Suma elemenata matrice */


int s=0;

/* Unos i alokacija */
printf("Unesi broj vrsta matrice : ");
scanf("%d",&m);

printf("Unesi broj kolona matrice : ");


scanf("%d",&n);

a=malloc(m*n*sizeof(int));
if (a == NULL) {
printf("Greska prilikom alokacije memorije!\n");
exit(1);
}

for (i=0; i<m; i++)


for (j=0; j<n; j++)
{
printf("Unesi element na poziciji (%d,%d) : ",i,j);
scanf("%d",&a(i,j));
}

/* Racunamo sumu elemenata matrice */


for (i=0; i<m; i++)
for (j=0; j<n; j++)
s+=a(i,j);

/* Ispis unete matrice */


printf("Uneli ste matricu : \n");
for (i=0; i<m; i++)

41
42 Milena VujosevicJanicic

{ for (j=0; j<n; j++)


printf("%d ",a(i,j));
printf("\n");
}

printf("Suma elemenata matrice je %d\n", s);

/* Oslobadjamo memoriju */
free(a);
}
Primer 1.10.3 Program ilustruje rad sa kvadratnim matricama i
relacijama. Elementi i je u relaciji sa elementom j ako je m[i][j] =
1, a nisu u relaciji ako je m[i][j] = 0.
#include <stdlib.h>
#include <stdio.h>

/* Dinamicka matrica je odredjena adresom


pocetka niza pokazivaca i dimenzijama tj.
int** a;
int m,n;
*/

/* Alokacija kvadratne matrice nxn */


int** alociraj(int n)
{
int** m;
int i;
m=malloc(n*sizeof(int*));
if (m == NULL) {
printf("Greska prilikom alokacije memorije!\n");
exit(1);
}

for (i=0; i<n; i++)


{
m[i]=malloc(n*sizeof(int));
if (m[i] == NULL)
{
int k;
printf("Greska prilikom alokacije memorije!\n");
for(k=0;k<i;k++)
free(m[k]);

42
1.10 Matrice 43

free(m);
exit(1);
}
}

return m;
}

/* Dealokacija matrice dimenzije nxn */


void obrisi(int** m, int n)
{
int i;
for (i=0; i<n; i++)
free(m[i]);
free(m);
}

/* Ispis matrice /
void ispisi_matricu(int** m, int n)
{
int i, j;
for (i=0; i<n; i++)
{
for (j=0; j<n; j++)
printf("%d ",m[i][j]);
printf("\n");
}
}

/* Provera da li je relacija predstavljena matricom refleksivna */


int refleksivna(int** m, int n)
{
int i;
for (i=0; i<n; i++)
if (m[i][i]==0)
return 0;

return 1;
}

/* Provera da li je relacija predstavljena matricom simetricna */


int simetricna(int** m, int n)
{

43
44 Milena VujosevicJanicic

int i,j;
for (i=0; i<n; i++)
for (j=i+1; j<n; j++)
if (m[i][j]!=m[j][i])
return 0;
return 1;
}

/* Provera da li je relacija predstavljena matricom tranzitivna*/


int tranzitivna(int** m, int n)
{
int i,j,k;

for (i=0; i<n; i++)


for (j=0; j<n; j++)
for (k=0; k<n; k++)
if ((m[i][j]==1)
&& (m[j][k]==1)
&& (m[i][k]!=1))
return 0;
return 1;
}

/* Pronalazi najmanju simetricnu relaciju koja sadrzi relaciju a */


void simetricno_zatvorenje(int** a, int n)
{
int i,j;
for (i=0; i<n; i++)
for (j=0; j<n; j++)
{
if (a[i][j]==1 && a[j][i]==0)
a[j][i]=1;
if (a[i][j]==0 && a[j][i]==1)
a[i][j]=1;
}
}

main()
{
int **m;
int n;
int i,j;

44
1.10 Matrice 45

printf("Unesi dimenziju matrice : ");


scanf("%d",&n);
m=alociraj(n);

for (i=0; i<n; i++)


for (j=0; j<n; j++)
scanf("%d",&m[i][j]);

printf("Uneli ste matricu : \n");

ispisi_matricu(m,n);

if (refleksivna(m,n))
printf("Relacija je refleksivna\n");
if (simetricna(m,n))
printf("Relacija je simetricna\n");
if (tranzitivna(m,n))
printf("Relacija je tranzitivna\n");

simetricno_zatvorenje(m,n);

ispisi_matricu(m,n);

obrisi(m,n);
}
Primer 1.10.4 Izracunati vrednost determinante matrice preko Laplasovog
razvoja.
#include <stdio.h>
#include <stdlib.h>

/* Funkcija alocira matricu dimenzije nxn */


int** allocate(int n)
{
int **m;
int i;
m=(int**)malloc(n*sizeof(int*));
if (m == NULL) {
printf("Greska prilikom alokacije memorije!\n");
exit(1);
}

for (i=0; i<n; i++)

45
46 Milena VujosevicJanicic

{
m[i]=malloc(n*sizeof(int));
if (m[i] == NULL)
{
int k;
for(k=0;k<i;k++)
free(m[k]);
printf("Greska prilikom alokacije memorije!\n");
free(m);
exit(1);
}
}

return m;
}

/* Funkcija vrsi dealociranje date matrice dimenzije n */


void deallocate(int** m, int n)
{
int i;
for (i=0; i<n; i++)
free(m[i]);
free(m);
}

/* Funkcija ucitava datu alociranu matricu sa standardnog ulaza */


void ucitaj_matricu(int** matrica, int n)
{
int i,j;
for (i=0; i<n; i++)
for (j=0; j<n; j++)
scanf("%d",&matrica[i][j]);
}

/* Rekurzivna funkcija koja vrsi Laplasov razvoj */


int determinanta(int** matrica, int n)
{
int i;
int** podmatrica;
int det=0,znak;

/* Izlaz iz rekurzije je matrica 1x1 */


if (n==1) return matrica[0][0];

46
1.11 Strukture 47

/* Podmatrica ce da sadrzi minore polazne matrice */


podmatrica=allocate(n-1);
znak=1;
for (i=0; i<n; i++)
{
int vrsta,kolona;
for (kolona=0; kolona<i; kolona++)
for(vrsta=1; vrsta<n; vrsta++)
podmatrica[vrsta-1][kolona] = matrica[vrsta][kolona];
for (kolona=i+1; kolona<n; kolona++)
for(vrsta=1; vrsta<n; vrsta++)
podmatrica[vrsta-1][kolona-1] = matrica[vrsta][kolona];

det+= znak*matrica[0][i]*determinanta(podmatrica,n-1);
znak*=-1;
}
deallocate(podmatrica,n-1);
return det;
}

main()
{
int **matrica;
int n;

scanf("%d", &n);
matrica = allocate(n);
ucitaj_matricu(matrica, n);
printf("Determinanta je : %d\n",determinanta(matrica,n));
deallocate(matrica, n);
}

1.11 Strukture
Informacije kojima se opisuje realni svet retko se predstavljaju u
elementarnoj formi u vidu celih, realnih, znakovnih konstanti itd.
Mnogo cesce imamo posla sa slozenim objektima koji se sastoje od
elemenata raznih tipova. Na primer jednu osobu karakterisu ime,
prezime, datum i mesto ro enja.
Struktura predstavlja skup podataka kojim se opisuju neka bitna
svojstva objekta. Komponente koje obrazuju strukturu nazivaju se

47
48 Milena VujosevicJanicic

elementi strukture.
Sintaksa strukture:

struct ime_strukture
{
tip ime_elementa1;
tip ime_elementa2;
...
};

Primer 1.11.1 Primer jednostavne strukture.

struct licnost
{
char ime[31];
char adresa[41];
unsigned starost;
};

struct licnost osoba1, osoba2;

Deklaraciju osobe1 i osobe2 mogli smo da zapisemo i na sledeci


nacin

struct licnost
{
char ime[31];
char adresa[41];
unsigned starost;
} osoba1, osoba2;

Ukoliko nemamo potrebu da se licnost koristi dalje u programu


mogu se napraviti dve osobe bez davanja imena strukturi:

struct
{
char ime[31];
char adresa[41];
unsigned starost;
} osoba1, osoba2;

Kada imamo promenljivu strukturnog tipa tada elementima date


strukture pristupamo uz pomoc operatora ..

48
1.11 Strukture 49

Primer 1.11.2
osoba1.starost=20;
osoba2.starost=21;
...
if (osoba1.starost == osoba2.starost)
printf(" Osobe su iste starosti");

Dozvoljeno je praviti nizove struktura. Npr. niz od 20 elemenata


koji sadrzi licnosti:
struct licnost nizLicnosti[20];
Tada da bi procitali starost neke licnosti u nizu pisemo:
nizLicnosti[5].starost
Moze se definisati pokazivac na strukturu.
struct licnost *posoba;
Tada se pristupanje elementima strukture moze vrsiti upotrebom
operatora . na standardni nacin:
(*posoba).ime
(*posoba).adresa
(*posoba).starost
ili koriscenjem specijalnog operatora 0 >0 na sledeci nacin:
posoba->ime
posoba->adresa
posoba->starost

Primer 1.11.3 Elementi strukture mogu da budu i druge strukture.


struct datum
{
unsigned dan;
unsigned mesec;
unsigned godina;
};

struct licnost
{
char ime[30];
struct datum datumrodjenja;
};

49
50 Milena VujosevicJanicic

Sada se danu, mesecu i godini datuma rodjenja pristupa na sledeci


nacin:
osoba.datumrodjenja.dan = 10;
osoba.datumrodjenja.mesec = 5;
osoba.datumrodjenja.godina = 1986;

1.11.1 Operator typedef


Operator typedef omogucava nam da definisemo nasa imena za neki
od osnovih ili izvedenih tipova. Na primer, mozemo da uradimo
sledece:
typedef double RealanBroj;
Nakon ovoga mozemo u tekstu deklarista promenljivu x kao Realan-
Broj, ona ce zapravo biti tipa double.
RealanBroj x; /* Umesto: double x;*/
Ili, ako zelimo da skratimo pisanje za neoznacene duge brojeve tj
za unsigned long int to mozemo da uradimo na sledeci nacin
typedef unsigned long int VelikiBroj;
Sada u kodu mozemo da koristimo VelikiBroj kao tip.
Operator typedef je narocito pogodan da bi se izbeglo ponavljal-
nje reci struct pri deklarisanju strukturnih promenljivih.
typedef struct _licnost licnost;
Sada deklaracija moze da bude:
licnost osoba1, osoba2;
/* umesto: struct _licnost osoba1, osoba2; */
Kao skracen zapis za
struct _tacka {
float x;
float y;
}

typedef struct _tacka tacka;


moze se koristiti:
typedef struct _tacka
{
float x;
float y;
} tacka;

50
1.11 Strukture 51

Primer 1.11.4 Struktura artikal.


typedef struct _artikal
{
long bar_kod;
char ime[MAX_IME];
float pdv;
} artikal;

Primer 1.11.5 Program ilustruje osnovne geometrijske algoritme


kao i rad sa strukturama.
#include <math.h>
#include <stdio.h>

typedef struct _tacka


{
float x;
float y;
} tacka;

typedef struct _vektor


{
float x, y;
} vektor;

/* Koordinatni pocetak */
tacka kp={0.0,0.0};

/* Niz tacaka */
tacka niz[100];

/* Pokazivac na strukturu tacke */


tacka *pt;

void IspisiTacku(tacka A)
{
printf("(%f,%f)\n",A.x,A.y);
}

void IspisiVektor(vektor v)
{
printf("(%f,%f)\n",v.x,v.y);
}

51
52 Milena VujosevicJanicic

float duzina(vektor v)
{
return sqrt(v.x*v.x+v.y*v.y);
}

vektor NapraviVektor(tacka *pA, tacka *pB)


{
vektor ab;
ab.x=pB->x - pA->x;
ab.y=pB->y - pA->y;
return ab;
}

float rastojanje(tacka A, tacka B)


{
float dx=B.x - A.x;
float dy=B.y - A.y;
return sqrt(dx*dx+dy*dy);
}

/* Heronov obrazac */
float PovrsinaTrougla(tacka A, tacka B, tacka C)
{
float a=rastojanje(B,C);
float b=rastojanje(A,C);
float c=rastojanje(A,B);

float s=(a+b+c)/2.0;
return sqrt(s*(s-a)*(s-b)*(s-c));
}

float PovrsinaKonveksnogPoligona(tacka poligon[], int br_temena)


{
int i;
float povrsina=0.0;
for (i=1; i<br_temena-1; i++)
povrsina+=PovrsinaTrougla(poligon[0], poligon[i], poligon[i+1]);

return povrsina;
}

float Obim(tacka poligon[], int br_temena)

52
1.11 Strukture 53

{
int i;
float o=0;

for (i=0; i<br_temena-1; i++)


o+=rastojanje(poligon[i], poligon[i+1]);

o+=rastojanje(poligon[0], poligon[br_temena-1]);
return o;
}

main()
{
tacka poligon[]={{0.0,0.0},
{0.0,1.0},
{1.0,1.0},
{1.0,0.0}};
printf("Obim poligona je %f\n",Obim(poligon,4));
printf("Povrsina poligona je %f\n",
PovrsinaKonveksnogPoligona(poligon,4));
}
Primer 1.11.6 Program koji ucitava niz studenata i sortira ih po
njihovim ocenama.
#include <stdio.h>
#include <ctype.h>

#define MAX_IME 20

typedef struct _student


{
char ime[MAX_IME];
char prezime[MAX_IME];
int ocena;
} student;

/* Funkcija ucitava rec i vraca njenu duzinu ili


-1 ukoliko smo dosli do znaka EOF*/
int getword(char word[],int max)
{
int c, i=0;

while (isspace(c=getchar()))

53
54 Milena VujosevicJanicic

while(!isspace(c) && c!=EOF && i<max-1)


{
word[i++]=c;
c = getchar();
}

word[i]=\0;

if (c==EOF) return -1;


else return i;

/* Funkcija ucitava niz studenata, vraca duzinu niza koji ucita */


int UcitajPodatke(student studenti[], int max)
{
int i=0;
while(i<max && getword(studenti[i].ime, MAX_IME)>0)
{
if (getword(studenti[i].prezime, MAX_IME) < 0)
break;
scanf("%d",&studenti[i].ocena);
i++;
}
return i;
}

void IspisiPodatke(student studenti[], int br_studenata)


{
int i;
printf("IME PREZIME OCENA\n");
printf("--------------------------------------\n");
for (i=0; i<br_studenata; i++)
printf("%-20s %-20s %5d\n",studenti[i].
ime, studenti[i].prezime, studenti[i].ocena);
}

/* Sortiranje studenata po ocenama */


void SelectionSort(student studenti[], int br_studenata)
{
int i,j;

54
1.11 Strukture 55

for (i=0; i<br_studenata-1; i++)


for (j=i; j<br_studenata; j++)
if (studenti[i].ocena<studenti[j].ocena)
{ student tmp=studenti[i];
studenti[i]=studenti[j];
studenti[j]=tmp;
}
}

main()
{
student studenti[100];
int br_studenata = UcitajPodatke(studenti,100);

SelectionSort(studenti, br_studenata);

IspisiPodatke(studenti, br_studenata);

}
Primer 1.11.7 Dinamicki niz.
/* Program za svaku rec unetu sa standardnog
ulaza ispisuje broj pojavljivanja.
Verzija sa dinamickim nizom i realokacijom.
*/

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Rec je opisana imenom i brojem pojavljivanja */


typedef struct _rec
{ char ime[80];
int br_pojavljivanja;
} rec;

/* Dinamicki niz reci je opisan pokazivacem na


pocetak, tekucim brojem upisanih elemenata i
tekucim brojem alociranih elemenata */
rec* niz_reci;
int duzina=0;
int alocirano=0;

55
56 Milena VujosevicJanicic

/* Realokacija se vrsi sa datim korakom */


#define KORAK 10

/* Funkcija ucitava rec i vraca njenu duzinu ili


-1 ukoliko smo dosli do znaka EOF*/
int getword(char word[],int max)
{
int c, i=0;

while (isspace(c=getchar()))
;

while(!isspace(c) && c!=EOF && i<max-1)


{
word[i++]=c;
c = getchar();
}

word[i]=\0;

if (c==EOF) return -1;


else return i;
}

main()
{
char procitana_rec[80];
int i;

while (getword(procitana_rec,80)!=-1)
{
/* Proveravamo da li rec vec postoji u nizu */
for (i=0; i<duzina; i++)
/* Ako bismo uporedili procitana_rec == niz_reci[i].ime
bili bi uporedjeni pokazivaci a ne odgovarajuci sadrzaji!!!
Zato koristimo strcmp. */
if (strcmp(procitana_rec, niz_reci[i].ime)==0)
{
niz_reci[i].br_pojavljivanja++;
break;
}

56
1.11 Strukture 57

/* Ukoliko rec ne postoji u nizu */


if (i==duzina)
{
rec nova_rec;
/* Ako bismo dodelili nova_rec.ime = procitana_rec
izvrsila bi se dodela pokazivaca a ne kopiranje niske
procitana_rec u nova_rec.ime. Zato koristimo strcpy!!! */
strcpy(nova_rec.ime,procitana_rec);
nova_rec.br_pojavljivanja=1;

/* Ukoliko je niz "kompletno popunjen" vrsimo realokaciju */


if (duzina==alocirano)
{
alocirano+=KORAK;

/* Sledeca linija zamenjuje blok koji sledi i moze se


koristiti alternativno. Blok je ostavljen samo da bi
demonstrirao korisnu tehniku */
/* niz_reci=realloc(niz_reci, (alocirano)*sizeof(rec)); */
{
/* alociramo novi niz, veci nego sto je bio prethodni */
rec* novi_niz=(rec *)malloc(alocirano*sizeof(rec));

if (novi_niz == NULL)
{
free(niz_reci);
printf("Greska prilikom alokacije memorije");
exit(1);
}

/* Kopiramo elemente starog niza u novi */


for (i=0; i<duzina; i++)
novi_niz[i]=niz_reci[i];

/* Uklanjamo stari niz */


free(niz_reci);

/* Stari niz postaje novi */


niz_reci=novi_niz;
}
}
/* Upisujemo rec u niz */
niz_reci[duzina]=nova_rec;

57
58 Milena VujosevicJanicic

duzina++;
}
}

/* Ispisujemo elemente niza */


for(i=0; i<duzina; i++)
printf("%s - %d\n",niz_reci[i].ime, niz_reci[i].br_pojavljivanja);

free(niz_reci);
}

1.12 qsort
Primer 1.12.1 Implementacija funkcije qsort.
#include <stdio.h>
#include <string.h>

void printarray(int v[], int left, int right)


{
int i;
for (i=left; i<=right; i++)
printf("%d ",v[i]);
putchar(\n);
}

void swap(int v[], int i, int j)


{
int tmp=v[i];
v[i]=v[j];
v[j]=tmp;
}

/* qsort: sortira v[left]...v[right] u rastucem poretku */


void qsort(int v[], int left, int right)
{
int i, last;

/* ne radi nista ako niz sadrzi */


/* manje od dva elementa */
if (left >= right)
return;
/* prebaci element particioniranja */

58
1.13 Sortiranje genericka funkcija 59

/* u v[left] */
swap(v, left, (left + right)/2);
last = left;

/* partition */
for (i = left + 1; i <= right; i++)
if (v[i] < v[left])
swap(v, ++last, i);

/* restore partition elem */


swap(v, left, last);

/* Sortiraj preostala dva dela niza */


qsort(v, left, last-1);
qsort(v, last+1, right);
}

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

printarray(array, 0, n-1);
qsort(array, 0, n-1);
printarray(array, 0, n-1);

1.13 Sortiranje genericka funkcija


Sortiranje niza celih brojeva (jedan od algoritama)
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(a[i]<a[j])
{
int pom=a[i];
a[i]=a[j];
a[j]=pom;
}
Sortiranje iz programa mozemo da izdvojimo u funkciju:
void sort_int(int a[], int n)

59
60 Milena VujosevicJanicic

{
int i, j;
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(a[i]<a[j])
{
int pom=a[i];
a[i]=a[j];
a[j]=pom;
}
}

Sortiranje niza realnih brojeva:

void sort_float(float a[], int n)


{
int i, j;
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(a[i]<a[j])
{
float pom=a[i];
a[i]=a[j];
a[j]=pom;
}
}

Razlike:
prvi argument funkcije;
pomocna promenljiva;
pore enje.
Sortiranje studenata po oceni ukoliko je data struktura student:

typedef struct _student {


char ime[MAX_IME];
char prezime[MAX_IME];
int ocena;
} student;

void sort_po_oceni(student a[], int n)


{
int i, j;

60
1.13 Sortiranje genericka funkcija 61

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


for(j=i+1; j<n; j++)
if(a[i].ocena < a[j].ocena)
{
student pom=a[i];
a[i]=a[j];
a[j]=pom;
}
}

Sortiranje studenta po prezimenu:


void sort_po_prezimenu(student a[], int n)
{
int i, j;
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(strcmp(a[i].prezime, a[j].prezime)<0)
{
student pom=a[i];
a[i]=a[j];
a[j]=pom;
}
}
Sortiranje studenta po imenu:
void sort_po_imenu(student a[], int n)
{
int i, j;
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(strcmp(a[i].ime, a[j].ime)<0)
{
student pom=a[i];
a[i]=a[j];
a[j]=pom;
}
}
Kako da napravimo jednu funkciju koja sortira studente bez obzira
na kriterijum?
Prvo moramo da izdvojimo funkciju pore enja:
int poredi_po_oceni(student st1, student st2)

61
62 Milena VujosevicJanicic

{
return st1.ocena - st2.ocena;
}

int poredi_po_prezimenu(student st1, student st2)


{
return strcmp(st1.prezime, s2.prezime);
}

int poredi_po_imenu(student st1, student st2)


{
return strcmp(st1.ime, st2.ime);
}
Funkcija pore enja vraca 0 ukoliko su elementi jednaki, broj manji
od nule ukoliko je prvi manji od drugog i broj veci od nule ukolikoje
prvi veci od drugog.

void sort_po_imenu(student a[], int n)


{
int i, j;
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
/*if(poredi_po_prezimenu(a[i], a[j])<0)*/
/*if(poredi_po_oceni(a[i], a[j])<0)*/
if(poredi_po_imenu(a[i], a[j])<0)
{
student pom=a[i];
a[i]=a[j];
a[j]=pom;
}
}

Sada mozemo da dodamo jos jedan argument funkciji sortiranja


i tako da dobijemo jednu funkciju umesto tri:
void sort_studente(student a[], int n, int (*f)(student, student))
{
int i, j;
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if((*f)(a[i], a[j])<0)
{
student pom=a[i];

62
1.13 Sortiranje genericka funkcija 63

a[i]=a[j];
a[j]=pom;
}
}
Sta dalje? Kako da dobijemo jednu funkciju sortiranja bez obzira
na tip elemenata niza?
Teba da resimo sledece stvari:
razmena mesta elemenata ne sme da zavisi od tipa elemenata
koji se razmenjuju.
potpis funkcije pore enja ne sme da zavisi od tipa elemenata
koji se porede kako bi on bio jedinstven.
prvi argument funkcije ne sme da zavisi od tipa elemenata niza.
Da bi smo razmenili dva elementa potrebna nam je pomocna
promenljiva u kojoj privremeno cuvamo neku vrednost. Ako ne
znamo tip elementa onda ne mozemo da napravimo pomocnu promenljivu.
Ali zato mozemo da koristeci funkciju malloc odvojimo neko mesto
u memoriji za smestanje elementa koji nam u datoj situaciji treba.
Koliko je to mesto? Nekada 4 bajta, npr za int, a nekada dosta vece,
npr za studenta. Kako funkcija sortiranja zna koliko mesta treba da
odvoji? Znace tako sto cemo joj tu velicinu proslediti kao argument.
Sada, dakle umesto pomocne promenljive, imamo blok u memoriji,
a umesto naredbe dodele koristicemo funkciju memcpy koja kopira
deo memorije sa jednog mesta na drugo mesto.
Dakle, razmenu cemo da radimo na sledeci nacin:
void* tmp = malloc(size);
if (tmp==NULL) {printf("Greska prilikom alokacije memorije!\n");exit(1);}
memcpy(tmp, adresa_itog, size);
memcpy(adresa_itog, adresa_jtog, size);
memcpy(adresa_jtog, tmp, size);
free(tmp);
Potpis funkcije pore enja ne sme da zavisi od tipa elemenata koji
se porede. To se moze postici koristeci pokazivac na tip void.
Na primer, pore enje dva cela broja:
int poredi_br(void* a, void* b)
{
int br_a = *(int*)a;
int br_b = *(int*)b;

return br_a-br_b;
}

63
64 Milena VujosevicJanicic

Na primer, pore enje dva realna broja:


int poredi_br(void* a, void* b)
{
float br_a = *(float*)a;
float br_b = *(float*)b;

if (br_a > br_b) return 1;


else if (br_a < br_b) return -1;
else return 0;
}
Na primer, pore enje dva studenta po oceni
int poredi_br(void* a, void* b)
{
student student1 = *(studnet*)a;
student student2 = *(studnet*)b;

return student1.ocena-student2.ocena;
}

Sada funkcija pore enja ima uvek potpis


int poredi(void* a, void* b)
i moze se kao parametar proslediti nasoj funkciji sortiranja.
Primer 1.13.1 /* Genericka funkcija sortiranja -
nezavisna od tipa elemenata niza
koji se sortira */
#include <stdlib.h>

void sort(void* a, int n, int size, int (*poredi)(void*, void*))


{
int i, j;
for (i = 0; i<n-1; i++)
for (j = i+1; j<n; j++)
{
void* adresa_itog = (char*)a+i*size;
void* adresa_jtog = (char*)a+j*size;

if (poredi(adresa_itog, adresa_jtog)<0)
{
void* tmp = malloc(size);

64
1.13 Sortiranje genericka funkcija 65

if (tmp==NULL) {
printf("Greska prilikom alokacije memorije!\n");
exit(1);
}
memcpy(tmp, adresa_itog, size);
memcpy(adresa_itog, adresa_jtog, size);
memcpy(adresa_jtog, tmp, size);
free(tmp);
}

}
}

int poredi_br(void* a, void* b) {


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

return br_a-br_b;
}

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


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

if (br_a > br_b) return 1;


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

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

sort(a, n, sizeof(int), poredi_br);

for (i = 0; i < n; i++)


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

65
66 Milena VujosevicJanicic

sort(b, nf, sizeof(float), poredi_float);

for (i = 0; i < n; i++)


printf("%f ", b[i]);
putchar(\n);
}

1.14 qSort funkcija iz standardne biblioteke


Primer 1.14.1 qSort-Upotreba.
/* Ilustracija upotrebe funkcije qsort iz stdlib.h
Sortira se niz celih brojeva.
*/

#include <stdlib.h>
#include <stdio.h>

/* const znaci da ono na sta pokazuje a (odnosno b)


nece biti menjano u funkciji */
int poredi(const void* a, const void* b)
{
/* Skracen zapis za
int br_a = *(int*)a;
int br_b = *(int*)b;

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

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


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

if (br_a > br_b) return 1;


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

main()

66
1.14 qSort funkcija iz standardne biblioteke 67

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

int n=sizeof(niz)/sizeof(int);
qsort((void*)niz, n, sizeof(int), poredi);
for(i=0; i<n; i++)
printf("%d",niz[i]);

n=sizeof(nizf)/sizeof(float);
qsort((void*)nizf, n, sizeof(float), poredi_float);
for(i=0; i<n; i++)
printf("%f",nizf[i]);

}
Primer 1.14.2 Binarno pretrazivanje - koriscenje ugra ene bsearch


funkcije.

/* Funkcija ilustruje koriscenje ugradjene funkcije bsearch */


#include <stdlib.h>

int poredi(const void* a, const void *b)


{
return *(int*)a-*(int*)b;
}

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

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

if (elem==NULL)
printf("Element nije pronadjen\n");
else
printf("Element postoji na poziciji %d\n",elem-niz);

67
68 Milena VujosevicJanicic

1.15 Genericko sortiranje reci


Primer 1.15.1 Sortiranje reci. Ako se sortira niz stringova, onda
svaki element je sam po sebi pokazivac tipa char *, te funkcija
pore enja tada prima podatke tipa char ** koji se konvertuju u svoj


tip i derefenciraju radi dobijanja podataka tipa char *.

/* Ilustracija upotrebe funkcije qsort iz stdlib.h


Sortira se niz reci i to ili leksikografski
ili po duzini
*/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int poredi(const void* a, const void* b)


{
char *s1 = *(char **)a;
char *s2 = *(char **) b;
return strcmp(s1, s2);

/* Prethodno je ekvivalentno sa:


return strcmp(*(char**)a,*(char**)b); */
}

int poredi_po_duzini(const void* a, const void* b)


{
char *s1 = *(char **) a;
char *s2 = *(char **) b;
return strlen(s1) - strlen(s2);
/* Prethodno je ekvivalentno sa:
return strlen(*(char**)b)-strlen(*(char**)a); */
}

main()
{
int i;
char* nizreci[]={"Jabuka","Kruska","Sljiva","Dinja","Lubenica"};

68
1.15 Genericko sortiranje reci 69

qsort((void*)nizreci, 5, sizeof(char*), poredi_po_duzini);

for (i=0; i<5; i++)


printf("%s\n",nizreci[i]);

qsort((void*)nizreci, 5, sizeof(char*), poredi);

for (i=0; i<5; i++)


printf("%s\n",nizreci[i]);
}
Primer 1.15.2 Sa ulaza se unose reci. Program broji pojavljivanja
svake od kljucnih reci programskog jezika C. Na kraju se reci ispisuju
opadajuce po broju pojavljivanja.
#include <stdio.h>
#include <stdlib.h>

/* Svaka kljucna rec se odlikuje imenom i brojem pojavljivanja */


typedef struct _keyword
{
char* word;
int num;
} keyword;

/* Kreiramo niz struktura sortiranih leksikografski


po imenu kljucne reci, kako bismo ubrzali pronalazak reci */
keyword keywords[]={ {"break",0},
{"continue",0},
{"float",0},
{"for",0},
{"if",0},
{"return",0},
{"struct",0},
{"while",0}
};

/* Funkcija cita sledecu rec sa standardnog ulaza */


int getword(char word[], int lim)
{
int c, i=0;
while(!isalpha(c=getchar()) && c!=EOF)
;
if (c==EOF)

69
70 Milena VujosevicJanicic

return -1;
do
{
word[i++]=c;
} while(--lim>0 && isalpha(c=getchar()));

word[i]=\0;
return i;
}

/* Funkcija leksikografskog poredjenja za bsearch */


int cmp(const void* a, const void* b) {
/* Funkcija strcmp prima kao argumente dva
pokazivaca na karaktere. Prvi je rec koju
trazimo u nizu, a drugi je element niza
sa kojim se vrsi poredjenje. Pokazivac
b konvertujemo u pokazivac na strukturu
keyword a zatim posmatramo rec koja se tu
cuva */
return strcmp((char*)a, (*(keyword*)b).word); }

/* Funkcija numerickog poredjenja za qsort */


int numcmp(const void* a, const void* b)
{
return ((*(keyword*)b).num-(*(keyword*)a).num);
}

main()
{
char word[80];
int i;

/* Broj kljucnih reci */


int num_of_keywords=sizeof(keywords)/sizeof(keyword);

/* Citamo reci */
while (getword(word,80)!=-1)
{
/* Trazimo rec u spisku kljucnih reci binarnom pretragom */
keyword* k=(keyword*)bsearch((void*)word,
(void*)keywords,
num_of_keywords,
sizeof(keyword),

70
1.16 Argumenti komandne linije 71

cmp);
/* Ukoliko je pronadjena uvecavamo broj pojavljivanja */
if (k!=NULL)
(*k).num++;
}

/* Sortiramo niz na osnovu broja pojavljivanja */


qsort((void*)keywords, num_of_keywords, sizeof(keyword), numcmp);

/* Vrsimo ispis */
for (i=0; i<num_of_keywords; i++)
printf("%s %d\n", keywords[i].word, keywords[i].num);
}

1.16 Argumenti komandne linije


Primer 1.16.1
/* Argumenti komandne linije programa */

/* Program pozivati sa npr.:


a.out
a.out prvi
a.out prvi drugi treci
a.out -a -bc ime.txt
*/

#include <stdio.h>

/* Imena ovih promenljivih mogu biti proizvoljna.


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

main(int argc, char* argv[])


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

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


for (i = 0; i<argc; i++)
printf("argv[%d] = %s\n", i, argv[i]);

71
72 Milena VujosevicJanicic

1.17 Datoteke
Primer 1.17.1 Program demonstrira otvaranje datoteka ("r" - read
i "w" - write mod) i osnovne tehnike rada sa datotekama.
/* U datoteku se upisuje prvih 10 prirodnih
brojeva, a zatim se iz iste datoteke
citaju brojevi dok se ne stigne do kraja i
ispisuju se na standardni izlaz */

#include <stdio.h>
#include <stdlib.h>

main()
{
int i;

/* Otvaramo datoteku sa imenom podaci.txt za pisanje */


FILE* f = fopen("podaci.txt", "w");

/* Ukoliko otvaranje nije uspelo, fopen vraca NULL.


U tom slucaju, prijavljujemo gresku i zavrsavamo program */
if (f == NULL)
{
printf("Greska prilikom otvaranja datoteke podaci.txt za pisanje\n");
exit(1);
}

/* Upisujemo u datoteku prvih 10 prirodnih brojeva


(svaki u posebnom redu) */
for (i = 0; i<10; i++)
fprintf(f, "%d\n", i);

/* Zatvaramo datoteku */
fclose(f);

/* Otvaramo datoteku sa imenom podaci.txt za citanje */


f = fopen("podaci.txt", "r");

/* Ukoliko otvaranje nije uspelo, fopen vraca NULL.


U tom slucaju, prijavljujemo gresku i zavrsavamo program */

72
1.17 Datoteke 73

if (f == NULL) {
printf("Greska prilikom otvaranja datoteke podaci.txt za citanje\n");
exit(1);
}

/* Citamo brojeve iz datoteke dok ne stignemo do kraja i ispisujemo ih


na standardni izlaz */
while(1) {
int br;
/* Pokusavamo da procitamo broj */
fscanf(f, "%d", &br);

/* Ukoliko smo dosli do kraja datoteke, prekidamo */


if (feof(f))
break;

/* Ispisujemo procitani broj */


printf("Procitano : %d\n", br);
}

/* Funkciju feof ne treba pozivati pre pokusaja citanja.


Sledeci kod moze dovesti do greske:
while (!feof(f))
fscanf(f,"%d",&br);
*/

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

Pokazivaci stdin, stdout i stderr su definisani u okviru stdio.h.


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

Primer 1.17.2 Program demonstrira a - append mod datoteka -


nadovezivanje.
#include <stdio.h>

main()
{
FILE* datoteka;

73
74 Milena VujosevicJanicic

/* Otvaramo datoteku za nadovezivanje


i proveravamo da li je doslo do greske */
if ( (datoteka=fopen("dat.txt","a"))==NULL)
{
fprintf(stderr,"Greska prilikom otvaranja dat.txt\n");
return 1;
}

/* Upisujemo sadrzaj u datoteku */


fprintf(datoteka,"Zdravo svima\n");

/* Zatvaramo datoteku */
fclose(datoteka);
}
Primer 1.17.3 Program ilustruje rad sa datotekama. Program kopira
datoteku cije se ime zadaje kao prvi argument komandne linije u da-
toteku cije se ime zadaje kao drugi argument komandne linije. Uz
svaku liniju se zapisuje i njen redni broj.
#include <stdio.h>

#define MAX_LINE 256

/* Funkcija fgets definisana je u stdio.h

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

fgets ucitava najvise sledecih n-1 znakova


u polje niza karaktera s, zaustavljajuci se
ako naidje na novu liniju koju takodje
upisuje u polje. Na kraju upisuje \0.
Funkcija vraca s ili NULL ako dodje do kraja
datoteke ili se pojavi greska

Funkcija getline moze jednostavno da se


realizuje preko funkcije fgets.

int getline(char s[], int lim)


{
char* c = fgets(s, lim, stdin);
return c==NULL ? 0 : strlen(s);
}

74
1.17 Datoteke 75

*/

main(int argc, char* argv[])


{

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

if (argc != 3) {
fprintf(stderr,"Upotreba : %s ulazna_datoteka izlazna_datoteka\n",argv[0]);
return 1;
}

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


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

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


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

/* Prepisivanje karakter po karakter je moguce ostvariti preko:


int c;
while ((c=fgetc(in)) != EOF)
putc(c,out);
*/

line_num = 1;

/* Citamo liniju po liniju sa ulaza*/


while (fgets(line, MAX_LINE, in) != NULL)
{
/* Ispisujemo broj linije i sadrzaj linije na izlaz */
fprintf(out, "%d :\t", line_num++);
fputs(line, out);
}

/* Zatvaramo datoteke */

75
76 Milena VujosevicJanicic

fclose(in);
fclose(out);
}
Primer 1.17.4 Prodavnica - ilustruje citanje niza struktura iz tek-
tsualne datoteke.
/* Datoteka, cije se ime zadaje kao argument komandne linije
ili ako se ne zada onda se ime unosi sa standardnog
ulaza, sadrzi podatke o proizvodima koji se prodaju
u okviru odredjene prodavnice. Svaki
proizvod se odlikuje sledecim podacima:
bar-kod - petocifreni pozitivan broj
ime - niska karaktera
cena - realan broj zaokruzen na dve decimale
pdv - stopa poreza - realan broj zaokruzen na dve decimale
Pretpostavljamo da su podaci u datoteci
korektno zadati.

Pretpostavljamo da se u prodavnici ne
prodaje vise od 1000 razlicitih artikala
Na standardni izlaz ispisati podatke o
svim proizvodima koji se prodaju u prodavnici.
Zadatak je moguce resiti i bez koriscenja nizova
(i takvo resenje je bolje). */

#include <stdio.h>

/* Maksimalna duzina imena proizvoda */


#define MAX_IME 30

/* Maksimalni broj artikala */


#define MAX_ARTIKALA 1000

/* Struktura za cuvanje podataka o jednom artiklu */


typedef struct _artikal {
int bar_kod;
char ime[MAX_IME];
float cena;
float pdv;
} artikal;

/* Niz struktura u kome se cuvaju podaci o artiklima */

76
1.17 Datoteke 77

artikal artikli[MAX_ARTIKALA];

/* Broj trenutno ucitanih artikala */


int br_artikala = 0;

/* Ucitava podatke o jednom artiklu iz date datoteke.


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

/* Ukoliko smo dosli do kraja datoteke prilikom pokusaja ucitavanja


prijavljujemo neuspeh */
if (feof(f))
return 0;

/* Prijavljujemo uspeh */
return 1;
}

/* Izracunava ukupnu cenu datog artikla */


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

/* Ispisuje podatke o svim artiklima */


void ispisi_artikle()
{
int i;
for (i = 0; i<br_artikala; i++)
printf("%-5d %-10s %.2f %.2f = %.2f\n",
artikli[i].bar_kod, artikli[i].ime,
artikli[i].cena, artikli[i].pdv,
cena(artikli[i]));
}

main(int argc, char* argv[])


{
FILE* f;

/* Ukoliko nije navedeno ime kao argument komandne linije, trazimo

77
78 Milena VujosevicJanicic

od korisnika da ga unese */
if (argc<2) {
/* Ucitavamo ime datoteke */
char ime_datoteke[256];
printf("U kojoj datoteci se nalaze podaci o proizvodima: ");
scanf("%s", ime_datoteke);

/* Otvaramo datoteku i proveravamo da li smo uspeli */


if ( (f = fopen(ime_datoteke, "r")) == NULL)
{
printf("Greska prilikom otvaranja datoteke %s\n", ime_datoteke);
return 1;
}
}
/* Ime datoteke je prvi argument komandne linije */
else {
/* Otvaramo datoteku i proveravamo da li smo uspeli */
if ( (f = fopen(argv[1], "r")) == NULL)
{
printf("Greska : datoteka %s ne moze biti otvorena\n", argv[1]);
return 1;
}

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

/* Ispisujemo podatke o svim artiklima */


ispisi_artikle();

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

1.18 Liste
1.18.1 Red

Primer 1.18.1 Program formira listu brojeva i demonstrira osnovne


elemente rada sa listom.

78
1.18 Liste 79

pocetak reda (brisanje get)


kraj reda (dodavanje add)

A B ... X NULL

novi element

pocetak reda
novi kraj reda

A B ... X Y NULL

pocetak reda nakon brisanja kraj reda

B ... X Y NULL

Slika 1.1: Red

#include <stdio.h>
#include <stdlib.h>

typedef struct elem {


int broj;
struct elem *sled;
} Elem;

/* Citanje brojeva i formiranje liste. Funkcija vraca pokazivac


na pocetak liste. */
Elem *citaj (void)
{
Elem *lista = NULL, *poslednji = NULL, *novi;
int broj;

printf("\n\nUnesite elemente liste - 0 za kraj\n");


scanf ("%d", &broj);

79
80 Milena VujosevicJanicic

while (broj) {
/*Alocira se prostor za novi clan liste*/
novi =(Elem*)malloc (sizeof (Elem));
if (novi == NULL)
{
fprintf(stderr, "Greska prilikom alokacije memorije\n");
exit(1);
}

/* Postavljanje vrednosti */
novi->broj = broj;
novi->sled = NULL;

/* Ukoliko lista nije prazna novi element se postavlja iza


poslednjeg elemnta liste - na koji pokazuje poslednji */
if (poslednji != NULL)
poslednji->sled = novi;
/* Inace se postavlja da bude pocetak liste */
else
lista = novi;

/*Poslednji se postavlja da pokazuje na poslednji element liste */


/*Ekvivalentno je sa
poslednji = poslednji ->sledeci */
poslednji = novi;
/* Ucitavanje novog elementa liste 0 za kraj */
scanf ("%d", &broj);
}
/* Funkcija vraca pokazivac na pocetak liste */
return lista;
}

/* Ispisivanje liste*/
void pisi (Elem *lista)
{
while (lista != NULL)
{
printf ("%d ", lista->broj),
lista = lista->sled;
}
putchar (\n);
}

80
1.18 Liste 81

/* Oslobadjanje memorije koju lista zauzima*/


void brisi (Elem* lista)
{
Elem *stari;
while (lista != NULL)
{
stari = lista;
lista = lista->sled;
free (stari);
}
}

/* Izbacivanje (brisanje) zadatog broja iz liste. Kako se


ovime pocetak liste moze izmeniti, vrednost pocetka liste
je povratna vrednost funkcije */
Elem* izbaci(Elem *lista, int k)
{
Elem *preth = NULL, *tekuci = lista, *zaizbacivanje;

while (tekuci != NULL)


/* Ukoliko tekuci pokazuje na clana
liste kojeg treba izbaciti */
if (tekuci->broj == k)
{
zaizbacivanje = tekuci;
tekuci = tekuci->sled;

if (preth != NULL )
preth->sled = tekuci;
/* Ovaj slucaj odnosi se na izbacivanje
elementa sa pocetka liste */
else lista = tekuci;

free (zaizbacivanje);
}
else
{
preth = tekuci;
tekuci = tekuci->sled;
}
return lista;
}

81
82 Milena VujosevicJanicic

main ()
{
Elem *lista;
int k;

lista = citaj ();


printf ("Ucitani lista = ");
pisi (lista);

printf("Koji element liste zelite da izbacite?\n");


scanf ("%d", &k);
printf ("Izostavlja se = %d\n", k);
printf ("Novi lista = ");
pisi (lista = izbaci (lista, k));
printf ("\n");

printf("Lista mi vise nije potrebna, oslobadjam memoriju!\n");


brisi (lista);
}
Primer 1.18.2 Rad sa listama - celine izdvojene u funkcije.
#include <stdio.h>
#include <stdlib.h>

typedef struct cvor {


int br;
struct cvor* sl;
} CVOR;

/* Pomocna funkcija koja kreira cvor liste sa datim sadrzajem.


Funkcija kreira cvor i postavlja mu sadrzaj na dati broj.
Funkcija vraca pokazivac na kreirani cvor. */
CVOR* napravi_cvor(int br) {
CVOR* novi = (CVOR*)malloc(sizeof(CVOR));
if (novi == NULL)
{
fprintf(stderr, "Greska prilikom alokacije memorije\n");
exit(1);
}
novi->br = br;
novi->sl = NULL;
return novi;
}

82
1.18 Liste 83

/* --------------------------------------------- */
/* Ispisivanje liste: iterativna verzija */
void ispisi_listu_i(CVOR* l) {
CVOR* t;
for (t = l; t != NULL; t=t->sl)
printf("%d ", t->br);
}

/* Ispisivanje liste: rekurzivna verzija */


void ispisi_listu_r(CVOR* l) {
if (l != NULL)
{
printf("%d ", l->br);
ispisi_listu_r(l->sl);
}
}

/* Ispisivanje liste unazad: rekurzivna verzija */


void ispisi_listu_unazad(CVOR* l) {
if (l != NULL)
{
ispisi_listu_unazad(l->sl);
printf("%d ", l->br);
}
}

/* --------------------------------------------- */
/* Oslobadjanje liste : iterativna verzija */
void oslobodi_listu_i(CVOR* l) {
while (l!=NULL)
{
CVOR* tmp = l->sl;
free(l);
l = tmp;
}
}

/* Oslobadjanje liste : rekurzivna verzija */


void oslobodi_listu_r(CVOR* l) {
if (l != NULL)
{
oslobodi_listu_r(l->sl);

83
84 Milena VujosevicJanicic

/* Prvo se oslobadja poslednji element liste */


free(l);
}
}

/* --------------------------------------------- */
/* Ubacuje dati broj na pocetak date liste.
Funkcija pozivaocu eksplicitno vraca pocetak
rezultujuce liste.*/
CVOR* ubaci_na_pocetak(CVOR* l, int br) {
CVOR* novi = napravi_cvor(br);
novi->sl = l;
return novi;
}

/* Funkcija vraca pocetak rezultujuce liste, a ubacuje


cvor na kraj bez pamcenja pokazivaca na kraj */
CVOR* ubaci_na_kraj(CVOR* l, int br) {
CVOR* novi = napravi_cvor(br);

if (l == NULL)
return novi;
else
{
CVOR* t;
/* Prodjemo do kraja liste */
for (t = l; t->sl!=NULL; t=t->sl)
;
t->sl = novi;

/* Pocetak se nije promenio */


return l;
}
}

/* Rekurzivna varijanta prethodne funkcije.


I ova funkcija vraca pokazivac na pocetak
rezultujuce liste */
CVOR* ubaci_na_kraj_rekurzivno(CVOR* l, int br) {
if (l == NULL)
{
CVOR* novi = napravi_cvor(br);
return novi;

84
1.18 Liste 85

l->sl = ubaci_na_kraj_rekurzivno(l->sl, br);


return l;
}

/* --------------------------------------------- */
/* Kljucna ideja u realizaciji ove funkcije je
pronalazenje poslednjeg elementa liste ciji
je kljuc manji od datog elementa br.
*/
CVOR* ubaci_sortirano(CVOR* pl, int br) {
CVOR* novi = napravi_cvor(br);

/* U sledeca dva slucaja ne postoji cvor


ciji je kljuc manji od datog broja (br)
- Prvi je slucaj prazne liste
- Drugi je slucaj kada je br manji od prvog elementa

U oba slucaja ubacujemo na pocetak liste.


*/
if (pl == NULL || br < pl->br)
{
novi->sl = pl;
pl = novi;
}
else
{
/* Krecemo od pocetka i idemo dalje sve dok t nije poslednji
manji element liste ili eventualno bas poslednji */
CVOR* t;
for(t = pl; t->sl!=NULL && t->sl->br < br; t=t->sl)
;
novi->sl = t->sl;
t->sl = novi;
}

return pl;
}

main() {
CVOR* l = NULL;
CVOR* s = NULL;

85
86 Milena VujosevicJanicic

int i;
for (i = 0; i<5; i++)
l = ubaci_na_kraj(l, i);
for (; i<10; i++)
l = ubaci_na_kraj_rekurzivno(l, i);

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


l = ubaci_na_pocetak(l, i);

ispisi_listu_i(l);
putchar(\n);

ispisi_listu_r(l);
putchar(\n);

ispisi_listu_unazad(l);
putchar(\n);

oslobodi_listu_i(l);

s = ubaci_sortirano(s, 5);
s = ubaci_sortirano(s, 8);
s = ubaci_sortirano(s, 7);
s = ubaci_sortirano(s, 6);
s = ubaci_sortirano(s, 4);

ispisi_listu_r(s);
putchar(\n);

oslobodi_listu_r(s);
}

1.18.2 Kruzna lista


Primer 1.18.3 (februar 2006.) Grupa od n plesaca (na cijim kos-
timima su u smeru kazaljke na satu redom brojevi od 1 do n) izvodi
svoju plesnu tacku tako sto formiraju krug iz kog najpre izlazi k-ti
plesac (odbrojava se pocev od plesaca oznacenog brojem 1 u smeru
kretanja kazaljke na satu). Preostali plesaci obrazuju manji krug
iz kog opet izlazi k-ti plesac (odbrojava se pocev od sledeceg suseda
prethodno izbacenog, opet u smeru kazaljke na satu). Izlasci iz kruga
se nastavljaju sve dok svi plesaci ne budu iskljuceni. Celi brojevi n,

86
1.18 Liste 87

pocetak ciklicne liste

A B C ... Z

Slika 1.2: Kruzna lista

k (k < n) se ucitavaju sa standardnog ulaza. Napisati program


koji ce na standardni izlaz ispisati redne brojeve plesaca u redosledu
napustanja kruga.
PRIMER: za n = 5, k = 3 redosled izlaska je 3 1 5 2 4.

1.18.3 Stek
Primer 1.18.4 Program proverava da li su zagrade ( i ) dobro up-
arene.

#include <stdio.h>
#include <stdlib.h>

main()
{
int c;
int br_otv = 0;
while((c=getchar()) != EOF)
{
switch(c)
{
case (:
br_otv++;
break;
case ):
br_otv--;
if (br_otv<0)
{
printf("Visak zatvorenih zagrada\n");
exit(1);
}

87
88 Milena VujosevicJanicic

}
}

if (br_otv == 0)
printf("Zagrade su u redu\n");
else
printf("Visak otvorenih zagrada\n");
}
Primer 1.18.5 Program proverava da li su zagrade (, [, {, }, ] i )
dobro uparene - staticka implementacija steka.
#include <stdio.h>
#include <stdlib.h>
#define MAX_ZAGRADA 100

int odgovarajuce(char z1, char z2) {


return (z1 == ( && z2 == )) ||
(z1 == { && z2 == }) ||
(z1 == [ && z2 == ]);
}

main()
{
int c;
char otv_zagrade[MAX_ZAGRADA];
int br_otv = 0;

while((c=getchar()) != EOF)
{
switch(c)
{
case (:
case {:
case [:
{
otv_zagrade[br_otv] = c;
br_otv++;
break;
}
case ]:
case }:
case ):
if (br_otv>0 && odgovarajuce(otv_zagrade[br_otv-1], c))

88
1.18 Liste 89

{
br_otv--;
}
else
{
printf("Visak zatvorenih zagrada: %c u liniji %d\n", c, br_linija);
exit(1);
}
}
}

if (br_otv == 0)
printf("Zagrade su u redu\n");
else
printf("Visak otvorenih zagrada\n");
}

vrh steka (i dodavanje i brisanje push i pop)

X Y ... A NULL

novi element

novi vrh steka

Y X V ... A NULL

vrh steka nakon brisanja

X V ... A NULL

Slika 1.3: Stek

Primer 1.18.6 Program ilustruje proveru validnosti HTML datoteke

89
90 Milena VujosevicJanicic

- proverava se da li su etikete dobro uparene pri cemu se stek imple-


mentira preko liste.

#include <stdio.h>
#include <string.h>
#include <ctype.h>

/* Maksimalna duzina etikete */


#define MAX_TAG 100

#define OTVORENA 1
#define ZATVORENA 2
#define GRESKA 0

/* Funkcija ucitava sledecu etiketu i smesta njen naziv u niz s


duzine max. Vraca OTVORENA za otvorenu etiketu, ZATVORENA za
zatvorenu etiketu, odnosno GRESKA inace */
int gettag(char s[], int max) {
int c, i;
int zatvorenost=OTVORENA;

/* Preskacemo sve do znaka < */


while ((c=getchar())!=EOF && c!=<)
;
/* Nismo naisli na etiketu */
if (c==EOF)
return GRESKA;

/* Proveravamo da li je etiketa zatvorena */


if ((c=getchar())==/)
zatvorenost=ZATVORENA;
else
/* Funkcija ungetc vraca karakter c na standardni ulaz */
ungetc(c,stdin);

/* Citamo etiketu dok nailaze slova i smestamo ih u nisku */


for (i=0; isalpha(c=getchar()) && i<max-1; s[i++] = c)
;
/* Vracamo poslednji karakter na ulaz jer je to bio neki karakter
koji nije slovo*/
ungetc(c,stdin);

s[i]=\0;

90
1.18 Liste 91

/* Preskacemo atribute do znaka > */


while ((c=getchar())!=EOF && c!=>)
;

/* Greska ukoliko nismo naisli na > */


return c==> ? zatvorenost : GRESKA;
}

/* Stek ce biti implementiran koriscenjem liste */


typedef struct
cvor {
char tag[MAX_TAG];
struct cvor* sledeci;
} CVOR;

CVOR* stek = NULL;

main()
{
char tag[MAX_TAG];
int zatvorenost;
while ((zatvorenost = gettag(tag, MAX_TAG))>0)
{
if (zatvorenost==OTVORENA)
{
/* Svaku otvorenu etiketu stavljamo na stek */

CVOR* tmp = (CVOR*)malloc(sizeof(CVOR));


if (tmp == NULL)
{
printf("Greska prilikom alokacije memorije!\n");
return 1;
}
strcpy(tmp->tag, tag);
tmp->sledeci = stek;
stek = tmp;

printf("Postavio <%s> na stek\n", stek->tag);


}

else
{

91
92 Milena VujosevicJanicic

/* Za zatvorene etikete proveravamo da li je stek prazan


odnosno da li se na vrhu steka nalazi odgovarajuca
otvorena etiketa */
if (stek != NULL && strcmp(stek->tag, tag) == 0)
{
/* Uklanjamo etiketu sa steka */
CVOR* tmp = stek->sledeci;
free(stek);
stek = tmp;
}
else
{
/* Prijavljujemo gresku */
printf("Neodgovarajuci tag : </%s>!\n",tag);
exit(1);
}
}
}

if (stek == NULL) printf("Datoteka je ispravna\n ");


else
{
printf("Visak otvorenih etiketa!\n");
/* Oslobadjamo memoriju koja je ostala
zarobljena na steku. */
while(stek!=NULL)
{
CVOR* tmp = stek->sledeci;
free(stek);
stek = tmp;
}
}
}

1.18.4 Dvostruko povezane liste


Primer 1.18.7 Napisati funkciju koja omogucava umetanje cvora u
dvostruko povezanu kruznu listu kao i izbacivanje cora iz dvostruko
povezane kruzne liste. Omoguciti i stampanje podataka koje cuva
lista.

/* Program implementira deciju razbrajalicu eci-peci-pec i sluzi


da ilustruje rad sa dvostruko povezanim kruznim listama */

92
1.18 Liste 93

pocetak dvostruko povezane liste kraj liste

...
NULL A B C ... Z NULL

Slika 1.4: Dvostruko povezana lista

#include <stdlib.h>
#include <stdio.h>

/* Dvostruko povezana lista */


typedef struct _cvor {
int broj;
struct _cvor* prethodni, *sledeci;
} cvor;

/* Umetanje u dvostruko povezanu listu */


cvor* ubaci(int br, cvor* lista) {
cvor* novi=(cvor*)malloc(sizeof(cvor));
if (novi==NULL)
{ printf("Greska prilikom alokacije memorije \n");
exit(1);
}
novi->broj=br;

if (lista==NULL)
{ novi->sledeci=novi;
novi->prethodni=novi;
return novi;
}
else
{ novi->prethodni=lista;
novi->sledeci=lista->sledeci;
lista->sledeci->prethodni=novi;
lista->sledeci=novi;
return novi;

93
94 Milena VujosevicJanicic

}
}

/* Ispis liste */
void ispisi(cvor* lista)
{
if (lista!=NULL)
{ cvor* tekuci=lista;
do
{ printf("%d\n",tekuci->broj);
tekuci=tekuci->sledeci;
} while (tekuci!=lista);
}
}

/* Izbacivanje datog cvora iz liste, funkcija


vraca pokazivac na novonastalu listu */
cvor* izbaci(cvor* lista) {
if (lista!=NULL)
{ cvor* sledeci=lista->sledeci;
if (lista==lista->sledeci)
{ printf("Pobednik %d\n",lista->broj);
free(lista);
return NULL;
}

printf("Ispada %d\n",lista->broj);

lista->sledeci->prethodni=lista->prethodni;
lista->prethodni->sledeci=lista->sledeci;
free(lista);
return sledeci;
}
else return NULL;
}

main() {
/* Umecemo petoro dece u listu */
cvor* lista = NULL;
lista=ubaci(1,lista);
lista=ubaci(2,lista);
lista=ubaci(3,lista);
lista=ubaci(4,lista);

94
1.18 Liste 95

lista=ubaci(5,lista);
lista=lista->sledeci;

/*Proverimo da smo dobro formirali listu*/


ispisi(lista);

int smer = 0;
/* Dok ima dece u listi */
while(lista!=NULL)
{ int i;

/* brojimo 13 slogova u krug i u svakom brojanju


menjamo smer obilaska*/
for (i=1; i<=13; i++)
lista = 1-smer ? lista->sledeci : lista->prethodni;

lista=izbaci(lista);
smer = smer ? 0 : 1;
}
}
Primer 1.18.8 Program ispisuje broj pojavljivanja za svaku od reci
koja se pojavila u tekstu unetom sa standardnog ulaza. Verzija sa
(sortiranom) listom.
#include <stdlib.h>
#include <stdio.h>

/* Definicija cvora liste */


typedef struct _cvor
{
char ime[80];
int br_pojavljivanja;
struct _cvor* sledeci;
} cvor;

/* Funkcija ispisuje listu rekurzivno, pocevsi od poslednjeg


elementa */
void ispisi_listu(cvor* pocetak)
{
if (pocetak!=NULL)
{
ispisi_listu(pocetak->sledeci);
printf("%s %d\n",pocetak->ime,pocetak->br_pojavljivanja);

95
96 Milena VujosevicJanicic

}
}

/* Funkcija koja brise listu */


void obrisi_listu(cvor* pocetak)
{
if (pocetak!=NULL)
{
obrisi_listu(pocetak->sledeci);
free(pocetak);
}
}

/* Funkcija ubacuje rekurzivno datu rec u listu koja je


leksikografski sortirana, na odgovarajuce mesto i vraca
pokazivac na novi pocetak liste */
cvor* ubaci_sortirano(cvor* pocetak, char* rec)
{
int cmp;
/* Ukoliko je lista prazna ubacujemo na pocetak liste*/
if (pocetak==NULL)
{ pocetak=(cvor*)malloc(sizeof(cvor));
if (pocetak == NULL)
{
printf("Greska prilikom alokacije memorije!\n");
exit(1);
}
strcpy(pocetak->ime,rec);
pocetak->br_pojavljivanja=1;
return pocetak;
}
/* Ukoliko lista nije prazna poredimo rec sa elementom u glavi */
cmp=strcmp(pocetak->ime,rec);
/* Ukoliko je rec pronadjena samo uvecavamo njen broj
pojavljivanja */
if (cmp==0)
{ pocetak->br_pojavljivanja++;
return pocetak;
}
/* Ukoliko je rec koju ubacujemo veca od tekuce reci, ubacujemo je
rekurzivno u rep */
else if (cmp>0)
{ pocetak->sledeci=ubaci_sortirano(pocetak->sledeci,rec);

96
1.18 Liste 97

return pocetak;
}
/* Ukoliko je rec koju ubacujemo manja od tekuce reci, gradimo novi
cvor i ubacujemo ga ispred pocetka */
else
{ cvor* novi=malloc(sizeof(cvor));
if (novi == NULL)
{
printf("Greska prilikom alokacije memorije!\n");
exit(1);
}
strcpy(novi->ime,rec);
novi->br_pojavljivanja=1;
novi->sledeci=pocetak;
return novi;
}
}

/* Pomocna funkcija koja cita rec sa standardnog ulaza i vraca


njenu duzinu, odnosno -1 ukoliko se naidje na EOF */
int getword(char word[], int lim) {
int c, i=0;
while (!isalpha(c=getchar()) && c!=EOF)
;

if (c==EOF)
return -1;
do
{ word[i++]=c;
}while (i<lim-1 && isalpha(c=getchar()));

word[i]=\0;
return i;
}

/* Funkcija koja rekurzivno pronalazi datu rec u datoj listi.


Funkcija vraca pokazivac na cvor u kome je nadjena rec, ili
NULL ukoliko rec nije nadjena */
cvor* nadji_rec(cvor* lista, char rec[])
{
if (lista==NULL)
return NULL;

97
98 Milena VujosevicJanicic

if (strcmp(lista->ime,rec)==0)
return lista;

return nadji_rec(lista->sledeci,rec);
}

main()
{
cvor* lista=NULL;
char procitana_rec[80];
while(getword(procitana_rec,80)!=-1)
{ cvor* pronadjen=nadji_rec(lista,procitana_rec);
if (pronadjen!=NULL)
pronadjen->br_pojavljivanja++;
else
lista=ubaci_sortirano(lista,procitana_rec);
}
ispisi_listu(lista);
obrisi_listu(lista);
}

1.19 Drvo
Primer 1.19.1 Binarno pretrazivacko drvo - drvo sadrzi cele bro-
jeve.

/* Program demonstrira rad sa binarnim pretrazivackim drvetima.


Drveta sadrze cele brojeve i sortirana su po velicini.
Za svaki cvor, levo podstabla sadrzi manje elemente, dok desno
podstablo sadrzi vece.
*/

#include <stdlib.h>
#include <stdio.h>

typedef struct _cvor


{
int broj;
struct _cvor *l, *d;
} cvor;

98
1.19 Drvo 99

NULL NULL

NULL NULL NULL

NULL NULL

Slika 1.5: Stablo

cvor* napravi_cvor(int b) {
cvor* novi = (cvor*)malloc(sizeof(cvor));
if (novi == NULL)
{
fprintf(stderr, "Greska prilikom
alokacije memorije");
exit(1);
}
novi->broj = b;
novi->l = NULL;
novi->d = NULL;
return novi;
}

/* Funkcija umece broj br u drvo ciji je koren dat preko

99
100 Milena VujosevicJanicic

17, 12, 21, 15, 5, 14


17

12 21

NULL NULL

5 15

NULL NULL NULL

inf ix : 5, 12, 14, 15, 17, 21


14 pref ix : 17, 12, 5, 15, 14, 21

postf ix : 5, 14, 15, 12, 21, 17


NULL NULL

Slika 1.6: Ure eno stablo




pokazivaca drvo. Funkcija vraca pokazivac na koren


novog drveta */
cvor* ubaci_u_drvo(cvor* drvo, int b)
{
if (drvo == NULL)
return napravi_cvor(b);

if (b < drvo->broj)
drvo->l = ubaci_u_drvo(drvo->l, b);
else
drvo->d = ubaci_u_drvo(drvo->d, b);

return drvo;
}

100
1.19 Drvo 101

/* Funkcija proverava da li dati broj postoji u drvetu */


int pronadji(cvor* drvo, int b)
{
if (drvo == NULL)
return 0;

if (drvo->broj == b)
return 1;

if (b < drvo->broj)
return pronadji(drvo->l, b);
else
return pronadji(drvo->d, b);
}

/* Funkcija ispisuje sve cvorove drveta u infiksnom redosledu */


void ispisi_drvo(cvor* drvo) {
if (drvo != NULL)
{
ispisi_drvo(drvo->l);
printf("%d ", drvo->broj);
ispisi_drvo(drvo->d);
}
}

void obrisi_drvo(cvor* drvo) {


if (drvo != NULL)
{
obrisi_drvo(drvo->l);
obrisi_drvo(drvo->d);
free(drvo);
}
}

/* Funkcija sumira sve vrednosti binarnog stabla */


int suma_cvorova(cvor* drvo)
{
if (drvo == NULL)
return 0;
return suma_cvorova(drvo->l) +
drvo->broj +
suma_cvorova(drvo->d);

101
102 Milena VujosevicJanicic

int broj_cvorova(cvor* drvo)


{
if (drvo == NULL)
return 0;
return broj_cvorova(drvo->l) +
1 +
broj_cvorova(drvo->d);
}

int broj_listova(cvor* drvo)


{
if (drvo == NULL)
return 0;
if (drvo->l == NULL && drvo->d == NULL)
return 1;
return broj_listova(drvo->l) +
broj_listova(drvo->d);
}

int suma_listova(cvor* drvo)


{
if (drvo == NULL)
return 0;

if (drvo->l == NULL && drvo->d == NULL)


return drvo->broj;

return suma_listova(drvo->l) +
suma_listova(drvo->d);
}

void ispisi_listove(cvor* drvo)


{
if (drvo == NULL)
return;

ispisi_listove(drvo->l);

if (drvo->l == NULL && drvo->d == NULL)


printf("%d ", drvo->broj);

102
1.19 Drvo 103

ispisi_listove(drvo->d);
}

/* Funkcija pronalazi maksimalnu vrednost u drvetu


Koristi se cinjenica da je ova vrednost
smestena u najdesnjem listu */
int max_vrednost(cvor* drvo)
{
if (drvo==NULL)
return 0;

if (drvo->d==NULL)
return drvo->broj;

return max_vrednost(drvo->d);
}

/* Iterativna funkcija za pronalazenje maksimalne vrednosti. */


int max_vrednost_nerekurzivno(cvor* drvo)
{
if (drvo==NULL)
return 0;
else
{
cvor* tekuci;
for (tekuci=drvo; tekuci->d!=NULL; tekuci=tekuci->d)
;
return tekuci->broj;
}
}

/* Funkcija racuna "dubinu" binarnog stabla */


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

int dubina(cvor* drvo)


{
if (drvo==NULL)
return 0;
else
{ int dl=dubina(drvo->l);
int dd=dubina(drvo->d);
return 1+max(dl,dd);

103
104 Milena VujosevicJanicic

}
}

main()
{
cvor* drvo = NULL;
drvo = ubaci_u_drvo(drvo, 1);
drvo = ubaci_u_drvo(drvo, 8);
drvo = ubaci_u_drvo(drvo, 5);
drvo = ubaci_u_drvo(drvo, 3);
drvo = ubaci_u_drvo(drvo, 7);
drvo = ubaci_u_drvo(drvo, 6);
drvo = ubaci_u_drvo(drvo, 9);

if (pronadji(drvo, 3))
printf("Pronadjeno 3\n");
if (pronadji(drvo, 2))
printf("Pronadjeno 2\n");
if (pronadji(drvo, 7))
printf("Pronadjeno 7\n");

ispisi_drvo(drvo);

putchar(\n);
printf("Suma cvorova : %d\n", suma_cvorova(drvo));
printf("Broj cvorova : %d\n", broj_cvorova(drvo));
printf("Broj listova : %d\n", broj_listova(drvo));
printf("Suma listova : %d\n", suma_listova(drvo));
printf("Dubina drveta : %d\n", dubina(drvo));
printf("Maximalna vrednost : %d\n", max_vrednost(drvo));

ispisi_listove(drvo);

obrisi_drvo(drvo);
}

/*
Pronadjeno 3
Pronadjeno 7
1 3 5 6 7 8 9
Suma cvorova : 39
Broj cvorova : 7
Broj listova : 3

104
1.19 Drvo 105

Suma listova : 18
Dubina drveta : 5
Maximalna vrednost : 9
3 6 9
*/
Primer 1.19.2 Program sa ulaza cita tekst i ispisuje broj pojavlji-
vanja svake od reci koje su se javljale u tekstu. Radi poboljsanja
efikasnosti, prilikom brojanja reci koristi se struktura podataka pogodna
za leksikografsku pretragu - u ovom slucaju binarno pretrazivacko
drvo.
#include <stdlib.h>
#include <stdio.h>

/* Cvor drveta sadrzi ime reci i


broj njenih pojavljivanja */
typedef struct _cvor {
char ime[80];
int br_pojavljivanja;
struct _cvor* levo, *desno;
} cvor;

/* Funkcija ispisuje drvo u inorder redosledu */


void ispisi_drvo(cvor* drvo)
{
if (drvo!=NULL)
{
ispisi_drvo(drvo->levo);
printf("%s %d\n",drvo->ime,drvo->br_pojavljivanja);
ispisi_drvo(drvo->desno);
}
}

/* Funkcija uklanja binarno drvo iz memorije */


void obrisi_drvo(cvor* drvo)
{
if (drvo!=NULL)
{
obrisi_drvo(drvo->levo);
obrisi_drvo(drvo->desno);
free(drvo);
}
}

105
106 Milena VujosevicJanicic

/* Funkcija ubacuje datu rec u dato drvo


i vraca pokazivac na koren drveta */
cvor* ubaci(cvor* drvo, char rec[]) {
/* Ukoliko je drvo prazno gradimo novi cvor */
if (drvo==NULL)
{
cvor* novi_cvor=(cvor*)malloc(sizeof(cvor));
if (novi_cvor==NULL)
{
printf("Greska prilikom alokacije memorije\n");
exit(1);
}
strcpy(novi_cvor->ime, rec);
novi_cvor->br_pojavljivanja=1;
return novi_cvor;
}

/* Uporedjujemo rec koju smo ucitali sa recju koja


se nalazi u cvoru drveta*/
int cmp = strcmp(rec, drvo->ime);

/* Ukoliko rec vec postoji u drvetu


uvecavamo njen broj pojavljivanja */
if (cmp==0)
{ drvo->br_pojavljivanja++;
return drvo;
}

/* Ukoliko je rec koju ubacujemo leksikografski


ispred reci koja je u korenu drveta, rec
ubacujemo u levo podstablo */
if (cmp<0)
{ drvo->levo=ubaci(drvo->levo, rec);
return drvo;
}

/* Ukoliko je rec koju ubacujemo


leksikografski iza reci koja je u
korenu drveta, rec ubacujemo u desno
podstablo */
if (cmp>0)
{ drvo->desno=ubaci(drvo->desno, rec);

106
1.19 Drvo 107

return drvo;
}
}

/* Pomocna funkcija koja cita rec sa


standardnog ulaza i vraca njenu
duzinu, odnosno -1 ukoliko se naidje na EOF.
Ukoliko umesto funkcije getword koristimo
funkciju gettag program ce ispisivati
broj pojavljivanja svakog od tagova sa ulaza */
int getword(char word[], int lim) {
int c, i=0;
while (!isalpha(c=getchar()) && c!=EOF)
;

if (c==EOF)
return -1;
do
{
word[i++]=c;
} while (i<lim-1 && isalpha(c=getchar()));

word[i]=\0;
return i;
}

main() {
/* Drvo je na pocetku prazno */
cvor* drvo=NULL;
char procitana_rec[80];

/* Citamo rec po rec dok ne


naidjemo na kraj datoteke i
ubacujemo ih u drvo */
while(getword(procitana_rec,80)!=-1)
drvo=ubaci(drvo,procitana_rec);

/* Ispisujemo drvo */
ispisi_drvo(drvo);

/* Uklanjamo ga iz memorije */
obrisi_drvo(drvo);
}

107
108 Milena VujosevicJanicic

Primer 1.19.3 Program iz datoteke cita tekst i ispisuje n najfrekvent-


nijih reci koje su se javljale u tekstu.
Radi poboljsanja efikasnosti, prilikom brojanja reci koristi se struk-
tura podataka pogodna za leksikografsku pretragu - u ovom slucaju
binarno pretrazivacko drvo.
Na kraju rada, cvorovi drveta se presortiraju na osnovu broja
pojavljivanja. Zbog ovoga je potrebno cuvati niz pokazivaca na ra-
zlicite cvorove drveta.
Da bismo ispisali 10 najfrekventnijih etiketa, potrebno je zameniti
funkciju getword funkcijom gettag.

#include <stdlib.h>
#include <stdio.h>

/* Cvor drveta sadrzi ime reci i


broj njenih pojavljivanja */
typedef struct _cvor {
char ime[80];
int br_pojavljivanja;
struct _cvor* levo, *desno;
} cvor;

/* Gradimo niz pokazivaca na cvorove drveta koji ce


nam sluziti da po prihvatanju svih reci izvrsimo
sortiranje po broju pojavljivanja */

#define MAX_BROJ_RAZLICITIH_RECI 1000

cvor* razlicite_reci[MAX_BROJ_RAZLICITIH_RECI];

/* Tekuci broj cvorova drveta */


int broj_razlicitih_reci=0;

/* Funkcija uklanja binarno drvo iz memorije */


void obrisi_drvo(cvor* drvo)
{
if (drvo!=NULL)
{ obrisi_drvo(drvo->levo);
obrisi_drvo(drvo->desno);
free(drvo);
}
}

108
1.19 Drvo 109

/* Funkcija ubacuje datu rec u dato drvo i vraca pokazivac na


koren drveta */
cvor* ubaci(cvor* drvo, char rec[])
{
/* Ukoliko je drvo prazno gradimo novi cvor */
if (drvo==NULL)
{
cvor* novi_cvor=(cvor*)malloc(sizeof(cvor));
if (novi_cvor==NULL)
{
printf("Greska prilikom alokacije memorije\n");
exit(1);
}
strcpy(novi_cvor->ime, rec);
novi_cvor->br_pojavljivanja=1;

/* pokazivac na novo napravljeni cvor smestamo u niz


pokazivaca na sve cvorove drveta */
razlicite_reci[broj_razlicitih_reci++] = novi_cvor;

return novi_cvor;
}
int cmp = strcmp(rec, drvo->ime);

/* Ukoliko rec vec postoji u drvetu


uvecavamo njen broj pojavljivanja */
if (cmp==0)
{ drvo->br_pojavljivanja++;
return drvo;
}

/* Ukoliko je rec koju ubacujemo leksikografski ispred


reci koja je u korenu drveta, rec ubacujemo
u levo podstablo */
if (cmp<0)
{ drvo->levo=ubaci(drvo->levo, rec);
return drvo;
}

/* Ukoliko je rec koju ubacujemo


leksikografski iza reci koja je u
korenu drveta, rec ubacujemo
u desno podstablo */

109
110 Milena VujosevicJanicic

if (cmp>0)
{ drvo->desno=ubaci(drvo->desno, rec);
return drvo;
}
}

/* Pomocna funkcija koja cita rec iz date datoteke i vraca


njenu duzinu, odnosno -1 ukoliko se naidje na EOF */
int getword(char word[], int lim, FILE* ulaz)
{
int c, i=0;
/* Umesto funkcije getchar koristimo fgetc
za rad sa datotekama */
while (!isalpha(c=fgetc(ulaz)) && c!=EOF)
;
if (c==EOF)
return -1;
do
{ word[i++]=c;
}while (i<lim-1 && isalpha(c=fgetc(ulaz)));

word[i]=\0;
return i;
}

/* Funkcija poredjenja za funkciju qsort. */


int poredi_br_pojavljivanja(const void* a, const void* b)
{
return
/* Konverzija pokazivaca b iz pokazivaca
na tip void u pokazivac na cvor jer
nam je svaki element niza koji sortiramo
tipa pokazivaca na cvor */
(*(cvor**)b)->br_pojavljivanja
-
(*(cvor**)a)->br_pojavljivanja;
}

main(int argc, char* argv[])


{
int i;

110
1.19 Drvo 111

/* Drvo je na pocetku prazno */


cvor* drvo=NULL;
char procitana_rec[80];
FILE* ulaz;

if (argc!=2)
{ fprintf(stderr,"Greska :
Ocekivano ime datoteke\n");
exit(1);
}

if ((ulaz=fopen(argv[1],"r"))==NULL)
{
fprintf(stderr,"Greska : nisam uspeo da otvorim datoteku %s\n");
exit(1);
}

/* Citamo rec po rec dok ne naidjemo na kraj datoteke i


ubacujemo ih u drvo */
while(getword(procitana_rec,80,ulaz)!=-1)
drvo=ubaci(drvo,procitana_rec);

/* Sortiramo niz pokazivaca na cvorove


drveta po broju pojavljivanja */
qsort(razlicite_reci,
broj_razlicitih_reci,
sizeof(cvor*),
poredi_br_pojavljivanja);

/* Ispisujemo prvih 10 (ukoliko ih ima)


reci i njihov broj pojavljivanja */
for (i=0; i<10 && i<broj_razlicitih_reci; i++)
printf("%s - %d\n",razlicite_reci[i]->ime,
razlicite_reci[i]->br_pojavljivanja);

/* Uklanjamo drvo iz memorije */


obrisi_drvo(drvo);

fclose(ulaz);
}

111
112 Milena VujosevicJanicic

1.20 Grafovi
Graf1 G=(V,E) sastoji se od skupa V cvorova i skupa E grana. Grane
predstavljaju relacije izme u cvorova i odgovara paru cvorova. Graf
moze biti usmeren (orijentisan), ako su mu grane ure eni parovi i
neusmeren (neorjentisan) ako su grane neure eni parovi.
Uobicajena su dva nacina predstavljanja grafova. To su matrica
povezanosti grafa i lista povezanosti.
Matrica povezanosti je kvadratna matrica dimenzije n, pri cemu
je n broj cvorova u grafu, takva da je element na preseku i-te vrste
i j-te kolone jednak jedinici ukoliko postoji grana u grafu od i-tog
do j-tog cvora, inace je nula.
Umesto da se i sve nepostojece grane eksplicitno predstavljaju u
matrici povezanosti, mogu se formirati povezane liste od jedinica iz
i-te vrste za i=1,2,...,n. To je lista povezanosti. Svakom cvoru se
pridruzuje povezana lista, koja sadrzi sve grane susedne tom cvoru.
Graf je predstavljen vektorom lista. Svaki elemenat vektora sadrzi
ime (indeks) cvora i pokazivac na njegovu listu cvorova.
Prvi problem na koji se nailazi pri konstrukciji bilo kog algo-
ritma za obradu grafa je kako pregledati ulaz. Postoje dva osnovna
algoritma za obilazak grafa: pretraga u dubinu (DFS, skracenica od
depth-first-search) i pretraga u sirinu (BFS, skracenica od breadth-
first-search).
Kod DFS algoritma, obilazak zapocinje iz proizvoljnog zadatog
cvora r koji se naziva koren pretrage u dubinu. Koren se oznacava
kao posecen. Zatim se bira proizvoljan neoznacen cvor r1, susedan
sa r, pa se iz cvora r1 rekurzivno startuje pretraga u dubinu. Iz
nekog nivoa rekurzije izlazi se kad se nai e na cvor v kome su svi
susedi vec oznaceni.
Primer 1.20.1 Primer reprezentovanja grafa preko matrice povezanosti.
U programu se unosi neorijentisan graf i DFS algoritmom se utvr uju 

cvrovi koji su dostizni iz cvora 0.


#include <stdlib.h>
#include <stdio.h>

int** alociraj_matricu(int n)
{ int **matrica;
int i;
matrica=malloc(n*sizeof(int*));
if (matrica==NULL)
1 Tekst i primeri preuzeti od Jelene Tomasevic, url: www.matf.bg.ac.yu/jtomasevic, zas-

novano na materijalu Algoritmi, Miodrag Zivkovic i http://www.matf.bg.ac.yu/filip

112
1.20 Grafovi 113

{
printf("Greska prilikom alokacije memorije\n");
exit(1);
}

for (i=0; i<n; i++)


{
/* Funkcija calloc popunjava rezervisan
prostor u memoriji nulama. */
matrica[i]=calloc(n,sizeof(int));
if (matrica[i]==NULL)
{
printf("Greska prilikom alokacije memorije\n");
exit(1);
}
}
return matrica;
}

void oslobodi_matricu(int** matrica, int n)


{ int i;
for (i=0; i<n; i++)
free(matrica[i]);
free(matrica);
}

int* alociraj_niz(int n)
{ int* niz;
niz=calloc(n,sizeof(int));
if (niz==NULL)
{
printf("Greska prilikom alokacije memorije\n");
exit(1);
}
return niz;
}

void oslobodi_niz(int* niz)


{ free(niz);
}

void unesi_graf(int** graf, int n)


{ int i,j;

113
114 Milena VujosevicJanicic

for (i=0; i<n; i++)


for (j=i; j<n; j++)
{ printf("Da li su element %d i %d povezani : ",i,j);
do
{ scanf("%d",&graf[i][j]);
/* Radimo sa neusmerenim grafom */
graf[j][i]=graf[i][j];
} /* Obezbedjujemo ispravan unos */
while (graf[i][j]!=0 && graf[i][j]!=1);
}
}

void ispisi_graf(int** graf, int n)


{ int i,j;
for (i=0; i<n; i++)
{ for (j=0; j<n; j++)
printf("%d",graf[i][j]);
printf("\n");
}
}

/* Broj cvorova grafa (dimenzija matrice) */


int n;
/* Matrica povezanosti */
int **graf;

/* Pomocni vektor koji govori o tome koji su cvorovi posecivani


tokom DFS obilaska */
int *posecen;

/* Rekurzivna implementacija DFS algoritma */


void poseti(int i)
{ int j;
posecen[i]=1;
printf("Posecujem cvor %d\n",i);
for (j=0; j<n; j++)
if (graf[i][j] && !posecen[j])
poseti(j);
}

114
1.20 Grafovi 115

main()
{
int i, j;
printf("Unesi broj cvorova : ");
scanf("%d",&n);

graf=alociraj_matricu(n);
unesi_graf(graf,n);
ispisi_graf(graf,n);

posecen=alociraj_niz(n);
poseti(0);

oslobodi_niz(posecen);
oslobodi_matricu(graf,n);
}
Primer 1.20.2 Primer predstavljanja grafa preko niza listi suseda
svakog od cvorova grafa U programu se unosi graf i DFS algoritmom
se utvrdjuje koji su cvorovi dostizni iz cvora 0.
#include <stdlib.h>
#include <stdio.h>

/* Cvor liste suseda */


typedef struct _cvor_liste
{ int broj; /* Indeks suseda */
struct _cvor_liste* sledeci;
} cvor_liste;

/* Ubacivanje na pocetak liste */


cvor_liste* ubaci_u_listu(cvor_liste* lista, int broj)
{ cvor_liste* novi=malloc(sizeof(cvor_liste));
if (novi==NULL)
{
printf("Greska prilikom alokacije memorije\n");
exit(1);
}
novi->broj=broj;
novi->sledeci=lista;
return novi;
}

115
116 Milena VujosevicJanicic

/* Rekurzivno brisanje liste */


void obrisi_listu(cvor_liste* lista)
{ if (lista)
{ obrisi_listu(lista->sledeci);
free(lista);
}
}

/* Ispis liste */
void ispisi_listu(cvor_liste* lista)
{ if (lista)
{ printf("%d ",lista->broj);
ispisi_listu(lista->sledeci);
}
}

/* Graf predstavlja niz pokazivaca na pocetke listi suseda */


#define MAX_BROJ_CVOROVA 100
cvor_liste* graf[MAX_BROJ_CVOROVA];
int broj_cvorova;

/* Rekurzivna implementacija DFS algoritma */


int posecen[MAX_BROJ_CVOROVA];
void poseti(int i)
{ cvor_liste* sused;
printf("Posecujem cvor %d\n",i);
posecen[i]=1;
for( sused=graf[i]; sused!=NULL; sused=sused->sledeci)
if (!posecen[sused->broj])
poseti(sused->broj);
}

main()
{
int i;
printf("Unesi broj cvorova grafa : ");
scanf("%d",&broj_cvorova);
for (i=0; i<broj_cvorova; i++)
{ int br_suseda,j;

graf[i]=NULL;

116
1.21 Razno 117

printf("Koliko cvor %d ima suseda : ",i);


scanf("%d",&br_suseda);
for (j=0; j<br_suseda; j++)
{ int sused;
do
{
printf("Unesi broj %d.-tog suseda cvora %d : ",j,i);
scanf("%d",&sused);
} while (sused<1 && sused>broj_cvorova);
graf[i]=ubaci_u_listu(graf[i],sused-1);
}
}

for (i=0; i<broj_cvorova; i++)


{ printf("%d - ",i);
ispisi_listu(graf[i]);
printf("\n");
}

poseti(0);
}

1.21 Razno
k
Primer 1.21.1 Stepenovanje prirodnog broja efikasno: nk = (n 2 )2
k1
ako je k parno ili nk = n(n 2 )2 ako je k neparno.
int stepen(int n, int k)
{
int p, s;
if (k==1) s=n;
else
{
p=stepen(n,k/2);
if(k%2==0) s=p*p;
else s=p*p*n;
}
return s;
}
Primer 1.21.2 MINESWEEPER - primer jednostavne igrice.
#include <stdlib.h>

117
118 Milena VujosevicJanicic

#include <stdio.h>
#include <time.h>

/* Dimenzija table */
int n;

/* Tabla koja sadrzi 0 i 1 u zavisnosti


od toga da li na polju postoji bomba */
int** bombe;

#define PRAZNO (-1)


#define ZATVORENO 0
#define ZASTAVICA 9

/* Tabla koja opisuje tekuce stanje igre.


Moze da sadrzi sledece vrednosti :
ZATVORENO - opisuje polje
koje jos nije bilo otvarano
PRAZNO - polje na kome ne
postoji ni jedna bomba
BROJ od 1-8 - polje koje je
otvoreno i na kome pise
koliko bombi postoji u okolini
ZASTAVICA - polje koje je korisnik
oznacio zastavicom
*/
int** stanje;

/* Ukupan broj bombi */


int broj_bombi;

/* Ukupan broj postavljenih zastavica */


int broj_zastavica = 0;

/* Pomocne funkcije za rad sa matricama */


int** alociraj(int n)
{
int i;
int** m=(int**)malloc(n*sizeof(int*));
for (i=0; i<n; i++)
m[i]=(int *)calloc(n,sizeof(int));
return m;
}

118
1.21 Razno 119

void obrisi(int** m, int n)


{ int i;
for (i=0; i<n; i++)
free(m[i]);

free(m);
}

/* Funkcija postavlja bombe */ void postavi_bombe()


{ broj_bombi=(n*n)/6;
int kolona;
int vrsta;
int i;

/* Inicijalizujemo generator slucajnih brojeva */


srand(time(NULL));

for (i=0; i<broj_bombi; i++)


{ /* Racunamo slucajni polozaj bombe */
kolona=rand()%n;
vrsta=rand()%n;

/* Ukoliko bomba vec postoji tu,


opet idemo u istu iteraciju */
if (bombe[vrsta][kolona]==1)
{ i--;
continue;
}

/* Postavljamo bombu */
bombe[vrsta][kolona]=1;
}
}

/* Funkcija ispisuje tablu sa bombama */


void ispisi_bombe()
{
int i,j;
for (i=0; i<n; i++)
{ for (j=0; j<n; j++)
printf("%d",bombe[i][j]);

119
120 Milena VujosevicJanicic

printf("\n");
}
}

/* Funkcija ispisuje tekuce stanje */


void ispisi_stanje()
{ int i,j;
for (i=0; i<n; i++)
{ for (j=0; j<n; j++)
{ if (stanje[i][j]==ZATVORENO)
printf(".");
else if (stanje[i][j]==PRAZNO)
printf(" ");
else if (stanje[i][j]==ZASTAVICA)
printf("*");
else
printf("%d",stanje[i][j]);
}
printf("\n");
}
}

/* Funkcija postavlja zastavicu na


dato polje ili je uklanja
ukoliko vec postoji */
void postavi_zastavicu(int i, int j)
{
if (stanje[i][j]==ZATVORENO)
{ stanje[i][j]=ZASTAVICA;
broj_zastavica++;
}
else if (stanje[i][j]==ZASTAVICA)
{ stanje[i][j]=ZATVORENO;
broj_zastavica--;
}
}

/* Funkcija izracunava koliko bombi


postoji u okolini date bombe */
int broj_bombi_u_okolini(int v, int k)
{ int i, j;
int br=0;
/* Prolazimo kroz sva okolna polja */

120
1.21 Razno 121

for (i=-1; i<=1; i++)


for(j=-1; j<=1; j++)
{ /* preskacemo centralno polje */
if (i==0 && j==0)
continue;
/* preskacemo polja "van table" */
if (v+i<0 || k+j<0 || v+i>=n || k+j>=n)
continue;
if (bombe[v+i][k+j]==1)
br++;
}

return br;

/* Centralna funkcija koja vrsi otvaranje


polja i pritom se otvaranje "siri"
i na polja koja su oko datog */

void otvori_polje(int v, int k) {


/* Ukoliko smo "nagazili" bombu
zavrsavamo program */
if (bombe[v][k]==1)
{ printf("BOOOOOOOOOOOOOOOOM!!!!\n");
ispisi_bombe();
exit(1);
}
else
{
/* Brojimo bombe u okolini */
int br=broj_bombi_u_okolini(v,k);

/* Azuriramo stanje ovog polja */


stanje[v][k]=(br==0)?PRAZNO:br;

/* Ukoliko u okolini nema bombi,


rekurzivno otvaramo
sva polja u okolini koja su zatvorena */
if (br==0)
{
/* Petlje indeksiraju sva okolna polja */
int i,j;

121
122 Milena VujosevicJanicic

for (i=-1; i<=1; i++)


for (j=-1; j<=1; j++)
{
/* Preskacemo centralno polje */
/* if (i==0 && j==0)
continue; */
/* Preskacemo polja van table */
if (v+i<0 || v+i>=n || k+j<0 || k+j>=n)
continue;
/* Ukoliko je okolno polje
zatvoreno, otvaramo ga */
if (stanje[v+i][k+j]==ZATVORENO)
otvori_polje(v+i, k+j);
}
}
}
}

/* Funkcija utrdjuje da li je partija gotova


Partija je gotova u trenutku kada su sve
bombe pokrivene zastavicama i
kada nijedno drugo polje nije
pokriveno zastavicom
*/

int gotova_partija()
{ int i,j;
for (i=0; i<n; i++)
for (j=0; j<n; j++)
{ /* Ukoliko postoji nepokrivena bomba,
partija nije zavrsena */
if (bombe[i][j]==1 && stanje[i][j]!=ZASTAVICA)
return 0;
}

/* Partija je zavrsena samo ukoliko je


broj zastavica jednak broj bombi */
return broj_zastavica==broj_bombi;

main() {

122
1.21 Razno 123

/* Unosimo dimenziju table */


printf("Unesite dimenziju table : ");
scanf("%d",&n);

/* Alociramo table */
bombe=alociraj(n);
stanje=alociraj(n);

/* Postavljamo bombe */
postavi_bombe();

/* Sve dok partija nije gotova */


while(!gotova_partija())
{ int v,k;
char akcija;

/* Ispisujemo tekuce stanje */


ispisi_stanje();

/* Sve dok korisnik ne unese o ili z


trazimo od njega da upise
odgovarajucu akciju */
do
{
getchar();
printf("Unesi akciju (o - otvaranje polja,
z - postavljanje zastavice) : ");
scanf("%c",&akcija);
} while (akcija!=o && akcija!=z);

/* Trazimo od korisnika da unese koordinate


polja sve dok ih ne unese ispravno
Korisnicke koordinate krecu od 1,
a interne od 0 */
do
{
printf("Unesi koordinate polja : ");
scanf("%d",&v);
scanf("%d",&k);
} while(v<1 || v>n || k<1 || k>n);

/* Reagujemo na akciju */

123
124 Milena VujosevicJanicic

switch(akcija)
{ case o:
otvori_polje(v-1,k-1);
break;
case z:
postavi_zastavicu(v-1,k-1);
}
}

/* Konstatujemo pobedu */
ispisi_stanje();
printf ("Cestitam! Pobedili ste\n");
obrisi(stanje,n);
obrisi(bombe,n);
}

124
Osnovi programiranja
Programski jezik C
Zadaci sa vezbi

Milena Vujosevic - Janicic 2005/2006


2

2
Sadrzaj

1 HTML 7

2 Konverzije 9
2.1 Pozicioni brojni sistemi . . . . . . . . . . . . . . . . . . . . . . . 9
2.2 Prevo enje iz dekadnog sistema u binarni . . . . . . . . . . . . . 10
2.3 Prevo enje iz dekadnog sistema u oktalni . . . . . . . . . . . . . 10
2.4 Prevo enje iz dekadnog sistema u heksadekadni . . . . . . . . . . 10
2.5 Prevo enje iz dekadnog sistema u sistem sa osnovom n . . . . . . 11
2.6 Prevo enje iz binarnog sistema u heksadekadni . . . . . . . . . . 11
2.7 Prevo enje iz binarnog sistema u oktalni . . . . . . . . . . . . . . 12

3 Algoritmi 13
3.1 Resavanje problema uz pomoc racunara . . . . . . . . . . . . . . 13
3.2 Formiranje algoritma . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.3 Algebarski algoritmi . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.3.1 NZD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.3.2 Koren prirodnog broja . . . . . . . . . . . . . . . . . . . . 19

4 Programski jezik C 21
4.1 Zdravo svete! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
4.2 Imena promenljivih . . . . . . . . . . . . . . . . . . . . . . . . . . 21
4.3 Deklaracije . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
4.4 Tipovi i velicina podataka . . . . . . . . . . . . . . . . . . . . . . 22
4.5 Funkcije printf i scanf . . . . . . . . . . . . . . . . . . . . . . . . 23
4.6 Aritmeticki operatori . . . . . . . . . . . . . . . . . . . . . . . . . 25
4.7 Operatori i izrazi dodeljivanja vrednosti . . . . . . . . . . . . . . 26
4.8 Inkrementacija i dekrementacija . . . . . . . . . . . . . . . . . . . 27
4.9 Relacioni i logicki operatori . . . . . . . . . . . . . . . . . . . . . 28
4.10 Kontrola toka if, while, do - while, for . . . . . . . . . . . . . . 30
4.10.1 if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
4.10.2 Else-if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
4.10.3 while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
4.10.4 do-while . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
4.10.5 for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.11 Switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.12 Uslovni izraz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
4.13 Simbolicke konstante . . . . . . . . . . . . . . . . . . . . . . . . . 35
4.14 Enumeracija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

3
4 SADRZAJ

4.15 Funkcije . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
4.16 Nizovi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
4.17 Konstante . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
4.18 Konverzija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
4.18.1 Automatska konverzija . . . . . . . . . . . . . . . . . . . . 41
4.18.2 Eksplicitna konverzija . . . . . . . . . . . . . . . . . . . . 41
4.18.3 Funkcije koje vrse konverziju . . . . . . . . . . . . . . . . 42
4.19 Operator sizeof() . . . . . . . . . . . . . . . . . . . . . . . . . . 43
4.20 Znakovni ulaz i izlaz . . . . . . . . . . . . . . . . . . . . . . . . . 44
4.21 Nizovi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
4.22 Dvostruka for petlja . . . . . . . . . . . . . . . . . . . . . . . . . 51
4.23 Formiranje HTML dokumenta . . . . . . . . . . . . . . . . . . . . 51
4.24 Funkcije prenos parametara po vrednosti . . . . . . . . . . . . 53
4.25 Break i continue . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
4.26 Rad sa niskama karaktera . . . . . . . . . . . . . . . . . . . . . . 56
4.27 Makroi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
4.28 Bitski operatori . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
4.29 Linearna i binarna pretraga . . . . . . . . . . . . . . . . . . . . . 69
4.30 Razni zadaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
4.31 Sortiranje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
4.32 Rekurzija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
4.33 Zivotni vek i oblast vazenja promenjivih, staticke promenljive . . 89
4.34 Pokazivaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
4.35 Pokazivaci i argumenti funkcija . . . . . . . . . . . . . . . . . . . 93
4.36 Pokazivaci i nizovi (polja) . . . . . . . . . . . . . . . . . . . . . . 94
4.37 Alokacija memorije . . . . . . . . . . . . . . . . . . . . . . . . . . 100
4.38 Niz pokazivaca . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
4.39 Pokazivaci na funkcije . . . . . . . . . . . . . . . . . . . . . . . . 104
4.40 Matrice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
4.41 Strukture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
4.41.1 Operator typedef . . . . . . . . . . . . . . . . . . . . . . . 113
4.42 qsort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
4.43 Sortiranje genericka funkcija . . . . . . . . . . . . . . . . . . . 121
4.44 qSort funkcija iz standardne biblioteke . . . . . . . . . . . . . . . 127
4.45 Genericko sortiranje reci . . . . . . . . . . . . . . . . . . . . . . . 129
4.46 Argumenti komandne linije . . . . . . . . . . . . . . . . . . . . . 131
4.47 Datoteke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
4.48 Liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
4.48.1 Red . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
4.48.2 Kruzna lista . . . . . . . . . . . . . . . . . . . . . . . . . . 145
4.48.3 Stek . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
4.48.4 Dvostruko povezane liste . . . . . . . . . . . . . . . . . . 150
4.49 Drvo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
4.50 Grafovi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
4.51 Razni zadaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171

4
Predgovor

Ovo je prateci materijal za vezbe koje drzim iz predmenta Osnovi programi-


ranja. On ne moze zameniti poha anje vezbi niti koriscenje druge preporucene
literature.
Veliki deo materijala cine zadaci i resenja mr Filipa Marica (raspolozivi na
www.matf.bg.ac.yu/~filip/pp/0405/index.pl). Tako e koriscen je i mater-
ijal sa sajta koleginice Jelene Grmuse www.matf.bg.ac.yu/~jelenagr i kolege
Miroslava Marica www.matf.bg.ac.yu/~maricm. Tekstovi i objasnjenja su uglavnom
zasnovani na knjizi Programski jezik C, autora Kerninghan & Ritchie
Zahvaljujem svojim studentima na aktivnom ucescu u nastavi cime su mi
pomogli u uoblicavanju ovog materijala.
Svi komentari i sugestije vezane za ovaj materijal bice veoma dobrodosli.

Milena Vujosevic-Janicic
www.matf.bg.ac.yu/~milena

5
6 SADRZAJ

6
Glava 1

HTML

http://www.matf.bg.ac.yu/nastavno/dvitas/nastava/op/html/op-html.html

7
8 Milena VujosevicJanicic

8
Glava 2

Konverzije

2.1 Pozicioni brojni sistemi


Brojevni sistemi1

naziv vrednost osnove cifre


dekadni 10 0,1,2,3,4,5,6,7,8,9
binarni 2 0,1
oktalni 8 0,1,2,3,4,5,6,7
heksadekadni 16 0,1,2,3,4,5,6,7,8,9,
A, B, C, D, E, F

Zapis u osnovi (bazi) b


(cn cn1 ...c1 c0 )b
gde su
cn , cn1 , ...c1 , c0
cifre u sistemu sa osnovom b ima vrednost

c0 b0 + c1 b1 + ... + cn1 bn1 + cn bn

Primer 2.1.1 1. (1101)2 = 1 20 + 0 21 + 1 22 + 1 23 = (13)10

2. (1101)16 = 1 160 + 0 161 + 1 162 + 1 163 = 1 + 256 + 4096 = (4353)10

3. (1101)7 = 1 70 + 0 71 + 1 72 + 1 73 = (399)10

4. (F 9A)16 = A 160 + 9 161 + F 162 == = 10 160 + 9 161 + 15 162 =


10 + 144 + 3840 = (3994)10

Zadatak 1
(110111100)2 = (?)10
(77)8 = (?)10
(F F F F )16 = (?)10
1 Deo teksta i primera preuzet sa sajta www.matf.bg.ac.yu/jelenagr

9
10 Milena VujosevicJanicic

2.2 Prevo enje iz dekadnog sistema u binarni




Primer 2.2.1
(26)10 = (?)2
kolicnik ostatak
26 / 2 = 13 0
13 / 2 = 6 1
6/2=30
3/2=11
1 / 2 = 0 1 kraj postupka konverzije
(26)10 = (11010)2
Zadatak 2
(54)10 = (?)2
(126)10 = (?)2
(332)10 = (?)2

2.3 Prevo enje iz dekadnog sistema u oktalni




Primer 2.3.1
(181)10 = (?)8
kolicnik ostatak
181 / 8 = 22 5
22 / 8 = 2 6
2 / 8 = 0 2 kraj postupka konverzije
(181)10 = (265)8
Zadatak 3
(67)10 = (?)8
(336)10 = (?)8
(442)10 = (?)8

2.4 Prevo enje iz dekadnog sistema u heksadekadni




Primer 2.4.1
(181)10 = (?)16
kolicnik ostatak
181 / 16 = 11 5
11 / 16 = 0 11 (heksadekadna cifra B) kraj postupka konverzije
(181)10 = (B5)16
Zadatak 4
(48)10 = (?)16
(1336)10 = (?)16
(332)10 = (?)16

10
2.5 Prevo enje iz dekadnog sistema u sistem sa osnovom n
 11

2.5 Prevo enje iz dekadnog sistema u sistem sa




osnovom n
Primer 2.5.1
(181)10 = (?)n
kolicnik ostatak
181 / n = k1 o1
k 1 / n = k 2 o2
...
kl / n = 0 ol+1 kraj postupka konverzije

(181)10 = (ol+1 ol ...o1 )n

Zadatak 5
(48)10 = (?)16
(1336)10 = (?)16
(332)10 = (?)16

2.6 Prevo enje iz binarnog sistema u heksadekadni




Prevo enje iz binarnog sistema u heksadekadni moze se uraditi bez me ukonverzije


u osnovu 10. Za kodiranje heksadecimalnih cifara dovoljne su binarne reci duzine
cetiri.

heksadekadna cifra kod


0 0000
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
8 1000
9 1001
A 1010
B 1011
C 1100
D 1101
E 1110
F 1111

primer:
4 0100 (0 20 + 0 21 + 1 22 + 0 23 )
F 1111 (1 20 + 1 21 + 1 22 + 1 23 )

Odavde je jasno kako zadovoljiti zahtev da se konverzija odvija direktno bez


posrednih konverzija. Binarne cifre se grupisu podgrupe od po 4 cifre, pocev

11
12 Milena VujosevicJanicic

od bitova najmanje tezine. Ako ukupan broj bitova nije deljiv sa cetiri, onda se
dopisuje potreban broj vodecih nula (one su bez uticaja na promenu vrednosti
originalnog zapisa).

Primer 2.6.1
(1111011100001101010000)2 =
= (001111011100001101010000)2 =
= (3DC350)16

Zadatak 6
(1111110111001100011010100100)2 = (?)16

2.7 Prevo enje iz binarnog sistema u oktalni




Prevo enje iz binarnog sistema u oktalni moze se uraditi bez me ukonverzije u


osnovu 10. Za kodiranje oktalnih cifara dovoljne su binarne reci duzine tri.

oktalna cifra kod


0 000
1 001
2 010
3 011
4 100
5 101
6 110
7 111

4 100 (0 20 + 0 21 + 1 22 )

Odavde je jasno kako zadovoljiti zahtev da se konverzija odvija direktno bez


posrednih konverzija. Binarne cifre se grupisu podgrupe od po 3 cifre, pocev
od bitova najmanje tezine. Ako ukupan broj bitova nije deljiv sa tri, onda se
dopisuje potreban broj vodecih nula.

Primer 2.7.1
(11111010001010)2 =
= (011111010001010)2 =
= (37212)8

Zadatak 7
(1111110111010100100)2 = (?)8

12
Glava 3

Algoritmi

3.1 Resavanje problema uz pomoc racunara


Resavanje problema uz pomoc racunara moze se podeliti na sledece korake:
1. Razumevanje problema
2. Izgradnja modela
3. Formiranje algoritma
4. Provera ispravnosti algoritma
5. Realizacija (implementacija) algoritma pisanje programa
6. Testiranje programa
7. Sastavljanje dokumentacije.

3.2 Formiranje algoritma


Formirati algoritam znaci dati skup preciznih uputstava kako doci do resenja
zadatog problema.
Algoritmi se mogu opisivati: prirodnim jezikom, pseudo-jezikom, blok-shemom
(dijagramom toka).
OPIS ALGORITAMA PRIRODNIM JEZIKOM
Opisati prirodnim jezikom detaljno, precizno i nedvosmisleno korake pri
resavanju problema, vodeci racuna o redosledu operacija koji se izvrsavaju.
OPIS ALGORITAMA PSEUDO JEZIKOM
Pseudo jezik je neformalna kombinacija prirodnog jezika i nekog program-
skoj jezika. Pri upotrebi pseudo jezika mora se voditi racuna da se jezicke
konstrukcije koriste uvek na isti nacin i da budu pracene objasnjenjima
(ako je potebno).
OPISIVANJE ALGORITAMA BLOK SEMOM
Za ovaj oblik opisa koriste se graficki simboli ciji je opis propisan ISO stan-
dardom. Tekst koji opisuje obradu se zapisuje unutar grafickih simbola.

13
14 Milena VujosevicJanicic

Tok rada algoritma se opisuju linijama koje povezuju graficke simbole koji
reprezenuju obradu.

3.3 Algebarski algoritmi


Primer 3.3.1 Algoritam zdravo svete

Algoritam Ispis
ulaz: nema podataka na ulazu
izlaz: poruka Zdravo, svete!!!
{
output " Zdravo, svete!!!"
}

Primer 3.3.2 Algoritam za sabiranje dva broja.

Algoritam Sabiranje
ulaz: x,y
izlaz: zbir brojeva x,y
/* algoritam je formiran tako da funkcionise
za bilo koji realan broj sa ulaza. Zbog toga se
u algoritmu koristi promenljiva - ime koje
oznacava promenljivu vrednost.*/
{
input x,y;
zbir = x + y;
output zbir;
}

Primer 3.3.3 Algoritam za maksimum dva broja.

Algoritam Maksimum
ulaz: x, y;
izlaz: veci od brojeva x i y
{
input x,y;
if (x>y) max=x
else max=y;
output max;
}

Primer 3.3.4 Algoritam za izracunavanje sume brojeva koja se unosi pre unosa
nule.

Algoritam Zbir
ulaz: brojevi sve dok se ne unese nula
izlaz: zbir brojeva
{
zbir=0; /*Inicijalizujemo zbir na nulu*/
input x; /*Unosimo prvi u nizu brojeva*/
while x!=0 /*Proveravani da li je broj

14
3.3 Algebarski algoritmi 15

x razlicit od nule i ako jeste


onda ga dodajemo na zbir*/
{
zbir=zbir+x;
input x; /*unosimo novi ulazni broj*/
}
output zbir; /*Na izlaz saljemo izracunati zbir*/
}

Zadatak 8 Algoritam za maksimum brojeva koji se unose, zavrsetak unosa je


nula.

Algoritam Maksimum
ulaz: brojevi sve dok se ne unese nula
izlaz: maksimum unetih brojeva
{
input x;
max = x;
while (x!=0) /*Proveravani da li je broj
x razlicit od nule*/
{
input x; /*unosimo novi ulazni broj*/
if (x>max) max=x; /*proveravamo da li je uneti
broj veci od tekuceg
maksimuma i ako jeste
onda tekucem maksimumu
dodeljujemo njegovu
vrednost*/
}
output max; /*Na izlaz saljemo izracunati
maximum*/
}

Zadatak 9 Algoritam za n!.

Algoritam n!
ulaz: prirodan broj n;
izlaz: faktorijel prirodnog broja n;
{
input n;
f=1;
while (n>1)
{
f=f*n;
n=n-1;
}
output f;
}

Zadatak 10 Algoritam za razmenu dva broja.

15
16 Milena VujosevicJanicic

Algoritam razmena
ulaz: dva broja
izlaz: razmena dva broja
{
input x,y;
pom=x;
x=y;
y=pom;
output x,y;
}

Zadatak 11 Celobrojni kolicnik i ostatak pri deljenju

x = qy + r, 0 r < y, 0 q

.
Algoritam kolicnik
ulaz: prirodni brojevi x i y;
izlaz: kolicnik i ostatak pri deljenju
{
input x,y;
kolicnik=0;
ostatak=x;
while (ostatak>=y)
{
ostatak=ostatak-y;
kolicnik=kolicnik+1;
}
output kolicnik, ostatak;
}

Zadatak 12 Algoritam koji resava kvadratnu jednacinu.

a x2 + b x + c

Algoritam kvadratna jednacina


ulaz: koeficijenti a, b,c
izlaz: resenje kvadratne jednacine
{
input a,b,c;
if (a=0)
if (b=0)
if (c=0)
output "C";
else output "prazan skup";
else x=-c/b
output x;
else d=b*b - 4ac
if (d>0)
{
x1=(-b+sqrt(d))/2a;

16
3.3 Algebarski algoritmi 17

x2=(-b-sqrt(d))/2a;
output x1, x2;
}
else if (d=0)
{
x=-b/2a;
output x;
}
else
{
Re=-b/2a;
Im=sqrt(-d)/2a;
output Re+i*Im, Re-i*Im;
}
}

Zadatak 13 Fibonacijevi brojevi.


Algoritam fibonaci
ulaz n;
izlaz n-ti fibonacijev broj;
{
input n;
x0=0;
x1=1;
if n=0 rezultat=x0;
else {
while (n>1)
{
novi=x0+x1;
x0=x1;
x1=novi;
n=n-1;
}
rezultat=x1;
output rezultat;
}
}

3.3.1 NZD
Zadatak 14 Naci najveci zajednicki delitelj za dva broja.
Algoritam NZD1
ulaz prirodni brojevi a, b;
izlaz nzd(a,b);
{
input a,b;
nzd = 1;
br=2;
while (br<=a && br<=b)

17
18 Milena VujosevicJanicic

{
if (a%br)==0 && (b%br)==0 nzd=br;
br=br+1;
}
output nzd;
}

Zadatak 15 Naci najveci zajednicki delitelj za dva broja.


Algoritam NZD2
ulaz prirodni brojevi a, b;
izlaz nzd(a,b);
{
input a,b;
nzd = 1;
if (a<b) nzd=a;
else nzd=b;
indikator=1;
while (indikator)
{
if (a%nzd)==0 && (b%nzd)==0 indikator=0;
else nzd=nzd-1;
}
output nzd;
}

Zadatak 16 Euklidov algoritam 1.


Algoritam NZD3
ulaz prirodni brojevi a, b;
izlaz nzd(a,b);
{
input a,b;
while (a!=b)
{
if (a>b) a=a-b;
else b=b-a;
}
output a;
}

Zadatak 17 Euklidov Algoritam 2.


Algoritam NZD4
ulaz prirodni brojevi a, b;
izlaz nzd(a,b);
{
input a,b;
if (a<b) {
pom=a;
a=b;
b=pom;

18
3.3 Algebarski algoritmi 19

}
while (b!=0)
{
pom = b;
b = a % b;
a = pom;
}
output a;
}

3.3.2 Koren prirodnog broja


Zadatak 18 Naci ceo deo korena prirodnog broja.

Algoritam Koren1
ulaz prirodan broj n;
izlaz ceo deo korena prirodnog broja;
{
input n;
koren=1;
while (koren*koren<=n)
koren=koren+1;
koren=koren-1;
output koren;
}

Zadatak 19 Naci ceo deo korena prirodnog broja.

Algoritam Koren2
ulaz prirodan broj n;
izlaz ceo deo korena prirodnog broja;
{
input n;
suma=0;
broj=0;
while (suma<=n)
{
suma=suma+broj+broj+1;
broj=broj+1;
}
broj=broj-1;
output broj;
}

19
20 Milena VujosevicJanicic

20
Glava 4

Programski jezik C

4.1 Zdravo svete!


Primer 4.1.1 Program stampa poruku hello, world.
#include <stdio.h>

main()
/*iskazi f-je main su zatvoreni u zagrade */
{
/*poziv f-je printf da odstampa poruku*/
printf("hello, world\n");
}
Primer 4.1.2 Program stampa poruku hello, world
#include <stdio.h>

main()
{
printf("hello, ");
printf("world");
printf("\n");
}
Specijalni znaci:
\n novi red
\t tabulator
\\ kosa crta
\" navodnici
\a zvuk
\ jednstruki navodnik

4.2 Imena promenljivih


Postoje ogranicenja: u imenu se mogu pojaviti slova i cifre, potcrta se sma-
tra slovom.

21
22 Milena VujosevicJanicic

Velika i mala slova se razlikuju.


int x, X; /*To su dve razlicite promenljive!!!*/
Kljucne reci kao sto su if, else, for, while, se ne mogu koristiti za imena promenljivih.

4.3 Deklaracije
Da bi se promenljiva mogla upotrebljavati ona se mora na pocetku programa
deklarisati. Prilikom deklaracije moze se izvrsiti i pocetna inicijalizacija.

int broj; /*Deklaracija celog broja*/


int vrednost=5; /*Deklaracija i inicijalizacija celog broja*/

Kvalifikator const moze biti dodeljen deklaraciji bilo koje promenljive da bi


oznacio da se ona nece menjati

const double e=2.71828182845905

4.4 Tipovi i velicina podataka


Osnovni tipovi podataka:

int ceo broj


char znak, jedan bajt
float realan broj
double realan broj dvostruke tacnosti

char jedan bajt, sadrzi jedan znak


int celobrojna vrednost,2 ili 4 bajta
float realan broj, jednostruka tacnost
double dvostruka tacnost

Postoje kvalifikatori koje pridruzujemo osnovnim tipovima short(16) i long(32):

short int kratak_broj;


long int dugacak_broj;
short kratak;
long dugacak;

Vazi

broj bajtova(short) <= broj bajtova(int) <= broj bajtova(long)

Postoje kvalifikatori signed i unsigned koji se odnose na oznacene i neoznacene


cele brojeve. Npr.
signed char: -128 do 127
dok je
unsigned char: od 0 do 255.
Float, double i long double.

Primer 4.4.1 Uvo enje promenljivih u program.




22
4.5 Funkcije printf i scanf 23

#include <stdio.h>

main()
{
/*deklaracija vise promenljivih
istog tipa */
int rez,pom1,pom2;
pom1=20;
pom2=15;
rez=pom1-pom2;

/*ispisivanje rezultata*/
printf("Rezultat je %d-%d=%d\n",pom1,pom2,rez);
}
Izlaz iz programa:
Rezultat je 20-15=5

Iskaz dodele:
pom1=20;
pom2=15;
Individualni iskazi se zavrsavaju sa ;

4.5 Funkcije printf i scanf


printf("%d\t%d\n", broj1, broj2);
uvek je prvi argument izmedju " "
%d ceo broj
\t tab izmedju
\n novi red
Svaka % konstrukcija je u paru sa argumentom koji sledi.

Primer 4.5.1
#include <stdio.h>
main()
{
printf("Slova:\n%3c\n%5c\n", z , Z);
}
Izlaz iz programa:
Slova:
z
Z
%c je za stampanje karaktera
%3c je za stampanje karaktera na tri pozicije
Isto tako smo mogli i %3d za stampanje broja na tri pozicije ili %6d za stampanje
broja na 6 pozicija.

Pravila:
%d stampaj kao ceo broj

23
24 Milena VujosevicJanicic

%6d stampaj kao ceo broj sirok najvise 6 znakova


%f stampaj kao realan broj
%6f stampaj kao realan broj sirok najvise 6 znakova
%.2f stampaj kao realan broj sa dve decimale
%6.2f stampaj kao realan broj sirok najvise 6 znakova a od toga 2 iza decimalne
tacke
%c karakter
%s string
%x heksadecimalni broj
%% je procenat

Primer 4.5.2 Prikazuje unos celog broja koristeci scanf("%d", &x)

#include <stdio.h>

main()
{
int x;
printf("Unesi ceo broj : ");

/* Obratiti paznju na znak &


(operator uzimanja adrese)
pre imena promenljive u funkciji
scanf */
scanf("%d",&x);

/* U funkciji printf nije


potrebno stavljati & */
printf("Uneli ste broj %d\n", x);
}

Primer 4.5.3 Program sabira dva uneta cela broja

#include <stdio.h>

main()
{
int a, b, c;
printf("Unesi prvi broj : ");
scanf("%d", &a);
printf("Unesi drugi broj : ");
scanf("%d", &b);
c = a + b;
printf("%d + %d = %d\n", a, b, c);
}
Ulaz:
Unesi prvi broj : 2 <enter>
Unesi drugi broj : 3 <enter>
Izlaz:
2 + 3 = 5

24
4.6 Aritmeticki operatori 25

4.6 Aritmeticki operatori


+ - * /
% (samo za celobrojne vrednosti)
unarno + i -

Asocijativnost sleva na desno, prioritet kao u matematici.

Primer 4.6.1 Program ilustruje neke od aritmetickih operacija.

#include <stdio.h>
main()
{
int a, b;
printf("Unesi prvi broj : ");
scanf("%d",&a);

printf("Unesi drugi broj : ");


scanf("%d",&b);

/* Kada se saberu dva cela broja, rezultat je ceo broj*/


printf("Zbir a+b je : %d\n",a+b);
/* Kada se oduzmu dva cela broja, rezultat je ceo broj*/
printf("Razlika a-b je : %d\n",a-b);
/* Kada se pomnoze dva cela broja, rezultat je ceo broj*/
printf("Proizvod a*b je : %d\n",a*b);
/* Kada se podele dva cela broja, rezultat je ceo broj!!!*/
printf("Celobrojni kolicnik a/b je : %d\n", a/b);
/* Rezultat je ceo broj, bez obzira sto ga ispisujemo kao realan*/
printf("Pogresan pokusaj racunanja realnog kolicnika a/b je : %f\n", a/b);
/* Eksplicitna konverzija, a i b pretvaramo u relane brojeve kako
bi deljenje bilo realno*/
printf("Realni kolicnik a/b je : %f\n", (float)a/(float)b);
/* Ostatak pri deljenju se moze izvrsiti samo nad celim brojevima*/
printf("Ostatak pri deljenju a/b je : %d\n", a%b);
}

Ulaz:
Unesi prvi broj : 2 <enter>
Unesi drugi broj : 3 <enter>
Izlaz:
Zbir a+b je : 5
Razlika a-b je : -1
Proizvod a*b je : 6
Celobrojni kolicnik a/b je : 0
Progresan pokusaj racunanja realnog kolicnika a/b je : 0.000000
Realni kolicnik a/b je : 0.666667
Ostatak pri deljenju a/b je : 2

Primer 4.6.2 Program ilustruje celobrojno i realno deljenje.

25
26 Milena VujosevicJanicic

#include <stdio.h>

main()
{
int a = 5;
int b = 2;
int d = 5/2; /* Celobrojno deljenje - rezultat je 2 */
float c = a/b; /* Iako je c float, vrsi se celobrojno
deljenje jer su i a i b celi */

/* Neocekivani rezultat 2.000000 */


printf("c = %f\n",c);
printf("Uzrok problema : 5/2 = %f\n", 5/2);
printf("Popravljeno : 5.0/2.0 = %f\n", 5.0/2.0);
printf("Moze i : 5/2.0 = %f i 5.0/2 = %f \n", 5/2.0, 5.0/2);
printf("Za promenljive mora kastovanje : %f\n", (float)a/(float)b);

Izlaz iz programa:
c = 2.000000
Uzrok problema : 5/2 = 2.000000
Popravljeno : 5.0/2.0 = 2.500000
Moze i : 5/2.0 = 2.500000 i 5.0/2 = 2.500000
Za promenljive mora kastovanje : 2.500000

Zadatak 20 Sta ce biti ispisano nakon izvrsavanja sledeceg programa?


#include <stdio.h>
main()
{
int x=506, y=3, z=21, t=2;
printf("x=%d y=%d\n",x,y);
printf("z - t=%d\n", z-t);
printf("z / t =%d\n",z / t);
printf("-x=%d\n",- x);
printf("x %% y=%d\n", x%y);
}

4.7 Operatori i izrazi dodeljivanja vrednosti


i = i + 2;
ekvivalento je sa
i+=2;

Moze i za:
+ - * / % << >> ^ |
izraz1 op = izraz2
je ekvivalnetno sa
izraz1 = (izraz1) op (izraz2)

26
4.8 Inkrementacija i dekrementacija 27

x*= y+1 je ekvivalento sa x = x * (y+1)

Takvo pisanje je krace i efikasnije.

4.8 Inkrementacija i dekrementacija


Operatori ++ i --

x=++n; se razlikuje od x=n++;

y=(x++)*(++z);

Primer 4.8.1 Ilustracija prefiksnog i postfiksnog operatora ++

#include <stdio.h>
main()
{
int x, y;
int a = 0, b = 0;

printf("Na pocetku : \na = %d\nb = %d\n", a, b);

/* Ukoliko se vrednost izraza ne koristi, prefiksni i


postfiksni operator se ne razlikuju */
a++;
++b;
printf("Posle : a++; ++b; \na = %d\nb = %d\n", a, b);

/* Prefiksni operator uvecava promenljivu, i rezultat


je uvecana vrednost */
x = ++a;

/* Postfiksni operator uvecava promenljivu, i rezultat je


stara (neuvecana) vrednost */
y = b++;

printf("Posle : x = ++a; \na = %d\nx = %d\n", a, x);


printf("Posle : y = b++; \nb = %d\ny = %d\n", b, y);
}

Izlaz iz programa:
Na pocetku:
a = 0
b = 0
Posle : a++; ++b;
a = 1
b = 1
Posle : x = ++a;
a = 2

27
28 Milena VujosevicJanicic

x = 2
Posle : y = b++;
b = 2
y = 1

4.9 Relacioni i logicki operatori


Relacioni operatori:
> >= < <= isti prioritet
== != nizi prioritet

(3<5)
(a<=10)
a < 5 != 1 <=> (a < 5)!=1
Logicki operatori:
! unarna negacija (najvisi prioritet)
&& logicko i (visi prioritet od ili)
|| logicko ili izracunavaju se sleva na desno!

5 && 4 vrednost je tacno


10 || 0 vrednost je tacno
0 && 5 vrednost je 0
!1 vrednost je 0
!9 vrednost je 0
!0 vrednost je 1
!(2>3) je 1
a>b && b>c || b>d je isto sto i ((a>b) && (b>c)) || (b>d)
koja je vrednost ako je a=10, b=5, c=1, d=15?

Primer 4.9.1 Ilustracija logickih i relacijskih operatora.


#include <stdio.h>

main()
{
int a = 3>5, /* manje */
b = 5>3, /* vece */
c = 3==5, /* jednako */
d = 3!=5; /* razlicito */

printf("3>5 - %d\n5>3 - %d\n3==5 - %d\n3!=5 - %d\n", a, b, c, d);

/*Lenjo izracunavanje: kako 3 nije vece od 5 to se vrednost


drugog poredjenja nece racunati jer je netacno u konjunkciji
sa proizvoljnim izrazom sigurno netacno. */
printf("Konjunkcija : 3>5 && 5>3 - %d\n", a && b);

/*Lenjo izravunavanje: tacno u disjunkciji sa proizvoljnim

28
4.9 Relacioni i logicki operatori 29

izrazom daje tacno tako da se vrednost izraza 3>5 nece


izracunavati*/
printf("Disjunkcija : 5>3 || 3>5 - %d\n", b || a);
printf("Negacija : !(3>5) - %d\n", !a);

Izlaz iz programa:
3>5 - 0
5>3 - 1
3==5 - 0
3!=5 - 1
Konjunkcija : 3>5 && 5>3 - 0
Disjunkcija : 3>5 || 5>3 - 1
Negacija : !(3>5) - 1
Primer 4.9.2 Ilustracija lenjog izracunavanja logickih operatora.
Prilikom izracunavanja izraza - A && B, ukoliko je A netacno, izraz B se
ne izracunava. Prilikom izracunavanja izraza - A k B, ukoliko je A tacno, izraz
B se ne izracunava.
#include <stdio.h>

/* Globalna promenljiva, vidljiva i iz funkcije main() i


iz funkcije izracunaj*/
int b = 0;

/* Funkcija ispisuje da je pozvana i uvecava promenjivu b.


Funkcija uvek vraca vrednost 1 (tacno)
*/
int izracunaj()
{
printf("Pozvano izracunaj()\n");
b++;
return 1;
}

main()
{
/* Funkcija izracunaj() ce biti pozvana
samo za parne vrednosti a */
int a;
for (a = 0; a < 10; a++)
if (a%2 == 0 && izracunaj())
printf("Uslov ispunjen : a = %d, b = %d\n", a, b);
else
printf("Uslov nije ispunjen : a = %d, b = %d\n", a, b);

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

/* Funkcija izracunaj() ce se pozivati samo

29
30 Milena VujosevicJanicic

za neparne vrednosti a */
b = 0;
for (a = 0; a < 10; a++)
if (a%2 == 0 || izracunaj())
printf("Uslov ispunjen : a = %d, b = %d\n", a, b);
else
printf("Uslov nije ispunjen : a = %d, b = %d\n", a, b);
}

4.10 Kontrola toka if, while, do - while, for


4.10.1 if
if (izraz)
iskaz1
else
iskaz2

Primer 4.10.1 Program ilustruje if i ispisuje ukoliko je uneti ceo broj negativan
#include <stdio.h>

main()
{
int b;
printf("Unesi ceo broj:");
scanf("%d", &b);
if (b < 0)
printf("Broj je negativan\n");
}

Else se odnosi na prvi neuparen if, voditi o tome racuna, ako zelimo drugacije
moramo da navedemo viticaste zagrade.
if (izraz)
if (izraz1) iskaz 1
else iskaz
ovo else se odnosi na drugo if a ne na prvo if!
if (izraz)
{
if (izraz1) iskaz 1
}
else iskaz
tek sada se else odnosi na prvo if!!!

4.10.2 Else-if
if (izraz1)
iskaz1

30
4.10 Kontrola toka if, while, do - while, for 31

else if (izraz2)
iskaz2
else if (izraz3)
iskaz3
else if (izraz4)
iskaz4
else iskaz

npr if (a<5)
printf("A je manje od 5\n");
else if (a=5)
printf("A je jednako 5\n");
else if (a>10)
printf("A je vece od 10\n");
else if (a=10)
printf("A je jednako 10\n");
else printf("A je vece od pet i manje od 10\n");

Primer 4.10.2 Program ilustruje if-else konstrukciju i ispituje znak broja.

#include <stdio.h>

main()
{
int b;
printf("Unesi ceo broj : ");
scanf("%d", &b);
if (b < 0)
printf("Broj je negativan\n");
else if (b == 0)
printf("Broj je nula\n");
else
printf("Broj je pozitivan\n");
}

Ulaz:
Unesi ceo broj:-5
Izlaz:
Broj je negativan

Ulaz:
Unesi ceo broj:5
Izlaz:
Broj je pozitivan

Primer 4.10.3 Pogresan program sa dodelom = umesto poredjenja ==.

#include <stdio.h>

main()

31
32 Milena VujosevicJanicic

{
int b;
printf("Unesi ceo broj : ");
scanf("%d", &b);

/* Obratiti paznju na = umesto == Analizirati rad programa*/


if (b = 0)
printf("Broj je nula\n");
else if (b < 0)
printf("Broj je negativan\n");
else
printf("Broj je pozitivan\n");
}

Ulaz:
Unesi ceo broj:-5
Izlaz:
Broj je pozitivan

4.10.3 while
while(uslov) { ... }
Uslov u zagradi se testira i ako je ispunjen telo petlje se izvrsava. Zatim se uslov
ponovo testira i ako je ispunjen ponovo se izvrsava telo petlje. I tako sve dok
uslov ne bude ispunjen. Tada se izlazi iz petlje i nastavlja sa prvom sledecom
naredbom u programu.
Ukoliko iza while sledi samo jedna naredba nema potrebe za zagradama.

while (i<j)
i=2*i;

4.10.4 do-while
Ovo je slicno paskalskom repeat-until izrazu.

do iskaz while (izraz)

Primer 4.10.4 Program ilustruje petlju do-while.

#include <stdio.h>

main()
{
int x;

x = 1;
do
{
printf("x = %d\n",x);
x++; /* x++ je isto kao i x=x+1 */

32
4.11 Switch 33

} while (x<=10);
}

4.10.5 for
Primer 4.10.5 Program ilustruje petlju - for.

#include <stdio.h>

main()
{
int x;

/* Inicijalizacija; uslov; inkrementacija*/


for (x = 1; x < 5; x++)
printf("x = %d\n",x);

}
Izlaz:
1
2
3
4

4.11 Switch
switch (iskaz) {
case konstantan_izraz1: iskazi1
case konstantan_izraz2: iskazi2
...
default: iskazi
}

Primer 4.11.1 Voditi racuna o upotrebi break-a.

#include <stdio.h> /*
Upotreba switch-a
*/

main() {
char x;
scanf("%c",&x);

switch (x)
{
case a:
case e:
case i:
case o:
case u: printf(" x je samoglasnik");

33
34 Milena VujosevicJanicic

break;
case r: printf(" x je r");
break;
default: printf(" x je suglasnik");
}
}

Primer 4.11.2 Ilustracija switch konstrukcije.

#include<stdio.h>
main()
{
int n;
printf("Unesi paran broj manji od 10\n");
scanf("%d",&n);
switch(n) {
case 0:
printf("Uneli ste nulu\n");
break;
case 2:
printf("Uneli ste dvojku\n");
break;
case 4:
printf("Uneli ste cetvorku\n");
break;
case 6:
printf("Uneli ste sesticu\n");
break;
case 8:
printf("Uneli ste osmicu\n");
break;
defalut:
printf("Uneli ste nesto sto nije paran broj\n");
}
}
Ulaz:
Unesi paran broj manji od 10
2
Izlaz:
Uneli ste dvojku

4.12 Uslovni izraz


Slicno kao if.

izraz1 ? izraz2 : izraz3

z = (a<b)? a : b; /*z=min(a,b)*/
max = (a>b)? a : b;

34
4.13 Simbolicke konstante 35

4.13 Simbolicke konstante


Primer 4.13.1 Konverzija centimetara u ince - while petlja.

#include <stdio.h>

/* Definicija simbolickih konstanti preko #define direktiva */


/* U fazi pretprocesiranja se vrsi doslovna zamena konstanti
njihovim vrednostima */

#define POCETAK 0
#define KRAJ 20
#define KORAK 10

main()
{
int a;
a = POCETAK;
while (a <= KRAJ)
{
printf("%d cm = %f in\n", a, a/2.54);
a += KORAK; /* isto sto i a = a + KORAK; */
}
}

Izlaz:
0 cm = 0.000000 in
10 cm = 3.937008 in
20 cm = 7.874016 in

Primer 4.13.2 Konverzija centimetara u ince - for petlja.

#include <stdio.h>
#define POCETAK 0
#define KRAJ 20
#define KORAK 10

main()
{
int a;
for (a = POCETAK; a <= KRAJ; a += KORAK)
printf("%d cm = %f in\n", a, a/2.54);
}

Izlaz:
0 cm = 0.000000 in
10 cm = 3.937008 in
20 cm = 7.874016 in

Zadatak 21 Sta ce biti ispisano nakon izvrsavanja sledeceg programa?

35
36 Milena VujosevicJanicic

#include <stdio.h>
#define EURO 85.90
main()
{
printf("4 eura ima vrednost %f dinara\n", 4*EURO);
printf("1 euro ima vrednost %.0f dinara\n",EURO);
}

4.14 Enumeracija
Izvesna alternativa za define

enum boolean {NO, YES};


enum meseci {JAN = 1, FEB, MAR, APR, MAJ, JUN,
JUL, AVG, SEP, OKT, NOV, DEC}
enum boje {CRVENA, ZELENA=5, PLAVA,
LJUBICASTA=10, ZUTA, CRNA}

koriscenje:

int x=0;
boje b;

x=CRVENA+3; /*x ce biti jednako tri*/

b=ZELENA;
x=b+CRNA; /* 5 + 12=17*/

b=0; /*Greska, ovako ne moze!!!*/

4.15 Funkcije
Primer 4.15.1 sum - najjednostavnija funkcija koja sabira dva broja

/* Definicija funkcije */
int sum(int a, int b)
{
int c;
c = a + b;
return c;
/* Ovo je krace moglo da bude napisano
kao return a+b; */
}

main()
{

int c;

36
4.15 Funkcije 37

/* Poziv funkcije */
c = sum(3,5);
printf("%d\n", c);

/* Ovo smo krace mogli da napisemo kao


printf("%d\n", sum(3,5)); */
}

Primer 4.15.2 Deklaracija funkcije moze da stoji nezavisno od definicije funkcije.


Deklaracija je neophodna u situacijama kada se definicija funkcije navodi nakon
upotrebe date funkcije u kodu.
/* Deklaracija funkcije*/
int zbir(int, int);

main()
{
/* Poziv funkcije */
printf("%d\n", zbir(3,5));
}

/* Definicija funkcije */
int zbir(int a, int b)
{
return a+b;
}

Primer 4.15.3 power - funkcija koja stepenuje realan broj na celobrojni izlozi-
lac
#include <stdio.h>

/* stepenuje x^k tako sto k puta pomnozi x */


float power(float x, int k)
{
int i;
float rezultat = 1;
for (i = 0; i<k; i++)
rezultat*=x;

return rezultat;
}

Primer 4.15.4 Verzija koja radi i za negativne izlozioce


float power(float x, int k)
{
int i;
float s = 1;
int negativan = (k<0);
float rezultat;

37
38 Milena VujosevicJanicic

if (negativan)
k = -k;

for (i = 0; i<k; i++)


s*=x;

rezultat = negativan ? 1.0/s : s;


return rezultat;
}

main()
{
/* Poziv funkcije */
float s = power(2.0,8);
printf("%f\n", s);
}

4.16 Nizovi
Deklaracija niza:
int niz[5]; /* niz od 5 elemenata tipa int*/
Pristupanje elementima niza:
niz[0] = 4;
niz[1] = 2 * niz[0]; /*niz[1] = 8*/
niz[2] = niz[0] * niz[1]; /*niz[2] = 32*/
niz[3] = 5;
niz[4] = 7;
Unos vrednosti elemenata niza sa tastature:
for(i=0; i<5; i++)
scanf("%d", &a[i]);
Stampanje elemenata niza
for(i=0; i<5; i++)
printf("%d ", a[i]);
Brojanje elemenata niza je od nule!
Pristupanje elementu niza, indeks moze da bude proizvoljan izraz celobrojne
vrednosti: niz[i*2]=5.

Primer 4.16.1 Program ilustruje koriscenje nizova. Ispisuje 10 unetih brojeva


unazad.
#include <stdio.h>

main()
{
int a[10];

38
4.16 Nizovi 39

int i;
for (i = 0; i<10; i++)
{
printf("a[%d]=",i);
scanf("%d",&a[i]);
}

printf("Unazad : \n");

for (i = 9; i>=0; i--)


printf("a[%d]=%d\n",i,a[i]);
}

Primer 4.16.2 Program pronalazi maksimum brojeva sa ulaza - verzija sa ni-


zom.
#include <stdio.h>
#define BR_ELEM 5
main()
{
int a[BR_ELEM];
int i;
int max;

/* Ucitavamo niz brojeva */


for (i = 0; i < BR_ELEM; i++)
scanf("%d",&a[i]);

/* Pronalazimo maksimum */
max = a[0];
for (i = 1; i < BR_ELEM; i++)
if (a[i]>max)
max = a[i];

/* Ispisujemo maksimum */
printf("Max = %d\n",max);
}

Primer 4.16.3 Program pronalazi maksimum brojeva sa ulaza - verzija bez


niza.

#include <stdio.h>
#define BR_ELEM 5

main()
{
int a, max, i;
scanf("%d",&a);
max = a;
for (i = 1; i < BR_ELEM; i++)
{

39
40 Milena VujosevicJanicic

scanf("%d",&a);
if (a>max)
max = a;
}

printf("Max : %d\n", max);


}

4.17 Konstante
Koji su tipovi konstanti?
Celobrojna konstanta 1234 je tipa int.
Da bi konstanta bila long navodi se iza nje slovo L ili l, npr 123456789L.
Ako zelimo da nam je konstanta unsigned onda na kraju pisemo U ili u.
Moze i 1234567ul.

Konstante realnih brojeva sadrze decimalnu tacku(123.4) ili eksponent(1e-


2) ili i jedno i drugo. Njihov tip je double osim ako nemaj sufiks f ili F kada je
u pitanju float. L ili l oznacavaju long double.
Oktalna konstanta pocinje sa 0, a heksadecimalna sa 0x. Npr broj 31 ili
037 - oktalno ili 0x1f - heksadecimalno. I one mogu da imaju U i L na kraju.
Znakovna konstanta je celobrojna vrednost napisana izme u jednostrukih
navodnika. Vrednost date konstante je numericka vrednost datog znaka u
racunarskom setu znakova. Npr mozemo da pisemo 0 umesto 48.
!!!Razlikovati znakovne konstante i niske koje se navode izme u dvostrukih
navodnika!
Posebni znaci su znak za kraj reda, tab i slicno.
Znakovna konstanta \0 predstavlja znak cija je vrednost nula, treba ga
razlikovati od 0 koja je znak cija je vrednost 48.
Konstantna niska: Ja sam niska
ili
/*prazna niska*/
Navodnici nisu deo niske vec se koriste da bi je ogranicili. Ako ih zelimo unutar
niske, oni se navode sa \".
Konstantna niska je polje znakova. Da bi se znalo gde je kraj niske, fizicko
memorisanje liste zahteva da postoji jedan znak vise koji oznacava kraj, to je
\0. Da bi se odredila duzina niske mora se proci kroz celu nisku.
!!!Vazno:

Koja je razlika izme u x i x ?

Primer 4.17.1 Primer funkcije koja izracunava duzinu niske znakova.


#include <stdio.h>

int strlen(char s[])


{
int i=0;

while (s[i] != \0)

40
4.18 Konverzija 41

++i;
return i;
}

int main()
{
printf("Duzina ove niske
je: %d \n",strlen("Duzina ove niske je:"));
return 0;
}

4.18 Konverzija
4.18.1 Automatska konverzija
Ako je jedan od operanada razlizlicit vrsi se konverzija, uvek u smeru manjeg
ka vecem tipu

Naredba dodele:
int i=5;
float f=2.3;
f=i; /* f ce imati vrednost 5.0*/

obrnuto:

int i=5;
float f=2.3;
i=f; /* i ce imati vrednost 2*/

4.18.2 Eksplicitna konverzija


(tip)<izraz>

float x;
x=2.3+4.2; /* x ce imati vrednost 6.5 */
x=(int)2.3+(int)4.2; /* x ce imati vrednost 6 */
x=(int)2.3*4.5; /* x ce imati vrednost 9.0 jer zbog prioriteta
operatora konverzije prvo ce biti izvrsena
konverzija broja 2.3 u 2 pa tek onda izvrseno
mnozenje. */
x=(int)(2.3*4.5) /* x ce imati vrednost 10.0 */

Primer 4.18.1 Kako izbeci celobrojno deljenje


int a,b;
float c;
a = 5;
b = 2;
c = a/b; /* Celobrojno deljenje, c=2*/
c = (1.0*a)/b; /* Implicitna konverzija: 1.0*a je realan

41
42 Milena VujosevicJanicic

broj pa priliko deljenja sa b dobija se


realan rezultat c=2.5*/
c = (0.0+a)/b; /* Implicitna konverzija: (0.0+a) je realan
broj pa priliko deljenja sa b dobija se
realan rezultat c=2.5*/
c = (float)a/(float)b; /* Eksplicitna konverzija*/

4.18.3 Funkcije koje vrse konverziju


Primer 4.18.2
#include <stdio.h>
main()
{
int vrednost;
vrednost=A;
printf("Veliko slovo\n karakter=%3c\nvrednost=%3d\n",vrednost,vrednost);
vrednost=a;
printf("Malo\n karakter=%3c\nvrednost=%3d\n",vrednost,vrednost);
}

Izlaz (u slucaju ASCII):


Veliko slovo
karakter= A
vrednost= 65
Malo
karakter= a
vrednost= 97

Primer 4.18.3 Funkcija koja konvertuje velika slova u mala slova.

#include<stdio.h>

/* Konvertuje karakter iz velikog u malo slovo */


char lower(char c)
{
if (c >= A && c <= Z)
return c - A + a ;
else
return c;
}

main()
{
char c;
printf("Unesi neko veliko slovo:\n");
scanf("%c", &c);
printf("Odgovarajuce malo slovo je %c\n", lower(c));
}

Primer 4.18.4 Konvertovanje niske cifara u ceo broj.

42
4.19 Operator sizeof() 43

#include<stdio.h>

/* atoi: konvertuje s u ceo broj */


int atoi(char s[])
{
int i, n;
n = 0;
for (i = 0; (s[i] >= 0) && (s[i] <= 9); ++i)
n = 10 * n + (s[i] - 0);
return n;
}

main()
{
int n;
n = atoi("234");
printf("\nN je : %d\n",n);
}

4.19 Operator sizeof()


Primer 4.19.1 Demonstracija sizeof operatora. Sizeof operator izracunava
velicinu tipa odnosno promenjive.
#include<stdio.h>
main()
{
int i;
float f;
int n[10];

printf("sizeof(int)=%d\n", sizeof(int));
printf("sizeof(long)=%d\n", sizeof(long));
printf("sizeof(short)=%d\n", sizeof(short));
printf("sizeof(signed)=%d\n", sizeof(signed));
printf("sizeof(unsigned)=%d\n", sizeof(unsigned));
printf("sizeof(char)=%d\n", sizeof(char));
printf("sizeof(float)=%d\n", sizeof(float));
printf("sizeof(double)=%d\n", sizeof(double));

printf("sizeof(i)=%d\n", sizeof(i));
printf("sizeof(f)=%d\n", sizeof(f));
printf("sizeof(n)=%d\n", sizeof(n));
printf("Broj elemenata niza n : %d\n", sizeof(n)/sizeof(int));

Izlaz iz programa(u konkretnom slucaju):


sizeof(int)=4
sizeof(long)=4

43
44 Milena VujosevicJanicic

sizeof(short)=2
sizeof(signed)=4
sizeof(unsigned)=4
sizeof(char)=1
sizeof(float)=4
sizeof(double)=8
sizeof(i)=4
sizeof(f)=4
sizeof(n)=40
Broj elemenata niza n : 10

4.20 Znakovni ulaz i izlaz


Funkcija za citanje jednog znaka sa ulaza
c = getchar()
promenljiva c sadrzi jedan znak sa ulaza.

Funkcija za stampanje jednog znaka na izlaz


putchar(c)
stampa sadrzaj promenljive c obicno na ekranu.

Konstanta EOF je celobrojna vrednost definisana u biblioteci <stdio.h>.


Ovu vrednost vrati funkcija getchar() kada nema vise ulaza. Nazvana je EOF
kao End Of File, kraj datoteke. Ova vrednost mora da se razlikuje od svake
vrednosti koja moze da bude karakter. Zato za c za koje je c=getchar() treba
da koristimo tip dovoljno veliki da moze da prihvati sve sto moze da vrati
getchar(), dakle i EOF. Zbog toga se za c koristi tip int.

Primer 4.20.1 Program cita jedan karakter i ispisuje ga - demonstracija putchar


i getchar.

#include <stdio.h>

main()
{
int c; /* Karakter - obratiti paznju na int */
c = getchar(); /* cita karakter sa standardnog ulaza */
putchar(c); /* pise karakter c na standardni izlaz */

putchar(\n); /* prelazak u novi red */


putchar(a); /* ispisuje malo a */
putchar(97); /* ekvivalentno prethodnom */
}
Ulaz:
s
Izlaz iz programa:
s
s
aa

44
4.20 Znakovni ulaz i izlaz 45

Primer 4.20.2 Program prepisuje standardni ulaz na standardni izlaz. Ilus-


tracija redirekcije standardnog ulaza i izlaza, pokrenuti program sa :
./a.out <primer.c
./a.out >tekst.txt
./a.out <primer.c >kopija.c

#include <stdio.h>

main()
{
/*Koristi se int a ne char zato sto zelimo
da razlikujemo kraj ulaza od vazecih znakova*/
int c;

/*Ucitava se prvi znak sa ulaza*/


c = getchar();

/*EOF predstavlja celobrojnu vrednost kraja datoteke.


To je konstanta definisana u <stdio.h>*/
while (c != EOF) {
putchar(c);
c = getchar();
}
}

Bilo koje dodeljivanje vrednosti je izraz koji ima vrednost a to je vrednost


leve strane posle dodeljivanja.

Primer 4.20.3 Program koji kopira ulaz na izlaz, skraceni kod.


#include <stdio.h>

main()
{
int c;

/* Obratiti paznju na raspored zagrada */


while ((c = getchar()) != EOF)
putchar(c);
}

Primer 4.20.4 Brojanje znakova na ulazu.


#include <stdio.h>

main()
{
long nc;

nc = 0;
while (getchar() != EOF)

45
46 Milena VujosevicJanicic

++nc;
/* %ld odnosi se na tip long. */
printf("%ld\n", nc);
}

Primer 4.20.5 Brojanje znakova na ulazu koriscenjem for petlje.


#include <stdio.h>

main()
{
double nc;

/*For petlja mora da ima telo pa makar


ono bilo przno*/
for (nc = 0; getchar() != EOF; ++nc)
;
printf("%.0f\n", nc);
}

Primer 4.20.6 Program broji linije i znakove na ulazu.


#include <stdio.h>
main()
{
int znak; /*prihvata znak sa ulaza */
long linije=0 ; /*brojac linija */
long br_znak=0; /*brojac znakova na ulazu */

while ( (znak=getchar() ) != EOF)


{
br_znak++;
if (znak==\n) linije ++;
}

printf("Prelazaka u novi red: %ld, karaktera: %ld \n",linije,br_znak);


}

Primer 4.20.7 Program broji blankove, horizontalne tabulatore i linije na ulazu.


#include <stdio.h>
main()
{
int znak; /*prihvata znak sa ulaza */
int Blanks=0; /*brojac blankova */
int Tabs=0; /*brojac horizontalnih tabulatora */
int NewLines=0; /*brojac linija */

/*UOCITI: blok naredbi while ciklusa NIJE OGRADJEN


viticastim zagradama jer postoji samo jedna if naredba! */
while( (znak=getchar())!=EOF )
if( znak== ) ++Blanks; /* brojimo blanko simbole */

46
4.20 Znakovni ulaz i izlaz 47

else if( znak==\t ) ++Tabs; /* brojimo tab-ove */


else if( znak==\n ) ++NewLines; /* brojimo redove */

/*izdavanje rezultata na standardni izlaz*/


printf("Blankova: %d. Tabulatora: %d. Prelazaka u novi red: %d\n",
Blanks, Tabs, NewLines);

Primer 4.20.8 Program prepisuje ulaz na izlaz pri cemu vise blanko znakova
zamenjuje jednim.
#include <stdio.h>

main()
{
int znak; /*tekuci znak sa ulaza*/
int preth; /*znak koji prethodi tekucem */
preth=a; /* inicijalizujemo vrednost prethodnog
da bi prvi prolazak kroz petlju bio ispravan*/
while ( (znak=getchar() ) !=EOF)
{
if (znak != || preth != ) putchar(znak);
preth=znak;
}
}

Primer 4.20.9 Program vrsi prebrojavanje cifara unetih na ulazu.


#include <stdio.h>

main()
{
int c;
int br_cifara = 0;
while ((c = getchar()) != EOF)
if (0<=c && c<=9)
br_cifara++;

printf("Broj cifara je : %d\n", br_cifara);


}

Primer 4.20.10 Program vrsi brojanje pojavljivanja karaktera 0, 1 i 2 (ilus-


truje switch).
#include <stdio.h>

main()
{
int c;
int br_0=0, br_1=0, br_2=0;

47
48 Milena VujosevicJanicic

while ((c = getchar()) != EOF)


{
switch(c)
{
/* Obratiti paznju da nije
case 0: */
case 0:
br_0++;
break; /* Isprobati veziju bez break */
case 1:
br_1++;
break;
case 2:
br_2++;
break;
default:
}
}
printf("Br 0 : %d\nBr 1 : %d\nBr 2 : %d\n",br_0, br_1, br_2);
}

4.21 Nizovi
Primer 4.21.1 Program ilustruje inicijalizaciju nizova.
#include <stdio.h>

main()
{
/* Niz inicijalizujemo tako sto mu navodimo vrednosti
u viticasnim zagradama. Dimenzija niza se odredjuje
na osnovu broja inicijalizatora */
int a[] = {1, 2, 3, 4, 5, 6};

/* Isto vazi i za niske karaktera */


char s[] = {a, b, c};

/* Ekvivalentno prethodnom bi bilo


char s[] = {97, 98, 99};
*/

/* Broj elemenata niza */


int a_br_elem = sizeof(a)/sizeof(int);
int s_br_elem = sizeof(s)/sizeof(char);

/* Ispisujemo nizove */

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

48
4.21 Nizovi 49

for (i = 0; i < s_br_elem; i++)


printf("s[%d]=%c\n",i, s[i]);

Primer 4.21.2 Program uvodi niske karaktera terminisane nulom.

#include <stdio.h>

main()
{
/* Poslednji bajt niske karaktera se postavlja na \0 tj. 0 */
char s[] = {a, b, c, \0 };

/* Kraci nacin da se postigne prethodno */


char t[] = "abc";

/* Ispis niske s karakter po karakter*/


int i;
for (i = 0; s[i] != \0; i++)
putchar(s[i]);
putchar(\n);

/* Ispis niske s koristeci funkciju printf */


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

/* Ispis niske t karakter po karakter*/


for (i = 0; t[i] != \0; i++)
putchar(t[i]);
putchar(\n);

/* Ispis niske t koristeci funkciju printf */


printf("%s\n", t);
}

Primer 4.21.3 Brojanje pojavljivanja svake od cifara. Koriscenje niza brojaca.

#include <stdio.h>

/* zbog funkcije isdigit */


#include <ctype.h>

main()
{
/* Niz brojaca za svaku od cifara */
int br_cifara[10];
int i, c;

/* Resetovanje brojaca */

49
50 Milena VujosevicJanicic

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


br_cifara[i] = 0;

/* Citamo sa ulaza i povecavamo odgovarajuce brojace */


while ((c = getchar()) != EOF)
if (isdigit(c))
br_cifara[c-0]++;

/* Ispis rezultata */
for (i = 0; i < 10; i++)
printf("Cifra %d se pojavila %d put%s\n",
i, br_cifara[i], br_cifara[i] == 1 ? "" : "a");
}

Primer 4.21.4 Brojanje reci

#include <stdio.h>

#define IN 1 /* inside a word */


#define OUT 0 /* outside a
word */

/* count lines, words, and characters in input */

main()
{
int c, nl, nw, nc, state;

state = OUT;

/*Postavljaju se sve tri promenljive na nulu*/


/*Isto kao da smo napisali
nl = (nw = (nc = 0));*/

nl = nw = nc = 0;
while ((c = getchar()) != EOF) {
++nc;
if (c == \n)
++nl;
/*Operator || znaci OR*/
if (c == || c == \n || c == \t)
state = OUT;
else if (state == OUT) {
state = IN;
++nw;
}
}
printf("%d %d %d\n", nl, nw, nc);
}

50
4.22 Dvostruka for petlja 51

4.22 Dvostruka for petlja


Primer 4.22.1 Dvostruka for petlja

#include<stdio.h>
int main()
{
int i,j;

for(i=1; i<=10; i++)


{
for(j=1; j<=10; j++)
printf("%d * %d = %d\t", i, j, i*j);
printf("\n");
}
}

Primer 4.22.2 Trostruka for petlja

#include<stdio.h>
int main()
{
int i,j;

for(i=1; i<=10; i++)


for(j=1; j<=10; j++)
{
for(k=1; k<=10; k++)
printf("%d * %d * %d = %d\t", i, j, k, i*j*k);
printf("\n");
}
}

Koliko puta se izvrsi naredba stampanja


printf("%d * %d * %d = %d\t", i, j, k, i*j*k);

4.23 Formiranje HTML dokumenta


Primer 4.23.1 Prilikm pokretanja programa koristiti redirekciju:
a.out >primer.html
kako bi se rezultat rada programa upisao u datoteku primer.html.

/*Ovaj program formira html dokument*/


#include <stdio.h>
main()
{
printf("<html><head><title>Ova stranica
je napravljena u c-u</title></head>");
printf("<body><h3 align=center>
Rezultat </h3></body></html>");
}

51
52 Milena VujosevicJanicic

Primer 4.23.2 Napisati program koji generise html dokument sa engleskim al-
fabetom.

#include <stdio.h>
main()
{
int i;
printf("<HTML><head><title>Engleski alfabet</title><head>\n");
printf("<body><ul>");
for(i=0;i<=25;i++)
printf("<li> %c %c \n",A+i,a+i);
printf("</ul></body></HTML>\n"); }

Primer 4.23.3 Napisati program koji generise html dokument koji prikazuje
tablicu mnozenja za brojeve od 1 do 10.

#include<stdio.h>
main()
{
int i,j;
printf("<html><head><title>Mnozenje</title></head>");
printf("<body><h3 align=center> Rezultat </h3>");
printf("<table border=1>\n");

/* Prva vrsta sadrzi brojeve od 1 do 10*/


printf("<tr>");
printf("<th></th>");
for(i=1; i<=10; i++)
printf("<th> %d </th>\n", i);
printf("</tr>");

for(i=1; i<=10; i++)


{
printf("<tr>");

/* Na pocetku svake vrste stampamo broj


odgovarajuce vrste*/
printf("<th>%d</th>", i);

for(j=1; j<=10; j++)


printf("<td>%d\t</td>\n", i*j);

printf("</tr>");
}
printf("</table>");
printf("</body></html>");
}

52
4.24 Funkcije prenos parametara po vrednosti 53

4.24 Funkcije prenos parametara po vred-


nosti
Primer 4.24.1 Funkcija koja proverava da li je broj prost i program koji ispisuje
sve proste brojeve manje od 100.
#include<stdio.h>
#include<math.h>

int prost(int p)
{
int i, koren, ind;
koren=sqrt(p);
ind=(p%2) || (p==2);
i=3;
while (ind && i<=koren)
{
ind=p%i;
i+=2;
}
return ind;
}

main()
{
int k;
for(k=2;k<=100;k++)
if (prost(k)) printf("%d ",k);
}

Primer 4.24.2
#include <stdio.h> /* Ilustruje vidljivost imena*/

int i=10;

void main() {
{
int i=3;
{
int i=1;
printf("%d\n", i);
}
printf("%d\n",i);
}
printf("%d\n",i);
}

Primer 4.24.3 Demonstracija prenosa parametara po vrednosti - preneti parametri


se ne mogu menjati
#include <stdio.h>

53
54 Milena VujosevicJanicic

void f(int x)
{
x++;
}

main()
{
int x=3;
f(x);
printf("%d\n", x);
}

Primer 4.24.4 Demonstrira prenos nizova u funkciju - preneti niz se moze


menjati.
#include <stdio.h>
#include <ctype.h>

/* Funkcija ucitava rec sa standardnog ulaza i smesta je u niz karaktera s.


Ovo uspeva zbog toga sto se po vrednosti prenosi adresa pocetka niza,
a ne ceo niz */
void get_word(char s[])
{
int c, i = 0;
while (!isspace(c=getchar()))
s[i++] = c;
s[i] = \0;
}

main()
{
/* Obavezno je alocirati memoriju za niz karaktera */
char s[100];

get_word(s);
printf("%s\n", s);
}

Primer 4.24.5 Funkcija za ispis niza brojeva - demonstrira prenos nizova bro-
jeva u funkciju.

#include <stdio.h>

/* Nizovi se prenose tako sto se prenese adresa njihovog pocetka.


Uglaste zagrade ostaju prazne!

Nizove je neophodno prenositi zajedno sa dimenzijom niza


(osim za niske karaktera, jer tamo vazi konvencija da
se kraj niza obelezava znakom \0)
*/
void print_array(int a[], int n)

54
4.25 Break i continue 55

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

/* Obratite paznju na ovo : */


printf("sizeof(a) - u okviru fje : %d\n", sizeof(a));
}

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

printf("sizeof(a) - u okviru main : %d\n", sizeof(a));


print_array(a, sizeof(a)/sizeof(int));
}

Primer 4.24.6 Funkcija za ispis niske karaktera - demonstrira prenos niske


karaktera u funkciju.

#include <stdio.h>

/* Uz nisku karaktera nije potrebno prenositi dimenziju


ukoliko se postuje dogovor
da se svaka niska zavrsava karakterom \0.*/
void print_string(char s[])
{
int i;
for (i = 0; s[i]!=\0; i++)
putchar(s[i]);
}

main()
{
print_string("Zdravo\n");
}

4.25 Break i continue


Primer 4.25.1 Funkcija uklanja beline, tabulatore ili znak za kraj reda sa kraja
stringa.

int trim(char s[])


{
int n;
for (n = strlen(s)-1; n >= 0; n--)
if (s[n] != && s[n] != \t && s[n] != \n)
break;

55
56 Milena VujosevicJanicic

s[n+1] = \0;
return n;
}

Continue se re e koristi, on prouzrokuje da se pre e na sledecu iteraciju u


petlji.

Primer 4.25.2
for(i=0; i<n; i++)
{
if (a[i]==0) continue;
... /* obradi pozitivne elemente nekako*/
}

4.26 Rad sa niskama karaktera


Primer 4.26.1 string reverse - obrce nisku karaktera.

#include <stdio.h>

/* Ova funkcija racuna duzinu date niske karaktera.


Umesto nje, moguce je koristiti standardnu funkciju strlen
za cije je koriscenje potrebno ukljuciti zaglavlje
<string.h>
*/
int string_length(char s[])
{
int i;
for (i = 0; s[i]!=\0; i++)
;

return i;
}

/* Funkcija obrce nisku karaktera */


void string_reverse(char s[])
{
int i, j;
for (i = 0, j = string_length(s)-1; i<j; i++, j--)
{
int tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}

/* Napomena : razlikovati prethodnu petlju od dve ugnjezdjene petlje:


for ( i = 0; ....)
for ( j = duzina(s)-1; ...
*/

56
4.26 Rad sa niskama karaktera 57

main()
{
char s[] = "Zdravo svima";
string_reverse(s);
printf("%s\n", s);
}
/*
Izlaz:
amivs ovardZ
*/

Primer 4.26.2 strlen, strcpy, strcat, strcmp, strchr, strstr - manip-


ulacija niskama karaktera. Vezbe radi, implementirane su funkcije biblioteke
string.h

#include <stdio.h>

/* Izracunava duzinu stringa */


int string_length(char s[])
{
int i;
/* Uslov s[i] je ekvivalentan uslovu
s[i]!=\0 ili uslovu s[i]! = 0*/
for (i = 0; s[i]; i++)
;
return i;
}

/* Kopira string src u string dest.


Pretpostavlja da u dest ima dovoljno prostora. */
void string_copy(char dest[], char src[])
{
/* Kopira karakter po karakter, sve dok nije iskopiran karakter \0 */
int i;
for (i = 0; (dest[i]=src[i]) != \0; i++)
;

/* Uslov != \0 se, naravno, moze izostaviti :

for (i = 0; dest[i]=src[i]; i++)


;
*/

/* Nadovezuje string t na kraj stringa s.

57
58 Milena VujosevicJanicic

Pretpostavlja da u s ima dovoljno prostora. */


void string_concatenate(char s[], char t[])
{
int i, j;
/* Pronalazimo kraj stringa s */
for (i = 0; s[i]; i++)
;

/* Vrsi se kopiranje, slicno funkciji string_copy */


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

/* Vrsi leksikografsko poredjenje dva stringa.


Vraca :
0 - ukoliko su stringovi jednaki
<0 - ukoliko je s leksikografski ispred t
>0 - ukoliko je s leksikografski iza t
*/
int string_compare(char s[], char t[])
{
/* Petlja tece sve dok ne naidjemo na prvi razliciti karakter */
int i;
for (i = 0; s[i]==t[i]; i++)
if (s[i] == \0) /* Naisli smo na kraj oba stringa,
a nismo nasli razliku */
return 0;

/* s[i] i t[i] su prvi karakteri u kojima se niske razlikuju.


Na osnovu njihovog odnosa, odredjuje se odnos stringova */
return s[i] - t[i];
}

/* Pronalazi prvu poziciju karaktera c u stringu s, odnosno -1


ukoliko s ne sadrzi c */
int string_char(char s[], char c)
{
int i;
for (i = 0; s[i]; i++)
if (s[i] == c)
return i;
/* nikako
else
return -1;
*/
/* Nije nadjeno */
return -1;
}

/* Pronalazi poslednju poziciju karaktera c u stringu s, odnosno -1

58
4.26 Rad sa niskama karaktera 59

ukoliko s ne sadrzi c */
int string_last_char(char s[], char c)
{
/* Pronalazimo kraj stringa s */
int i;
for (i = 0; s[i]; i++)
;

/* Krecemo od kraja i trazimo c unazad */


for (i--; i>=0; i--)
if (s[i] == c)
return i;

/* Nije nadjeno */
return -1;

/*
Koristeci string_length :

for (i = string_length(s) - 1; i>0; i--)


if (s[i] == c)
return i;

return -1;
*/
}

/* Proverava da li string str sadrzi string sub.


Vraca poziciju na kojoj sub pocinje, odnosno -1 ukoliko ga nema
*/
int string_string(char str[], char sub[])
{
int i, j;
/* Proveravamo da li sub pocinje na svakoj poziciji i */
for (i = 0; str[i]; i++)
/* Poredimo sub sa str pocevsi od poziciji i
sve dok ne naidjemo na razliku */
for (j = 0; str[i+j] == sub[j]; j++)
/* Nismo naisli na razliku a ispitali smo
sve karaktere niske sub */
if (sub[j+1]==\0)
return i;
/* Nije nadjeno */
return -1;
}

main()
{
char s[100];
char t[] = "Zdravo";

59
60 Milena VujosevicJanicic

char u[] = " svima";

string_copy(s, t);
printf("%s\n", s);

string_concatenate(s, u);
printf("%s\n", s);

printf("%d\n",string_char("racunari", n));
printf("%d\n",string_last_char("racunari", a));

printf("%d\n",string_string("racunari", "rac"));
printf("%d\n",string_string("racunari", "ari"));
printf("%d\n",string_string("racunari", "cun"));
printf("%d\n",string_string("racunari", "cna"));
}

/*
Izlaz:
Zdravo
Zdravo svima
4
5
0
5
2
-1*/

4.27 Makroi
#define ime tekst_zamene

Zamene se vrse samo na simbolima, a ne obavljaju se u niskama nutar navodnika.


Moguce je definisati makroe sa argumentima tako da tekst zamene bude
razlicit za razlicita pojavljivanja makroa.

Primer 4.27.1 Demonstracija pretprocesorske direktive #define

#include<stdio.h>

/* Racuna sumu dva broja */


#define sum(a,b) ((a)+(b))

/* Racuna kvadrat broja - pogresna verzija */


#define square_w(a) a*a

/* Racuna kvadrat broja */


#define square(a) ((a)*(a))

/* Racuna minimum tri broja */

60
4.27 Makroi 61

#define min(a, b, c) (a)<(b)? ((a)<(c)? (a) : (c)) : ((b)<(c)? (b) : (c))

main()
{
printf("sum(3,5) = %d\n", sum(3,5));
printf("square_w(5) = %d\n", square_w(5));
printf("square_w(3+2) = %d\n", square_w(3+2));
printf("square(3+2) = %d\n", square(3+2));
printf("min(1,2,3) = %d\n", min(1,2,3));
printf("min(1,3,2) = %d\n", min(1,3,2));
printf("min(2,1,3) = %d\n", min(2,1,3));
printf("min(2,3,1) = %d\n", min(2,3,1));
printf("min(3,1,2) = %d\n", min(3,1,2));
printf("min(3,2,1) = %d\n", min(3,2,1));
}

Izlaz iz programa:
sum(3,5) = 8
square_w(5) = 25
square_w(3+2) = 11
square(3+2) = 25
min(1,2,3) = 1
min(1,3,2) = 1
min(2,1,3) = 1
min(2,3,1) = 1
min(3,1,2) = 1
min(3,2,1) = 1

Primer 4.27.2
#define max(A, B) ((A)>(B) ? (A) : (B))

na osnovu ovoga ce linija

x=max(p+q, r+s)

biti zamenjena linijom

x=((p+q) > (r+s) ? (p+q) : (r+s));

Treba voditi racuna o sporednim efektima. Sledeca linija koda pruzrokovace


uvecanje vrednosti i ili j za dva.

max(i++, j++)

Tako e treba voditi racuna o zagradama. Sledeci makro prouzrokovace


neocekivane rezultate za upotrebu square(a+1)

#define square(x) x*x

Primer 4.27.3 Ilustacija beskonacne petlje:

#define forever for(;;);

61
62 Milena VujosevicJanicic

Primer 4.27.4
#include <stdio.h>
#define max1(x,y) (x>y?x:y)
#define max2(x,y) ((x)>(y)?(x):(y))
#define swapint(x,y) { int z; z=x; x=y; y=z; }
#define swap(t,x,y) { \
t z; \
z=x; \
x=y; \
y=z; }

main()
{

int x=2,y=3;

printf( "max1(x,y) = %d\n", max1(x,y) );


/* max1(x,y) = 3 */

/* Zamena makroom se ne vrsi


unutar niski pod navodnicima*/
printf( "max1(x=5,y) = %d\n", max1(x,y) );
/* max1(x=5,y) = 3 */

printf( "max1(x++,y++) = %d\n", max1(x++,y++) );


/* max1(x++,y++) = 4 */

printf( "x = %d, y = %d\n", x, y );


/* x = 3, y = 5 */

swapint(x,y);

printf( "x = %d, y = %d\n", x, y );


/* x = 5, y = 3 */

swap(int,x,y);
printf( "x = %d, y = %d\n", x, y );
/* x = 3, y = 5 */
}

Izlaz:
max1(x,y) = 3
max1(x=5,y) = 3
max1(x++,y++) = 4
x = 3, y = 5
x = 5, y = 3
x = 3, y = 5

62
4.28 Bitski operatori 63

4.28 Bitski operatori


!!!Ne mesati sa logickim operatorima!!!

& bitsko AND


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

Primer 4.28.1 Demonstracija bitskih operatora

#include <stdio.h>

main()
{ printf("%o %o\n",255,15);
printf( "255 & 15 = %d\n", 255 & 15 );
printf( "255 | 15 = %d\n", 255 | 15 );
printf( "255 ^ 15 = %d\n", 255 ^ 15 );
printf( "2 << 2 = %d\n", 2 << 2 );
printf( "16 >> 2 = %d\n", 16 >> 2 );
}

Izlaz iz programa je:


377 17
255 & 15 = 15
255 | 15 = 255
255 ^ 15 = 240
2 << 2 = 8
16 >> 2 = 4

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

#include <stdio.h>

/* Funkcija stampa bitove datog celog broja x.


Vrednost bita na poziciji i je 0 ako i
samo ako se pri konjunkciji broja x sa maskom
000..010....000 - sve 0 osim 1 na poziciji i,
dobija 0.
Funkcija krece od pozicije najvece tezine
kreirajuci masku pomeranjem jedinice u levo
za duzina(x) - 1 mesto, i zatim pomerajuci
ovu masku za jedno mesto u levo u svakoj
sledecoj iteraciji sve dok maska ne postane 0.
*/

void print_bits(int x)
{
/* Broj bitova tipa unsigned */

63
64 Milena VujosevicJanicic

int wl = sizeof(int)*8;

unsigned mask;
for (mask = 1<<wl-1; mask; mask >>= 1)
putchar(x&mask ? 1 : 0);

putchar(\n);
}

main()
{
print_bits(127);
print_bits(128);
print_bits(0x00FF00FF);
print_bits(0xFFFFFFFF);
}

Izlaz iz programa:
00000000000000000000000001111111
00000000000000000000000010000000
00000000111111110000000011111111
11111111111111111111111111111111

Primer 4.28.3 Program proverava da li se na k-tom mestu nalazi 1.

#include <stdio.h>

/* Pozicije brojimo kao u sledecem primeru:


poz: ... 10 9 8 7 6 5 4 3 2 1 0
bit: ... 0 0 0 1 1 1 0 0 1 1 0 */

main()
{
int n,k;
printf("Unesite broj i poziciju tog broja koju zelite da proverite:\n");
scanf("%d%d",&n,&k);
if ((n & (1 << k))!=0)
printf("Bit je 1\n");
else
printf("Bit je 0\n");
}

Primer 4.28.4 Program postavlja na k-to mesto 1


#include <stdio.h>

void print_bits(int x)
{
/* Broj bitova tipa unsigned */
int wl = sizeof(int)*8;

64
4.28 Bitski operatori 65

unsigned mask;
for (mask = 1<<wl-1; mask; mask >>= 1)
putchar(x&mask ? 1 : 0);

putchar(\n);
}

main(){
int n,k;
printf("Unesite broj i poziciju tog broja koju zelite da promenite:\n");
scanf("%d%d",&n,&k);
printf("Binarno, une\v seni broj je\n");
print_bits(n);
printf("Novi broj je %d\n",(n |(1<<k)));
printf("Binarno, novi broj je\n");
print_bits((n |(1<<k)));
}

Izrazom a>>b vrsi se pomeranje sadrzaja operanda a predstavljenog u bi-


narnom obliku za b mesta u desno. Popunjavanje upraznjenih mesta na levoj
strani zavisi od tipa podataka i vrste racunara. Ako se pomeranje primen-
juje nad operandom tipa unsigned popunjavanje je nulama. Ako se radi o
oznacenom operandu popunjavanje je jedinicama kada je u krajnjem levom bitu
jedinica, a nulama kada je u krajnjem levom bitu nula.

Primer 4.28.5 sum of bits - izracunava sumu bitova datog neoznacenog broja.
#include <stdio.h>

/* Pomocna funkcija - stampa bitove neoznacenog broja */


void print_bits(unsigned x)
{
int wl = sizeof(unsigned)*8;

unsigned mask;
for (mask = 1<<wl-1; mask; mask >>= 1)
putchar(x&mask ? 1 : 0);

putchar(\n);
}

int sum_of_bits(unsigned x)
{
int br;
for (br = 0; x; x>>=1)
if (x&1)
br++;

return br;
}

65
66 Milena VujosevicJanicic

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

Izlaz iz programa:
Binarni zapis broja 127 je
00000000000000000000000001111111
Suma bitova broja 127 je 7
Binarni zapis broja 128 je
00000000000000000000000010000000
Suma bitova broja 128 je 1
Binarni zapis broja 0x00FF00FF je
00000000111111110000000011111111
Suma bitova broja 0x00FF00FF je 16
Binarni zapis broja 0xFFFFFFFF je
11111111111111111111111111111111
Suma bitova broja 0xFFFFFFFF je 32
Primer 4.28.6 get bits, set bits, invert bits - izdvajanje, postavljanje i inver-
tovanje pojedinacnih bitova
#include <stdio.h>

/* Pomocna funkcija - stampa bitove neoznacenog broja */


void print_bits(unsigned x)
{
int wl = sizeof(unsigned)*8;

unsigned mask;
for (mask = 1<<wl-1; mask; mask >>= 1)
putchar(x&mask ? 1 : 0);

putchar(\n);
}

/* Funkcija vraca n bitova broja x koji pocinju na poziciji p */


unsigned get_bits(unsigned x, int p, int n)
{
/* Gradimo masku koja ima poslednjih n jedinica

66
4.28 Bitski operatori 67

0000000...00011111
tako sto sve jedinice ~0 pomerimo u levo za n mesta
1111111...1100000
a zatim komplementiramo
*/
unsigned last_n_1 = ~(~0 << n);

/* x pomerimo u desno za odgovarajuci broj mesta, a zatim


konjunkcijom sa konstruisanom maskom obrisemo pocetne cifre */

return (x >> p+1-n) & last_n_1;


}

/* Funkcija vraca modifikovano x tako sto mu je izmenjeno n bitova


pocevsi od pozicije p i na ta mesta je upisano poslednjih n bitova
broja y */
unsigned set_bits(unsigned x, int p, int n, unsigned y)
{
/* Maska 000000...000111111 - poslednjih n jedinica */
unsigned last_n_1 = ~(~0 << n);

/* Maska 1111100..000111111 - n nula pocevsi od pozicije p */


unsigned middle_n_0 = ~(last_n_1 << p+1-n);

/* Brisemo n bitova pocevsi od pozicije p */


x = x & middle_n_0;

/* Izdvajamo poslednjih n bitova broja y i pomeramo ih


na poziciju p */
y = (y & last_n_1) << p+1-n;

/* Upisujemo bitove broja y u broj x i vracamo rezultat */


return x | y;
}

/* Invertuje n bitova broja x pocevsi od pozicije p */


unsigned invert_bits(unsigned x, int p, int n)
{
/* Maska 000000111...1100000 - n jedinica pocevsi od pozicije p */
unsigned middle_n_1 = ~(~0 << n) << p+1-n;

/* Invertujemo koristeci ekskluzivnu disjunkciju */


return x ^ middle_n_1;
}

main()
{
unsigned x = 0x0AA0AFA0;
print_bits(x);

67
68 Milena VujosevicJanicic

print_bits(get_bits(x, 15, 8));


print_bits(set_bits(x, 15, 8, 0xFF));
print_bits(invert_bits(x, 15, 8));
}

Izlaz iz programa:
00001010101000001010111110100000
00000000000000000000000010101111
00001010101000001111111110100000
00001010101000000101000010100000
Primer 4.28.7 right rotate bits, mirror bits - rotiranje i simetrija bitova.
#include <stdio.h>

/* Pomocna funkcija - stampa bitove neoznacenog broja */


void print_bits(unsigned x)
{
int wl = sizeof(unsigned)*8;

unsigned mask;
for (mask = 1<<wl-1; mask; mask >>= 1)
putchar(x&mask ? 1 : 0);

putchar(\n);
}

/* Funkcija vrsi rotaciju neoznacenog broja x za n pozicija u desno */


unsigned right_rotate(unsigned x, int n)
{
int i;
int wl = sizeof(unsigned)*8;

/* Postupak se ponavlja n puta */


for (i = 0; i < n; i++)
{
/* Poslednji bit broja x */
unsigned last_bit = x & 1;

/* x pomeramo za jedno mesto u desno */


x >>= 1;

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

x |= last_bit<<wl-1;
}

return x;
}

/* Funkcija obrce binarni zapis neoznacenog broja x tako sto bitove

68
4.29 Linearna i binarna pretraga 69

cita unatrag */
unsigned mirror(unsigned x)
{
int i;
int wl = sizeof(unsigned)*8;

/* Rezultat inicijalizujemo na poslednji bit broja x */


unsigned y = x & 1;

/* Postupak se ponavlja wl-1 puta */


for (i = 1; i<wl; i++)
{
/* x se pomera u desno za jedno mesto */
x >>= 1;
/* rezultat se pomera u levo za jedno mesto */
y <<= 1;

/* Poslednji bit broja x upisujemo na poslednje


mesto rezultata */
y |= x & 1;
}
return y;
}

main()
{
unsigned x = 0xFAF0FAF0;
print_bits(x);
print_bits(mirror(x));
print_bits(right_rotate(x, 2));
}

Izlaz iz programa:
11111010111100001111101011110000
00001111010111110000111101011111
00111110101111000011111010111100

4.29 Linearna i binarna pretraga


Primer 4.29.1 Linearna pretraga
#include <stdio.h>

/* Funkcija proverava da li se dati element x nalazi


u datom nizu celih brojeva.
Funkcija vraca poziciju u nizu na
kojoj je x pronadjen
odnosno -1 ukoliko elementa nema.
*/
int linearna_pretraga(int niz[], int br_elem, int x)

69
70 Milena VujosevicJanicic

{
int i;
for (i = 0; i<br_elem; i++)
if (niz[i] == x)
return i;
/* nikako else */

return -1;
}

main()
{
/* Inicijalizacija niza moguca je
i na ovaj nacin*/
int a[] = {4, 3, 2, 6, 7, 9, 11};

/* Da bi smo odredili koliko clanova


ima niz mozemo koristiti operator
sizeof*/
int br_elem = sizeof(a)/sizeof(int);
int x;
int i;
printf("Unesite broj koji trazimo : ");
scanf("%d",&x);

i = linearna_pretraga(a, br_elem, x);


if (i == -1)
printf("Element %d nije nadjen\n",x);
else
printf("Element %d je nadjen na
poziciji %d\n",x, i);
}
Primer 4.29.2 Binarna pretraga niza
/* Binarna pretraga niza celih brojeva - iterativna verzija*/
#include <stdio.h>

/* Funkcija proverava da li se element x javlja unutar niza


celih brojeva a.
Funkcija vraca poziciju na kojoj je element nadjen odnosno
-1 ako ga nema.

!!!!! VAZNO !!!!!


Pretpostavka je da je niz a uredjen po velicini
*/

int binarna_pretraga(int a[], int n, int x)


{
/* Pretrazujemo interval [l, d] */
int l = 0;

70
4.30 Razni zadaci 71

int d = n-1;

/* Sve dok interval [l, d] nije prazan */


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

/* Ispitujemo odnos x i a[srednjeg elementa] */


if (x == a[s])
/* Element je pronadjen */
return s;
else if (x < a[s])
{
/* Pretrazujemo interval [l, s-1] */
d = s-1;
}
else
{
/* Pretrazujemo interval [s+1, d] */
l = s+1;
}
}

/* Element je nadjen */
return -1;
}

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

printf("Unesi element kojega trazimo : ");


scanf("%d",&x);
i = binarna_pretraga(a, sizeof(a)/sizeof(int), x);

if (i==-1)
printf("Elementa %d nema\n", x);
else
printf("Pronadjen na poziciji %d\n", i);
}

4.30 Razni zadaci


Primer 4.30.1 Obrtanje stringa i pretvaranje broja u string
#include <stdio.h>
#include <string.h>

71
72 Milena VujosevicJanicic

/* reverse: obrce string, npr string "1234" postaje "4321" */


void reverse(char s[])
{
int c, i, j;

for (i = 0, j = strlen(s)-1; i < j; i++, j--)


{
c = s[i];
s[i] = s[j];
s[j] = c;
}
}

/* itoa: konvertuje broj n u niz karaktera s */


void itoa(int n, char s[])
{
int i, sign;

if ((sign = n) < 0) /* sacuvaj znak */


n = -n; /* napravi da je n pozitivno */
i = 0;
do {
/* generisanje cifara u obrnutom smeru */
s[i++] = n % 10 + 0; /* izracunaj sledecu cifru */
} while ((n /= 10) > 0); /* izbaci cifru iz zapisa */
if (sign < 0)
s[i++] = -;
s[i] = \0;
reverse(s);
}

main()
{
int n=-44;
char nst[100];
itoa(n,nst);
printf("%s\n",nst);
}
Primer 4.30.2 btoi - konverzija iz datog brojnog sistema u dekadni.
#include <stdio.h>
#include <ctype.h>

/* Pomocna funkcija koja izracunava vrednost


koju predstavlja karakter u datoj osnovi
Funkcija vraca -1 ukoliko cifra nije validna.

Npr.
cifra B u osnovi 16 ima vrednost 11

72
4.30 Razni zadaci 73

cifra 8 nije validna u osnovi 6


*/

int digit_value(char c, int base)


{
/* Proveravamo obicne cifre */
if (isdigit(c) && c < 0+base)
return c-0;

/* Proveravamo slovne cifre za mala slova */


if (a<=c && c < a+base-10)
return c-a+10;

/* Proveravamo slovne cifre za velika slova */


if (A<=c && c < A+base-10)
return c-A+10;

return -1;
}

/* Funkcija izracunava vrednost celog broja koji je zapisan u datom


nizu karaktera u datoj osnovi. Za izracunavanje se koristi
Hornerova shema.
*/
int btoi(char s[], int base)
{
int sum = 0;

/* Obradjuju se karakteri sve dok su to validne cifre */


int i, vr;
for (i = 0; (vr = digit_value(s[i], base)) != -1; i++)
sum = base*sum + vr;

return sum;
}

main()
{
char bin[] = "11110000";
char hex[] = "FF";

printf("Dekadna vrednost binarnog broja %s je %d\n", bin, btoi(bin, 2));


printf("Dekadna vrednost heksadekadnog
broja %s je %d\n", hex, btoi(hex, 16));
}
Primer 4.30.3 Ucitava linije sa ulaza i pamti najduzu liniju.
#include <stdio.h>
#define MAXLINE 1000 /* maximum input line length */

73
74 Milena VujosevicJanicic

int getline(char line[], int maxline);


void copy(char to[], char from[]);

/* print the longest input line */


main()
{
int len; /* current line length */
int max; /* maximum length seen so far */
char line[MAXLINE]; /* current input line */
char longest[MAXLINE]; /* longest line saved here */

max = 0;
while ((len = getline(line, MAXLINE)) > 0)
if (len > max) {
max = len;
copy(longest, line);
}
if (max > 0) /* there was a line */
printf("%s", longest);
}

/* getline: read a line into s, return length */


int getline(char s[],int lim)
{
int c, i;

for (i=0; i < lim-1


&& (c=getchar())!=EOF && c!=\n;++i)
s[i] = c;
if (c == \n) {
s[i] = c;
++i;
}
s[i] = \0;
return i;
}

/* copy: copy from into to;


assume to is big enough */
void copy(char to[], char from[])
{
int i;

i = 0;
while ((to[i] = from[i]) != \0)
++i;
}

Primer 4.30.4 Konvertovanje stringa u broj u pokretnom zarezu.

74
4.30 Razni zadaci 75

#include <ctype.h>
#include <stdio.h>
#define MAXLINE 100

/* getline: get line into s, return length */


int getline(char s[], int lim)
{
int c, i;

i = 0;
while (--lim > 0 && (c=getchar()) != EOF && c != \n)
s[i++] = c;
if (c == \n)
s[i++] = c;
s[i] = \0;
return i;
}

/* atof: convert string s to double */


double atof(char s[])
{
double val, power;
int i, sign;

/* skip white space */


for (i = 0; isspace(s[i]); i++)
;
/* Postavlja se znak broja*/
sign = (s[i] == -) ? -1 : 1;

/* Preskace se jedno mesto ukoliko je bio upisan znak u broj*/


if (s[i] == + || s[i] == -)
i++;

/* Racuna se vrednost broja dok se ne naidje na tacku */


for (val = 0.0; isdigit(s[i]); i++)
val = 10.0 * val + (s[i] - 0);

if (s[i] == .)
i++;

/* Racuna se vrednost broja iza tacke*/


for (power = 1.0; isdigit(s[i]); i++)
{
val = 10.0 * val + (s[i] - 0);
power *= 10;
}
return sign * val / power;
}

75
76 Milena VujosevicJanicic

/* Program sabira brojeve u pokretnom zarezu koji se unose sa ulaza*/


main()
{
double sum;
char line[MAXLINE];

sum = 0;
while (getline(line, MAXLINE) > 0)
printf("\t%g\n", sum += atof(line));
}

Primer 4.30.5 Funkcija koja uklanja znak c kad god se pojavi u stringu s.

#include <stdio.h>

void squeeze(char s[], char c)


{
int i,j;
for(i=j=0; s[i]!=\0;i++)
if(s[i]!=c) s[j++]=s[i];
s[j]=\0;
}

main()
{
char niz[20];
char c;

printf("Unesi karakter\n\n");
scanf("%c", &c);

scanf("%s", niz);
squeeze(niz, c);
printf("%s\n", niz);
}

4.31 Sortiranje
Primer 4.31.1 U prvom prolazu se razmenjuju vrednosti a[0] sa onim clanovima
ostatka niza koji su veci od njega. Na taj nacin ce se posle prvog prolaza kroz
niz a[0] postaviti na najveci element niza.

#include<stdio.h>
#define MAXDUZ 100

int main()
{
/* Niz od maksimalno MAXDUZ elemenata*/
int a[MAXDUZ];

76
4.31 Sortiranje 77

/* Dimenzija niza, pomocna i brojacke promenljive */


int n,pom,i,j;

printf("Unesite dimenziju niza\n");


scanf("%d",&n);

if (n>MAXDUZ)
{
printf("Nedozvoljena vrednost za n\n");
exit(1);
}

/* Unos clanova niza */


for(i=0; i<n; i++)
{
printf("Unesite %d. clan niza\n",i+1);
scanf("%d",&a[i]);
}

/*Sortiranje*/
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(a[i]<a[j])
{
pom=a[i];
a[i]=a[j];
a[j]=pom;
}

/* Ispis niza */
printf("Sortirani niz:\n");
for(i=0; i<n; i++)
printf("%d\t",a[i]);

putchar(\n);

return 0;

}
Primer 4.31.2 sort2
Modifikacija prethodnog resenja radi dobijanja na efikasnosti. Ne vrse se zamene
svaki put vec samo jednom, kada se prona e odgovarajuci element u nizu sa


kojim treba izvrsiti zamenu tako da u nizu bude postavljen trenutno najveci
element na odgovarajuce mesto.
#include<stdio.h>
#define MAXDUZ 100

int main()
{

77
78 Milena VujosevicJanicic

/* Niz od maksimalno MAXDUZ elemenata*/


int a[MAXDUZ];

/* Dimenzija niza, indeks najveceg elementa


u i-tom prolazu,pomocna i brojacke promenljive */
int n,ind,pom,i,j;

printf("Unesite dimenziju niza\n");


scanf("%d",&n);

if (n>MAXDUZ)
{
printf("Nedozvoljena vrednost za n\n");
exit(1);
}

/* Unos clanova niza */


for(i=0; i<n; i++)
{
printf("Unesite %d. clan niza\n",i+1);
scanf("%d",&a[i]);
}

/*Sortiranje - bez stalnih zamena vec se


pronalazi indeks trenutno najveceg clana niza*/
for(i=0; i<n-1; i++)
{
for(ind=i,j=i+1; j<n; j++)
if(a[ind]<a[j])
ind=j;

/* Vrsi se zamena onda kada na i-tom mestu


nije najveci element. Tada se na i-to mesto
postavlja najveci element koji se nalazio na
mestu ind. */
if(i != ind)
{
pom=a[ind];
a[ind]=a[i];
a[i]=pom;
}
}
/* Ispis niza */
printf("Sortirani niz:\n");
for(i=0; i<n; i++)
printf("%d\t",a[i]);

return 0;

78
4.31 Sortiranje 79

}
Primer 4.31.3 bbsort1
Algoritam sortiranja buble sort poredi dva susedna elementa niza i ako su pogresno
raspore eni zamenjuje im mesta. Posle pore enja svih susednih parova najmanji
 

od njih ce isplivati na kraj niza. Zbog toga se ovaj metod naziva metod mehurica.
Da bi se najmanji broj nesortiranog dela niza doveo na svoje mesto treba ponoviti
postupak.
#include<stdio.h>
#define MAXDUZ 100

int main()
{
/* Dimenzija niza, pomocna promenljiva
i brojacke promenljive */
int n,pom,i,j;

/* Niz od maksimalno MAXDUZ elemenata*/


int a[MAXDUZ];

printf("Unesite dimenziju niza\n");


scanf("%d",&n);

if (n>MAXDUZ)
{
printf("Nedozvoljena vrednost za n\n");
exit(1);
}

/* Unos clanova niza */


for(i=0; i<n; i++)
{
printf("Unesite %d. clan niza\n",i+1);
scanf("%d",&a[i]);
}

/*Sortiranje */
for(i=n-1; i>0; i--)
for(j=0; j<i; j++)
if(a[j]<a[j+1])
{
pom=a[j];
a[j]=a[j+1];
a[j+1]=pom;
}

/* Ispis niza */
printf("Sortirani niz:\n");
for(i=0; i<n; i++)
printf("%d\t",a[i]);

79
80 Milena VujosevicJanicic

/* Stampa prazan red */


putchar(\n);

/*Regularan zavrsetak rada programa */


return 0;

}
Primer 4.31.4 bbsort2
Unapredjujemo prethodni algoritam kako bismo obezbedli da se ne vrse provere
onda kada je niz vec sortiran nego da se u tom slucaju prekine rad.
#include<stdio.h>
#define MAXDUZ 100

int main()
{
/* Dimenzija niza, pomocna promenljiva
i brojacke promenljive */
int n,pom,i,j;

/* Niz od maksimalno MAXDUZ elemenata*/


int a[MAXDUZ];

/* Promenljiva koja govori da li je izvrsena


zamena u i-tom prolazu kroz niz pa ako nije
sortiranje je zavrseno jer su svaka dva
susedna elementa niza u odgovarajucem poretku */
int zam;

printf("Unesite dimenziju niza\n");


scanf("%d",&n);

if (n>MAXDUZ)
{
printf("Nedozvoljena vrednost za n\n");
exit(1);
}

/* Unos clanova niza */


for(i=0; i<n; i++)
{
printf("Unesite %d. clan niza\n",i+1);
scanf("%d",&a[i]);
}

/*Sortiranje */
for(zam=1,i=n-1; zam && i>0; i--)
for(zam=0,j=0; j<i; j++)
if(a[j]<a[j+1])

80
4.31 Sortiranje 81

{
/* Zamena odgovarajucih clanova niza */
pom=a[j];
a[j]=a[j+1];
a[j+1]=pom;

/* Posto je u i-tom prolazu


izvrsena bar ova zamena zam
se postavlja na 1 sto
nastavlja sortiranje */
zam=1;
}

/* Ispis niza */
printf("Sortirani niz:\n");
for(i=0; i<n; i++)
printf("%d\t",a[i]);

return 0;

}
Primer 4.31.5 isort
Insert sort, u svakom trenutku je pocetak niza sortiran a sortiranje se vrsi tako
sto se jedan po jedan element niza sa kraja ubacuje na odgovarajuce mesto.
#include<stdio.h>
#define MAXDUZ 100

int main()
{
/* Dimenzija niza, pomocna
i brojacke promenljive */
int n,pom,i,j;

/* Niz od maksimalno MAXDUZ elemenata*/


int a[MAXDUZ];

printf("Unesite dimenziju niza\n");


scanf("%d",&n);

if (n>MAXDUZ)
{
printf("Nedozvoljena vrednost za n!\n");
exit(1);
}

/* Unos clanova niza */


for(i=0; i<n; i++)
{
printf("Unesite %d. clan niza\n",i+1);

81
82 Milena VujosevicJanicic

scanf("%d",&a[i]);
}

/*Sortiranje*/
for(i=1; i<n; i++)
for(j=i; (j>0) && (a[j]>a[j-1]); j--)
{
pom=a[j];
a[j]=a[j-1];
a[j-1]=pom;
}

/* Ispis niza */
printf("Sortirani niz:\n");
for(i=0; i<n; i++)
printf("%d\t",a[i]);

putchar(\n);
return 0;
}
Primer 4.31.6 Binarno pretrazivanje
#include<stdio.h>
#define MAXDUZ 100

int main()
{
/* Dimenzija niza,pomocna i brojacke
promenljive */
int n,pom,i,j;

/* Niz od maksimalno MAXDUZ elemenata*/


int a[MAXDUZ];

/* Elemet koji se trazi i pozicija


na kojoj se nalazi- ukoliko je u nizu*/
int x,pozicija;

/* Pomocne promenljive za pretragu */


int donji, gornji, srednji;

printf("Unesite dimenziju niza\n");


scanf("%d",&n);

/* Unos clanova niza */


for(i=0; i<n; i++)
{
printf("Unesite %d. clan niza\n",i+1);
scanf("%d",&a[i]);
}

82
4.31 Sortiranje 83

/*Sortiranje*/
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(a[i]>a[j])
{
pom=a[i];
a[i]=a[j];
a[j]=pom;
}
/* Unos elementa binarne pretrage */
printf("Unesite element koji se trazi\n");
scanf("%d",&x);

donji = 0;
gornji = n-1;
pozicija = -1;

while(donji<=gornji)
{
srednji = (donji + gornji)/2;
if(a[srednji] == x)
{
pozicija = srednji;
break;
}
else
if(a[srednji] < x)
donji = srednji + 1;
else
gornji = srednji -1;
}

/* Ispis rezultata */
if(pozicija == -1)
printf("Trazeni broj se ne nalazi u nizu!\n");
else
printf("Broj %d se nalazi na %d poziciji
sortiranog niza! \n",x,pozicija+1);

putchar(\n);

return 0;
}
Primer 4.31.7 Sabiranje dva velika broja, njihovo pore enje, unos i ispis, mnozenje


velikog broja cifrom.

#include<stdio.h>

83
84 Milena VujosevicJanicic

#define MAXDUZ 1000

int unos_broja(int cifre[], int maxduz)


{
int brcifara=0;
char c;

c=getchar();
while ( brcifara < maxduz && c >= 0 && c <= 9)
{
cifre[brcifara++]=c-0;
c=getchar();
}

return brcifara;
}

void obrni(int cifre[],int brcifara)


{
int i,pom;

for (i=0; i<brcifara/2; i++)


{
pom=cifre[i];
cifre[i]=cifre[brcifara-i-1];
cifre[brcifara-i-1]=pom;
}
}

void ispisi(int cifre[],int brcifara)


{ int i;
putchar(\n);
for (i=brcifara-1; i>=0; i--)
printf("%d",cifre[i]);
/* ili
putchar(cifre[i]+0);
*/
putchar(\n);
}

int jednaki(int cifre1[],int cifre2[],


int brcifara1, int brcifara2)
{
int i;
if (brcifara1 != brcifara2) return 0;

for (i=0; i<brcifara1; i++)


if (cifre1[i] != cifre2[i]) return 0;
return 1;
}

84
4.31 Sortiranje 85

int veci(int cifre1[], int brcifara1,


int cifre2[], int brcifara2)
{
int i;
if (brcifara1>brcifara2) return 1;
if (brcifara1<brcifara2) return 0;

for (i=brcifara1-1; i>=0; i--)


{
if (cifre1[i]<cifre2[i]) return 0;
if (cifre1[i]>cifre2[i]) return 1;
}

return 0;
}

int saberi(int cifre1[], int brcifara1,


int cifre2[], int brcifara2,
int cifre[])
{
int brcifara=0;
int i,pom,pamtim=0;

for(i=0; i<brcifara1 || i<brcifara2; i++)


{
pom =((i < brcifara1)? cifre1[i] : 0 )
+((i < brcifara2)? cifre2[i] : 0)
+ pamtim;

cifre[i] = pom%10;
pamtim = pom/10;
}
if (pamtim)
{
cifre[i]=pamtim;
brcifara=i+1;
}
else brcifara=i;

return brcifara;
}

int pomnozic(int c,int cifre[],


int brcifara, int pcifre[])
{
int pbrcifara=0;
int i,pamtim=0;

85
86 Milena VujosevicJanicic

for (i=0; i<brcifara; i++)


{
pcifre[i]=(cifre[i]*c+pamtim)%10;
pamtim=(cifre[i]*c+pamtim)/10;
}
pbrcifara=brcifara;
if (pamtim)
{
pcifre[pbrcifara]=pamtim;
pbrcifara++;
}

return pbrcifara;
}

int main()
{
int d1,d2,d;
int broj1[MAXDUZ], broj2[MAXDUZ], zbir[MAXDUZ];
d1=unos_broja(broj1,MAXDUZ);
d2=unos_broja(broj2,MAXDUZ);

obrni(broj1,d1);
obrni(broj2,d2);
d=saberi(broj1,d1,broj2,d2,zbir);
ispisi(zbir,d);
return 0;
}

4.32 Rekurzija
C funkcije se mogu rekurzivno koristiti, sto znaci da funkcija moze pozvati samu
sebe direktno ili indirektno.

Primer 4.32.1 Stampanje celog broja.


#include<stdio.h>
void printb(long int n)
{
if(n<0)
{
putchar(-);
n=-n;
}
if(n/10)
printb(n/10);
putchar(n % 10 + 0);
}

86
4.32 Rekurzija 87

int main()
{
long int b=-1234;
printb(b);
putchar(\n);
return 0;
}

Kad funkcija rekurzivno pozove sebe, svakim pozivom pojavljuje se novi skup
svih automatskih promenljivih, koji je nezavisan od prethodonog skupa. Prva
funkcija printb kao argument dobija broj -12345, ona prenosi 1234 u drugu printb
funkciju, koja dalje prenosi 123 u trecu, i tako redom do poslednje koja prima
1 kao argument. Ta funkcija stampa 1 i zavrsava sa radom tako da se vraca na
prethodni nivo, na kome se stampa dva i tako redom.

Primer 4.32.2 Racunanje sume prvih n prirodnih brojeva.

#include<stdio.h>
int suma(int n)
{
if(n!=0)
return( n + suma(n-1) );
else return n;
}

main()
{
int S,n;
printf("Unesite n\n");
scanf("%d",&n);
S=suma(n);
printf("S=%d",S);
putchar(\n);
}

Primer 4.32.3 Racunanje faktorijela prirodnog broja.

#include<stdio.h>
unsigned long fakt(int n)
{
if(n!=0)
return( n*fakt(n-1) );
else return 1;
}

main()
{
int n;
unsigned long f;
printf("Unesite n\n");
scanf("%d",&n);

87
88 Milena VujosevicJanicic

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

Primer 4.32.4 Fibonacijevi brojevi.


#include<stdio.h>
int fibr(int n)
{
if((n==1)||(n==2))
return 1;
else return(fibr(n-1)+fibr(n-2));
}

int main()
{
int Fn,n;
printf("Unesite n\n");
scanf("%d",&n);
Fn=fibr(n);
printf("F[%d]=%d",n,Fn);
putchar(\n);
return 0;
}

Primer 4.32.5 Iterativna i rekurzivna varijanta racunanja sume niza.


int suma_niza_iterativno(int a[], int n)
{
int suma = 0;
int i;
for (i = 0; i<n; i++)
suma+=a[i];
return suma;
}

int suma_niza(int a[], int n)


{
if (n == 1)
return a[0];
else
return suma_niza(a, n-1)+a[n-1];
}

Primer 4.32.6 Stepenovanje prirodnog broja


int stepenuj (int n, int k)
{
if (k == 0)
return 1;
else

88
4.33 Zivotni vek i oblast vazenja promenjivih, staticke promenljive89

return n*stepenuj(n, k-1);


}

4.33 Zivotni vek i oblast vazenja promenjivih,


staticke promenljive
Primer 4.33.1 Demonstracija zivotnog veka i oblasti vazenja promenjivih (scope).

#include <stdio.h>

/* Globalna promenjiva */
int a = 0;

/* Uvecava se globalna promenjiva a */


void increase()
{
a++;
printf("increase::a = %d\n", a);
}

/* Umanjuje se lokalna promenjiva a.


Globalna promenjiva zadrzava svoju vrednost. */
void decrease()
{
/* Ovo a je nezavisna promenjiva u odnosu na globalno a */
int a = 0;
a--;
printf("decrease::a = %d\n", a);

void nonstatic_var()
{
/* Nestaticke promenjive ne cuvaju vrednosti kroz pozive funkcije */
int s=0;
s++;
printf("nonstatic::s=%d\n",s);
}

void static_var()
{
/* Staticke promenjive cuvaju vrednosti kroz pozive funkcije.
Inicijalizacija se odvija samo u okviru prvog poziva. */
static int s=0;
s++;
printf("static::s=%d\n",s);
}

main()

89
90 Milena VujosevicJanicic

{
/* Promenjive lokalne za funkciju main */
int i;
int x = 3;

printf("main::x = %d\n", x);

for (i = 0; i<3; i++)


{
/* Promenjiva u okviru bloka je nezavisna od spoljne promenjive.
Ovde se koristi promenjiva x lokalna za blok petlje koja ima
vrednost 5, dok originalno x i dalje ima vrednost 3*/
int x = 5;
printf("for::x = %d\n", x);
}

/* U ovom bloku x ima vrednost 3 */


printf("main::x = %d\n", x);

increase();
decrease();

/* Globalna promenjiva a */
printf("main::a = %d\n", a);

/* Demonstracija nestatickih promenjivih */


for (i = 0; i<3; i++)
nonstatic_var();

/* Demonstracija statickih promenjivih */


for (i = 0; i<3; i++)
static_var();
}

Izlaz iz programa:
main::x = 3
for::x = 5
for::x = 5
for::x = 5
main::x = 3
increase::a = 1
decrease::a = -1
main::a = 1
nonstatic::s=1
nonstatic::s=1
nonstatic::s=1
static::s=1
static::s=2
static::s=3

90
4.34 Pokazivaci 91

Primer 4.33.2 Ilustracija statickih promenljivih.

#include <stdio.h>

void f()
{
static int a;
a++;
printf("%d\n",a);
}

main()
{
int i;
for (i=0; i<=10; i++)
f();
}

/* Izlaz iz programa 1 2 3 4 5 6 7 8 9 10 11*/

4.34 Pokazivaci
Pokazivac je promenljiva koja sadrzi adresu promenljive.

int x=1, y=1, z[10];


int *ip; /* ip je pokazivac na int,
odnosno *ip je tipa int*/

ip = &x; /* ip sada pokazuje na x */


y=*ip; /* y je sada 1 */
*ip = 0; /* x je sada 0 */

*ip+=10; /* x je sada 10*/


++*ip; /* x je sada 11*/
(*ip)++; /* x je sada 12,
zagrada neophodna zbog prioriteta
operatora*/

ip = &z[0]; /* ip sada pokazuje na z[0]*/

Primer 4.34.1 Ilustracija rada sa pokazivackim promenljivim.

#include <stdio.h>
main()
{
int x = 3;

/* Adresu promenjive x zapamticemo u novoj promeljivoj.


Nova promenljiva je tipa pokazivaca na int (int*) */
int* px;

91
92 Milena VujosevicJanicic

printf("Adresa promenljive x je : %p\n", &x);


printf("Vrednost promenljive x je : %d\n", x);

px = &x;
printf("Vrednost promenljive px je (tj. px) : %p\n", px);
printf("Vrednost promenljive na koju ukazuje px (tj. *px) je : %d\n", *px);

/* Menjamo vrednost promenljive na koju ukazuje px */


*px = 6;
printf("Vrednost promenljive na koju ukazuje px (tj. *px) je : %d\n", *px);

/* Posto px sadrzi adresu promenljive x, ona ukazuje na x tako da je


posredno promenjena i vrednost promenljive x */
printf("Vrednost promenljive x je : %d\n", x);

Izlaz (u konkretnom slucaju):


Adresa promenljive x je : 0012FF88
Vrednost promenljive x je : 3
Vrednost promenljive px je (tj. px) : 0012FF88
Vrednost promenljive na koju ukazuje px (tj. *px) je : 3
Vrednost promenljive na koju ukazuje px (tj. *px) je : 6
Vrednost promenljive x je : 6

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

void *pp;

Njemu moze da se dodeli da pokazuje na int, ili na char ili na proizvoljan tip ali
je to neophodno eksplicitno naglasiti svaki put kada zelimo da koristimo ono na
sta on pokazuje.

Primer 4.34.2 Upotreba pokazivaca na prazan tip.

#include<stdio.h>

main()
{
void *pp;
int x=2;
char c=a;

pp = &x;
*(int *)pp = 17; /* x postaje 17*/
printf("\n adresa od x je %p", &x);
printf("\n%d i %p",*(int*)pp,(int * )pp);

pp = &c;
printf("\n adresa od c je %p", &c);

92
4.35 Pokazivaci i argumenti funkcija 93

printf("\n%c i %p",*(char*)pp,(char * )pp);

/*
adresa od x je 0012FF78
17 i 0012FF78
adresa od c je 0012FF74
a i 0012FF74
*/

Posebna konstanta koja se koristi da se oznaci da pokazivac ne pokazuje na


neko mesto u memoriji je NULL.

4.35 Pokazivaci i argumenti funkcija


C prosle uje argumente u funkcije pomocu vrednosti. To znaci da sledeca
funkcija nece uraditi ono sto zelimo:

void swap (int x, int y) /* POGRESNO!!!!!!!!*/


{
int temp;
temp = x;
x=y;
y=temp;
}

Zbog prenosa parametara preko vrednosti swap ne moze da utice na argu-


mente a i b u funkciji koja je pozvala swap. Ova swap funkcija samo zamenjuje
kopije od a i b.
Da bi se dobio zeljeni efekat, potrebno je da se proslede pokazivaci:

/* Zameni *px i *py */


void swap (int *px, int *py)
{
int temp;
temp =*px;
*px = *py;
*py = temp;
}

a poziv funkcije swap izlgeda sada ovako

swap(&a, &b);

Primer 4.35.1 Demonstracija vise povratnih vrednosti funkcije koristeci prenos


preko pokazivaca.

/* Funkcija istovremeno vraca dve vrednosti - kolicnik i ostatak


dva data broja. Ovo se postize tako sto se funkciji predaju
vrednosti dva broja (x i y) koji se dele

93
94 Milena VujosevicJanicic

i adrese dve promenljive na koje ce se smestiti rezultati */

void div_and_mod(int x, int y, int* pdiv, int* pmod)


{
printf("Kolicnik postavljam na adresu : %p\n", pdiv);
printf("Ostatak postavljam na adresu : %p\n", pmod);
*pdiv = x / y;
*pmod = x % y;
}

main()
{
int div, mod;
printf("Adresa promenljive div je %p\n", &div);
printf("Adresa promenljive mod je %p\n", &mod);

/* Pozivamo funkciju tako sto joj saljemo


vrednosti dva broja (5 i 2)
i adrese promenljvih div i mod na koje
ce se postaviti rezultati */
div_and_mod(5, 2, &div, &mod);

printf("Vrednost promenljive div je %d\n", div);


printf("Vrednost promenljive mod je %d\n", mod);

Izlaz u konkretnom slucaju:


Adresa promenljive div je 0012FF88
Adresa promenljive mod je 0012FF84
Kolicnik postavljam na adresu : 0012FF88
Ostatak postavljam na adresu : 0012FF84
Vrednost promenljive div je 2
Vrednost promenljive mod je 1

4.36 Pokazivaci i nizovi (polja)


U C-u postoji cvrsta veza izme u pokazivaca i nizova. Bilo koja operacija koja
se moze ostvariti dopisivanjem indeksa niza moze se uraditi i sa pokazivacima.
Deklaracija
int a[10];
definise niz a velicine 10 koji predstavlja blok od 10 uzastopnih objekata
nazvanih a[0], a[1], ..., a[9]. Notacija a[i] odgovara i-tom elementu
niza.
Ako je pa pokazivac na ceo broj
int *pa;
tada iskaz pa = &a[0];
podesava da pa pokaze na nulti element niza a, odnosno pa sadrzi adresu od
a[0].

94
4.36 Pokazivaci i nizovi (polja) 95

Ako pa pokazuje na odre eni element polja, onda po definiciji pa+1 pokazuje
na sledeci element, pa+i pokazuje na i-ti element posle pa. Stoga, ako pa
pokazuje na a[0] tada
*(pa+1)
se odnosi na sadrzaj od a[1].
pa+i je adresa od a[i], a
*(pa+i)
je sadrzaj od a[i]. Dozvoljeno je upotrebljavati i sintaksu kao kod nizova:
*(pa+i) <==> pa[i]
Ovo sve vazi bez obzira na tip ili velicinu elemenata u polju a.
Iskaz pa=&a[0] se moze napisati kao pa=a jer je ime niza sinonim za
lokaciju pocetnog elementa.

Primer 4.36.1 Veza izme u pokazivaca i nizova.




#include <stdio.h>

void print_array(int* pa, int n);

main()
{
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int num_of_elements = sizeof(a)/sizeof(int);
int* pa;

/* Niz je isto sto i adresa prvog elementa */


printf("Niz a : %p\n", a);
printf("Adresa prvog elementa niza a (&a[0]) : %p\n", &a[0]);
/* Niz a : 0012FF5C
Adresa prvog elementa niza a (&a[0]) : 0012FF5C */

/* Moguce je dodeliti niz pokazivacu odgovarajuceg tipa */


pa = a;

printf("Pokazivac pa ukazuje na adresu : %p\n", pa);


/* Pokazivac pa ukazuje na adresu : 0012FF5C */

/* Nizu nije moguce dodeliti pokazivacku promenljivu


(nizove mozemo smatrati KONSTANTNIM pokazivacima na prvi element) */
/* a = pa; */

/* Pokazivace je dalje moguce indeksirati kao nizove */


printf("pa[0] = %d\n", pa[0]);
printf("pa[5] = %d\n", pa[5]);
/* pa[0] = 1
pa[5] = 6 */

/* Medjutim, sizeof(pa) je samo velicina pokazivaca, a ne niza */


printf("sizeof(a) = %d\n", sizeof(a));
printf("sizeof(pa) = %d\n", sizeof(pa));

95
96 Milena VujosevicJanicic

/* sizeof(a) = 40
sizeof(pa) = 4 */

/* Pozivamo funkciju za stampanje niza i saljemo joj niz */


print_array(a, num_of_elements);
/* 1 2 3 4 5 6 7 8 9 10 */

/* Pozivamo funkciju za stampanje niza


i saljemo joj pokazivac na pocetak niza */
print_array(pa, num_of_elements);
/* 1 2 3 4 5 6 7 8 9 10 */
}

/* Prosledjivanje niza u funkciju


void print_array(int pa[], int n);
je ekvivalentno prosledjivanju pokazivaca u funkciju
void print_array(int* pa, int n);
Izmedju ovih konstrukcija nema nikakve razlike!
*/
void print_array(int* pa, int n)
{
int i;
for (i = 0; i<n; i++)
printf("%d ", pa[i]);
putchar(\n);
}

Prilikom deklaracije treba praviti razliku izme u niza znakova i pokazivaca:


char poruka[]="danas je lep dan!";
char *pporuka = "danas je lep dan!";
poruka je niz znakova koji sadrzi dati tekst. Pojedine znake moguce je promeniti
ali se poruka uvek odnosi na isto mesto u memoriji.
pporuka je pokazivac, koji je inicijalizovan da pokazuje na konstantnu nisku, on
moze biti preusmeren da pokazuje na nesto drugo, ali rezultat nece biti definisan
ako pokusate da modifikujete sadrzaj niske (jer je to konstantna niska).
Ako deklarisemo
char *pporuka1 = "danas je lep dan!";
char *pporuka2 = "danas je lep dan!";
char *pporuka3 = "danas pada kisa";
tada ce pokazivaci pporuka1 i pporuka2 pokazivati na isto mesto u memoriji, a
pporuka3 na neko drugo mesto u memoriji.
Ako uporedimo (pporuka1==pporuka3) uporedice se vrednosti pokazivaca.
Ako uporedimo (pporuka1 < pporuka2) uporedice se vrednosti pokazivaca. Ako
dodelimo pporuka1=pporuka3 tada ce pporuka1 dobiti vrednost pokazivaca
pporuka3 i pokazivace na isto mesto u memoriji. Nece se izvrsiti kopiranje
sadrzaja memorije!!!

Primer 4.36.2 Vezba pokazivacke aritmetike.

96
4.36 Pokazivaci i nizovi (polja) 97

#include <stdio.h>

/* Funkcija pronalazi x u nizu niz date dimenzije,


bez koriscenja indeksiranja. Funkcija vraca pokazivac na
poziciju pronadjenog elementa. */

int* nadjiint(int* niz, int n, int x)


{
while (--n >= 0 && *niz!=x)
niz++;

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


}

main()
{
int a[]={1,2,3,4,5,6,7,8};
int* poz=nadjiint(a,sizeof(a)/sizeof(int),4);

if (poz!=NULL)
printf("Element pronadjen na poziciji %d\n",poz-a);
}
Primer 4.36.3
int strlen(char *s)
{
int n;
for(n=0; *s != \0; s++) n++;
return n;
}

Primer 4.36.4
/* Funkcija kopira string t u string s */
void copy(char* s, char* t)
{
while (*s++=*t++)
;
}

/* Ovo je bio skraceni zapis za sledeci kod


while(*t != \0)
{
*s=*t;
s++;
t++;
}
*s = \0;

*/

97
98 Milena VujosevicJanicic

Primer 4.36.5
/* Vrsi leksikografsko poredjenje dva stringa.
Vraca :
0 - ukoliko su stringovi jednaki
<0 - ukoliko je s leksikografski ispred t
>0 - ukoliko je s leksikografski iza t
*/
int string_compare1(char *s, char *t)
{
/* Petlja tece sve dok ne naidjemo
na prvi razliciti karakter */
for (; *s == *t; s++, t++)
if (*s == \0) /* Naisli smo na kraj
oba stringa, a nismo nasli razliku */
return 0;

/* *s i *t su prvi karakteri u kojima


se niske razlikuju.
Na osnovu njihovog odnosa,
odredjuje se odnos stringova */

return *s - *t;
}

/* Mozemo koristiti i sintaksu kao kod nizova */


int string_compare2(char *s, char *t) {
int i;
for (i = 0; s[i] == t[i]; i++)
if (s[i] == \0)
return 0;
return s[i] - t[i];
}

Primer 4.36.6 Pronalazi prvu poziciju karaktera c u stringu s, i vraca pokazivac


na nju, odnosno NULL ukoliko s ne sadrzi c.

char* string_char(char *s, char c)


{
int i;
for (; *s; s++)
if (*s == c)
return s;

/* Nije nadjeno */
return NULL;
}

Primer 4.36.7 Pronalazi poslednju poziciju karaktera c u stringu s, i vraca


pokazivac na nju, odnosno NULL ukoliko s ne sadrzi c.

98
4.36 Pokazivaci i nizovi (polja) 99

char* string_last_char(char *s, char c)


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

/* Krecemo od kraja i trazimo c unazad */


for (t--; t >= s; t--)
if (*t == c)
return t;

/* Nije nadjeno */
return NULL;
}

Primer 4.36.8
#include <stdio.h>

/* proverava da li se niska t nalazi unutar niske s*/


int sadrzi_string(char s[], char t[])
{
int i;
for (i = 0; s[i]; i++)
{
int j;
for (j=0, k=0; s[i+j]==t[j]; j++)
if (t[j+1]==\0)
return i;
}
return -1;
}

/* Verzija funkcije strstr implementirane bez


koriscenja indeksiranja */
/* proverava da li se niska t nalazi unutar niske s*/
char* sadrzi_string_pok(char* s, char* t)
{
while(*s)
{
char *i, *j;
for (i = s, j = t; *i == *j; i++,j++)
if (*(j+1)==\0)
return s;
s++;
}
return NULL;
}

/* Cita liniju sa stadnardnog ulaza i

99
100 Milena VujosevicJanicic

vraca njenu duzinu */


int getline(char* line, int max)
{
char *s=line;
int c;
while ( max-->0 && (c=getchar())!=\n && c!=EOF)
*s++ = c;

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

*s = \0;
return s - line;
}

main()
{
char rec[]="zdravo";
char linija[100];
while (getline(linija, 100))
if (sadrzi_string_pok(linija, rec))
printf("%s",linija);
}

4.37 Alokacija memorije


void* malloc(size_t n) vraca pokazivac na n bajtova neinicijalizovane mem-
orije ili NULL ukoliko zahtev ne moze da se ispuni.
Za njeno koriscenje neophodno je ukljuciti zaglavlje stdlib.h. Osloba anje
memorije - funkcija free.
Ne sme se koristiti nesto sto je vec oslobo eno, ne sme se dva puta osloba ati
ista memorija.

Primer 4.37.1
#include <stdio.h>
#include <stdlib.h>

main()
{
int n;
int i;
int *a;

printf("Unesi broj clanova niza : ");


scanf("%d", &n);

/* Kao da ste mogli da uradite

100
4.37 Alokacija memorije 101

int a[n];
*/
a = (int*)malloc(n*sizeof(int));

/* Kad god se vrsi alokacija memorije mora se proveriti da li je ona


uspesno izvrsena!!! */
if (a == NULL)
{
printf("Nema slobodne memorije\n");
exit(1);
}

/* Od ovog trenutka a koristim kao obican niz */


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

/* Stampamo niz u obrnutom redosledu */


for(i = n-1; i>=0; i--)
printf("%d",a[i]);

/* Oslobadjamo memoriju*/
free(a);
}
Primer 4.37.2 Demonstracija funkcije calloc - funkcija inicijalizuje sadrzaj
memorije na 0.
#include <stdio.h>
#include <stdlib.h>

main()
{
int *m, *c, i, n;

printf("Unesi broj clanova niza : ");


scanf("%d", &n);

/* Niz m NE MORA garantovano da ima sve nule */


m = malloc(n*sizeof(int));
if (m == NULL) {
printf("Greska prilikom alokacije memorije!\n");
exit(1);
}

/* Niz c MORA garantovano da ima sve nule */


c = calloc(n, sizeof(int));
if (c == NULL) {
printf("Greska prilikom alokacije memorije!\n");
free(m);
exit(1);
}

101
102 Milena VujosevicJanicic

for (i = 0; i<n; i++)


printf("m[%d] = %d\n", i, m[i]);

for (i = 0; i<n; i++)


printf("c[%d] = %d\n", i, c[i]);

free(m);
free(c);
}

4.38 Niz pokazivaca


Primer 4.38.1
#include <stdio.h>
#include <stdlib.h>
main()
{
/* Niz od tri elemenata tipa int*/
int nizi[3];

/* Niz od tri elemenata tipa int*, dakle


niz od tri pokazivaca na int*/
int* nizip[3];

/* Alociramo memoriju za prvi element niza*/


nizip[0] = (int*) malloc(sizeof(int));
if (nizip[0] == NULL)
{
printf("Nema slobodne memorije\n");
exit(1);
}
/* Upisujemo u prvi element niza broj 5*/
*nizip[0] = 5;
printf("%d", *nizip[0]);

/* Alociramo memoriju za drugi element niza.


Drugi element niza pokazuje na niz od dva
elementa*/
nizip[1] = (int*) malloc(2*sizeof(int));
if (nizip[1] == NULL) {
printf("Nema slobodne memorije\n");
free(nizip[0]);
exit(1);
}

/* Pristupamo prvom elementu na koji pokazuje


pokazivac nizip[1]*/
*(nizip[1]) = 1;

102
4.38 Niz pokazivaca 103

/* Pristupamo sledecem elementu u nizu na koji pokazuje


nizip[1].
*/
*(nizip[1] + 1) = 2;

printf("%d", nizip[1][1]);

/* Alociramo memoriju za treci element niza nizip. */


nizip[2] = (int*) malloc(sizeof(int));
if (nizip[2] == NULL) {
printf("Nema slobodne memorije\n");
free(nizip[0]);
free(nizip[1]);
exit(1);
}

*(nizip[2]) = 2;

printf("%d", *(nizip[2]));

free(nizip[0]);
free(nizip[1]);
free(nizip[2]);
}

Primer 4.38.2
#include <stdio.h>
#include <stdlib.h>
main()
{
/* Niz karaktera*/
char nizc[5];

/* Niz karaktera od cetiri elementa


(A, n, a, \0)*/
char nizcc[]="Ana";
printf("%s", nizcc);

/* Niz od tri pokazivaca. Prvi pokazuje na


nisku karaktera Kruska, drugi na nisku karaktera
Sljiva a treci na Ananas. */
char* nizcp[]={"Kruska", "Sljiva", "Ananas"};

printf("%s", nizcp[0]);
printf("%s", nizcp[1]);
printf("%s", nizcp[2]);
}

103
104 Milena VujosevicJanicic

4.39 Pokazivaci na funkcije


Primer 4.39.1 Program demonstrira upotrebu pokazivaca na funkcije.

#include <stdio.h>

int kvadrat(int n)
{
return n*n;
}

int kub(int n)
{
return n*n*n;
}

int parni_broj(int n)
{
return 2*n;
}

/* Funkcija izracunava sumu od 1 do n f(i),


gde je f data funkcija */
int sumiraj(int (*f) (int), int n)
{
int i, suma=0;
for (i=1; i<=n; i++)
suma += (*f)(i);

return suma;
}

main()
{
printf("Suma kvadrata brojeva od jedan do 3 je %d\n", sumiraj(kvadrat,3));
printf("Suma kubova brojeva od jedan do 3 je %d\n", sumiraj(kub,3));
printf("Suma prvih pet parnih brojeva je %d\n", sumiraj(parni_broj,5));
}
/*Izlaz:
Suma kvadrata brojeva od jedan do 3 je 14
Suma kubova brojeva od jedan do 3 je 36
Suma prvih pet parnih brojeva je 30
*/

4.40 Matrice
Primer 4.40.1 Staticka alokacija prostora za matricu.

#include <stdio.h>

104
4.40 Matrice 105

main()
{
int a[3][3] = {{0, 1, 2}, {10, 11, 12}, {20, 21, 22}};
int i, j;

/* Alternativni unos elemenata matrice


for(i=0; i<3; i++)
for(j=0; j<3; j++)
{
printf("a[%d][%d] = ", i, j);
scanf("%d", &a[i][j]);
}
*/

a[1][1] = a[0][0] + a[2][2];


/* a[1][1] = 0 + 22 = 22 */

printf("%d\n", a[1][1]); /* 22 */

/* Stampanje elemenata matrice*/


for(i=0; i<3; i++)
{
for(j=0; j<3; j++)
printf("%d\t", a[i][j]);
printf("\n");
}
}

Nama je potrebno da imamo vecu fleksibilnost, tj da se dimenzije matrice


mogu uneti kao parametri naseg programa. Zbog toga je neophodno koristiti
dinamicku alokaciju memorije.

Primer 4.40.2 Implementacija matrice preko niza.


#include <stdlib.h>
#include <stdio.h>

/* Makro pristupa clanu na poziciji i, j matrice koja ima


m vrsta i n kolona */
#define a(i,j) a[(i)*n+(j)]

main()
{
/* Dimenzije matrice */
int m, n;

/* Matrica */
int *a;

int i,j;

105
106 Milena VujosevicJanicic

/* Suma elemenata matrice */


int s=0;

/* Unos i alokacija */
printf("Unesi broj vrsta matrice : ");
scanf("%d",&m);

printf("Unesi broj kolona matrice : ");


scanf("%d",&n);

a=malloc(m*n*sizeof(int));
if (a == NULL) {
printf("Greska prilikom alokacije memorije!\n");
exit(1);
}

for (i=0; i<m; i++)


for (j=0; j<n; j++)
{
printf("Unesi element na poziciji (%d,%d) : ",i,j);
scanf("%d",&a(i,j));
}

/* Racunamo sumu elemenata matrice */


for (i=0; i<m; i++)
for (j=0; j<n; j++)
s+=a(i,j);

/* Ispis unete matrice */


printf("Uneli ste matricu : \n");
for (i=0; i<m; i++)
{ for (j=0; j<n; j++)
printf("%d ",a(i,j));
printf("\n");
}

printf("Suma elemenata matrice je %d\n", s);

/* Oslobadjamo memoriju */
free(a);
}
Primer 4.40.3 Program ilustruje rad sa kvadratnim matricama i relacijama.
Elementi i je u relaciji sa elementom j ako je m[i][j] = 1, a nisu u relaciji ako
je m[i][j] = 0.
#include <stdlib.h>
#include <stdio.h>

/* Dinamicka matrica je odredjena adresom


pocetka niza pokazivaca i dimenzijama tj.

106
4.40 Matrice 107

int** a;
int m,n;
*/

/* Alokacija kvadratne matrice nxn */


int** alociraj(int n)
{
int** m;
int i;
m=malloc(n*sizeof(int*));
if (m == NULL) {
printf("Greska prilikom alokacije memorije!\n");
exit(1);
}

for (i=0; i<n; i++)


{
m[i]=malloc(n*sizeof(int));
if (m[i] == NULL)
{
int k;
printf("Greska prilikom alokacije memorije!\n");
for(k=0;k<i;k++)
free(m[k]);
free(m);
exit(1);
}
}

return m;
}

/* Dealokacija matrice dimenzije nxn */


void obrisi(int** m, int n)
{
int i;
for (i=0; i<n; i++)
free(m[i]);
free(m);
}

/* Ispis matrice /
void ispisi_matricu(int** m, int n)
{
int i, j;
for (i=0; i<n; i++)
{
for (j=0; j<n; j++)
printf("%d ",m[i][j]);
printf("\n");

107
108 Milena VujosevicJanicic

}
}

/* Provera da li je relacija predstavljena matricom refleksivna */


int refleksivna(int** m, int n)
{
int i;
for (i=0; i<n; i++)
if (m[i][i]==0)
return 0;

return 1;
}

/* Provera da li je relacija predstavljena matricom simetricna */


int simetricna(int** m, int n)
{
int i,j;
for (i=0; i<n; i++)
for (j=i+1; j<n; j++)
if (m[i][j]!=m[j][i])
return 0;
return 1;
}

/* Provera da li je relacija predstavljena matricom tranzitivna*/


int tranzitivna(int** m, int n)
{
int i,j,k;

for (i=0; i<n; i++)


for (j=0; j<n; j++)
for (k=0; k<n; k++)
if ((m[i][j]==1)
&& (m[j][k]==1)
&& (m[i][k]!=1))
return 0;
return 1;
}

/* Pronalazi najmanju simetricnu relaciju koja sadrzi relaciju a */


void simetricno_zatvorenje(int** a, int n)
{
int i,j;
for (i=0; i<n; i++)
for (j=0; j<n; j++)
{
if (a[i][j]==1 && a[j][i]==0)
a[j][i]=1;
if (a[i][j]==0 && a[j][i]==1)

108
4.40 Matrice 109

a[i][j]=1;
}
}

main()
{
int **m;
int n;
int i,j;

printf("Unesi dimenziju matrice : ");


scanf("%d",&n);
m=alociraj(n);

for (i=0; i<n; i++)


for (j=0; j<n; j++)
scanf("%d",&m[i][j]);

printf("Uneli ste matricu : \n");

ispisi_matricu(m,n);

if (refleksivna(m,n))
printf("Relacija je refleksivna\n");
if (simetricna(m,n))
printf("Relacija je simetricna\n");
if (tranzitivna(m,n))
printf("Relacija je tranzitivna\n");

simetricno_zatvorenje(m,n);

ispisi_matricu(m,n);

obrisi(m,n);
}
Primer 4.40.4 Izracunati vrednost determinante matrice preko Laplasovog razvoja.
#include <stdio.h>
#include <stdlib.h>

/* Funkcija alocira matricu dimenzije nxn */


int** allocate(int n)
{
int **m;
int i;
m=(int**)malloc(n*sizeof(int*));
if (m == NULL) {
printf("Greska prilikom alokacije memorije!\n");
exit(1);
}

109
110 Milena VujosevicJanicic

for (i=0; i<n; i++)


{
m[i]=malloc(n*sizeof(int));
if (m[i] == NULL)
{
int k;
for(k=0;k<i;k++)
free(m[k]);
printf("Greska prilikom alokacije memorije!\n");
free(m);
exit(1);
}
}

return m;
}

/* Funkcija vrsi dealociranje date matrice dimenzije n */


void deallocate(int** m, int n)
{
int i;
for (i=0; i<n; i++)
free(m[i]);
free(m);
}

/* Funkcija ucitava datu alociranu matricu sa standardnog ulaza */


void ucitaj_matricu(int** matrica, int n)
{
int i,j;
for (i=0; i<n; i++)
for (j=0; j<n; j++)
scanf("%d",&matrica[i][j]);
}

/* Rekurzivna funkcija koja vrsi Laplasov razvoj */


int determinanta(int** matrica, int n)
{
int i;
int** podmatrica;
int det=0,znak;

/* Izlaz iz rekurzije je matrica 1x1 */


if (n==1) return matrica[0][0];

/* Podmatrica ce da sadrzi minore polazne matrice */


podmatrica=allocate(n-1);
znak=1;
for (i=0; i<n; i++)

110
4.41 Strukture 111

{
int vrsta,kolona;
for (kolona=0; kolona<i; kolona++)
for(vrsta=1; vrsta<n; vrsta++)
podmatrica[vrsta-1][kolona] = matrica[vrsta][kolona];
for (kolona=i+1; kolona<n; kolona++)
for(vrsta=1; vrsta<n; vrsta++)
podmatrica[vrsta-1][kolona-1] = matrica[vrsta][kolona];

det+= znak*matrica[0][i]*determinanta(podmatrica,n-1);
znak*=-1;
}
deallocate(podmatrica,n-1);
return det;
}

main()
{
int **matrica;
int n;

scanf("%d", &n);
matrica = allocate(n);
ucitaj_matricu(matrica, n);
printf("Determinanta je : %d\n",determinanta(matrica,n));
deallocate(matrica, n);
}

4.41 Strukture
Informacije kojima se opisuje realni svet retko se predstavljaju u elementarnoj
formi u vidu celih, realnih, znakovnih konstanti itd. Mnogo cesce imamo posla
sa slozenim objektima koji se sastoje od elemenata raznih tipova. Na primer
jednu osobu karakterisu ime, prezime, datum i mesto ro enja.
Struktura predstavlja skup podataka kojim se opisuju neka bitna svojstva
objekta. Komponente koje obrazuju strukturu nazivaju se elementi strukture.
Sintaksa strukture:

struct ime_strukture
{
tip ime_elementa1;
tip ime_elementa2;
...
};

Primer 4.41.1 Primer jednostavne strukture.

struct licnost
{
char ime[31];

111
112 Milena VujosevicJanicic

char adresa[41];
unsigned starost;
};

struct licnost osoba1, osoba2;

Deklaraciju osobe1 i osobe2 mogli smo da zapisemo i na sledeci nacin


struct licnost
{
char ime[31];
char adresa[41];
unsigned starost;
} osoba1, osoba2;
Ukoliko nemamo potrebu da se licnost koristi dalje u programu mogu se
napraviti dve osobe bez davanja imena strukturi:

struct
{
char ime[31];
char adresa[41];
unsigned starost;
} osoba1, osoba2;

Kada imamo promenljivu strukturnog tipa tada elementima date strukture


pristupamo uz pomoc operatora ..

Primer 4.41.2
osoba1.starost=20;
osoba2.starost=21;
...
if (osoba1.starost == osoba2.starost)
printf(" Osobe su iste starosti");

Dozvoljeno je praviti nizove struktura. Npr. niz od 20 elemenata koji sadrzi


licnosti:
struct licnost nizLicnosti[20];
Tada da bi procitali starost neke licnosti u nizu pisemo:
nizLicnosti[5].starost
Moze se definisati pokazivac na strukturu.
struct licnost *posoba;
Tada se pristupanje elementima strukture moze vrsiti upotrebom operatora .
na standardni nacin:
(*posoba).ime
(*posoba).adresa
(*posoba).starost

112
4.41 Strukture 113

ili koriscenjem specijalnog operatora 0 >0 na sledeci nacin:

posoba->ime
posoba->adresa
posoba->starost

Primer 4.41.3 Elementi strukture mogu da budu i druge strukture.

struct datum
{
unsigned dan;
unsigned mesec;
unsigned godina;
};

struct licnost
{
char ime[30];
struct datum datumrodjenja;
};

Sada se danu, mesecu i godini datuma rodjenja pristupa na sledeci nacin:

osoba.datumrodjenja.dan = 10;
osoba.datumrodjenja.mesec = 5;
osoba.datumrodjenja.godina = 1986;

4.41.1 Operator typedef


Operator typedef omogucava nam da definisemo nasa imena za neki od osnovih
ili izvedenih tipova. Na primer, mozemo da uradimo sledece:

typedef double RealanBroj;

Nakon ovoga mozemo u tekstu deklarista promenljivu x kao RealanBroj, ona ce


zapravo biti tipa double.

RealanBroj x; /* Umesto: double x;*/

Ili, ako zelimo da skratimo pisanje za neoznacene duge brojeve tj za unsigned


long int to mozemo da uradimo na sledeci nacin

typedef unsigned long int VelikiBroj;

Sada u kodu mozemo da koristimo VelikiBroj kao tip.


Operator typedef je narocito pogodan da bi se izbeglo ponavljalnje reci struct
pri deklarisanju strukturnih promenljivih.

typedef struct _licnost licnost;

Sada deklaracija moze da bude:

licnost osoba1, osoba2;


/* umesto: struct _licnost osoba1, osoba2; */

113
114 Milena VujosevicJanicic

Kao skracen zapis za

struct _tacka {
float x;
float y;
}

typedef struct _tacka tacka;

moze se koristiti:

typedef struct _tacka


{
float x;
float y;
} tacka;

Primer 4.41.4 Struktura artikal.


typedef struct _artikal
{
long bar_kod;
char ime[MAX_IME];
float pdv;
} artikal;

Primer 4.41.5 Program ilustruje osnovne geometrijske algoritme kao i rad sa


strukturama.

#include <math.h>
#include <stdio.h>

typedef struct _tacka


{
float x;
float y;
} tacka;

typedef struct _vektor


{
float x, y;
} vektor;

/* Koordinatni pocetak */
tacka kp={0.0,0.0};

/* Niz tacaka */
tacka niz[100];

/* Pokazivac na strukturu tacke */


tacka *pt;

114
4.41 Strukture 115

void IspisiTacku(tacka A)
{
printf("(%f,%f)\n",A.x,A.y);
}

void IspisiVektor(vektor v)
{
printf("(%f,%f)\n",v.x,v.y);
}

float duzina(vektor v)
{
return sqrt(v.x*v.x+v.y*v.y);
}

vektor NapraviVektor(tacka *pA, tacka *pB)


{
vektor ab;
ab.x=pB->x - pA->x;
ab.y=pB->y - pA->y;
return ab;
}

float rastojanje(tacka A, tacka B)


{
float dx=B.x - A.x;
float dy=B.y - A.y;
return sqrt(dx*dx+dy*dy);
}

/* Heronov obrazac */
float PovrsinaTrougla(tacka A, tacka B, tacka C)
{
float a=rastojanje(B,C);
float b=rastojanje(A,C);
float c=rastojanje(A,B);

float s=(a+b+c)/2.0;
return sqrt(s*(s-a)*(s-b)*(s-c));
}

float PovrsinaKonveksnogPoligona(tacka poligon[], int br_temena)


{
int i;
float povrsina=0.0;
for (i=1; i<br_temena-1; i++)
povrsina+=PovrsinaTrougla(poligon[0], poligon[i], poligon[i+1]);

return povrsina;
}

115
116 Milena VujosevicJanicic

float Obim(tacka poligon[], int br_temena)


{
int i;
float o=0;

for (i=0; i<br_temena-1; i++)


o+=rastojanje(poligon[i], poligon[i+1]);

o+=rastojanje(poligon[0], poligon[br_temena-1]);
return o;
}

main()
{
tacka poligon[]={{0.0,0.0},
{0.0,1.0},
{1.0,1.0},
{1.0,0.0}};
printf("Obim poligona je %f\n",Obim(poligon,4));
printf("Povrsina poligona je %f\n",
PovrsinaKonveksnogPoligona(poligon,4));
}
Primer 4.41.6 Program koji ucitava niz studenata i sortira ih po njihovim
ocenama.
#include <stdio.h>
#include <ctype.h>

#define MAX_IME 20

typedef struct _student


{
char ime[MAX_IME];
char prezime[MAX_IME];
int ocena;
} student;

/* Funkcija ucitava rec i vraca njenu duzinu ili


-1 ukoliko smo dosli do znaka EOF*/
int getword(char word[],int max)
{
int c, i=0;

while (isspace(c=getchar()))
;

while(!isspace(c) && c!=EOF && i<max-1)


{
word[i++]=c;

116
4.41 Strukture 117

c = getchar();
}

word[i]=\0;

if (c==EOF) return -1;


else return i;

/* Funkcija ucitava niz studenata, vraca duzinu niza koji ucita */


int UcitajPodatke(student studenti[], int max)
{
int i=0;
while(i<max && getword(studenti[i].ime, MAX_IME)>0)
{
if (getword(studenti[i].prezime, MAX_IME) < 0)
break;
scanf("%d",&studenti[i].ocena);
i++;
}
return i;
}

void IspisiPodatke(student studenti[], int br_studenata)


{
int i;
printf("IME PREZIME OCENA\n");
printf("--------------------------------------\n");
for (i=0; i<br_studenata; i++)
printf("%-20s %-20s %5d\n",studenti[i].
ime, studenti[i].prezime, studenti[i].ocena);
}

/* Sortiranje studenata po ocenama */


void SelectionSort(student studenti[], int br_studenata)
{
int i,j;
for (i=0; i<br_studenata-1; i++)
for (j=i; j<br_studenata; j++)
if (studenti[i].ocena<studenti[j].ocena)
{ student tmp=studenti[i];
studenti[i]=studenti[j];
studenti[j]=tmp;
}
}

main()
{
student studenti[100];

117
118 Milena VujosevicJanicic

int br_studenata = UcitajPodatke(studenti,100);

SelectionSort(studenti, br_studenata);

IspisiPodatke(studenti, br_studenata);

}
Primer 4.41.7 Dinamicki niz.
/* Program za svaku rec unetu sa standardnog
ulaza ispisuje broj pojavljivanja.
Verzija sa dinamickim nizom i realokacijom.
*/

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Rec je opisana imenom i brojem pojavljivanja */


typedef struct _rec
{ char ime[80];
int br_pojavljivanja;
} rec;

/* Dinamicki niz reci je opisan pokazivacem na


pocetak, tekucim brojem upisanih elemenata i
tekucim brojem alociranih elemenata */
rec* niz_reci;
int duzina=0;
int alocirano=0;

/* Realokacija se vrsi sa datim korakom */


#define KORAK 10

/* Funkcija ucitava rec i vraca njenu duzinu ili


-1 ukoliko smo dosli do znaka EOF*/
int getword(char word[],int max)
{
int c, i=0;

while (isspace(c=getchar()))
;

while(!isspace(c) && c!=EOF && i<max-1)


{
word[i++]=c;
c = getchar();
}

118
4.41 Strukture 119

word[i]=\0;

if (c==EOF) return -1;


else return i;
}

main()
{
char procitana_rec[80];
int i;

while (getword(procitana_rec,80)!=-1)
{
/* Proveravamo da li rec vec postoji u nizu */
for (i=0; i<duzina; i++)
/* Ako bismo uporedili procitana_rec == niz_reci[i].ime
bili bi uporedjeni pokazivaci a ne odgovarajuci sadrzaji!!!
Zato koristimo strcmp. */
if (strcmp(procitana_rec, niz_reci[i].ime)==0)
{
niz_reci[i].br_pojavljivanja++;
break;
}

/* Ukoliko rec ne postoji u nizu */


if (i==duzina)
{
rec nova_rec;
/* Ako bismo dodelili nova_rec.ime = procitana_rec
izvrsila bi se dodela pokazivaca a ne kopiranje niske
procitana_rec u nova_rec.ime. Zato koristimo strcpy!!! */
strcpy(nova_rec.ime,procitana_rec);
nova_rec.br_pojavljivanja=1;

/* Ukoliko je niz "kompletno popunjen" vrsimo realokaciju */


if (duzina==alocirano)
{
alocirano+=KORAK;

/* Sledeca linija zamenjuje blok koji sledi i moze se


koristiti alternativno. Blok je ostavljen samo da bi
demonstrirao korisnu tehniku */
/* niz_reci=realloc(niz_reci, (alocirano)*sizeof(rec)); */
{
/* alociramo novi niz, veci nego sto je bio prethodni */
rec* novi_niz=(rec *)malloc(alocirano*sizeof(rec));

if (novi_niz == NULL)
{
free(niz_reci);

119
120 Milena VujosevicJanicic

printf("Greska prilikom alokacije memorije");


exit(1);
}

/* Kopiramo elemente starog niza u novi */


for (i=0; i<duzina; i++)
novi_niz[i]=niz_reci[i];

/* Uklanjamo stari niz */


free(niz_reci);

/* Stari niz postaje novi */


niz_reci=novi_niz;
}
}
/* Upisujemo rec u niz */
niz_reci[duzina]=nova_rec;
duzina++;
}
}

/* Ispisujemo elemente niza */


for(i=0; i<duzina; i++)
printf("%s - %d\n",niz_reci[i].ime, niz_reci[i].br_pojavljivanja);

free(niz_reci);
}

4.42 qsort
Primer 4.42.1 Implementacija funkcije qsort.
#include <stdio.h>
#include <string.h>

void printarray(int v[], int left, int right)


{
int i;
for (i=left; i<=right; i++)
printf("%d ",v[i]);
putchar(\n);
}

void swap(int v[], int i, int j)


{
int tmp=v[i];
v[i]=v[j];
v[j]=tmp;
}

120
4.43 Sortiranje genericka funkcija 121

/* qsort: sortira v[left]...v[right] u rastucem poretku */


void qsort(int v[], int left, int right)
{
int i, last;

/* ne radi nista ako niz sadrzi */


/* manje od dva elementa */
if (left >= right)
return;
/* prebaci element particioniranja */
/* u v[left] */
swap(v, left, (left + right)/2);
last = left;

/* partition */
for (i = left + 1; i <= right; i++)
if (v[i] < v[left])
swap(v, ++last, i);

/* restore partition elem */


swap(v, left, last);

/* Sortiraj preostala dva dela niza */


qsort(v, left, last-1);
qsort(v, last+1, right);
}

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

printarray(array, 0, n-1);
qsort(array, 0, n-1);
printarray(array, 0, n-1);

4.43 Sortiranje genericka funkcija


Sortiranje niza celih brojeva (jedan od algoritama)
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(a[i]<a[j])
{
int pom=a[i];
a[i]=a[j];
a[j]=pom;
}

121
122 Milena VujosevicJanicic

Sortiranje iz programa mozemo da izdvojimo u funkciju:

void sort_int(int a[], int n)


{
int i, j;
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(a[i]<a[j])
{
int pom=a[i];
a[i]=a[j];
a[j]=pom;
}
}

Sortiranje niza realnih brojeva:

void sort_float(float a[], int n)


{
int i, j;
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(a[i]<a[j])
{
float pom=a[i];
a[i]=a[j];
a[j]=pom;
}
}

Razlike:

prvi argument funkcije;

pomocna promenljiva;

pore enje.

Sortiranje studenata po oceni ukoliko je data struktura student:

typedef struct _student {


char ime[MAX_IME];
char prezime[MAX_IME];
int ocena;
} student;

void sort_po_oceni(student a[], int n)


{
int i, j;
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(a[i].ocena < a[j].ocena)

122
4.43 Sortiranje genericka funkcija 123

{
student pom=a[i];
a[i]=a[j];
a[j]=pom;
}
}

Sortiranje studenta po prezimenu:


void sort_po_prezimenu(student a[], int n)
{
int i, j;
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(strcmp(a[i].prezime, a[j].prezime)<0)
{
student pom=a[i];
a[i]=a[j];
a[j]=pom;
}
}
Sortiranje studenta po imenu:
void sort_po_imenu(student a[], int n)
{
int i, j;
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(strcmp(a[i].ime, a[j].ime)<0)
{
student pom=a[i];
a[i]=a[j];
a[j]=pom;
}
}
Kako da napravimo jednu funkciju koja sortira studente bez obzira na kri-
terijum?
Prvo moramo da izdvojimo funkciju pore enja:
int poredi_po_oceni(student st1, student st2)
{
return st1.ocena - st2.ocena;
}

int poredi_po_prezimenu(student st1, student st2)


{
return strcmp(st1.prezime, s2.prezime);
}

int poredi_po_imenu(student st1, student st2)

123
124 Milena VujosevicJanicic

{
return strcmp(st1.ime, st2.ime);
}
Funkcija pore enja vraca 0 ukoliko su elementi jednaki, broj manji od nule
ukoliko je prvi manji od drugog i broj veci od nule ukolikoje prvi veci od drugog.

void sort_po_imenu(student a[], int n)


{
int i, j;
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
/*if(poredi_po_prezimenu(a[i], a[j])<0)*/
/*if(poredi_po_oceni(a[i], a[j])<0)*/
if(poredi_po_imenu(a[i], a[j])<0)
{
student pom=a[i];
a[i]=a[j];
a[j]=pom;
}
}

Sada mozemo da dodamo jos jedan argument funkciji sortiranja i tako da


dobijemo jednu funkciju umesto tri:
void sort_studente(student a[], int n, int (*f)(student, student))
{
int i, j;
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if((*f)(a[i], a[j])<0)
{
student pom=a[i];
a[i]=a[j];
a[j]=pom;
}
}
Sta dalje? Kako da dobijemo jednu funkciju sortiranja bez obzira na tip
elemenata niza?
Teba da resimo sledece stvari:
razmena mesta elemenata ne sme da zavisi od tipa elemenata koji se raz-
menjuju.
potpis funkcije pore enja ne sme da zavisi od tipa elemenata koji se porede
kako bi on bio jedinstven.
prvi argument funkcije ne sme da zavisi od tipa elemenata niza.
Da bi smo razmenili dva elementa potrebna nam je pomocna promenljiva
u kojoj privremeno cuvamo neku vrednost. Ako ne znamo tip elementa onda
ne mozemo da napravimo pomocnu promenljivu. Ali zato mozemo da koristeci

124
4.43 Sortiranje genericka funkcija 125

funkciju malloc odvojimo neko mesto u memoriji za smestanje elementa koji nam
u datoj situaciji treba. Koliko je to mesto? Nekada 4 bajta, npr za int, a nekada
dosta vece, npr za studenta. Kako funkcija sortiranja zna koliko mesta treba
da odvoji? Znace tako sto cemo joj tu velicinu proslediti kao argument. Sada,
dakle umesto pomocne promenljive, imamo blok u memoriji, a umesto naredbe
dodele koristicemo funkciju memcpy koja kopira deo memorije sa jednog mesta
na drugo mesto.
Dakle, razmenu cemo da radimo na sledeci nacin:

void* tmp = malloc(size);


if (tmp==NULL) {printf("Greska prilikom alokacije memorije!\n");exit(1);}
memcpy(tmp, adresa_itog, size);
memcpy(adresa_itog, adresa_jtog, size);
memcpy(adresa_jtog, tmp, size);
free(tmp);

Potpis funkcije pore enja ne sme da zavisi od tipa elemenata koji se porede.
To se moze postici koristeci pokazivac na tip void.
Na primer, pore enje dva cela broja:

int poredi_br(void* a, void* b)


{
int br_a = *(int*)a;
int br_b = *(int*)b;

return br_a-br_b;
}

Na primer, pore enje dva realna broja:

int poredi_br(void* a, void* b)


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

if (br_a > br_b) return 1;


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

Na primer, pore enje dva studenta po oceni

int poredi_br(void* a, void* b)


{
student student1 = *(studnet*)a;
student student2 = *(studnet*)b;

return student1.ocena-student2.ocena;
}

Sada funkcija pore enja ima uvek potpis

125
126 Milena VujosevicJanicic

int poredi(void* a, void* b)

i moze se kao parametar proslediti nasoj funkciji sortiranja.

Primer 4.43.1 /* Genericka funkcija sortiranja -


nezavisna od tipa elemenata niza
koji se sortira */
#include <stdlib.h>

void sort(void* a, int n, int size, int (*poredi)(void*, void*))


{
int i, j;
for (i = 0; i<n-1; i++)
for (j = i+1; j<n; j++)
{
void* adresa_itog = (char*)a+i*size;
void* adresa_jtog = (char*)a+j*size;

if (poredi(adresa_itog, adresa_jtog)<0)
{
void* tmp = malloc(size);
if (tmp==NULL) {
printf("Greska prilikom alokacije memorije!\n");
exit(1);
}
memcpy(tmp, adresa_itog, size);
memcpy(adresa_itog, adresa_jtog, size);
memcpy(adresa_jtog, tmp, size);
free(tmp);
}

}
}

int poredi_br(void* a, void* b) {


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

return br_a-br_b;
}

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


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

if (br_a > br_b) return 1;


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

126
4.44 qSort funkcija iz standardne biblioteke 127

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

sort(a, n, sizeof(int), poredi_br);

for (i = 0; i < n; i++)


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

sort(b, nf, sizeof(float), poredi_float);

for (i = 0; i < n; i++)


printf("%f ", b[i]);
putchar(\n);
}

4.44 qSort funkcija iz standardne biblioteke


Primer 4.44.1 qSort-Upotreba.
/* Ilustracija upotrebe funkcije qsort iz stdlib.h
Sortira se niz celih brojeva.
*/

#include <stdlib.h>
#include <stdio.h>

/* const znaci da ono na sta pokazuje a (odnosno b)


nece biti menjano u funkciji */
int poredi(const void* a, const void* b)
{
/* Skracen zapis za
int br_a = *(int*)a;
int br_b = *(int*)b;

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

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


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

127
128 Milena VujosevicJanicic

if (br_a > br_b) return 1;


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

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

int n=sizeof(niz)/sizeof(int);
qsort((void*)niz, n, sizeof(int), poredi);
for(i=0; i<n; i++)
printf("%d",niz[i]);

n=sizeof(nizf)/sizeof(float);
qsort((void*)nizf, n, sizeof(float), poredi_float);
for(i=0; i<n; i++)
printf("%f",nizf[i]);

}
Primer 4.44.2 Binarno pretrazivanje - koriscenje ugra ene bsearch funkcije.


/* Funkcija ilustruje koriscenje ugradjene funkcije bsearch */


#include <stdlib.h>

int poredi(const void* a, const void *b)


{
return *(int*)a-*(int*)b;
}

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

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

if (elem==NULL)
printf("Element nije pronadjen\n");
else
printf("Element postoji na poziciji %d\n",elem-niz);
}

128
4.45 Genericko sortiranje reci 129

4.45 Genericko sortiranje reci


Primer 4.45.1 Sortiranje reci. Ako se sortira niz stringova, onda svaki ele-
ment je sam po sebi pokazivac tipa char *, te funkcija pore enja tada prima


podatke tipa char ** koji se konvertuju u svoj tip i derefenciraju radi dobijanja
podataka tipa char *.

/* Ilustracija upotrebe funkcije qsort iz stdlib.h


Sortira se niz reci i to ili leksikografski
ili po duzini
*/

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int poredi(const void* a, const void* b)


{
char *s1 = *(char **)a;
char *s2 = *(char **) b;
return strcmp(s1, s2);

/* Prethodno je ekvivalentno sa:


return strcmp(*(char**)a,*(char**)b); */
}

int poredi_po_duzini(const void* a, const void* b)


{
char *s1 = *(char **) a;
char *s2 = *(char **) b;
return strlen(s1) - strlen(s2);
/* Prethodno je ekvivalentno sa:
return strlen(*(char**)b)-strlen(*(char**)a); */
}

main()
{
int i;
char* nizreci[]={"Jabuka","Kruska","Sljiva","Dinja","Lubenica"};

qsort((void*)nizreci, 5, sizeof(char*), poredi_po_duzini);

for (i=0; i<5; i++)


printf("%s\n",nizreci[i]);

qsort((void*)nizreci, 5, sizeof(char*), poredi);

for (i=0; i<5; i++)


printf("%s\n",nizreci[i]);

129
130 Milena VujosevicJanicic

}
Primer 4.45.2 Sa ulaza se unose reci. Program broji pojavljivanja svake od
kljucnih reci programskog jezika C. Na kraju se reci ispisuju opadajuce po broju
pojavljivanja.
#include <stdio.h>
#include <stdlib.h>

/* Svaka kljucna rec se odlikuje imenom i brojem pojavljivanja */


typedef struct _keyword
{
char* word;
int num;
} keyword;

/* Kreiramo niz struktura sortiranih leksikografski


po imenu kljucne reci, kako bismo ubrzali pronalazak reci */
keyword keywords[]={ {"break",0},
{"continue",0},
{"float",0},
{"for",0},
{"if",0},
{"return",0},
{"struct",0},
{"while",0}
};

/* Funkcija cita sledecu rec sa standardnog ulaza */


int getword(char word[], int lim)
{
int c, i=0;
while(!isalpha(c=getchar()) && c!=EOF)
;
if (c==EOF)
return -1;
do
{
word[i++]=c;
} while(--lim>0 && isalpha(c=getchar()));

word[i]=\0;
return i;
}

/* Funkcija leksikografskog poredjenja za bsearch */


int cmp(const void* a, const void* b) {
/* Funkcija strcmp prima kao argumente dva
pokazivaca na karaktere. Prvi je rec koju
trazimo u nizu, a drugi je element niza
sa kojim se vrsi poredjenje. Pokazivac

130
4.46 Argumenti komandne linije 131

b konvertujemo u pokazivac na strukturu


keyword a zatim posmatramo rec koja se tu
cuva */
return strcmp((char*)a, (*(keyword*)b).word); }

/* Funkcija numerickog poredjenja za qsort */


int numcmp(const void* a, const void* b)
{
return ((*(keyword*)b).num-(*(keyword*)a).num);
}

main()
{
char word[80];
int i;

/* Broj kljucnih reci */


int num_of_keywords=sizeof(keywords)/sizeof(keyword);

/* Citamo reci */
while (getword(word,80)!=-1)
{
/* Trazimo rec u spisku kljucnih reci binarnom pretragom */
keyword* k=(keyword*)bsearch((void*)word,
(void*)keywords,
num_of_keywords,
sizeof(keyword),
cmp);
/* Ukoliko je pronadjena uvecavamo broj pojavljivanja */
if (k!=NULL)
(*k).num++;
}

/* Sortiramo niz na osnovu broja pojavljivanja */


qsort((void*)keywords, num_of_keywords, sizeof(keyword), numcmp);

/* Vrsimo ispis */
for (i=0; i<num_of_keywords; i++)
printf("%s %d\n", keywords[i].word, keywords[i].num);
}

4.46 Argumenti komandne linije


Primer 4.46.1
/* Argumenti komandne linije programa */

/* Program pozivati sa npr.:


a.out
a.out prvi

131
132 Milena VujosevicJanicic

a.out prvi drugi treci


a.out -a -bc ime.txt
*/

#include <stdio.h>

/* Imena ovih promenljivih mogu biti proizvoljna.


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

main(int argc, char* argv[])


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

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


for (i = 0; i<argc; i++)
printf("argv[%d] = %s\n", i, argv[i]);
}

4.47 Datoteke
Primer 4.47.1 Program demonstrira otvaranje datoteka ("r" - read i "w" -
write mod) i osnovne tehnike rada sa datotekama.
/* U datoteku se upisuje prvih 10 prirodnih
brojeva, a zatim se iz iste datoteke
citaju brojevi dok se ne stigne do kraja i
ispisuju se na standardni izlaz */

#include <stdio.h>
#include <stdlib.h>

main()
{
int i;

/* Otvaramo datoteku sa imenom podaci.txt za pisanje */


FILE* f = fopen("podaci.txt", "w");

/* Ukoliko otvaranje nije uspelo, fopen vraca NULL.


U tom slucaju, prijavljujemo gresku i zavrsavamo program */
if (f == NULL)
{
printf("Greska prilikom otvaranja datoteke podaci.txt za pisanje\n");
exit(1);
}

132
4.47 Datoteke 133

/* Upisujemo u datoteku prvih 10 prirodnih brojeva


(svaki u posebnom redu) */
for (i = 0; i<10; i++)
fprintf(f, "%d\n", i);

/* Zatvaramo datoteku */
fclose(f);

/* Otvaramo datoteku sa imenom podaci.txt za citanje */


f = fopen("podaci.txt", "r");

/* Ukoliko otvaranje nije uspelo, fopen vraca NULL.


U tom slucaju, prijavljujemo gresku i zavrsavamo program */
if (f == NULL) {
printf("Greska prilikom otvaranja datoteke podaci.txt za citanje\n");
exit(1);
}

/* Citamo brojeve iz datoteke dok ne stignemo do kraja i ispisujemo ih


na standardni izlaz */
while(1) {
int br;
/* Pokusavamo da procitamo broj */
fscanf(f, "%d", &br);

/* Ukoliko smo dosli do kraja datoteke, prekidamo */


if (feof(f))
break;

/* Ispisujemo procitani broj */


printf("Procitano : %d\n", br);
}

/* Funkciju feof ne treba pozivati pre pokusaja citanja.


Sledeci kod moze dovesti do greske:
while (!feof(f))
fscanf(f,"%d",&br);
*/

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

Pokazivaci stdin, stdout i stderr su definisani u okviru stdio.h.


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

Primer 4.47.2 Program demonstrira a - append mod datoteka - nadovezi-


vanje.

133
134 Milena VujosevicJanicic

#include <stdio.h>

main()
{
FILE* datoteka;

/* Otvaramo datoteku za nadovezivanje


i proveravamo da li je doslo do greske */
if ( (datoteka=fopen("dat.txt","a"))==NULL)
{
fprintf(stderr,"Greska prilikom otvaranja dat.txt\n");
return 1;
}

/* Upisujemo sadrzaj u datoteku */


fprintf(datoteka,"Zdravo svima\n");

/* Zatvaramo datoteku */
fclose(datoteka);
}
Primer 4.47.3 Program ilustruje rad sa datotekama. Program kopira datoteku
cije se ime zadaje kao prvi argument komandne linije u datoteku cije se ime
zadaje kao drugi argument komandne linije. Uz svaku liniju se zapisuje i njen
redni broj.
#include <stdio.h>

#define MAX_LINE 256

/* Funkcija fgets definisana je u stdio.h

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

fgets ucitava najvise sledecih n-1 znakova


u polje niza karaktera s, zaustavljajuci se
ako naidje na novu liniju koju takodje
upisuje u polje. Na kraju upisuje \0.
Funkcija vraca s ili NULL ako dodje do kraja
datoteke ili se pojavi greska

Funkcija getline moze jednostavno da se


realizuje preko funkcije fgets.

int getline(char s[], int lim)


{
char* c = fgets(s, lim, stdin);
return c==NULL ? 0 : strlen(s);
}
*/

134
4.47 Datoteke 135

main(int argc, char* argv[])


{

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

if (argc != 3) {
fprintf(stderr,"Upotreba : %s ulazna_datoteka izlazna_datoteka\n",argv[0]);
return 1;
}

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


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

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


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

/* Prepisivanje karakter po karakter je moguce ostvariti preko:


int c;
while ((c=fgetc(in)) != EOF)
putc(c,out);
*/

line_num = 1;

/* Citamo liniju po liniju sa ulaza*/


while (fgets(line, MAX_LINE, in) != NULL)
{
/* Ispisujemo broj linije i sadrzaj linije na izlaz */
fprintf(out, "%d :\t", line_num++);
fputs(line, out);
}

/* Zatvaramo datoteke */
fclose(in);
fclose(out);
}
Primer 4.47.4 Prodavnica - ilustruje citanje niza struktura iz tektsualne da-
toteke.
/* Datoteka, cije se ime zadaje kao argument komandne linije
ili ako se ne zada onda se ime unosi sa standardnog
ulaza, sadrzi podatke o proizvodima koji se prodaju

135
136 Milena VujosevicJanicic

u okviru odredjene prodavnice. Svaki


proizvod se odlikuje sledecim podacima:
bar-kod - petocifreni pozitivan broj
ime - niska karaktera
cena - realan broj zaokruzen na dve decimale
pdv - stopa poreza - realan broj zaokruzen na dve decimale
Pretpostavljamo da su podaci u datoteci
korektno zadati.

Pretpostavljamo da se u prodavnici ne
prodaje vise od 1000 razlicitih artikala
Na standardni izlaz ispisati podatke o
svim proizvodima koji se prodaju u prodavnici.
Zadatak je moguce resiti i bez koriscenja nizova
(i takvo resenje je bolje). */

#include <stdio.h>

/* Maksimalna duzina imena proizvoda */


#define MAX_IME 30

/* Maksimalni broj artikala */


#define MAX_ARTIKALA 1000

/* Struktura za cuvanje podataka o jednom artiklu */


typedef struct _artikal {
int bar_kod;
char ime[MAX_IME];
float cena;
float pdv;
} artikal;

/* Niz struktura u kome se cuvaju podaci o artiklima */


artikal artikli[MAX_ARTIKALA];

/* Broj trenutno ucitanih artikala */


int br_artikala = 0;

/* Ucitava podatke o jednom artiklu iz date datoteke.


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

/* Ukoliko smo dosli do kraja datoteke prilikom pokusaja ucitavanja


prijavljujemo neuspeh */
if (feof(f))
return 0;

136
4.47 Datoteke 137

/* Prijavljujemo uspeh */
return 1;
}

/* Izracunava ukupnu cenu datog artikla */


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

/* Ispisuje podatke o svim artiklima */


void ispisi_artikle()
{
int i;
for (i = 0; i<br_artikala; i++)
printf("%-5d %-10s %.2f %.2f = %.2f\n",
artikli[i].bar_kod, artikli[i].ime,
artikli[i].cena, artikli[i].pdv,
cena(artikli[i]));
}

main(int argc, char* argv[])


{
FILE* f;

/* Ukoliko nije navedeno ime kao argument komandne linije, trazimo


od korisnika da ga unese */
if (argc<2) {
/* Ucitavamo ime datoteke */
char ime_datoteke[256];
printf("U kojoj datoteci se nalaze podaci o proizvodima: ");
scanf("%s", ime_datoteke);

/* Otvaramo datoteku i proveravamo da li smo uspeli */


if ( (f = fopen(ime_datoteke, "r")) == NULL)
{
printf("Greska prilikom otvaranja datoteke %s\n", ime_datoteke);
return 1;
}
}
/* Ime datoteke je prvi argument komandne linije */
else {
/* Otvaramo datoteku i proveravamo da li smo uspeli */
if ( (f = fopen(argv[1], "r")) == NULL)
{
printf("Greska : datoteka %s ne moze biti otvorena\n", argv[1]);
return 1;
}

137
138 Milena VujosevicJanicic

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

/* Ispisujemo podatke o svim artiklima */


ispisi_artikle();

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

4.48 Liste
4.48.1 Red

pocetak reda (brisanje get)


kraj reda (dodavanje add)

A B ... X NULL

novi element

pocetak reda
novi kraj reda

A B ... X Y NULL

pocetak reda nakon brisanja kraj reda

B ... X Y NULL

Slika 4.1: Red

Primer 4.48.1 Program formira listu brojeva i demonstrira osnovne elemente


rada sa listom.
#include <stdio.h>

138
4.48 Liste 139

#include <stdlib.h>

typedef struct elem {


int broj;
struct elem *sled;
} Elem;

/* Citanje brojeva i formiranje liste. Funkcija vraca pokazivac


na pocetak liste. */
Elem *citaj (void)
{
Elem *lista = NULL, *poslednji = NULL, *novi;
int broj;

printf("\n\nUnesite elemente liste - 0 za kraj\n");


scanf ("%d", &broj);

while (broj) {
/*Alocira se prostor za novi clan liste*/
novi =(Elem*)malloc (sizeof (Elem));
if (novi == NULL)
{
fprintf(stderr, "Greska prilikom alokacije memorije\n");
exit(1);
}

/* Postavljanje vrednosti */
novi->broj = broj;
novi->sled = NULL;

/* Ukoliko lista nije prazna novi element se postavlja iza


poslednjeg elemnta liste - na koji pokazuje poslednji */
if (poslednji != NULL)
poslednji->sled = novi;
/* Inace se postavlja da bude pocetak liste */
else
lista = novi;

/*Poslednji se postavlja da pokazuje na poslednji element liste */


/*Ekvivalentno je sa
poslednji = poslednji ->sledeci */
poslednji = novi;
/* Ucitavanje novog elementa liste 0 za kraj */
scanf ("%d", &broj);
}
/* Funkcija vraca pokazivac na pocetak liste */
return lista;
}

/* Ispisivanje liste*/

139
140 Milena VujosevicJanicic

void pisi (Elem *lista)


{
while (lista != NULL)
{
printf ("%d ", lista->broj),
lista = lista->sled;
}
putchar (\n);
}

/* Oslobadjanje memorije koju lista zauzima*/


void brisi (Elem* lista)
{
Elem *stari;
while (lista != NULL)
{
stari = lista;
lista = lista->sled;
free (stari);
}
}

/* Izbacivanje (brisanje) zadatog broja iz liste. Kako se


ovime pocetak liste moze izmeniti, vrednost pocetka liste
je povratna vrednost funkcije */
Elem* izbaci(Elem *lista, int k)
{
Elem *preth = NULL, *tekuci = lista, *zaizbacivanje;

while (tekuci != NULL)


/* Ukoliko tekuci pokazuje na clana
liste kojeg treba izbaciti */
if (tekuci->broj == k)
{
zaizbacivanje = tekuci;
tekuci = tekuci->sled;

if (preth != NULL )
preth->sled = tekuci;
/* Ovaj slucaj odnosi se na izbacivanje
elementa sa pocetka liste */
else lista = tekuci;

free (zaizbacivanje);
}
else
{
preth = tekuci;
tekuci = tekuci->sled;
}

140
4.48 Liste 141

return lista;
}

main ()
{
Elem *lista;
int k;

lista = citaj ();


printf ("Ucitani lista = ");
pisi (lista);

printf("Koji element liste zelite da izbacite?\n");


scanf ("%d", &k);
printf ("Izostavlja se = %d\n", k);
printf ("Novi lista = ");
pisi (lista = izbaci (lista, k));
printf ("\n");

printf("Lista mi vise nije potrebna, oslobadjam memoriju!\n");


brisi (lista);
}
Primer 4.48.2 Rad sa listama - celine izdvojene u funkcije.
#include <stdio.h>
#include <stdlib.h>

typedef struct cvor {


int br;
struct cvor* sl;
} CVOR;

/* Pomocna funkcija koja kreira cvor liste sa datim sadrzajem.


Funkcija kreira cvor i postavlja mu sadrzaj na dati broj.
Funkcija vraca pokazivac na kreirani cvor. */
CVOR* napravi_cvor(int br) {
CVOR* novi = (CVOR*)malloc(sizeof(CVOR));
if (novi == NULL)
{
fprintf(stderr, "Greska prilikom alokacije memorije\n");
exit(1);
}
novi->br = br;
novi->sl = NULL;
return novi;
}

/* --------------------------------------------- */
/* Ispisivanje liste: iterativna verzija */
void ispisi_listu_i(CVOR* l) {

141
142 Milena VujosevicJanicic

CVOR* t;
for (t = l; t != NULL; t=t->sl)
printf("%d ", t->br);
}

/* Ispisivanje liste: rekurzivna verzija */


void ispisi_listu_r(CVOR* l) {
if (l != NULL)
{
printf("%d ", l->br);
ispisi_listu_r(l->sl);
}
}

/* Ispisivanje liste unazad: rekurzivna verzija */


void ispisi_listu_unazad(CVOR* l) {
if (l != NULL)
{
ispisi_listu_unazad(l->sl);
printf("%d ", l->br);
}
}

/* --------------------------------------------- */
/* Oslobadjanje liste : iterativna verzija */
void oslobodi_listu_i(CVOR* l) {
while (l!=NULL)
{
CVOR* tmp = l->sl;
free(l);
l = tmp;
}
}

/* Oslobadjanje liste : rekurzivna verzija */


void oslobodi_listu_r(CVOR* l) {
if (l != NULL)
{
oslobodi_listu_r(l->sl);
/* Prvo se oslobadja poslednji element liste */
free(l);
}
}

/* --------------------------------------------- */
/* Ubacuje dati broj na pocetak date liste.
Funkcija pozivaocu eksplicitno vraca pocetak
rezultujuce liste.*/
CVOR* ubaci_na_pocetak(CVOR* l, int br) {
CVOR* novi = napravi_cvor(br);

142
4.48 Liste 143

novi->sl = l;
return novi;
}

/* Funkcija vraca pocetak rezultujuce liste, a ubacuje


cvor na kraj bez pamcenja pokazivaca na kraj */
CVOR* ubaci_na_kraj(CVOR* l, int br) {
CVOR* novi = napravi_cvor(br);

if (l == NULL)
return novi;
else
{
CVOR* t;
/* Prodjemo do kraja liste */
for (t = l; t->sl!=NULL; t=t->sl)
;
t->sl = novi;

/* Pocetak se nije promenio */


return l;
}
}

/* Rekurzivna varijanta prethodne funkcije.


I ova funkcija vraca pokazivac na pocetak
rezultujuce liste */
CVOR* ubaci_na_kraj_rekurzivno(CVOR* l, int br) {
if (l == NULL)
{
CVOR* novi = napravi_cvor(br);
return novi;
}

l->sl = ubaci_na_kraj_rekurzivno(l->sl, br);


return l;
}

/* --------------------------------------------- */
/* Kljucna ideja u realizaciji ove funkcije je
pronalazenje poslednjeg elementa liste ciji
je kljuc manji od datog elementa br.
*/
CVOR* ubaci_sortirano(CVOR* pl, int br) {
CVOR* novi = napravi_cvor(br);

/* U sledeca dva slucaja ne postoji cvor


ciji je kljuc manji od datog broja (br)
- Prvi je slucaj prazne liste
- Drugi je slucaj kada je br manji od prvog elementa

143
144 Milena VujosevicJanicic

U oba slucaja ubacujemo na pocetak liste.


*/
if (pl == NULL || br < pl->br)
{
novi->sl = pl;
pl = novi;
}
else
{
/* Krecemo od pocetka i idemo dalje sve dok t nije poslednji
manji element liste ili eventualno bas poslednji */
CVOR* t;
for(t = pl; t->sl!=NULL && t->sl->br < br; t=t->sl)
;
novi->sl = t->sl;
t->sl = novi;
}

return pl;
}

main() {
CVOR* l = NULL;
CVOR* s = NULL;

int i;
for (i = 0; i<5; i++)
l = ubaci_na_kraj(l, i);
for (; i<10; i++)
l = ubaci_na_kraj_rekurzivno(l, i);

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


l = ubaci_na_pocetak(l, i);

ispisi_listu_i(l);
putchar(\n);

ispisi_listu_r(l);
putchar(\n);

ispisi_listu_unazad(l);
putchar(\n);

oslobodi_listu_i(l);

s = ubaci_sortirano(s, 5);
s = ubaci_sortirano(s, 8);
s = ubaci_sortirano(s, 7);
s = ubaci_sortirano(s, 6);

144
4.48 Liste 145

s = ubaci_sortirano(s, 4);

ispisi_listu_r(s);
putchar(\n);

oslobodi_listu_r(s);
}

4.48.2 Kruzna lista

pocetak ciklicne liste

A B C ... Z

Slika 4.2: Kruzna lista

Primer 4.48.3 (februar 2006.) Grupa od n plesaca (na cijim kostimima su


u smeru kazaljke na satu redom brojevi od 1 do n) izvodi svoju plesnu tacku
tako sto formiraju krug iz kog najpre izlazi k-ti plesac (odbrojava se pocev od
plesaca oznacenog brojem 1 u smeru kretanja kazaljke na satu). Preostali plesaci
obrazuju manji krug iz kog opet izlazi k-ti plesac (odbrojava se pocev od sledeceg
suseda prethodno izbacenog, opet u smeru kazaljke na satu). Izlasci iz kruga se
nastavljaju sve dok svi plesaci ne budu iskljuceni. Celi brojevi n, k (k < n) se
ucitavaju sa standardnog ulaza. Napisati program koji ce na standardni izlaz
ispisati redne brojeve plesaca u redosledu napustanja kruga.
PRIMER: za n = 5, k = 3 redosled izlaska je 3 1 5 2 4.

4.48.3 Stek
Primer 4.48.4 Program proverava da li su zagrade ( i ) dobro uparene.

#include <stdio.h>
#include <stdlib.h>

main()
{
int c;
int br_otv = 0;
while((c=getchar()) != EOF)
{
switch(c)

145
146 Milena VujosevicJanicic

{
case (:
br_otv++;
break;
case ):
br_otv--;
if (br_otv<0)
{
printf("Visak zatvorenih zagrada\n");
exit(1);
}
}
}

if (br_otv == 0)
printf("Zagrade su u redu\n");
else
printf("Visak otvorenih zagrada\n");
}

Primer 4.48.5 Program proverava da li su zagrade (, [, {, }, ] i ) dobro uparene


- staticka implementacija steka.

#include <stdio.h>
#include <stdlib.h>
#define MAX_ZAGRADA 100

int odgovarajuce(char z1, char z2) {


return (z1 == ( && z2 == )) ||
(z1 == { && z2 == }) ||
(z1 == [ && z2 == ]);
}

main()
{
int c;
char otv_zagrade[MAX_ZAGRADA];
int br_otv = 0;

while((c=getchar()) != EOF)
{
switch(c)
{
case (:
case {:
case [:
{
otv_zagrade[br_otv] = c;
br_otv++;
break;

146
4.48 Liste 147

}
case ]:
case }:
case ):
if (br_otv>0 && odgovarajuce(otv_zagrade[br_otv-1], c))
{
br_otv--;
}
else
{
printf("Visak zatvorenih zagrada: %c u liniji %d\n", c, br_linija);
exit(1);
}
}
}

if (br_otv == 0)
printf("Zagrade su u redu\n");
else
printf("Visak otvorenih zagrada\n");
}

vrh steka (i dodavanje i brisanje push i pop)

X Y ... A NULL

novi element

novi vrh steka

Y X V ... A NULL

vrh steka nakon brisanja

X V ... A NULL

Slika 4.3: Stek

147
148 Milena VujosevicJanicic

Primer 4.48.6 Program ilustruje proveru validnosti HTML datoteke - prover-


ava se da li su etikete dobro uparene pri cemu se stek implementira preko liste.

#include <stdio.h>
#include <string.h>
#include <ctype.h>

/* Maksimalna duzina etikete */


#define MAX_TAG 100

#define OTVORENA 1
#define ZATVORENA 2
#define GRESKA 0

/* Funkcija ucitava sledecu etiketu i smesta njen naziv u niz s


duzine max. Vraca OTVORENA za otvorenu etiketu, ZATVORENA za
zatvorenu etiketu, odnosno GRESKA inace */
int gettag(char s[], int max) {
int c, i;
int zatvorenost=OTVORENA;

/* Preskacemo sve do znaka < */


while ((c=getchar())!=EOF && c!=<)
;
/* Nismo naisli na etiketu */
if (c==EOF)
return GRESKA;

/* Proveravamo da li je etiketa zatvorena */


if ((c=getchar())==/)
zatvorenost=ZATVORENA;
else
/* Funkcija ungetc vraca karakter c na standardni ulaz */
ungetc(c,stdin);

/* Citamo etiketu dok nailaze slova i smestamo ih u nisku */


for (i=0; isalpha(c=getchar()) && i<max-1; s[i++] = c)
;
/* Vracamo poslednji karakter na ulaz jer je to bio neki karakter
koji nije slovo*/
ungetc(c,stdin);

s[i]=\0;

/* Preskacemo atribute do znaka > */


while ((c=getchar())!=EOF && c!=>)
;

/* Greska ukoliko nismo naisli na > */


return c==> ? zatvorenost : GRESKA;

148
4.48 Liste 149

/* Stek ce biti implementiran koriscenjem liste */


typedef struct
cvor {
char tag[MAX_TAG];
struct cvor* sledeci;
} CVOR;

CVOR* stek = NULL;

main()
{
char tag[MAX_TAG];
int zatvorenost;
while ((zatvorenost = gettag(tag, MAX_TAG))>0)
{
if (zatvorenost==OTVORENA)
{
/* Svaku otvorenu etiketu stavljamo na stek */

CVOR* tmp = (CVOR*)malloc(sizeof(CVOR));


if (tmp == NULL)
{
printf("Greska prilikom alokacije memorije!\n");
return 1;
}
strcpy(tmp->tag, tag);
tmp->sledeci = stek;
stek = tmp;

printf("Postavio <%s> na stek\n", stek->tag);


}

else
{
/* Za zatvorene etikete proveravamo da li je stek prazan
odnosno da li se na vrhu steka nalazi odgovarajuca
otvorena etiketa */
if (stek != NULL && strcmp(stek->tag, tag) == 0)
{
/* Uklanjamo etiketu sa steka */
CVOR* tmp = stek->sledeci;
free(stek);
stek = tmp;
}
else
{
/* Prijavljujemo gresku */
printf("Neodgovarajuci tag : </%s>!\n",tag);

149
150 Milena VujosevicJanicic

exit(1);
}
}
}

if (stek == NULL) printf("Datoteka je ispravna\n ");


else
{
printf("Visak otvorenih etiketa!\n");
/* Oslobadjamo memoriju koja je ostala
zarobljena na steku. */
while(stek!=NULL)
{
CVOR* tmp = stek->sledeci;
free(stek);
stek = tmp;
}
}
}

4.48.4 Dvostruko povezane liste

pocetak dvostruko povezane liste kraj liste

...
NULL A B C ... Z NULL

Slika 4.4: Dvostruko povezana lista

Primer 4.48.7 Napisati funkciju koja omogucava umetanje cvora u dvostruko


povezanu kruznu listu kao i izbacivanje cora iz dvostruko povezane kruzne liste.
Omoguciti i stampanje podataka koje cuva lista.

/* Program implementira deciju razbrajalicu eci-peci-pec i sluzi


da ilustruje rad sa dvostruko povezanim kruznim listama */

#include <stdlib.h>
#include <stdio.h>

/* Dvostruko povezana lista */


typedef struct _cvor {
int broj;

150
4.48 Liste 151

struct _cvor* prethodni, *sledeci;


} cvor;

/* Umetanje u dvostruko povezanu listu */


cvor* ubaci(int br, cvor* lista) {
cvor* novi=(cvor*)malloc(sizeof(cvor));
if (novi==NULL)
{ printf("Greska prilikom alokacije memorije \n");
exit(1);
}
novi->broj=br;

if (lista==NULL)
{ novi->sledeci=novi;
novi->prethodni=novi;
return novi;
}
else
{ novi->prethodni=lista;
novi->sledeci=lista->sledeci;
lista->sledeci->prethodni=novi;
lista->sledeci=novi;
return novi;
}
}

/* Ispis liste */
void ispisi(cvor* lista)
{
if (lista!=NULL)
{ cvor* tekuci=lista;
do
{ printf("%d\n",tekuci->broj);
tekuci=tekuci->sledeci;
} while (tekuci!=lista);
}
}

/* Izbacivanje datog cvora iz liste, funkcija


vraca pokazivac na novonastalu listu */
cvor* izbaci(cvor* lista) {
if (lista!=NULL)
{ cvor* sledeci=lista->sledeci;
if (lista==lista->sledeci)
{ printf("Pobednik %d\n",lista->broj);
free(lista);
return NULL;
}

printf("Ispada %d\n",lista->broj);

151
152 Milena VujosevicJanicic

lista->sledeci->prethodni=lista->prethodni;
lista->prethodni->sledeci=lista->sledeci;
free(lista);
return sledeci;
}
else return NULL;
}

main() {
/* Umecemo petoro dece u listu */
cvor* lista = NULL;
lista=ubaci(1,lista);
lista=ubaci(2,lista);
lista=ubaci(3,lista);
lista=ubaci(4,lista);
lista=ubaci(5,lista);
lista=lista->sledeci;

/*Proverimo da smo dobro formirali listu*/


ispisi(lista);

int smer = 0;
/* Dok ima dece u listi */
while(lista!=NULL)
{ int i;

/* brojimo 13 slogova u krug i u svakom brojanju


menjamo smer obilaska*/
for (i=1; i<=13; i++)
lista = 1-smer ? lista->sledeci : lista->prethodni;

lista=izbaci(lista);
smer = smer ? 0 : 1;
}
}
Primer 4.48.8 Program ispisuje broj pojavljivanja za svaku od reci koja se
pojavila u tekstu unetom sa standardnog ulaza. Verzija sa (sortiranom) listom.
#include <stdlib.h>
#include <stdio.h>

/* Definicija cvora liste */


typedef struct _cvor
{
char ime[80];
int br_pojavljivanja;
struct _cvor* sledeci;
} cvor;

152
4.48 Liste 153

/* Funkcija ispisuje listu rekurzivno, pocevsi od poslednjeg


elementa */
void ispisi_listu(cvor* pocetak)
{
if (pocetak!=NULL)
{
ispisi_listu(pocetak->sledeci);
printf("%s %d\n",pocetak->ime,pocetak->br_pojavljivanja);
}
}

/* Funkcija koja brise listu */


void obrisi_listu(cvor* pocetak)
{
if (pocetak!=NULL)
{
obrisi_listu(pocetak->sledeci);
free(pocetak);
}
}

/* Funkcija ubacuje rekurzivno datu rec u listu koja je


leksikografski sortirana, na odgovarajuce mesto i vraca
pokazivac na novi pocetak liste */
cvor* ubaci_sortirano(cvor* pocetak, char* rec)
{
int cmp;
/* Ukoliko je lista prazna ubacujemo na pocetak liste*/
if (pocetak==NULL)
{ pocetak=(cvor*)malloc(sizeof(cvor));
if (pocetak == NULL)
{
printf("Greska prilikom alokacije memorije!\n");
exit(1);
}
strcpy(pocetak->ime,rec);
pocetak->br_pojavljivanja=1;
return pocetak;
}
/* Ukoliko lista nije prazna poredimo rec sa elementom u glavi */
cmp=strcmp(pocetak->ime,rec);
/* Ukoliko je rec pronadjena samo uvecavamo njen broj
pojavljivanja */
if (cmp==0)
{ pocetak->br_pojavljivanja++;
return pocetak;
}
/* Ukoliko je rec koju ubacujemo veca od tekuce reci, ubacujemo je
rekurzivno u rep */
else if (cmp>0)

153
154 Milena VujosevicJanicic

{ pocetak->sledeci=ubaci_sortirano(pocetak->sledeci,rec);
return pocetak;
}
/* Ukoliko je rec koju ubacujemo manja od tekuce reci, gradimo novi
cvor i ubacujemo ga ispred pocetka */
else
{ cvor* novi=malloc(sizeof(cvor));
if (novi == NULL)
{
printf("Greska prilikom alokacije memorije!\n");
exit(1);
}
strcpy(novi->ime,rec);
novi->br_pojavljivanja=1;
novi->sledeci=pocetak;
return novi;
}
}

/* Pomocna funkcija koja cita rec sa standardnog ulaza i vraca


njenu duzinu, odnosno -1 ukoliko se naidje na EOF */
int getword(char word[], int lim) {
int c, i=0;
while (!isalpha(c=getchar()) && c!=EOF)
;

if (c==EOF)
return -1;
do
{ word[i++]=c;
}while (i<lim-1 && isalpha(c=getchar()));

word[i]=\0;
return i;
}

/* Funkcija koja rekurzivno pronalazi datu rec u datoj listi.


Funkcija vraca pokazivac na cvor u kome je nadjena rec, ili
NULL ukoliko rec nije nadjena */
cvor* nadji_rec(cvor* lista, char rec[])
{
if (lista==NULL)
return NULL;
if (strcmp(lista->ime,rec)==0)
return lista;

return nadji_rec(lista->sledeci,rec);
}

154
4.49 Drvo 155

main()
{
cvor* lista=NULL;
char procitana_rec[80];
while(getword(procitana_rec,80)!=-1)
{ cvor* pronadjen=nadji_rec(lista,procitana_rec);
if (pronadjen!=NULL)
pronadjen->br_pojavljivanja++;
else
lista=ubaci_sortirano(lista,procitana_rec);
}
ispisi_listu(lista);
obrisi_listu(lista);
}

4.49 Drvo

NULL NULL

NULL NULL NULL

NULL NULL

Slika 4.5: Stablo

155
156 Milena VujosevicJanicic

Primer 4.49.1 Binarno pretrazivacko drvo - drvo sadrzi cele brojeve.

17, 12, 21, 15, 5, 14


17

12 21

NULL NULL

5 15

NULL NULL NULL

inf ix : 5, 12, 14, 15, 17, 21


14 pref ix : 17, 12, 5, 15, 14, 21

postf ix : 5, 14, 15, 12, 21, 17


NULL NULL

Slika 4.6: Ure eno stablo

/* Program demonstrira rad sa binarnim pretrazivackim drvetima.


Drveta sadrze cele brojeve i sortirana su po velicini.
Za svaki cvor, levo podstabla sadrzi manje elemente, dok desno
podstablo sadrzi vece.
*/

#include <stdlib.h>
#include <stdio.h>

typedef struct _cvor


{
int broj;
struct _cvor *l, *d;
} cvor;

156
4.49 Drvo 157

cvor* napravi_cvor(int b) {
cvor* novi = (cvor*)malloc(sizeof(cvor));
if (novi == NULL)
{
fprintf(stderr, "Greska prilikom
alokacije memorije");
exit(1);
}
novi->broj = b;
novi->l = NULL;
novi->d = NULL;
return novi;
}

/* Funkcija umece broj br u drvo ciji je koren dat preko


pokazivaca drvo. Funkcija vraca pokazivac na koren
novog drveta */
cvor* ubaci_u_drvo(cvor* drvo, int b)
{
if (drvo == NULL)
return napravi_cvor(b);

if (b < drvo->broj)
drvo->l = ubaci_u_drvo(drvo->l, b);
else
drvo->d = ubaci_u_drvo(drvo->d, b);

return drvo;
}

/* Funkcija proverava da li dati broj postoji u drvetu */


int pronadji(cvor* drvo, int b)
{
if (drvo == NULL)
return 0;

if (drvo->broj == b)
return 1;

if (b < drvo->broj)
return pronadji(drvo->l, b);
else
return pronadji(drvo->d, b);
}

/* Funkcija ispisuje sve cvorove drveta u infiksnom redosledu */


void ispisi_drvo(cvor* drvo) {
if (drvo != NULL)
{
ispisi_drvo(drvo->l);

157
158 Milena VujosevicJanicic

printf("%d ", drvo->broj);


ispisi_drvo(drvo->d);
}
}

void obrisi_drvo(cvor* drvo) {


if (drvo != NULL)
{
obrisi_drvo(drvo->l);
obrisi_drvo(drvo->d);
free(drvo);
}
}

/* Funkcija sumira sve vrednosti binarnog stabla */


int suma_cvorova(cvor* drvo)
{
if (drvo == NULL)
return 0;
return suma_cvorova(drvo->l) +
drvo->broj +
suma_cvorova(drvo->d);
}

int broj_cvorova(cvor* drvo)


{
if (drvo == NULL)
return 0;
return broj_cvorova(drvo->l) +
1 +
broj_cvorova(drvo->d);
}

int broj_listova(cvor* drvo)


{
if (drvo == NULL)
return 0;
if (drvo->l == NULL && drvo->d == NULL)
return 1;
return broj_listova(drvo->l) +
broj_listova(drvo->d);
}

int suma_listova(cvor* drvo)


{
if (drvo == NULL)
return 0;

if (drvo->l == NULL && drvo->d == NULL)

158
4.49 Drvo 159

return drvo->broj;

return suma_listova(drvo->l) +
suma_listova(drvo->d);
}

void ispisi_listove(cvor* drvo)


{
if (drvo == NULL)
return;

ispisi_listove(drvo->l);

if (drvo->l == NULL && drvo->d == NULL)


printf("%d ", drvo->broj);

ispisi_listove(drvo->d);
}

/* Funkcija pronalazi maksimalnu vrednost u drvetu


Koristi se cinjenica da je ova vrednost
smestena u najdesnjem listu */
int max_vrednost(cvor* drvo)
{
if (drvo==NULL)
return 0;

if (drvo->d==NULL)
return drvo->broj;

return max_vrednost(drvo->d);
}

/* Iterativna funkcija za pronalazenje maksimalne vrednosti. */


int max_vrednost_nerekurzivno(cvor* drvo)
{
if (drvo==NULL)
return 0;
else
{
cvor* tekuci;
for (tekuci=drvo; tekuci->d!=NULL; tekuci=tekuci->d)
;
return tekuci->broj;
}
}

/* Funkcija racuna "dubinu" binarnog stabla */


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

159
160 Milena VujosevicJanicic

int dubina(cvor* drvo)


{
if (drvo==NULL)
return 0;
else
{ int dl=dubina(drvo->l);
int dd=dubina(drvo->d);
return 1+max(dl,dd);
}
}

main()
{
cvor* drvo = NULL;
drvo = ubaci_u_drvo(drvo, 1);
drvo = ubaci_u_drvo(drvo, 8);
drvo = ubaci_u_drvo(drvo, 5);
drvo = ubaci_u_drvo(drvo, 3);
drvo = ubaci_u_drvo(drvo, 7);
drvo = ubaci_u_drvo(drvo, 6);
drvo = ubaci_u_drvo(drvo, 9);

if (pronadji(drvo, 3))
printf("Pronadjeno 3\n");
if (pronadji(drvo, 2))
printf("Pronadjeno 2\n");
if (pronadji(drvo, 7))
printf("Pronadjeno 7\n");

ispisi_drvo(drvo);

putchar(\n);
printf("Suma cvorova : %d\n", suma_cvorova(drvo));
printf("Broj cvorova : %d\n", broj_cvorova(drvo));
printf("Broj listova : %d\n", broj_listova(drvo));
printf("Suma listova : %d\n", suma_listova(drvo));
printf("Dubina drveta : %d\n", dubina(drvo));
printf("Maximalna vrednost : %d\n", max_vrednost(drvo));

ispisi_listove(drvo);

obrisi_drvo(drvo);
}

/*
Pronadjeno 3
Pronadjeno 7
1 3 5 6 7 8 9
Suma cvorova : 39

160
4.49 Drvo 161

Broj cvorova : 7
Broj listova : 3
Suma listova : 18
Dubina drveta : 5
Maximalna vrednost : 9
3 6 9
*/
Primer 4.49.2 Program sa ulaza cita tekst i ispisuje broj pojavljivanja svake od
reci koje su se javljale u tekstu. Radi poboljsanja efikasnosti, prilikom brojanja
reci koristi se struktura podataka pogodna za leksikografsku pretragu - u ovom
slucaju binarno pretrazivacko drvo.
#include <stdlib.h>
#include <stdio.h>

/* Cvor drveta sadrzi ime reci i


broj njenih pojavljivanja */
typedef struct _cvor {
char ime[80];
int br_pojavljivanja;
struct _cvor* levo, *desno;
} cvor;

/* Funkcija ispisuje drvo u inorder redosledu */


void ispisi_drvo(cvor* drvo)
{
if (drvo!=NULL)
{
ispisi_drvo(drvo->levo);
printf("%s %d\n",drvo->ime,drvo->br_pojavljivanja);
ispisi_drvo(drvo->desno);
}
}

/* Funkcija uklanja binarno drvo iz memorije */


void obrisi_drvo(cvor* drvo)
{
if (drvo!=NULL)
{
obrisi_drvo(drvo->levo);
obrisi_drvo(drvo->desno);
free(drvo);
}
}

/* Funkcija ubacuje datu rec u dato drvo


i vraca pokazivac na koren drveta */
cvor* ubaci(cvor* drvo, char rec[]) {
/* Ukoliko je drvo prazno gradimo novi cvor */
if (drvo==NULL)

161
162 Milena VujosevicJanicic

{
cvor* novi_cvor=(cvor*)malloc(sizeof(cvor));
if (novi_cvor==NULL)
{
printf("Greska prilikom alokacije memorije\n");
exit(1);
}
strcpy(novi_cvor->ime, rec);
novi_cvor->br_pojavljivanja=1;
return novi_cvor;
}

/* Uporedjujemo rec koju smo ucitali sa recju koja


se nalazi u cvoru drveta*/
int cmp = strcmp(rec, drvo->ime);

/* Ukoliko rec vec postoji u drvetu


uvecavamo njen broj pojavljivanja */
if (cmp==0)
{ drvo->br_pojavljivanja++;
return drvo;
}

/* Ukoliko je rec koju ubacujemo leksikografski


ispred reci koja je u korenu drveta, rec
ubacujemo u levo podstablo */
if (cmp<0)
{ drvo->levo=ubaci(drvo->levo, rec);
return drvo;
}

/* Ukoliko je rec koju ubacujemo


leksikografski iza reci koja je u
korenu drveta, rec ubacujemo u desno
podstablo */
if (cmp>0)
{ drvo->desno=ubaci(drvo->desno, rec);
return drvo;
}
}

/* Pomocna funkcija koja cita rec sa


standardnog ulaza i vraca njenu
duzinu, odnosno -1 ukoliko se naidje na EOF.
Ukoliko umesto funkcije getword koristimo
funkciju gettag program ce ispisivati
broj pojavljivanja svakog od tagova sa ulaza */
int getword(char word[], int lim) {
int c, i=0;
while (!isalpha(c=getchar()) && c!=EOF)

162
4.49 Drvo 163

if (c==EOF)
return -1;
do
{
word[i++]=c;
} while (i<lim-1 && isalpha(c=getchar()));

word[i]=\0;
return i;
}

main() {
/* Drvo je na pocetku prazno */
cvor* drvo=NULL;
char procitana_rec[80];

/* Citamo rec po rec dok ne


naidjemo na kraj datoteke i
ubacujemo ih u drvo */
while(getword(procitana_rec,80)!=-1)
drvo=ubaci(drvo,procitana_rec);

/* Ispisujemo drvo */
ispisi_drvo(drvo);

/* Uklanjamo ga iz memorije */
obrisi_drvo(drvo);
}

Primer 4.49.3 Program iz datoteke cita tekst i ispisuje n najfrekventnijih reci


koje su se javljale u tekstu.
Radi poboljsanja efikasnosti, prilikom brojanja reci koristi se struktura po-
dataka pogodna za leksikografsku pretragu - u ovom slucaju binarno pretrazivacko
drvo.
Na kraju rada, cvorovi drveta se presortiraju na osnovu broja pojavljivanja.
Zbog ovoga je potrebno cuvati niz pokazivaca na razlicite cvorove drveta.
Da bismo ispisali 10 najfrekventnijih etiketa, potrebno je zameniti funkciju
getword funkcijom gettag.

#include <stdlib.h>
#include <stdio.h>

/* Cvor drveta sadrzi ime reci i


broj njenih pojavljivanja */
typedef struct _cvor {
char ime[80];
int br_pojavljivanja;
struct _cvor* levo, *desno;

163
164 Milena VujosevicJanicic

} cvor;

/* Gradimo niz pokazivaca na cvorove drveta koji ce


nam sluziti da po prihvatanju svih reci izvrsimo
sortiranje po broju pojavljivanja */

#define MAX_BROJ_RAZLICITIH_RECI 1000

cvor* razlicite_reci[MAX_BROJ_RAZLICITIH_RECI];

/* Tekuci broj cvorova drveta */


int broj_razlicitih_reci=0;

/* Funkcija uklanja binarno drvo iz memorije */


void obrisi_drvo(cvor* drvo)
{
if (drvo!=NULL)
{ obrisi_drvo(drvo->levo);
obrisi_drvo(drvo->desno);
free(drvo);
}
}

/* Funkcija ubacuje datu rec u dato drvo i vraca pokazivac na


koren drveta */
cvor* ubaci(cvor* drvo, char rec[])
{
/* Ukoliko je drvo prazno gradimo novi cvor */
if (drvo==NULL)
{
cvor* novi_cvor=(cvor*)malloc(sizeof(cvor));
if (novi_cvor==NULL)
{
printf("Greska prilikom alokacije memorije\n");
exit(1);
}
strcpy(novi_cvor->ime, rec);
novi_cvor->br_pojavljivanja=1;

/* pokazivac na novo napravljeni cvor smestamo u niz


pokazivaca na sve cvorove drveta */
razlicite_reci[broj_razlicitih_reci++] = novi_cvor;

return novi_cvor;
}
int cmp = strcmp(rec, drvo->ime);

/* Ukoliko rec vec postoji u drvetu


uvecavamo njen broj pojavljivanja */
if (cmp==0)

164
4.49 Drvo 165

{ drvo->br_pojavljivanja++;
return drvo;
}

/* Ukoliko je rec koju ubacujemo leksikografski ispred


reci koja je u korenu drveta, rec ubacujemo
u levo podstablo */
if (cmp<0)
{ drvo->levo=ubaci(drvo->levo, rec);
return drvo;
}

/* Ukoliko je rec koju ubacujemo


leksikografski iza reci koja je u
korenu drveta, rec ubacujemo
u desno podstablo */
if (cmp>0)
{ drvo->desno=ubaci(drvo->desno, rec);
return drvo;
}
}

/* Pomocna funkcija koja cita rec iz date datoteke i vraca


njenu duzinu, odnosno -1 ukoliko se naidje na EOF */
int getword(char word[], int lim, FILE* ulaz)
{
int c, i=0;
/* Umesto funkcije getchar koristimo fgetc
za rad sa datotekama */
while (!isalpha(c=fgetc(ulaz)) && c!=EOF)
;
if (c==EOF)
return -1;
do
{ word[i++]=c;
}while (i<lim-1 && isalpha(c=fgetc(ulaz)));

word[i]=\0;
return i;
}

/* Funkcija poredjenja za funkciju qsort. */


int poredi_br_pojavljivanja(const void* a, const void* b)
{
return
/* Konverzija pokazivaca b iz pokazivaca
na tip void u pokazivac na cvor jer
nam je svaki element niza koji sortiramo
tipa pokazivaca na cvor */
(*(cvor**)b)->br_pojavljivanja

165
166 Milena VujosevicJanicic

-
(*(cvor**)a)->br_pojavljivanja;
}

main(int argc, char* argv[])


{
int i;

/* Drvo je na pocetku prazno */


cvor* drvo=NULL;
char procitana_rec[80];
FILE* ulaz;

if (argc!=2)
{ fprintf(stderr,"Greska :
Ocekivano ime datoteke\n");
exit(1);
}

if ((ulaz=fopen(argv[1],"r"))==NULL)
{
fprintf(stderr,"Greska : nisam uspeo da otvorim datoteku %s\n");
exit(1);
}

/* Citamo rec po rec dok ne naidjemo na kraj datoteke i


ubacujemo ih u drvo */
while(getword(procitana_rec,80,ulaz)!=-1)
drvo=ubaci(drvo,procitana_rec);

/* Sortiramo niz pokazivaca na cvorove


drveta po broju pojavljivanja */
qsort(razlicite_reci,
broj_razlicitih_reci,
sizeof(cvor*),
poredi_br_pojavljivanja);

/* Ispisujemo prvih 10 (ukoliko ih ima)


reci i njihov broj pojavljivanja */
for (i=0; i<10 && i<broj_razlicitih_reci; i++)
printf("%s - %d\n",razlicite_reci[i]->ime,
razlicite_reci[i]->br_pojavljivanja);

/* Uklanjamo drvo iz memorije */


obrisi_drvo(drvo);

fclose(ulaz);
}

166
4.50 Grafovi 167

4.50 Grafovi
Graf1 G=(V,E) sastoji se od skupa V cvorova i skupa E grana. Grane predstavl-
jaju relacije izme u cvorova i odgovara paru cvorova. Graf moze biti usmeren
(orijentisan), ako su mu grane ure eni parovi i neusmeren (neorjentisan) ako su
grane neure eni parovi.
Uobicajena su dva nacina predstavljanja grafova. To su matrica povezanosti
grafa i lista povezanosti.
Matrica povezanosti je kvadratna matrica dimenzije n, pri cemu je n broj
cvorova u grafu, takva da je element na preseku i-te vrste i j-te kolone jednak
jedinici ukoliko postoji grana u grafu od i-tog do j-tog cvora, inace je nula.
Umesto da se i sve nepostojece grane eksplicitno predstavljaju u matrici
povezanosti, mogu se formirati povezane liste od jedinica iz i-te vrste za i=1,2,...,n.
To je lista povezanosti. Svakom cvoru se pridruzuje povezana lista, koja sadrzi
sve grane susedne tom cvoru. Graf je predstavljen vektorom lista. Svaki eleme-
nat vektora sadrzi ime (indeks) cvora i pokazivac na njegovu listu cvorova.
Prvi problem na koji se nailazi pri konstrukciji bilo kog algoritma za obradu
grafa je kako pregledati ulaz. Postoje dva osnovna algoritma za obilazak grafa:
pretraga u dubinu (DFS, skracenica od depth-first-search) i pretraga u sirinu
(BFS, skracenica od breadth-first-search).
Kod DFS algoritma, obilazak zapocinje iz proizvoljnog zadatog cvora r koji
se naziva koren pretrage u dubinu. Koren se oznacava kao posecen. Zatim se
bira proizvoljan neoznacen cvor r1, susedan sa r, pa se iz cvora r1 rekurzivno
startuje pretraga u dubinu. Iz nekog nivoa rekurzije izlazi se kad se nai e na
cvor v kome su svi susedi vec oznaceni.

Primer 4.50.1 Primer reprezentovanja grafa preko matrice povezanosti. U


programu se unosi neorijentisan graf i DFS algoritmom se utvr uju cvrovi koji


su dostizni iz cvora 0.

#include <stdlib.h>
#include <stdio.h>

int** alociraj_matricu(int n)
{ int **matrica;
int i;
matrica=malloc(n*sizeof(int*));
if (matrica==NULL)
{
printf("Greska prilikom alokacije memorije\n");
exit(1);
}

for (i=0; i<n; i++)


{
/* Funkcija calloc popunjava rezervisan
prostor u memoriji nulama. */
matrica[i]=calloc(n,sizeof(int));
1 Tekst i primeri preuzeti od Jelene Tomasevic, url: www.matf.bg.ac.yu/jtomasevic, zas-

novano na materijalu Algoritmi, Miodrag Zivkovic i http://www.matf.bg.ac.yu/filip

167
168 Milena VujosevicJanicic

if (matrica[i]==NULL)
{
printf("Greska prilikom alokacije memorije\n");
exit(1);
}
}
return matrica;
}

void oslobodi_matricu(int** matrica, int n)


{ int i;
for (i=0; i<n; i++)
free(matrica[i]);
free(matrica);
}

int* alociraj_niz(int n)
{ int* niz;
niz=calloc(n,sizeof(int));
if (niz==NULL)
{
printf("Greska prilikom alokacije memorije\n");
exit(1);
}
return niz;
}

void oslobodi_niz(int* niz)


{ free(niz);
}

void unesi_graf(int** graf, int n)


{ int i,j;
for (i=0; i<n; i++)
for (j=i; j<n; j++)
{ printf("Da li su element %d i %d povezani : ",i,j);
do
{ scanf("%d",&graf[i][j]);
/* Radimo sa neusmerenim grafom */
graf[j][i]=graf[i][j];
} /* Obezbedjujemo ispravan unos */
while (graf[i][j]!=0 && graf[i][j]!=1);
}
}

void ispisi_graf(int** graf, int n)


{ int i,j;
for (i=0; i<n; i++)
{ for (j=0; j<n; j++)
printf("%d",graf[i][j]);

168
4.50 Grafovi 169

printf("\n");
}
}

/* Broj cvorova grafa (dimenzija matrice) */


int n;
/* Matrica povezanosti */
int **graf;

/* Pomocni vektor koji govori o tome koji su cvorovi posecivani


tokom DFS obilaska */
int *posecen;

/* Rekurzivna implementacija DFS algoritma */


void poseti(int i)
{ int j;
posecen[i]=1;
printf("Posecujem cvor %d\n",i);
for (j=0; j<n; j++)
if (graf[i][j] && !posecen[j])
poseti(j);
}

main()
{
int i, j;
printf("Unesi broj cvorova : ");
scanf("%d",&n);

graf=alociraj_matricu(n);
unesi_graf(graf,n);
ispisi_graf(graf,n);

posecen=alociraj_niz(n);
poseti(0);

oslobodi_niz(posecen);
oslobodi_matricu(graf,n);
}
Primer 4.50.2 Primer predstavljanja grafa preko niza listi suseda svakog od
cvorova grafa U programu se unosi graf i DFS algoritmom se utvrdjuje koji su
cvorovi dostizni iz cvora 0.
#include <stdlib.h>
#include <stdio.h>

169
170 Milena VujosevicJanicic

/* Cvor liste suseda */


typedef struct _cvor_liste
{ int broj; /* Indeks suseda */
struct _cvor_liste* sledeci;
} cvor_liste;

/* Ubacivanje na pocetak liste */


cvor_liste* ubaci_u_listu(cvor_liste* lista, int broj)
{ cvor_liste* novi=malloc(sizeof(cvor_liste));
if (novi==NULL)
{
printf("Greska prilikom alokacije memorije\n");
exit(1);
}
novi->broj=broj;
novi->sledeci=lista;
return novi;
}

/* Rekurzivno brisanje liste */


void obrisi_listu(cvor_liste* lista)
{ if (lista)
{ obrisi_listu(lista->sledeci);
free(lista);
}
}

/* Ispis liste */
void ispisi_listu(cvor_liste* lista)
{ if (lista)
{ printf("%d ",lista->broj);
ispisi_listu(lista->sledeci);
}
}

/* Graf predstavlja niz pokazivaca na pocetke listi suseda */


#define MAX_BROJ_CVOROVA 100
cvor_liste* graf[MAX_BROJ_CVOROVA];
int broj_cvorova;

/* Rekurzivna implementacija DFS algoritma */


int posecen[MAX_BROJ_CVOROVA];
void poseti(int i)
{ cvor_liste* sused;
printf("Posecujem cvor %d\n",i);
posecen[i]=1;
for( sused=graf[i]; sused!=NULL; sused=sused->sledeci)
if (!posecen[sused->broj])
poseti(sused->broj);

170
4.51 Razni zadaci 171

main()
{
int i;
printf("Unesi broj cvorova grafa : ");
scanf("%d",&broj_cvorova);
for (i=0; i<broj_cvorova; i++)
{ int br_suseda,j;

graf[i]=NULL;

printf("Koliko cvor %d ima suseda : ",i);


scanf("%d",&br_suseda);
for (j=0; j<br_suseda; j++)
{ int sused;
do
{
printf("Unesi broj %d.-tog suseda cvora %d : ",j,i);
scanf("%d",&sused);
} while (sused<1 && sused>broj_cvorova);
graf[i]=ubaci_u_listu(graf[i],sused-1);
}
}

for (i=0; i<broj_cvorova; i++)


{ printf("%d - ",i);
ispisi_listu(graf[i]);
printf("\n");
}

poseti(0);
}

4.51 Razni zadaci


k
Primer 4.51.1 Stepenovanje prirodnog broja efikasno: nk = (n 2 )2 ako je k
k1
parno ili nk = n(n 2 )2 ako je k neparno.

int stepen(int n, int k)


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

171
172 Milena VujosevicJanicic

}
return s;
}
Primer 4.51.2 MINESWEEPER - primer jednostavne igrice.
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

/* Dimenzija table */
int n;

/* Tabla koja sadrzi 0 i 1 u zavisnosti


od toga da li na polju postoji bomba */
int** bombe;

#define PRAZNO (-1)


#define ZATVORENO 0
#define ZASTAVICA 9

/* Tabla koja opisuje tekuce stanje igre.


Moze da sadrzi sledece vrednosti :
ZATVORENO - opisuje polje
koje jos nije bilo otvarano
PRAZNO - polje na kome ne
postoji ni jedna bomba
BROJ od 1-8 - polje koje je
otvoreno i na kome pise
koliko bombi postoji u okolini
ZASTAVICA - polje koje je korisnik
oznacio zastavicom
*/
int** stanje;

/* Ukupan broj bombi */


int broj_bombi;

/* Ukupan broj postavljenih zastavica */


int broj_zastavica = 0;

/* Pomocne funkcije za rad sa matricama */


int** alociraj(int n)
{
int i;
int** m=(int**)malloc(n*sizeof(int*));
for (i=0; i<n; i++)
m[i]=(int *)calloc(n,sizeof(int));
return m;
}

172
4.51 Razni zadaci 173

void obrisi(int** m, int n)


{ int i;
for (i=0; i<n; i++)
free(m[i]);

free(m);
}

/* Funkcija postavlja bombe */ void postavi_bombe()


{ broj_bombi=(n*n)/6;
int kolona;
int vrsta;
int i;

/* Inicijalizujemo generator slucajnih brojeva */


srand(time(NULL));

for (i=0; i<broj_bombi; i++)


{ /* Racunamo slucajni polozaj bombe */
kolona=rand()%n;
vrsta=rand()%n;

/* Ukoliko bomba vec postoji tu,


opet idemo u istu iteraciju */
if (bombe[vrsta][kolona]==1)
{ i--;
continue;
}

/* Postavljamo bombu */
bombe[vrsta][kolona]=1;
}
}

/* Funkcija ispisuje tablu sa bombama */


void ispisi_bombe()
{
int i,j;
for (i=0; i<n; i++)
{ for (j=0; j<n; j++)
printf("%d",bombe[i][j]);
printf("\n");
}
}

/* Funkcija ispisuje tekuce stanje */


void ispisi_stanje()
{ int i,j;
for (i=0; i<n; i++)

173
174 Milena VujosevicJanicic

{ for (j=0; j<n; j++)


{ if (stanje[i][j]==ZATVORENO)
printf(".");
else if (stanje[i][j]==PRAZNO)
printf(" ");
else if (stanje[i][j]==ZASTAVICA)
printf("*");
else
printf("%d",stanje[i][j]);
}
printf("\n");
}
}

/* Funkcija postavlja zastavicu na


dato polje ili je uklanja
ukoliko vec postoji */
void postavi_zastavicu(int i, int j)
{
if (stanje[i][j]==ZATVORENO)
{ stanje[i][j]=ZASTAVICA;
broj_zastavica++;
}
else if (stanje[i][j]==ZASTAVICA)
{ stanje[i][j]=ZATVORENO;
broj_zastavica--;
}
}

/* Funkcija izracunava koliko bombi


postoji u okolini date bombe */
int broj_bombi_u_okolini(int v, int k)
{ int i, j;
int br=0;
/* Prolazimo kroz sva okolna polja */
for (i=-1; i<=1; i++)
for(j=-1; j<=1; j++)
{ /* preskacemo centralno polje */
if (i==0 && j==0)
continue;
/* preskacemo polja "van table" */
if (v+i<0 || k+j<0 || v+i>=n || k+j>=n)
continue;
if (bombe[v+i][k+j]==1)
br++;
}

return br;

174
4.51 Razni zadaci 175

/* Centralna funkcija koja vrsi otvaranje


polja i pritom se otvaranje "siri"
i na polja koja su oko datog */

void otvori_polje(int v, int k) {


/* Ukoliko smo "nagazili" bombu
zavrsavamo program */
if (bombe[v][k]==1)
{ printf("BOOOOOOOOOOOOOOOOM!!!!\n");
ispisi_bombe();
exit(1);
}
else
{
/* Brojimo bombe u okolini */
int br=broj_bombi_u_okolini(v,k);

/* Azuriramo stanje ovog polja */


stanje[v][k]=(br==0)?PRAZNO:br;

/* Ukoliko u okolini nema bombi,


rekurzivno otvaramo
sva polja u okolini koja su zatvorena */
if (br==0)
{
/* Petlje indeksiraju sva okolna polja */
int i,j;
for (i=-1; i<=1; i++)
for (j=-1; j<=1; j++)
{
/* Preskacemo centralno polje */
/* if (i==0 && j==0)
continue; */
/* Preskacemo polja van table */
if (v+i<0 || v+i>=n || k+j<0 || k+j>=n)
continue;
/* Ukoliko je okolno polje
zatvoreno, otvaramo ga */
if (stanje[v+i][k+j]==ZATVORENO)
otvori_polje(v+i, k+j);
}
}
}
}

/* Funkcija utrdjuje da li je partija gotova


Partija je gotova u trenutku kada su sve
bombe pokrivene zastavicama i
kada nijedno drugo polje nije

175
176 Milena VujosevicJanicic

pokriveno zastavicom
*/

int gotova_partija()
{ int i,j;
for (i=0; i<n; i++)
for (j=0; j<n; j++)
{ /* Ukoliko postoji nepokrivena bomba,
partija nije zavrsena */
if (bombe[i][j]==1 && stanje[i][j]!=ZASTAVICA)
return 0;
}

/* Partija je zavrsena samo ukoliko je


broj zastavica jednak broj bombi */
return broj_zastavica==broj_bombi;

main() {

/* Unosimo dimenziju table */


printf("Unesite dimenziju table : ");
scanf("%d",&n);

/* Alociramo table */
bombe=alociraj(n);
stanje=alociraj(n);

/* Postavljamo bombe */
postavi_bombe();

/* Sve dok partija nije gotova */


while(!gotova_partija())
{ int v,k;
char akcija;

/* Ispisujemo tekuce stanje */


ispisi_stanje();

/* Sve dok korisnik ne unese o ili z


trazimo od njega da upise
odgovarajucu akciju */
do
{
getchar();
printf("Unesi akciju (o - otvaranje polja,
z - postavljanje zastavice) : ");
scanf("%c",&akcija);

176
4.51 Razni zadaci 177

} while (akcija!=o && akcija!=z);

/* Trazimo od korisnika da unese koordinate


polja sve dok ih ne unese ispravno
Korisnicke koordinate krecu od 1,
a interne od 0 */
do
{
printf("Unesi koordinate polja : ");
scanf("%d",&v);
scanf("%d",&k);
} while(v<1 || v>n || k<1 || k>n);

/* Reagujemo na akciju */
switch(akcija)
{ case o:
otvori_polje(v-1,k-1);
break;
case z:
postavi_zastavicu(v-1,k-1);
}
}

/* Konstatujemo pobedu */
ispisi_stanje();
printf ("Cestitam! Pobedili ste\n");
obrisi(stanje,n);
obrisi(bombe,n);
}

177
Programiranje 1
Programski jezik C
Zadaci sa vezbi

Milena Vujosevic - Janicic 2008/2009


Predgovor

Ovo je prateci materijal za vezbe koje drzim iz predmenta Programi-


ranje 1. On ne moze zameniti pohadanje vezbi niti koriscenje druge
preporucene literature.
Deo materijala cine zadaci i resenja mr Filipa Marica (raspolo-
zivi na www.matf.bg.ac.yu/~filip/pp/0405/index.pl). Takode
koriscen je i materijal sa sajta koleginice Jelene Grmuse
www.matf.bg.ac.yu/~jelenagr i kolege Miroslava Marica
www.matf.bg.ac.yu/~maricm. Tekstovi i objasnjenja su uglavnom
zasnovani na knjizi Programski jezik C, autora Kerninghan & Ritchie.
Zahvaljujem svojim studentima na aktivnom ucescu u nastavi
cime su mi pomogli u uoblicavanju ovog materijala.
Svi komentari i sugestije vezane za ovaj materijal bice veoma
dobrodosli.

Milena Vujosevic-Janicic
www.matf.bg.ac.yu/~milena

1
Sadrzaj

1 Programski jezik C 4
1.1 Zdravo svete! . . . . . . . . . . . . . . . . . . . . . . 4
1.2 Imena promenljivih . . . . . . . . . . . . . . . . . . . 5
1.3 Deklaracije . . . . . . . . . . . . . . . . . . . . . . . 5
1.4 Tipovi i velicina podataka . . . . . . . . . . . . . . . 5
1.5 Konstante . . . . . . . . . . . . . . . . . . . . . . . . 7
1.6 Funkcije printf i scanf . . . . . . . . . . . . . . . . . . 8
1.7 Aritmeticki operatori . . . . . . . . . . . . . . . . . . 10
1.8 Operatori i izrazi dodeljivanja vrednosti . . . . . . . 12
1.9 Inkrementacija i dekrementacija . . . . . . . . . . . . 12
1.10 Relacioni i logicki operatori . . . . . . . . . . . . . . 14
1.11 Kontrola toka if, while, do - while, for . . . . . . . 15
1.11.1 if . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.11.2 Else-if . . . . . . . . . . . . . . . . . . . . . . 16
1.11.3 while . . . . . . . . . . . . . . . . . . . . . . . 18
1.11.4 do-while . . . . . . . . . . . . . . . . . . . . . 18
1.11.5 for . . . . . . . . . . . . . . . . . . . . . . . . 18
1.12 Switch . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.13 Uslovni izraz . . . . . . . . . . . . . . . . . . . . . . . 20
1.14 Konverzija . . . . . . . . . . . . . . . . . . . . . . . . 21
1.14.1 Automatska konverzija . . . . . . . . . . . . . 21
1.14.2 Eksplicitna konverzija . . . . . . . . . . . . . 21
1.15 Dvostruka for petlja . . . . . . . . . . . . . . . . . . 22
1.16 Simbolicke konstante . . . . . . . . . . . . . . . . . . 22
1.17 Enumeracija . . . . . . . . . . . . . . . . . . . . . . . 24
1.18 Operator sizeof() . . . . . . . . . . . . . . . . . . . 24
1.19 Znakovni ulaz i izlaz . . . . . . . . . . . . . . . . . . 25
1.20 Makroi . . . . . . . . . . . . . . . . . . . . . . . . . . 32
1.21 Pokazivaci . . . . . . . . . . . . . . . . . . . . . . . . 35
1.22 Nizovi . . . . . . . . . . . . . . . . . . . . . . . . . . 36
1.23 Pokazivaci i nizovi (polja) . . . . . . . . . . . . . . . 40
1.24 Break i continue . . . . . . . . . . . . . . . . . . . . . 42

2
SADRZAJ SADRZAJ

1.25 Funkcije . . . . . . . . . . . . . . . . . . . . . . . . . 43
1.26 Zivotni vek i oblast vazenja promenjivih, staticke promenljive 46
1.27 Funkcije prenos parametara po vrednosti . . . . . 49
1.28 Pokazivaci i argumenti funkcija . . . . . . . . . . . . 52
1.29 Povratne vrednosti funkcija . . . . . . . . . . . . . . 56
1.30 Rad sa niskama karaktera . . . . . . . . . . . . . . . 58
1.31 Linearna i binarna pretraga . . . . . . . . . . . . . . 69
1.32 Strukture . . . . . . . . . . . . . . . . . . . . . . . . 72
1.33 Operator typedef . . . . . . . . . . . . . . . . . . . . 74
1.34 Unije . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
1.35 Strukture primeri . . . . . . . . . . . . . . . . . . 76
1.36 Datoteke . . . . . . . . . . . . . . . . . . . . . . . . . 86

3
Glava 1

Programski jezik C

1.1 Zdravo svete!


Primer 1.1.1 Program stampa poruku hello, world.
#include <stdio.h>

main()
/*iskazi f-je main su zatvoreni u zagrade */
{
/*poziv f-je printf da odstampa poruku*/
printf("hello, world\n");
}
Primer 1.1.2 Program stampa poruku hello, world
#include <stdio.h>

main()
{
printf("hello, ");
printf("world");
printf("\n");
}
Specijalni znaci:
\n novi red
\t tabulator
\\ kosa crta
\" navodnici
\a zvuk
\ jednstruki navodnik

4
Milena VujosevicJanicic 1.2 Imena promenljivih

1.2 Imena promenljivih


Postoje ogranicenja: u imenu se mogu pojaviti slova i cifre, potcrta
se smatra slovom.
Velika i mala slova se razlikuju.
int x, X; /*To su dve razlicite promenljive!!!*/
Kljucne reci kao sto su if, else, for, while, se ne mogu koristiti za
imena promenljivih.

1.3 Deklaracije
Da bi se promenljiva mogla upotrebljavati ona se mora na pocetku
programa deklarisati. Prilikom deklaracije moze se izvrsiti i pocetna
inicijalizacija.

int broj; /*Deklaracija celog broja*/


int vrednost=5; /*Deklaracija i inicijalizacija celog broja*/

Kvali kator const moze biti dodeljen deklaraciji bilo koje promenljive
da bi oznacio da se ona nece menjati
const double e=2.71828182845905

1.4 Tipovi i velicina podataka


Osnovni tipovi podataka:
int ceo broj
char znak, jedan bajt
float realan broj
double realan broj dvostruke tacnosti
char jedan bajt, sadrzi jedan znak
int celobrojna vrednost, 2 ili 4 bajta
float realan broj, jednostruka tacnost
double dvostruka tacnost
Postoje kvali katori koje pridruzujemo osnovnim tipovima short(16)
i long(32):
short int kratak_broj;
long int dugacak_broj;
short kratak;
long dugacak;

5
Milena VujosevicJanicic 1.4 Tipovi i velicina podataka

Vazi
broj bajtova(short) <= broj bajtova(int) <= broj bajtova(long)
Tip char zauzima jedan bajt ali u zavisnosti od sistema ovaj
tip moze da se odnosi na oznacene ili na neoznacene brojeve. Zato
Postoje kvali katori signed i unsigned koji preciziraju da li se misli
na oznacene ili neoznacene cele brojeve. Npr.
signed char: -128 do 127
dok je
unsigned char: od 0 do 255.
Velicina za int je razlicita u zavisnosti od sistema i moze biti 2
ili 4 bajta. Medutim, ako je promenljiva tipa short int onda ona
sigurno zauzima samo dva bajta a to znaci da u nju mogu da stanu
celobrojne vrednosti iz intervala -32 768 do +32 767, odnosno mogu
se koristiti sledeci sinonimi
short <=> short int <=> signed short int <=> -32 768 do 32 767
Ukoliko se koristi unsigned short int onda je interval
unsigned short int <=> 0 do 65 535
Za realne tipove podataka koriste se float, double i long double.
Njihove velicine mogu da zavise od sistema. Na primer:
float (4 bajta)
float minimalna pozitivna vrednost 1.175494351e-38
float maximalna pozitivna vrednost 3.402823466e+38

double (8 bajta)
double minimalna pozitivna vrednost 2.2250738585072014e-308
double maximalna pozitivna vrednost 1.7976931348623158e+308

long double (10 bajta)


long double minimalna pozitivna 3.3621031431120935063e-4932
long double maximalna pozitivna 1.189731495357231765e+4932
Primer 1.4.1 Uvodenje promenljivih u program.
#include <stdio.h>

main()
{
/*deklaracija vise promenljivih
istog tipa */
int rez,pom1,pom2;
pom1=20;

6
Milena VujosevicJanicic 1.5 Konstante

pom2=15;
rez=pom1-pom2;

/*ispisivanje rezultata*/
printf("Rezultat je %d-%d=%d\n",pom1,pom2,rez);
}
Izlaz iz programa:
Rezultat je 20-15=5
Iskaz dodele:
pom1=20;
pom2=15;
Individualni iskazi se zavrsavaju sa ;

1.5 Konstante
Koji su tipovi konstanti?
Celobrojna konstanta 1234 je tipa int.
Da bi konstanta bila long navodi se iza nje slovo L ili l, npr 123456789L.
Ako zelimo da nam je konstanta unsigned onda na kraju pisemo U
ili u.
Moze i 1234567ul.

Konstante realnih brojeva sadrze decimalnu tacku(123.4) ili


eksponent(1e-2) ili i jedno i drugo. Njihov tip je double osim ako
nemaj su ks f ili F kada je u pitanju oat. L ili l oznacavaju long
double.
Oktalna konstanta pocinje sa 0, a heksadecimalna sa 0x. Npr
broj 31 ili 037 - oktalno ili 0x1f - heksadecimalno. I one mogu da
imaju U i L na kraju.
Znakovna konstanta je celobrojna vrednost napisana izmedu
jednostrukih navodnika. Vrednost date konstante je numericka vred-
nost datog znaka u racunarskom setu znakova. Npr mozemo da
pisemo 0 umesto 48.
!!!Razlikovati znakovne konstante i niske koje se navode izmedu
dvostrukih navodnika!
Posebni znaci su znak za kraj reda \n, tab \t i slicno. Iako se
zapisuju kao vise znakova, oni oznacavaju samo jedan znak i njima
takode odgovara samo jedan bajt.
Znakovna konstanta \0 predstavlja znak cija je vrednost nula,
treba ga razlikovati od 0 koja je znak cija je vrednost 48.
Primer 1.5.1 Koja je vrednost konstantnog izraza

7
Milena VujosevicJanicic 1.6 Funkcije printf i scanf

1. 0x10 + 020 + 9 - 1
2. 0x20 + 010 + 8 - 0

1.6 Funkcije printf i scanf


printf("%d\t%d\n", broj1, broj2);
uvek je prvi argument izmedju " "
%d ceo broj
\t tab izmedju
\n novi red
Svaka % konstrukcija je u paru sa argumentom koji sledi.
Primer 1.6.1
#include <stdio.h>
main()
{
printf("Slova:\n%3c\n%5c\n", z , Z);
}
Izlaz iz programa:
Slova:
z
Z
%c je za stampanje karaktera
%3c je za stampanje karaktera na tri pozicije
Isto tako smo mogli i %3d za stampanje broja na tri pozicije ili %6d
za stampanje broja na 6 pozicija.
Pravila:
%d stampaj kao ceo broj
%6d stampaj kao ceo broj sirok najvise 6 znakova
%f stampaj kao realan broj
%6f stampaj kao realan broj sirok najvise 6 znakova
%.2f stampaj kao realan broj sa dve decimale
%6.2f stampaj kao realan broj sirok najvise 6 znakova a od toga 2
iza decimalne tacke
%c karakter
%s string
%x heksadecimalni broj
%% je procenat

Primer 1.6.2 Ispisivanje karaktera: %c, ispisivanje asci vrednosti


karaktera %d

8
Milena VujosevicJanicic 1.6 Funkcije printf i scanf

#include <stdio.h>
main()
{
int vrednost;
vrednost=A;
printf("Veliko slovo\n karakter=%3c\nvrednost=%3d\n",vrednost,vrednost);
vrednost=a;
printf("Malo\n karakter=%3c\nvrednost=%3d\n",vrednost,vrednost);
}

Izlaz (u slucaju ASCII):


Veliko slovo
karakter= A
vrednost= 65
Malo
karakter= a
vrednost= 97

Primer 1.6.3 Prikazuje unos celog broja koristeci scanf("%d", &x)


#include <stdio.h>

main()
{
int x;
printf("Unesi ceo broj : ");

/* Obratiti paznju na znak &


(operator uzimanja adrese)
pre imena promenljive u funkciji
scanf */
scanf("%d",&x);

/* U funkciji printf nije


potrebno stavljati & */
printf("Uneli ste broj %d\n", x);
}

Primer 1.6.4 Program sabira dva uneta cela broja


#include <stdio.h>

main()
{

9
Milena VujosevicJanicic 1.7 Aritmeticki operatori

int a, b, c;
printf("Unesi prvi broj : ");
scanf("%d", &a);
printf("Unesi drugi broj : ");
scanf("%d", &b);
c = a + b;
printf("%d + %d = %d\n", a, b, c);
}
Ulaz:
Unesi prvi broj : 2 <enter>
Unesi drugi broj : 3 <enter>
Izlaz:
2 + 3 = 5

1.7 Aritmeticki operatori


+ - * /
% (samo za celobrojne vrednosti)
unarno + i -

Asocijativnost sleva na desno, prioritet kao u matematici.

Primer 1.7.1 Program ilustruje neke od aritmetickih operacija.


#include <stdio.h>
main()
{
int a, b;
printf("Unesi prvi broj : ");
scanf("%d",&a);

printf("Unesi drugi broj : ");


scanf("%d",&b);

/* Kada se saberu dva cela broja, rezultat je ceo broj*/


printf("Zbir a+b je : %d\n",a+b);
/* Kada se oduzmu dva cela broja, rezultat je ceo broj*/
printf("Razlika a-b je : %d\n",a-b);
/* Kada se pomnoze dva cela broja, rezultat je ceo broj*/
printf("Proizvod a*b je : %d\n",a*b);
/* Kada se podele dva cela broja, rezultat je ceo broj!!!*/
printf("Celobrojni kolicnik a/b je : %d\n", a/b);
/* Rezultat je ceo broj, bez obzira sto ga ispisujemo kao realan*/

10
Milena VujosevicJanicic 1.7 Aritmeticki operatori

printf("Pogresan pokusaj racunanja realnog kolicnika a/b je : %f\n", a/b);


/* Eksplicitna konverzija, a i b pretvaramo u relane brojeve kako
bi deljenje bilo realno*/
printf("Realni kolicnik a/b je : %f\n", (float)a/(float)b);
/* Ostatak pri deljenju se moze izvrsiti samo nad celim brojevima*/
printf("Ostatak pri deljenju a/b je : %d\n", a%b);
}

Ulaz:
Unesi prvi broj : 2 <enter>
Unesi drugi broj : 3 <enter>
Izlaz:
Zbir a+b je : 5
Razlika a-b je : -1
Proizvod a*b je : 6
Celobrojni kolicnik a/b je : 0
Progresan pokusaj racunanja realnog kolicnika a/b je : 0.000000
Realni kolicnik a/b je : 0.666667
Ostatak pri deljenju a/b je : 2
Primer 1.7.2 Program ilustruje celobrojno i realno deljenje.
#include <stdio.h>

main()
{
int a = 5;
int b = 2;
int d = 5/2; /* Celobrojno deljenje - rezultat je 2 */
float c = a/b; /* Iako je c float, vrsi se celobrojno
deljenje jer su i a i b celi */

/* Neocekivani rezultat 2.000000 */


printf("c = %f\n",c);
printf("Uzrok problema : 5/2 = %f\n", 5/2);
printf("Popravljeno : 5.0/2.0 = %f\n", 5.0/2.0);
printf("Moze i : 5/2.0 = %f i 5.0/2 = %f \n", 5/2.0, 5.0/2);
printf("Za promenljive mora kastovanje : %f\n", (float)a/(float)b);

Izlaz iz programa:
c = 2.000000
Uzrok problema : 5/2 = 2.000000

11
Milena VujosevicJanicic 1.8 Operatori i izrazi dodeljivanja vrednosti

Popravljeno : 5.0/2.0 = 2.500000


Moze i : 5/2.0 = 2.500000 i 5.0/2 = 2.500000
Za promenljive mora kastovanje : 2.500000

Zadatak 1 Sta ce biti ispisano nakon izvrsavanja sledeceg programa?


#include <stdio.h>
main()
{
int x=506, y=3, z=21, t=2;
printf("x=%d y=%d\n",x,y);
printf("z - t=%d\n", z-t);
printf("z / t =%d\n",z / t);
printf("-x=%d\n",- x);
printf("x %% y=%d\n", x%y);
}

1.8 Operatori i izrazi dodeljivanja vrednosti


i = i + 2;
ekvivalento je sa
i+=2;

Moze i za:
+ - * / % << >> ^ |
izraz1 op = izraz2
je ekvivalnetno sa
izraz1 = (izraz1) op (izraz2)

x*= y+1 je ekvivalento sa x = x * (y+1)


Takvo pisanje je krace i e kasnije.

1.9 Inkrementacija i dekrementacija


Operatori ++ i --
x=++n; se razlikuje od x=n++;

y=(x++)*(++z);
Primer 1.9.1 Ilustracija prefiksnog i postfiksnog operatora ++

12
Milena VujosevicJanicic 1.9 Inkrementacija i dekrementacija

#include <stdio.h>
main()
{
int x, y;
int a = 0, b = 0;

printf("Na pocetku : \na = %d\nb = %d\n", a, b);

/* Ukoliko se vrednost izraza ne koristi, prefiksni i


postfiksni operator se ne razlikuju */
a++;
++b;
printf("Posle : a++; ++b; \na = %d\nb = %d\n", a, b);

/* Prefiksni operator uvecava promenljivu, i rezultat


je uvecana vrednost */
x = ++a;

/* Postfiksni operator uvecava promenljivu, i rezultat je


stara (neuvecana) vrednost */
y = b++;

printf("Posle : x = ++a; \na = %d\nx = %d\n", a, x);


printf("Posle : y = b++; \nb = %d\ny = %d\n", b, y);
}

Izlaz iz programa:
Na pocetku:
a = 0
b = 0
Posle : a++; ++b;
a = 1
b = 1
Posle : x = ++a;
a = 2
x = 2
Posle : y = b++;
b = 2
y = 1

13
Milena VujosevicJanicic 1.10 Relacioni i logicki operatori

1.10 Relacioni i logicki operatori


Relacioni operatori:
> >= < <= isti prioritet
== != nizi prioritet

(3<5)
(a<=10)
a < 5 != 1 <=> (a < 5)!=1
Logicki operatori:
! unarna negacija (najvisi prioritet)
&& logicko i (visi prioritet od ili)
|| logicko ili izracunavaju se sleva na desno!

5 && 4 vrednost je tacno


10 || 0 vrednost je tacno
0 && 5 vrednost je 0
!1 vrednost je 0
!9 vrednost je 0
!0 vrednost je 1
!(2>3) je 1
a>b && b>c || b>d je isto sto i ((a>b) && (b>c)) || (b>d)
koja je vrednost ako je a=10, b=5, c=1, d=15?

Primer 1.10.1 Ilustracija logickih i relacijskih operatora.


#include <stdio.h>

main()
{
int a = 3>5, /* manje */
b = 5>3, /* vece */
c = 3==5, /* jednako */
d = 3!=5; /* razlicito */

printf("3>5 - %d\n5>3 - %d\n3==5 - %d\n3!=5 - %d\n", a, b, c, d);

/*Lenjo izracunavanje: kako 3 nije vece od 5 to se vrednost


drugog poredjenja nece racunati jer je netacno u konjunkciji
sa proizvoljnim izrazom sigurno netacno. */
printf("Konjunkcija : 3>5 && 5>3 - %d\n", a && b);

14
Milena VujosevicJanicic 1.11 Kontrola toka if, while, do - while, for

/*Lenjo izravunavanje: tacno u disjunkciji sa proizvoljnim


izrazom daje tacno tako da se vrednost izraza 3>5 nece
izracunavati*/
printf("Disjunkcija : 5>3 || 3>5 - %d\n", b || a);
printf("Negacija : !(3>5) - %d\n", !a);

Izlaz iz programa:
3>5 - 0
5>3 - 1
3==5 - 0
3!=5 - 1
Konjunkcija : 3>5 && 5>3 - 0
Disjunkcija : 3>5 || 5>3 - 1
Negacija : !(3>5) - 1

1.11 Kontrola toka if, while, do - while, for


1.11.1 if
if (izraz)
iskaz1
else
iskaz2

Primer 1.11.1 Program ilustruje if i ispisuje ukoliko je uneti ceo


broj negativan
#include <stdio.h>

main()
{
int b;
printf("Unesi ceo broj:");
scanf("%d", &b);
if (b < 0)
printf("Broj je negativan\n");
}

Else se odnosi na prvi neuparen if, voditi o tome racuna, ako


zelimo drugacije moramo da navedemo viticaste zagrade.
if (izraz)

15
Milena VujosevicJanicic 1.11 Kontrola toka if, while, do - while, for

if (izraz1) iskaz 1
else iskaz
ovo else se odnosi na drugo if a ne na prvo if!
if (izraz)
{
if (izraz1) iskaz 1
}
else iskaz
tek sada se else odnosi na prvo if!!!

1.11.2 Else-if
if (izraz1)
iskaz1
else if (izraz2)
iskaz2
else if (izraz3)
iskaz3
else if (izraz4)
iskaz4
else iskaz

npr if (a<5)
printf("A je manje od 5\n");
else if (a=5)
printf("A je jednako 5\n");
else if (a>10)
printf("A je vece od 10\n");
else if (a=10)
printf("A je jednako 10\n");
else printf("A je vece od pet i manje od 10\n");
Primer 1.11.2 Program ilustruje if-else konstrukciju i ispituje znak
broja.
#include <stdio.h>

main()
{
int b;
printf("Unesi ceo broj : ");
scanf("%d", &b);

16
Milena VujosevicJanicic 1.11 Kontrola toka if, while, do - while, for

if (b < 0)
printf("Broj je negativan\n");
else if (b == 0)
printf("Broj je nula\n");
else
printf("Broj je pozitivan\n");
}

Ulaz:
Unesi ceo broj:-5
Izlaz:
Broj je negativan

Ulaz:
Unesi ceo broj:5
Izlaz:
Broj je pozitivan

Primer 1.11.3 Pogresan program sa dodelom = umesto poredjenja


==.
#include <stdio.h>

main()
{
int b;
printf("Unesi ceo broj : ");
scanf("%d", &b);

/* Obratiti paznju na = umesto == Analizirati rad programa*/


if (b = 0)
printf("Broj je nula\n");
else if (b < 0)
printf("Broj je negativan\n");
else
printf("Broj je pozitivan\n");
}

Ulaz:
Unesi ceo broj:-5
Izlaz:
Broj je pozitivan

17
Milena VujosevicJanicic 1.11 Kontrola toka if, while, do - while, for

1.11.3 while
while(uslov) { ... }
Uslov u zagradi se testira i ako je ispunjen telo petlje se izvrsava.
Zatim se uslov ponovo testira i ako je ispunjen ponovo se izvrsava
telo petlje. I tako sve dok uslov ne bude ispunjen. Tada se izlazi iz
petlje i nastavlja sa prvom sledecom naredbom u programu.
Ukoliko iza while sledi samo jedna naredba nema potrebe za
zagradama.
while (i<j)
i=2*i;

1.11.4 do-while
Ovo je slicno paskalskom repeat-until izrazu.
do iskaz while (izraz)
Primer 1.11.4 Program ilustruje petlju do-while.
#include <stdio.h>

main()
{
int x;

x = 1;
do
{
printf("x = %d\n",x);
x++; /* x++ je isto kao i x=x+1 */
} while (x<=10);
}

1.11.5 for
Primer 1.11.5 Program ilustruje petlju - for.
#include <stdio.h>

main()
{
int x;

/* Inicijalizacija; uslov; inkrementacija*/

18
Milena VujosevicJanicic 1.12 Switch

for (x = 1; x < 5; x++)


printf("x = %d\n",x);

}
Izlaz:
1
2
3
4

1.12 Switch
switch (iskaz) {
case konstantan_izraz1: iskazi1
case konstantan_izraz2: iskazi2
...
default: iskazi
}
Primer 1.12.1 Voditi racuna o upotrebi break-a.
#include <stdio.h> /*
Upotreba switch-a
*/

main() {
char x;
scanf("%c",&x);

switch (x)
{
case a:
case e:
case i:
case o:
case u: printf(" x je samoglasnik");
break;
case r: printf(" x je r");
break;
default: printf(" x je suglasnik");
}
}
Primer 1.12.2 Ilustracija switch konstrukcije.

19
Milena VujosevicJanicic 1.13 Uslovni izraz

#include<stdio.h>
main()
{
int n;
printf("Unesi paran broj manji od 10\n");
scanf("%d",&n);
switch(n) {
case 0:
printf("Uneli ste nulu\n");
break;
case 2:
printf("Uneli ste dvojku\n");
break;
case 4:
printf("Uneli ste cetvorku\n");
break;
case 6:
printf("Uneli ste sesticu\n");
break;
case 8:
printf("Uneli ste osmicu\n");
break;
defalut:
printf("Uneli ste nesto sto nije paran broj\n");
}
}
Ulaz:
Unesi paran broj manji od 10
2
Izlaz:
Uneli ste dvojku

1.13 Uslovni izraz


Slicno kao if.

izraz1 ? izraz2 : izraz3

z = (a<b)? a : b; /*z=min(a,b)*/
max = (a>b)? a : b;

20
Milena VujosevicJanicic 1.14 Konverzija

1.14 Konverzija
1.14.1 Automatska konverzija
Ako je jedan od operanada razlizlicit vrsi se konverzija, uvek u smeru
manjeg ka vecem tipu

Naredba dodele:
int i=5;
float f=2.3;
f=i; /* f ce imati vrednost 5.0*/

obrnuto:

int i=5;
float f=2.3;
i=f; /* i ce imati vrednost 2*/

1.14.2 Eksplicitna konverzija


(tip)<izraz>

float x;
x=2.3+4.2; /* x ce imati vrednost 6.5 */
x=(int)2.3+(int)4.2; /* x ce imati vrednost 6 */
x=(int)2.3*4.5; /* x ce imati vrednost 9.0 jer zbog prioriteta
operatora konverzije prvo ce biti izvrsena
konverzija broja 2.3 u 2 pa tek onda izvrseno
mnozenje. */
x=(int)(2.3*4.5) /* x ce imati vrednost 10.0 */
Primer 1.14.1 Kako izbeci celobrojno deljenje
int a,b;
float f;
a = 5;
b = 2;
f = a/b; /* Celobrojno deljenje, f=2*/
f = (1.0*a)/b; /* Implicitna konverzija: 1.0*a je realan
broj pa priliko deljenja sa b dobija se
realan rezultat f=2.5*/
f = (0.0+a)/b; /* Implicitna konverzija: (0.0+a) je realan
broj pa priliko deljenja sa b dobija se
realan rezultat f=2.5*/

21
Milena VujosevicJanicic 1.15 Dvostruka for petlja

f = (float)a/(float)b; /* Eksplicitna konverzija*/

1.15 Dvostruka for petlja


Primer 1.15.1 Dvostruka for petlja
#include<stdio.h>
int main()
{
int i,j;

for(i=1; i<=10; i++)


{
for(j=1; j<=10; j++)
printf("%d * %d = %d\t", i, j, i*j);
printf("\n");
}
}
Primer 1.15.2 Trostruka for petlja
#include<stdio.h>
int main()
{
int i,j;

for(i=1; i<=10; i++)


for(j=1; j<=10; j++)
{
for(k=1; k<=10; k++)
printf("%d * %d * %d = %d\t", i, j, k, i*j*k);
printf("\n");
}
}
Koliko puta se izvrsi naredba stampanja
printf("%d * %d * %d = %d\t", i, j, k, i*j*k);

1.16 Simbolicke konstante


Primer 1.16.1 Konverzija centimetara u ince - while petlja.
#include <stdio.h>

22
Milena VujosevicJanicic 1.16 Simbolicke konstante

/* Definicija simbolickih konstanti preko #define direktiva */


/* U fazi pretprocesiranja se vrsi doslovna zamena konstanti
njihovim vrednostima */

#define POCETAK 0
#define KRAJ 20
#define KORAK 10

main()
{
int a;
a = POCETAK;
while (a <= KRAJ)
{
printf("%d cm = %f in\n", a, a/2.54);
a += KORAK; /* isto sto i a = a + KORAK; */
}
}

Izlaz:
0 cm = 0.000000 in
10 cm = 3.937008 in
20 cm = 7.874016 in

Primer 1.16.2 Konverzija centimetara u ince - for petlja.


#include <stdio.h>
#define POCETAK 0
#define KRAJ 20
#define KORAK 10

main()
{
int a;
for (a = POCETAK; a <= KRAJ; a += KORAK)
printf("%d cm = %f in\n", a, a/2.54);
}

Izlaz:
0 cm = 0.000000 in
10 cm = 3.937008 in
20 cm = 7.874016 in
Zadatak 2 Sta ce biti ispisano nakon izvrsavanja sledeceg programa?

23
Milena VujosevicJanicic 1.17 Enumeracija

#include <stdio.h>
#define EURO 85.90
main()
{
printf("4 eura ima vrednost %f dinara\n", 4*EURO);
printf("1 euro ima vrednost %.0f dinara\n",EURO);
}

1.17 Enumeracija
Izvesna alternativa za define
enum boolean {NO, YES};
enum meseci {JAN = 1, FEB, MAR, APR, MAJ, JUN,
JUL, AVG, SEP, OKT, NOV, DEC}
enum boje {CRVENA, ZELENA=5, PLAVA,
LJUBICASTA=10, ZUTA, CRNA}

koriscenje:

int x=0;
boje b;

x=CRVENA+3; /*x ce biti jednako tri*/

b=ZELENA;
x=b+CRNA; /* x = 5 + 12*/

b=0; /*Greska, ovako ne moze!!! b je boja i


moze imati samo vrednosti CRVENA, ZELENA ...*/

1.18 Operator sizeof()


Primer 1.18.1 Demonstracija sizeof operatora. Sizeof operator
izracunava velicinu tipa odnosno promenjive.
#include<stdio.h>
main()
{
int i;
float f;

24
Milena VujosevicJanicic 1.19 Znakovni ulaz i izlaz

printf("sizeof(int)=%d\n", sizeof(int));
printf("sizeof(long)=%d\n", sizeof(long));
printf("sizeof(short)=%d\n", sizeof(short));
printf("sizeof(signed)=%d\n", sizeof(signed));
printf("sizeof(unsigned)=%d\n", sizeof(unsigned));
printf("sizeof(char)=%d\n", sizeof(char));
printf("sizeof(float)=%d\n", sizeof(float));
printf("sizeof(double)=%d\n", sizeof(double));

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

Izlaz iz programa (u konkretnom slucaju):


sizeof(int)=4
sizeof(long)=4
sizeof(short)=2
sizeof(signed)=4
sizeof(unsigned)=4
sizeof(char)=1
sizeof(float)=4
sizeof(double)=8
sizeof(i)=4
sizeof(f)=4

1.19 Znakovni ulaz i izlaz


Funkcija za citanje jednog znaka sa ulaza
c = getchar()
promenljiva c sadrzi jedan znak sa ulaza i potrebno je da bude
celobrojnog tipa jer je funkcija getchar() tako de nisana da vraca
celobrojnu vrednost (odnosno vrednost koja ima tip int).

Funkcija za stampanje jednog znaka na izlaz


putchar(c)
stampa sadrzaj promenljive c na standardni izlaz.

Konstanta EOF je celobrojna vrednost de nisana u biblioteci <stdio.h>


(najcesce ima vrednost -1). Ovu vrednost vrati funkcija getchar()
kada nema vise ulaza. Nazvana je EOF kao End Of File, kraj da-
toteke. Sa tastature, ovaj znak se moze uneti kombinacijom tastera
ctrl i D.

25
Milena VujosevicJanicic 1.19 Znakovni ulaz i izlaz

Primer 1.19.1 Program cita jedan karakter i ispisuje ga - demon-


stracija putchar i getchar.
#include <stdio.h>

main()
{
int c; /* Karakter - obratiti paznju na int */
c = getchar(); /* cita karakter sa standardnog ulaza */
putchar(c); /* pise karakter c na standardni izlaz */

putchar(\n); /* prelazak u novi red */


putchar(a); /* ispisuje malo a */
putchar(97); /* ekvivalentno prethodnom, tj ispisuje
se karakter ciji je asci kod 97 */

putchar(A+ 10); /* na izlazu ce biti otstampan znak ciji


je asci kod za deset veci od asci koda
slova A, dakle znak ciji je asci kod
65+10=75, a to je znak koji se nalazi
za deset mesta iza slova A u abecedi,
dakle znak K */
putchar(a+ 3); /* znak d */

}
Ulaz:
s
Izlaz iz programa:
s
s
aa
K
d

Primer 1.19.2 Pretpostavimo da se od korisnika zahteva da unese


prvo jedno veliko pa onda jedno malo slove engleske abecede. Sta ce
biti izlaz iz programa ako korisnik unese prvo slovo B a zatim slovo
f?
#include <stdio.h>

main()
{
int c;

26
Milena VujosevicJanicic 1.19 Znakovni ulaz i izlaz

c = getchar(); /* Ucitavamo jedno veliko slovo */


putchar(c - A + a); /* sta ce biti ispisano? */

putchar(\n); /* prelazak u novi red */

c = getchar(); /* Ucitavamo jedno malo slovo */


putchar(c -a+A); /* sta ce biti ispisano? */
putchar(c - a + A + 1); /* sta ce biti ispisano? */
}

Primer 1.19.3 Program prepisuje standardni ulaz na standardni


izlaz. Ilustracija redirekcije standardnog ulaza i izlaza, pokrenuti
program sa :
./a.out <primer.c
./a.out >tekst.txt
./a.out <primer.c >kopija.c

#include <stdio.h>

main()
{

int c;

/*Ucitava se prvi znak sa ulaza*/


c = getchar();

/*EOF predstavlja celobrojnu vrednost kraja datoteke.


To je konstanta definisana u <stdio.h>*/
while (c != EOF) {
putchar(c);
c = getchar();
}
}

Bilo koje dodeljivanje vrednosti je izraz koji ima vrednost a to je


vrednost leve strane posle dodeljivanja.
Primer 1.19.4 Program koji kopira ulaz na izlaz, skraceni kod.
#include <stdio.h>

main()
{

27
Milena VujosevicJanicic 1.19 Znakovni ulaz i izlaz

int c;

/* Obratiti paznju na raspored zagrada


koje su neophodne zbog prioriteta operatora */
while ((c = getchar()) != EOF)
putchar(c);
}

Primer 1.19.5 Brojanje znakova na ulazu.


#include <stdio.h>

main()
{
long broj_znakova;

broj_znakova = 0;
while (getchar() != EOF)
++broj_znakova;
/* %ld odnosi se na tip long. */
printf("%ld\n", broj_znakova);
}

Primer 1.19.6 Brojanje znakova na ulazu koriscenjem for petlje.


#include <stdio.h>

main()
{
long broj_znakova;

/*For petlja mora da ima telo pa makar


ono bilo przno*/
for (broj_znakova = 0; getchar() != EOF; ++broj_znakova)
;
printf("%ld\n", broj_znakova);
}

Primer 1.19.7 Program broji linije i znakove na ulazu.


#include <stdio.h>
main()
{
int znak; /*prihvata znak sa ulaza */
long linije=0 ; /*brojac linija */

28
Milena VujosevicJanicic 1.19 Znakovni ulaz i izlaz

long br_znak=0; /*brojac znakova na ulazu */

while ( (znak=getchar() ) != EOF)


{
br_znak++;
if (znak==\n) linije ++;
}

printf("Prelazaka u novi red: %ld, karaktera: %ld \n",linije,br_znak);


}

Primer 1.19.8 Program broji blankove, horizontalne tabulatore i


linije na ulazu.
#include <stdio.h>
main()
{
int znak; /*prihvata znak sa ulaza */
int Blanks=0; /*brojac blankova */
int Tabs=0; /*brojac horizontalnih tabulatora */
int NewLines=0; /*brojac linija */

/*UOCITI: blok naredbi while ciklusa NIJE OGRADJEN


viticastim zagradama jer postoji samo jedna if naredba! */
while( (znak=getchar()) != EOF )
if( znak== ) ++Blanks; /* brojimo blanko simbole */
else if( znak==\t ) ++Tabs; /* brojimo tab-ove */
else if( znak==\n ) ++NewLines; /* brojimo redove */

/* Stampanje rezultata na standardni izlaz*/


printf("Blankova: %d. \n", Blanks);
printf("Tabulatora: %d. \n", Tabs);
printf("Prelazaka u novi red: %d. \n", NewLines);
}

Primer 1.19.9 Program vrsi prebrojavanje cifara unetih na ulazu.


#include <stdio.h>

main()
{
int c;
int br_cifara = 0;
while ((c = getchar()) != EOF)

29
Milena VujosevicJanicic 1.19 Znakovni ulaz i izlaz

if (0<=c && c<=9)


br_cifara++;

printf("Broj cifara je : %d\n", br_cifara);


}
Primer 1.19.10 Program vrsi brojanje pojavljivanja karaktera 0, 1
i 2 (ilustruje switch).
#include <stdio.h>

main()
{
int c;
int br_0=0, br_1=0, br_2=0;

while ((c = getchar()) != EOF)


{
switch(c)
{
/* Obratiti paznju da nije
case 0: */
case 0:
br_0++;
break; /* Isprobati veziju bez break */
case 1:
br_1++;
break;
case 2:
br_2++;
break;
default:
}
}
printf("Br 0 : %d\nBr 1 : %d\nBr 2 : %d\n",br_0, br_1, br_2);
}
Primer 1.19.11 Program prepisuje ulaz na izlaz pri cemu vise blanko
znakova zamenjuje jednim.
#include <stdio.h>

main()
{

30
Milena VujosevicJanicic 1.19 Znakovni ulaz i izlaz

int znak; /*tekuci znak sa ulaza*/


int preth; /*znak koji prethodi tekucem */
preth=a; /* inicijalizujemo vrednost prethodnog
da bi prvi prolazak kroz petlju bio ispravan*/
while ( (znak=getchar() ) !=EOF)
{
if (znak != || preth != ) putchar(znak);
preth=znak;
}
}
Primer 1.19.12 Brojanje reci, linija i karaktera koji se unose sa
ulaza.
#include <stdio.h>

#define IN 1 /* inside a word */


#define OUT 0 /* outside a word */

/* count lines, words, and characters in input */

main()
{
int c, nl, nw, nc, state;

state = OUT;

/*Postavljaju se sve tri promenljive na nulu*/


/*Prvi nacin:
nl = 0;
nw = 0;
nc = 0;*/
/*To je isto kao da smo napisali
nl = (nw = (nc = 0));
A moze i bez zagrada: */

nl = nw = nc = 0;
while ((c = getchar()) != EOF) {
++nc;
if (c == \n)
++nl;

if (c == || c == \n || c == \t)
state = OUT;

31
Milena VujosevicJanicic 1.20 Makroi

else if (state == OUT) {


state = IN;
++nw;
}
}
printf("%d %d %d\n", nl, nw, nc);
}

1.20 Makroi
#define ime tekst_zamene

Zamene se vrse samo na simbolima, a ne obavljaju se u niskama


nutar navodnika.
Moguce je de nisati makroe sa argumentima tako da tekst zamene
bude razlicit za razlicita pojavljivanja makroa.

Primer 1.20.1 Demonstracija pretprocesorske direktive #define


#include<stdio.h>

/* Racuna sumu dva broja */


#define sum(a,b) ((a)+(b))

/* Racuna kvadrat broja - pogresna verzija */


#define square_w(a) a*a

/* Racuna kvadrat broja */


#define square(a) ((a)*(a))

/* Racuna minimum tri broja */


#define min(a, b, c) (a)<(b)? ((a)<(c)? (a) : (c)) : ((b)<(c)? (b) : (c))

main()
{
printf("sum(3,5) = %d\n", sum(3,5));
printf("square_w(5) = %d\n", square_w(5));
printf("square_w(3+2) = %d\n", square_w(3+2));
printf("square(3+2) = %d\n", square(3+2));
printf("min(1,2,3) = %d\n", min(1,2,3));
printf("min(1,3,2) = %d\n", min(1,3,2));
printf("min(2,1,3) = %d\n", min(2,1,3));
printf("min(2,3,1) = %d\n", min(2,3,1));

32
Milena VujosevicJanicic 1.20 Makroi

printf("min(3,1,2) = %d\n", min(3,1,2));


printf("min(3,2,1) = %d\n", min(3,2,1));
}

Izlaz iz programa:
sum(3,5) = 8
square_w(5) = 25
square_w(3+2) = 11
square(3+2) = 25
min(1,2,3) = 1
min(1,3,2) = 1
min(2,1,3) = 1
min(2,3,1) = 1
min(3,1,2) = 1
min(3,2,1) = 1

Primer 1.20.2
#define max(A, B) ((A)>(B) ? (A) : (B))

na osnovu ovoga ce linija


x=max(p+q, r+s)
biti zamenjena linijom
x=((p+q) > (r+s) ? (p+q) : (r+s));
Treba voditi racuna o sporednim efektima. Sledeca linija koda
pruzrokovace uvecanje vrednosti i ili j za dva.

max(i++, j++)

Takode treba voditi racuna o zagradama. Sledeci makro prouzrokovace


neocekivane rezultate za upotrebu square(a+1)

#define square(x) x*x

Primer 1.20.3 Ilustacija beskonacne petlje:


#define forever for(;;);

Primer 1.20.4
#include <stdio.h>
#define max1(x,y) (x>y?x:y)
#define max2(x,y) ((x)>(y)?(x):(y))
#define swapint(x,y) { int z; z=x; x=y; y=z; }
#define swap(t,x,y) { \

33
Milena VujosevicJanicic 1.20 Makroi

t z; \
z=x; \
x=y; \
y=z; }

main()
{

int x=2,y=3;

printf( "max1(x,y) = %d\n", max1(x,y) );


/* max1(x,y) = 3 */

/* Zamena makroom se ne vrsi


unutar niski pod navodnicima*/
printf( "max1(x=5,y) = %d\n", max1(x,y) );
/* max1(x=5,y) = 3 */

printf( "max1(x++,y++) = %d\n", max1(x++,y++) );


/* max1(x++,y++) = 4 */

printf( "x = %d, y = %d\n", x, y );


/* x = 3, y = 5 */

swapint(x,y);

printf( "x = %d, y = %d\n", x, y );


/* x = 5, y = 3 */

swap(int,x,y);
printf( "x = %d, y = %d\n", x, y );
/* x = 3, y = 5 */
}

Izlaz:
max1(x,y) = 3
max1(x=5,y) = 3
max1(x++,y++) = 4
x = 3, y = 5
x = 5, y = 3
x = 3, y = 5

34
Milena VujosevicJanicic 1.21 Pokazivaci

1.21 Pokazivaci
Pokazivac je promenljiva koja sadrzi adresu promenljive.
int x=1, y=1;
int *ip; /* ip je pokazivac na int,
odnosno *ip je tipa int*/

ip = &x; /* ip sada pokazuje na x */


y=*ip; /* y je sada 1 */
*ip = 0; /* x je sada 0 */

*ip+=10; /* x je sada 10*/


++*ip; /* x je sada 11*/
(*ip)++; /* x je sada 12,
zagrada neophodna zbog prioriteta
operatora*/

Primer 1.21.1 Ilustracija rada sa pokazivackim promenljivim.


#include <stdio.h>
main()
{
int x = 3;

/* Adresu promenjive x zapamticemo u novoj promeljivoj.


Nova promenljiva je tipa pokazivaca na int (int*) */
int* px;

printf("Adresa promenljive x je : %p\n", &x);


printf("Vrednost promenljive x je : %d\n", x);

px = &x;
printf("Vrednost promenljive px je (tj. px) : %p\n", px);
printf("Vrednost promenljive na koju
ukazuje px (tj. *px) je : %d\n", *px);

/* Menjamo vrednost promenljive na koju ukazuje px */


*px = 6;
printf("Vrednost promenljive na koju
ukazuje px (tj. *px) je : %d\n", *px);

/* Posto px sadrzi adresu promenljive x,


ona ukazuje na x tako da je

35
Milena VujosevicJanicic 1.22 Nizovi

posredno promenjena i vrednost promenljive x */


printf("Vrednost promenljive x je : %d\n", x);

Izlaz (u konkretnom slucaju):


Adresa promenljive x je : 0012FF88
Vrednost promenljive x je : 3
Vrednost promenljive px je (tj. px) : 0012FF88
Vrednost promenljive na koju ukazuje px (tj. *px) je : 3
Vrednost promenljive na koju ukazuje px (tj. *px) je : 6
Vrednost promenljive x je : 6

1.22 Nizovi
Deklaracija niza:
int niz[5]; /* niz od 5 elemenata tipa int*/
Pristupanje elementima niza:
niz[0] = 4;
niz[1] = 2 * niz[0]; /*niz[1] = 8*/
niz[2] = niz[0] * niz[1]; /*niz[2] = 32*/
niz[3] = 5;
niz[4] = 7;
Unos vrednosti elemenata niza sa tastature:
for(i=0; i<5; i++)
scanf("%d", &a[i]);
Stampanje elemenata niza
for(i=0; i<5; i++)
printf("%d ", a[i]);
Brojanje elemenata niza je od nule!
Pristupanje elementu niza, indeks moze da bude proizvoljan izraz
celobrojne vrednosti: niz[i*2]=5.
Primer 1.22.1 Program ilustruje koriscenje nizova. Ispisuje 10
unetih brojeva unazad.
#include <stdio.h>
#define BR_ELEM 10

36
Milena VujosevicJanicic 1.22 Nizovi

main()
{
int a[BR_ELEM];
int i;
for (i = 0; i<BR_ELEM; i++)
{
printf("a[%d]=",i);
scanf("%d",&a[i]);
}

printf("Unazad : \n");

for (i = BR_ELEM - 1; i>=0; i--)


printf("a[%d]=%d\n",i,a[i]);
}

Primer 1.22.2 Program pronalazi maksimum brojeva sa ulaza -


verzija sa nizom.
#include <stdio.h>
#define BR_ELEM 5
main()
{
int a[BR_ELEM];
int i;
int max;

/* Ucitavamo niz brojeva */


for (i = 0; i < BR_ELEM; i++)
scanf("%d",&a[i]);

/* Pronalazimo maksimum */
max = a[0];
for (i = 1; i < BR_ELEM; i++)
if (a[i]>max)
max = a[i];

/* Ispisujemo maksimum */
printf("Max = %d\n",max);
}
Primer 1.22.3 Program pronalazi maksimum brojeva sa ulaza -
verzija bez niza. (Ovo resenje je efikasnije jer je brze i koristi manje
memorije.)

37
Milena VujosevicJanicic 1.22 Nizovi

#include <stdio.h>
#define BR_ELEM 5

main()
{
int a, max, i;
scanf("%d",&a);
max = a;
for (i = 1; i < BR_ELEM; i++)
{
scanf("%d",&a);
if (a>max)
max = a;
}

printf("Max : %d\n", max);


}
Primer 1.22.4 Program ilustruje inicijalizaciju nizova.
#include <stdio.h>

main()
{
/* Niz inicijalizujemo tako sto mu navodimo vrednosti
u viticasnim zagradama. Dimenzija niza se odredjuje
na osnovu broja inicijalizatora */
int a[] = {1, 2, 3, 4, 5, 6};

/* Isto vazi i za niske karaktera */


char s[] = {a, b, c};

/* Ekvivalentno prethodnom bi bilo


char s[] = {97, 98, 99};
*/

/* Broj elemenata niza */


int a_br_elem = sizeof(a)/sizeof(int);
int s_br_elem = sizeof(s)/sizeof(char);

/* Ispisujemo nizove */

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

38
Milena VujosevicJanicic 1.22 Nizovi

printf("a[%d]=%d\n",i, a[i]);

for (i = 0; i < s_br_elem; i++)


printf("s[%d]=%c\n",i, s[i]);

}
Primer 1.22.5 Brojanje pojavljivanja svake od cifara. Koriscenje
niza brojaca.
#include <stdio.h>

/* zbog funkcije isdigit */


#include <ctype.h>

main()
{
/* Niz brojaca za svaku od cifara */
int br_cifara[10];
int i, c;

/* Resetovanje brojaca */
for (i = 0; i < 10; i++)
br_cifara[i] = 0;

/* Citamo sa ulaza i povecavamo odgovarajuce brojace */


while ((c = getchar()) != EOF)
if (isdigit(c))
br_cifara[c-0]++;

/* Ispis rezultata */
for (i = 0; i < 10; i++)
printf("Cifra %d se pojavila %d put%s\n",
i, br_cifara[i], br_cifara[i] == 1 ? "" : "a");
}

Konstantne niske
Konstantna niska: Ja sam niska
ili
/*prazna niska*/
Navodnici nisu deo niske vec se koriste da bi je ogranicili. Ako ih
zelimo unutar niske, oni se navode sa \".

39
Milena VujosevicJanicic 1.23 Pokazivaci i nizovi (polja)

Konstantna niska je polje znakova. Da bi se znalo gde je kraj


niske, zicko memorisanje liste zahteva da postoji jedan znak vise
koji oznacava kraj, to je \0. Da bi se odredila duzina niske mora
se proci kroz celu nisku.
!!!Vazno:

Koja je razlika izmedu x i x ?

Primer 1.22.6 Program uvodi niske karaktera terminisane nulom.


#include <stdio.h>

main()
{
/* Poslednji bajt niske karaktera se postavlja na \0 tj. 0 */
char s[] = {a, b, c, \0 };

/* Kraci nacin da se postigne prethodno */


char t[] = "abc";

/* Ispis niske s karakter po karakter*/


int i;
for (i = 0; s[i] != \0; i++)
putchar(s[i]);
putchar(\n);

/* Ispis niske s koristeci funkciju printf */


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

/* Ispis niske t karakter po karakter*/


for (i = 0; t[i] != \0; i++)
putchar(t[i]);
putchar(\n);

/* Ispis niske t koristeci funkciju printf */


printf("%s\n", t);
}

1.23 Pokazivaci i nizovi (polja)


U C-u postoji cvrsta veza izmedu pokazivaca i nizova. Bilo koja
operacija koja se moze ostvariti dopisivanjem indeksa niza moze se
uraditi i sa pokazivacima.

40
Milena VujosevicJanicic 1.23 Pokazivaci i nizovi (polja)

Deklaracija
int a[10];
de nise niz a velicine 10 koji predstavlja blok od 10 uzastopnih
objekata nazvanih a[0], a[1], ..., a[9]. Notacija a[i] odgo-
vara i-tom elementu niza.
Ako je pa pokazivac na ceo broj
int *pa;
tada iskaz pa = &a[0];
podesava da pa pokaze na nulti element niza a, odnosno pa sadrzi
adresu od a[0].
Ako pa pokazuje na odredeni element polja, onda po de niciji
pa+1 pokazuje na sledeci element, pa+i pokazuje na i-ti element
posle pa. Stoga, ako pa pokazuje na a[0] tada
*(pa+1)
se odnosi na sadrzaj od a[1].
pa+i je adresa od a[i], a
*(pa+i)
je sadrzaj od a[i]. Dozvoljeno je upotrebljavati i sintaksu kao
kod nizova:
*(pa+i) <==> pa[i]
Ovo sve vazi bez obzira na tip ili velicinu elemenata u polju a.
Iskaz pa=&a[0] se moze napisati kao pa=a jer je ime niza
sinonim za lokaciju pocetnog elementa.

Primer 1.23.1 Veza izmedu pokazivaca i nizova.


#include <stdio.h>

main()
{
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int num_of_elements = sizeof(a)/sizeof(int);
int* pa;

/* Niz je isto sto i adresa prvog elementa */


printf("Niz a : %p\n", a);
printf("Adresa prvog elementa niza a (&a[0]) : %p\n", &a[0]);
/* Niz a : 0012FF5C
Adresa prvog elementa niza a (&a[0]) : 0012FF5C */

/* Moguce je dodeliti niz pokazivacu odgovarajuceg tipa */


pa = a;

41
Milena VujosevicJanicic 1.24 Break i continue

printf("Pokazivac pa ukazuje na adresu : %p\n", pa);


/* Pokazivac pa ukazuje na adresu : 0012FF5C */

/* Nizu nije moguce dodeliti pokazivacku promenljivu


(nizove mozemo smatrati KONSTANTNIM pokazivacima na prvi element) */
/* a = pa; */

/* Pokazivace je dalje moguce indeksirati kao nizove */


printf("pa[0] = %d\n", pa[0]);
printf("pa[5] = %d\n", pa[5]);
/* pa[0] = 1
pa[5] = 6 */

/* Medjutim, sizeof(pa) je samo velicina pokazivaca, a ne niza */


printf("sizeof(a) = %d\n", sizeof(a));
printf("sizeof(pa) = %d\n", sizeof(pa));
/* sizeof(a) = 40
sizeof(pa) = 4 */
}

1.24 Break i continue


break moze da se koristi unutar switch naredbe ali i unutar petlje
(ukljucujuci sve tri vrste petlje). Kada se koristi unutar petlje,
break prouzrokuje nasilan izlazak iz petlje. Na primer:
/* Ako se neki clan niza nula,
petlja ce biti nasilno zavrsena,
sto znaci da preostali elementi niza
nece biti razmatrani, na primer ako je niz
1 2 3 0 4 5
tada ce za i=0, i=1 i i=2 biti izvrseno
mnozenje i proizvod ce biti 6,
za i=3 vazice uslov da je a[i]==0 i break
ce da prekine petlju, program ce se nastaviti
nakon for petlje i proizvod ce biti 6*/
prizvod = 1;
for(i=0; i<n; i++)
{
if (a[i]==0) break;
proizvod *= a[i];
}

42
Milena VujosevicJanicic 1.25 Funkcije

Continue se rede koristi, on prouzrokuje da se prede na sledecu


iteraciju u petlji.

/* Izracunace se proizvod nenula elemenata niza*/


prizvod = 1;
for(i=0; i<n; i++)
{
if (a[i]==0) continue;
prizvod *= a[i];
}

1.25 Funkcije
Primer 1.25.1 sum - najjednostavnija funkcija koja sabira dva broja
/* Definicija funkcije */
int sum(int a, int b)
{
int c;
c = a + b;
return c;
/* Ovo je krace moglo da bude napisano
kao return a+b; */
}

main()
{

int c;
/* Poziv funkcije */
c = sum(3,5);
printf("%d\n", c);

/* Ovo smo krace mogli da napisemo kao


printf("%d\n", sum(3,5)); */
}

Primer 1.25.2 Deklaracija funkcije moze da stoji nezavisno od defini-


cije funkcije. Deklaracija je neophodna u situacijama kada se defini-
cija funkcije navodi nakon upotrebe date funkcije u kodu.
/* Deklaracija funkcije*/
int zbir(int, int);

43
Milena VujosevicJanicic 1.25 Funkcije

main()
{
/* Poziv funkcije */
printf("%d\n", zbir(3,5));
}

/* Definicija funkcije */
int zbir(int a, int b)
{
return a+b;
}

Primer 1.25.3 power - funkcija koja stepenuje realan broj na celo-


brojni izlozilac
#include <stdio.h>

/* stepenuje x^k tako sto k puta pomnozi x */


float power(float x, int k)
{
int i;
float rezultat = 1;
for (i = 0; i<k; i++)
rezultat*=x;

return rezultat;
}

Primer 1.25.4 Verzija koja radi i za negativne izlozioce


float power(float x, int k)
{
int i;
float s = 1;
int negativan = (k<0);
float rezultat;

if (negativan)
k = -k;

for (i = 0; i<k; i++)


s*=x;

rezultat = negativan ? 1.0/s : s;

44
Milena VujosevicJanicic 1.25 Funkcije

return rezultat;
}

main()
{
/* Poziv funkcije */
float s = power(2.0,8);
printf("%f\n", s);
}

Primer 1.25.5 Funkcija koja konvertuje velika slova u mala slova.


#include<stdio.h>

/* Konvertuje karakter iz velikog u malo slovo */


char lower(char c)
{
if (c >= A && c <= Z)
return c - A + a ;
else
return c;
}

main()
{
char c;
printf("Unesi neko veliko slovo:\n");
scanf("%c", &c);
printf("Odgovarajuce malo slovo je %c\n", lower(c));
}

Primer 1.25.6 Funkcija koja proverava da li je broj prost i program


koji ispisuje sve proste brojeve manje od 100.
#include<stdio.h>
#include<math.h>

int prost(int p)
{
int i, koren, ind;
koren=sqrt(p);
ind=(p%2) || (p==2);
i=3;
while (ind && i<=koren)

45
Milena VujosevicJanicic
1.26 Zivotni vek i oblast vazenja promenjivih, staticke promenljive

{
ind=p%i;
i+=2;
}
return ind;
}

main()
{
int k;
for(k=2;k<=100;k++)
if (prost(k)) printf("%d ",k);
}

1.26 Zivotni vek i oblast vazenja promenjivih,


staticke promenljive
Primer 1.26.1
/* Ilustruje vidljivost imena*/
#include <stdio.h>

int i=10;

void main() {
{
int i=3;
{
int i=1;
printf("%d\n", i);
}
printf("%d\n",i);
}
printf("%d\n",i);
}
Primer 1.26.2 Demonstracija zivotnog veka i oblasti vazenja promen-
jivih.
#include <stdio.h>

/* Globalna promenjiva */
int a = 0;

46
Milena VujosevicJanicic
1.26 Zivotni vek i oblast vazenja promenjivih, staticke promenljive

/* Uvecava se globalna promenjiva a */


void increase()
{
a++;
printf("increase::a = %d\n", a);
}

/* Umanjuje se lokalna promenjiva a.


Globalna promenjiva zadrzava svoju vrednost. */
void decrease()
{
/* Ovo a je nezavisna promenjiva u odnosu na globalno a */
int a = 0;
a--;
printf("decrease::a = %d\n", a);

void nonstatic_var()
{
/* Nestaticke promenjive ne cuvaju vrednosti kroz pozive funkcije */
int s=0;
s++;
printf("nonstatic::s=%d\n",s);
}

void static_var()
{
/* Staticke promenjive cuvaju vrednosti kroz pozive funkcije.
Inicijalizacija se odvija samo u okviru prvog poziva. */
static int s=0;
s++;
printf("static::s=%d\n",s);
}

main()
{
/* Promenjive lokalne za funkciju main */
int i;
int x = 3;

printf("main::x = %d\n", x);

47
Milena VujosevicJanicic
1.26 Zivotni vek i oblast vazenja promenjivih, staticke promenljive

for (i = 0; i<3; i++)


{
/* Promenjiva u okviru bloka je nezavisna od spoljne promenjive.
Ovde se koristi promenjiva x lokalna za blok petlje koja ima
vrednost 5, dok originalno x i dalje ima vrednost 3*/
int x = 5;
printf("for::x = %d\n", x);
}

/* U ovom bloku x ima vrednost 3 */


printf("main::x = %d\n", x);

increase();
decrease();

/* Globalna promenjiva a */
printf("main::a = %d\n", a);

/* Demonstracija nestatickih promenjivih */


for (i = 0; i<3; i++)
nonstatic_var();

/* Demonstracija statickih promenjivih */


for (i = 0; i<3; i++)
static_var();
}

Izlaz iz programa:
main::x = 3
for::x = 5
for::x = 5
for::x = 5
main::x = 3
increase::a = 1
decrease::a = -1
main::a = 1
nonstatic::s=1
nonstatic::s=1
nonstatic::s=1
static::s=1
static::s=2
static::s=3

48
Milena VujosevicJanicic 1.27 Funkcije prenos parametara po vrednosti

1.27 Funkcije prenos parametara po vred-


nosti
Primer 1.27.1 Demonstracija prenosa parametara po vrednosti -
preneti parametri se ne mogu menjati
#include <stdio.h>
void f(int x)
{
x++;
}

main()
{
int x=3;
f(x);
printf("%d\n", x);
}

Primer 1.27.2 Funkcija za ispis niza brojeva - demonstrira prenos


nizova brojeva u funkciju.
#include <stdio.h>

/* Nizovi se prenose tako sto se prenese adresa njihovog pocetka.


Uglaste zagrade ostaju prazne!

Nizove je neophodno prenositi zajedno sa dimenzijom niza


(osim za niske karaktera, jer tamo vazi konvencija da
se kraj niza obelezava znakom \0)
*/
void print_array(int a[], int n)
{
int i;
for (i = 0; i < n; i++)
printf("%d ",a[i]);
putchar(\n);

/* Obratite paznju na ovo : */


printf("sizeof(a) - u okviru fje : %d\n", sizeof(a));
}

main()
{

49
Milena VujosevicJanicic 1.27 Funkcije prenos parametara po vrednosti

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

printf("sizeof(a) - u okviru main : %d\n", sizeof(a));


print_array(a, sizeof(a)/sizeof(int));
}
Primer 1.27.3 Funkcija za ispis niske karaktera - demonstrira prenos
niske karaktera u funkciju.
#include <stdio.h>

/* Uz nisku karaktera nije potrebno prenositi dimenziju


ukoliko se postuje dogovor
da se svaka niska zavrsava karakterom \0.*/
void print_string(char s[])
{
int i;
for (i = 0; s[i]!=\0; i++)
putchar(s[i]);
}

main()
{
string str[] = "Zdravo\n"
print_string(str);
}

Primer 1.27.4 Konvertovanje niske cifara u ceo broj.


#include<stdio.h>

/* atoi: konvertuje s u ceo broj */


int atoi(char s[])
{
int i, n;
n = 0;
for (i = 0; (s[i] >= 0) && (s[i] <= 9); ++i)
n = 10 * n + (s[i] - 0);
return n;
}

main()
{
int n;

50
Milena VujosevicJanicic 1.27 Funkcije prenos parametara po vrednosti

char broj[]="234"
n = atoi(broj);
printf("\nN je : %d\n",n);
}
Primer 1.27.5 Demonstrira prenos nizova u funkciju - preneti niz
se moze menjati.
#include <stdio.h>
#include <ctype.h>

/* Funkcija ucitava rec sa standardnog ulaza


i smesta je u niz karaktera s.
Ovo uspeva zbog toga sto se po vrednosti
prenosi adresa pocetka niza,
a ne ceo niz */
void get_word(char s[])
{
int c, i = 0;
while (!isspace(c=getchar()))
s[i++] = c;
s[i] = \0;
}

main()
{
/* Obavezno je alocirati memoriju za niz karaktera */
char s[100];

get_word(s);
printf("%s\n", s);
}
Primer 1.27.6 Veza izmedu pokazivaca i nizova u funkcijama.
#include <stdio.h>

/* Deklaracija funkcije print_array */


void print_array(int* pa, int n);

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

51
Milena VujosevicJanicic 1.28 Pokazivaci i argumenti funkcija

int* pa;

pa = a;

/* Pozivamo funkciju za stampanje niza i saljemo joj niz */


print_array(a, num_of_elements);

/* Pozivamo funkciju za stampanje niza


i saljemo joj pokazivac na pocetak niza */
print_array(pa, num_of_elements);
}

/* Prosledjivanje niza u funkciju


void print_array(int pa[], int n);
je ekvivalentno prosledjivanju pokazivaca u funkciju
void print_array(int* pa, int n);
Izmedju ovih konstrukcija nema nikakve razlike!
*/
void print_array(int* pa, int n)
{
int i;
printf("%d\n", sizeof(pa));
for (i = 0; i<n; i++)
printf("%d ", pa[i]);
putchar(\n);
}

1.28 Pokazivaci i argumenti funkcija


C prosleduje argumente u funkcije pomocu vrednosti. To znaci da
sledeca funkcija nece uraditi ono sto zelimo:
void swap (int x, int y) /* POGRESNO!!!!!!!!*/
{
int temp;
temp = x;
x=y;
y=temp;
}
Zbog prenosa parametara preko vrednosti swap ne moze da utice
na argumente a i b u funkciji koja je pozvala swap. Ova swap
funkcija samo zamenjuje kopije od a i b.

52
Milena VujosevicJanicic 1.28 Pokazivaci i argumenti funkcija

Da bi se dobio zeljeni efekat, potrebno je da se proslede pokazivaci:


/* Zameni *px i *py */
void swap (int *px, int *py)
{
int temp;
temp =*px;
*px = *py;
*py = temp;
}
a poziv funkcije swap izlgeda sada ovako
swap(&a, &b);
Primer 1.28.1 Prethodni primer moze se testirati uz pomoc sledeceg
programa.
#include <stdio.h>

/* Pogresna verzija funkcije swap. Zbog prenosa po vrednosti, funkcija


razmenjuje kopije promenljivih iz main-a, a ne samih promenljivih */
void swap_wrong(int x, int y)
{
int tmp;
printf("swap_wrong: ");
printf("Funkcija menja vrednosti promenljivim na adresama : \n");
printf("x : %p\n", &x);
printf("y : %p\n", &y);
tmp = x;
x = y;
y = tmp;
}

/* Resenje je prenos argumenata preko pokazivaca */


void swap(int* px, int* py)
{
int tmp;
printf("swap : Funkcija menja vrednosti promenljivim na adresama : \n");
printf("px = %p\n", px);
printf("py = %p\n", py);
tmp = *px;
*px = *py;
*py = tmp;
}

53
Milena VujosevicJanicic 1.28 Pokazivaci i argumenti funkcija

main()
{
int x = 3, y = 5;
printf("Adresa promenljive x je %p\n", &x);
printf("Vrednost promenljive x je %d\n", x);
printf("Adresa promenljive y je %p\n", &y);
printf("Vrednost promenljive y je %d\n", y);

/* Pokusavamo zamenu koristeci pogresnu verziju funkcije */


swap_wrong(x, y);
printf("Posle swap_wrong:\n");
printf("Vrednost promenljive x je %d\n", x);
printf("Vrednost promenljive y je %d\n", y);

/* Vrsimo ispravnu zamenu. Funkciji swap saljemo adrese promenljvih


x i y, a ne njihove vrednosti */
swap(&x, &y);
printf("Posle swap:\n");
printf("Vrednost promenljive x je %d\n", x);
printf("Vrednost promenljive y je %d\n", y);
}

Izlaz u konkretnom slucaju:


Adresa promenljive x je 0012FF88
Vrednost promenljive x je 3
Adresa promenljive y je 0012FF84
Vrednost promenljive y je 5
swap_wrong: Funkcija menja vrednosti promenljivim na adresama :
x : 0012FF78
y : 0012FF7C
Posle swap_wrong:
Vrednost promenljive x je 3
Vrednost promenljive y je 5
swap : Funkcija menja vrednosti promenljivim na adresama :
px = 0012FF88
py = 0012FF84
Posle swap:
Vrednost promenljive x je 5
Vrednost promenljive y je 3
Primer 1.28.2 Demonstracija vise povratnih vrednosti funkcije ko-
risteci prenos preko pokazivaca.

54
Milena VujosevicJanicic 1.28 Pokazivaci i argumenti funkcija

/* Funkcija istovremeno vraca dve vrednosti - kolicnik i ostatak


dva data broja. Ovo se postize tako sto se funkciji predaju
vrednosti dva broja (x i y) koji se dele
i adrese dve promenljive na koje ce se smestiti rezultati */

void div_and_mod(int x, int y, int* pdiv, int* pmod)


{
printf("Kolicnik postavljam na adresu : %p\n", pdiv);
printf("Ostatak postavljam na adresu : %p\n", pmod);
*pdiv = x / y;
*pmod = x % y;
}

main()
{
int div, mod;
printf("Adresa promenljive div je %p\n", &div);
printf("Adresa promenljive mod je %p\n", &mod);

/* Pozivamo funkciju tako sto joj saljemo


vrednosti dva broja (5 i 2)
i adrese promenljvih div i mod na koje
ce se postaviti rezultati */
div_and_mod(5, 2, &div, &mod);

printf("Vrednost promenljive div je %d\n", div);


printf("Vrednost promenljive mod je %d\n", mod);

Izlaz u konkretnom slucaju:


Adresa promenljive div je 0012FF88
Adresa promenljive mod je 0012FF84
Kolicnik postavljam na adresu : 0012FF88
Ostatak postavljam na adresu : 0012FF84
Vrednost promenljive div je 2
Vrednost promenljive mod je 1
Primer 1.28.3 Ilustracija lenjog izracunavanja logickih operatora.
Prilikom izracunavanja izraza - A && B, ukoliko je A netacno,
izraz B se ne izracunava. Prilikom izracunavanja izraza - A k B,
ukoliko je A tacno, izraz B se ne izracunava.
#include <stdio.h>

55
Milena VujosevicJanicic 1.29 Povratne vrednosti funkcija

/* Globalna promenljiva, vidljiva i iz funkcije main() i


iz funkcije izracunaj*/
int b = 0;

/* Funkcija ispisuje da je pozvana i uvecava promenjivu b.


Funkcija uvek vraca vrednost 1 (tacno)
*/
int izracunaj()
{
printf("Pozvano izracunaj()\n");
b++;
return 1;
}

main()
{
/* Funkcija izracunaj() ce biti pozvana
samo za parne vrednosti a */
int a;
for (a = 0; a < 10; a++)
if (a%2 == 0 && izracunaj())
printf("Uslov ispunjen : a = %d, b = %d\n", a, b);
else
printf("Uslov nije ispunjen : a = %d, b = %d\n", a, b);

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

/* Funkcija izracunaj() ce se pozivati samo


za neparne vrednosti a */
b = 0;
for (a = 0; a < 10; a++)
if (a%2 == 0 || izracunaj())
printf("Uslov ispunjen : a = %d, b = %d\n", a, b);
else
printf("Uslov nije ispunjen : a = %d, b = %d\n", a, b);
}

1.29 Povratne vrednosti funkcija


Funkcije mogu da nemaju povratnu vrednost (onda se to oznacava
kljucnom reci void) ili da vrate bilo koji osnovni tip podataka, struk-

56
Milena VujosevicJanicic 1.29 Povratne vrednosti funkcija

turu, uniju ili pokazivac. U sledecim primerima date su deklaracije


funkcija bez argumenata sa razlicitim povratnim vrednostima:
void f1(); /*Funkcija nema povratnu vrednost*/
void f2(void); /*Funkcija nema povratnu vrednost*/

int f3(); /*Povratna vrednost celobrojna*/


unsigned int f4(); /*Povratna vrednost tipa unsigned int*/
long int f5(); /*Povratna vrednost tipa long int*/

float f6(); /*Povratna vrednost tipa float*/


double f7(); /*Povratna vrednost tipa double*/

int* f8(); /*Povratna vrednost je pokazivac na int*/


struct licnost f9(); /*Povratna vrednost je struktura*/
struct licnost* f10(); /*Povratna vrednost je pokazivac na strukturu*/
Funkcija ne moze da vrati niz, dakle deklaracija sledeceg oblika
je neispravna:
/* Sintaksno neispravna deklaracija funkcije*/
int[] funkcija();
Moguce je vratiti adresu prvog elementa niza, i to se radi koriscenjem
funkcije koja ima za povratnu vrednost pokazivac. Na primer,
int* funkcija();
Treba voditi racuna da iako je sledeci kod sintaksno ispravan, on
je potpuno semanticki neispravan i moze izazvati prekid rada pro-
grama:

/*Neispravna upotreba pokazivaca */


int* funkcija()
{
int i;
int a[20];
for(i=0; i<20; i++)
a[i] = i;
return a;
}
Do greske dolazi jer se kao povratna vrednost funkcije vraca adresa
niza a koji je lokalna promenljiva u funkciji i cija se memorija

57
Milena VujosevicJanicic 1.30 Rad sa niskama karaktera

oslobada zavrsavanjem rada funkcije (tj. niz a prestaje da postoji


kada funkcija zavrsi rad tako da pokazivac ukazuje na adresu objekta
koji na tom mestu vise ne postoji). Dakle, nije moguce kreirati
lokalni niz u funkciji, sracunati njegove vrednosti i onda vratiti
pokazivac na prvi element tog niza. Da bi funkcija f sracunala
elemente nekog niza, potrebno je da se taj niz alocira u funkciji
koja poziva funkciju f, a da se samoj funkciji proslede adresa prvog
elementa niza i broj elemenata niza. Dakle,
void funkcija(int a[], int n)
{
int i;
for(i=0; i<20; i++)
a[i] = i;
}
main()
{
int a[20];
funkcija(a, 20);
...
}

1.30 Rad sa niskama karaktera


Primer 1.30.1 Primer funkcije koja izracunava duzinu niske znakova.
#include <stdio.h>

/* Ova funkcija racuna duzinu date niske karaktera.


Umesto nje, moguce je koristiti standardnu funkciju strlen
za cije je koriscenje potrebno ukljuciti zaglavlje
<string.h>
*/
int strlen(char s[])
{
int i=0;
while (s[i] != \0)
++i;
return i;
}

main()
{

58
Milena VujosevicJanicic 1.30 Rad sa niskama karaktera

printf("Duzina ove niske je: %d \n",strlen("Duzina ove niske je:"));


}

Primer 1.30.2 Funkcija uklanja beline, tabulatore ili znak za kraj


reda sa kraja stringa.
int trim(char s[])
{
int n;
for (n = strlen(s)-1; n >= 0; n--)
if (s[n] != && s[n] != \t && s[n] != \n)
break;
s[n+1] = \0;
return n;
}

Primer 1.30.3 string_reverse - obrce nisku karaktera.


#include <stdio.h>

/* Ova funkcija racuna duzinu date niske karaktera.


Umesto nje, moguce je koristiti standardnu funkciju strlen
za cije je koriscenje potrebno ukljuciti zaglavlje
<string.h>
*/
int string_length(char s[])
{
int i;
for (i = 0; s[i]!=\0; i++)
;

return i;
}

/* Funkcija obrce nisku karaktera */


void string_reverse(char s[])
{
int i, j;
for (i = 0, j = string_length(s)-1; i<j; i++, j--)
{
int tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}

59
Milena VujosevicJanicic 1.30 Rad sa niskama karaktera

/* Napomena : razlikovati prethodnu petlju od dve ugnjezdjene petlje:


for ( i = 0; ....)
for ( j = duzina(s)-1; ...
*/

main()
{
char s[] = "Zdravo svima";
string_reverse(s);
printf("%s\n", s);
}
/*
Izlaz:
amivs ovardZ
*/
Primer 1.30.4 strlen, strcpy, strcat, strcmp, strchr, strstr
- manipulacija niskama karaktera. Vezbe radi, implementirane su
funkcije biblioteke string.h
#include <stdio.h>

/* Izracunava duzinu stringa */


int string_length(char s[])
{
int i;
/* Uslov s[i] je ekvivalentan uslovu
s[i]!=\0 ili uslovu s[i]! = 0*/
for (i = 0; s[i]; i++)
;
return i;
}

/* Kopira string src u string dest.


Pretpostavlja da u dest ima dovoljno prostora. */
void string_copy(char dest[], char src[])
{
/* Kopira karakter po karakter, sve dok nije
iskopiran karakter \0 */
int i;
for (i = 0; (dest[i]=src[i]) != \0; i++)

60
Milena VujosevicJanicic 1.30 Rad sa niskama karaktera

/* Uslov != \0 se, naravno, moze izostaviti :

for (i = 0; dest[i]=src[i]; i++)


;
*/
}

/* Vrsi leksikografsko poredjenje dva stringa.


Vraca :
0 - ukoliko su stringovi jednaki
<0 - ukoliko je s leksikografski ispred t
>0 - ukoliko je s leksikografski iza t
*/
int string_compare(char s[], char t[])
{
/* Petlja tece sve dok ne naidjemo na prvi razliciti karakter */
int i;
for (i = 0; s[i]==t[i]; i++)
if (s[i] == \0) /* Naisli smo na kraj oba stringa,
a nismo nasli razliku */
return 0;

/* s[i] i t[i] su prvi karakteri u kojima se niske razlikuju.


Na osnovu njihovog odnosa, odredjuje se odnos stringova */
return s[i] - t[i];
}

/* Nadovezuje string t na kraj stringa s.


Pretpostavlja da u s ima dovoljno prostora. */
void string_concatenate(char s[], char t[])
{
int i, j;
/* Pronalazimo kraj stringa s */
for (i = 0; s[i]; i++)
;

/* Vrsi se kopiranje, slicno funkciji string_copy */


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

61
Milena VujosevicJanicic 1.30 Rad sa niskama karaktera

/* Pronalazi prvu poziciju karaktera c u stringu s, odnosno -1


ukoliko s ne sadrzi c */
int string_char(char s[], char c)
{
int i;
for (i = 0; s[i]; i++)
if (s[i] == c)
return i;
/* nikako
else
return -1;
*/
/* Nije nadjeno */
return -1;
}

/* Pronalazi poslednju poziciju karaktera c u stringu s, odnosno -1


ukoliko s ne sadrzi c */
int string_last_char(char s[], char c)
{
/* Pronalazimo kraj stringa s */
int i;
for (i = 0; s[i]; i++)
;

/* Krecemo od kraja i trazimo c unazad */


for (i--; i>=0; i--)
if (s[i] == c)
return i;

/* Nije nadjeno */
return -1;

/*
Koristeci string_length :

for (i = string_length(s) - 1; i>0; i--)


if (s[i] == c)
return i;

return -1;

62
Milena VujosevicJanicic 1.30 Rad sa niskama karaktera

*/
}

/* Proverava da li string str sadrzi string sub.


Vraca poziciju na kojoj sub pocinje, odnosno -1 ukoliko ga nema
*/
int string_string(char str[], char sub[])
{
int i, j;
/* Proveravamo da li sub pocinje na svakoj poziciji i */
for (i = 0; str[i]; i++)
/* Poredimo sub sa str pocevsi od poziciji i
sve dok ne naidjemo na razliku */
for (j = 0; str[i+j] == sub[j]; j++)
/* Nismo naisli na razliku a ispitali smo
sve karaktere niske sub */
if (sub[j+1]==\0)
return i;
/* Nije nadjeno */
return -1;
}

main()
{
char s[100];
char t[] = "Zdravo";
char u[] = " svima";

string_copy(s, t);
printf("%s\n", s);

string_concatenate(s, u);
printf("%s\n", s);

printf("%d\n",string_char("racunari", n));
printf("%d\n",string_last_char("racunari", a));

printf("%d\n",string_string("racunari", "rac"));
printf("%d\n",string_string("racunari", "ari"));
printf("%d\n",string_string("racunari", "cun"));
printf("%d\n",string_string("racunari", "cna"));
}

63
Milena VujosevicJanicic 1.30 Rad sa niskama karaktera

/*
Izlaz:
Zdravo
Zdravo svima
4
5
0
5
2
-1*/

Primer 1.30.5 Funkcija koja uklanja proizvoljan znak c kad god se


pojavi u stringu s.
#include <stdio.h>

void squeeze(char s[], char c)


{
int i,j;
for(i=j=0; s[i]!=\0;i++)
if(s[i]!=c) s[j++]=s[i];
s[j]=\0;
}

main()
{
char niz[20];
char c;

printf("Unesi karakter\n\n");
scanf("%c", &c);

scanf("%s", niz);
squeeze(niz, c);
printf("%s\n", niz);
}
Primer 1.30.6 Obrtanje stringa i pretvaranje broja u string
#include <stdio.h>
#include <string.h>

/* reverse: obrce string, npr string "1234" postaje "4321" */


void reverse(char s[])

64
Milena VujosevicJanicic 1.30 Rad sa niskama karaktera

{
int c, i, j;

for (i = 0, j = strlen(s)-1; i < j; i++, j--)


{
c = s[i];
s[i] = s[j];
s[j] = c;
}
}

/* itoa: konvertuje broj n u niz karaktera s */


void itoa(int n, char s[])
{
int i, sign;

if ((sign = n) < 0) /* sacuvaj znak */


n = -n; /* napravi da je n pozitivno */
i = 0;
do {
/* generisanje cifara u obrnutom smeru */
s[i++] = n % 10 + 0; /* izracunaj sledecu cifru */
} while ((n /= 10) > 0); /* izbaci cifru iz zapisa */
if (sign < 0)
s[i++] = -;
s[i] = \0;
reverse(s);
}

main()
{
int n=-44;
char nst[100];
itoa(n,nst);
printf("%s\n",nst);
}
Primer 1.30.7 Konvertovanje stringa u broj u pokretnom zarezu.
#include <ctype.h>
#include <stdio.h>
#define MAXLINE 100

/* getline: get line into s, return length */

65
Milena VujosevicJanicic 1.30 Rad sa niskama karaktera

int getline(char s[], int lim)


{
int c, i;

i = 0;
while (--lim > 0 && (c=getchar()) != EOF && c != \n)
s[i++] = c;
if (c == \n)
s[i++] = c;
s[i] = \0;
return i;
}

/* atof: convert string s to double */


double atof(char s[])
{
double val, power;
int i, sign;

/* skip white space */


for (i = 0; isspace(s[i]); i++)
;

/* Postavlja se znak broja*/


sign = (s[i] == -) ? -1 : 1;

/* Preskace se jedno mesto ukoliko je bio upisan znak u broj*/


if (s[i] == + || s[i] == -)
i++;

/* Racuna se vrednost broja dok se ne naidje na tacku */


for (val = 0.0; isdigit(s[i]); i++)
val = 10.0 * val + (s[i] - 0);

if (s[i] == .)
i++;

/* Racuna se vrednost broja iza tacke*/


for (power = 1.0; isdigit(s[i]); i++)
{
val = 10.0 * val + (s[i] - 0);
power *= 10;
}

66
Milena VujosevicJanicic 1.30 Rad sa niskama karaktera

return sign * val / power;


}

/* Program sabira brojeve u pokretnom zarezu koji se unose sa ulaza*/


main()
{
double sum;
char line[MAXLINE];

sum = 0;
while (getline(line, MAXLINE) > 0)
printf("\t%g\n", sum += atof(line));
}
Primer 1.30.8 Program ucitava linije sa ulaza i pamti najduzu lin-
iju.
#include <stdio.h>
#define MAXLINE 1000 /* maximum input line length */

int getline(char line[], int maxline);


void copy(char to[], char from[]);

/* print the longest input line */


main()
{
int len; /* current line length */
int max; /* maximum length seen so far */
char line[MAXLINE]; /* current input line */
char longest[MAXLINE]; /* longest line saved here */

max = 0;
while ((len = getline(line, MAXLINE)) > 0)
if (len > max) {
max = len;
copy(longest, line);
}
if (max > 0) /* there was a line */
printf("%s", longest);
}

/* getline: read a line into s, return length */


int getline(char s[],int lim)
{

67
Milena VujosevicJanicic 1.30 Rad sa niskama karaktera

int c, i;

for (i=0; i < lim-1 && (c=getchar())!=EOF && c!=\n;++i)


s[i] = c;
if (c == \n) {
s[i] = c;
++i;
}
s[i] = \0;
return i;
}

/* copy: copy from into to;


assume to is big enough */
void copy(char to[], char from[])
{
int i;

i = 0;
while ((to[i] = from[i]) != \0)
++i;
}

Primer 1.30.9 btoi - konverzija iz datog brojnog sistema u dekadni.


#include <stdio.h>
#include <ctype.h>

/* Pomocna funkcija koja izracunava vrednost


koju predstavlja karakter u datoj osnovi
Funkcija vraca -1 ukoliko cifra nije validna.

Npr.
cifra B u osnovi 16 ima vrednost 11
cifra 8 nije validna u osnovi 6
*/

int digit_value(char c, int base)


{
/* Proveravamo obicne cifre */
if (isdigit(c) && c < 0+base)
return c-0;

68
Milena VujosevicJanicic 1.31 Linearna i binarna pretraga

/* Proveravamo slovne cifre za mala slova */


if (a<=c && c < a+base-10)
return c-a+10;

/* Proveravamo slovne cifre za velika slova */


if (A<=c && c < A+base-10)
return c-A+10;

return -1;
}

/* Funkcija izracunava vrednost celog broja koji je zapisan u datom


nizu karaktera u datoj osnovi.
*/
int btoi(char s[], int base)
{
int sum = 0;

/* Obradjuju se karakteri sve dok su to validne cifre */


int i, vr;
for (i = 0; (vr = digit_value(s[i], base)) != -1; i++)
sum = base*sum + vr;

return sum;
}

main()
{
char bin[] = "11110000";
char hex[] = "FF";

printf("Dekadna vrednost binarnog broja %s je %d\n", bin, btoi(bin, 2));


printf("Dekadna vrednost heksadekadnog
broja %s je %d\n", hex, btoi(hex, 16));
}

1.31 Linearna i binarna pretraga


Primer 1.31.1 Linearna pretraga
#include <stdio.h>

/* Funkcija proverava da li se dati element x nalazi

69
Milena VujosevicJanicic 1.31 Linearna i binarna pretraga

u datom nizu celih brojeva.


Funkcija vraca poziciju u nizu na kojoj je x pronadjen
odnosno -1 ukoliko elementa nema.
*/
int linearna_pretraga(int niz[], int br_elem, int x)
{
int i;
for (i = 0; i<br_elem; i++)
if (niz[i] == x)
return i;
/* nikako else return -1; !!!!*/
return -1;
}

main()
{
/* Inicijalizacija niza */
int a[] = {4, 3, 2, 6, 7, 9, 11};

/* Da bi smo odredili koliko clanova ima niz mozemo


koristiti operator sizeof*/
int br_elem = sizeof(a)/sizeof(int);
int x;
int i;

printf("Unesite broj koji trazimo : ");


scanf("%d",&x);

i = linearna_pretraga(a, br_elem, x);


if (i == -1)
printf("Element %d nije nadjen\n",x);
else
printf("Element %d je nadjen na poziciji %d\n",x, i);
}
Primer 1.31.2 Binarna pretraga niza iterativna verzija.
#include <stdio.h>

/* Funkcija proverava da li se element x javlja unutar niza


celih brojeva a.
Funkcija vraca poziciju na kojoj je element nadjen odnosno
-1 ako ga nema.

70
Milena VujosevicJanicic 1.31 Linearna i binarna pretraga

!!!!! VAZNO !!!!!


Pretpostavka je da je niz a uredjen rastuce po velicini
*/

int binarna_pretraga(int a[], int n, int x)


{
/* Pretrazujemo interval [l, d] */
int l = 0;
int d = n-1;

/* Sve dok interval [l, d] nije prazan */


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

/* Ispitujemo odnos x i a[srednjeg elementa] */


if (x == a[s])
/* Element je pronadjen */
return s;
else if (x < a[s])
{
/* Pretrazujemo interval [l, s-1] */
d = s-1;
}
else
{
/* Pretrazujemo interval [s+1, d] */
l = s+1;
}
}

/* Element nije nadjen */


return -1;
}

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

printf("Unesi element koji trazimo : ");

71
Milena VujosevicJanicic 1.32 Strukture

scanf("%d",&x);
i = binarna_pretraga(a, sizeof(a)/sizeof(int), x);

if (i==-1)
printf("Elementa %d nema u nizu!\n", x);
else
printf("Element %d je pronadjen na poziciji %d\n", x, i);
}

1.32 Strukture
Informacije kojima se opisuje realni svet retko se predstavljaju u
elementarnoj formi u vidu celih, realnih, znakovnih konstanti itd.
Mnogo cesce imamo posla sa slozenim objektima koji se sastoje od
elemenata raznih tipova. Na primer jednu osobu karakterisu ime,
prezime, datum i mesto rodenja.
Struktura predstavlja skup podataka kojim se opisuju neka bitna
svojstva objekta. Komponente koje obrazuju strukturu nazivaju se
elementi strukture.
Sintaksa strukture:

struct ime_strukture
{
tip ime_elementa1;
tip ime_elementa2;
...
};
Za svaki element strukture odvaja se odgovarajuci blok memorije.

Primer 1.32.1 Primer jednostavne strukture.


struct licnost
{
char ime[31];
char adresa[41];
unsigned starost;
};
Sada mozemo deklarisati dve osobe na sledeci nacin:
struct licnost osoba1, osoba2;
Kada imamo promenljivu strukturnog tipa tada elementima date
strukture pristupamo uz pomoc operatora ..

72
Milena VujosevicJanicic 1.32 Strukture

Primer 1.32.2
osoba1.starost=20;
osoba2.starost=21;
...
if (osoba1.starost == osoba2.starost)
printf("Osobe su iste starosti\n");

/* Sledece poredjenje poredi samo adrese


na kojima se nalaze imena osoba, i kako su
osobe na razlicitim adresama, pa time i njihova
imena, to znaci da ce rezultat ovog
poredjenja uvek biti "netacno"
if(osoba1.ime == osoba2.ime)
*/
/* Ispravno poredjenje imena je: */
if(strcmp(osoba1.ime, osoba2.ime) == 0)
printf("Osobe se isto zovu!\n");

Dozvoljeno je praviti nizove struktura. Na primer, niz od 20


elemenata koji sadrzi licnosti:
struct licnost nizLicnosti[20];
Tada da bi procitali starost neke licnosti u nizu pisemo:
nizLicnosti[5].starost
Moze se de nisati pokazivac na strukturu.
struct licnost *posoba;
Tada se pristupanje elementima strukture moze vrsiti upotrebom
operatora . na standardni nacin (upotreba zagrada je vazna zbog
prioriteta operatora):
(*posoba).ime
(*posoba).adresa
(*posoba).starost
ili koriscenjem specijalnog operatora 0
>0 na sledeci nacin:
posoba->ime
posoba->adresa
posoba->starost

Primer 1.32.3 Elementi strukture mogu da budu i druge strukture.

73
Milena VujosevicJanicic 1.33 Operator typedef

struct datum
{
unsigned dan;
unsigned mesec;
unsigned godina;
};

struct licnost
{
char ime[30];
struct datum datumrodjenja;
};
Sada se danu, mesecu i godini datuma rodjenja pristupa na sledeci
nacin:
osoba.datumrodjenja.dan = 10;
osoba.datumrodjenja.mesec = 5;
osoba.datumrodjenja.godina = 1986;

1.33 Operator typedef


Operator typedef omogucava nam da de nisemo nasa imena za neki
od osnovih ili izvedenih tipova. Na primer, mozemo da uradimo
sledece:
typedef double RealanBroj;
Nakon ovoga mozemo u tekstu deklarista promenljivu x kao Realan-
Broj, ona ce zapravo biti tipa double.
RealanBroj x; /* Umesto: double x;*/
Ili, ako zelimo da skratimo pisanje za neoznacene duge brojeve tj
za unsigned long int to mozemo da uradimo na sledeci nacin
typedef unsigned long int VelikiBroj;
Sada u kodu mozemo da koristimo VelikiBroj kao tip, na primer:
VelikiBroj x /* Umesto: unsigned long int x; */;
Operator typedef je narocito pogodan da bi se izbeglo ponavl-
jalnje reci struct pri deklarisanju strukturnih promenljivih.
typedef struct _licnost licnost;
Sada deklaracija moze da bude:

74
Milena VujosevicJanicic 1.34 Unije

licnost osoba1, osoba2;


/* umesto: struct _licnost osoba1, osoba2; */
Kao skracen zapis za
struct _tacka {
float x;
float y;
};

typedef struct _tacka tacka;


moze se koristiti:
typedef struct _tacka
{
float x;
float y;
} tacka;

Primer 1.33.1 Struktura artikal.


typedef struct _artikal
{
long bar_kod;
char ime[MAX_IME];
float pdv;
} artikal;

1.34 Unije
Unije se kreiraju koristeci kljucnu rec union a elementima unija se
pristupa uz pomoc operatora . (tacka). Osnovna razlika izmedu
unija i struktura je u tome sto unije koriste manju koicinu memorije
u odnosu na odgovarajuce strukture. Na primer, struktura koja ima
dva elementa, jedan tipa double i jedan tipa int zauzima 8+4=12
bajtova u memoriji dok odgovarajuca unija zauzima samo 8 bajtova.
To je zato sto se za uniju odvaja onoliko prostora koliko je potrebno
za najveci element unije, dok se u strukturi odvaja memorija za
svaki element pojedinacno. Usteda u memoriji se placa time sto
programer mora da vodi racuna na koji nacin u kom trenutku moze
da koristi uniju.
Primer 1.34.1
#include<stdio.h>

75
Milena VujosevicJanicic 1.35 Strukture primeri

typedef union num


{
double d;
int i;
} NUM;

main()
{
NUM n;
/* Nakon naredne dodele n.d ima vrednost 3.14*/
n.d = 3.14;

/* Nakon naredne dodele n.i ima vrednost 5.


Vrednost n.d (3.14) je prepisana vrednoscu 5
i n.d se ne moze ispravno koristiti sa desne
strane jednakosti. To je zato sto n.d i n.i
dele isti memorijski prostor.*/
n.i = 5;
}

1.35 Strukture primeri


Primer 1.35.1 Ulustracija deklaracije i inicijalizacije strukture.
#include <stdio.h>

/* Tacke su predstavljene sa dve koordinate.


Strukturom gradimo novi tip podataka. */
typedef struct _point
{
int x;
int y;
} point;

main()
{
/* Deklarisemo neinicijalizovanu tacku */
point a;

/* Deklarisemo i inicijalizujemo tacku b na (1,2) */


point b = {1, 2};

76
Milena VujosevicJanicic 1.35 Strukture primeri

/* Postavljamo vrednosti koordinata tacke a (posto ona


nije bila inicijalizovana prilikom deklaracije).*/
a.x = 0;
a.y = 0;

/* Ispisujemo velicinu strukture tacka */


printf("sizeof(point) = %d\n", sizeof(point));

/* Ispisujemo vrednosti koordinata tacaka */


printf("x koordinata tacke a je %d\n", a.x);
printf("y koordinata tacke a je %d\n", a.y);
printf("x koordinata tacke b je %d\n", b.x);
printf("y koordinata tacke b je %d\n", b.y);
}

Izlaz:
sizeof(point) = 8
x koordinata tacke a je 0
y koordinata tacke a je 0
x koordinata tacke b je 1
y koordinata tacke b je 2

Primer 1.35.2 Program omogucava unos tacaka sa standardnog ulaza


i izracunava kvadrate rastojanja svih tacaka od koordinatnog pocetka,
zbir kvadrata rastojanja i tacku koja je najdalja od koordinatnog
pocetka.
#include <stdio.h>

#define MAXDUZ 100

typedef struct _tacka


{
int x, y;
} tacka;

main()
{
tacka Tacke[MAXDUZ];

/*Brojac i velicina niza*/


int i, n;

77
Milena VujosevicJanicic 1.35 Strukture primeri

/*Pomocne promenljive za cuvanje trazenih vrednosti*/


int pozicija, maxRastojanje, kvRastojanje, zbir;

printf("Unesite broj tacaka (manji od %d):\n", MAXDUZ);


scanf("%d",&n);

/* Ucitava se niz tacaka*/


for(i=0; i<n; i++)
{
printf("Unesi x koordinatu %d. tacke\n", i+1);
scanf("%d", &Tacke[i].x);
printf("Unesi y koordinatu %d. tacke\n", i+1);
scanf("%d", &Tacke[i].y);
}

pozicija = 0;
maxRastojanje = 0;
zbir = 0;

/*Izracunavaju se trazene vrednosti*/


for(i=0; i<n; i++)
{
/*Racunamo kvadrat rastojanja tekuce tacke*/
kvRastojanje = Tacke[i].x*Tacke[i].x + Tacke[i].y*Tacke[i].y;
printf("Kvadrat rastojanja %d. tacke je %d\n", i+1, kvRastojanje);

/*Poredimo maksimalno rastojanje sa rastojanjem tekuce tacke */


if (kvRastojanje > maxRastojanje)
{
maxRastojanje = kvRastojanje;
pozicija = i;
}

/*Racunamo trazeni zbir*/


zbir += kvRastojanje;
}

/*Stampaju se trazene vrednosti*/


printf("Zbir kvadrata rastojanja je %d\n", zbir);
printf("Najdalja tacka od koordinatnog pocetka\n");
printf("je tacka (%d,%d)\n", Tacke[pozicija].x, Tacke[pozicija].y);
}

78
Milena VujosevicJanicic 1.35 Strukture primeri

/* Izlaz iz programa:
Unesite broj tacaka (manji od 100):
4
Unesi x koordinatu 1. tacke
1
Unesi y koordinatu 1. tacke
1
Unesi x koordinatu 2. tacke
0
Unesi y koordinatu 3. tacke
1
Unesi x koordinatu 3. tacke
2
Unesi y koordinatu 3. tacke
2
Unesi x koordinatu 4. tacke
1
Unesi y koordinatu 4. tacke
0
Kvadrat rastojanja 1. tacke je 2
Kvadrat rastojanja 2. tacke je 1
Kvadrat rastojanja 3. tacke je 8
Kvadrat rastojanja 4. tacke je 1
Zbir kvadrata rastojanja je 12
Najdalja tacka od koordinatnog pocetka
je tacka (2,2)
*/
Primer 1.35.3 Napisati funkcije koje izracunavaju povrsinu i obim
proizvoljnog poligona cija su temena zadatak kao nizovi tacaka i pro-
gram koji testira te funkcije i izracunava obim i povrvsinu trougla i
kvadrata.
#include <stdio.h>

/* Zbog funkcije sqrt. */


#include <math.h>

/* Upozorenje: pod linux-om je potrebno program prevoditi sa


gcc -lm primer.c
kada god se koristi <math.h>
*/

/* Tacke su predstavljene sa dve koordinate.

79
Milena VujosevicJanicic 1.35 Strukture primeri

Strukturom gradimo novi tip podataka. */


typedef struct _point
{
int x;
int y;
} point;

/* Izracunava duzinu duzi zadatu sa dve tacke */


float segment_length(point A, point B)
{
int dx, dy;
dx = A.x - B.x;
dy = A.y - B.y;
return sqrt(dx*dx + dy*dy);
}

/* Izracunava povrsinu trougla Heronovim obrascem.


Argumenti funkcije su tri tacke koje predstavljaju
temena trougla */
float Heron(point A, point B, point C)
{
/* Duzine stranica */
float a = segment_length(B, C);
float b = segment_length(A, C);
float c = segment_length(A, B);

/* Poluobim */
float s = (a+b+c)/2;
return sqrt(s*(s-a)*(s-b)*(s-c));
}

/* Izracunava obim poligona. Argumenti funkcije su niz tacaka


koje predstavljaju temena poligona kao i njihov broj */
float obimPoligona(point polygon[], int num)
{
int i;
float obim = 0.0;

/* Dodajemo duzine stranica koje spajaju susedna temena */


for (i = 0; i<num-1; i++)
obim += segment_length(polygon[i], polygon[i+1]);

/* Dodajemo duzinu stranice koja spaja prvo i poslednje teme */

80
Milena VujosevicJanicic 1.35 Strukture primeri

obim += segment_length(polygon[num-1], polygon[0]);

return obim;
}

/* Izracunava povsinu konveksnog poligona. Argumenti funkcije


su niz tacaka koje predstavljaju temena poligona kao i njihov
broj */
float area(point polygon[], int num)
{
/* Povrsina */
float a = 0.0;
int i;

/* Poligon delimo na trouglove i posebno izracunavamo


povrsinu svakoga od njih */
for (i = 1; i < num -1; i++)
a += Heron(polygon[0], polygon[i], polygon[i+1]);

return a;
}

main()
{
/* Definisemo dva poligona: trougao i kvadrat. */

/* triangle je niz od tri tacke - trougao (0,0), (0,1), (1,0)


inicijalizaciju vrsimo naknadno */
point triangle[3];

/* square je niz od cetiri tacke - jedinicni kvadrat.


Obratiti paznju na nacin inicijalizacije niza struktura */
point square[4] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}};

/* Gradimo trougao (0,0), (0,1), (1,0) */


triangle[0].x = 0; triangle[0].y = 0;
triangle[1].x = 0; triangle[1].y = 1;
triangle[2].x = 1; triangle[2].y = 0;

/* Stampamo obim trougla i obim kvadrata. */


printf("Obim trougla je %f\n", obimPoligona(triangle, 3));
printf("Obim kvadrata je %f\n", obimPoligona(square, 4));

81
Milena VujosevicJanicic 1.35 Strukture primeri

/* Stampamo povrsine trougla i kvadrata. */


printf("Povrsina trougla je %f\n",
Heron(triangle[0], triangle[1], triangle[2]));

/* Broj tacaka je moguce odrediti i putem sizeof */


printf("Povrsina kvadrata je %f\n",
area(square, sizeof(square)/sizeof(point)));
}
Izlaz:
Obim trougla je 3.414214
Obim kvadrata je 4.000000
Povrsina trougla je 0.500000
Povrsina kvadrata je 1.000000
Primer 1.35.4 Napisati program koji izracunava broj pojavljivanja
imena u datoteci koja se preusmeravanjem ucitava sa standardnog
ulaza i na standardni izlaz stampa ono ime koje se pojavilo najveci
broj puta. Razmatrati pojavljivanja sledecih imena Jelena, Ivana,
Milena, Ruzica, Ana, Milos, Petar, Janko i Pedja.
Program pokrecemo sa
a.out < datoteka.txt
da bi odredili koje se ime pojavilo najveci broj puta u datoteci datoteka.txt
(odnosno, vrsimo preusmeravanje standardnog ulaza).
#include <stdio.h>
#include <ctype.h>
#include <string.h>

/* Velicina reci. */
#define SIZE 100

typedef struct _ime


{
char rec[SIZE];
int broj_pojavljivanja;
} ime;

/* Funkcija get_word ucitava narednu rec sa standardnog ulaza.


Pretpostavlja se da je za s rezervisana dovoljna kolicina memorije.
Funkcija vraca poslednji procitan karakter ili EOF
*/
int get_word(char s[])
{

82
Milena VujosevicJanicic 1.35 Strukture primeri

int c, i = 0;

/* Preskoci blanko znake */


while (((c=getchar())!=EOF) && isspace(c))
;

/* Ako je doslo do kraja datoteke a nije ucitana rec


vrati EOF. */
if (c == EOF)
return c;

/* Upisuje se prvi karakter u rec. */


s[i++] = c;

/* Ucitava se i ostatak reci */


while (((c=getchar())!=EOF) && !isspace(c))
s[i++] = c;
s[i] = \0;
return c;
}

main()
{
ime niz[] = { {"Jelena", 0}, {"Ivana", 0}, {"Milena", 0},
{"Ruzica", 0}, {"Ana", 0}, {"Milos", 0},
{"Petar", 0}, {"Janko", 0}, {"Pedja", 0}
};

char s[SIZE]; /* Tekuca ucitana rec. */


int c, i, max, pozicija;

/* Ucitava se jedna po jedna rec*/


while ((c = get_word(s)) != EOF)
{
/* Proverava se da li je ucitana rec ime*/
for (i=0; i < sizeof(niz)/sizeof(ime); i++)
if ((strcmp(s, niz[i].rec) == 0))
{
/* Ukoliko je u pitanju trazeno ime, povecava se
njen broj pojavljivanja. */
niz[i].broj_pojavljivanja++;
break;
}

83
Milena VujosevicJanicic 1.35 Strukture primeri

max = 0;
pozicija = 0;
/* Izracunava se maksimalan broj pojavljivanja. */
for (i=0; i < sizeof(niz)/sizeof(ime); i++)
if (niz[i].broj_pojavljivanja > max)
{
max = niz[i].broj_pojavljivanja;
pozicija = i;
}

printf("Makslimalan broj pojavljivanja je: %d, za ime %s\n",


niz[pozicija].broj_pojavljivanja, niz[pozicija].rec);
}
Primer 1.35.5 Napisati program koji izracunava broj pojavljivanja
svake od reci u datoteci koja se preusmeravanjem ucitava sa stan-
dardnog ulaza. Program treba da odstampa broj pojavljivanja svake
od reci i da odstampa posebno onu rec koja se pojavila najveci broj
puta. Pretpostaviti da reci nisu duze od 30 karaktera i da u datoteci
nece biti vise od 500 razlicitih reci.
#include<stdio.h>
#include<ctype.h>
#include<string.h>

typedef struct _rec


{
char ime[30];
int brpoj;
} rec;

/*Funkcija koja ucitava jednu rec*/


int getword(char s[])
{
int c, i=0;
while (((c=getchar())!=EOF) && isspace(c));

if (c==EOF) return c;

s[i++]=c;

while (((c=getchar())!=EOF) && !isspace(c))

84
Milena VujosevicJanicic 1.35 Strukture primeri

s[i++]=c;

s[i]=\0;
return c;
}

main()
{
char s[30];
rec r[500];
int i,c,max, pozicija;
int n=0; /*Broj elemenata u nizu reci*/

/*Ucitava se jedna po jedna rec*/


while ((c=getword(s))!=EOF)
{
/*Proverava se da li dati niz sadrzi ucitanu rec*/
for(i=0;i<n;i++)
/*Ukoliko pronadjemo rec, povecavamo njen brojac*/
if (strcmp(s,r[i].ime)==0)
{
(r[i].brpoj)++;
break;
}

/*Ukoliko rec nismo pronasli*/


if(i==n)
{
/*Dodajemo je u niz i postavljamo njen
brojac na 1*/
strcpy(r[n].ime,s);
r[n].brpoj=1;
/*Povecavamo tekuci broj elemenata niza*/
n++;
}
}

/*Izracunava se maksimalan broj pojavljivanja*/


max=r[0].brpoj;
printf("rec: %s se pojavila: %d puta\n",r[0].ime, r[0].brpoj);
for(i=1;i<n;i++)
{
if (r[i].brpoj>max)

85
Milena VujosevicJanicic 1.36 Datoteke

{
max=r[i].brpoj;
pozicija = i;
}
printf("rec: %s se pojavila %d puta\n",r[i].ime,r[i].brpoj);
}
printf("Max broj pojavljivanja je %d za rec %s",max.r[pozicija].ime);
}

1.36 Datoteke
Primer 1.36.1 Program demonstrira otvaranje datoteka ("r" - read
i "w" - write mod) i osnovne tehnike rada sa datotekama.
/* U datoteku se upisuje prvih 10 prirodnih
brojeva, a zatim se iz iste datoteke
citaju brojevi dok se ne stigne do kraja i
ispisuju se na standardni izlaz */

#include <stdio.h>
#include <stdlib.h>

main()
{
int i;

/* Otvaramo datoteku sa imenom podaci.txt za pisanje */


FILE* f = fopen("podaci.txt", "w");

/* Ukoliko otvaranje nije uspelo, fopen vraca NULL.


U tom slucaju, prijavljujemo gresku i zavrsavamo program */
if (f == NULL)
{
printf("Greska prilikom otvaranja datoteke podaci.txt za pisanje\n");
exit(1);
}

/* Upisujemo u datoteku prvih 10 prirodnih brojeva


(svaki u posebnom redu) */
for (i = 0; i<10; i++)
fprintf(f, "%d\n", i);

/* Zatvaramo datoteku */

86
Milena VujosevicJanicic 1.36 Datoteke

fclose(f);

/* Otvaramo datoteku sa imenom podaci.txt za citanje */


f = fopen("podaci.txt", "r");

/* Ukoliko otvaranje nije uspelo, fopen vraca NULL.


U tom slucaju, prijavljujemo gresku i zavrsavamo program */
if (f == NULL) {
printf("Greska prilikom otvaranja datoteke podaci.txt za citanje\n");
exit(1);
}

/* Citamo brojeve iz datoteke dok ne stignemo do kraja i ispisujemo ih


na standardni izlaz */
while(1) {
int br;
/* Pokusavamo da procitamo broj */
fscanf(f, "%d", &br);

/* Ukoliko smo dosli do kraja datoteke, prekidamo */


if (feof(f))
break;

/* Ispisujemo procitani broj */


printf("Procitano : %d\n", br);
}

/* Funkciju feof ne treba pozivati pre pokusaja citanja.


Sledeci kod moze dovesti do greske:
while (!feof(f))
fscanf(f,"%d",&br);
*/

/* Zatvaramo datoteku */
fclose(f);
}
Pokazivaci stdin, stdout i stderr su de nisani u okviru stdio.h
i mogu se koristiti za pisanje na standardni ulaz, izlaz i izlaz za
gresku.
FILE* stdin;
FILE* stdout;
FILE* stderr;

87
Milena VujosevicJanicic 1.36 Datoteke

Primer 1.36.2 Program demonstrira a - append mod datoteka -


nadovezivanje.
#include <stdio.h>
#include <stdlib.h>

main()
{
FILE* datoteka;

/* Otvaramo datoteku za nadovezivanje


i proveravamo da li je doslo do greske */
if ( (datoteka=fopen("dat.txt","a"))==NULL)
{
/*Funkcija fprintf u odnosu na funkciju printf ima
jedan argument vise --- prvi argument je pokazivac
na datoteku u koju treba upisati poruku*/
fprintf(stderr,"Greska prilikom otvaranja dat.txt\n");

/*exit je funkcija iz biblioteke stdlib koja omogucava


trenutno zaustavljanje rada programa*/
exit(1);
}

/* Upisujemo sadrzaj u datoteku */


fprintf(datoteka,"Zdravo svima\n");

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

Primer 1.36.3 Program kopira sadrzaj datoteke ulaz.txt u da-


toteku izlaz.txt.
#include <stdio.h>
#include <stdlib.h>

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

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


{

88
Milena VujosevicJanicic 1.36 Datoteke

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


exit(1);
}

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


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

/*Funkcija fgetc ucitava iz datoteke jedan karakter.


Funkcija fputc upisuje jedan karakter u datoteku. */
while ((c=fgetc(in)) != EOF)
fputc(c,out);

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

89
Programiranje 2
Programski jezik C
Zadaci sa vezbi

Milena Vujosevic - Janicic 2008/2009


Predgovor

Ovo je prateci materijal za vezbe koje drzim iz predmenta Programiranje 2. On ne


moze zameniti pohadanje vezbi niti koriscenje druge preporucene literature.
Deo materijala cine zadaci i resenja mr Filipa Marica (raspolozivi na
www.matf.bg.ac.yu/~filip/pp/0405/index.pl).
Takode koriscen je i materijal sa sajta koleginice Jelene Grmuse
www.matf.bg.ac.yu/~jelenagr
kolege Miroslava Marica
www.matf.bg.ac.yu/~maricm
i kolege Milana Bankovica
www.matf.bg.ac.yu/~milan.
Tekstovi i objasnjenja su uglavnom zasnovani na knjizi Programski jezik C, autora
Kerninghan & Ritchie.
Zahvaljujem svojim studentima na aktivnom ucescu u nastavi cime su mi pomogli
u uoblicavanju ovog materijala.
Svi komentari i sugestije vezane za ovaj materijal bice veoma dobrodosli.

Milena Vujosevic-Janicic
www.matf.bg.ac.yu/~milena

1
Sadrzaj

1 Argumenti komandne linije 4

2 Datoteke 7

3 Bitski operatori 19

4 Vezbanje 30
4.1 Polinomi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
4.2 Veliki brojevi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

5 Sortiranje 40
5.1 Vremenska slozenost . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
5.2 Selection sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
5.3 Bubble sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
5.4 Insertion sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
5.5 Razni zadaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

6 Pokazivaci 58
6.1 Pokazivacka aritmetika primeri . . . . . . . . . . . . . . . . . . . . 59
6.2 Niska karaktera i pokazivac na konstantnu nisku . . . . . . . . . . . . 64
6.3 Pokazivaci na pokazivace . . . . . . . . . . . . . . . . . . . . . . . . . 65
6.4 Nizovi pokazivaca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

7 Rekurzija 69
7.1 Osnovni primeri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
7.2 Binarna pretraga . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
7.3 MergeSort algoritam . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
7.4 QuickSort algoritam . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

8 Pokazivaci na funkcije 86
8.1 Funkcija qsort iz standardne biblioteke . . . . . . . . . . . . . . . . . 89
8.2 Funkcija bsearch iz standardne biblioteke . . . . . . . . . . . . . . . 93
8.3 Funkcije lsearch i lfind . . . . . . . . . . . . . . . . . . . . . . . . 97
8.4 Pokazivaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97

2
SADRZAJ SADRZAJ

9 Dinamicka alokacija memorije 99


9.1 Matrice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
9.2 Realokacija memorije . . . . . . . . . . . . . . . . . . . . . . . . . . . 114

10 Liste 118
10.1 Implementacija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
10.2 Kruzna (ciklicna) lista . . . . . . . . . . . . . . . . . . . . . . . . . . 143
10.3 Red . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
10.4 Stek . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
10.5 Dvostruko povezane liste . . . . . . . . . . . . . . . . . . . . . . . . . 160

11 Stabla 166
11.1 Binarno pretrazivacko stablo . . . . . . . . . . . . . . . . . . . . . . . 167

12 Grafovi 209

3
Glava 1

Argumenti komandne linije

Primer 1.1 Argumenti komandne linije programa.


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

#include <stdio.h>

/* Imena ovih promenljivih mogu biti proizvoljna.


Npr:
main (int br_argumenata, char** argumenti);
ipak, uobicajeno je da se koriste sledeca imena:
main(int argc, char** argv)
Cesto se koristi i sledeca (ekvivalentna) notacija
main(int argc, char* argv[])
*/

main(int argc, char* argv[])


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

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


for (i = 0; i<argc; i++)
printf("argv[%d] = %s\n", i, argv[i]);
}

Primer 1.2 Program ispisuje opcije navedene u komandnoj liniji.


/* Opcije se navode koriscenjem znaka -, pri cemu je moguce da

4
Milena VujosevicJanicic Argumenti komandne linije

iza jednog znaka - sledi i nekoliko opcija.


Npr. za
a.out -abc -d -fg dat.txt -vxy
su prisutne opcije a b c d f g */

#include <stdio.h>
main(int argc, char** argv)
{
/* Za svaki argument komande linije, pocevsi od argv[1]
(preskacemo ime programa) */
int i;
for (i = 1; i < argc; i++)
{
/* Ukoliko i-ti argument pocinje crticom */
if (argv[i][0] == -)
{
/* Ispisujemo sva njegova slova pocevsi od pozicije 1 */
int j;
for (j = 1; argv[i][j] != \0; j++)
printf("Prisutna je opcija : %c\n", argv[i][j]);
}
/* Ukoliko ne pocinje crticom, prekidamo */
else
break;
}
}
Izlaz:
Prisutna opcija : a
Prisutna opcija : b
Prisutna opcija : c
Prisutna opcija : d
Prisutna opcija : f
Prisutna opcija : g
Primer 1.3 Program ispisuje opcije navedene u komandnoj liniji. K&R resenje.
#include <stdio.h>

/* Resnje se intenzivno zasniva na pokazivackoj aritmetici


i prioritetu operatora */
main(int argc, char** argv)
{
char c;
/* Dok jos ima argumenata i dok je karakter na poziciji
0 upravo crtica */
while(--argc>0 && (*++argv)[0]==-)

5
Milena VujosevicJanicic Argumenti komandne linije

/* Dok god ne dodjemo do kraja tekuceg stringa */


while (c=*++argv[0])
printf("Prisutna opcija : %c\n",c);
}

6
Glava 2

Datoteke

Primer 2.1 Program demonstrira otvaranje datoteka ("r" - read i "w" - write mod)
i osnovne tehnike rada sa datotekama.
/* U datoteku se upisuje prvih 10 prirodnih
brojeva, a zatim se iz iste datoteke
citaju brojevi dok se ne stigne do kraja i
ispisuju se na standardni izlaz */

#include <stdio.h>
#include <stdlib.h>

main()
{
int i;

/* Otvaramo datoteku sa imenom podaci.txt za pisanje */


FILE* f = fopen("podaci.txt", "w");

/* Ukoliko otvaranje nije uspelo, fopen vraca NULL.


U tom slucaju, prijavljujemo gresku i zavrsavamo program */
if (f == NULL)
{
printf("Greska prilikom otvaranja datoteke podaci.txt za pisanje\n");
exit(1);
}

/* Upisujemo u datoteku prvih 10 prirodnih brojeva


(svaki u posebnom redu) */
for (i = 0; i<10; i++)
fprintf(f, "%d\n", i);

/* Zatvaramo datoteku */

7
Milena VujosevicJanicic Datoteke

fclose(f);

/* Otvaramo datoteku sa imenom podaci.txt za citanje */


f = fopen("podaci.txt", "r");

/* Ukoliko otvaranje nije uspelo, fopen vraca NULL.


U tom slucaju, prijavljujemo gresku i zavrsavamo program */
if (f == NULL) {
printf("Greska prilikom otvaranja datoteke podaci.txt za citanje\n");
exit(1);
}

/* Citamo brojeve iz datoteke dok ne stignemo do kraja i ispisujemo ih


na standardni izlaz */
while(1) {
int br;
/* Pokusavamo da procitamo broj */
fscanf(f, "%d", &br);

/* Ukoliko smo dosli do kraja datoteke, prekidamo */


if (feof(f))
break;

/* Ispisujemo procitani broj */


printf("Procitano : %d\n", br);
}

/* Funkciju feof ne treba pozivati pre pokusaja citanja.


Sledeci kod moze dovesti do greske:
while (!feof(f))
fscanf(f,"%d",&br);
*/

/* Zatvaramo datoteku */
fclose(f);
}
Pokazivaci stdin, stdout i stderr su de nisani u okviru stdio.h i mogu se
koristiti za pisanje na standardni ulaz, izlaz i izlaz za gresku.
FILE* stdin;
FILE* stdout;
FILE* stderr;
Primer 2.2 Program demonstrira a - append mod datoteka - nadovezivanje.
#include <stdio.h>

8
Milena VujosevicJanicic Datoteke

#include <stdlib.h>

main()
{
FILE* datoteka;

/* Otvaramo datoteku za nadovezivanje


i proveravamo da li je doslo do greske */
if ( (datoteka=fopen("dat.txt","a"))==NULL)
{
/*Funkcija fprintf u odnosu na funkciju printf ima
jedan argument vise --- prvi argument je pokazivac
na datoteku u koju treba upisati poruku*/
fprintf(stderr,"Greska prilikom otvaranja dat.txt\n");

/*exit je funkcija iz biblioteke stdlib koja omogucava


trenutno zaustavljanje rada programa*/
exit(1);
}

/* Upisujemo sadrzaj u datoteku */


fprintf(datoteka,"Zdravo svima\n");

/* Zatvaramo datoteku */
fclose(datoteka);
}
Primer 2.3 Program kopira sadrzaj datoteke ulaz.txt u datoteku izlaz.txt.
#include <stdio.h>
#include <stdlib.h>

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

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


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

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


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

9
Milena VujosevicJanicic Datoteke

exit(1);
}

/*Funkcija fgetc ucitava iz datoteke jedan karakter.


Funkcija fputc upisuje jedan karakter u datoteku. */
while ((c=fgetc(in)) != EOF)
fputc(c,out);

/* Zatvaramo datoteke */
fclose(in);
fclose(out);
}
Primer 2.4 Program kopira n puta sadrzaj datoteke ulaz.txt u datoteku izlaz.txt.
#include <stdio.h>
#include <stdlib.h>

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

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


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

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


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

printf("Unesi prirodan broj\n");


scanf("%d", &n);

for(i=0; i<n; i++)


{
/* Prepisuje se sadrzaj datoteke*/
while ((c=fgetc(in)) != EOF)
fputc(c,out);

/* in se pozicionira na pocetak datoteke*/


rewind(in);

10
Milena VujosevicJanicic Datoteke

}
/* Zatvaramo datoteke */
fclose(in);
fclose(out);
}
Primer 2.5 Program ilustruje rad sa datotekama. Program kopira datoteku cije se
ime zadaje kao prvi argument komandne linije u datoteku cije se ime zadaje kao
drugi argument komandne linije. Uz svaku liniju se zapisuje i njen redni broj.
#include <stdio.h>
#include <stdlib.h>

#define MAX_LINE 256

/* Funkcija fgets definisana je u stdio.h

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

fgets ucitava najvise sledecih n-1 znakova


u polje niza karaktera s, zaustavljajuci se
ako naidje na novu liniju koju takodje
upisuje u polje. Na kraju upisuje \0.
Funkcija vraca s ili NULL ako dodje do kraja
datoteke ili se pojavi greska.

Funkcija fputs definisana je u stdio.h

int fputs(char *s, FILE *stream)

fputs upisuje nisku s u datoteku na koju


pokazuje stream, vraca nenegativnu vrednost ili
EOF ako se pojavi greska
*/

main(int argc, char* argv[])


{

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

if (argc != 3) {
fprintf(stderr,"Neispravna upotreba programa!\n
Pravilna upotreba:
%s ulazna_datoteka izlazna_datoteka\n",argv[0]);

11
Milena VujosevicJanicic Datoteke

exit(1);
}

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


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

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


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

line_num = 1;

/* Citamo liniju po liniju sa ulaza*/


while (fgets(line, MAX_LINE, in) != NULL)
{
/* Ispisujemo broj linije i sadrzaj linije na izlaz */
fprintf(out, "%d :\t", line_num++);
fputs(line, out);
}

/* Zatvaramo datoteke */
fclose(in);
fclose(out);
}
Primer 2.6 Prodavnica - ilustruje citanje niza struktura iz tektsualne datoteke.
/* Datoteka, cije se ime zadaje kao argument komandne linije
ili ako se ne zada onda se ime unosi sa standardnog
ulaza, sadrzi podatke o proizvodima koji se prodaju
u okviru odredjene prodavnice. Svaki
proizvod se odlikuje sledecim podacima:
bar-kod - petocifreni pozitivan broj
ime - niska karaktera
cena - realan broj zaokruzen na dve decimale
pdv - stopa poreza - realan broj zaokruzen na dve decimale
Pretpostavljamo da su podaci u datoteci
korektno zadati.
Pretpostavljamo da se u prodavnici ne
prodaje vise od 1000 razlicitih artikala
Na standardni izlaz ispisujemo podatke o

12
Milena VujosevicJanicic Datoteke

svim proizvodima koji se prodaju u prodavnici.

Zadatak je moguce resiti i bez koriscenja nizova


(i takvo resenje je bolje). */

#include <stdio.h>
#include <stdlib.h>

/* Maksimalna duzina imena proizvoda */


#define MAX_IME 30

/* Maksimalni broj artikala */


#define MAX_ARTIKALA 1000

/* Struktura za cuvanje podataka o jednom artiklu */


typedef struct _artikal {
int bar_kod;
char ime[MAX_IME];
float cena;
float pdv;
} artikal;

/* Ucitava podatke o jednom artiklu iz date datoteke.


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

/* Ukoliko smo dosli do kraja datoteke prilikom pokusaja ucitavanja


prijavljujemo neuspeh */
if (feof(f))
return 0;

/* Prijavljujemo uspeh */
return 1;
}

/* Izracunava ukupnu cenu datog artikla */


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

13
Milena VujosevicJanicic Datoteke

/* Ispisuje podatke o svim artiklima */


void ispisi_artikle(artikal artikli[], int br_artikala)
{
int i;
for (i = 0; i<br_artikala; i++)
printf("%-5d %-10s %.2f %.2f = %.2f\n",
artikli[i].bar_kod, artikli[i].ime,
artikli[i].cena, artikli[i].pdv,
cena(artikli[i]));
}

main(int argc, char* argv[])


{
FILE* f;

/* Niz struktura u kome se cuvaju podaci o artiklima */


artikal artikli[MAX_ARTIKALA];

/* Broj trenutno ucitanih artikala */


int br_artikala;

/* Ukoliko nije navedeno ime kao argument komandne linije, trazimo


od korisnika da ga unese */
if (argc<2) {
/* Ucitavamo ime datoteke */
char ime_datoteke[256];
printf("U kojoj datoteci se nalaze podaci o proizvodima: ");
scanf("%s", ime_datoteke);

/* Otvaramo datoteku i proveravamo da li smo uspeli */


if ( (f = fopen(ime_datoteke, "r")) == NULL)
{
printf("Greska prilikom otvaranja datoteke %s\n", ime_datoteke);
exit(1);
}
}
/* Ime datoteke je prvi argument komandne linije */
else {
/* Otvaramo datoteku i proveravamo da li smo uspeli */
if ( (f = fopen(argv[1], "r")) == NULL)
{
printf("Greska : datoteka %s ne moze biti otvorena\n", argv[1]);
exit(1);
}

14
Milena VujosevicJanicic Datoteke

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

/* Ispisujemo podatke o svim artiklima */


ispisi_artikle(artikli, br_artikala);

/* Zatvara se datoteka*/
fclose(f);
}
Primer 2.7 Program u datoteku cije se ime zadaje kao prvi argument komandne
linije upisuje prvih N prirodnih brojeva (N se zadaje sa standardnog ulaza) i zatim
izracunava duzinu datoteke u bajtovima.
#include <stdio.h>
#include <stdlib.h>

/*Deklaracija funkcije za racunanje duzine datoteke*/


long filesize(FILE *f);

void main()
{
FILE *f;
int i, n;

/* Ukoliko nije navedeno ime datoteke kao


argument komandne linije, zavrsavamo rad programa*/
if (argc<2)
{
printf("Program se pokrece sa a.out ime_datoteke!\n");
exit(1);
}

/* Otvaramo datoteku i proveravamo da li smo uspeli */


if ( (f = fopen(argv[1], "w+")) == NULL)
{
printf("Greska: datoteka %s ne moze biti otvorena\n", argv[1]);
exit(1);
}

printf("Unesi prirodan broj\n");


scanf("%d", &n);

15
Milena VujosevicJanicic Datoteke

/* Upisuje se sadrzaj u datoteku*/


for(i=0; i<n; i++)
fprintf(f, "%d ", i);

printf("Velicina datoteke je %ld bajtova\n", filesize(f));


fclose(f);
}

/*Funkcija koja racuna duzinu datoteke*/


long filesize(FILE *f)
{
long trenutna_pozicija, duzina;

/*Funkcija ftell vraca trenutnu poziciju u datoteci*/


/*Pamti se trenutna pozicija da bismo
mogli na nju da se vratimo*/
trenutna_pozicija = ftell(f);

/* Funkcija fseek se pozicionira na odredjeno


mesto u datoteci i ima sledece argumente
1. FILE* f - datoteka sa kojom se radi
2. int offset - rastojanje u bajtovima
od odgovarajuce pozicije
3. int origin - pozicija u odnosu na koju se gleda offset
i moze da ima vrednost jedne od
sledecih konstanti
SEEK_END - kraj
SEEK_SET - pocetak
SEEK_CUR - trenutna pozicija */

/*pozicioniranje na kraj fajla*/


fseek(f, 0, SEEK_END);

/*uzimamo poziciju u broju bajtova od


pocetka fajla, to je duzina*/
duzina = ftell(f);

/*vracamo se nazad na zapamcenu poziciju*/


fseek(f, trenutna_pozicija, SEEK_SET);
return duzina;
}

Primer 2.8 Napisati program koji u datoteci cije se ime zadaje kao prvi argument

16
Milena VujosevicJanicic Datoteke

komandne linije zamenjuje sva pojavljivanja niske koja se zadaje kao drugi argument
komandne linije niskom koja se zadaje kao treci argument komandne linije (pret-
postaviti da ce obe niske iste duzine i da nisu duze od 20 karaktera). Na primer, ako
se program pokrene sa
a.out datoteka.txt ana Ana
tada se svako pojavljivanje reci ana u datoteci datoteka.txt zamenjuje sa Ana.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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


{
FILE *f;
int c;
int i;
long pos;
int duzina;
char rec1[20];
char rec2[20];

/* Ukoliko nisu navedeni odgovarajuci


argumenti program se zavrsava */
if (argc<4)
{
printf("Program se pokrece sa a.out datoteka rec zamena!\n");
exit(1);
}

/* Otvaramo datoteku i proveravamo da li smo uspeli */


if ( (f = fopen(argv[1], "r+")) == NULL)
{
printf("Greska: datoteka %s ne moze biti otvorena\n", argv[1]);
exit(1);
}

/*Prepisujemo argumente komandne linije u rec1 i rec2*/


strcpy(rec1, argv[2]);
strcpy(rec2, argv[3]);

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


{
/*ako smo naisli na prvi karakter niske*/
if (c == rec1[0])
{

17
Milena VujosevicJanicic Datoteke

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


duzina = strlen(rec1);

/*petlja koja prepoznaje rec*/


for(i=1; i<duzina; i++)
/*ako se karakteri ne poklapaju izlazimo iz petlje
if (rec1[i]!=fgetc(f))
break;

/*ako je bila pronadjena cela rec prepisujemo


je zamenom*/
if (i==duzina)
{
/*vracamo se na pocetak reci da bismo je prepisali
fseek(f,pos-1,SEEK_SET);
for(i=0; rec2[i]; i++)
fputc(rec2[i], f);
fseek(f,0,SEEK_CUR); /*pozicionira na tu poziciju
(jer inace fputc smatra da upisuje
na kraj fajla pa fseek pocisti taj
fleg*/
}
else
/*vracamo se na pocetak reci ali iza prvog slova*/
fseek(f, pos, SEEK_SET);
}
}
fclose(f);
}

18
Glava 3

Bitski operatori

Bitski operatori su operatori koji deluju nad bitovima i vazno je razlikovati ih od


logickih operatora.
& bitsko AND
| bitsko OR
^ bitsko ekskluzivno OR
<< levo pomeranje
>> desno pomeranje
~ jedinicni komplement
Primer 3.1 Demonstracija bitskih operatora
#include <stdio.h>

main()
{ printf("%o %o\n",255,15);
printf( "255 & 15 = %d\n", 255 & 15 );
printf( "255 | 15 = %d\n", 255 | 15 );
printf( "255 ^ 15 = %d\n", 255 ^ 15 );
printf( "2 << 2 = %d\n", 2 << 2 );
printf( "16 >> 2 = %d\n", 16 >> 2 );
}

Izlaz iz programa je:


377 17
255 & 15 = 15
255 | 15 = 255
255 ^ 15 = 240
2 << 2 = 8
16 >> 2 = 4
Primer 3.2 print bits - stampa bitove u zapisu datog celog broja x.
#include <stdio.h>

19
Milena VujosevicJanicic Bitski operatori

/* Funkcija stampa bitove datog celog broja x.


Vrednost bita na poziciji i je 0 ako i
samo ako se pri konjunkciji broja x sa maskom
000..010....000 - sve 0 osim 1 na poziciji i,
dobija 0.
Funkcija krece od pozicije najvece tezine
kreirajuci masku pomeranjem jedinice u levo
za duzina(x) - 1 mesto, i zatim pomerajuci
ovu masku za jedno mesto u levo u svakoj
sledecoj iteraciji sve dok maska ne postane 0.
*/

void print_bits(int x)
{
/* Broj bitova tipa unsigned */
int wl = sizeof(int)*8;

unsigned mask;
for (mask = 1<<wl-1; mask; mask >>= 1)
putchar(x&mask ? 1 : 0);

putchar(\n);
}

main()
{
print_bits(127);
print_bits(128);
print_bits(0x00FF00FF);
print_bits(0xFFFFFFFF);
}

Izlaz iz programa:
00000000000000000000000001111111
00000000000000000000000010000000
00000000111111110000000011111111
11111111111111111111111111111111
Primer 3.3 Program proverava da li se na k-tom mestu broja n nalazi bit koji ima
vrednost 1.
#include <stdio.h>

/* Pozicije brojimo kao u sledecem primeru:


poz: ... 10 9 8 7 6 5 4 3 2 1 0

20
Milena VujosevicJanicic Bitski operatori

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

main()
{
int n,k;
printf("Unesite broj i poziciju tog broja koju zelite da proverite:\n");
scanf("%d%d",&n,&k);
if ((n & (1 << k))!=0)
printf("Bit je 1\n");
else
printf("Bit je 0\n");
}
Primer 3.4 Program postavlja na k-to mesto broja n bit 1.
#include <stdio.h>

void print_bits(int x)
{
/* Broj bitova tipa unsigned */
int wl = sizeof(int)*8;

unsigned mask;
for (mask = 1<<wl-1; mask; mask >>= 1)
putchar(x&mask ? 1 : 0);

putchar(\n);
}

main(){
int n,k;
printf("Unesite broj i poziciju tog broja koju zelite da postavite na 1:\n");
scanf("%d%d",&n,&k);
printf("Binarno, uneseni broj je\n");
print_bits(n);
printf("Novi broj je %d\n",(n |(1<<k)));
printf("Binarno, novi broj je\n");
print_bits((n |(1<<k)));
}
Izrazom a>>b vrsi se pomeranje sadrzaja operanda a predstavljenog u binarnom
obliku za b mesta u desno. Popunjavanje upraznjenih mesta na levoj strani zavisi od
tipa podataka i vrste racunara. Ako se pomeranje primenjuje nad operandom tipa
unsigned popunjavanje je nulama. Ako se radi o oznacenom operandu popunjavanje
je jedinicama kada je u krajnjem levom bitu jedinica, a nulama kada je u krajnjem
levom bitu nula.

21
Milena VujosevicJanicic Bitski operatori

Da li vazi sledeca jednakost (za prirodan broj k):


((~0) >> k) == (~0)?
Posto je 0 konstanta celobrojnog tipa, to je ~0 takodje tipa int, pri cemu je to
broj koji je zapisan svim jedinicama. Prema tome, njegovim siftovanjem u desno
dobijamo isti taj broj, jer se upraznjen prostor sa desne strane popunjava jedinicama.
VAZNO:
Vrednost izraza a<<b je jednaka vrednosti a 2b .
Vrednost izraza a>>b je jednaka vrednosti a/2b .
Bitovski operatori su e kasniji od operacija * i / tako da svaki put kad se javi
potreba za mnozenjem ili deljenjem stepenom broja dva, treba koristiti operacije <<
i >>.
Primer 3.5 sum of bits - izracunava sumu bitova datog neoznacenog broja.
#include <stdio.h>

/* Pomocna funkcija - stampa bitove neoznacenog broja */


void print_bits(unsigned x)
{
int wl = sizeof(unsigned)*8;

unsigned mask;
for (mask = 1<<wl-1; mask; mask >>= 1)
putchar(x&mask ? 1 : 0);

putchar(\n);
}

int sum_of_bits(unsigned x)
{
int br;
for (br = 0; x; x>>=1)
if (x&1)
br++;

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

unsigned mask;
for (mask = 1<<wl-1; mask; mask >>= 1)
if(x&mask) br++ ;
*/
return br;
}

22
Milena VujosevicJanicic Bitski operatori

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

Izlaz iz programa:
Binarni zapis broja 127 je
00000000000000000000000001111111
Suma bitova broja 127 je 7
Binarni zapis broja 128 je
00000000000000000000000010000000
Suma bitova broja 128 je 1
Binarni zapis broja 0x00FF00FF je
00000000111111110000000011111111
Suma bitova broja 0x00FF00FF je 16
Binarni zapis broja 0xFFFFFFFF je
11111111111111111111111111111111
Suma bitova broja 0xFFFFFFFF je 32
Primer 3.6 get_bits, set_bits, invert_bits - izdvajanje, postavljanje i inver-
tovanje pojedinacnih bitova.
#include <stdio.h>

/* Pomocna funkcija - stampa bitove neoznacenog broja */


void print_bits(unsigned x)
{
int wl = sizeof(unsigned)*8;

unsigned mask;
for (mask = 1<<wl-1; mask; mask >>= 1)
putchar(x&mask ? 1 : 0);

putchar(\n);
}

23
Milena VujosevicJanicic Bitski operatori

/* Funkcija vraca n bitova broja x koji pocinju na poziciji p */


unsigned get_bits(unsigned x, int p, int n)
{
/* Gradimo masku koja ima poslednjih n jedinica
0000000...00011111
tako sto sve jedinice ~0 pomerimo u levo za n mesta
1111111...1100000
a zatim komplementiramo
*/
unsigned last_n_1 = ~(~0 << n);

/* x pomerimo u desno za odgovarajuci broj mesta, a zatim


konjunkcijom sa konstruisanom maskom obrisemo pocetne cifre */

return (x >> p+1-n) & last_n_1;


}

/* Funkcija vraca modifikovano x tako sto mu je izmenjeno n bitova


pocevsi od pozicije p i na ta mesta je upisano poslednjih n bitova
broja y */
unsigned set_bits(unsigned x, int p, int n, unsigned y)
{
/* Maska 000000...000111111 - poslednjih n jedinica */
unsigned last_n_1 = ~(~0 << n);

/* Maska 1111100..000111111 - n nula pocevsi od pozicije p */


unsigned middle_n_0 = ~(last_n_1 << p+1-n);

/* Brisemo n bitova pocevsi od pozicije p */


x = x & middle_n_0;

/* Izdvajamo poslednjih n bitova broja y i pomeramo ih


na poziciju p */
y = (y & last_n_1) << p+1-n;

/* Upisujemo bitove broja y u broj x i vracamo rezultat */


return x | y;
}

/* Invertuje n bitova broja x pocevsi od pozicije p */


unsigned invert_bits(unsigned x, int p, int n)
{
/* Maska 000000111...1100000 - n jedinica pocevsi od pozicije p */

24
Milena VujosevicJanicic Bitski operatori

unsigned middle_n_1 = ~(~0 << n) << p+1-n;

/* Invertujemo koristeci ekskluzivnu disjunkciju */


return x ^ middle_n_1;
}

main()
{
unsigned x = 0x0AA0AFA0;
print_bits(x);

print_bits(get_bits(x, 15, 8));


print_bits(set_bits(x, 15, 8, 0xFF));
print_bits(invert_bits(x, 15, 8));
}

Izlaz iz programa:
00001010101000001010111110100000
00000000000000000000000010101111
00001010101000001111111110100000
00001010101000000101000010100000
Primer 3.7 right_rotate_bits, mirror_bits - rotiranje i simetrija bitova.
#include <stdio.h>

/* Pomocna funkcija - stampa bitove neoznacenog broja */


void print_bits(unsigned x)
{
int wl = sizeof(unsigned)*8;

unsigned mask;
for (mask = 1<<wl-1; mask; mask >>= 1)
putchar(x&mask ? 1 : 0);

putchar(\n);
}

/* Funkcija vrsi rotaciju neoznacenog broja x za n pozicija u desno */


unsigned right_rotate(unsigned x, int n)
{
int i;
int wl = sizeof(unsigned)*8;

/* Postupak se ponavlja n puta */


for (i = 0; i < n; i++)

25
Milena VujosevicJanicic Bitski operatori

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

/* x pomeramo za jedno mesto u desno */


x >>= 1;

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

x |= last_bit<<wl-1;
}

return x;
}

/* Funkcija obrce binarni zapis neoznacenog broja x tako sto bitove


cita unatrag */
unsigned mirror(unsigned x)
{
int i;
int wl = sizeof(unsigned)*8;

/* Rezultat inicijalizujemo na poslednji bit broja x */


unsigned y = x & 1;

/* Postupak se ponavlja wl-1 puta */


for (i = 1; i<wl; i++)
{
/* x se pomera u desno za jedno mesto */
x >>= 1;
/* rezultat se pomera u levo za jedno mesto */
y <<= 1;

/* Poslednji bit broja x upisujemo na poslednje


mesto rezultata */
y |= x & 1;
}
return y;
}

main()
{
unsigned x = 0xFAF0FAF0;
print_bits(x);

26
Milena VujosevicJanicic Bitski operatori

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

Izlaz iz programa:
11111010111100001111101011110000
00001111010111110000111101011111
00111110101111000011111010111100
Primer 3.8 Promeljiva c je tipa char. Sta ce biti vrednost promenljive c posle izraza
dodele
 c=(15|3)>>1;?
 c=(15 & 3)<<1; ?
Primer 3.9 Napisati program koji sa standardnog ulaza uccitava pozitivan ceo broj,
a na standardni izlaz ispisuje vrednost tog broja sa razmenjenim vrednostima bitova
na pozicijama i, j. Pozicije i, j se ucitavaju kao parametri komandne linije. Sma-
trati da je krajnji desni bit binarne reprezentacije 0-ti bit. Pri resavanju nije dozvol-
jeno koristiti pomocni niz niti aritmeticke operatore +,-,/,*,%.
#include <stdio.h>
#include <stdlib.h>

int razmeni(unsigned n, unsigned i, unsigned j)


{
int rezultat = n;

/* Broj bitova tipa unsigned */


int wl = sizeof(int)*8;

unsigned mask_i = (1 << i);


unsigned mask_j = (1 << j);

if(n & mask_i)


/* Ako je na i-tom mestu 1, upisujemo
to na j-to mesto*/
rezultat |= mask_j;
/* Ako je na i-tom mestu 0, upisujemo
to na j-to mesto*/
else
rezultat &= ~mask_j;

if(n & mask_j)


/* Ako je na j-tom mestu 1, upisujemo
to na i-to mesto*/

27
Milena VujosevicJanicic Bitski operatori

rezultat |= mask_i;
/* Ako je na j-tom mestu 0, upisujemo
to na i-to mesto*/
else
rezultat &= ~mask_i;

return rezultat;
}

int main(int argc, char** argv)


{
unsigned n, i, j, m;
if(argc < 3)
{
fprintf(stderr, "Neispravna upotreba programa!\n");
exit(1);
}

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

/* Racunaju se brojevi na osnovu argumenata


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

m = razmeni(n, i, j);

printf("Broj nastao razmenom bitova (%u, %u) broja %u je %u\n",


i, j, n, m);
return 0;
}
Primer 3.10 Napisati funkciju koja prima ceo broj n i ispisuje razliku broja jedinica
na parnim i neparnim pozicijama u binarnom zapisu broja n.
PRIMER: za n = 19 = (10011)2 izlaz je 1.
Napisati program koji pozivom ove funkcije racuna i stampa razliku broja jedinica
za sve argumente komandne linije (pretpostavka je da su argumenti komandne linije
zadati korektno).
#include <stdio.h>
#include <stdlib.h>

int par_nepar(int n)
{

28
Milena VujosevicJanicic Bitski operatori

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


int br1_nepar = 0;

/* Broj bitova tipa unsigned */


int wl = sizeof(int)*8;
unsigned mask=1;
char par = 1;
for( ; mask; mask <<= 1)
{
if(mask&n)
if(par) br1_par++; /* if(par) rezultat++; */
else br1_nepar++; /* else rezultat--; */
par = 1 - par;
}
return br1_par - br1_nepar; /* return rezultat;*/
}

main(int argc, char** argv)


{
unsigned n, i, m;
if(argc < 2)
{
fprintf(stderr, "Neispravna upotreba programa!\n");
exit(1);
}
for(i=1; i<argc; i++)
{
n = atoi(argv[i]);
m = par_nepar(n);
printf("Razlika jedinica na parnim i neparnim za broj %u je %d\n", n, m);
}
}

29
Glava 4

Vezbanje

4.1 Polinomi
Primer 4.1 Program ilustruje rad sa polinomima.
#include <stdio.h>
#include <math.h>
#define max(a, b) ((a) > (b) ? (a) : (b))

/*
* Polinom 3*x^3 + 2*x + 1.5 se predstavlja kao:
* stepen -> 3
* koeficijenti -> 1.5 2 0 3 x x x x x ... x
*/
typedef struct polinom
{
float koeficijenti[21];
int stepen;
} Polinom;

/*
* Funkcija vraca koeficijent uz x^i u polinomu p
* Zbog efikasnosti ne prenosimo celu strukturu vec
* samo pokazivac na strukturu.
*/
float vratiKoeficijent(Polinom* p, int i)
{
return i <= p->stepen ? p->koeficijenti[i] : 0.0f;
}

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

30
Milena VujosevicJanicic 4.1 Polinomi

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

/*
Ukoliko je stepen polinoma bio manji, postavljamo
sve koeficijente izmedju na 0.0 i uvecavamo stepen
*/
if (i > p->stepen)
{
for (j = p->stepen+1; j < i; j++)
p->koeficijenti[j] = 0.0f;
p->stepen = i;
}
p->koeficijenti[i] = k;
}

/*
* Funkcija kreira polinom datog stepena sa datim nizom
* koeficijenata. Pretpostavlja se da su koeficijenti
* u datom nizu koeficijenti[] uredjeni opadajuce po stepenima
* polinoma.
*/
Polinom napraviPolinom(int stepen, float koeficijenti[])
{
int i;
Polinom p;
p.stepen = stepen;
for (i = 0; i <= stepen; i++)
{
postaviKoeficijent(&p, i, koeficijenti[stepen - i]);
}
return p;
}

/*
* Funkcija ispisuje polinom u citljivijem obliku.
* Na primer: 3.0*x^3 + 0.0*x^2 + 2.0*x^1 + 1.5*x^0
*/
void ispisiPolinom(Polinom* p)
{
int i;
for (i = p->stepen; i >= 0; i--)

31
Milena VujosevicJanicic 4.1 Polinomi

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

/*
* Funkcija izracunava vrednost polinoma u tacki x
* Hornerovom shemom. Na primer,
* 3*x^3 + 2*x + 1.5 =
* (((0*x + 3)*x + 0)*x + 2)*x + 1.5
* Postupak izracunavanja p(10):
* 0.0
* 10 * 0.0 + 3 = 3.0
* 10 * 3.0 + 0 = 30.0
* 10 * 30.0 + 2 = 302.0
* 10 * 302.0 + 1.5 = 3021.5
*/
float vrednost(Polinom* p, float x)
{
int i;
float suma = 0.0f;
for (i = p->stepen; i >= 0; i--)
{
suma = suma*x + vratiKoeficijent(p, i);
}
return suma;
}

/*
* Funkcija sabira dva polinoma
*/
Polinom saberi(Polinom* p, Polinom* q)
{
int i;
Polinom zbir;
zbir.stepen = max(p->stepen, q->stepen);
for (i = 0; i <= zbir.stepen; i++)
postaviKoeficijent(&zbir, i,
vratiKoeficijent(p, i)
+ vratiKoeficijent(q, i));
return zbir;

32
Milena VujosevicJanicic 4.1 Polinomi

/*
* Funkcija mnozi dva polinoma. Na primer,
*
* 1*x^2 + 2*x + 3
* 4*x + 7
*
* 0.0*x^3 + 0.0*x^2 + 0.0*x + 0.0
* 0.0*x^3 + 0.0*x^2 + 0.0*x + 21.0 i=0 j=0
* 0.0*x^3 + 0.0*x^2 + 12.0*x + 21.0 i=0 j=1
* 0.0*x^3 + 0.0*x^2 + 26.0*x + 21.0 i=1 j=0
* 0.0*x^3 + 8.0*x^2 + 26.0*x + 21.0 i=1 j=1
* 0.0*x^3 + 15.0*x^2 + 26.0*x + 21.0 i=2 j=0
* 4.0*x^3 + 15.0*x^2 + 26.0*x + 21.0 i=2 j=1
*/
Polinom pomnozi(Polinom* p, Polinom* q)
{
int i, j;
Polinom proizvod;
proizvod.stepen = p->stepen + q->stepen;
for (i = 0; i <= proizvod.stepen; i++)
{
postaviKoeficijent(&proizvod, i, 0.0f);
}
for (i = 0; i <= p->stepen; i++)
{
for (j = 0; j <= q->stepen; j++)
{
/* r[i+j] = r[i+j] + p[i]*q[j] */
postaviKoeficijent(&proizvod, i+j,
vratiKoeficijent(&proizvod, i+j) +
vratiKoeficijent(p, i) * vratiKoeficijent(q, j));
}
}
return proizvod;
}
main()
{
float pkoeficijenti[] = {1.0f, 2.0f, 1.0f};
Polinom p = napraviPolinom(2, pkoeficijenti);
float qkoeficijenti[] = {1.0f, 1.0f};
Polinom q = napraviPolinom(1, qkoeficijenti);
Polinom r = pomnozi(&p, &q);

33
Milena VujosevicJanicic 4.2 Veliki brojevi

ispisiPolinom(&r);
}

4.2 Veliki brojevi


Primer 4.2 Program ilustruje rad sa velikim celim brojevima. Brojevi se interno
reprezentuju preko niza svojih cifara.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX_CIFRE 100

/* Funkcija obrce cifre prosledjenog niza */


void obrni_cifre (int cifre[], int duzina)
{
int i, j;
for (i=0, j=duzina-1; i<j; i++, j--)
{
int pom = cifre[i];
cifre[i] = cifre[j];
cifre[j] = pom;
}
}

/* Funkcija sa standardnog ulaza ucitava niz cifara, duzine


najvise max_cifre i smesta ga u niz brojeva cifre[]. Zatim
se niz cifre[] obrce kako bi cifre najmanje tezine bile
na pocetku niza.
Kao rezultat, funkcija vraca broj cifara ucitanog broja */
int uzmi_broj (int cifre[], int max_cifre)
{
int duzina = 0;
char c;
while ( --max_cifre>0 && isdigit(c=getchar()))
cifre[duzina++]=c-0;
obrni_cifre(cifre, duzina);
return duzina;
}

/* Funkcija ispisuje "veliki" broj predstavljen


nizom cifara cifre, duzine duzina, na standardni
izlaz imajuci u vidu da su cifre u nizu zapisane
"naopako" tj. pocevsi od cifre najmanje tezine */
void ispisi_broj(int cifre[],int duzina)

34
Milena VujosevicJanicic 4.2 Veliki brojevi

{
int i;
for (i=duzina-1; i>=0; i--)
printf("%d",cifre[i]);
putchar(\n);
}

/* Da li su dva broja data svojim nizovima cifara i duzinama jednaka?


Funkcija vraca 1 ako jesu, a 0 ako nisu */
int jednaki(int a[], int duzina_a, int b[], int duzina_b)
{
int i;
/* Poredimo duzine */
if (duzina_a != duzina_b)
return 0;

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


for (i=0; i<duzina_a; i++)
if (a[i] != b[i])
return 0;

return 1;
}

/* Funckija poredi dva broja a i b, data svojim nizovima cifara i duzinama


i vraca:
1 ako je a>b
0 ako je a=b
-1 ako je b>a
*/
int uporedi(int a[], int duzina_a, int b[], int duzina_b)
{
int i;
/* Uporedjujemo duzine brojeva a i b */
if (duzina_a > duzina_b)
return 1;
if (duzina_a < duzina_b)
return -1;
/* U ovom trenutku znamo da su brojevi iste duzine, tako da
prelazimo na poredjenje cifre po cifre, pocevsi od cifre
najvece tezine */
for (i=duzina_a-1; i>=0; i--)
{
if (a[i] > b[i])

35
Milena VujosevicJanicic 4.2 Veliki brojevi

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

/* Funkcija sabira dva broja data svojim nizovima cifara


i duzinama */
void saberi(int a[], int duzina_a, int b[], int duzina_b,
int rezultat[],
int* duzina_rezultata)
{
int i;

/* Prenos sa prethodne pozicije */


int prenos = 0;

/* Sabiranje vrsimo dok ne prodjemo sve cifre duzeg od brojeva a i b */


for(i=0; i<duzina_a || i<duzina_b; i++)
{
/* Sabiramo i-tu cifra broja a (ako postoji) sa i-tom cifrom
broja b (ako postoji) i prenos sa prethodne pozicije */
int cifra_rezulata = ((i<duzina_a)? a[i] : 0) +
((i<duzina_b)? b[i] : 0) +
prenos;

/* Nova cifra rezultata */


rezultat[i] = cifra_rezulata%10;

/* Prenos na sledecu poziciju */


prenos = cifra_rezulata/10;
}

/* Kada smo zavrsili sa svim ciframa brojeva a i b moguce je da je


postojao prenos na sledecu poziciju u kom slucaju uvecavamo duzinu
rezultata. Inace duzinu rezultata postavljamo na duzinu duzeg od
brojeva a i b, koja se nalazi trenutno u promenjivoj i */
if (prenos != 0)
{
if (i>=MAX_CIFRE)
{printf("Doslo je do prekoracenja!\n"); exit(1);}
else
{

36
Milena VujosevicJanicic 4.2 Veliki brojevi

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

return;
}

/* Funkcija mnozi broj, dat svojim nizom cifara i duzinom, datom cifrom c */
void pomnozi_cifrom (int a[], int duzina_a, int cifra,
int rezultat[],
int* duzina_rezultata)
{
int i, prenos = 0;

for (i=0; i<duzina_a; i++)


{
/* Svaku cifru broja a mnozimo cifrom c, dodajemo na to
prenos sa prethodne pozicije i to smestamo u promenljivu
pom */
int pom = a[i]*cifra + prenos;
/* Nova cifra rezultata */
rezultat[i] = pom%10;
/* Prenos na sledecu poziciju */
prenos = pom/10;
}

/* Kada smo zavrsili sa svim ciframa broja a, moguce je da je


postojao prenos na sledecu poziciju u kom slucaju uvecavamo
duzinu rezultata. Inace duzinu rezultata postavljamo na duzinu
broja a, koja se nalazi trenutno u promenjivoj i */
if (prenos != 0)
{
if (i>=MAX_CIFRE)
{printf("Doslo je do prekoracenja !\n"); exit(1);}
else
{
rezultat[i] = prenos;
*duzina_rezultata = duzina_a+1;
}
}
else

37
Milena VujosevicJanicic 4.2 Veliki brojevi

*duzina_rezultata = duzina_a;
}

/* Funkcija mnozi dva broja data svojim nizovima cifara i duzinama*/


void pomnozi (int a[], int duzina_a, int b[], int duzina_b,
int rezultat[],
int* duzina_rezultata)
{
/* Ova funkcija se gradi kombinovanjem algoritama mnozenja broja cifrom i
sabiranja dva broja */
int i,j,k;

/* Broj pom ce da sadrzi rezultat mnozenja broja a jednom po jednom


cifrom broja b, dok ce na broj rezultat da se dodaje svaki
put (10^i)*pom */
int pom[MAX_CIFRE], duzina_pom, prenos;

*duzina_rezultata = 0;

/*
b=351 * a=123
---------------
1 korak ===> rez: 351 * 3 = 1053
2 korak ===> 351 * 2 = 702
------------------
rez: 8073
3 korak ===> 351 * 1 = 351
------------------
rez: 43173
*/
/* Za svaku cifru broja a */
for (i=0; i<duzina_a; i++)
{
/* vrsimo mnozenje broja b i-tom cifrom broja a */
pomnozi_cifrom(b, duzina_b, a[i], pom, &duzina_pom);

/* Zatim dodajemo broj pom na rezultat, ali dodavanje pocinjemo od


i-te cifre rezultata.*/
prenos = 0;
for (k=0; k<duzina_pom; k++)
{
int pm=((i+k<*duzina_rezultata) ? rezultat[i+k] : 0) + pom[k] + prenos;
rezultat[i+k] = pm%10;
prenos = pm/10;

38
Milena VujosevicJanicic 4.2 Veliki brojevi

}
if (prenos)
{
rezultat[i+k] = prenos;
*duzina_rezultata = i+k+1;
}
else
*duzina_rezultata = i+k;
}
}

/* Primer koriscenja funkcija */


main()
{
/* duzina brojeva a i b */
int duzina_a, duzina_b;

/* nizovi cifara brojeva a i b */


int a[MAX_CIFRE], b[MAX_CIFRE], zbir[MAX_CIFRE], proizvod[MAX_CIFRE];

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

printf("Unesite drugi broj : ");


duzina_b = uzmi_broj(b, MAX_CIFRE);

/* Sabiraju se i ispisuje se zbir */


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

/* Mnoze se i ispisuje se proizvod */


pomnozi(a, duzina_a, b, duzina_b, proizvod, &duzina_proizvoda);
printf("Proizvod je : ");
ispisi_broj(proizvod, duzina_proizvoda);
}

39
Glava 5

Sortiranje

Niz moze biti sortiran ili uredjen u


 opadajucem poretku:
niz[0] > niz[1] > ... > niz[i] > niz[i + 1] > ... > niz[n 1]

 rastucem poretku:
niz[0] < niz[1] < ... < niz[i] < niz[i + 1] < ... < niz[n 1]

 neopadajucem poretku:
niz[0]  niz[1]  ...  niz[i]  niz[i + 1]  ...  niz[n 1]

 nerastucem poretku:
niz[0] niz[1] ... niz[i] niz[i + 1] ... niz[n 1]

U nastavku su dati primeri algoritama za sortiranje u nerastucem poretku celobro-


jnog niza. Jednostavnim modi kacijama svakim od ovih algoritama niz se moze
sortirati i u opadajucem, rastucem ili neopadajucem poretku.

5.1 Vremenska slozenost


Pogledati slike koje oslikavaju vremensku slozenost za razlicite algoritme i razlicite
nizove:
 Rezultati dobijeni za slucajno generisane nizove:
http://www.matf.bg.ac.yu/~filip/pp/0405/random-sort.gif
 Rezultati dobijeni za vec sortirane nizove:
http://www.matf.bg.ac.yu/~filip/pp/0405/sorted-sort.gif
 Rezultati dobijeni za naopako sortirane nizove:
http://www.matf.bg.ac.yu/~filip/pp/0405/reverse-sorted-sort.gif

40
Milena VujosevicJanicic 5.2 Selection sort

5.2 Selection sort


Primer 5.1 (Selection sort) U prvom prolazu se razmenjuju vrednosti a[0] sa
onim clanovima ostatka niza koji su veci od njega. Na taj nacin ce se posle prvog
prolaza kroz niz a[0] postaviti na najveci element niza. U svakom sledecem prolazu,
postavlja se na i-to mesto najveci element niza a[i], a[i+1] ... a[n-1].
Primer sortiranja:
n = 6 a: 1 3 5 2 6 8
-------------
i = 0 j = 1 => a: 3 1 5 2 6 8
i = 0 j = 2 => a: 5 1 3 2 6 8
i = 0 j = 3 => a: 5 1 3 2 6 8
i = 0 j = 4 => a: 6 1 3 2 5 8
i = 0 j = 5 => a: 8 1 3 2 5 6
-------------
i = 1 j = 2 => a: 8 3 1 2 5 6
i = 1 j = 3 => a: 8 3 1 2 5 6
i = 1 j = 4 => a: 8 5 1 2 3 6
i = 1 j = 5 => a: 8 6 1 2 3 5
...
#include<stdio.h>
#include<stdlib.h>

#define MAXDUZ 100

void selection(int a[], int n)


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

/*Sortiranje*/
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(a[i]<a[j])
{
pom=a[i];
a[i]=a[j];
a[j]=pom;
}
}

main()
{
/* Niz od maksimalno MAXDUZ elemenata*/

41
Milena VujosevicJanicic 5.2 Selection sort

int a[MAXDUZ];

/* Dimenzija niza, pomocna i brojacke promenljive */


int n,i;

printf("Unesite dimenziju niza\n");


scanf("%d",&n);

if (n>MAXDUZ)
{
printf("Nedozvoljena vrednost za n\n");
exit(1);
}

/* Unos clanova niza */


for(i=0; i<n; i++)
{
printf("Unesite %d. clan niza\n",i+1);
scanf("%d",&a[i]);
}

selection(a,n);

/* Ispis niza */
printf("Sortirani niz:\n");
for(i=0; i<n; i++)
printf("%d\t",a[i]);

putchar(\n);

}
Primer 5.2 (Selection sort2) Modifikacija prethodnog resenja radi dobijanja na
efikasnosti. Ne vrse se zamene svaki put vec samo jednom, kada se pronade odgo-
varajuci element u nizu sa kojim treba izvrsiti zamenu tako da u nizu bude postavljen
trenutno najveci element na odgovarajuce mesto.
Primer sortiranja:
n = 6 a: 1 3 5 2 6 8
-------------
i = 0 => a: 8 1 5 2 6 3
-------------
i = 1 => a: 8 6 5 2 1 3
-------------
i = 2 => a: 8 6 5 2 1 3
-------------

42
Milena VujosevicJanicic 5.3 Bubble sort

...
void selection2(int a[], int n)
{
int i, j, max;

/*Sortiranje - bez stalnih zamena vec se


pronalazi indeks trenutno najveceg clana niza*/
for(i=0; i<n-1; i++)
{
max = i;
for(j=i+1; j<n; j++)
if(a[max]<a[j])
max=j;

/* Vrsi se zamena onda kada na i-tom mestu


nije najveci element. Tada se na i-to mesto
postavlja najveci element koji se nalazio na
mestu ind. */
if(i != max)
{
pom=a[max];
a[max]=a[i];
a[i]=pom;
}
}
}

5.3 Bubble sort


Primer 5.3 (Bubble sort) Algoritam sortiranja buble sort poredi dva susedna el-
ementa niza i ako su pogresno rasporedeni zamenjuje im mesta. Posle poredenja
svih susednih parova najmanji od njih ce isplivati na kraj niza. Zbog toga se ovaj
metod naziva metod mehurica. Da bi se najmanji broj nesortiranog dela niza doveo
na svoje mesto treba ponoviti postupak.
Primer sortiranja:
n = 6 a: 1 3 5 2 6 8
-------------
i = 5 j = 0 => a: 3 1 5 2 6 8
i = 5 j = 1 => a: 3 5 1 2 6 8
i = 5 j = 2 => a: 3 5 2 1 6 8
i = 5 j = 3 => a: 3 5 2 6 1 8
i = 5 j = 4 => a: 3 5 2 6 8 1
-------------

43
Milena VujosevicJanicic 5.3 Bubble sort

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

void bubble(int a[], int n)


{
int i, j, pom;

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


for(j=0; j<i; j++)
if(a[j]<a[j+1])
{
pom=a[j];
a[j]=a[j+1];
a[j+1]=pom;
}
}
Primer 5.4 (Bubble sort 2) Unapredjujemo prethodni algoritam kako bismo obezbedli
da se ne vrse provere onda kada je niz vec sortiran nego da se u tom slucaju prekine
rad.
void bubble2(int a[], int n)
{
/* Promenljiva koja govori da li je izvrsena
zamena u i-tom prolazu kroz niz pa ako nije
sortiranje je zavrseno jer su svaka dva
susedna elementa niza u odgovarajucem poretku */
int zam;

zam=1;
for(i=n-1; zam && i>0; i--)
for(zam=0,j=0; j<i; j++)
if(a[j]<a[j+1])
{
/* Zamena odgovarajucih clanova niza */
pom=a[j];
a[j]=a[j+1];
a[j+1]=pom;

/* Posto je u i-tom prolazu


izvrsena bar ova zamena zam
se postavlja na 1 sto
nastavlja sortiranje */
zam=1;
}

44
Milena VujosevicJanicic 5.4 Insertion sort

5.4 Insertion sort


Primer 5.5 (Insertion sort) U svakom trenutku je pocetak niza sortiran, a sorti-
ranje se vrsi tako sto se jedan po jedan element niza sa kraja ubacuje na odgovarajuce
mesto.
Primer sortiranja:
n = 6 a: 1 3 5 2 6 8
-------------
i = 1 j = 1 => a: 3 1 5 2 6 8
-------------
i = 2 j = 2 => a: 3 5 1 2 6 8
i = 2 j = 1 => a: 5 3 1 2 6 8
-------------
i = 3 j = 3 => a: 5 3 2 1 6 8
-------------
i = 4 j = 4 => a: 5 3 2 6 1 8
...
void insertion(int a[], int n)
{
/* Pomocna i brojacke promenljive */
int pom,i,j;

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


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

Primer 5.6 (Insertion sort 2) Broj dodela se moze redukovati tako sto se umesto
stalnih zamena koristi dodela privremenoj promenljivoj elemente niza pomeramo
za jedno mesto sve dok ne nademo poziciju na koju treba da postavimo dati element
(koji je sacuvan u privremenoj promenljivoj).
void insertion2(int a[], int n)
{
int i, j, tmp;
for (i = 1; i < n; i++)
{
int tmp = a[i];

45
Milena VujosevicJanicic 5.5 Razni zadaci

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


a[j] = a[j-1];
}
a[j] = tmp;
}
}

5.5 Razni zadaci


Primer 5.7 Napisati funkciju koja od dva sortirana niza formira treci sortiran niz
(nizovi su sortirani neopadajucie).
#include <stdio.h>

/* Funkcija spaja dva uredjena niza:


a koji ima na elemenata i
b koji ima nb elemenata
i na osnovu njih gradi uredjeni niz c ciji
broj elemenata vraca.
Pretpostavlja se da u nizu c ima dovoljno prostora.
*/
int merge(int a[], int na, int b[], int nb, int c[])
{
/* Dok god ima elemenata u oba niza uzima se
manji od dva tekuca i prepisuje u niz c */
int i = 0, j = 0, k = 0;
while(i < na && j < nb)
{
if (a[i] < b[j])
c[k++] = a[i++];
else
c[k++] = b[j++];
}

/* Prepisujemo eventualno preostale elemente niza a */


for (; i < na; i++, k++)
c[k] = a[i];

/* Prepisujemo eventualno preostale elemente niza b */


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

return k;
}

46
Milena VujosevicJanicic 5.5 Razni zadaci

main() {
int a[] = {1, 5, 6, 9, 13};
int b[] = {2, 3, 7, 11, 12, 15};
int c[30];
int na = sizeof(a)/sizeof(int);
int nb = sizeof(b)/sizeof(int);
int nc = merge(a, na, b, nb, c);
int i;

for (i = 0; i < nc; i++)


printf("%d ", c[i]);
printf("\n");
}
Primer 5.8 Program ucitava niz studenata i sortira ih po njihovim ocenama.
#include <stdio.h>
#include <ctype.h>

#define MAX_IME 20

typedef struct _student


{
char ime[MAX_IME];
char prezime[MAX_IME];
int ocena;
} student;

/* Funkcija ucitava rec i vraca njenu duzinu ili


-1 ukoliko smo dosli do znaka EOF*/
int getword(char word[],int max)
{
int c, i=0;

while (isspace(c=getchar()))
;

while(!isspace(c) && c!=EOF && i<max-1)


{
word[i++]=c;
c = getchar();
}

word[i]=\0;

if (c==EOF) return -1;

47
Milena VujosevicJanicic 5.5 Razni zadaci

else return i;

/* Funkcija ucitava niz studenata, vraca duzinu niza koji ucita */


int UcitajPodatke(student studenti[], int max)
{
int i=0;
while(i<max && getword(studenti[i].ime, MAX_IME)>0)
{
if (getword(studenti[i].prezime, MAX_IME) < 0)
break;
scanf("%d",&studenti[i].ocena);
i++;
}
return i;
}

void IspisiPodatke(student studenti[], int br_studenata)


{
int i;
printf("IME PREZIME OCENA\n");
printf("--------------------------------------\n");
for (i=0; i<br_studenata; i++)
printf("%-20s %-20s %5d\n",studenti[i].
ime, studenti[i].prezime, studenti[i].ocena);
}

/* Sortiranje studenata po ocenama */


void SelectionSort(student studenti[], int br_studenata)
{
int i,j;
for (i=0; i<br_studenata-1; i++)
for (j=i; j<br_studenata; j++)
if (studenti[i].ocena<studenti[j].ocena)
{ student tmp=studenti[i];
studenti[i]=studenti[j];
studenti[j]=tmp;
}
}

main()
{
student studenti[100];

48
Milena VujosevicJanicic 5.5 Razni zadaci

int br_studenata = UcitajPodatke(studenti,100);

SelectionSort(studenti, br_studenata);
IspisiPodatke(studenti, br_studenata);
}
Primer 5.9 Program ucitava informacije o studentima iz datoteke cije se ime zadaje
iz komandne linije, i koja je u formatu:
n
prezime1 ime1 smer1 prosek1
prezime2 ime2 smer2 prosek2
...
prezimen imen smern prosekn
Studenti se sortiraju leksikografski po prezimenima i imenima, a zatim se njihovi
podaci tako sortirani ispisuju na izlaz, ili u izlazni fajl, ako je njegovo ime zadato u
komandnoj liniji.
#include <stdio.h>
#include <string.h>

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

#define MAX_STUDENATA 100

/* Struktura koja predstavlja informacije o studentu */


typedef struct student {

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

} Student;

/* Funkcija uporedjuje dva studenta po leksikografskom poretku


njihovih imena i prezimena. Funkcija vraca vrednost manju od
nule ako je prvi student "manji" od drugog, vrednost vecu
od nule ako je prvi student "veci" od drugog, dok nulu vraca
ako se studenti zovu isto. */
int uporedi(Student *s, Student *p)
{
int t;

49
Milena VujosevicJanicic 5.5 Razni zadaci

/* Najpre poredimo prezimena. Ako su prezimena ista, onda poredimo


i imena. */
if((t = strcmp(s->prezime, p->prezime)) != 0)
return t;
else
return strcmp(s->ime, p->ime);
}

/* Funkcija sortira niz studenata u leksikografskom poretku */


void sortiraj(Student studenti[], int n)
{
int i, j;
int min;
Student pom;

/* Studenti se porede funkcijom uporedi(). Zamena elemenata


niza se obavlja na uobicajen nacin, zato sto je dodela
struktura legitimna operacija i zato sto struktura ne
sadrzi pokazivace za koje je memorija alocirana dinamicki. */

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


{
min = i;
for (j = i + 1; j < n; j++)
if (uporedi(&studenti[j], &studenti[min]) < 0)
min = j;

if (min != i)
{
pom = studenti[i];
studenti[i] = studenti[min];
studenti[min] = pom;
}
}
}

/* Funkcija ucitava podatke o studentu */


void ucitaj(FILE *in, Student *s)
{
fscanf(in, "%s", s->prezime);
fscanf(in, "%s", s->ime);
fscanf(in, "%s", s->smer);

50
Milena VujosevicJanicic 5.5 Razni zadaci

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


}

/* Ispisujemo informacije o studentu */


void ispisi(FILE *out, Student *s)
{
fprintf(out, "%s %s %s %f\n", s->prezime, s->ime, s->smer, s->prosek);
}

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

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

/* Ako je korisnik uneo ime ulaznog fajla...*/


if(argc > 1)
if((in = fopen(argv[1], "r")) == NULL)
{
fprintf(stderr, "Greska prilikom otvaranja fajla!\n");
return 1;
}

/* Ako je korisnik uneo i ime izlaznog fajla...*/


if(argc > 2)
if((out = fopen(argv[2], "w")) == NULL)
{
fprintf(stderr, "Greska prilikom otvaranja fajla!\n");
return 1;
}

/* Ucitavamo broj studenata */


fscanf(in, "%d", &n);

/* Ucitavamo informacije o studentima */


for(i = 0; i < n; i++)
ucitaj(in, &studenti[i]);

/* Sortiramo niz studenata */


sortiraj(studenti, n);

/* Ispisujemo niz studenata */

51
Milena VujosevicJanicic 5.5 Razni zadaci

for(i = 0; i < n; i++)


ispisi(out, &studenti[i]);

fclose(in);
fclose(out);

return 0;
}
Primer 5.10 Program utvrduje da li su dve niske karaktera anagrami. Dve niske
su anagrami ako se sastoje od istog broja istih karaktera. Na primer, niske trave
i vetar jesu anagrami, dok vetar i vatra nisu.
#include <stdio.h>
#include <string.h>

#define MAX 1024

/* Funkcija sortira karaktere stringa s */


void sortiraj (char s[])
{
int i, j;
int min;
char pom;
int n;

/* Racunamo duzinu stringa */


for (n = 0; s[n] != \0; n++)
;

/* Ostatak funkcije je identican funkciji


za sortiranje celih brojeva. */
for (i = 0; i < n - 1; i++)
{
min = i;
for (j = i + 1; j < n; j++)
if (s[j] < s[min])
min = j;

if (min != i)
{
pom = s[i];
s[i] = s[min];
s[min] = pom;
}
}

52
Milena VujosevicJanicic 5.5 Razni zadaci

/* Funkcija utvrdjuje da li su reci s i t anagrami.


Za reci kazemo da su anagrami, ako se jedna rec
moze dobiti od druge premestanjem slova u reci */
int anagrami (char *s, char *t)
{
char sp[MAX];
char tp[MAX];

/* Kopiramo stringove (reci) u pomocne nizove sp i tp


zato sto ne zelimo da nasa funkcija promeni originalne
nizove. */
strcpy (sp, s);
strcpy (tp, t);

/* Sortiramo karaktere stringova u pomocnim nizovima */


sortiraj (sp);
sortiraj (tp);

/* Ako su stringovi nakon sortiranja jednaki, tada su polazne reci


bile anagrami */
return strcmp (sp, tp) == 0;
}

/* Test program */
int main ()
{

char s[MAX], t[MAX];

/* Ucitavamo dve reci */


printf ("Uneti prvu rec: ");
scanf ("%s", s);
printf ("Uneti drugu rec: ");
scanf ("%s", t);

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


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

53
Milena VujosevicJanicic 5.5 Razni zadaci

return 0;
}
Primer 5.11 Interpolaciona pretraga se moze porediti sa pretragom recnika:
ako neko trazi rec na slovo B, sigurno nece da otvori recnik na polovini, vec verovatno
negde blize pocetku.
/* Funkcija trazi u SORTIRANOM nizu a[] duzine n
broj x. Vraca indeks pozicije nadjenog elementa
ili -1, ako element nije pronadjen */
int interpolaciona_pretraga (int a[], int n, int x)
{
int l = 0;
int d = n - 1;
int s;

/* Dokle god je indeks l levo od indeksa d... */


while (l <= d)
{

/* Ako je element manji od pocetnog ili veci od poslednjeg


clana u delu niza a[l],...,a[d] tada nije u tom delu niza.
Ova provera je neophodna, da se ne bi dogodilo da se prilikom
izracunavanja indeksa s izadje izvan opsega indeksa [l,d]
*/
if(x < a[l] || x > a[d])
return -1;
/* U suprotnom, x je izmedju a[l] i a[d], pa ako su a[l] i a[d]
jednaki, tada je jasno da je x jednako ovim vrednostima, pa
vracamo indeks l (ili indeks d, sve jedno je).Ova provera je
neophodna, zato sto bismo inace prilikom izracunavanja s imali
deljenje nulom.
*/
else if(a[l] == a[d])
return l;

/* Indeks s je uvek izmedju l i d, ali ce


verovatno biti blize trazenoj vrednosti nego da
smo prosto uvek uzimali srednji element.*/
/* Racunamo sredisnji indeks */
s = l + ((double)(x - a[l]) / (a[d] - a[l])) * (d - l);

/* Ako je sredisnji element veci od x,


tada se x mora nalaziti u levoj polovini niza */
if (x < a[s])
d = s - 1;

54
Milena VujosevicJanicic 5.5 Razni zadaci

/* Ako je sredisnji element manji od x,


tada se x mora nalaziti u desnoj polovini niza
*/
else if (x > a[s])
l = s + 1;
else
/* Ako je sredisnji element jednak x,
tada smo pronasli x na poziciji s
*/
return s;
}

/* ako nije pronadjen vracamo -1 */


return -1;
}
Primer 5.12 Data su dva rastuca niza A i B, napisati funkciju koja formira niz C
koji sadrzi:
(a) zajednicke elemente nizova A i B (presek skupova A i B).
(b) elemente koje sadrzi niz A a ne sadrzi niz B (razlika skupova A i B).
(c) sve elemente koje sadrze nizovi A i B (unija skupova A i B) ovo je ekvivalentno
spajanju dva uredena niza primer 5.7.
/* Funkcija kreira presek dva rastuca niza a i b i rezultat smesta u
niz c (takodje u rastucem radosledu). Funkcija vraca broj elemenata
preseka */
int kreiraj_presek(int a[], int n_a, int b[], int n_b, int c[])
{
int i = 0, j = 0, k = 0;

/* Dokle god ima elemenata u oba niza... */


while (i < n_a && j < n_b)
{
/* Ako su jednaki, ubacujemo vrednost u presek,
i prelazimo na sledece elemente u oba niza. */
if(a[i] == b[j])
{
c[k++] = a[i];
i++;
j++;
}
/* Ako je element niza a manji, tada u tom nizu prelazimo
na sledeci element */
else if(a[i] < b[j])

55
Milena VujosevicJanicic 5.5 Razni zadaci

i++;
/* Ako je element niza b manji, tada u tom nizu prelazimo
na sledeci element */
else
j++;
}
/* Vracamo broj elemenata preseka */
return k;

/* Funkcija kreira razliku dva rastuca niza a i b i rezultat smesta u


niz c (takodje u rastucem radosledu). Funkcija vraca broj elemenata
razlike */
int kreiraj_razliku (int a[], int n_a, int b[], int n_b, int c[])
{
int i = 0, j = 0 , k = 0;

/* Sve dok ima elemenata u oba niza...*/


while(i < n_a && j < n_b)
{
/* Ako je tekuci element niza a manji, tada
je on u razlici, jer su svi sledeci elementi
niza b jos veci. Ubacujemo ga u razliku i
prelazimo na sledeci element niza a */
if(a[i] < b[j])
c[k++] = a[i++];
/* Ako je tekuci element niza b manji, tada
prelazimo na sledeci element u nizu b */
else if (a[i] > b[j])
j++;
/* Ako su jednaki, tada ih oba preskacemo. Tekuci
element niza a ocigledno nije u razlici. */
else
{
i++;
j++;
}
}

/* Ako su preostali elementi niza a, tada su oni u razlici


jer su svi elementi niza b bili manji od tekuceg elementa
niza a, i svih koji za njim slede */
while (i < n_a)

56
Milena VujosevicJanicic 5.5 Razni zadaci

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

/* Vracamo broj elemenata u razlici */


return k;
}

57
Glava 6

Pokazivaci

Pokazivac je promenljiva koja sadrzi adresu promenljive.


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

ip = &x; /* ip cuva adresu promenljive x, tj ip pokazuje na x */


y=*ip; /* y dobija vrednost onoga sto se nalazi na adresi koju
cuva promenljiva ip, tj posto ip cuva adresu promenljive
x, a x ima vrednost 1 to je i y sada 1 */
*ip = 0; /* preko pokazivaca njema se sadrzaj na adresi koju cuva ip,
prema tome, x je sada 0 */

*ip+=10; /* x je sada 10*/


++*ip; /* x je sada 11*/
(*ip)++; /* x je sada 12,
zagrada neophodna zbog prioriteta operatora*/
Pored pokazivaca na osnovne tipove, postoji i pokazivac na prazan tip void.
void *pp;
Njemu moze da se dodeli da pokazuje na int, char, float ili na bilo koji drugi tip
ali je neophodno eksplicitno naglasiti na koji tip ukazuje pokazivac svaki put kada
zelimo da koristimo sadrzaj adrese koju pokazivac cuva.
Primer 6.1 Upotreba pokazivaca na prazan tip.
#include<stdio.h>

main()
{
void *pp; /* Ovaj pokazivac moze da pokazuje na adrese
na kojima se nalaze razliciti tipovi
podataka. */
int x=2;

58
Milena VujosevicJanicic 6.1 Pokazivacka aritmetika primeri

char c=a;

pp = &x; /* Pokazivac sada sadrzi adresu promenljive tipa int*/


*(int *)pp = 17; /* x postaje 17, kroz pokazivac pp je
promenjena vrednost promenljive x.
Kastovanje (int *) ukazuje na to da se prilikom
citanja vrednosti koja se nalazi na
adresi koju cuva pokazivac pp, ovaj pokazivac
tretira kao pokazivac na tip int */
printf("Adresa od x je %p\n ", &x);
printf("%d i %p\n",*(int*)pp,(int * )pp);

pp = &c; /* Pokazivac sada sadrzi adresu promenljive tipa char*/


printf("Adresa od c je %p\n", &c);
printf("%c i %p\n",*(char*)pp,(char * )pp);
/* Kastovanje (char *) ukazuje na to da se prilikom
citanja vrednosti koja se nalazi na
adresi koju cuva pokazivac pp, ovaj pokazivac
tretira kao pokazivac na tip char */
}

/*
Adresa od x je 0012FF78
17 i 0012FF78
Adresa od c je 0012FF74
a i 0012FF74
*/

Posebna konstanta koja se koristi da se oznaci da pokazivac ne pokazuje na neko


mesto u memoriji je NULL. Ova konstanta je de nisana u biblioteci stdio.h i ima
vrednost 0.

6.1 Pokazivacka aritmetika primeri


Primer 6.2 Funkcija proverava da li se neka vrednost x nalazi u nizu niz dimenzije
n, bez koriscenja indeksiranja. Funkcija vraca pokazivac na poziciju pronadjenog
elementa ili NULL ukoliko element nije pronaden.

#include <stdio.h>

int* nadjiint(int* niz, int n, int x)


{
while (--n >= 0 && *niz != x)
niz++;

59
Milena VujosevicJanicic 6.1 Pokazivacka aritmetika primeri

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


}

main()
{
int a[]={1,2,3,4,5,6,7,8};
int* poz=nadjiint(a,sizeof(a)/sizeof(int),4);

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

Primer 6.3 Funkcije izracunavaju duzinu niske koriscenjem pokazivaca.


int string_length1(char *s)
{
int n;
for(n=0; *s != \0; s++)
n++;
return n;
}

/* Druga varijanta iste funkcije */


int string_length2(char *s)
{
char* t;
for (t = s; *t; t++)
;
return t - s;
}

Primer 6.4 Funkcija kopira string t u string s (podrazumeva se da je za string s


rezervisano dovoljno mesta).
void copy(char* dest, char* src)
{
while (*dest++=*src++)
;
}

/* Ovo je bio skraceni zapis za sledeci kod


while(*src != \0)
{
*dest=*src;
dest++;
src++;

60
Milena VujosevicJanicic 6.1 Pokazivacka aritmetika primeri

}
*dest = \0;
*/
Primer 6.5 Nadovezuje string t na kraj stringa s. Pretpostavlja da u s ima do-
voljno prostora.
void string_concatenate(char *s, char *t)
{
/* Pronalazimo kraj stringa s */
while (*s) /* while (*s != 0)*/
s++;
/* Nakon prethodne petlje, s pokazuje na \0, kopiranje
pocinje od tog mesta, tako da ce znak \0 biti prepisan. */
/* Kopiranje se vrisi slicno funkciji string_copy */
while (*s++ = *t++)
;
}
Primer 6.6 Funkcija strcmp vrsi leksikografsko poredenje dva stringa. Vraca:
0 ukoliko su stringovi jednaki
<0 ukoliko je s leksikografski ispred t
>0 ukoliko je s leksikografski iza t

int strcmp(char *s, char *t)


{
/* Petlja tece sve dok ne naidjemo
na prvi razliciti karakter */
for (; *s == *t; s++, t++)
if (*s == \0) /* Naisli smo na kraj
oba stringa, a nismo nasli razliku */
return 0;

/* *s i *t su prvi karakteri u kojima se niske


razlikuju. Na osnovu njihovog odnosa,
odredjuje se odnos stringova */

return *s - *t;
}
Primer 6.7 Pronalazi prvu poziciju karaktera c u stringu s, i vraca pokazivac na
nju, odnosno NULL ukoliko s ne sadrzi c.
char* string_char(char *s, char c)
{

61
Milena VujosevicJanicic 6.1 Pokazivacka aritmetika primeri

int i;
for (; *s; s++)
if (*s == c)
return s;

/* Nije nadjeno */
return NULL;
}

Primer 6.8 Pronalazi poslednju poziciju karaktera c u stringu s, i vraca pokazivac


na nju, odnosno NULL ukoliko s ne sadrzi c.
char* string_last_char(char *s, char c)
{
char *t = s;
/* Pronalazimo kraj stringa s */
while (*t)
t++;

/* Krecemo od kraja i trazimo c unazad */


for (t--; t >= s; t--)
if (*t == c)
return t;

/* Nije nadjeno */
return NULL;
}

Primer 6.9 Za svaku liniju ucitanu sa ulaza proverava se da li sadrzi rec zdravo.
#include <stdio.h>

/* Proverava da li se niska t nalazi unutar niske s


Vraca poziciju na kojoj string pocinje odnosno
-1 ukoliko niska t nije podniska niske s. */
int sadrzi_string(char s[], char t[])
{
int i;
for (i = 0; s[i]; i++)
{
int j;
for (j=0, k=0; s[i+j]==t[j]; j++)
if (t[j+1]==\0)
return i;
}
return -1;

62
Milena VujosevicJanicic 6.1 Pokazivacka aritmetika primeri

/* Proverava da li string str sadrzi string sub.


Vraca pokazivac na kojoj sub pocinje,
odnosno NULL ukoliko ga nema. */
char* string_string(char *str, char *sub)
{
char *s, *t;

/* Proveravamo da li sub pocinje na svakoj poziciji i */


for (; *str; str++)
/* Poredimo sub sa str pocevsi od pozicije na koju ukazuje
str sve dok ne naidjemo na razliku */
for (s = str, t = sub; *s == *t; s++, t++)
/* Nismo naisli na razliku a ispitali smo sve
karaktere niske sub */
if (*(t+1) == \0)
return str;

/* Nije nadjeno */
return NULL;
}

/* Cita liniju sa stadnardnog ulaza i vraca njenu duzinu */


int getline(char* line, int max)
{
char *s=line;
int c;
while ( max-->0 && (c=getchar())!=\n && c!=EOF)
*s++ = c; /* ekvivalentno sa *s=c; s++; */

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

*s = \0;
return s - line;
}

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

63
Milena VujosevicJanicic 6.2 Niska karaktera i pokazivac na konstantnu nisku

printf("%s",linija);
}

6.2 Niska karaktera i pokazivac na konstantnu nisku


Prilikom deklaracije treba praviti razliku izmedu niza znakova i pokazivaca na kon-
stantnu nisku. Ukoliko su date deklaracije:
char poruka[]="danas je lep dan!";
char *pporuka = "danas je lep dan!";
tada vazi:
 poruka je niz znakova koji sadrzi tekst danas je lep dan!. Pojedine znake
moguce je promeniti, na primer, nakon naredbe
poruka[0] = D;
poruka ce sadrzati tekst Danas je lep dan!. Niska poruka se uvek odnosi na
novo mesto u memoriji.
 pporuka je pokazivac, koji je inicijalizovan da pokazuje na konstantnu nisku,
on moze biti preusmeren da pokazuje na nesto drugo, na primer, moguce je
preusmeriti ovaj pokazivac sledecom naredbom
pporuka = poruka;
i u ovom slucaju ce pokazivac pporuka pokazivati na mesto u memoriji na
kojem se nalazi poruka. Pokusaj modi kacije elementa niske karaktera na koju
ukazuje pporuka nije de nisan (jer je to konstantna niska). Na primer, rezultat
naredbe pporuka[0]=D je nede nisan.
Ako deklarisemo
char *pporuka1 = "danas je lep dan!";
char *pporuka2 = "danas je lep dan!";
char *pporuka3 = "danas pada kisa";
tada ce pokazivaci pporuka1 i pporuka2 pokazivati na isto mesto u memoriji, a
pporuka3 na drugo mesto u memoriji.
Ako uporedimo
(pporuka1==pporuka3)
uporedice se vrednosti pokazivaca. Ako uporedimo
(pporuka1 < pporuka2)
uporedice se vrednosti pokazivaca. Ako dodelimo
pporuka1=pporuka3
tada ce pporuka1 dobiti vrednost pokazivaca pporuka3 i pokazivace na isto mesto
u memoriji. Nece se izvrsiti kopiranje sadrzaja memorije.
Primer 6.10 Nakon deklaracije
char a[] = "informatika";
char *p = "informatika";

64
Milena VujosevicJanicic 6.3 Pokazivaci na pokazivace

 Loliko elemenata ima niz a?


 Koju vrednost ima a?
 Da li se moze promeniti vrednost a?
 Koju vrednost ima a[0]?
 Da li se moze promeniti vrednost a[0]?
 Koju vrednost ima p?
 Da li se moze promeniti vrednost p?
 Koju vrednost ima p[0]?
 Da li se moze promeniti vrednost p[0]?

6.3 Pokazivaci na pokazivace


Pokazivacke promenljive su podaci kao i svi drugi, pa samim tim imaju svoju adresu
u memoriji. Zbog toga je moguce govoriti o pokazivacima na pokazivace. Na primer,
ako je de nisan pokazivac na int:
int *p;
tada mozemo de nisati pokazivac na pokazivac na int:
int **pp;
Ovaj pokazivac moze uzeti adresu pokazivacke promenljive p:
pp = &p;
Nakon toga se pokazivackoj promenljivoj p moze pristupiti i indirektno, preko pokazivaca
na pokazivac pp, zato sto je *pp ekvivalentno sa p. Takode, celom broju na koji
pokazuje p moze se pristupiti i sa **pp zato sto je **pp ekvivalentno sa *p.

6.4 Nizovi pokazivaca


Elementi nizova mogu biti bilo kog tipa, pa i pokazivaci. Na primer, niz pokazivaca
na karaktere se moze de nisati na sledeci nacin:
char * pokazivaci[100];
Ovim se rezervise prostor za niz od 100 pokazivaca na karaktere. Njima se pris-
tupa putem indeksa, kako je i uobicajeno. S obzirom da se ime niza uvek ponasa
kao adresa prvog objekta u nizu, sledi da je izraz pokazivaci tipa pokazivac na
pokazivac na char. Otuda se uobicajena pokazivacka aritmetika moze primenjivati
i na nizove pokazivaca.

65
Milena VujosevicJanicic 6.4 Nizovi pokazivaca

Primer 6.11 Program ucitava linije iz fajla ulaz.txt i zatim ih ispisuje na stan-
dardnom izlazu sortirane po duzini, pocev od najkrace linije.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

#define MAX_RED 1024


#define MAX_REDOVA 1024

/* Funkcija sortira niz pokazivaca na karaktere, pri cemu


je kriterijum sortiranja duzina stringova na koje pokazuju
ti pokazivaci. */
void sortiraj(char *redovi[], int n);

int main()
{
char redovi[MAX_REDOVA][MAX_RED];
char *p_redovi[MAX_REDOVA];

int i, n;
FILE * in;

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

/* Proveravamo da li smo uspesno otvorili fajl */


if(in == NULL)
{
printf("Greska! Fajl nije uspesno otvoren!\n");
exit(1);
}

/* Citamo linije, i smestamo ih u dvodimenzioni niz karaktera redovi[] (i-tu


liniju smestamo u niz redovi[i]). Citamo najvise MAX_REDOVA. Pokazivac
p_redovi[i] postavljamo da pokazuje na prvi karakter u nizu redovi[i]. */
for(i = 0; i < MAX_REDOVA; i++)
if(fgets(redovi[i], MAX_RED, in) != NULL)
p_redovi[i] = redovi[i];
else
break;

n = i;

66
Milena VujosevicJanicic 6.4 Nizovi pokazivaca

/* Zatavaramo fajl */
fclose(in);

/* NAPOMENA: Umesto da sortiramo niz nizova, sto podrazumeva zamenu


vrednosti citavih nizova, efikasnije je da definisemo niz pokazivaca
na karaktere koje cemo da usmerimo najpre na odgovarajuce stringove
koji se nalaze u nizu nizova redovi[] (Pokazivac p_redovi[i] se
se usmerava na string u nizu redovi[i]). Nakon toga se sortira niz
pokazivaca, tj. pokazivaci se ispremestaju tako da redom pokazuju
na stringove po rastucim duzinama. Ovim je sortiranje bitno efikasnije
jer je brze razmeniti dva pokazivaca nego citave nizove. */

/* Sortiramo niz pokazivaca */


sortiraj(p_redovi, n);

/* Prikazujemo linije u poretku rasta duzina */


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

return 0;
}

/* Funkcija razmenjuje vrednosti dva pokazivaca na karaktere.


S obzirom da je potrebno preneti adrese ovih promenljivih,
parametri su tipa "pokazivac na pokazivac na char". */
void razmeni(char **s, char **t)
{
char *p;

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

/* Funkcija implementira uobicajeni algoritam sortiranja izborom


najmanjeg elementa, pri cemu se pod najmanjim elementom ovde
podrazumeva pokazivac koji pokazuje na string koji je najkraci */
void sortiraj(char *redovi[], int n)
{

int i,j, min;

67
Milena VujosevicJanicic 6.4 Nizovi pokazivaca

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


{
min = i;
for(j = i + 1; j < n; j++)
if(strlen(redovi[j]) < strlen(redovi[min]))
min = j;

if(min != i)
{
razmeni(&redovi[min], &redovi[i]);
}
}
}

68
Glava 7

Rekurzija

Funkcija1 moze da poziva samu sebe, neposredno ili posredno. Ova pojava se zove
rekurzija. Ovakav pristup se cesto koristi prilikom resavanja problema koji imaju
prirodnu rekurzivnu de niciju, tj. kod kojih se problem dimenzije n moze jednos-
tavno svesti na problem dimenzije n-1 ili neke druge manje dimenzije. Rekurzija je
analogna matematickoj indukciji.
Ono sto je potencijalni problem kod razumevanja rekurzije je to sto se u jednom
trenutku mogu izvrsavati vise poziva jedne iste funkcije. Na primer, ako funkcija
f() prilikom svog izvrsavanja pozove samu sebe, tada se zapocinje novi poziv iste
funkcije. Prethodni poziv ceka da se zavrsi tekuci, a zatim nastavlja sa radom. Poziv
rekurzivne funkcije koji je zapocet, a cije izvrsavanje jos nije zavrseno nazivamo
aktivni poziv. Svaki poziv funkcije izvrsava se nezavisno od svih ostalih aktivnih
poziva u tom trenutku, zahvaljujuci cinjenici da svaki od aktivnih poziva ima svoje
sopostvene kopije formalnih parametara i lokalnih podataka. Kada se neki od poziva
zavrsi, njegove kopije nestaju iz memorije, ali kopije ostalih poziva i dalje postoje u
memoriji. Posledica ovog pristupa je da kada rekurzivna funkcija promeni vrednosti
svojih lokalnih podataka, ove promene ne uticu na ostale aktivne pozive, zato sto
oni imaju svoje lokalne kopije istih podataka.
Kreiranje i odrzavanje lokalnih kopija se jednostavno i e kasno ostvaruje zah-
valjujuci tome sto su parametri funkcije i lokalne nestaticke promenljive smestene
na sistemskom steku u pitanju je struktura podataka u kojoj se novi podaci uvek
smestaju na vrh a prilikom uklanjanja podataka takodje se uklanja podatak sa vrha,
tj. podatak koji je poslednji dodat (LIFO struktura last in, rst out). Prilikom
pozivanja bilo koje funkcije najpre se na stek smeste njeni argumenti (one vrednosti
koje su predate prilikom poziva) a zatim se na vrh steka smeste i lokalne promenljive.
Nakon toga se zapocne izvrsavanje tela funkcije. Ako se tom prilikom pozove neka
druga funkcija (ili ta ista, ako je rekurzija u pitanju) tada se na vrh steka dodaju
argumenti ovog poziva, kao i lokalne promenljive te funkcije, itd. Kada se funkci-
jski poziv zavrsi, tada se sa vrha steka skidaju njegove lokalne promenljive, kao i
parametri poziva, nakon cega na vrhu steka ostaju lokalne promenljive prethodnog
poziva itd.
1 Tekst preuzet sa www.matf.bg.ac.rs/milan

69
Milena VujosevicJanicic 7.1 Osnovni primeri

Lokalni staticki podaci (promenljive deklarisane kao static unutar funkcije) se


ne kreiraju na steku, vec u statickoj zoni memorije, i zajednicki su za sve pozive.
Zato se promene vrednosti ovih promenljivih u jednom pozivu vide i iz drugih ak-
tivnih poziva iste funkcije. Zato treba biti oprezan prilikom koriscenja statickih
promenljivih u rekurzivnim funkcijama (obicno se to i ne radi).
Svaka rekurzivna funkcija mora imati izlaz iz rekurzije kao i rekurzivni poziv
kojim se problem svodi na problem nizeg reda. Izlaz iz rekurzije je najcesce jednos-
tavan, ali ne mora uvek da bude tako.

7.1 Osnovni primeri


Primer 7.1 Racunanje faktorijela prirodnog broja.
#include<stdio.h>

unsigned long faktorijel_iterativno(int n)


{
long f = 1;
int i;
for (i = 1; i<=n; i++)
f *= i;
return f;
}

unsigned long faktorijel(int n)


{
if(n==0)
return 1;
else
return n*faktorijel(n-1);

/* Alternativni zapis:
return n == 0 ? 1 : n*faktorijel(n-1); */

main()
{
int n;
unsigned long f;

printf("Unesite n\n");
scanf("%d", &n);

f = faktorijel(n);

70
Milena VujosevicJanicic 7.1 Osnovni primeri

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

Primer 7.2 Racunanje sume prvih n prirodnih brojeva.


#include<stdio.h>
unsigned suma(unsigned n)
{
if(n==0)
return 0;
else
return (n + suma(n-1));

/* Najefikasniji nacin za resavanje ovog problema je


return (n*(n+1))/2; */
}

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

Primer 7.3 Iterativna i rekurzivna varijanta racunanja sume niza.


int suma_niza_iterativno(int a[], int n)
{
int suma = 0;
int i;
for (i = 0; i<n; i++)
suma+=a[i];
return suma;
}

int suma_niza(int a[], int n)


{
if (n == 1)
return a[0];
else
return suma_niza(a,n-1) + a[n-1];

/* Skracen zapis je:

71
Milena VujosevicJanicic 7.1 Osnovni primeri

return n == 1 ? a[0] : suma_niza(a,n-1) + a[n-1];*/


}
Primer 7.4 Stampanje celog broja.
#include<stdio.h>
void printb(long int n)
{
if(n<0)
{
putchar(-);
n=-n;
}
if(n>=10)
printb(n/10);
putchar(n % 10 + 0);
}

int main()
{
long int b=-1234;
printb(b);
putchar(\n);
return 0;
}
Kad funkcija rekurzivno pozove sebe, svakim pozivom pojavljuje se novi skup svih
automatskih promenljivih, koji je nezavisan od prethodonog skupa. Prva funkcija
printb kao argument dobija broj -12345, ona prenosi 1234 u drugu printb funkciju,
koja dalje prenosi 123 u trecu, i tako redom do poslednje koja prima 1 kao argument.
Ta funkcija stampa 1 i zavrsava sa radom tako da se vraca na prethodni nivo, na
kome se stampa dva i tako redom.
Primer 7.5 Stepenovanje prirodnog broja
 iterativno
 rekurzivno, koristeci cinjenicu da je xk = x xk1 i x0 = 1
k k 1
 rekurzivno, koristeci cinjenicu da je xk = (x2 ) 2 ako je k parno ili xk = x(x2 ) 2

ako je k neparno, i x0 = 1 i x1 = x.
#include <stdio.h>

/* Iterativna verzija prethodne funkcije */


int stepen_iterativno(int x, int k)
{
int i;

72
Milena VujosevicJanicic 7.1 Osnovni primeri

int s = 1;
for (i = 0; i<k; i++)
s*=x;
return s;
}

int stepen(int x, int k)


{
printf("Racunam stepen(%d, %d)\n",x,k); /* Ilustracije radi! */

if (k == 0)
return 1;
else
return x*stepen(x, k-1);

/* Krace se moze zapisati na sledeci nacin


return k==0 ? 1 : x*stepen(x, k-1); */
}

/* Efikasnija verzija rekurzivne funkcije. */


int stepen2(int x, int k)
{
printf("Racunam stepen2(%d, %d)\n",x,k); /* Ilustracije radi! */
if (k == 0)
return 1;
else
if (k == 1)
return x;
else
/* Ako je stepen paran*/
if((k%2)==0)
return stepen2(x*x, k/2);
else
return x * stepen2(x*x, k/2);
}

/* Alternativna funkcija stepen2


int stepen2(int n, int k)
{
int p, s;
if (k == 0) s = 1;
else
if (k == 1) s = n;
else

73
Milena VujosevicJanicic 7.1 Osnovni primeri

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

main()
{
printf("Stepen je: %d\n", stepen(2, 8));
printf("------------------\n");
printf("Stepen je: %d\n", stepen2(2, 8));
}
/* Izlaz iz programa:
Racunam stepen(2, 8)
Racunam stepen(2, 7)
Racunam stepen(2, 6)
Racunam stepen(2, 5)
Racunam stepen(2, 4)
Racunam stepen(2, 3)
Racunam stepen(2, 2)
Racunam stepen(2, 1)
Racunam stepen(2, 0)
Stepen je: 256
------------------
Racunam stepen2(2, 8)
Racunam stepen2(4, 4)
Racunam stepen2(16, 2)
Racunam stepen2(256, 1)
Stepen je: 256
*/
Primer 7.6 Fibonacijevi brojevi se definisu rekurentno na sledeci nacin:
f(0) = 1, f(1) = 1, f(n) = f(n-1) + f(n-2)
Napisati funkciju koja izracunava n-ti Fibonacijev broj.
#include <stdio.h>
#include <stdlib.h>

/* Rekurzivna implementacija - obratiti paznju na neefikasnost funkcije */


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

74
Milena VujosevicJanicic 7.1 Osnovni primeri

if((n==0)||(n==1))
return 1;
else
return(Fib(n-1)+Fib(n-2));

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

/* Iterativna verzija bez niza */


int Fib_iterativno(int n)
{
/* Promenljiva pp cuva pretposlednji, a p poslednji element niza */
int pp = 1, p = 1;
int i;
for (i = 0; i <= n-2; i++)
{
int pom = pp;
pp = p;
p = p + pom;
}
return p;
}
main()
{
printf("Fib(5) = %d\n", Fib(5));
}
/*
Izlaz iz programa:
Racunam Fib(5)
Racunam Fib(4)
Racunam Fib(3)
Racunam Fib(2)
Racunam Fib(1)
Racunam Fib(0)
Racunam Fib(1)
Racunam Fib(2)
Racunam Fib(1)
Racunam Fib(0)
Racunam Fib(3)
Racunam Fib(2)
Racunam Fib(1)
Racunam Fib(0)

75
Milena VujosevicJanicic 7.1 Osnovni primeri

Racunam Fib(1)
Fib(5) = 8

Kako se izvrsava program za vrednost 5:


_______________________________________________________________

Fib(5)?
=> 8 = 5+3
/ \
/ \
/ \
Fib(4)? Fib(3)?
=> 5=3+2 => 3=2+1
/ \ / \
Fib(3)? Fib(2)? Fib(2)? Fib(1)?
=> 3=2+1 => 2=1+1 => 2=1+1 |
/ \ / \ / \ 1
Fib(2)? Fib(1) Fib(1) Fib(0) Fib(1) Fib(0)
=> 2=1+1 | | | | |
/ \ 1 1 1 1 1
Fib(1) Fib(0)
| |
1 1
_______________________________________________________________

*/
Primer 7.7 U slucaju da se rekurzijom problem svodi na vise manjih podproblema
koji se mogu preklapati, postoji opasnost da se pojedini podproblemi manjih dimenz-
ija resavaju veci broj puta. Na primer,
fibonacci(20) = fibonacci(19) + fibonacci(18)
fibonacci(19) = fibonacci(18) + fibonacci(17)
tj. problem fibonacci(18) se resava dva puta. Problemi manjih dimenzija ce se
resavati jos veci broj puta. Resenje za ovaj problem je kombinacija rekurzije sa tzv.
dinamickim programiranjem podproblemi se resavaju samo jednom, a njihova
resenja se pamte u memoriji (obicno u nizovima ili matricama), odakle se koriste
ako tokom resavanja ponovo budu potrebni.
#include <stdio.h>
#include <stdlib.h>

#define MAX 50

/* Niz koji cuva resenja podproblema. */


int f[MAX];

76
Milena VujosevicJanicic 7.1 Osnovni primeri

/* Funkcija izracunava n-ti fibonacijev broj */


int fibonacci(int n)
{

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


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

/* Izlaz iz rekurzije */
if(n < 2)
return f[n] = 1;
else
/* Rekurzivni pozivi */
return f[n] = fibonacci(n - 1) + fibonacci(n - 2);
}

/* Test program */
int main()
{
int n, i;

/*Inicijalizuje se niz*/
for(i=0; i<MAX; i++)
f[i] = 0;

scanf("%d", &n);
printf("%d\n", fibonacci(n));

return 0;
}

Primer 7.8 Program resava problem tzv. hanojskih kula: data su tri vertikalna
stapa, na jednom se nalazi n diskova poluprecnika 1,2,3,... do n, tako da se najveci
nalazi na dnu, a najmanji na vrhu. Ostala dva stapa su prazna. Potrebno je pre-
mestiti diskove na drugi stap tako da budu u istom redosledu, premestajuci jedan po
jedan disk, pri cemu se ni u jednom trenutku ne sme staviti veci disk preko manjeg.

77
Milena VujosevicJanicic 7.1 Osnovni primeri

/*
| | |
=== | |
===== | |
======= | |
========= | |
----------- ----------- -----------
X Y Z
===>
...
| | |
| | |
| | ===
| | =====
========= | =======
----------- ----------- -----------
X Y Z
...
===>

| | |
| === |
| ===== |
| ======= |
| ========= |
----------- ----------- -----------
X Y Z
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_TOWER 100


#define MAX_NAME 64

/* Stuktura definise jednu hanojsku kulu */


typedef struct {
int s[MAX_TOWER]; /* Stap sa diskovima */
int n; /* Broj diskova na stapu */
char name[MAX_NAME]; /* Naziv kule */
} Tower;

/* Funkcija postavlja naziv kule na dato ime, a zatim na stap postavlja

78
Milena VujosevicJanicic 7.1 Osnovni primeri

diskove velicine n, n-1, ..., 2, 1 redom */


void init_tower(Tower * tower, char * name, int n)
{
int i;
strcpy(tower->name, name);
tower->n = n;
for(i = 0; i < n; i++)
tower->s[i] = n - i;
}

/* Funkcija prikazuje sadrzaj na datoj kuli */


void print_tower(Tower * tower)
{
int i;

printf("%s: ", tower->name);


for(i = 0; i < tower->n; i++)
printf("%d ", tower->s[i]);
putchar(\n);
}

/* Funkcija premesta jedan disk sa vrha prve kule na vrh druge kule */
void move(Tower *from, Tower * to)
{
/* Proveravamo da li je potez ispravan */
if(from->n == 0 || (to->n > 0 && from->s[from->n - 1] >= to->s[to->n - 1]))
{

printf("Ilegal move: %d from %s to %s!!\n",


from->s[from->n - 1],
from->name,
to->name );
exit(1);
}
else
{
/* Prikaz opisa poteza */
printf("Moving disc %d from %s to %s\n",
from->s[from->n - 1],
from->name,
to->name);

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

79
Milena VujosevicJanicic 7.1 Osnovni primeri

}
}

/* Rekurzivna funkcija koja premesta n diska sa kule x na kulu y. Kao


pomocna kula koristi se kula z. */
void hanoi(Tower *x, Tower *y, Tower * z, int n)
{
/* Izlaz iz rekurzije */
if(n == 0)
return;

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


hanoi(x, z, y, n - 1);

/* Premestamo jedan disk sa x na y */


move(x,y);

/* Prikaz stanja kula nakon poteza */


print_tower(x);
print_tower(y);
print_tower(z);

/* Premestamo n - 1 disk sa z na y, pomocu kule x */


hanoi(z, y, x, n - 1);
}

/* Test program */
int main()
{
Tower x, y, z;
int n;

/* Ucitavamo dimenziju problema */


scanf("%d", &n);

/* Inicijalizujemo kule. Kula x ima n diskova, ostale su prazne */


init_tower(&x, "X", n);
init_tower(&y, "Y", 0);
init_tower(&z, "Z", 0);

/* Prikaz kula na pocetku */


print_tower(&x);
print_tower(&y);

80
Milena VujosevicJanicic 7.2 Binarna pretraga

print_tower(&z);

/* Poziv funkcije hanoi() */


hanoi(&x, &y, &z, n);

return 0;
}

7.2 Binarna pretraga


Primer 7.9 Rekurzivna varijanta algoritma binarne pretrage.
#include <stdio.h>

/* Funkcija proverava da li se element x javlja unutar niza


celih brojeva a.
Funkcija vraca poziciju na kojoj je element nadjen odnosno
-1 ako ga nema.

!!!!! VAZNO !!!!!


Pretpostavka je da je niz a uredjen po velicini
*/

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


{
/* Ukoliko je interval prazan, elementa nema */
if (l > d)
return -1;

/* Srednja pozicija intervala [l, d] */


int s = (l+d)/2;

/* Ispitujemo odnos x-a i srednjeg elementa */


if (x == a[s])
/* Element je pronadjen */
return s;
else if (x < a[s])
/* Pretrazujemo interval [l, s-1] */
return binary_search(a, l, s-1, x);
else
/* Pretrazujemo interval [s+1, d] */
return binary_search(a, s+1, d, x);
}

main()

81
Milena VujosevicJanicic 7.3 MergeSort algoritam

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

printf("Unesi element kojega trazimo : ");


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

if (i==-1)
printf("Elementa %d nema\n", x);
else
printf("Pronadjen na poziciji %d\n", i);
}

7.3 MergeSort algoritam


Primer 7.10 Sortiranje niza celih brojeva ucesljavanjem - MergeSort algoritam.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX 100

/* sortiranje ucesljavanjem */
void merge_sort (int a[], int l, int d)
{
int s;
int b[MAX]; /* pomocni niz */
int i, j, k;

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

/* Odredjujemo sredisnji indeks */


s = (l + d) / 2;

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

/* Inicijalizacija indeksa. Indeks i prolazi


krozi levu polovinu niza, dok indeks j

82
Milena VujosevicJanicic 7.3 MergeSort algoritam

prolazi kroz desnu polovinu niza. Indeks


k prolazi kroz pomocni niz b[] */
i = l;
j = s + 1;
k = 0;

/* "ucesljavanje" koriscenjem pomocnog niza b[] */


while(i <= s && j <= d)
{
if(a[i] < a[j])
b[k++] = a[i++];
else
b[k++] = a[j++];
}

while(i <= s)
b[k++] = a[i++];

while(j <= d)
b[k++] = a[j++];

/* prepisujemo "ucesljani" niz u originalni niz */


for (k = 0, i = l; i <= d; i++, k++)
a[i] = b[k];
}

/* Test program */
int main(int argc, char ** argv)
{
int a[MAX];
int n, i;
int x;

/* Niz brojeva se zadaje na komandnoj liniji */


for(n = 0; n + 1 < argc && n < MAX; n++)
a[n] = atoi(argv[n + 1]);

/* Poziv funkcije */
merge_sort(a, 0, n - 1);

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

83
Milena VujosevicJanicic 7.4 QuickSort algoritam

putchar(\n);

return 0;
}

7.4 QuickSort algoritam


Primer 7.11 Sortiranje niza celih brojeva - QuickSort algoritam.
/* Funkcija menja mesto i-tom i j-tom elementu niza a */
void swap(int a[], int i, int j)
{
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}

/* Funkcija particionise interval [l, r] niza a, tako da levo od pivota


budu svi elementi manji od njega, a desno svi veci od njega.
Ovi podnizovi ne moraju biti sortirani.
Funkcija vraca poziciju pivota.
*/
int partition(int a[], int l, int r)
{
int last, i;

/* Srednji element uzimamo za pivot i postavljamo ga na pocetak */


swap(a, l, (l + r)/2);

/* Niz organizujemo tako da pivot postavimo na pocetak, zatim da iza


njega budu svi elementi manji od njega, pa zatim svi elementi koji
su veci od njega tj.
pivot < < < < > > > >
*/

/* last je pozicija poslednjeg elementa niza za koji znamo da je


manji od pivota. U pocetku takvih elemenata nema */
last = l;
for (i = l+1; i <= r; i++)
/* Ukoliko je element na poziciji i manji od pivota,
postavljamo ga iza niza elemenata manjih od pivota,
menjajuci mu mesto sa prvim sledecim */
if (a[i] < a[l])
swap(a, ++last, i);

84
Milena VujosevicJanicic 7.4 QuickSort algoritam

/* Zahtevanu konfiguraciju < < < < pivot > > > > dobijamo tako
sto zamenimo mesto pivotu i poslednjem elementu manjem od njega */
swap(a, l, last);

/* Pivot se sada nalazi na poziciji last */


return last;
}

/* Funkcija sortira deo niza brojeva a izmedju pozicija l i r*/


void quick_sort(int a[], int l, int r)
{
int i, last;

/* Ukoliko je interval [l, r] prazan nema nista da se radi */


if (l >= r)
return;

/* Particionisemo interval [l, r] */


int pivot = partition(a, l, r);

/* Rekurzivno sortiramo elemente manje od pivota */


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

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

quick_sort(a, 0, n-1);

for (i = 0; i < n; i++)


printf("%d ", a[i]);
printf("\n");
}

85
Glava 8

Pokazivaci na funkcije

Binarne instrukcije koje cine funkciju su takode negde u memoriji, i imaju svoju
adresu. Zato je moguce je de nisati pokazivac na funkciju. Na primer, deklaracija:
int (*fp)(int);
de nise promenljivu f, koja je tipa pokazivac na funkciju koja prihvata argument
tipa int, i vraca vrednost tipa int. Ova promenljiva sadrzi adresu neke funkcije
tog tipa. Na primer, ako je deklarisana funkcija:
int f(int a);
Tada je moguce dodeliti:
fp = &f; /* Operator adrese nije neophodan. */
Promenljiva fp sadrzi adresu funkcije f. Funkcija f se sada moze pozivati derefer-
enciranjem pokazivaca fp:
(*fp)(3);
Zagrade oko izraza *fp su neophodne zbog prioriteta operatora. Dereferenciranjem
pokazivaca na funkciju dobija se funkcija, koja se onda poziva na uobicajen nacin.

Primer 8.1 Program demonstrira upotrebu pokazivaca na funkcije.


#include <stdio.h>

int kvadrat(int n)
{
return n*n;
}

int kub(int n)
{
return n*n*n;
}

86
Milena VujosevicJanicic Pokazivaci na funkcije

int parni_broj(int n)
{
return 2*n;
}

/* Funkcija izracunava sumu brojeva f(i) za i iz intervala [1, n].


int (*f) (int) u argumentu funkcije sumiraj je pokazivac
na funkciju sa imenom f, koja kao argument prima promenljivu
tipa int i vraca kao rezultat vrednost tipa int
*/
int sumiraj(int (*f) (int), int n)
{
int i, suma=0;
for (i=1; i<=n; i++)
suma += (*f)(i);

return suma;
}

main()
{

/* U pozivu funkcije sumiraj, imena funkcija kvadrat, kub i parni_broj su


zapravo istovremneo i adrese funkcija pa operator & nije neophodan
ali nije greska ukoliko se se operator & ipak koristi ispred
imena funkcije. */

printf("Suma kvadrata brojeva od jedan do 3 je %d\n", sumiraj(kvadrat,3));


printf("Suma kubova brojeva od jedan do 3 je %d\n", sumiraj(kub,3));
printf("Suma prvih pet parnih brojeva je %d\n", sumiraj(parni_broj,5));

/* Ili:
printf("Suma kvadrata brojeva od jedan do 3 je %d\n", sumiraj(&kvadrat,3));
printf("Suma kubova brojeva od jedan do 3 je %d\n", sumiraj(&kub,3));
printf("Suma prvih pet parnih brojeva je %d\n", sumiraj(&parni_broj,5));
*/
}
/*Izlaz:
Suma kvadrata brojeva od jedan do 3 je 14
Suma kubova brojeva od jedan do 3 je 36
Suma prvih pet parnih brojeva je 30
*/

Primer 8.2 Program tabelarno ispisuje vrednosti raznih matematickih funkcija u

87
Milena VujosevicJanicic Pokazivaci na funkcije

tackama datog intervala sa datim korakom.


#include <stdio.h>
#include <math.h>

/*
Zaglavlje math.h sadrzi deklaracije razih matematickih funkcija. Izmedju
ostalog, to su sledece funkcije:
double sin(double x);
double cos(double x);
double tan(double x);
double asin(double x);
double acos(double x);
double atan(double x);
double atan2(double y, double x);
double sinh(double x);
double cosh(double x);
double tanh(double x);
double exp(double x);
double log(double x);
double log10(double x);
double pow(double x, double y);
double sqrt(double x);
double ceil(double x);
double floor(double x);
double fabs(double x);
*/

/* Funkcija tabeliraj() prihvata granice intervala a i b, korak h, kao i


pokazivac f koji pokazuje na funkciju koja prihvata double argument, i
vraca double rezultat. Za tako datu funkciju ispisuje njene vrednosti u
intervalu [a,b] sa korakom h */

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


{
double x;

printf("-----------------------\n");
for(x = a; x <= b; x+=h)
printf("| %8.3f | %8.3f |\n", x, (*f)(x));
printf("-----------------------\n");

88
Milena VujosevicJanicic 8.1 Funkcija qsort iz standardne biblioteke

/* Funkcija main */
int main()
{
double a, b, h;

/* Unosimo granice intervala */


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

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

/* Testiramo funkciju tabeliraj() za sin(), cos() i exp() */


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

return 0;
}

8.1 Funkcija qsort iz standardne biblioteke


Prototip funkcije qsort iz stdlib.h je:
void qsort(void *niz, int duzina_niza, int velicina_elementa_niza,
int (*poredi)(const void*, const void*) )
Ova funkcija sortira niz
niz[0], niz[1], ..., niz[duzina_niza - 1]
elemenata velicine velicina_elementa_niza koriscenjem funkcije poredi koja uporeduje
dva elementa niza.
Posto je void* tip niza niz to obezbeduje mogucnost koriscenja ove funkcije za
nizove razlicitih tipova podataka. Da bi funkcija qsort znala sa kakvim elementima
barata, potrebno joj je proslediti i velicinu jednog elementa u nizu (ovo je kljucno
za korak u kome se vrisi razmena elemenata niza funkcija qsort mora da zna
koliko bajtova zauzima jedan element niza kako bi mogla adekvatno da vrsi kopiranje
memorije).
Funkcija poredi vrsi poredenje dva elementa niza. Kada ova funkcija vraca
pozitivnu vrednost ako je prvi element veci od drugog, 0 ako su jednaki i negativnu
vrednost ako je prvi element manji, tada ce se niz sortirati u rastucem poretku.
Modi kacijom ove funkcije niz se moze sortirati u opadajucem poretku (ukoliko

89
Milena VujosevicJanicic 8.1 Funkcija qsort iz standardne biblioteke

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

Kvalifikator const
Kljucna rec const u programskom jeziku C sluzi za de nisanje konstanti. Ako
napisemo:
const int a = 2;
tada se u daljem toku programa promenljivoj a ne moze dodeljivati vrednost. Za
razliku od konstanti de nisanih de ne direktivom ova konstanta ima jasno de nisan
tip koji prevodilac proverava prilikom upotrebe.
Treba naglasiti, medjutim, da ako se napise:
const int * p = &a;
tada se const ne odnosi na promenljivu p, vec na podatak tipa int na koji p
pokazuje. Dakle, nije pokazivac konstantan, vec on pokazuje na konstantan podatak.
Na primer:
int b;
p = &b;
je dozvoljeno, ali:
*p = 4;
nije dozvoljeno, zato sto je p pokazivac na konstantan int (odnosno, kroz pokazivac
p nije moguce menjati vrednost koja se nalazi na adresi na koju on ukazuje). Ovo
se moze razumeti tako sto se deklaracija procita sa desna u levo:
const int * p; /* p je pokazivac na int koji je konstantan*/
Slicno bi bilo i ako napisemo:
int const * p; /* p je pokazivac na konstantan int. */
Medutim, ako napisemo:
int * const p; /* p je konstantan pokazivac na int. */
Kombinacija ovoga je:
const int * const p; /* p je konstantan pokazivac na int
koji je konstantan.*/
Dakle, u ovom poslednjem slucaju konstantni su i pokazivac i ono na sta on pokazuje.

90
Milena VujosevicJanicic 8.1 Funkcija qsort iz standardne biblioteke

Upotreba qsort
Primer 8.3 Upotrebom qsort funkcije iz standardne biblioteke izvrsiti sortiranje
niza celih i niza realnih brojeva.
/* Ilustracija upotrebe funkcije qsort iz stdlib.h
Sortira se niz celih brojeva.
*/

#include <stdlib.h>
#include <stdio.h>

/* const znaci da ono na sta pokazuje a (odnosno b)


nece biti menjano u funkciji */
int poredi(const void* a, const void* b)
{
/* Skracen zapis za
int br_a = *(int*)a;
int br_b = *(int*)b;

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

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


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

if (br_a > br_b) return 1;


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

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

int n=sizeof(niz)/sizeof(int);
qsort((void*)niz, n, sizeof(int), poredi);
for(i=0; i<n; i++)
printf("%d",niz[i]);

91
Milena VujosevicJanicic 8.1 Funkcija qsort iz standardne biblioteke

n=sizeof(nizf)/sizeof(float);
qsort((void*)nizf, n, sizeof(float), poredi_float);
for(i=0; i<n; i++)
printf("%f",nizf[i]);
}
Primer 8.4 Sortiranje reci. Ako se sortira niz stringova, onda svaki element je
sam po sebi pokazivac tipa char *, te funkcija poredenja tada prima podatke tipa
char ** koji se konvertuju u svoj tip i derefenciraju radi dobijanja podataka tipa
char *.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

/* Funkcija koja vrsi leksikografsko poredjenje dve reci.


Vraca kao rezultat >0 ukoliko je prva rec veca, 0 ako su jednake
i <0 ako je prva rec manja. Sortiranje ce biti u rastucem poretku.*/
int poredi_leksikografski(const void* a, const void* b)
{
char *s1 = *(char **)a;
char *s2 = *(char **) b;
return strcmp(s1, s2);

/* Prethodno je ekvivalentno sa:


return strcmp(*(char**)a,*(char**)b); */
}

/* Funkcija koja vrsi poredjenje po duzini dve reci,


sortiranje koje koristiovu funkciju ca biti opadajuce!*/
int poredi_po_duzini(const void* a, const void* b)
{
char *s1 = *(char **) a;
char *s2 = *(char **) b;
return strlen(s1) - strlen(s2);
/* Prethodno je ekvivalentno sa:
return strlen(*(char**)b)-strlen(*(char**)a); */
}

main()
{
int i;
char* nizreci[]={"Jabuka","Kruska","Sljiva","Dinja","Lubenica"};

qsort((void*)nizreci, sizeof(nizreci)/sizeof(char *),


sizeof(char*), poredi_po_duzini);

92
Milena VujosevicJanicic 8.2 Funkcija bsearch iz standardne biblioteke

for (i=0; i<5; i++)


printf("%s\n",nizreci[i]);

qsort((void*)nizreci, sizeof(nizreci),
sizeof(char*), poredi_leksikografski);

printf("Sortirano:\n");
for (i=0; i<sizeof(nizreci); i++)
printf("%s\n",nizreci[i]);
}
/*
Izlaz:
Dinja Jabuka Kruska Lubenica Sljiva
Sortirano:
Lubenica Kruska Jabuka Sljiva Dinja
*/

8.2 Funkcija bsearch iz standardne biblioteke


Prototip funkcije bsearch iz stdlib.h je:
void *bsearch (const void *kljuc, const void *niz, int duzina_niza,
int velicina_elementa_niza,
int (*poredi)(const void*, const void*) )
Ova funkcija u nizu
niz[0], niz[1], ..., niz[duzina_niza - 1]
elemenata velicine velicina_elementa_niza trazi element koji ima krakteristiku
na koju ukazuje pokazivac kljuc.
Funkcija poredi moze da se razlikuje od funkcije poredi koju prima funkcija
qsort. Njen prvi argument je kljuc pretrage, a drugi argument je element niza. To
znaci da ova dva argumenta mogu ali i ne moraju da budu istog tipa. Na primer,
ako u nizu studenata trazimo onog studenta koji ima indeks mm08123 tada je kljuc
tipa char* a element niza je tipa strukture student, znaci kljuc pretrage i element
niza su razlicitog tipa, pa u skladu sa tim funkcija poredenja prima dva argumenta
razlicitog tipa. S druge strane, ako u nizu studenata trazimo onog studenta koji ima
indeks mm08123, i ime Pera i prezime Peric, tada je kljuc istog tipa kao i element
niza, i tada funkcija poredenja prima argumente istog tipa (i analogna je funkciji
poredenja koja se pise za funkciju qsort). Dakle, poredenje se vrsi po kljucu koji
moze biti istog tipa kao i elementi niza ali i ne mora.
Funkcija poredi treba da vrati vrednost 0 ako je prvi argument (kljuc pretrage)
veci (u smislu kljuca pretrage) od drugog argumenta (koji je element niza), 0 ako su
jednaki (u smislu kljuca pretrage) i broj manji od 0 ako je prvi argument manji (u
smislu kljuca pretrage) od drugog argumenta, ukoliko su elementi u nizu niz uredeni

93
Milena VujosevicJanicic 8.2 Funkcija bsearch iz standardne biblioteke

u rastucem redosledu u odnosu na dati kljuc. Funkcija bsearch vraca pokazivac na


pronadeni element ili NULL ukoliko element sa datom vrednoscu kljuca ne postoji.

Primer 8.5 Binarno pretrazivanje - koriscenje ugradene bsearch funkcije.

/* Funkcija ilustruje koriscenje ugradjene funkcije bsearch */


#include <stdlib.h>

int poredi(const void* a, const void *b)


{
return *(int*)a-*(int*)b;
}

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

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

if (elem==NULL)
printf("Element nije pronadjen\n");
else
printf("Element postoji na poziciji %d\n",elem-niz);
}

Primer 8.6 Sa ulaza se unose reci. Program broji pojavljivanja svake od kljucnih
reci programskog jezika C. Na kraju se reci ispisuju opadajuce po broju pojavljivanja.
#include <stdio.h>
#include <stdlib.h>

/* Svaka kljucna rec se odlikuje imenom i brojem pojavljivanja */


typedef struct _keyword
{
char word[20];
int num;
} keyword;

/* Kreiramo niz struktura sortiranih leksikografski


po imenu kljucne reci, kako bismo ubrzali pronalazak reci */

94
Milena VujosevicJanicic 8.2 Funkcija bsearch iz standardne biblioteke

keyword keywords[]={ {"break",0},


{"continue",0},
{"float",0},
{"for",0},
{"if",0},
{"return",0},
{"struct",0},
{"while",0}
};

/* Funkcija cita sledecu rec sa standardnog ulaza */


int getword(char word[], int lim)
{
int c, i=0;
while(!isalpha(c=getchar()) && c!=EOF)
;
if (c==EOF)
return -1;
do
{
word[i++]=c;
} while(--lim>0 && isalpha(c=getchar()));

word[i]=\0;
return i;
}

/* Funkcija leksikografskog poredjenja za bsearch */


int cmp(const void* a, const void* b) {
/* Funkcija strcmp prima kao argumente dva
pokazivaca na karaktere. U ovom slucaju, prvi argument je
rec koju trazimo u nizu --- prilikom poziva funkcije
bsearch funkciji se kao prvi argument prosledjuje pokazivac
na kljuc pretrage - to znaci da ukoliko se funkciji prosledi
adresa podatka tipa char* tada bi bilo potrebno uraditi
dereferenciranje sa *(char **)a; medjutim, ukoliko se prosledi
samo promenljiva tipa char* tada je potrebno uraditi
dereferenciranje sa (char *)a. Drugi argument funkcije
je element niza sa kojim se vrsi poredjenje. Pokazivac
b konvertujemo u pokazivac na strukturu
keyword a zatim posmatramo rec koja se tu
cuva */
return strcmp((char*)a, (*(keyword*)b).word); }

95
Milena VujosevicJanicic 8.2 Funkcija bsearch iz standardne biblioteke

/* Funkcija numerickog poredjenja za qsort */


int numcmp(const void* a, const void* b)
{
return ((*(keyword*)b).num-(*(keyword*)a).num);
}

main()
{
char word[80];
int i;

/* Broj kljucnih reci */


int num_of_keywords=sizeof(keywords)/sizeof(keyword);

/* Citamo reci */
while (getword(word,80)!=-1)
{
/* Trazimo rec u spisku kljucnih reci binarnom pretragom */
/* Prvi argument funkcije bsearch treba da bude pokazivac
na rec koju trazimo. Posto je word tipa niza karaktera, tada
uzimanjem adrese od word dobijamo istu vrednost kao i word,
tj nema razlike izmedju word i &word. Zbog toga se u funkciji
poredjenja koristi dreferenciranje na sledeci nacin
strcmp((char*)a, (*(keyword*)b).word); }
Da je word tipa char*, tada bi poziv funkcije bsearch
sa argumentom &word povlacilo da funkcija poredjenja
koristi dereferenciranje na sledeci nacin
strcmp(*(char**)a, (*(keyword*)b).word); }
*/
keyword* k=(keyword*)bsearch((void*)word,
(void*)keywords,
num_of_keywords,
sizeof(keyword),
cmp);
/* Ukoliko je pronadjena uvecavamo broj pojavljivanja */
if (k!=NULL)
(*k).num++;
}

/* Sortiramo niz na osnovu broja pojavljivanja */


qsort((void*)keywords, num_of_keywords, sizeof(keyword), numcmp);

/* Vrsimo ispis */
for (i=0; i<num_of_keywords; i++)

96
Milena VujosevicJanicic 8.3 Funkcije lsearch i lfind

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


}

8.3 Funkcije lsearch i lfind


Funkcije za linearnu pretragu standardne biblioteke su funkcije lsearch i lfind.
Funkcija lsearch ima sledece argumente
void *lsearch(const void *kljuc, void *niz, int *duzina_niza,
int velicina_elementa_niza,
int (*comp)(const void *, const void *));
Ova funkcija ima iste argumente kao i funkcija bsearch() jedina razlika je u tome
sto se kao treci argument ne predaje duzina niza vec adresa celobrojne promenljive
u kojoj se nalazi duzina niza. Ovo je zato sto funkcija lsearch() ukoliko linearnom
pretragom ne pronade element koji se trazi, umece trazeni element na kraj niza,
a duzinu niza uvecava za jedan (sto cini tako sto promenljivoj pozivajuce funkcije
pristupa preko pokazivaca i menja je). Takode, posto postiji mogucnost umetanja
elementa u niz, kao kljuc pretrage potrebno je koristiti kljuc koji je istog tipa kao sto
su to elementi niza. Funkcija za uporedjivanja elemenata na koju pokazuje pokazi-
vac comp treba da zadovoljava ista pravila kao i kod funkcije bsearch. Medjutim,
s obzirom da se kod linearne pretrage koristi iskljucivo poredenje na jednakost, do-
voljno je da funkcija za uporedjivanje vraca 0 ako su objekti koji se uporedjuju
jednaki, a razlicito od nule u suprotnom.
Funkcija lfind:
void *lfind(const void *kljuc, void *niz, int *duzina_niza,
int velicina_elementa_niza,
int (*comp)(const void *, const void *));
funkcionise isto kao i lsearch, s tom razlikom sto ne umece novi element u slucaju
neuspesne pretrage, vec vraca NULL (funkcija lsearch u slucaju neuspesne pretrage
umece trazeni element na kraj i vraca njegovu adresu). Za funkciju lfind moguce je
koristiti kljuc pretrage koji nije istog tipa kao elementi niza, u tom slucaju potrebno
je adekvatno de nisati funkciju poredenja.

8.4 Pokazivaci
Primer 8.7 Razlicite deklaracije:
int *p; pokazivac na int
int **p; pokazivac na pokazivac na tip int

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


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

97
Milena VujosevicJanicic 8.4 Pokazivaci

int p[5][10]; pet nizova od po 10 elemenata tipa int


int (*p)[10]; pokazivac na niz od deset celobrojnih vrednosti

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


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

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


int *(*p)(); pokazivac na funkciju bez argumenata koja vraca pokazivac na int
int* (*p)(); pokazivac na funkciju bez argumenata koja vraca pokazivac na int
Razlika izmedu int** t i int (*t)[5]
int x;
int (*t)[5];
int aa[4][5];
t = aa;
x=t[2][2]; /*Da je t tipa int** ova dodela ne bi bila moguca!*/

98
Glava 9

Dinamicka alokacija memorije

Do sada smo memoriju za podatke rezervisali na dva nacina1 :


Staticka alokacija podaci se kreiraju staticki prilikom pokretanja programa
i ostaju u memoriji do kraja njegovog izvrsavanja. Ovakvu alokaciju imaju
globalne promenljive (promenljive de nisane van svake funkcije ili bloka) kao i
staticke lokalne promenljive (deklarisane kljucnom recju static unutar funkcije
ili bloka).
Automatska alokacija podaci se kreiraju automatski prilikom ulaska u funkciju
ili blok, i nestaju kada se iz funkcije/bloka izade. Ovakvo ponasanje imaju
sve lokalne promenljive koje nisu deklarisane kao static. Prostor za ove
promenljive se rezervise na programskom steku.
Glavni nedostatak oba ova pristupa je to sto programer u vreme pisanja programa
mora da predvidi koliko ce mu prostora biti potrebno za podatke. Cesto tako nesto
nije moguce, jer dimenzije problema mogu varirati. Drugi nedostatak je to sto je
zivotni vek svakog podatka jasno de nisan gornjim pravilima. Programer moze zeleti
da nakon kreiranja nekog objekta u memoriji on ostane tu dokle god je potreban,
te da ga kasnije ukloni kada vise za njim nema potrebe.
Svi ovi problemi resavaju se dinamickom alokacijom memorije. Pored staticke
zone i steka, u memoriji postoji i odredeni prostor koji se naziva hip (eng. heap). U
ovom prostoru se po potrebi mogu kreirati objekti proizvoljne velicine. Taj prostor
se kasnije moze (i treba) osloboditi, kada programer vise nema potrebu da koristi
taj prostor.
U programskom jeziku C, ovo se moze ostvariti pozivom funkcije standardne
biblioteke malloc() koja je deklarisana u zaglavlju stdlib.h:
void * malloc(int n);
Ova funkcija alocira na hipu kontinualni prostor od n bajtova, i vraca adresu pocetka
tog prostora ili vraca vrednost NULL ukoliko zahtev ne moze da se ispuni. Jedini nacin
da se ovom prostoru pristupi je preko pokazivaca (jer ne postoji ime promenljive kao
kod statickih i automatskih promenljivih).
Osim funkcije malloc() postoje i druge funkcije za alokaciju, na primer:
1 Tekst preuzet sa sajta www.matf.bg.ac.rs/~milan

99
Milena VujosevicJanicic Dinamicka alokacija memorije

void * calloc(int n, int s);


Ova funkcija alocira prostor za n susednih elemenata velicine s bajtova (zapravo
alocira n*s bajtova). Ova funkcija jos i inicijalizuje rezervisani prostor na vrednost
0, za razliku od malloc() funkcije koja prostor ostavlja neinicijalizovan. Funkcija
void * realloc(void *p, int n);
vrsi realokaciju prostora na koji pokazuje pokazivac p za koji je memorija prethodno
bila dinamicki alocirana. Alocira se n bajtova, kopira se stari sadrzaj u novi prostor,
a zatim se stari prostor oslobada. Ova funkcija se obicno koristi da bi se prosirio
postojeci dinamicki alocirani prostor.
Prostor alociran prethodnim funkcijama se moze dealocirati pozivom funkcije:
void free(void *p);
koja je takode deklarisana u zaglavlju stdlib.h, i koja za argument mora imati
adresu koju je funkcija (m|c|re)alloc() vratila u nekom od prethodnih poziva
(drugim recima, ne moze se proizvoljan prostor oslobadati ovom funkcijom, vec
samo prostor na hipu alociran (m|c|re)alloc()-om). Kada se jednom dealocira,
prostor vise ne sme da se koristi (vrlo je verovatno da ce ga kasnije funkcija koja
vrsi alokaciju dodeliti nekom drugom).
Trenutak oslobadanja prostora na hipu odreduje programer. Nebitno je da li
smo izasli iz funkcije ili bloka u kome je funkcija za alokaciju memorije pozvana,
prostor ostaje rezervisan dokle god ne pozovemo free() sa argumentom adrese tog
prostora. Ova memorija se moze koristiti i u drugim funkcijama sve dok imamo
pokazivac kojim mozemo da joj pristupimo.
Tiha greska je ako izgubimo pokazivac na dinamicki alocirani prostor, a da ga
nismo prethodno dealocirali. U ovom slucaju taj prostor ostaje rezervisan do kraja
izvrsavanja programa, bez mogucnosti da ga koristimo ili da ga kasnije obrisemo
(jer nemamo njegovu adresu). Ovaj fenomen se naziva curenje memorije (eng.
memory leak). Odgovornost je programera kao i odlika dobrog stila da se dinamicki
prostor uvek oslobodi kada vise nije potreban. Takode, greska je i ukoliko programer
pokusa dva puta da oslobodi istu memoriju ili da pristupi memoriji koja je vec
oslobodena (ovo dovodi do greske prilikom izvrsavanja programa).
Primer 9.1 Dinamicka alokacija memorije za niz.
#include <stdio.h>
#include <stdlib.h>

main()
{
int n;
int i;
int *a;

/* Ranije smo alocirali konstantan prostor za niz,

100
Milena VujosevicJanicic Dinamicka alokacija memorije

sada cemo alocirati tacno onoliko koliko nam je


potrebno. */
printf("Unesi broj clanova niza : ");
scanf("%d", &n);

/* Kao da smo mogli da deklarisemo


int a[n];
Alocira se n mesta za podatke tipa int.
Funkcija malloc vraca vrednost tipa void*
tako da vrsimo kastovanje.
*/
a = (int*)malloc(n*sizeof(int));

/* Kad god se vrsi alokacija memorije mora se


proveriti da li je alokacija uspesno izvrsena!!! */
if (a == NULL)
{
printf("Nema slobodne memorije\n");
exit(1);
}

/* Od ovog trenutka a koristimo kao obican niz */


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

/* Stampamo niz u obrnutom redosledu */


for(i = n-1; i>=0; i--)
printf("%d",a[i]);

/* Oslobadjamo memoriju*/
free(a);
}
Primer 9.2 Demonstracija funkcije calloc - funkcija inicijalizuje sadrzaj memo-
rije na 0.
#include <stdio.h>
#include <stdlib.h>

main()
{
int *m, *c, i, n;

printf("Unesi broj clanova niza : ");


scanf("%d", &n);

101
Milena VujosevicJanicic Dinamicka alokacija memorije

/* Niz m NE MORA garantovano da ima sve nule */


m = (int*) malloc(n*sizeof(int));
if (m == NULL) {
printf("Greska prilikom alokacije memorije!\n");
exit(1);
}

/* Niz c MORA garantovano da ima sve nule */


c = (int*) calloc(n, sizeof(int));
if (c == NULL) {
printf("Greska prilikom alokacije memorije!\n");
free(m);
exit(1);
}

/*Odstampace se sadrzaj neinicijalizovane memorije*/


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

/*Odstampace se nule*/
for (i = 0; i<n; i++)
printf("c[%d] = %d\n", i, c[i]);

/* Oslobadja se rezervisana memorija. */


free(m);
free(c);
}
Primer 9.3 Da bi funkcija omogucila pozivajucoj funkciji da koristi vrednosti niza
koji je kreirala, neophodno je da memorija kreiranog niza bude dinamicki alocirana
kako bi nastavila da postoji i nakon zavrsetka rada funkcije. U tom slucaju, pozi-
vajuca funkcija ima odgovornost i da se brine o dealokaciji rezervisanog prostora.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX 1000

/* Funkcija dinamicki kreira niz karaktera u koji smesta rezultat


nadovezivanja stringova s i t. Adresa niza se vraca kao povratna
vrednost. */
char * nadovezi_stringove(char *s, char *t)
{
/* Dinamicki kreiramo prostor dovoljne velicine */
char *p = (char*) malloc((strlen(s) + strlen(t) + 1) * sizeof(char));

102
Milena VujosevicJanicic Dinamicka alokacija memorije

/* Proveravamo uspeh alokacije */


if(p == NULL)
{
fprintf(stderr, "malloc() greska!\n");
exit(1);
}

/* Kopiramo i nadovezujemo stringove */


strcpy(p,s);
strcat(p,t);

/* Vracamo p */
return p;
}

int main()
{
char * p = NULL;
char s[MAX], t[MAX];

/* Ucitavamo stringove */
scanf("%s", s);
scanf("%s", t);

/* Nadovezujemo stringove */
p = nadovezi_stringove(s,t);

/* Prikazujemo rezultat */
printf("%s\n", p);

/* Oslobadjamo memoriju*/
free(p);

return 0;
}
Primer 9.4 Niz pokazivaca na nizove razlicitih duzina.
#include <stdio.h>
#include <stdlib.h>
main()
{
/* Niz od tri elemenata tipa int*/
int nizi[3];

103
Milena VujosevicJanicic Dinamicka alokacija memorije

/* Niz od tri elemenata tipa int*, dakle


niz od tri pokazivaca na int*/
int* nizip[3];

/* Alociramo memoriju za prvi element niza*/


nizip[0] = (int*) malloc(sizeof(int));
if (nizip[0] == NULL)
{
printf("Nema slobodne memorije\n");
exit(1);
}
/* Upisujemo u prvi element niza broj 5*/
*nizip[0] = 5;
printf("%d", *nizip[0]);

/* Alociramo memoriju za drugi element niza.


Drugi element niza pokazuje na niz od dva
elementa*/
nizip[1] = (int*) malloc(2*sizeof(int));
if (nizip[1] == NULL) {
printf("Nema slobodne memorije\n");
free(nizip[0]);
exit(1);
}

/* Pristupamo prvom elementu na koji pokazuje


pokazivac nizip[1]*/
*(nizip[1]) = 1;

/* Pristupamo sledecem elementu u nizu na koji pokazuje


nizip[1].
*/
*(nizip[1] + 1) = 2;

printf("%d", nizip[1][1]);

/* Alociramo memoriju za treci element niza nizip. */


nizip[2] = (int*) malloc(sizeof(int));
if (nizip[2] == NULL) {
printf("Nema slobodne memorije\n");
free(nizip[0]);
free(nizip[1]);
exit(1);
}

104
Milena VujosevicJanicic 9.1 Matrice

*(nizip[2]) = 2;

printf("%d", *(nizip[2]));

/* Oslobadjamo memoriju. */
free(nizip[0]);
free(nizip[1]);
free(nizip[2]);
}

9.1 Matrice
Primer 9.5 Staticka alokacija prostora za matricu.
#include <stdio.h>

main()
{
int i, j;

/* Deklaracija i inicijalizacija elemenata matrice */


int a[3][3] = {{0, 1, 2}, {10, 11, 12}, {20, 21, 22}};

/* Alternativni unos elemenata matrice


for(i=0; i<3; i++)
for(j=0; j<3; j++)
{
printf("a[%d][%d] = ", i, j);
scanf("%d", &a[i][j]);
}
*/

/*Pristup elementima matrice */


a[1][1] = a[0][0] + a[2][2];
/* a[1][1] = 0 + 22 = 22 */

printf("%d\n", a[1][1]); /* 22 */

/* Stampanje elemenata matrice*/


for(i=0; i<3; i++)
{
for(j=0; j<3; j++)
printf("%d\t", a[i][j]);
printf("\n");

105
Milena VujosevicJanicic 9.1 Matrice

}
}
Ukoliko je potrebna veca eksibilnost, tj. da se dimenzije matrice mogu uneti kao
parametri programa, tada je neophodno koristiti dinamicku alokaciju memorije.
Primer 9.6 Implementacija matrice preko niza.
#include <stdlib.h>
#include <stdio.h>

/* Makro pristupa clanu na poziciji i, j matrice koja ima


m vrsta i n kolona */
#define a(i,j) a[(i)*n+(j)]

main()
{
/* Dimenzije matrice */
int m, n;

/* Matrica */
int *a;

int i,j;

/* Suma elemenata matrice */


int s=0;

/* Unos i alokacija */
printf("Unesi broj vrsta matrice : ");
scanf("%d",&m);

printf("Unesi broj kolona matrice : ");


scanf("%d",&n);

/*Rezervise se prostor za niz a*/


a=(int*)malloc(m*n*sizeof(int));
if (a == NULL) {
printf("Greska prilikom alokacije memorije!\n");
exit(1);
}

for (i=0; i<m; i++)


for (j=0; j<n; j++)
{
printf("Unesi element na poziciji (%d,%d) : ",i,j);

106
Milena VujosevicJanicic 9.1 Matrice

scanf("%d",&a(i,j));
}

/* Racunamo sumu elemenata matrice */


for (i=0; i<m; i++)
for (j=0; j<n; j++)
s+=a(i,j);

/* Ispis unete matrice */


printf("Uneli ste matricu : \n");
for (i=0; i<m; i++)
{ for (j=0; j<n; j++)
printf("%d ",a(i,j));
printf("\n");
}

printf("Suma elemenata matrice je %d\n", s);

/* Oslobadjamo memoriju */
free(a);
}
Primer 9.7 Druga opcija za implementaciju matrice je koristci pokazivac na pokazivac.
1. Definisemo pokazivac na pokazivac na int:
int **p;
Ovaj pokazivac ce cuvati adresu prvog u nizu dinamicki alociranih pokazivaca
na int-ove.
2. Dinamicki alociramo niz od m pokazivaca na int-ove, i adresu prvog u nizu
smestamo u promenljivu p:
p = (int**) malloc(sizeof(int*) * m));
Ovi pokazivaci sluze da pokazuju na prve elemente nizova int-ova koji pred-
stavljaju dinamicki alocirane vrste.
3. Svaku vrstu alociramo posebnim malloc-om, i povratnu adresu smestamo u i-ti
pokazivac u malopre alociranom nizu pokazivaca.
for(i = 0; i < m; i++)
p[i] = malloc(sizeof(int) * n);
Primetimo da nizovi int-ova koji se alociraju nisu morali biti jednakih dimen-
zija (ne moraju svi biti duzine n, kao sto je ovde receno). Ovo moze da bude
korisno, ako znamo da ce u nekoj vrsti biti korisceno samo nekoliko prvih ele-
menata, tada mozemo alocirati manje za tu vrstu, i tako ustedeti prostor.

107
Milena VujosevicJanicic 9.1 Matrice

4. U toku rada se elementima ovako alocirane matrice pristupa sa p[i][j] p[i]


je i-ti pokazivac u nizu, a kako on pokazuje na pocetni element u i-toj vrsti,
tada je p[i][j] upravo j-ti element u i-toj vrsti.
5. Dealokacija se sastoji u brisanju svih vrsta, nakon cega se obrise i niz pokazivaca
(dakle, dealokacija ide u suprotnom redosledu od redosleda alokacije):

for(i = 0; i < m; i++)


free(p[i]);
free(p);

#include <stdio.h>
#include <stdlib.h>

int main()
{
int **p;
int m, n;
int i, j;

printf("Uneti broj vrsta matrice: ");


scanf("%d", &m);
printf("Unesite broj kolona matrice: ");
scanf("%d", &n);

/* Alociramo m pokazivaca na vrste matrice */


if((p = (int**)malloc(sizeof(int*) * m)) == NULL)
{
fprintf(stderr, "malloc() greska\n");
exit(1);
}

/* Alociramo m vrsta od po n int-ova */


for(i = 0; i < m; i++)
if((p[i] = (int*)malloc(sizeof(int) * n)) == NULL)
{
fprintf(stderr, "malloc() greska\n");
exit(1);
}

/* Postavljamo p[i][j] na vrednost abs(i - j) */


for(i = 0; i < m ; i++)
for(j = 0; j < n; j++)
p[i][j] = i - j >=0 ? i - j : j - i;

108
Milena VujosevicJanicic 9.1 Matrice

/* Ispis matrice */
for(i = 0; i < m ; i++)
{
for(j = 0; j < n; j++)
printf("%3d ", p[i][j]);
putchar(\n);
}

/* Oslobadjanje vrsta matrice */


for(i = 0; i < m; i++)
free(p[i]);

/* Oslobadjanje niza pokazivaca */


free(p);

return 0;
}
Primer 9.8 Program ilustruje rad sa kvadratnim matricama i relacijama. Kod za
alokaciju i dealokaciju memorije je izdvojen u funkcije. Element i je u relaciji sa
elementom j ako je m[i][j] = 1, a nisu u relaciji ako je m[i][j] = 0.
#include <stdlib.h>
#include <stdio.h>

/* Dinamicka matrica je odredjena adresom


pocetka niza pokazivaca i dimenzijama tj.
int** a;
int m,n;
*/

/* Alokacija kvadratne matrice nxn */


int** alociraj(int n)
{
int** m;
int i;
m = (int**)malloc(n*sizeof(int*));
if (m == NULL) {
printf("Greska prilikom alokacije memorije!\n");
exit(1);
}

for (i=0; i<n; i++)


{
m[i]=(int*)malloc(n*sizeof(int));
if (m[i] == NULL)

109
Milena VujosevicJanicic 9.1 Matrice

{
int k;
printf("Greska prilikom alokacije memorije!\n");
for(k=0;k<i;k++)
free(m[k]);
free(m);
exit(1);
}
}

return m;
}

/* Dealokacija matrice dimenzije nxn */


void obrisi(int** m, int n)
{
int i;
for (i=0; i<n; i++)
free(m[i]);
free(m);
}

/* Ispis matrice /
void ispisi_matricu(int** m, int n)
{
int i, j;
for (i=0; i<n; i++)
{
for (j=0; j<n; j++)
printf("%d ",m[i][j]);
printf("\n");
}
}

/* Provera da li je relacija predstavljena matricom refleksivna */


int refleksivna(int** m, int n)
{
int i;
for (i=0; i<n; i++)
if (m[i][i]==0)
return 0;

return 1;
}

110
Milena VujosevicJanicic 9.1 Matrice

/* Provera da li je relacija predstavljena matricom simetricna */


int simetricna(int** m, int n)
{
int i,j;
for (i=0; i<n; i++)
for (j=i+1; j<n; j++)
if (m[i][j]!=m[j][i])
return 0;
return 1;
}

/* Provera da li je relacija predstavljena matricom tranzitivna*/


int tranzitivna(int** m, int n)
{
int i,j,k;

for (i=0; i<n; i++)


for (j=0; j<n; j++)
for (k=0; k<n; k++)
if ((m[i][j]==1)
&& (m[j][k]==1)
&& (m[i][k]!=1))
return 0;
return 1;
}

/* Pronalazi najmanju simetricnu relaciju koja sadrzi relaciju a */


void simetricno_zatvorenje(int** a, int n)
{
int i,j;
for (i=0; i<n; i++)
for (j=0; j<n; j++)
{
if (a[i][j]==1 && a[j][i]==0)
a[j][i]=1;
if (a[i][j]==0 && a[j][i]==1)
a[i][j]=1;
}
}

main()
{
int **m;

111
Milena VujosevicJanicic 9.1 Matrice

int n;
int i,j;

printf("Unesi dimenziju matrice : ");


scanf("%d",&n);
m=alociraj(n);

for (i=0; i<n; i++)


for (j=0; j<n; j++)
scanf("%d",&m[i][j]);

printf("Uneli ste matricu : \n");

ispisi_matricu(m,n);

if (refleksivna(m,n))
printf("Relacija je refleksivna\n");
if (simetricna(m,n))
printf("Relacija je simetricna\n");
if (tranzitivna(m,n))
printf("Relacija je tranzitivna\n");

simetricno_zatvorenje(m,n);

ispisi_matricu(m,n);

obrisi(m,n);
}
Primer 9.9 Izracunati vrednost determinante matrice preko Laplasovog razvoja.
#include <stdio.h>
#include <stdlib.h>

/* Funkcija alocira matricu dimenzije nxn */


int** allocate(int n)
{
int **m;
int i;
m=(int**)malloc(n*sizeof(int*));
if (m == NULL) {
printf("Greska prilikom alokacije memorije!\n");
exit(1);
}

for (i=0; i<n; i++)

112
Milena VujosevicJanicic 9.1 Matrice

{
m[i]=malloc(n*sizeof(int));
if (m[i] == NULL)
{
int k;
for(k=0;k<i;k++)
free(m[k]);
printf("Greska prilikom alokacije memorije!\n");
free(m);
exit(1);
}
}

return m;
}

/* Funkcija vrsi dealociranje date matrice dimenzije n */


void deallocate(int** m, int n)
{
int i;
for (i=0; i<n; i++)
free(m[i]);
free(m);
}

/* Funkcija ucitava datu alociranu matricu sa standardnog ulaza */


void ucitaj_matricu(int** matrica, int n)
{
int i,j;
for (i=0; i<n; i++)
for (j=0; j<n; j++)
scanf("%d",&matrica[i][j]);
}

/* Rekurzivna funkcija koja vrsi Laplasov razvoj */


int determinanta(int** matrica, int n)
{
int i;
int** podmatrica;
int det=0,znak;

/* Izlaz iz rekurzije je matrica 1x1 */


if (n==1) return matrica[0][0];

113
Milena VujosevicJanicic 9.2 Realokacija memorije

/* Podmatrica ce da sadrzi minore polazne matrice */


podmatrica=allocate(n-1);
znak=1;
for (i=0; i<n; i++)
{
int vrsta,kolona;
for (kolona=0; kolona<i; kolona++)
for(vrsta=1; vrsta<n; vrsta++)
podmatrica[vrsta-1][kolona] = matrica[vrsta][kolona];
for (kolona=i+1; kolona<n; kolona++)
for(vrsta=1; vrsta<n; vrsta++)
podmatrica[vrsta-1][kolona-1] = matrica[vrsta][kolona];

det+= znak*matrica[0][i]*determinanta(podmatrica,n-1);
znak*=-1;
}
deallocate(podmatrica,n-1);
return det;
}

main()
{
int **matrica;
int n;

scanf("%d", &n);
matrica = allocate(n);
ucitaj_matricu(matrica, n);
printf("Determinanta je : %d\n",determinanta(matrica,n));
deallocate(matrica, n);
}

9.2 Realokacija memorije


Primer 9.10 Dinamicki niz.
/* Program za svaku rec unetu sa standardnog
ulaza ispisuje broj pojavljivanja.
Verzija sa dinamickim nizom i realokacijom.
*/

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

114
Milena VujosevicJanicic 9.2 Realokacija memorije

/* Rec je opisana imenom i brojem pojavljivanja */


typedef struct _rec
{ char ime[80];
int br_pojavljivanja;
} rec;

/* Realokacija se vrsi sa datim korakom */


#define KORAK 10

/* Funkcija ucitava rec i vraca njenu duzinu ili


-1 ukoliko smo dosli do znaka EOF*/
int getword(char word[],int max)
{
int c, i=0;

while (isspace(c=getchar()))
;

while(!isspace(c) && c!=EOF && i<max-1)


{
word[i++]=c;
c = getchar();
}

word[i]=\0;

if (c==EOF) return -1;


else return i;
}

main()
{

/* Dinamicki niz reci je opisan pokazivacem na


pocetak, tekucim brojem upisanih elemenata i
tekucim brojem alociranih elemenata */
rec* niz_reci;
int duzina=0;
int alocirano=0;

char procitana_rec[80];
int i;

115
Milena VujosevicJanicic 9.2 Realokacija memorije

while (getword(procitana_rec,80)!=-1)
{
/* Proveravamo da li rec vec postoji u nizu */
for (i=0; i<duzina; i++)
/* Ako bismo uporedili procitana_rec == niz_reci[i].ime
bili bi uporedjeni pokazivaci a ne odgovarajuci sadrzaji.
Zato koristimo strcmp. */
if (strcmp(procitana_rec, niz_reci[i].ime)==0)
{
niz_reci[i].br_pojavljivanja++;
break;
}

/* Ukoliko rec ne postoji u nizu */


if (i==duzina)
{
rec nova_rec;
/* Ako bismo dodelili nova_rec.ime = procitana_rec
izvrsila bi se dodela pokazivaca a ne kopiranje niske
procitana_rec u nova_rec.ime. Zato koristimo strcpy. */
strcpy(nova_rec.ime,procitana_rec);
nova_rec.br_pojavljivanja=1;

/* Ukoliko je niz "kompletno popunjen" vrsimo realokaciju */


if (duzina==alocirano)
{
alocirano+=KORAK;

/* Sledeca linija zamenjuje blok koji sledi i moze se


koristiti alternativno. Blok je ostavljen samo da bi
demonstrirao korisnu tehniku */
/* niz_reci=realloc(niz_reci, (alocirano)*sizeof(rec)); */
{
/* alociramo novi niz, veci nego sto je bio prethodni */
rec* novi_niz=(rec *)malloc(alocirano*sizeof(rec));

if (novi_niz == NULL)
{
free(niz_reci);
printf("Greska prilikom alokacije memorije");
exit(1);
}

/* Kopiramo elemente starog niza u novi */

116
Milena VujosevicJanicic 9.2 Realokacija memorije

for (i=0; i<duzina; i++)


novi_niz[i]=niz_reci[i];

/* Uklanjamo stari niz */


free(niz_reci);

/* Stari niz postaje novi */


niz_reci=novi_niz;
}
}
/* Upisujemo rec u niz */
niz_reci[duzina]=nova_rec;
duzina++;
}
}

/* Ispisujemo elemente niza */


for(i=0; i<duzina; i++)
printf("%s - %d\n",niz_reci[i].ime, niz_reci[i].br_pojavljivanja);

free(niz_reci);
}

117
Glava 10

Liste

Jednostruko povezana lista1 je struktura podataka koja se sastoji od sekvence cvorova.


Svaki cvor sadrzi podatak (odredenog tipa) i pokazivac na sledeci cvor u sekvenci.
Prvi cvor u sekvenci naziva se glava liste. Ostatak liste (bez glave) je takode lista,
i naziva se rep liste. Lista koja ne sadrzi cvorove naziva se prazna lista. Prilikom
baratanja listom mi cuvamo pokazivac na glavu liste. Kada pristupimo glavi liste, u
njoj imamo zapisanu adresu sledeceg elementa, pa mu samim tim mozemo pristupiti.
Kada mu pristupimo, u njemu je sadrzana adresa sledeceg elementa, pa preko tog
pokazivaca mozemo da mu pristupimo, itd. Poslednji element u listi nema sledeci
element: u tom slucaju se njegov pokazivac na sledeci postavlja na NULL. Takode,
prazna lista se predstavlja NULL pokazivacem.
Prednost koriscenja povezanih lista u odnosu na dinamicki niz je u tome sto se
elementi mogu e kasno umetati i brisati sa bilo koje pozicije u nizu, bez potrebe
za realokacijom ili premestanjem elemenata. Nedostatak ovakvog pristupa je to sto
ne mozemo nasumicno pristupiti proizvoljnom elementu, vec se elementi moraju
obradivati redom (iteracijom kroz listu).

10.1 Implementacija
Prilikom promene liste (dodavanje novog elementa, brisanje elementa, premestanje
elemenata, itd.) postoji mogucnost da glava liste bude promenjena, tj. da to postane
neki drugi cvor (sa drugom adresom). U tom slucaju se pokazivac na glavu liste mora
azurirati. Kada promenu liste obavljamo u posebnoj funkciji (kao sto je bio slucaj u
prethodnom primeru, gde smo za dodavanje i brisanje imali posebne funkcije) onda
je potrebno da se pozivajucoj funkciji vrati informacija o promeni adrese glave,
kako bi pozivajuca funkcija mogla da azurira svoju pokazivacku promenljivu. Ovo
se moze uraditi na dva nacina:
1. Pozvana funkcija koja vrsi promenu na listi vraca kao povratnu vrednost adresu
glave nakon promene. Ova adresa moze biti ista kao i pre promene (ako glava
nije dirana) a moze se i razlikovati. U svakom slucaju, ta adresa treba da se
dodeli pokazivackoj promenljivoj koja cuva adresu glave u pozivajucoj funkciji.
1 Tekst preuzet sa sajta www.matf.bg.ac.rs/ milan

118
Milena VujosevicJanicic 10.1 Implementacija

Zbog toga se funkcija za promenu liste uvek poziva na sledeci nacin:


pok = funkcija_za_promenu(pok, ...);
tj. promenljivoj cija se vrednost predaje kao adresa glave u pozivu mora se do-
deliti povratna vrednost funkcije, za slucaj da je adresa glave interno promen-
jena.
2. Pozvana funkcija koja vrsi promenu na listi prihvata kao argument pokazivac
na pokazivacku promenljivu koja u pozivajucoj funkciji cuva adresu glave i
koju eventalno treba azurirati. Sada pozvana funkcija moze interno da preko
dobijenog pokazivaca promeni promenljivu pozivajuce funkcije direktno. Na
primer:
funkcija_za_promenu(&pok, ...);
Funkcija koja se poziva je po pravilu tipa void. Prednost drugog metoda je
jednostavnije pozivanje, dok je prednost prvog metoda jednostavnija sintaksa
unutar pozvane funkcije.
U prethodnom primeru je demonstriran prvi pristup. Naredni primer ilustruje drugi
pristup.
Primer 10.1 Osnovne funkcije za rad sa listama.
#include <stdio.h>
#include <stdlib.h>

/* Struktura koja predstavlja cvor liste */


typedef struct cvor {
int vrednost; /* podatak koji cvor sadrzi */
struct cvor *sledeci; /* pokazivac na sledeci cvor */
} Cvor;

/* Pomocna funkcija koja kreira cvor. Funkcija vrednost


novog cvora inicijalizuje na broj, dok pokazivac na
sledeci cvor u novom cvoru postavlja na NULL. Funkcija
ispisuje poruku o gresci i prekida program u slucaju
da malloc() funkcija ne uspe da alocira prostor.
Funkcija vraca pokazivac na novokreirani cvor */
Cvor* napravi_cvor(int broj)
{
Cvor *novi = NULL;
if((novi = (Cvor *) malloc(sizeof(Cvor))) == NULL)
{
fprintf(stderr,"malloc() greska!\n");
exit(1);
}

novi->vrednost = broj;
novi->sledeci = NULL;

119
Milena VujosevicJanicic 10.1 Implementacija

return novi;
}

/* Funkcija dodaje novi cvor na pocetak liste. Funkcija


kreira novi cvor koriscenjem funkcije napravi_cvor().
Funkcija vraca pokazivac na novu glavu liste */
Cvor* dodaj_na_pocetak_liste(Cvor *glava, int broj)
{
Cvor * novi = napravi_cvor(broj);
novi->sledeci = glava;
return novi;
}

/*void dodaj_na_pocetak_liste(Cvor **glava, int broj)


{
Cvor *novi = napravi_cvor(broj);
novi->sledeci = *glava;
*glava = novi;
}
*/

/* Funkcija dodaje novi cvor na kraj liste. Funkcija


kreira novi cvor koriscenjem funkcije napravi_cvor().
Funkcija vraca pokazivac na glavu liste (koji moze
biti promenjen u slucaju da je lista inicijalno bila
prazna). */
Cvor* dodaj_na_kraj_liste(Cvor *glava, int broj)
{
Cvor * novi = napravi_cvor(broj);
Cvor *tekuci = glava;

/* slucaj prazne liste. U tom slucaju je glava nove liste


upravo novi cvor. */
if(glava == NULL) return novi;

/* Ako lista nije prazna, tada se krecemo duz liste sve dok
ne dodjemo do poslednjeg cvora (tj. do cvora ciji pokazivac
na sledeci pokazuje na NULL) */
while(tekuci->sledeci != NULL)
tekuci = tekuci->sledeci;

/* Dodajemo novi element na kraj preusmeravanjem pokazivaca */


tekuci->sledeci = novi;

120
Milena VujosevicJanicic 10.1 Implementacija

/* Vracamo pokazivac na glavu liste */


return glava;
}

/*void dodaj_na_kraj_liste(Cvor **glava, int broj)


{
Cvor *novi = napravi_cvor(broj);
Cvor *tekuci = *glava;

/* slucaj prazne liste. U tom slucaju je glava nove liste


upravo novi cvor. */
if(*glava == NULL)
{
*glava = novi;
return;
}

/* Ako lista nije prazna, tada se krecemo duz liste sve dok
ne dodjemo do poslednjeg cvora (tj. do cvora ciji pokazivac
na sledeci pokazuje na NULL) */
while(tekuci->sledeci != NULL)
tekuci = tekuci->sledeci;

/* Dodajemo novi element na kraj preusmeravanjem pokazivaca */


tekuci->sledeci = novi;
}
*/

/* Funkcija trazi u listi element cija je vrednost jednaka


datom broju. Funkcija vraca pokazivac na cvor liste u
kome je sadrzan trazeni broj ili NULL u slucaju da takav
element ne postoji u listi */
Cvor* pretrazi_listu(Cvor *glava, int broj)
{
for(; glava != NULL ; glava = glava->sledeci)
if(glava->vrednost == broj)
return glava;

return NULL;
}

/* Funkcija prikazuje elemente liste pocev


od glave ka kraju liste */
void prikazi_listu(Cvor *glava)

121
Milena VujosevicJanicic 10.1 Implementacija

{
putchar([);
for(;glava != NULL; glava = glava->sledeci)
printf("%d ", glava->vrednost);
putchar(]);

putchar(\n);
}

/* Funkcija oslobadja dinamicku memoriju zauzetu


od strane liste. Funkcija vraca NULL, tj.
vrednost koju treba dodeliti pokazivackoj
promenljivoj, s obzirom da je sada lista prazna. */
Cvor* oslobodi_listu(Cvor *glava)
{
Cvor *pomocni;

while(glava != NULL)
{
/* moramo najpre zapamtiti adresu sledeceg
elementa, a tek onda osloboditi glavu */
pomocni = glava->sledeci;
free(glava);
glava = pomocni;
}
return NULL;
}

/*void oslobodi_listu(Cvor **glava)


{
Cvor *pomocni;

while(*glava != NULL)
{
/* moramo najpre zapamtiti adresu sledeceg
elementa, a tek onda osloboditi glavu */
pomocni = (*glava)->sledeci;
free(*glava);
*glava = pomocni;
}
}
*/

/* Funkcija dodaje novi element u sortiranu listu tako da i nova

122
Milena VujosevicJanicic 10.1 Implementacija

lista ostane sortirana. Funkcija kreira novi cvor koriscenjem


funkcije napravi_cvor(). Funkcija vraca pokazivac na glavu liste
(koji moze biti promenjen u slucaju da je novi element dodat na
pocetak liste) */
Cvor* dodaj_sortirano(Cvor *glava, int broj)
{
Cvor *novi = napravi_cvor(broj);
Cvor *tekuci = glava;

/* u slucaju prazne liste glava nove liste je


upravo novi element */
if(glava == NULL) return novi;

/* ako je novi element manji ili jednak od glave,


tada novi element mora da bude nova glava */
if(glava->vrednost >= novi->vrednost)
{
novi->sledeci = glava;
return novi;
}

/* u slucaju da je glava manja od novog elementa, tada se krecemo kroz


listu sve dok se ne dodje do elementa ciji je sledeci element veci ili
jednak od novog elementa, ili dok se ne dodje do poslednjeg elementa. */
while(tekuci->sledeci != NULL && tekuci->sledeci->vrednost < novi->vrednost)
tekuci = tekuci->sledeci;

/* U svakom slucaju novi element dodajemo IZA tekuceg elementa */


novi->sledeci = tekuci->sledeci;
tekuci->sledeci = novi;

/* vracamo pokazivac na glavu liste*/


return glava;
}

/* void dodaj_sortirano(Cvor **glava, int broj)


{
Cvor *novi = napravi_cvor(broj);
Cvor *tekuci = *glava;

/* u slucaju prazne liste glava nove liste je


upravo novi element */
if(*glava == NULL)
{

123
Milena VujosevicJanicic 10.1 Implementacija

*glava = novi;
return;
}

/* ako je novi element manji ili jednak od glave,


tada novi element mora da bude nova glava */
if((*glava)->vrednost >= novi->vrednost)
{
novi->sledeci = *glava;
*glava = novi;
return;
}

/* u slucaju da je glava manja od novog elementa, tada se krecemo kroz


listu sve dok se ne dodje do elementa ciji je sledeci element veci ili
jednak od novog elementa, ili dok se ne dodje do poslednjeg elementa. */
while(tekuci->sledeci != NULL && tekuci->sledeci->vrednost < novi->vrednost)
tekuci = tekuci->sledeci;

/* U svakom slucaju novi element dodajemo IZA tekuceg elementa */


novi->sledeci = tekuci->sledeci;
tekuci->sledeci = novi;
}
*/

/* Funkcija brise iz liste sve cvorove koji sadrze dati broj.


Funkcija vraca pokazivac na glavu liste (koji moze biti
promenjen u slucaju da se obrise stara glava) */
Cvor* obrisi_element(Cvor *glava, int broj)
{
Cvor *tekuci;
Cvor *pomocni;

/* Brisemo sa pocetka liste sve eventualne cvorove


koji su jednaki datom broju, i azuriramo pokazivac
na glavu */
while(glava != NULL && glava->vrednost == broj)
{
pomocni = glava->sledeci;
free(glava);
glava = pomocni;
}

/* Ako je nakon toga lista ostala prazna vracamo

124
Milena VujosevicJanicic 10.1 Implementacija

NULL */
if(glava == NULL) return NULL;

/* Od ovog trenutka se u svakom koraku nalazimo


na tekucem cvoru koji je razlicit od trazenog
broja (kao i svi levo od njega). Poredimo
vrednost sledeceg cvora (ako postoji) sa trazenim
brojem i brisemo ga ako je jednak, a prelazimo na
sledeci cvor ako je razlicit. Ovaj postupak ponavljamo
dok ne dodjemo do poslednjeg cvora. */
tekuci = glava;
while(tekuci->sledeci != NULL)
if(tekuci->sledeci->vrednost == broj)
{
pomocni = tekuci->sledeci;
tekuci->sledeci = tekuci->sledeci->sledeci;
free(pomocni);
}
else tekuci = tekuci->sledeci;

/* vracamo novu glavu */


return glava;
}

/* void obrisi_element(Cvor **glava, int broj)


{
Cvor *tekuci;
Cvor *pomocni;

/* Brisemo sa pocetka liste sve eventualne cvorove


koji su jednaki datom broju, i azuriramo pokazivac
na glavu */
while(*glava != NULL && (*glava)->vrednost == broj)
{
pomocni = (*glava)->sledeci;
free(*glava);
*glava = pomocni;
}

/* Ako je nakon toga lista ostala prazna prekidamo


funkciju */
if(*glava == NULL) return;

/* Od ovog trenutka se u svakom koraku nalazimo

125
Milena VujosevicJanicic 10.1 Implementacija

na tekucem cvoru koji je razlicit od trazenog


broja (kao i svi levo od njega). Poredimo
vrednost sledeceg cvora (ako postoji) sa trazenim
brojem i brisemo ga ako je jednak, a prelazimo na
sledeci cvor ako je razlicit. Ovaj postupak ponavljamo
dok ne dodjemo do poslednjeg cvora. */
tekuci = *glava;
while(tekuci->sledeci != NULL)
if(tekuci->sledeci->vrednost == broj)
{
pomocni = tekuci->sledeci;
tekuci->sledeci = tekuci->sledeci->sledeci;
free(pomocni);
}
else tekuci = tekuci->sledeci;

return;
}
*/
/* test program */
int main()
{

Cvor *glava = NULL;


Cvor *pomocni = NULL;
int broj;

/* Testiranje dodavanja na pocetak */


printf("-------------------------------------------------------\n");
printf("---------- Testiranje dodavanja na pocetak ------------\n");
do {
printf("-------------------------------------------------------\n");
printf("Prikaz trenutnog sadrzaja liste:\n");
prikazi_listu(glava);
printf("-------------------------------------------------------\n");
printf("Dodati element na pocetak liste (ctrl-D za kraj unosa):\n");
} while(scanf("%d", &broj) > 0 &&
(glava = dodaj_na_pocetak_liste(glava, broj)) );
/* dodaj_na_pocetak_liste(&glava, broj);*/
printf("-------------------------------------------------------\n");
putchar(\n);

/* Testiranje pretrage elementa */

126
Milena VujosevicJanicic 10.1 Implementacija

printf("-------------------------------------------------------\n");
printf("---------------- Testiranje pretrage ------------------\n");
printf("-------------------------------------------------------\n");
printf("Prikaz trenutnog sadrzaja liste:\n");
prikazi_listu(glava);
printf("-------------------------------------------------------\n");
printf("Uneti broj koji se trazi: ");
scanf("%d",&broj);

if((pomocni = pretrazi_listu(glava, broj)) == NULL)


printf("Trazeni broj nije u listi\n");
else
printf("Trazeni element %d je u listi\n", pomocni->vrednost);
printf("-------------------------------------------------------\n");
putchar(\n);

glava = oslobodi_listu(glava);
/*oslobodi_listu(&glava);*/

/* Testiranje dodavanja na kraj */


printf("-------------------------------------------------------\n");
printf("------------ Testiranje dodavanja na kraj -------------\n");
do{
printf("-------------------------------------------------------\n");
printf("Prikaz liste:\n");
prikazi_listu(glava);
printf("-------------------------------------------------------\n");
printf("Dodati element na kraj liste (ctrl-D za kraj unosa):\n");
} while(scanf("%d",&broj) > 0 &&
(glava = dodaj_na_kraj_liste(glava, broj)));
/*(dodaj_na_kraj_liste(&glava,broj)));*/
printf("-------------------------------------------------------\n");
putchar(\n);

/* Testiranje brisanja elemenata */


printf("-------------------------------------------------------\n");
printf("--------------- Testiranje brisanja -------------------\n");
printf("-------------------------------------------------------\n");
printf("Prikaz trenutnog sadrzaja liste:\n");
prikazi_listu(glava);
printf("-------------------------------------------------------\n");
printf("Uneti broj koji se brise: ");
scanf("%d", &broj);

127
Milena VujosevicJanicic 10.1 Implementacija

glava = obrisi_element(glava, broj);


/* obrisi_element(&glava, broj); */
printf("-------------------------------------------------------\n");
printf("Lista nakon izbacivanja:\n");
prikazi_listu(glava);
printf("-------------------------------------------------------\n");
putchar(\n);

glava = oslobodi_listu(glava);
/*oslobodi_listu(&glava);*/

/* Testiranje sortiranog dodavanja */


printf("-------------------------------------------------------\n");
printf("----------- Testiranje sortiranog dodavanja -----------\n");
do{
printf("-------------------------------------------------------\n");
printf("Prikaz liste:\n");
prikazi_listu(glava);
printf("-------------------------------------------------------\n");
printf("Dodati element sortirano (ctrl-D za kraj unosa):\n");
} while(scanf("%d",&broj) > 0 &&
(glava = dodaj_sortirano(glava, broj)));
/*(dodaj_sortirano(&glava, broj)));*/
printf("-------------------------------------------------------\n");
putchar(\n);

glava = oslobodi_listu(glava);
/*oslobodi_listu(&glava);*/

return 0;
}
Primer 10.2 Sve funkcije iz prethodnih primera, za koje to ima smisla, definisane
su rekurzivno. Primetno je da su ove rekurzivne varijante mnogo jednostavnije.
Razlog je to sto su liste po svojoj prirodi rekurzivne strukture. Naime, liste se mogu
rekurzivno definisati na sledeci nacin:
 objekat oznacen sa [] je lista (prazna lista)
 ako je L lista, i G neki element, tada je uredeni par (G,L) takode lista. Element
G nazivamo glavom liste, a listu L repom liste.
Na primer, uredjeni par (2, []) je lista, i po dogovoru cemo je zapisivati kao [2].
Takodje par (3,[2]) je lista koju mozemo zapisati kao [3 2], itd.
U opstem slucaju, ako je L=[a1 a2 a3 ... an] lista, i ako je b neki element,
tada je uredjeni par (b,L) takode lista, koju mozemo zapisati kao [b a1 a2 ... an].

128
Milena VujosevicJanicic 10.1 Implementacija

Glava liste je b, a rep liste je lista L. Sada se obrada liste moze razdvojiti na dva
dela:
 Izvrsiti operaciju nad glavom liste
 Izvrsiti rekurzivni postupak nad repom liste (koji je takode lista).
Za testiranje narednog programa moze se koristiti main funkcija iz primera 10.1.
#include <stdio.h>
#include <stdlib.h>

/* Struktura koja predstavlja cvor liste */


typedef struct cvor {
int vrednost; /* podatak koji cvor sadrzi */
struct cvor *sledeci; /* pokazivac na sledeci cvor */
} Cvor;

/* Pomocna funkcija koja kreira cvor. Funkcija vrednost


novog cvora inicijalizuje na broj, dok pokazivac na
sledeci cvor u novom cvoru postavlja na NULL. Funkcija
ispisuje poruku o gresci i prekida program u slucaju
da malloc() funkcija ne uspe da alocira prostor.
Funkcija vraca pokazivac na novokreirani cvor */
Cvor* napravi_cvor(int broj)
{
Cvor *novi = NULL;
if((novi = (Cvor *) malloc(sizeof(Cvor))) == NULL)
{
fprintf(stderr,"malloc() greska!\n");
exit(1);
}

novi->vrednost = broj;
novi->sledeci = NULL;
return novi;
}

/* Funkcija dodaje novi cvor na pocetak liste. Funkcija


kreira novi cvor koriscenjem funkcije napravi_cvor().
Funkcija vraca pokazivac na novu glavu liste */
Cvor* dodaj_na_pocetak_liste(Cvor *glava, int broj)
{
Cvor * novi = napravi_cvor(broj);
novi->sledeci = glava;
return novi;

129
Milena VujosevicJanicic 10.1 Implementacija

}
/*
void dodaj_na_pocetak_liste(Cvor **glava, int broj)
{
Cvor * novi = napravi_cvor(broj);
novi->sledeci = *glava;
*glava = novi;
}
*/

/* Funkcija dodaje novi cvor na kraj liste. Funkcija


kreira novi cvor koriscenjem funkcije napravi_cvor().
Funkcija vraca pokazivac na glavu liste (koji moze
biti promenjen u slucaju da je lista inicijalno bila
prazna). Funkcija koristi rekurziju. */
Cvor* dodaj_na_kraj_liste(Cvor *glava, int broj)
{
/* Izlaz iz rekurzije: slucaj prazne liste.
U tom slucaju je glava nove liste upravo novi cvor. */
if(glava == NULL) return napravi_cvor(broj);

/* U slucaju da je lista neprazna, tada ona ima glavu i rep,


pri cemu je rep opet lista. Tada je dodavanje na kraj
liste ekvivalentno dodavanju na kraj repa liste, sto
radimo rekurzivnim pozivom. Povratna vrednost rekurzivnog
poziva je adresa glave modifikovanog repa liste koja se
treba sacuvati u pokazivacu na sledeci u glavi */
glava->sledeci = dodaj_na_kraj_liste(glava->sledeci, broj);

/* Vracamo glavu liste, koja je mozda izmenjena */


return glava;
}

/*
void dodaj_na_kraj_liste(Cvor **glava, int broj)
{
/* Izlaz iz rekurzije: slucaj prazne liste.
U tom slucaju je glava nove liste upravo novi cvor. */
if(*glava == NULL)
*glava = napravi_cvor(broj);
else
/* U slucaju da je lista neprazna, tada ona ima glavu i rep,
pri cemu je rep opet lista. Tada je dodavanje na kraj
liste ekvivalentno dodavanju na kraj repa liste, sto

130
Milena VujosevicJanicic 10.1 Implementacija

radimo rekurzivnim pozivom. */


dodaj_na_kraj_liste(&(*glava->sledeci), broj);
}

*/

/* Funkcija dodaje novi element u sortiranu listu tako da i nova


lista ostane sortirana. Funkcija kreira novi cvor koriscenjem
funkcije napravi_cvor(). Funkcija vraca pokazivac na glavu liste
(koji moze biti promenjen u slucaju da je novi element dodat na
pocetak liste). Funkcija koristi rekurziju. */
Cvor* dodaj_sortirano(Cvor *glava, int broj)
{
/* u slucaju da je lista prazna, ili da je vrednost
glave veca ili jednaka od vrednosti broja koji
umecemo, tada se novi cvor umece na pocetak liste. */
if(glava == NULL || glava->vrednost >= broj)
{
Cvor *novi = napravi_cvor(broj);
novi->sledeci = glava;
return novi;
}

/* U slucaju da je lista neprazna, i da je vrednost


glave manja od vrednosti broja koji umecemo u listu,
tada je sigurno da se novi element umece DESNO od glave,
tj. u rep liste. Dakle, mozemo rekurzivno pozvati istu
funkciju za rep liste. S obzirom da po induktivnoj
pretpostavci rep nakon toga ostaje sortiran, a svi
elementi u repu ukljucujuci i element koji je dodat
su jednaki ili veci od glave, tada ce i cela lista
biti sortirana. Povratna vrednost rekurzivnog poziva
predstavlja adresu glave modifikovanog repa liste,
pa se ta adresa mora sacuvati u pokazivacu na sledeci
u glavi liste. */
glava->sledeci = dodaj_sortirano(glava->sledeci, broj);

/* vracamo staru - novu glavu */


return glava;
}

/*
void dodaj_sortirano(Cvor **glava, int broj)
{

131
Milena VujosevicJanicic 10.1 Implementacija

/* u slucaju da je lista prazna, ili da je vrednost


glave veca ili jednaka od vrednosti broja koji
umecemo, tada se novi cvor umece na pocetak liste. */
if(*glava == NULL || *glava->vrednost >= broj)
{
Cvor *novi = napravi_cvor(broj);
novi->sledeci = *glava;
*glava = novi;
}
else
/* U slucaju da je lista neprazna, i da je vrednost
glave manja od vrednosti broja koji umecemo u listu,
tada je sigurno da se novi element umece DESNO od glave,
tj. u rep liste. Dakle, mozemo rekurzivno pozvati istu
funkciju za rep liste. S obzirom da po induktivnoj
pretpostavci rep nakon toga ostaje sortiran, a svi
elementi u repu ukljucujuci i element koji je dodat
su jednaki ili veci od glave, tada ce i cela lista
biti sortirana.*/
dodaj_sortirano(&(*glava->sledeci), broj);
}
*/

/* Funkcija trazi u listi element cija je vrednost jednaka


datom broju. Funkcija vraca pokazivac na cvor liste u
kome je sadrzan trazeni broj ili NULL u slucaju da takav
element ne postoji u listi. Funkcija koristi rekurziju. */
Cvor* pretrazi_listu(Cvor *glava, int broj)
{
/* Izlaz iz rekurzije: prazna lista */
if(glava == NULL) return NULL;

/* ako je glava jednaka datom broju, vracamo adresu glave */


if(glava->vrednost == broj)
return glava;
/* u suprotnom pretrazujemo rep rekurzivnim pozivom i vracamo
ono sto taj rekurzivni poziv vrati */
else
return pretrazi_listu(glava->sledeci, broj);

/* Funkcija brise iz liste sve cvorove koji sadrze dati broj.


Funkcija vraca pokazivac na glavu liste (koji moze biti

132
Milena VujosevicJanicic 10.1 Implementacija

promenjen u slucaju da se obrise stara glava). Funkcija


koristi rekurziju. */
Cvor* obrisi_element(Cvor *glava, int broj)
{

/* Izlaz iz rekurzije: prazna lista ostaje prazna nakon


brisanja elemenata koji su jednaki sa brojem */
if(glava == NULL) return NULL;

/* Rekurzivno iz repa uklanjamo sve pojave datog broja.


Rekurzivni poziv vraca adresu glave tako modifikovanog
repa, koja se cuva u pokazivacu na sledeci u okviru glave */
glava->sledeci = obrisi_element(glava->sledeci, broj);

/* Nakon ovoga znamo da u repu nema pojava datog broja. Jedino


ostaje da proverimo jos i glavu, i da je po potrebi obrisemo */
if(glava->vrednost == broj)
{
Cvor *pomocni = glava;
glava = glava->sledeci;
free(pomocni);
}

/* vracamo novu glavu */


return glava;
}

/*
void obrisi_element(Cvor **glava, int broj)
{

/* Izlaz iz rekurzije: prazna lista ostaje prazna nakon


brisanja elemenata koji su jednaki sa brojem */
if(*glava == NULL) return;

/* Rekurzivno iz repa uklanjamo sve pojave datog broja.


Rekurzivni poziv vraca adresu glave tako modifikovanog
repa, koja se cuva u pokazivacu na sledeci u okviru glave */
obrisi_element(&(*glava->sledeci), broj);

/* Nakon ovoga znamo da u repu nema pojava datog broja. Jedino


ostaje da proverimo jos i glavu, i da je po potrebi obrisemo */

133
Milena VujosevicJanicic 10.1 Implementacija

if(*glava->vrednost == broj)
{
Cvor *pomocni = *glava;
*glava = *glava->sledeci;
free(pomocni);
}
}
*/

/* Pomocna rekurzivna funkcija koja prikazuje


listu. Definisana je kao static, cime se
sprecava njeno koriscenje od strane funkcija
koje nisu definisane u ovom fajlu */
static void prikazi_listu_r(Cvor *glava)
{

/* Izlaz iz rekurzije */
if(glava == NULL) return;

/* Prikaz glave */
printf("%d ", glava->vrednost);

/* Prikaz repa (rekurzivnim pozivom) */


prikazi_listu_r(glava->sledeci);

/* Funkcija prikazuje elemente liste pocev od glave


ka kraju liste. Koristi rekurzivnu funkciju
prikazi_listu_r(). Ova funkcija prosto dodaje
uglaste zagrade i novi red na kraju ispisa. */
void prikazi_listu(Cvor *glava)
{
putchar([);

prikazi_listu_r(glava);

putchar(]);

putchar(\n);
}

/* Funkcija oslobadja dinamicku memoriju zauzetu


od strane liste. Funkcija koristi rekurziju. */

134
Milena VujosevicJanicic 10.1 Implementacija

Cvor* oslobodi_listu(Cvor *glava)


{
/* Izlaz iz rekurzije */
if(glava == NULL) return NULL;

/* Oslobadjamo rep liste */


oslobodi_listu(glava->sledeci);

/* Oslobadjamo glavu liste */


free(glava);

return NULL;
}

/*
void oslobodi_listu(Cvor **glava)
{
/* Izlaz iz rekurzije */
if(*glava == NULL) return;

/* Oslobadjamo rep liste */


oslobodi_listu(&(*glava->sledeci));

/* Oslobadjamo glavu liste */


free(*glava);

*glava = NULL;
}
*/
Primer 10.3 Program ispisuje broj pojavljivanja za svaku od reci koja se pojavila u
tekstu unetom sa standardnog ulaza. Verzija sa (sortiranom) listom.
#include <stdlib.h>
#include <stdio.h>

/* Definicija cvora liste */


typedef struct _cvor
{
char ime[80];
int br_pojavljivanja;
struct _cvor* sledeci;
} cvor;

/* Pomocna funkcija koja kreira cvor.


Funkcija vraca pokazivac na novokreirani cvor */

135
Milena VujosevicJanicic 10.1 Implementacija

cvor* napravi_cvor(char* rec)


{
cvor *novi = NULL;
if((novi = (cvor *) malloc(sizeof(cvor))) == NULL)
{
fprintf(stderr,"malloc() greska!\n");
exit(1);
}

strcpy(novi->ime, rec);
novi->br_pojavljivanja = 1;
novi->sledeci = NULL;
return novi;
}

/* Funkcija ispisuje listu rekurzivno, pocevsi od poslednjeg


elementa */
void ispisi_listu(cvor* pocetak)
{
if (pocetak!=NULL)
{
ispisi_listu(pocetak->sledeci);
printf("%s %d\n",pocetak->ime,pocetak->br_pojavljivanja);
}
}

/* Funkcija koja brise listu */


void obrisi_listu(cvor* pocetak)
{
if (pocetak!=NULL)
{
obrisi_listu(pocetak->sledeci);
free(pocetak);
}
}

/* Funkcija ubacuje rekurzivno datu rec u listu koja je


leksikografski sortirana, na odgovarajuce mesto i vraca
pokazivac na novi pocetak liste */
cvor* ubaci_sortirano(cvor* pocetak, char* rec)
{
int cmp;
/* Ukoliko je lista prazna ubacujemo na pocetak liste*/
if (pocetak==NULL)

136
Milena VujosevicJanicic 10.1 Implementacija

return napravi_cvor(rec);

/* Ukoliko lista nije prazna poredimo rec sa elementom u glavi */


cmp=strcmp(pocetak->ime,rec);
/* Ukoliko je rec pronadjena samo uvecavamo njen broj
pojavljivanja */
if (cmp==0)
{ pocetak->br_pojavljivanja++;
return pocetak;
}
/* Ukoliko je rec koju ubacujemo veca od tekuce reci, ubacujemo je
rekurzivno u rep */
else if (cmp>0)
{ pocetak->sledeci=ubaci_sortirano(pocetak->sledeci,rec);
return pocetak;
}
/* Ukoliko je rec koju ubacujemo manja od tekuce reci, gradimo novi
cvor i ubacujemo ga ispred pocetka */
else
{
cvor* novi=napravi_cvor(rec);
novi->sledeci=pocetak;
return novi;
}
}

/* Pomocna funkcija koja cita rec sa standardnog ulaza i vraca


njenu duzinu, odnosno -1 ukoliko se naidje na EOF */
int getword(char word[], int lim) {
int c, i=0;
while (!isalpha(c=getchar()) && c!=EOF)
;

if (c==EOF)
return -1;
do
{ word[i++]=c;
}while (i<lim-1 && isalpha(c=getchar()));

word[i]=\0;
return i;
}

/* Funkcija koja rekurzivno pronalazi datu rec u datoj listi.

137
Milena VujosevicJanicic 10.1 Implementacija

Funkcija vraca pokazivac na cvor u kome je nadjena rec, ili


NULL ukoliko rec nije nadjena. */
cvor* nadji_rec(cvor* lista, char rec[])
{
if (lista==NULL)
return NULL;
if (strcmp(lista->ime,rec)==0)
return lista;
/* Da bi pretrazivanje u sortiranoj listi
bilo efikasnije:
if (strcmp(lista->ime,rec)<0)
return NULL;
*/
return nadji_rec(lista->sledeci,rec);
}

main()
{
cvor* lista=NULL;
char procitana_rec[80];
cvor* pronadjen;

while(getword(procitana_rec,80)!=-1)
lista=ubaci_sortirano(lista,procitana_rec);

pronadjen=nadji_rec(lista,"programiranje");
if (pronadjen!=NULL)
printf("Rec programiranje se javlja u listi!\n");
else
printf("Rec programiranje se ne javlja u listi!\n");

ispisi_listu(lista);
obrisi_listu(lista);
}
Primer 10.4 Primer ilustruje sortiranje liste. Lista moze biti sortirana na dva
nacina. Prvi nacin je da se premestaju cvorovi u listi (sto zahteva prevezivanje
pokazivaca), a drugi je da se premestaju vrednosti koje cvorovi sadrze. Prvi nacin
je komplikovaniji, ali je cesto efikasniji, narocito ako su objekti koji se cuvaju kao
podaci u cvorovima veliki.
U oba slucaja se moze koristiti rekurzija, a moze se realizovati i iterativno. U
ovom primeru ilustrujemo oba nacina sortiranja lista (prvi rekurzivno, a drugi iter-
ativno).
#include <stdio.h>
#include <stdlib.h>

138
Milena VujosevicJanicic 10.1 Implementacija

#include <time.h>

/* Struktura koja predstavlja cvor liste */


typedef struct cvor {
int vrednost; /* podatak koji cvor sadrzi */
struct cvor *sledeci; /* pokazivac na sledeci cvor */
} Cvor;

/* Pomocna funkcija koja kreira cvor. Funkcija vrednost


novog cvora inicijalizuje na broj, dok pokazivac na
sledeci cvor u novom cvoru postavlja na NULL. Funkcija
ispisuje poruku o gresci i prekida program u slucaju
da malloc() funkcija ne uspe da alocira prostor.
Funkcija vraca pokazivac na novokreirani cvor */
Cvor* napravi_cvor(int broj)
{
Cvor *novi = NULL;
if((novi = (Cvor *) malloc(sizeof(Cvor))) == NULL)
{
fprintf(stderr,"malloc() greska!\n");
exit(1);
}

novi->vrednost = broj;
novi->sledeci = NULL;
return novi;
}

/* Funkcija dodaje novi cvor na pocetak liste. Funkcija


kreira novi cvor koriscenjem funkcije napravi_cvor().
Funkcija vraca pokazivac na novu glavu liste */
Cvor * dodaj_na_pocetak_liste(Cvor *glava, int broj)
{
Cvor * novi = napravi_cvor(broj);
novi->sledeci = glava;
return novi;
}

/* Pomocna rekurzivna funkcija koja prikazuje


listu. Definisana je kao static, cime se
sprecava njeno koriscenje od strane funkcija
koje nisu definisane u ovom fajlu */
static void prikazi_listu_r(Cvor *glava)

139
Milena VujosevicJanicic 10.1 Implementacija

/* Izlaz iz rekurzije */
if(glava == NULL) return;

/* Prikaz glave */
printf("%d ", glava->vrednost);

/* Prikaz repa (rekurzivnim pozivom) */


prikazi_listu_r(glava->sledeci);
}

/* Funkcija prikazuje elemente liste pocev od glave


ka kraju liste. Koristi rekurzivnu funkciju
prikazi_listu_r(). Ova funkcija prosto dodaje
uglaste zagrade i novi red na kraju ispisa. */
void prikazi_listu(Cvor *glava)
{
putchar([);

prikazi_listu_r(glava);

putchar(]);

putchar(\n);
}

/* Funkcija oslobadja dinamicku memoriju zauzetu


od strane liste. Funkcija koristi rekurziju. */
Cvor* oslobodi_listu(Cvor *glava)
{
/* Izlaz iz rekurzije */
if(glava == NULL) return NULL;

/* Oslobadjamo rep liste */


oslobodi_listu(glava->sledeci);

/* Oslobadjamo glavu liste */


free(glava);

return NULL;
}

Cvor* dodaj_cvor_sortirano(Cvor * glava, Cvor * novi)

140
Milena VujosevicJanicic 10.1 Implementacija

{
/* u slucaju da je lista prazna, ili da je vrednost
glave veca ili jednaka od vrednosti broja koji
umecemo, tada se novi cvor umece na pocetak liste. */
if(glava == NULL || glava->vrednost >= novi->vrednost)
{
novi->sledeci = glava;
return novi;
}

/* U slucaju da je lista neprazna, i da je vrednost


glave manja od vrednosti broja koji umecemo u listu,
tada je sigurno da se novi element umece DESNO od glave,
tj. u rep liste. Dakle, mozemo rekurzivno pozvati istu
funkciju za rep liste. S obzirom da po induktivnoj
pretpostavci rep nakon toga ostaje sortiran, a svi
elementi u repu ukljucujuci i element koji je dodat
su jednaki ili veci od glave, tada ce i cela lista
biti sortirana. Povratna vrednost rekurzivnog poziva
predstavlja adresu glave modifikovanog repa liste,
pa se ta adresa mora sacuvati u pokazivacu na sledeci
u glavi liste. */
glava->sledeci = dodaj_cvor_sortirano(glava->sledeci, novi);

/* vracamo glavu */
return glava;
}

/* Sortira listu i vraca adresu glave liste. Lista se sortira


rekurzivno, prevezivanjem cvorova. */
Cvor* sortiraj_listu(Cvor * glava)
{
Cvor * pomocni;

/* Izlaz iz rekurzije */
if(glava == NULL)
return NULL;

/* Odvajamo cvor glave iz liste, a za glavu proglasavamo


sledeci cvor */
pomocni = glava;
glava = glava->sledeci;
pomocni->sledeci = NULL;

141
Milena VujosevicJanicic 10.1 Implementacija

/* Sortiramo ostatak liste */


glava = sortiraj_listu(glava);
glava = dodaj_cvor_sortirano(glava, pomocni);

/* Vracamo novu glavu */


return glava;
}

/* Funkcija sortira listu i vraca adresu glave liste. Lista se


sortira iterativno, zamenom vrednosti u cvorovima. */
Cvor* sortiraj_listu2(Cvor * glava)
{
int t;
Cvor * pi, * pj, * min;

/* Slucaj prazne liste */


if(glava == NULL)
return glava;

/* Simuliramo selection sort */


for(pi = glava; pi->sledeci != NULL ; pi = pi->sledeci)
{
min = pi;
for(pj = pi->sledeci; pj != NULL; pj = pj->sledeci)
{
if(pj->vrednost < min->vrednost)
min = pj;
}
t = min->vrednost;
min->vrednost = pi->vrednost;
pi->vrednost = t;
}

/* Vracamo glavu */
return glava;
}

/* test program */
int main()
{
Cvor *glava = NULL;
int n = 10;

/* Inicijalizujemo sekvencu slucajnih brojeva. */

142
Milena VujosevicJanicic 10.2 Kruzna (ciklicna) lista

srand(time(NULL));

/* Generisemo n slucajnih brojeva i dodajemo ih na pocetak liste */


while(n--)
glava = dodaj_na_pocetak_liste(glava, (int) (100 * (rand()/(double)RAND_MAX)));

/* Prikazujemo generisanu listu */


printf("Generisana lista:\n");
prikazi_listu(glava);

/* Sortiramo listu */
glava = sortiraj_listu(glava);
/* glava = sortiraj_listu2(glava); */

/* Prikazujemo listu nakon sortiranja */


printf("Lista nakon sortiranja:\n");
prikazi_listu(glava);

/* Oslobadjamo listu */
glava = oslobodi_listu(glava);

return 0;
}

10.2 Kruzna (ciklicna) lista

pocetak ciklicne liste

A B C ... Z

Slika 10.1: Kruzna lista

Primer 10.5 (februar 2006.) Grupa od n plesaca (na cijim kostimima su u smeru
kazaljke na satu redom brojevi od 1 do n) izvodi svoju plesnu tacku tako sto formiraju
krug iz kog najpre izlazi k-ti plesac (odbrojava se pocev od plesaca oznacenog brojem
1 u smeru kretanja kazaljke na satu). Preostali plesaci obrazuju manji krug iz kog
opet izlazi k-ti plesac (odbrojava se pocev od sledeceg suseda prethodno izbacenog,
opet u smeru kazaljke na satu). Izlasci iz kruga se nastavljaju sve dok svi plesaci

143
Milena VujosevicJanicic 10.3 Red

ne budu iskljuceni. Celi brojevi n, k (k < n) se ucitavaju sa standardnog ulaza.


Napisati program koji ce na standardni izlaz ispisati redne brojeve plesaca u redosledu
napustanja kruga.
PRIMER: za n = 5, k = 3 redosled izlaska je 3 1 5 2 4.

10.3 Red

pocetak reda (brisanje get)


kraj reda (dodavanje add)

A B ... X NULL

novi element

pocetak reda
novi kraj reda

A B ... X Y NULL

pocetak reda nakon brisanja kraj reda

B ... X Y NULL

Slika 10.2: Red

Red (eng. queue) je struktura podataka nad kojom su de nisane sledece operacije:
 Dodavanje elementa kazemo da je element dodat na kraj reda (eng. enqueue()
operacija)
 Uklanjanje elementa koji je prvi dodat kazemo da je element skinut sa pocetka
reda (eng. dequeue() operacija)
 Ocitavanje vrednosti elementa koji je na pocetku reda (eng. front() operacija)
Red spada u FIFO strukture (eng. First In First Out). Moze se implementirati
na vise nacina. Najjednostavniji nacin je da se de nise kao niz. Medjutim, tada
je ogranicen max. broj elemenata u redu dimenzijom niza. Zbog toga se obicno
pribegava koriscenju lista za implementaciju reda, gde se enqueue() operacija svodi
na dodavanje na kraj liste, a dequeue() operacija se svodi na uklanjanje glave liste.

144
Milena VujosevicJanicic 10.3 Red

Obe operacije se izvode u konstantnom vremenu, pod uslovom da se osim pokazivaca


na glavu liste cuva i pokazivac na poslednji element u listi.
Primer 10.6 Skupovi brojeva su predstavljeni tekstualnim fajlovima koji sadrze bro-
jeve i imena drugih fajlova. Ako se broj x nalazi u fajlu S, tada broj x pripada skupu
S. Ako se ime fajla S1 nalazi u fajlu S2, tada je skup S1 podskup skupa S2. Program
za dati skup S i dati broj x proverava da li x pripada S.
U ovom zadatku ce red biti koriscen na sledeci nacin: inicijalno se u red stavlja
ime fajla koji predstavlja dati skup S. Iz reda se zatim u petlji uzima sledeci fajl i
otvara za citanje. Prilikom citanja, svaki put kada se u fajlu koji se trenutno cita
naidje na ime drugog fajla, to ime ce biti dodato u red. Kada se zavrsi sa citanjem
tekuceg fajla, isti se zatvara, skida se sa reda sledeci fajl i citanje se nastavlja u
njemu. Ovaj proces se ponavlja dok se ne naidje na trazeni broj, ili dok se ne
isprazni red.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX 100

/* Struktura koja predstavlja cvor liste */


typedef struct cvor {
char ime_fajla[MAX]; /* Sadrzi ime fajla */
struct cvor *sledeci; /* pokazivac na sledeci cvor */
} Cvor;

/* Funkcija kreira novi cvor, upisuje u njega etiketu


i vraca njegovu adresu */
Cvor * napravi_cvor(char * ime_fajla)
{
Cvor *novi = NULL;
if((novi = (Cvor *) malloc(sizeof(Cvor))) == NULL)
{
fprintf(stderr,"malloc() greska!\n");
exit(1);
}

strcpy(novi->ime_fajla, ime_fajla);
novi->sledeci = NULL;
return novi;
}

/* Funkcija dodaje na kraj reda novi fajl */

145
Milena VujosevicJanicic 10.3 Red

void dodaj_u_red(Cvor **pocetak, Cvor **kraj, char *ime_fajla)


{
Cvor * novi = napravi_cvor(ime_fajla);

if(*kraj != NULL)
{
(*kraj)->sledeci = novi;
*kraj = novi;
}
else /* ako je red prazan */
{
*pocetak = novi;
*kraj = novi;
}
}

/* Funkcija skida sa pocetka reda fajl. Ako je poslednji argument


pokazivac razlicit od NULL, tada u niz karaktera na koji on
pokazuje upisuje ime fajla koji je upravo skinut sa reda
dok u suprotnom ne radi nista. Funkcija vraca 0 ako je red
prazan (pa samim tim nije bilo moguce skinuti vrednost sa
reda) ili 1 u suprotnom. */
int skini_sa_reda(Cvor **pocetak, Cvor ** kraj, char * ime_fajla)
{
Cvor * pomocni;

if(*pocetak == NULL)
return 0;

if(ime_fajla != NULL)
strcpy(ime_fajla, (*pocetak)->ime_fajla);

pomocni = *pocetak;
*pocetak = (*pocetak)->sledeci;
free(pomocni);

if(*pocetak == NULL)
*kraj = NULL;

return 1;
}

/* Funkcija vraca pokazivac na string koji sadrzi ime fajla

146
Milena VujosevicJanicic 10.3 Red

na pocetku reda. Ukoliko je red prazan, vraca NULL */


char * pocetak_reda(Cvor *pocetak)
{
if(pocetak == NULL)
return NULL;
else
return pocetak->ime_fajla;
}

/* Funkcija prazni red */


void oslobodi_red(Cvor **pocetak, Cvor **kraj)
{
Cvor *pomocni;

while(*pocetak != NULL)
{
pomocni = *pocetak;
*pocetak = (*pocetak)->sledeci;
free(pomocni);
}
*kraj = NULL;
}

/* Glavni program */
int main(int argc, char ** argv)
{
Cvor * pocetak = NULL, * kraj = NULL;
FILE *in = NULL;
char ime_fajla[MAX];
int x, y;
int pronadjen = 0;

/* NAPOMENA: Pretpostavlja se da nema cirkularnih zavisnosti, tj. da ne moze


da se desi slucaj: S2 podskup od S1, S3 podskup S2,...,S1 podskup od Sn,
u kom slucaju bismo imali beskonacnu petlju. */

/* Ime fajla i broj se zadaju sa komandne linije */


if(argc < 3)
{
fprintf(stderr, "koriscenje: %s fajl broj\n", argv[0]);
exit(1);
}

/* Dodajemo skup S u red */

147
Milena VujosevicJanicic 10.3 Red

dodaj_u_red(&pocetak, &kraj, argv[1]);

/* Trazeni broj x */
x = atoi(argv[2]);

/* Dokle god broj nije pronadjen, a ima jos fajlova u redu */


while(!pronadjen && skini_sa_reda(&pocetak, &kraj, ime_fajla))
{
/* Otvaramo sledeci fajl sa reda */
if((in = fopen(ime_fajla, "r")) == NULL)
{
fprintf(stderr, "Greska prilikom otvaranja fajla: %s\n", ime_fajla);
exit(1);
}

/* Dokle god nismo stigli do kraja fajla i nismo pronasli broj */


while(!feof(in) && !pronadjen)
{
/* Ako je broj sledeci podatak u fajlu */
if(fscanf(in, "%d", &y) == 1)
{
/* Ako je nadjen trazeni broj */
if(x == y)
{
printf("Broj x=%d pripada skupu!\n", x);
pronadjen = 1;
}
}
/* Ako je ime fajla sledeci podatak u fajlu */
else if(fscanf(in, "%s", ime_fajla) == 1)
{
/* Dodajemo ga u red */
dodaj_u_red(&pocetak, &kraj, ime_fajla);
}

}
/* Zatvaramo fajl */
fclose(in);
}

/* Ako do kraja nije pronadjen */


if(!pronadjen)
printf("Broj x=%d ne pripada skupu!\n", x);

148
Milena VujosevicJanicic 10.3 Red

/* Oslobadjamo red */
oslobodi_red(&pocetak, &kraj);

return 0;
}
Primer 10.7 Program formira celobrojni red i ispisuje sadrzaj reda na standardni
izlaz.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX 100

/* Struktura koja predstavlja cvor liste */


typedef struct cvor {
int broj; /* broj */
struct cvor *sledeci; /* pokazivac na sledeci cvor */
} Cvor;

/* Funkcija kreira novi cvor, upisuje u njega broj


i vraca njegovu adresu */
Cvor * napravi_cvor(int broj)
{
Cvor *novi = NULL;
if((novi = (Cvor *) malloc(sizeof(Cvor))) == NULL)
{
fprintf(stderr,"malloc() greska!\n");
exit(1);
}
novi->broj = broj;
novi->sledeci = NULL;
return novi;
}

/* Funkcija dodaje na kraj reda broj */


void dodaj_u_red(Cvor **pocetak, Cvor **kraj, int broj)
{
Cvor * novi = napravi_cvor(broj);

if(*kraj != NULL)
{

149
Milena VujosevicJanicic 10.3 Red

(*kraj)->sledeci = novi;
*kraj = novi;
}
else /* ako je red prazan */
{
*pocetak = novi;
*kraj = novi;
}
}

/* Funkcija skida sa pocetka reda broj */


int skini_sa_reda(Cvor **pocetak, Cvor ** kraj, int *broj)
{
Cvor * pomocni;

if(*pocetak == NULL)
return 0;

if(broj != NULL)
*broj = (*pocetak)->broj);

pomocni = *pocetak;
*pocetak = (*pocetak)->sledeci;
free(pomocni);

if(*pocetak == NULL)
*kraj = NULL;

return 1;
}

main()
{
Cvor * pocetak = NULL, * kraj = NULL;
int i, broj;
/*Formiranje jednostavnog reda*/
for(i=0; i<100; i++)
dodaj_u_red(&pocetak, &kraj, i);

/*Ispis elemenata reda koristeci operacije nad redom*/


while(skini_sa_reda(&pocetak, &kraj, &broj))
printf("Element uzet sa pocetka reda je %d\n", broj);

150
Milena VujosevicJanicic 10.4 Stek

/*Nema potrebe da se oslobadja memorija jer je memorija koju


je red zauzimao oslobodjena prilikom ispisa elemenata
reda - nakon ispisa red je ostao prazan!*/
}

10.4 Stek
Stek (eng. stack) je struktura podataka nad kojom su de nisane sledece operacije:
 Dodavanje elementa kazemo da je element potisnut na vrh steka (eng. push()
operacija).
 Uklanjanje elementa koji je poslednji dodat kazemo da je element skinut sa
vrha steka (eng. pop() operacija).
 Ocitavanje vrednosti elementa koji je poslednji dodat (eng. top() operacija).
Stek spada u LIFO strukture (eng. Last In First Out). Moze se implementirati
na vise nacina. Najjednostavniji nacin je da se de nise kao niz. Medjutim, tada
je ogranicen max. broj elemenata na steku dimenzijom niza. Zbog toga se obicno
pribegava koriscenju lista za implementaciju steka, gde se push() operacija svodi
na dodavanje na pocetak, a pop() operacija se svodi na uklanjanje glave liste. Obe
operacije se izvode u konstantnom vremenu.
Primer 10.8 Program proverava da li su zagrade (, [, {, }, ] i ) dobro uparene
staticka implementacija steka (pretpostavka da se na ulazu nece naci vise od 100
otvorenih zagrada za redom).
#include <stdio.h>
#include <stdlib.h>
#define MAX_ZAGRADA 100

int odgovarajuce(char z1, char z2) {


return (z1 == ( && z2 == )) ||
(z1 == { && z2 == }) ||
(z1 == [ && z2 == ]);
}

main()
{
int c;
char otv_zagrade[MAX_ZAGRADA];
int br_otv = 0;

while((c=getchar()) != EOF)
{
switch(c)

151
Milena VujosevicJanicic 10.4 Stek

{
case (:
case {:
case [:
{
otv_zagrade[br_otv] = c;
br_otv++;
break;
}
case ]:
case }:
case ):
if (br_otv>0 && odgovarajuce(otv_zagrade[br_otv-1], c))
{
br_otv--;
}
else
{
printf("Visak zatvorenih zagrada: %c u liniji %d\n", c, br_linija);
exit(1);
}
}
}

if (br_otv == 0)
printf("Zagrade su u redu\n");
else
printf("Visak otvorenih zagrada\n");
}

Primer 10.9 Program proverava da li su etikete u datom HTML fajlu dobro up-
arene.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MAX 100

#define OTVORENA 1
#define ZATVORENA 2

#define VAN_ETIKETE 0
#define PROCITANO_MANJE 1

152
Milena VujosevicJanicic 10.4 Stek

vrh steka (i dodavanje i brisanje push i pop)

X Y ... A NULL

novi element

novi vrh steka

Y X V ... A NULL

vrh steka nakon brisanja

X V ... A NULL

Slika 10.3: Stek

#define U_ETIKETI 2

/* Struktura koja predstavlja cvor liste */


typedef struct cvor {
char etiketa[MAX]; /* Sadrzi ime etikete */
struct cvor *sledeci; /* pokazivac na sledeci cvor */
} Cvor;

/* Funkcija kreira novi cvor, upisuje u njega etiketu


i vraca njegovu adresu */
Cvor * napravi_cvor(char * etiketa)
{
Cvor *novi = NULL;
if((novi = (Cvor *) malloc(sizeof(Cvor))) == NULL)
{
fprintf(stderr,"malloc() greska!\n");
exit(1);
}

strcpy(novi->etiketa, etiketa);
novi->sledeci = NULL;

153
Milena VujosevicJanicic 10.4 Stek

return novi;
}

/* Funkcija postavlja na vrh steka novu etiketu */


void potisni_na_stek(Cvor **vrh, char *etiketa)
{
Cvor * novi = napravi_cvor(etiketa);
novi->sledeci = *vrh;
*vrh = novi;
}

/* Funkcija skida sa vrha steka etiketu. Ako je drugi argument


pokazivac razlicit od NULL, tada u niz karaktera na koji on
pokazuje upisuje ime etikete koja je upravo skinuta sa steka
dok u suprotnom ne radi nista. Funkcija vraca 0 ako je stek
prazan (pa samim tim nije bilo moguce skinuti vrednost sa
steka) ili 1 u suprotnom. */
int skini_sa_steka(Cvor **vrh, char * etiketa)
{
Cvor * pomocni;

if(*vrh == NULL)
return 0;

if(etiketa != NULL)
strcpy(etiketa, (*vrh)->etiketa);

pomocni = *vrh;
*vrh = (*vrh)->sledeci;
free(pomocni);

return 1;
}

/* Funkcija vraca pokazivac na string koji sadrzi etiketu


na vrhu steka. Ukoliko je stek prazan, vraca NULL */
char * vrh_steka(Cvor *vrh)
{
if(vrh == NULL)
return NULL;
else
return vrh->etiketa;
}

154
Milena VujosevicJanicic 10.4 Stek

/* Funkcija prazni stek */


void oslobodi_stek(Cvor **vrh)
{
Cvor *pomocni;

while(*vrh != NULL)
{
pomocni = *vrh;
*vrh = (*vrh)->sledeci;
free(pomocni);
}
}

/* Funkcija iz fajla na koji pokazuje f cita sledecu


etiketu, i njeno ime upisuje u niz na koji pokazuje
pokazivac etiketa. Funkcija vraca EOF u slucaju da
se dodje do kraja fajla pre nego sto se procita
etiketa, vraca OTVORENA ako je procitana otvorena
etiketa, odnosno ZATVORENA ako je procitana zatvorena
etiketa. */
int uzmi_etiketu(FILE *f, char * etiketa)
{
int c;
int stanje = VAN_ETIKETE;
int i = 0;
int tip;

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


{
switch(stanje)
{
case VAN_ETIKETE:
if(c == <)
{
stanje = PROCITANO_MANJE;
}
break;
case PROCITANO_MANJE:
if(c == /)
{
tip = ZATVORENA;
}
else if(isalpha(c))

155
Milena VujosevicJanicic 10.4 Stek

{
tip = OTVORENA;
etiketa[i++] = tolower(c);
}
stanje = U_ETIKETI;
break;
case U_ETIKETI:
if(isalpha(c) && i < MAX - 1)
etiketa[i++] = tolower(c);
else {
stanje = VAN_ETIKETE;
etiketa[i]=\0;
return tip;
}
break;
}
}
return EOF;
}

/* Test program */
int main(int argc, char **argv)
{

Cvor * vrh = NULL;


char etiketa[MAX];
int tip;
int u_redu = 1;
FILE * f;

/* Ime datoteke zadajemo na komandnoj liniji */


if(argc < 2)
{
fprintf(stderr, "Koriscenje: %s ime_html_datoteke\n", argv[0]);
exit(0);
}

/* Otvaramo datoteku */
if((f = fopen(argv[1], "r")) == NULL)
{
fprintf(stderr, "fopen() greska!\n");
exit(1);
}

156
Milena VujosevicJanicic 10.4 Stek

/* Dokle god ima etiketa, uzimamo ih jednu po jednu sa ulaza */


while((tip = uzmi_etiketu(f, etiketa)) != EOF)
{
/* Ako je otvorena etiketa, dodajemo je na stek. Izuzetak su
etikete <br>, <hr> i <meta> koje nemaju sadrzaj, tako da
ih nije potrebno zatvoriti. NAPOMENA: U html-u postoje
jos neke etikete koje koje nemaju sadzaj (npr link).
Pretpostavimo da njih nema u dokumentu, zbog jednostavnosti */
if(tip == OTVORENA)
{
if(strcmp(etiketa, "br") != 0
&& strcmp(etiketa, "hr") != 0
&& strcmp(etiketa, "meta") != 0)
potisni_na_stek(&vrh, etiketa);
}
/* Ako je zatvorena etiketa, tada je uslov dobre uparenosti da je u pitanju
zatvaranje etikete koja je poslednja otvorena, a jos uvek nije zatvorena.
Ova etiketa se mora nalaziti na vrhu steka. Ako je taj uslov ispunjen,
tada je skidamo sa steka, jer je zatvorena. U suprotnom, obavestavamo
korisnika da etikete nisu pravilno uparene. */
else if(tip == ZATVORENA)
{
if(vrh_steka(vrh) != NULL && strcmp(vrh_steka(vrh), etiketa) == 0)
skini_sa_steka(&vrh, NULL);
else
{
printf(vrh_steka(vrh) != NULL ?
"Etikete nisu pravilno uparene\n(nadjena etiketa
</%s> a poslednja otvorena etiketa je <%s>)\n" :
"Etikete nisu pravilno uparene\n(nadjena etiketa
</%s> koja nije otvorena)\n",
etiketa, vrh_steka(vrh));
u_redu = 0;
break;
}
}
}

/* Zatvaramo fajl */
fclose(f);

/* Ako nismo pronasli pogresno uparivanje...*/


if(u_redu)
{

157
Milena VujosevicJanicic 10.4 Stek

/* Nakon zavrsetka citanja etiketa uslov je da stek mora biti prazan.


Ako nije, tada znaci da postoje jos neke etikete koje su otvorene
ali nisu zatvorene. */
if(vrh_steka(vrh) == NULL)
printf("Etikete su pravilno uparene!\n");
else
printf("Etikete nisu pravilno uparene\n(etiketa <%s> nije zatvorena)\n",
vrh_steka(vrh));
}

/* Oslobadjamo stek */
oslobodi_stek(&vrh);

return 0;
}
Primer 10.10 Program formira celobrojni stek i ispisuje sadrzaj steks na standardni
izlaz.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX 100

/* Struktura koja predstavlja cvor liste */


typedef struct cvor {
int broj; /* broj */
struct cvor *sledeci; /* pokazivac na sledeci cvor */
} Cvor;

/* Funkcija kreira novi cvor, upisuje u njega broj


i vraca njegovu adresu */
Cvor * napravi_cvor(int broj)
{
Cvor *novi = NULL;
if((novi = (Cvor *) malloc(sizeof(Cvor))) == NULL)
{
fprintf(stderr,"malloc() greska!\n");
exit(1);
}
novi->broj = broj;
novi->sledeci = NULL;
return novi;
}

158
Milena VujosevicJanicic 10.4 Stek

/* Funkcija dodaje broj na stek*/


void potisni_na_stek(Cvor **vrh, int broj)
{
Cvor * novi = napravi_cvor(broj);
novi->sledeci = *vrh;
*vrh = novi;
}

/* Funkcija skida broj sa steka */


int skini_sa_steka(Cvor **vrh, int *broj)
{
Cvor * pomocni;

if(*vrh == NULL)
return 0;

if(broj != NULL)
*broj = (*vrh)->broj);

pomocni = *vrh;
*vrh = (*vrh)->sledeci;
free(pomocni);

return 1;
}

main()
{
Cvor * vrh = NULL;
int i, broj;

/*Formiranje steka*/
for(i=0; i<100; i++)
potisni_na_stek(&vrh, i);

/*Ispis elemenata steka: 99, 98 ... 0*/


while(skini_sa_steka(&pocetak, &kraj, &broj))
printf("Broj skinut sa vrha steka je %d\n", broj);

/*Nema potrebe da se oslobadja memorija jer je memorija koju


je stek zauzimao oslobodjena prilikom ispisa elemenata
steka - nakon ispisa stek je ostao prazan!*/

159
Milena VujosevicJanicic 10.5 Dvostruko povezane liste

10.5 Dvostruko povezane liste

pocetak dvostruko povezane liste kraj liste

...
NULL A B C ... Z NULL

Slika 10.4: Dvostruko povezana lista

Dvostruko povezana lista je struktura podataka koja se sastoji od sekvence cvorova.


Svaki cvor sadrzi podatak (odredenog tipa) i pokazivace na prethodni i sledeci cvor
u sekvenci. Za razliku od obicne liste, u svakom cvoru imamo zapisanu i adresu
prethodnog elementa, pa se kroz listu mozemo kretati i unazad. Poslednji element u
listi nema sledeci element: u tom slucaju se njegov pokazivac na sledeci postavlja na
NULL. Slicno, glava liste nema prethodni element, pa je njen pokazivac na prethodni
postavljen na NULL. Takode, prazna lista se predstavlja NULL pokazivacem.
Prednost dvostruko povezane liste u odnosu na jednostruko povezanu je u tome
sto se mozemo kretati u oba smera kroz listu. Nedostatak je to sto se velicina
memorije potrebne za cuvanje cvora povecava za velicinu jednog pokazivaca.
Primer 10.11 Program demonstrira rad sa dvostruko povezanim listama. Za testi-
ranje narednih funkcija moze se koristiti main funkcija iz primera 10.1.
#include <stdio.h>
#include <stdlib.h>

/* Struktura koja predstavlja cvor liste */


typedef struct cvor {
int vrednost; /* podatak koji cvor sadrzi */
struct cvor *sledeci; /* pokazivac na sledeci cvor */
struct cvor *prethodni; /* pokazivac na prethodni */
} Cvor;

/* Pomocna funkcija koja kreira cvor. Funkcija vrednost


novog cvora inicijalizuje na broj, dok pokazivace na
prethodni i sledeci cvor u novom cvoru postavlja na NULL.
Funkcija ispisuje poruku o gresci i prekida program u
slucaju da malloc() funkcija ne uspe da alocira prostor.

160
Milena VujosevicJanicic 10.5 Dvostruko povezane liste

Funkcija vraca pokazivac na novokreirani cvor */


Cvor* napravi_cvor(int broj)
{
Cvor *novi = NULL;
if((novi = (Cvor *) malloc(sizeof(Cvor))) == NULL)
{
fprintf(stderr,"malloc() greska!\n");
exit(1);
}

novi->vrednost = broj;
novi->prethodni = NULL;
novi->sledeci = NULL;
return novi;
}

/* Funkcija dodaje novi cvor na pocetak liste. Funkcija


kreira novi cvor koriscenjem funkcije napravi_cvor().
Funkcija vraca pokazivac na novu glavu liste */
Cvor* dodaj_na_pocetak_liste(Cvor *glava, int broj)
{
Cvor *novi = napravi_cvor(broj);
novi->sledeci = glava;
if(glava != NULL) glava->prethodni = novi;

return novi;
}

/* Funkcija dodaje novi cvor na kraj liste. Funkcija


kreira novi cvor koriscenjem funkcije napravi_cvor().
Funkcija vraca pokazivac na glavu liste (koji moze
biti promenjen u slucaju da je lista inicijalno bila
prazna). */
Cvor* dodaj_na_kraj_liste(Cvor *glava, int broj)
{
Cvor *novi = napravi_cvor(broj);
Cvor *tekuci = glava;

/* slucaj prazne liste. U tom slucaju je glava nove liste


upravo novi cvor. */
if(glava == NULL) return novi;

/* Ako lista nije prazna, tada se krecemo duz liste sve dok
ne dodjemo do poslednjeg cvora (tj. do cvora ciji pokazivac

161
Milena VujosevicJanicic 10.5 Dvostruko povezane liste

na sledeci pokazuje na NULL) */


while(tekuci->sledeci != NULL)
tekuci = tekuci->sledeci;

/* Dodajemo novi element na kraj preusmeravanjem pokazivaca */


tekuci->sledeci = novi;
novi->prethodni = tekuci;

/* Vracamo glavu liste */


return glava;
}

/* Funkcija dodaje novi element u sortiranu listu tako da i nova


lista ostane sortirana. Funkcija kreira novi cvor koriscenjem
funkcije napravi_cvor(). Funkcija vraca pokazivac na glavu liste
(koji moze biti promenjen u slucaju da je novi element dodat na
pocetak liste) */
Cvor* dodaj_sortirano(Cvor *glava, int broj)
{
Cvor *novi = napravi_cvor(broj);
Cvor *tekuci = glava;

/* u slucaju prazne liste glava nove liste je


upravo novi element */
if(glava == NULL) return novi;

/* ako je novi element manji ili jednak od glave,


tada novi element mora da bude nova glava */
if(glava->vrednost >= novi->vrednost)
{
novi->sledeci = glava;
glava->prethodni = novi;
return novi;
}

/* u slucaju da je glava manja od novog elementa, tada se krecemo kroz


listu sve dok se ne dodje do elementa ciji je sledeci element veci ili
jednak od novog elementa, ili dok se ne dodje do poslednjeg elementa. */
while(tekuci->sledeci != NULL && tekuci->sledeci->vrednost < novi->vrednost)
tekuci = tekuci->sledeci;

/* U svakom slucaju novi element dodajemo IZA tekuceg elementa */


novi->sledeci = tekuci->sledeci;
novi->prethodni = tekuci;

162
Milena VujosevicJanicic 10.5 Dvostruko povezane liste

if(tekuci->sledeci != NULL)
tekuci->sledeci->prethodni = novi;
tekuci->sledeci = novi;

/* vracamo vrednost glave */


return glava;
}

/* Funkcija trazi u listi element cija je vrednost jednaka


datom broju. Funkcija vraca pokazivac na cvor liste u
kome je sadrzan trazeni broj ili NULL u slucaju da takav
element ne postoji u listi */
Cvor* pretrazi_listu(Cvor *glava, int broj)
{
/* Pretrazivanje se vrsi bez pretpostavke o sortiranosti
liste.*/
for(; glava != NULL ; glava = glava->sledeci)
if(glava->vrednost == broj)
return glava;

return NULL;
}

/* Funkcija brise tekuci element liste, tj. element liste


na koji pokazuje pokazivac tekuci. Funkcija vraca pokazivac
na glavu liste, koja moze biti promenjena ako je upravo
glava obrisani cvor */
Cvor* obrisi_tekuci(Cvor * glava, Cvor * tekuci)
{
if(tekuci == NULL)
return glava;

/* Preusmeravamo pokazivace prethodnog i sledeceg


ako oni postoje */
if(tekuci->prethodni != NULL)
tekuci->prethodni->sledeci = tekuci->sledeci;
if(tekuci->sledeci != NULL)
tekuci->sledeci->prethodni = tekuci->prethodni;

/* Ako je cvor koji brisemo glava, tada moramo da


promenimo glavu (sledeci element postaje glava) */
if(tekuci == glava)
glava = tekuci->sledeci;

163
Milena VujosevicJanicic 10.5 Dvostruko povezane liste

/* Brisemo tekuci cvor */


free(tekuci);
return glava;
}

/* Funkcija brise iz liste sve cvorove koji sadrze dati broj.


Funkcija vraca pokazivac na glavu liste (koji moze biti
promenjen u slucaju da se obrise stara glava) */
Cvor* obrisi_element(Cvor *glava, int broj)
{
Cvor *tekuci = glava;
Cvor *pomocni;

/* Pretrazujemo listu pocev od tekuceg elementa trazeci


datu vrednost. Ako je pronadjemo, brisemo nadjeni cvor
i nastavljamo pretragu od elementa koji sledi nakon
upravo obrisanog */
while((tekuci = pretrazi_listu(tekuci, broj)) != NULL)
{
pomocni = tekuci->sledeci;
glava = obrisi_tekuci(glava, tekuci);
tekuci = pomocni;
}
/* vracamo novu glavu */
return glava;
}

/* Funkcija prikazuje elemente liste pocev


od glave ka kraju liste */
void prikazi_listu(Cvor *glava)
{
putchar([);
for(;glava != NULL; glava = glava->sledeci)
printf("%d ", glava->vrednost);
putchar(]);

putchar(\n);
}

/* Funkcija prikazuje elemente liste u obrnutom poretku */


void prikazi_listu_obrnuto(Cvor * glava)
{
/* Ako je lista prazna... */
if(glava == NULL)

164
Milena VujosevicJanicic 10.5 Dvostruko povezane liste

{
printf("[]\n");
return;
}

/* Prolazimo kroz listu dok ne stignemo do poslednjeg


elementa. */
while(glava->sledeci != NULL)
glava = glava->sledeci;

/* Ispisujemo elemente liste iteracijom u suprotnom smeru */


putchar([);
for(;glava != NULL; glava = glava->prethodni)
printf("%d ", glava->vrednost);
putchar(]);

putchar(\n);
}

/* Funkcija oslobadja dinamicku memoriju zauzetu


od strane liste. Funkcija vraca NULL, tj.
vrednost koju treba dodeliti pokazivackoj
promenljivoj, s obzirom da je sada lista prazna. */
Cvor* oslobodi_listu(Cvor *glava)
{
Cvor *pomocni;

while(glava != NULL)
{
/* moramo najpre zapamtiti adresu sledeceg
elementa, a tek onda osloboditi glavu */
pomocni = glava->sledeci;
free(glava);
glava = pomocni;
}

return NULL;
}

165
Glava 11

Stabla

Binarno stablo1 je skup cvorova koji su povezani na sledeci nacin:


1. Svaki cvor moze imati levog i desnog SINA (pri tom svaki od sinova moze biti
i izostavljen, ili oba). Kazemo da je dati cvor RODITELJ svojim sinovima. Ako
je cvor U roditelj cvoru V, tada pisemo da je U < V . Cvor koji nema ni levog
ni desnog sina naziva se LIST.
2. Postoji jedan jedinstveni cvor takav da nema roditelja. Ovaj cvor nazivamo
KOREN stabla.
3. U stablu nema ciklusa, tj. ne postoji niz cvorova x1,x2,...,xn, takav da je
x1 < x2 < ... < xn < x1.
Inace, niz cvorova x1 < x2 < ... < xn nazivamo put u stablu. Kazemo da je
cvor U predak cvora V ako u stablu postoji put od U do V. Specijalno, svaki cvor
je predak samom sebi. Lako se moze pokazati da je koren predak svih cvorova u
stablu. Rastojanje od korena do nekog cvora naziva se visina cvora (koren je visine
0). Maksimalna visina cvora u stablu naziva se visina stabla.
Stablo koje nema cvorova naziva se prazno stablo.
Za svaki cvor V u stablu mozemo posmatrati stablo koje se sastoji od svih njegovih
potomaka (svih cvorova kojima je on predak). Ovo stablo se naziva podstablo sa
datim korenom V. Podstablo sa njegovim levim sinom kao korenom nazivamo levim
podstablom cvora V, dok podstablo sa njegovim desnim sinom kao korenom nazivamo
desnim podstablom cvora V. Ako je neki od njegovih sinova izostavljen, tada kazemo
da je odgovarajuce podstablo cvora V prazno stablo. Specijalno, ako je V koren, tada
njegovo levo i desno podstablo nazivamo levim i desnim podstablom datog (citavog)
stabla.
Stablo se moze de nisati i rekurzivno na sledeci nacin:
1. Prazno stablo je stablo
2. Ako su data dva stabla t1 i t2, i cvor r, tada je i (t1,r,t2) takodje stablo.
t1 je tada levo podstablo, t2 je desno podstablo dok je cvor r koren tako
formiranog stabla.

166
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

NULL NULL

NULL NULL NULL

NULL NULL

Slika 11.1: Binarno stablo

U programiranju se stabla obicno koriste kao strukture podataka, tako sto svaki
cvor sadrzi po jedan podatak odredenog tipa. Nacin rasporedivanja podataka u
stablu zavisi od konkretne primene stabla. S obzirom na rekurzivnu prirodu stabla,
uobicajeno je da se u programiranju stabla obraduju rekurzivno.

11.1 Binarno pretrazivacko stablo


Posebna vrsta stabla su tzv. binarna pretrazivacka stabla. Ova stabla imaju osobinu
da za svaki cvor vazi sledece: svi cvorovi njegovog levog podstabla sadrze podatke
sa manjom vrednoscu od vrednosti podatka u tom cvoru, dok svi cvorovi njegovog
desnog podstabla sadrze podatke sa vecom vrednoscu od vrednosti podatka u tom
cvoru. Ovakva organizacija omogu cava e kasno pretrazivanje.
Primer 11.1 Program demonstrira rad sa binarnim pretrazivackim drvetima ciji su
podaci celi brojevi. Drvo sadrzi cele brojeve sortirane po velicini. Za svaki cvor, levo
podstabla sadrzi manje elemente, dok desno podstablo sadrzi vece.
#include <stdlib.h>
1 Tekst preuzet sa sajta http://www.matf.bg.ac.rs/~milan

167
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

17, 12, 21, 15, 5, 14


17

12 21

NULL NULL

5 15

NULL NULL NULL

inf ix : 5, 12, 14, 15, 17, 21


14 pref ix : 17, 12, 5, 15, 14, 21

postf ix : 5, 14, 15, 12, 21, 17


NULL NULL

Slika 11.2: Uredeno stablo

#include <stdio.h>

/* Struktura koja predstavlja cvor drveta */


typedef struct _cvor
{
int broj;
struct _cvor *l, *d;
} cvor;

/* Pomocna funkcija za kreiranje cvora. */


cvor* napravi_cvor(int b) {
cvor* novi = (cvor*)malloc(sizeof(cvor));
if (novi == NULL)
{
fprintf(stderr, "Greska prilikom
alokacije memorije");
exit(1);
}

168
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

novi->broj = b;
novi->l = NULL;
novi->d = NULL;
return novi;
}

/* Funkcija umece broj b u drvo ciji je koren dat preko


pokazivaca koren. Funkcija vraca pokazivac na koren
novog drveta */
cvor* ubaci_u_drvo(cvor* koren, int b)
{
if (koren == NULL)
return napravi_cvor(b);

if (b < koren->broj)
koren->l = ubaci_u_drvo(koren->l, b);
else
koren->d = ubaci_u_drvo(koren->d, b);

return koren;
}

/* Funkcija proverava da li dati broj postoji u drvetu */


int pronadji(cvor* koren, int b)
{
if (koren == NULL)
return 0;

if (koren->broj == b)
return 1;

if (b < koren->broj)
return pronadji(koren->l, b);
else
return pronadji(koren->d, b);
}

/* Funkcija ispisuje sve cvorove drveta u infiksnom redosledu */


void ispisi_drvo(cvor* koren) {
if (koren != NULL)
{
ispisi_drvo(koren->l);
printf("%d ", koren->broj);
ispisi_drvo(koren->d);

169
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

}
}

/* Funkcija oslobadja memoriju koju je drvo zauzimalo */


void obrisi_drvo(cvor* koren) {
if (koren != NULL)
{
/* Oslobadja se memorija za levo poddrvo */
obrisi_drvo(koren->l);
/* Oslobadja se memorija za desno poddrvo */
obrisi_drvo(koren->d);
/* Oslobadja se memorija koju zauzima koren */
free(koren);
}
}

/* Funkcija sumira sve vrednosti binarnog stabla */


int suma_cvorova(cvor* koren)
{
if (koren == NULL)
return 0;
return suma_cvorova(koren->l) +
koren->broj +
suma_cvorova(koren->d);
}

/* Funkcija prebrojava broj cvorova binarnog stabla */


int broj_cvorova(cvor* koren)
{
if (koren == NULL)
return 0;
return broj_cvorova(koren->l) +
1 +
broj_cvorova(koren->d);
}

/* Funkcija prebrojava broj listova binarnog stabla */


int broj_listova(cvor* koren)
{
if (koren == NULL)
return 0;
if (koren->l == NULL && koren->d == NULL)
return 1;
return broj_listova(koren->l) +

170
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

broj_listova(koren->d);
}

/* Funkcija izracunava sumu listova binarnog stabla */


int suma_listova(cvor* koren)
{
if (koren == NULL)
return 0;

if (koren->l == NULL && koren->d == NULL)


return koren->broj;

return suma_listova(koren->l) +
suma_listova(koren->d);
}

/* Funkcija ispisuje sadrzaj listova binarnog stabla */


void ispisi_listove(cvor* koren)
{
if (koren == NULL)
return;

ispisi_listove(koren->l);

if (koren->l == NULL && koren->d == NULL)


printf("%d ", koren->broj);

ispisi_listove(koren->d);
}

/* Funkcija pronalazi maksimalnu vrednost u drvetu


Koristi se cinjenica da je ova vrednost
smestena u najdesnjem listu */
int max_vrednost(cvor* koren)
{
if (koren==NULL)
return 0;

if (koren->d==NULL)
return koren->broj;

return max_vrednost(koren->d);
}

171
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

/* Iterativna funkcija za pronalazenje maksimalne vrednosti. */


int max_vrednost_nerekurzivno(cvor* koren)
{
if (koren==NULL)
return 0;
else
{
cvor* tekuci;
for (tekuci=koren; tekuci->d!=NULL; tekuci=tekuci->d)
;
return tekuci->broj;
}
}

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

/* Funkcija racuna "dubinu" binarnog stabla */


int dubina(cvor* koren)
{
if (koren==NULL)
return 0;
else
{ int dl=dubina(koren->l);
int dd=dubina(koren->d);
return 1+max(dl,dd);
}
}

/* Program koji testira rad prethodnih funkcija */


main()
{
cvor* koren = NULL;
koren = ubaci_u_drvo(koren, 1);
koren = ubaci_u_drvo(koren, 8);
koren = ubaci_u_drvo(koren, 5);
koren = ubaci_u_drvo(koren, 3);
koren = ubaci_u_drvo(koren, 7);
koren = ubaci_u_drvo(koren, 6);
koren = ubaci_u_drvo(koren, 9);

if (pronadji(koren, 3))
printf("Pronadjeno 3\n");
if (pronadji(koren, 2))

172
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

printf("Pronadjeno 2\n");
if (pronadji(koren, 7))
printf("Pronadjeno 7\n");

ispisi_drvo(koren);

putchar(\n);
printf("Suma cvorova : %d\n", suma_cvorova(koren));
printf("Broj cvorova : %d\n", broj_cvorova(koren));
printf("Broj listova : %d\n", broj_listova(koren));
printf("Suma listova : %d\n", suma_listova(koren));
printf("Dubina drveta : %d\n", dubina(koren));
printf("Maximalna vrednost : %d\n", max_vrednost(koren));

ispisi_listove(koren);

obrisi_drvo(koren);
}

/*
Pronadjeno 3
Pronadjeno 7
1 3 5 6 7 8 9
Suma cvorova : 39
Broj cvorova : 7
Broj listova : 3
Suma listova : 18
Dubina drveta : 5
Maximalna vrednost : 9
3 6 9
*/
Primer 11.2 Binarno pretrazivacko drvo - funkcije za izracunavanje kopije, unije,
preseka i razlike dva drveta, funkcija za izbacivanje cvora iz drveta.
/* Struktura koja predstavlja cvor drveta */
typedef struct cvor {

int vrednost; /* Vrednost koja se cuva */


struct cvor * levi; /* Pokazivac na levo podstablo */
struct cvor * desni; /* Pokazivac na desno podstablo */

} Cvor;

/* NAPOMENA: Prazno stablo se predstavlja NULL pokazivacem. */

173
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

/* Pomocna funkcija za kreiranje cvora. Cvor se kreira


dinamicki, funkcijom malloc(). U slucaju greske program
se prekida i ispisuje se poruka o gresci. U slucaju
uspeha inicijalizuje se vrednost datim brojem, a pokazivaci
na podstabla se inicijalizuju na NULL. Funkcija vraca
adresu novokreiranog cvora */
Cvor * napravi_cvor (int broj)
{

/* dinamicki kreiramo cvor */


Cvor * novi = (Cvor *) malloc (sizeof(Cvor));

/* u slucaju greske ... */


if (novi == NULL)
{
fprintf (stderr,"malloc() greska\n");
exit (1);
}

/* inicijalizacija */
novi->vrednost = broj;
novi->levi = NULL;
novi->desni = NULL;

/* vracamo adresu novog cvora */


return novi;
}

/* Funkcija dodaje novi cvor u stablo sa datim korenom.


Ukoliko broj vec postoji u stablu, ne radi nista.
Cvor se kreira funkcijom napravi_cvor(). Funkcija
vraca koren stabla nakon ubacivanja novog cvora. */
Cvor * dodaj_u_stablo (Cvor *koren, int broj)
{

/* izlaz iz rekurzije: ako je stablo bilo prazno,


novi koren je upravo novi cvor */
if (koren == NULL)
return napravi_cvor (broj);

/* Ako je stablo neprazno, i koren sadrzi manju vrednost


od datog broja, broj se umece u desno podstablo,
rekurzivnim pozivom */

174
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

if (koren->vrednost < broj)


koren->desni = dodaj_u_stablo (koren->desni, broj);
/* Ako je stablo neprazno, i koren sadrzi vecu vrednost
od datog broja, broj se umece u levo podstablo,
rekurzivnim pozivom */
else if (koren->vrednost > broj)
koren->levi = dodaj_u_stablo (koren->levi, broj);

/* U slucaju da je koren jednak datom broju, tada


broj vec postoji u stablu, i ne radimo nista */

/* Vracamo koren stabla */


return koren;

/* Funkcija pretrazuje binarno stablo. Ukoliko


pronadje cvor sa vrednoscu koja je jednaka
datom broju, vraca adresu tog cvora. U
suprotnom vraca NULL */
Cvor * pretrazi_stablo (Cvor * koren, int broj)
{

/* Izlaz iz rekurzije: ako je stablo prazno,


tada trazeni broj nije u stablu */
if (koren == NULL)
return NULL;

/* Ako je stablo neprazno, tada se pretrazivanje


nastavlja u levom ili desnom podstablu, u
zavisnosti od toga da li je trazeni broj
respektivno manji ili veci od vrednosti
korena. Ukoliko je pak trazeni broj jednak
korenu, tada se vraca adresa korena. */
if (koren->vrednost < broj)
return pretrazi_stablo (koren->desni, broj);
else if (koren->vrednost > broj)
return pretrazi_stablo (koren->levi, broj);
else
return koren;
}

/* Funkcija vraca adresu cvora sa najmanjom vrednoscu


u stablu, ili NULL ako je stablo prazno */

175
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

Cvor * pronadji_najmanji (Cvor * koren)


{

/* Slucaj praznog stabla */


if (koren == NULL)
return NULL;

/* Izlaz iz rekurzije: ako koren nema levog sina,


tada je upravo koren po vrednosti najmanji cvor.*/
if (koren->levi == NULL)
return koren;
/* U suprotnom je najmanja vrednost u stablu upravo
najmanja vrednost u levom podstablu, pa se pretraga
nastavlja rekurzivno u levom podstablu. */
else
return pronadji_najmanji (koren->levi);
}

/* Funkcija vraca adresu cvora sa najvecom vrednoscu


u stablu, ili NULL ako je stablo prazno */
Cvor * pronadji_najveci (Cvor * koren)
{

/* Slucaj praznog stabla */


if (koren == NULL)
return NULL;

/* Izlaz iz rekurzije: ako koren nema desnog sina,


tada je upravo koren po vrednosti najveci cvor. */
if (koren->desni == NULL)
return koren;
/* U suprotnom je najveca vrednost u stablu upravo
najveca vrednost u desnom podstablu, pa se pretraga
nastavlja rekurzivno u desnom podstablu. */
else
return pronadji_najveci (koren->desni);

/* Funkcija brise cvor sa datom vrednoscu iz stabla,


ukoliko postoji. U suprotnom ne radi nista. Funkcija
vraca koren stabla (koji moze biti promenjen nakon
brisanja) */
Cvor * obrisi_element (Cvor * koren, int broj)

176
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

Cvor * pomocni=NULL;

/* Izlaz iz rekurzije: ako je stablo prazno, ono ostaje


prazno i nakon brisanja */
if (koren == NULL)
return NULL;

/* Ako je vrednost broja veca od vrednosti korena,


tada se broj eventualno nalazi u desnom podstablu,
pa treba rekurzivno primeniti postupak na desno
podstablo. Koren ovako modifikovanog stabla je
nepromenjen, pa vracamo stari koren */
if (koren->vrednost < broj)
{
koren->desni = obrisi_element (koren->desni, broj);
return koren;
}

/* Ako je vrednost broja manja od vrednosti korena,


tada se broj eventualno nalazi u levom podstablu,
pa treba rekurzivno primeniti postupak na levo
podstablo. Koren ovako modifikovanog stabla je
nepromenjen, pa vracamo stari koren */
if (koren->vrednost > broj)
{
koren->levi = obrisi_element (koren->levi, broj);
return koren;
}

/* Slede podslucajevi vezani za slucaj kada je vrednost


korena jednaka broju koji se brise (tj. slucaj kada
treba obrisati koren) */

/* Ako koren nema sinova, tada se on prosto brise, i


rezultat je prazno stablo (vracamo NULL) */
if (koren->levi == NULL && koren->desni == NULL)
{
free (koren);
return NULL;
}

/* Ako koren ima samo levog sina, tada se brisanje

177
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

vrsi tako sto obrisemo koren, a novi koren postaje


levi sin */
if (koren->levi != NULL && koren->desni == NULL)
{
pomocni = koren->levi;
free (koren);
return pomocni;
}

/* Ako koren ima samo desnog sina, tada se brisanje


vrsi tako sto obrisemo koren, a novi koren postaje
desni sin */
if (koren->desni != NULL && koren->levi == NULL)
{
pomocni = koren->desni;
free (koren);
return pomocni;
}

/* Slucaj kada koren ima oba sina. U tom slucaju se


brisanje vrsi na sledeci nacin: najpre se potrazi
sledbenik korena (u smislu poretka) u stablu. To
je upravo po vrednosti najmanji cvor u desnom podstablu.
On se moze pronaci npr. funkcijom pronadji_najmanji().
Nakon toga se u koren smesti vrednost tog cvora, a u taj
cvor se smesti vrednost korena (tj. broj koji se brise).
Onda se prosto rekurzivno pozove funkcija za brisanje
na desno podstablo. S obzirom da u njemu treba obrisati
najmanji element, a on definitivno ima najvise jednog
potomka, jasno je da ce to brisanje biti obavljeno na
jedan od nacina koji je gore opisan. */
pomocni = pronadji_najmanji (koren->desni);
koren->vrednost = pomocni->vrednost;
pomocni->vrednost = broj;
koren->desni = obrisi_element (koren->desni, broj);
return koren;
}

/* Funkcija prikazuje stablo s leva u desno (tj.


prikazuje elemente u rastucem poretku) */
void prikazi_stablo (Cvor * koren)
{
/* izlaz iz rekurzije */

178
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

if(koren == NULL)
return;

prikazi_stablo (koren->levi);
printf("%d ", koren->vrednost);
prikazi_stablo (koren->desni);
}

/* Funkcija oslobadja prostor koji je alociran za


cvorove stabla. Funkcija vraca NULL, zato sto je
nakon oslobadjanja stablo prazno. */
Cvor * oslobodi_stablo (Cvor *koren)
{

/* Izlaz iz rekurzije */
if(koren == NULL)
return NULL;

koren->levi = oslobodi_stablo (koren->levi);


koren->desni = oslobodi_stablo (koren->desni);
free(koren);

return NULL;
}

/* Funkcija kreira novo stablo identicno stablu koje je


dato korenom. Funkcija vraca pokazivac na koren
novog stabla. */
Cvor * kopiraj_stablo (Cvor * koren)
{
Cvor * duplikat = NULL;

/* Izlaz iz rekurzije: ako je stablo prazno,


vracamo NULL */
if(koren == NULL)
return NULL;

/* Dupliramo koren stabla i postavljamo ga


da bude koren novog stabla */
duplikat = napravi_cvor (koren->vrednost);

/* Rekurzivno dupliramo levo podstablo i njegovu


adresu cuvamo u pokazivacu na levo podstablo
korena duplikata. */

179
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

duplikat->levi = kopiraj_stablo (koren->levi);

/* Rekurzivno dupliramo desno podstablo i njegovu


adresu cuvamo u pokazivacu na desno podstablo
korena duplikata. */
duplikat->desni = kopiraj_stablo (koren->desni);

/* Vracamo adresu korena duplikata */


return duplikat;

/* Funkcija modifikuje stablo dato korenom koren_1


tako da sadrzi i sve elemente drugog stabla datog
korenom koren_2 (drugim recima funkcija kreira uniju
dva stabla, i rezultat se smesta u prvo stablo).
Funkcija vraca pokazivac na koren tako modifikovanog
prvog stabla. */
Cvor * kreiraj_uniju (Cvor * koren_1, Cvor * koren_2)
{

/* Ako je drugo stablo neprazno */


if(koren_2 != NULL)
{
/* dodajemo koren drugog stabla u prvo stablo */
koren_1 = dodaj_u_stablo (koren_1, koren_2->vrednost);

/* rekurzivno racunamo uniju levog i desnog podstabla


drugog stabla sa prvim stablom */
koren_1 = kreiraj_uniju (koren_1, koren_2->levi);
koren_1 = kreiraj_uniju (koren_1, koren_2->desni);
}

/* vracamo pokazivac na modifikovano prvo stablo */


return koren_1;
}

/* Funkcija modifikuje stablo dato korenom koren_1


tako da sadrzi samo one elemente koji su i elementi
stabla datog korenom koren_2 (drugim recima funkcija
kreira presek dva stabla, i rezultat se smesta u prvo
stablo). Funkcija vraca pokazivac na koren tako
modifikovanog prvog stabla. */
Cvor * kreiraj_presek (Cvor * koren_1, Cvor * koren_2)

180
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

/* Ako je prvo stablo prazno, tada je i rezultat prazno


stablo */
if(koren_1 == NULL)
return NULL;

/* Kreiramo presek levog i desnog podstabla sa drugim


stablom, tj. iz levog i desnog podstabla prvog stabla
brisemo sve one elemente koji ne postoje u drugom
stablu */
koren_1->levi = kreiraj_presek (koren_1->levi, koren_2);
koren_1->desni = kreiraj_presek (koren_1->desni, koren_2);

/* Ako se koren prvog stabla ne nalazi u drugom stablu


tada ga uklanjamo iz prvog stabla */
if(pretrazi_stablo (koren_2, koren_1->vrednost) == NULL)
koren_1 = obrisi_element (koren_1, koren_1->vrednost);

/* Vracamo koren tako modifikovanog prvog stabla */


return koren_1;

/* Funkcija modifikuje stablo dato korenom koren_1


tako da sadrzi samo one elemente koji nisu i elementi
stabla datog korenom koren_2 (drugim recima funkcija
kreira razliku dva stabla, i rezultat se smesta u prvo
stablo). Funkcija vraca pokazivac na koren tako
modifikovanog prvog stabla. */
Cvor * kreiraj_razliku (Cvor * koren_1, Cvor * koren_2)
{

/* Ako je prvo stablo prazno, tada je i rezultat prazno


stablo */
if(koren_1 == NULL)
return NULL;

/* Kreiramo razliku levog i desnog podstabla sa drugim


stablom, tj. iz levog i desnog podstabla prvog stabla
brisemo sve one elemente koji postoje i u drugom
stablu */
koren_1->levi = kreiraj_razliku (koren_1->levi, koren_2);
koren_1->desni = kreiraj_razliku (koren_1->desni, koren_2);

181
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

/* Ako se koren prvog stabla nalazi i u drugom stablu


tada ga uklanjamo iz prvog stabla */
if(pretrazi_stablo (koren_2, koren_1->vrednost) != NULL)
koren_1 = obrisi_element (koren_1, koren_1->vrednost);

/* Vracamo koren tako modifikovanog prvog stabla */


return koren_1;

/* test program */
int main()
{

Cvor * koren = NULL, * koren_2 = NULL;


Cvor * pomocni = NULL;
int broj;

/* Testiranje dodavanja u stablo */


printf("-------------------------------------------------------\n");
printf("---------- Testiranje dodavanja u stablo --------------\n");
do {
printf("-------------------------------------------------------\n");
printf("Prikaz trenutnog sadrzaja stabla:\n");
prikazi_stablo (koren);
putchar(\n);
printf("-------------------------------------------------------\n");
printf("Dodati element u stablo (ctrl-D za kraj unosa):\n");
} while(scanf("%d", &broj) > 0 &&
(koren = dodaj_u_stablo (koren, broj)) );

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

/* Testiranje pretrage elementa */


printf("-------------------------------------------------------\n");
printf("---------------- Testiranje pretrage ------------------\n");
printf("-------------------------------------------------------\n");
printf("Prikaz trenutnog sadrzaja stabla:\n");
prikazi_stablo (koren);
putchar(\n);
printf("-------------------------------------------------------\n");

182
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

printf("Uneti broj koji se trazi: ");


scanf("%d", &broj);

if((pomocni = pretrazi_stablo (koren, broj)) == NULL)


printf("Trazeni broj nije u stablu\n");
else
printf("Trazeni element %d je u stablu\n", pomocni->vrednost);
printf("-------------------------------------------------------\n");
putchar(\n);

/* Testiranje brisanja elemenata */


printf("-------------------------------------------------------\n");
printf("--------------- Testiranje brisanja -------------------\n");
printf("-------------------------------------------------------\n");
printf("Prikaz trenutnog sadrzaja stabla:\n");
prikazi_stablo (koren);
putchar(\n);
printf("-------------------------------------------------------\n");
printf("Uneti broj koji se brise: ");
scanf("%d", &broj);

koren = obrisi_element (koren, broj);


printf("-------------------------------------------------------\n");
printf("Stablo nakon izbacivanja:\n");
prikazi_stablo (koren);
putchar(\n);
printf("-------------------------------------------------------\n");
putchar(\n);

/* Testiranje dupliranja, unije, preseka i razlike */


printf("-------------------------------------------------------\n");
printf("----- Testiranje dupliranja i skupovnih operacija -----\n");
do {
printf("-------------------------------------------------------\n");
printf("Prikaz trenutnog sadrzaja 2. stabla:\n");
prikazi_stablo (koren_2);
putchar(\n);
printf("-------------------------------------------------------\n");
printf("Dodati element u 2. stablo (ctrl-D za kraj unosa):\n");
} while(scanf("%d", &broj) > 0 &&
(koren_2 = dodaj_u_stablo (koren_2, broj)) );

183
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

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

pomocni = kopiraj_stablo(koren);
pomocni = kreiraj_uniju(pomocni, koren_2);

printf("-------------------------------------------------------\n");
printf("Prikaz 1. stabla:\n");
prikazi_stablo (koren);
putchar(\n);
printf("-------------------------------------------------------\n");
printf("Prikaz 2. stabla:\n");
prikazi_stablo (koren_2);
putchar(\n);
printf("-------------------------------------------------------\n");
printf("Unija ova dva stabla:\n");
prikazi_stablo (pomocni);
putchar(\n);
printf("-------------------------------------------------------\n");

pomocni = oslobodi_stablo(pomocni);

pomocni = kopiraj_stablo(koren);
pomocni = kreiraj_presek(pomocni, koren_2);

printf("Presek ova dva stabla:\n");


prikazi_stablo (pomocni);
putchar(\n);
printf("-------------------------------------------------------\n");

pomocni = oslobodi_stablo(pomocni);

pomocni = kopiraj_stablo(koren);
pomocni = kreiraj_razliku(pomocni, koren_2);

printf("Razlika ova dva stabla:\n");


prikazi_stablo (pomocni);
putchar(\n);
printf("-------------------------------------------------------\n");

pomocni = oslobodi_stablo (pomocni);


koren_2 = oslobodi_stablo (koren_2);
koren = oslobodi_stablo (koren);

184
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

return 0;

}
Primer 11.3 Primer demonstrira sortiranje niza pomocu binarnog stabla. Elementi
niza se redom prvo smeste u binarno stablo pretrage, a zatim se elementi pokupe
iz stabla obilazeci ga sa leva u desno (tj. u rastucem poretku). Vremenska slozenost
ovakvog algoritma je u ekvivalentna quick_sort()-u. Prostorna slozenost je nesto
veca, jer sortiranje nije u mestu, vec se koristi pomocna struktura binarno
stablo.
#include <stdio.h>
#include <stdlib.h>

#define MAX 1000

/* Struktura koja predstavlja cvor stabla */


typedef struct cvor {

int vrednost;
struct cvor * levi;
struct cvor * desni;

} Cvor;

/* Funkcija kreira novi cvor */


Cvor * napravi_cvor (int broj)
{

Cvor * novi = (Cvor *) malloc (sizeof(Cvor));

if (novi == NULL)
{
fprintf (stderr,"malloc() greska\n");
exit (1);
}

novi->vrednost = broj;
novi->levi = NULL;
novi->desni = NULL;

return novi;

185
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

/* Funkcija dodaje novu vrednost u stablo. Dozvoljava


ponavljanje vrednosti u stablu -- levo se dodaju
manje vrednosti, a desno vece ili jednake. */
Cvor * dodaj_u_stablo (Cvor * koren, int broj)
{

if (koren == NULL)
return napravi_cvor (broj);

if (koren->vrednost <= broj)


koren->desni = dodaj_u_stablo (koren->desni, broj);

else if (koren->vrednost > broj)


koren->levi = dodaj_u_stablo (koren->levi, broj);

return koren;

/* Funkcija oslobadja stablo */


void oslobodi_stablo (Cvor *koren)
{

if(koren == NULL)
return;

oslobodi_stablo (koren->levi);
oslobodi_stablo (koren->desni);
free(koren);

/* Funkcija obilazi stablo sa leva u desno i


vrednosti cvorova smesta u niz. Funkcija
vraca broj vrednosti koje su smestene u niz. */
int kreiraj_niz(Cvor * koren, int a[])
{
int r, s;

if(koren == NULL)
return 0;

r = kreiraj_niz(koren->levi, a);

186
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

a[r] = koren->vrednost;

s = kreiraj_niz(koren->desni, a + r + 1);

return r + s + 1;

/* Funkcija sortira niz tako sto najpre elemente


niza smesti u stablo, a zatim kreira novi niz
prolazeci kroz stablo sa leva u desno. */
void sortiraj(int a[], int n)
{
int i;
Cvor * koren = NULL;

for(i = 0; i < n; i++)


koren = dodaj_u_stablo(koren, a[i]);

kreiraj_niz(koren, a);

oslobodi_stablo(koren);

/* Test program */
int main()
{
int a[MAX];
int n, i;

printf("Uneti dimenziju niza manju od %d: ", MAX);


scanf("%d", &n);

printf("Uneti elemente niza: ");


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

printf("Niz pre sortiranja:\n");


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

187
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

sortiraj(a, n);

printf("Niz nakon sortiranja:\n");


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

return 0;
}
Primer 11.4 Program sa ulaza cita tekst i ispisuje broj pojavljivanja svake od reci
koje su se javljale u tekstu. Radi poboljsanja efikasnosti, prilikom brojanja reci koristi
se struktura podataka pogodna za leksikografsku pretragu u ovom slucaju binarno
pretrazivacko drvo.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MAX 1024

typedef struct cvor {


char rec[MAX]; /* rec */
int brojac; /* broj pojavljivanja reci */
struct cvor * levi;
struct cvor * desni;
} Cvor;

/* Pomocna funkcija za kreiranje cvora. Funkcija vraca


adresu novokreiranog cvora */
Cvor * napravi_cvor (char * rec)
{

/* dinamicki kreiramo cvor */


Cvor * novi = (Cvor *) malloc (sizeof(Cvor));

/* u slucaju greske ... */


if (novi == NULL)
{
fprintf (stderr,"malloc() greska\n");
exit (1);
}

/* inicijalizacija */

188
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

strcpy(novi->rec, rec);
novi->brojac = 1;
novi->levi = NULL;
novi->desni = NULL;

/* vracamo adresu novog cvora */


return novi;
}

/* Funkcija dodaje novi cvor u stablo sa datim korenom.


Ukoliko rec vec postoji u stablu, uvecava dati brojac.
Cvor se kreira funkcijom napravi_cvor(). Funkcija
vraca koren stabla nakon ubacivanja novog cvora. */
Cvor * dodaj_u_stablo (Cvor * koren, char *rec)
{

/* izlaz iz rekurzije: ako je stablo bilo prazno,


novi koren je upravo novi cvor */
if (koren == NULL)
return napravi_cvor (rec);

/* Ako je stablo neprazno, i koren sadrzi leksikografski


manju rec od date reci, broj se umece u desno podstablo,
rekurzivnim pozivom */
if (strcmp(koren->rec, rec) < 0)
koren->desni = dodaj_u_stablo (koren->desni, rec);
/* Ako je stablo neprazno, i koren sadrzi vecu vrednost
od datog broja, broj se umece u levo podstablo,
rekurzivnim pozivom */
else if (strcmp(koren->rec, rec) > 0)
koren->levi = dodaj_u_stablo (koren->levi, rec);
else
/* Ako je data rec vec u stablu, samo uvecavamo brojac. */
koren->brojac++;

/* Vracamo koren stabla */


return koren;

/* Funkcija pronalazi najfrekventniju rec, tj. cvor ciji


brojac ima najvecu vrednost. Funkcija vraca NULL, ako
je stablo prazno, odnosno adresu cvora koji sadrzi
najfrekventniju rec u suprotnom. */

189
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

Cvor * nadji_najfrekventniju (Cvor * koren)


{
Cvor *max, *max_levi, *max_desni;

/* Izlaz iz rekurzije */
if (koren == NULL)
return NULL;

/* Odredjujemo najfrekventnije reci u levom i desnom podstablu */


max_levi = nadji_najfrekventniju(koren->levi);
max_desni = nadji_najfrekventniju(koren->desni);

/* Odredjujemo MAX(koren, max_levi, max_desni) */


max = koren;
if(max_levi != NULL && max_levi->brojac > max->brojac)
max = max_levi;
if(max_desni != NULL && max_desni->brojac > max->brojac)
max = max_desni;

/* Vracamo adresu cvora sa najvecim brojacem */


return max;

/* Prikazuje reci u leksikografskom poretku, kao i broj pojava svake


od reci */
void prikazi_stablo(Cvor *koren)
{
if(koren == NULL)
return;

prikazi_stablo(koren->levi);
printf("%s: %d\n", koren->rec, koren->brojac);
prikazi_stablo(koren->desni);

/* Funkcija oslobadja prostor koji je alociran za


cvorove stabla. Funkcija vraca NULL, zato sto je
nakon oslobadjanja stablo prazno. */
void oslobodi_stablo (Cvor *koren)
{
/* Izlaz iz rekurzije */

190
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

if(koren == NULL)
return;

oslobodi_stablo (koren->levi);
oslobodi_stablo (koren->desni);
free(koren);

/* Funkcija ucitava sledecu rec iz fajla i upisuje je


u niz na koji pokazuje rec, maksimalne duzine max.
Funkcija vraca EOF ako nema vise reci, 0 u suprotnom.
Rec je niz alfabetskih karaktera.*/
int sledeca_rec(FILE *f, char * rec, int max)
{
int c;
int i = 0;

/* Dokle god ima mesta za jos jedan karakter u stringu,


i dokle god nismo stigli do kraja fajla... */
while(i < max - 1 && (c = fgetc(f)) != EOF)
{
/* Ako je slovo, ubacujemo ga u rec */
if(isalpha(c))
rec[i++] = tolower(c);
/* U suprotnom, ako smo procitali bar jedno slovo
prethodno, onda imamo rec. Inace idemo na sledecu
iteraciju */
else if(i > 0)
break;
}

/* Zatvaramo string */
rec[i] = \0;

/* Vracamo 0 ako imamo rec, EOF u suprotnom */


return i > 0 ? 0 : EOF;
}

/* test program */
int main(int argc, char **argv)
{

191
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

Cvor *koren = NULL, *max;


FILE *f;
char rec[MAX];

/* Proveravamo da li je navedeno ime datoteke */


if(argc < 2)
{
fprintf(stderr, "Morate uneti ime datoteke sa tekstom!\n");
exit(0);
}

/* Otvaramo datoteku */
if((f = fopen(argv[1], "r")) == NULL)
{
fprintf(stderr, "fopen() greska\n");
exit(1);
}

/* Ucitavamo reci iz datoteke. Rec je niz alfabetskih karaktera. */


while(sledeca_rec(f, rec, MAX) != EOF)
{
koren = dodaj_u_stablo(koren, rec);
}
/* Zatvaramo datoteku */
fclose(f);

/* Prikazujemo sve reci i brojeve njihovih pojavljivanja */


prikazi_stablo(koren);

/* Pronalazimo najfrekventniju rec */


if((max = nadji_najfrekventniju(koren)) == NULL)
printf("U tekstu nema reci!\n");
else
printf("Najcesca rec %s (pojavljuje se %d puta)\n", max->rec, max->brojac);

/* Oslobadjamo stablo */
oslobodi_stablo(koren);

return 0;
}
Primer 11.5 Mapa je apstraktna struktura podataka koja u sebi sadrzi parove oblika
(kljuc, vrednost). Pri tom su i kljuc i vrednost unapred odredenog (ne obavezno
istog) tipa (na primer, kljuc nam moze biti string koji predstavlja ime studenta, a
vrednost je npr. broj koji predstavlja njegov prosek). Operacije koje mapa mora

192
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

efikasno da podrzava su:


 dodavanje para (kljuc, vrednost) u mapu
 brisanje para (kljuc, vrednost) iz mape
 pronalazenje vrednosti za dati kljuc
 promena vrednosti za dati kljuc
Jedan od najcescih nacina implementacije mape je preko binarnog stabla pretrage.
Svaki cvor ovog stabla sadrzace odgovarajuci par (kljuc, vrednost), tj. svaki cvor
ce sadrzati dva podatka. Pri tom ce poredak u stablu biti odreden poretkom koji je
definisan nad kljucevima. Ovim se postize da se pretraga po kljucu moze obaviti na
uobicajen nacin, kao i sve ostale navedene operacije.
Jasno je da ovako implementirana mapa nece efikasno podrzavati operaciju pre-
trage po vrednosti (npr. naci sve kljuceve koji imaju datu vrednost), zato sto poredak
u stablu nije ni na koji nacin u vezi sa poretkom medu vrednostima. Medutim, u
mapi se najcesce i ne zahteva takva operacija.
Sledi primer koji demonstrira implementaciju mapa pomocu binarnog stabla.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX 1024

/* Struktura koja predstavlja cvor stabla */


typedef struct cvor {
char naziv[MAX];
int cena;
struct cvor * levi;
struct cvor * desni;
} Cvor;

/* Funkcija kreira novi cvor i vraca njegovu adresu */


Cvor * napravi_cvor (char * naziv, int cena)
{

/* dinamicki kreiramo cvor */


Cvor * novi = (Cvor *) malloc (sizeof(Cvor));

/* u slucaju greske ... */


if (novi == NULL)
{
fprintf (stderr,"malloc() greska\n");
exit (1);
}

193
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

/* inicijalizacija */
strcpy(novi->naziv, naziv);
novi->cena = cena;
novi->levi = NULL;
novi->desni = NULL;

/* vracamo adresu novog cvora */


return novi;

/* Funkcija dodaje novi cvor u stablo sa datim korenom.


U cvor se upisuje vrednost (naziv, cena). Ukoliko naziv
vec postoji u stablu, tada se azurira njegova cena.
Cvor se kreira funkcijom napravi_cvor(). Funkcija
vraca koren stabla nakon ubacivanja novog cvora. */
Cvor * dodaj_u_stablo (Cvor * koren, char * naziv, int cena)
{

/* izlaz iz rekurzije: ako je stablo bilo prazno,


novi koren je upravo novi cvor */
if (koren == NULL)
return napravi_cvor (naziv, cena);

/* Ako je stablo neprazno, i koren sadrzi naziv koji je


leksikografski manji od datog naziva, vrednost se umece
u desno podstablo, rekurzivnim pozivom */
if (strcmp(koren->naziv, naziv) < 0)
koren->desni = dodaj_u_stablo (koren->desni, naziv, cena);
/* Ako je stablo neprazno, i koren sadrzi naziv koji je
leksikografski veci od datog naziva, vrednost se umece
u levo podstablo, rekurzivnim pozivom */
else if (strcmp(koren->naziv, naziv) > 0)
koren->levi = dodaj_u_stablo (koren->levi, naziv, cena);
/* Ako je naziv korena jednak nazivu koja se umece, tada se samo
azurira cena. */
else
koren->cena = cena;

/* Vracamo koren stabla */


return koren;

194
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

/* Funkcija pretrazuje binarno stablo. Ukoliko


pronadje cvor sa vrednoscu naziva koja je jednaka
datom nazivu, vraca adresu tog cvora. U
suprotnom vraca NULL */
Cvor * pretrazi_stablo (Cvor * koren, char * naziv)
{

/* Izlaz iz rekurzije: ako je stablo prazno,


tada trazeni broj nije u stablu */
if (koren == NULL)
return NULL;

/* Ako je stablo neprazno, tada se pretrazivanje


nastavlja u levom ili desnom podstablu, u
zavisnosti od toga da li je trazeni naziv
respektivno manji ili veci od vrednosti naziva
korena. Ukoliko je pak trazeni naziv jednak
nazivu korena, tada se vraca adresa korena. */
if (strcmp(koren->naziv, naziv) < 0)
return pretrazi_stablo (koren->desni, naziv);
else if (strcmp(koren->naziv, naziv) > 0)
return pretrazi_stablo (koren->levi, naziv);
else
return koren;

/* cvor liste */
typedef struct cvor_liste {
char naziv[MAX];
int cena;
struct cvor_liste * sledeci;
} Cvor_liste;

/* Pomocna funkcija koja kreira cvor liste */


Cvor_liste * napravi_cvor_liste(char * naziv, int cena)
{
Cvor_liste * novi;

if((novi = malloc(sizeof(Cvor_liste))) == NULL)


{
fprintf(stderr, "malloc() greska\n");
exit(1);

195
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

strcpy(novi->naziv, naziv);
novi->cena = cena;
novi->sledeci = NULL;
return novi;
}

/* Funkcija pronalazi sve nazive cija je cena manja ili jednaka od date,
i formira listu koja sadrzi nadjene parove (naziv, cena) u leksikogra-
fskom poretku po nazivima. Prilikom pocetnog poziva, treci argument
treba da bude NULL. Funkcija obilazi stablo sa desna u levo, kako bi
se prilikom dodavanja na pocetak liste poslednji dodao onaj koji je
leksikografski najmanji (tj. on ce biti na pocetku). */
Cvor_liste * pronadji_manje (Cvor * koren, int cena, Cvor_liste * glava)
{
if(koren == NULL)
return glava;

/* Dodajemo na pocetak liste sve cvorove desnog podstabla cija je cena


manja od date. */
glava = pronadji_manje(koren->desni, cena, glava);

/* Dodajemo koren u listu, ako mu je cena manja od date */


if(koren->cena <= cena)
{
Cvor_liste * novi = napravi_cvor_liste(koren->naziv, koren->cena);
novi->sledeci = glava;
glava = novi;
}

/* Dodajemo na pocetak liste sve cvorove levog podstabla cija je cena


manja od date */
glava = pronadji_manje(koren->levi, cena, glava);

/* Vracamo glavu liste nakon svih modifikacija */


return glava;

/* Funkcija prikazuje listu */


void prikazi_listu(Cvor_liste * glava)
{
if(glava == NULL)

196
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

return;

printf("%s = %d\n", glava->naziv, glava->cena);


prikazi_listu(glava->sledeci);
}

/* Funkcija oslobadja listu */


Cvor_liste * oslobodi_listu(Cvor_liste * glava)
{
if(glava == NULL)
return NULL;

glava->sledeci = oslobodi_listu(glava->sledeci);
free(glava);

return NULL;
}

/* Funkcija oslobadja stablo. */


Cvor * oslobodi_stablo (Cvor *koren)
{

if(koren == NULL)
return NULL;

koren->levi = oslobodi_stablo (koren->levi);


koren->desni = oslobodi_stablo (koren->desni);
free(koren);

return NULL;

/* test program */
int main(int argc, char ** argv)
{
Cvor * koren = NULL, * pomocni;
Cvor_liste * glava = NULL;
FILE *f;
char naziv[MAX];
int cena;

/* Proveravamo da li je navedeno ime datoteke */

197
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

if(argc < 2)
{
fprintf(stderr, "Morate navesti ime datoteke!\n");
exit(0);
}

/* Otvaramo datoteku */
if((f = fopen(argv[1], "r")) == NULL)
{
fprintf(stderr, "fopen() greska\n");
exit(1);
}

/* Ubacujemo proizvode u stablo */


while(fscanf(f, "%s%d", naziv, &cena) == 2)
{
koren = dodaj_u_stablo(koren, naziv, cena);
}
fclose(f);

/* Testiranje pretrage po nazivu (efikasna operacija) */


printf("Uneti naziv proizvoda koji vas zanima: ");
scanf("%s", naziv);

if((pomocni = pretrazi_stablo(koren, naziv)) == NULL)


printf("Trazeni proizvod ne postoji\n");
else
printf("Cena trazenog proizvoda je: %d\n", pomocni->cena);

/* Testiranje pretrage po ceni (neefikasno) */


printf("Unesite maksimalnu cenu: ");
scanf("%d", &cena);
glava = pronadji_manje(koren, cena, NULL);
prikazi_listu(glava);

/* Oslobadjanje memorije */
glava = oslobodi_listu(glava);
koren = oslobodi_stablo(koren);

return 0;
}

Primer 11.6 Program broji pojavljivanje svake etikete u tekstu i ispisuje etikete i
njihove frekvencije u opadajucem poretku po frekvencijama.
Radi poboljsanja efikasnosti, prilikom brojanja pojavljivanja etiketa koristi se

198
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

struktura podataka pogodna za leksikografsku pretragu - u ovom slucaju binarno pre-


trazivacko drvo.
Na kraju rada, cvorovi drveta se presortiraju na osnovu broja pojavljivanja.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

/* Makimalna duzina imena etikete */


#define MAX_ETIKETA 32

/* Definisemo stanja prilikom citanja html datoteke */


#define VAN_ETIKETE 1
#define U_ETIKETI 2

/* Struktura koja predstavlja cvor stabla */


typedef struct cvor {
char etiketa[MAX_ETIKETA]; /* Ime etikete */
int brojac; /* Brojac pojavljivanja etkete u tekstu */
struct cvor *levi; /* Pokazivaci na levo */
struct cvor *desni; /* i desno podstablo */
} Cvor;

/* Funkcija dodaje ime html etikete u binarno stablo,


u rastucem leksikografskom poretku. Funkcija vraca
koren stabla nakon modifikacije. U slucaju da je
etiketa sa istim imenom vec u stablu, uvecava se
brojac pojavljivanja. */
Cvor * dodaj_leksikografski(Cvor *koren, char *etiketa)
{
int cmp;

/* Izlaz iz rekurzije */
if(koren == NULL)
{
if((koren = malloc(sizeof(Cvor))) == NULL)
{
fprintf(stderr,"malloc() greska\n");
exit(1);
}

/* Ime etikete se kopira u novi cvor, a brojac


se inicijalizuje na 1 (prvo pojavljivanje) */

199
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

strcpy(koren->etiketa, etiketa);
koren->brojac = 1;
koren->levi = NULL;
koren->desni = NULL;
return koren;
}

/* Rekurzivni pozivi */
if((cmp = strcmp(koren->etiketa,etiketa)) < 0)
koren->desni = dodaj_leksikografski(koren->desni, etiketa);
else if(cmp > 0)
koren->levi = dodaj_leksikografski(koren->levi, etiketa);
else
koren->brojac++; /* uvecanje brojaca za vec prisutne etikete */

return koren;
}

/* Funkcija cita ulazni fajl i iz njega izdvaja sve


otvorene html etikete (npr. <html>, <br> itd, ali ne
i </html>, </body> itd.) i njihova imena (bez znakova
(< i > kao i bez eventualnih atributa) ubacuje u stablo
u leksikografskom poretku. Tom prilikom ce se prebrojati
i pojavljivanja svake od etiketa. Funkcija vraca pokazivac
na koren kreiranog stabla. */
Cvor * ucitaj(FILE *f)
{
Cvor * koren = NULL;
int c;
int stanje = VAN_ETIKETE;
int i;
char etiketa[MAX_ETIKETA];

/* NAPOMENA: prilikom izdvajanja etiketa pretpostavlja se da je


html datoteka sintaksno ispravna, kao i da nakon znaka <
nema belina. Zato se otvorene etikete mogu lako prepoznati
tako sto pronadjemo znak < i nakon toga izdvojimo sva
slova koja slede. Ako postoji neprazan niz slova nakon znaka
<, tada je to upravo ime etikete. Ako ne, tada je verovatno
u pitanju zatvorena etiketa, npr. </html>, pa je ignorisemo. */

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


{
switch(stanje)

200
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

{
/* u ovom stanju trazimo prvu sledecu pojavu znaka < */
case VAN_ETIKETE:
if(c == <)
{
stanje = U_ETIKETI; /* sada smo u etiketi */
i = 0;
}
break;
/* u ovom stanju citamo slova koja slede, i nakon toga
ubacujemo procitanu etiketu u stablo */
case U_ETIKETI:
/* Ako je slovo, i nismo prekoracili duzinu niza
dodajemo slovo u niz */
if(isalpha(c) && i < MAX_ETIKETA - 1)
etiketa[i++] = c;
/* u suprotnom se vracamo u stanje VAN_ETIKETE */
else {
stanje = VAN_ETIKETE;
/* Ako je niz slova nakon < bio neprazan... */
if(i > 0)
{
etiketa[i]=\0;
/* ubacujemo procitanu etiketu u stablo */
koren = dodaj_leksikografski(koren, etiketa);
}
}
break;
}

return koren;

/* Funkcija dodaje u stablo etiketu ciji je broj pojavljivanja


poznat (broj), i to u opadajucem poretku po broju pojavljivanja.
Funkcija vraca pokazivac na koren tako modifikovanog stabla */
Cvor * dodaj_po_broju(Cvor * koren, char * etiketa, int broj)
{

/* Izlaz iz rekurzije */
if(koren == NULL)

201
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

{
if((koren = malloc(sizeof(Cvor))) == NULL)
{
fprintf(stderr,"malloc() greska\n");
exit(1);
}

/* Kopiramo u novi cvor ime i broj pojavljivanja etikete */


strcpy(koren->etiketa, etiketa);
koren->brojac = broj;
koren->levi = NULL;
koren->desni = NULL;
return koren;
}

/* NAPOMENA: s obzirom da dve ili vise etiketa mogu imati isti broj
pojavljivanja, etiketa se mora dodavati u stablo, cak i ako ima
isti broj pojavljivanja sa korenom. Zato cemo u levo podstablo
dodavati etikete koje imaju veci broj pojavljivanja od korena,
dok cemo u desno podstablo dodavati etikete koje imaju manji
ili jednak broj pojavljivanja od korena. */

/* Rekurzivni pozivi */
if(koren->brojac >= broj)
koren->desni = dodaj_po_broju(koren->desni, etiketa, broj);
else if(koren->brojac < broj)
koren->levi = dodaj_po_broju(koren->levi, etiketa, broj);

return koren;

/* Funkcija pretpostavlja da je novo stablo ili prazno, ili


uredjeno prema opadajucem poretku broja pojavljavanja
etiketa. Funkcija u takvo stablo rekurzivno dodaje sve
etikete iz starog stabla, i vraca koren na tako modifikovano
novo stablo. */
Cvor * resortiraj_stablo(Cvor * staro, Cvor * novo)
{

/* Izlaz iz rekurzije - nemamo sta da dodamo u novo stablo */


if(staro == NULL)
return novo;

202
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

/* Dodajemo etiketu iz korena starog stabla u novo stablo,


sortirano opadajuce prema broju pojavljivanja */
novo = dodaj_po_broju(novo, staro->etiketa, staro->brojac);

/* Rekurzivno dodajemo u novo stablo sve cvorove iz levog


i desnog podstabla starog stabla. */
novo = resortiraj_stablo(staro->levi, novo);
novo = resortiraj_stablo(staro->desni, novo);

return novo;
}

/* Ispis stabla - s leva na desno */


void ispisi_stablo(Cvor * koren)
{
if(koren == NULL)
return;

ispisi_stablo(koren->levi);
printf("%s: %d\n", koren->etiketa, koren->brojac);
ispisi_stablo(koren->desni);

/* Oslobadjanje dinamicki alociranog prostora */


void oslobodi_stablo(Cvor *koren)
{
if(koren == NULL)
return;

oslobodi_stablo(koren->levi);
oslobodi_stablo(koren->desni);
free(koren);
}

/* glavni program */
int main(int argc, char **argv)
{

FILE *in = NULL; /* Ulazni fajl */


Cvor * koren = NULL; /* Stablo u leksikografskom poretku */
Cvor * resortirano = NULL; /* stablo u poretku po broju pojavljivanja */

203
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

/* Mora se zadati makar ime ulaznog fajla na komandnoj liniji.


Opciono se kao drugi argument moze zadati opcija "-b"
sto dovodi do ispisa po broju pojavljivanja (umesto leksikografski) */
if(argc < 2)
{
fprintf(stderr, "koriscenje: %s ime_fajla [-b]\n", argv[0]);
exit(1);
}

/* Otvaramo fajl */
if((in = fopen(argv[1], "r")) == NULL)
{
fprintf(stderr, "fopen() greska\n");
exit(1);
}

/* Formiramo leksikografsko stablo etiketa */


koren = ucitaj(in);

/* Ako je korisnok zadao "-b" kao drugi argument, tada


se vrsi resortiranje, i ispisuje izvestaj sortiran
opadajuce po broju pojavljivanja */
if(argc == 3 && strcmp(argv[2], "-b") == 0)
{
resortirano = resortiraj_stablo(koren, resortirano);
ispisi_stablo(resortirano);
}
/* U suprotnom se samo ispisuje izvestaj u leksikografskom poretku */
else
ispisi_stablo(koren);

/* Oslobadjamo stabla */
oslobodi_stablo(koren);
oslobodi_stablo(resortirano);

return 0;
}
Primer 11.7 Efikasnije sortiranje corova stabla formira se niz pokazivaca na
cvorove stabla koji se u skladu sa funkcijom poredenja sortiraju pomocu bibliotecke
qsort funkcije.
#include <stdlib.h>
#include <stdio.h>

204
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

/* Cvor drveta sadrzi ime reci i


broj njenih pojavljivanja */
typedef struct _cvor {
char ime[80];
int br_pojavljivanja;
struct _cvor* levo, *desno;
} cvor;

/* Gradimo niz pokazivaca na cvorove drveta koji ce


nam sluziti da po prihvatanju svih reci izvrsimo
sortiranje po broju pojavljivanja */

#define MAX_BROJ_RAZLICITIH_RECI 1000

cvor* razlicite_reci[MAX_BROJ_RAZLICITIH_RECI];

/* Tekuci broj cvorova drveta */


int broj_razlicitih_reci=0;

/* Funkcija uklanja binarno drvo iz memorije */


void obrisi_drvo(cvor* drvo)
{
if (drvo!=NULL)
{ obrisi_drvo(drvo->levo);
obrisi_drvo(drvo->desno);
free(drvo);
}
}

cvor* napravi_cvor(char rec[])


{
cvor* novi_cvor=(cvor*)malloc(sizeof(cvor));
if (novi_cvor==NULL)
{
printf("Greska prilikom alokacije memorije\n");
exit(1);
}
strcpy(novi_cvor->ime, rec);
novi_cvor->br_pojavljivanja=1;

return novi_cvor;
}

205
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

/* Funkcija ubacuje datu rec u dato drvo i vraca pokazivac na


koren drveta */
cvor* ubaci(cvor* drvo, char rec[])
{
/* Ukoliko je drvo prazno gradimo novi cvor */
if (drvo==NULL)
{
cvor* novi_cvor = napravi_cvor(rec);

/* pokazivac na novo napravljeni cvor smestamo u niz


pokazivaca na sve cvorove drveta */
razlicite_reci[broj_razlicitih_reci++] = novi_cvor;

return novi_cvor;
}

int cmp = strcmp(rec, drvo->ime);

/* Ukoliko rec vec postoji u drvetu


uvecavamo njen broj pojavljivanja */
if (cmp==0)
{ drvo->br_pojavljivanja++;
return drvo;
}

/* Ukoliko je rec koju ubacujemo leksikografski ispred


reci koja je u korenu drveta, rec ubacujemo
u levo podstablo */
if (cmp<0)
{ drvo->levo=ubaci(drvo->levo, rec);
return drvo;
}

/* Ukoliko je rec koju ubacujemo


leksikografski iza reci koja je u
korenu drveta, rec ubacujemo
u desno podstablo */
if (cmp>0)
{ drvo->desno=ubaci(drvo->desno, rec);
return drvo;
}
}

/* Pomocna funkcija koja cita rec iz date datoteke i vraca

206
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

njenu duzinu, odnosno -1 ukoliko se naidje na EOF */


int getword(char word[], int lim, FILE* ulaz)
{
int c, i=0;
/* Umesto funkcije getchar koristimo fgetc
za rad sa datotekama */
while (!isalpha(c=fgetc(ulaz)) && c!=EOF)
;
if (c==EOF)
return -1;
do
{ word[i++]=c;
}while (i<lim-1 && isalpha(c=fgetc(ulaz)));

word[i]=\0;
return i;
}

/* Funkcija poredjenja za funkciju qsort. */


int poredi_br_pojavljivanja(const void* a, const void* b)
{
return
/* Konverzija pokazivaca b iz pokazivaca
na tip void u pokazivac na cvor jer
nam je svaki element niza koji sortiramo
tipa pokazivaca na cvor */
(*(cvor**)b)->br_pojavljivanja
-
(*(cvor**)a)->br_pojavljivanja;
}

main(int argc, char* argv[])


{
int i;

/* Drvo je na pocetku prazno */


cvor* drvo=NULL;
char procitana_rec[80];
FILE* ulaz;

if (argc!=2)
{ fprintf(stderr,"Greska :
Ocekivano ime datoteke\n");

207
Milena VujosevicJanicic 11.1 Binarno pretrazivacko stablo

exit(1);
}

if ((ulaz=fopen(argv[1],"r"))==NULL)
{
fprintf(stderr,"Greska : nisam uspeo da otvorim datoteku %s\n");
exit(1);
}

/* Citamo rec po rec dok ne naidjemo na kraj datoteke i


ubacujemo ih u drvo */
while(getword(procitana_rec,80,ulaz)!=-1)
drvo=ubaci(drvo,procitana_rec);

/* Sortiramo niz pokazivaca na cvorove


drveta po broju pojavljivanja */
qsort(razlicite_reci,
broj_razlicitih_reci,
sizeof(cvor*),
poredi_br_pojavljivanja);

/* Ispisujemo prvih 10 (ukoliko ih ima)


reci i njihov broj pojavljivanja */
for (i=0; i<10 && i<broj_razlicitih_reci; i++)
printf("%s - %d\n",razlicite_reci[i]->ime,
razlicite_reci[i]->br_pojavljivanja);

/* Uklanjamo drvo iz memorije */


obrisi_drvo(drvo);

fclose(ulaz);
}

208
Glava 12

Grafovi

Graf1 G=(V,E) sastoji se od skupa V cvorova i skupa E grana. Grane predstavljaju


relacije izmedu cvorova i odgovara paru cvorova. Graf moze biti usmeren (orijen-
tisan), ako su mu grane uredeni parovi i neusmeren (neorjentisan) ako su grane
neuredeni parovi.
Put u grafu je niz cvorova v1,v2,...,vn, pri cemu u grafu postoje grane (v1,v2),
(v2,v3), ..., (vn-1, vn). Ako jos vazi da je v1 = vn, tada se ovakav put naziva ciklus.
Iako su liste i stabla specijalni oblici grafova, u programiranju postoji bitna raz-
lika: liste i stabala se prevashodno koriste kao kontejneri za podatke (u svaki cvor
se smesta neki podatak odredenog tipa), grafovi se pre svega koriste za modeliranje
nekih problema iz prakse, kako bi se ti problemi predstavili na apstraktan nacin
i resili primenom algoritama nad odgovarajucim grafom. Na primer, cvorovima u
grafu se mogu predstaviti raskrsnice u gradu, a granama ulice koji ih povezuju. Tada
se zadatak nalazenja najkraceg puta od tacke A do tacke B u gradu moze svesti na
nalazenje najkraceg puta od cvora u do cvora v u grafu. Slicno se mogu resavati
problemi sa racunarskim mrezama (racunari se predstave cvorovima, a veze medu
njima granama), itd.
Grafovi se mogu predstavljati na vise nacina. Uobicajena su dva nacina pred-
stavljanja grafova. To su matrica povezanosti grafa i lista povezanosti.
Matrica povezanosti je kvadratna matrica dimenzije n, pri cemu je n broj cvorova
u grafu, takva da je element na preseku i-te vrste i j-te kolone jednak jedinici uko-
liko postoji grana u grafu od i-tog do j-tog cvora, inace je nula. Jasno je da
ce neusmerenim grafovima odgovarati simetricne matrice. Prednost ovakvog pred-
stavljanja je jednostavnost. Nedostatak ovakvog pristupa je neracionalno koriscenje
memorije u slucaju retkih grafova (grafova sa malo grana), gde ce najveci broj
elemenata matrice biti 0.
Umesto da se i sve nepostojece grane eksplicitno predstavljaju u matrici povezanosti,
mogu se formirati povezane liste od jedinica iz i-te vrste za i=1,2,...,n. To je
lista povezanosti. Svakom cvoru se pridruzuje povezana lista, koja sadrzi sve grane
susedne tom cvoru. Graf je predstavljen vektorom lista. Svaki elemenat vektora
1 Tekst i primeri preuzeti od Jelene Tomasevic, www.matf.bg.ac.yu/~jtomasevic, i Milana
Bankovica www.matf.bg.ac.yu/~milan zasnovano na materijalu Algoritmi, Miodrag Zivkovic i
http://www.matf.bg.ac.yu/~filip

209
Milena VujosevicJanicic Grafovi

sadrzi ime (indeks) cvora i pokazivac na njegovu listu cvorova. Ovakav pristup stedi
memoriju, a omogucava i e kasno dodavanje novih cvorova i grana.
Osnovni problem koji se javlja kod grafova jeste kako polazeci od nekog cvora, kre-
tanjem kroz puteva grafa posetiti sve cvorove. Ovakav postupak se naziva obilazak
grafa. Postoje dva osnovna algoritma za obilazak grafa: pretraga u dubinu (DFS,
skracenica od depth- rst-search) i pretraga u sirinu (BFS, skracenica od breadth-
rst-search).
Kod DFS algoritma, obilazak zapocinje iz proizvoljnog zadatog cvora r koji se
naziva koren pretrage u dubinu. Koren se oznacava kao posecen. Zatim se bira
proizvoljan neoznacen cvor r1, susedan sa r, pa se iz cvora r1 rekurzivno startuje
pretraga u dubinu. Iz nekog nivoa rekurzije izlazi se kad se naide na cvor v kome su
svi susedi vec oznaceni.
Primer 12.1 Primer reprezentovanja grafa preko matrice povezanosti. U programu
se unosi neorijentisan graf i DFS algoritmom se utvrduju cvrovi koji su dostizni iz
cvora 0.
#include <stdlib.h>
#include <stdio.h>

int** alociraj_matricu(int n)
{ int **matrica;
int i;
matrica=malloc(n*sizeof(int*));
if (matrica==NULL)
{
printf("Greska prilikom alokacije memorije\n");
exit(1);
}

for (i=0; i<n; i++)


{
/* Funkcija calloc popunjava rezervisan
prostor u memoriji nulama. */
matrica[i]=calloc(n,sizeof(int));
if (matrica[i]==NULL)
{
printf("Greska prilikom alokacije memorije\n");
exit(1);
}
}
return matrica;
}

void oslobodi_matricu(int** matrica, int n)


{ int i;

210
Milena VujosevicJanicic Grafovi

for (i=0; i<n; i++)


free(matrica[i]);
free(matrica);
}

int* alociraj_niz(int n)
{ int* niz;
niz=calloc(n,sizeof(int));
if (niz==NULL)
{
printf("Greska prilikom alokacije memorije\n");
exit(1);
}
return niz;
}

void oslobodi_niz(int* niz)


{ free(niz);
}

void unesi_graf(int** graf, int n)


{ int i,j;
for (i=0; i<n; i++)
for (j=i; j<n; j++)
{ printf("Da li su element %d i %d povezani : ",i,j);
do
{ scanf("%d",&graf[i][j]);
/* Radimo sa neusmerenim grafom */
graf[j][i]=graf[i][j];
} /* Obezbedjujemo ispravan unos */
while (graf[i][j]!=0 && graf[i][j]!=1);
}
}

void ispisi_graf(int** graf, int n)


{ int i,j;
for (i=0; i<n; i++)
{ for (j=0; j<n; j++)
printf("%d",graf[i][j]);
printf("\n");
}
}

211
Milena VujosevicJanicic Grafovi

/* Rekurzivna implementacija DFS algoritma */


void poseti(int i, int** graf, int n, int* posecen)
{ int j;
posecen[i]=1;
printf("Posecujem cvor %d\n",i);
for (j=0; j<n; j++)
if (graf[i][j] && !posecen[j])
poseti(j);
}

main()
{

/* Broj cvorova grafa (dimenzija matrice) */


int n;
/* Matrica povezanosti */
int **graf;

/* Pomocni vektor koji govori o tome koji su cvorovi posecivani


tokom DFS obilaska */
int *posecen;

int i, j;
printf("Unesi broj cvorova : ");
scanf("%d",&n);

graf=alociraj_matricu(n);
unesi_graf(graf,n);
ispisi_graf(graf,n);

posecen=alociraj_niz(n);
poseti(0, graf, n);

oslobodi_niz(posecen);
oslobodi_matricu(graf,n);
}
Primer 12.2 Primer demonstrira osnovne algoritme nad grafovima. U ovom primer
grafovi se predstavljaju matricama povezanosti. Zbog jednostavnosti, pretpostavlja se
da je broj cvorova ogranicen nekom fiksiranom konstantom, tako da se odgovarajuce
matrice alociraju staticki. Takode, da bi se pojednostavile liste argumenata pojedinih
funkcija, vecina promenljivih u ovom primeru se deklarisu kao globalne, kako bi kao
takve bile dostupne svim funkcijama.
#include <stdio.h>
#include <stdlib.h>

212
Milena VujosevicJanicic Grafovi

#define MAX_CVOROVA 100

/* Matrica povezanosti grafa. Pretpostavka je da broj


cvorova grafa nece biti veca od MAX_CVOROVA */
int graf[MAX_CVOROVA][MAX_CVOROVA];
int broj_cvorova;

/* Niz 0/1 vrednosti kojim se obelezavaju poseceni cvorovi */


int posecen[MAX_CVOROVA];

/* Pomocna funkcija koja utvrdjuje da li postoji neposecen cvor.


Funkcija vraca indeks prvog takvog cvora, ili -1 u slucaju da
su svi cvorovi vec poseceni */
int postoji_neposecen()
{
int i;

for(i = 0; i < broj_cvorova; i++)


if(!posecen[i]) return i;

return -1;

/* Pomocna funkcija koja sluzi za inicijalizaciju raznih nizova


(poput posecen[], dolazna_numeracija[] itd.) Za sve nizove
se pretpostavlja da su duzine broj_cvorova. */
void inicijalizuj(int niz[])
{
int i;

for(i = 0 ; i < broj_cvorova ; i++)


niz[i] = 0;

/* NAPOMENA: za potrebu demonstracije obilaska grafa, obrada koja


se prilikom obilaska vrsi bice numerisanje cvorova grafa u
poretku posecivanja. */

/* Staticki podaci koji se koriste za smestanje rezultata


prilikom numeracije cvorova (i za DFS i za BFS). */
int dolazna_numeracija[MAX_CVOROVA];

213
Milena VujosevicJanicic Grafovi

int odlazna_numeracija[MAX_CVOROVA];

/* Donji brojaci treba da se postave na nulu pre pozivanja


funkcija za numeraciju */
int brojac_dolazna=0;
int brojac_odlazna=0;

/* Funkcija obilazi graf DFS algoritmom, i tom prilikom


vrsi dolaznu i odlaznu numeraciju cvorova. Pre poziva
ove funkcije obavezno je postaviti brojace dolazne i
odlazne numeracije na 0 */
void DFS_numeracija(int polazni_cvor)
{
int i;

/* Obelezavanje */
posecen[polazni_cvor] = 1;

/* Ulazna obrada */
dolazna_numeracija[polazni_cvor] = ++brojac_dolazna;

/* Rekurzija (za sve cvorove ka kojima postoji grana


i koji jos nisu obelezeni) */
for(i = 0 ; i < broj_cvorova; i++)
if(graf[polazni_cvor][i] && !posecen[i])
DFS_numeracija(i);

/* Izlazna obrada */
odlazna_numeracija[polazni_cvor] = ++brojac_odlazna;
}

/* Funkcija vrsi BFS obilazak i numerise cvorove u poretku


obilaska. Pre poziva ove funkcije treba inicijalizovati
posecen[] i brojac_dolazna */
void BFS_numeracija(int polazni_cvor)
{

/* Improvizovani red koji koristimo za smestanje


cvorova koji cekaju da budu obradjeni. Cvorovi
se smestaju na kraj reda (kraj niza), a uzimaju
sa pocetka reda (niza). Zato imamo dva indeksa
koji pokazuju na pocetak i kraj reda. Duzina
ovog reda je MAX_CVOROVA sto je dovoljno jer
ce svaki cvor na red biti postavljen tacno jednom */

214
Milena VujosevicJanicic Grafovi

int red[MAX_CVOROVA];
int sledeci_na_redu = 0;
int poslednji_na_redu = -1;
int i;

/* Inicijalno se na redu nalazi samo polazni cvor */


posecen[polazni_cvor] = 1;
red[++poslednji_na_redu] = polazni_cvor;

/* Dokle god imamo cvorove u redu...*/


while(sledeci_na_redu <= poslednji_na_redu)
{
/* Vrsimo obradu cvora (numeracija) */
dolazna_numeracija[red[sledeci_na_redu]] = ++brojac_dolazna;

/* Za sve cvorove ka kojima postoji grana i koji nisu


poseceni vrsimo obelezavanje i dodavanje u red */
for(i = 0; i < broj_cvorova; i++)
if(graf[red[sledeci_na_redu]][i] && !posecen[i])
{
red[++poslednji_na_redu] = i;
posecen[i] = 1;
}
/* Prelazimo na sledeci u redu */
sledeci_na_redu++;
}
}

/* Test program */
int main()
{
int i,j;
int aciklican;

/* Unos matrice povezanosti grafa */


printf("Unesite broj cvorova grafa (<=%d): ", MAX_CVOROVA);
scanf("%d",&broj_cvorova);

for(i = 0; i < broj_cvorova; i++)


for(j = 0; j < broj_cvorova; j++)
{
if(i == j) continue;

printf("Da li postoji grana (%d,%d) (0/1): ", i, j);

215
Milena VujosevicJanicic Grafovi

scanf("%d", &graf[i][j]);
}

/* Testiramo DFS numeraciju */


inicijalizuj(posecen);

brojac_dolazna = 0;
brojac_odlazna = 0;

while((i = postoji_neposecen()) >= 0)


DFS_numeracija(i);

printf("Dolazna DFS numeracija: ");


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

putchar(\n);
printf("Odlazna DFS numeracija: ");
for(i = 0; i < broj_cvorova; i++)
printf("%d ", odlazna_numeracija[i]);
putchar(\n);

/* Testiramo BFS numeraciju */


inicijalizuj(posecen);
brojac_dolazna = 0;

while((i = postoji_neposecen()) >= 0)


BFS_numeracija(i);

printf("Dolazna BFS numeracija: ");


for(i = 0; i < broj_cvorova; i++)
printf("%d ",dolazna_numeracija[i]);
putchar(\n);

return 0;
}
Primer 12.3 Primer predstavljanja grafa preko niza listi suseda svakog od cvorova
grafa. U programu se unosi graf i DFS algoritmom se utvrdjuje koji su cvorovi
dostizni iz cvora 0.
#include <stdlib.h>
#include <stdio.h>

/* Cvor liste suseda */

216
Milena VujosevicJanicic Grafovi

typedef struct _cvor_liste


{ int broj; /* Indeks suseda */
struct _cvor_liste* sledeci;
} cvor_liste;

/* Ubacivanje na pocetak liste */


cvor_liste* ubaci_u_listu(cvor_liste* lista, int broj)
{ cvor_liste* novi=malloc(sizeof(cvor_liste));
if (novi==NULL)
{
printf("Greska prilikom alokacije memorije\n");
exit(1);
}
novi->broj=broj;
novi->sledeci=lista;
return novi;
}

/* Rekurzivno brisanje liste */


void obrisi_listu(cvor_liste* lista)
{ if (lista)
{ obrisi_listu(lista->sledeci);
free(lista);
}
}

/* Ispis liste */
void ispisi_listu(cvor_liste* lista)
{ if (lista)
{ printf("%d ",lista->broj);
ispisi_listu(lista->sledeci);
}
}

#define MAX_BROJ_CVOROVA 100

/* Graf predstavlja niz pokazivaca na pocetke listi suseda */


cvor_liste* graf[MAX_BROJ_CVOROVA];
int broj_cvorova;

int posecen[MAX_BROJ_CVOROVA];

/* Rekurzivna implementacija DFS algoritma */


void poseti(int i)

217
Milena VujosevicJanicic Grafovi

{ cvor_liste* sused;
printf("Posecujem cvor %d\n",i);
posecen[i]=1;
for( sused=graf[i]; sused!=NULL; sused=sused->sledeci)
if (!posecen[sused->broj])
poseti(sused->broj);
}

void oslobodi_graf(cvor_liste* graf[], int broj_cvorova)


{
int i;
for(i=0; i<broj_cvorova; i++)
obrisi_listu(graf[i]);
}

main()
{
int i;
printf("Unesi broj cvorova grafa : ");
scanf("%d",&broj_cvorova);
/*Unos grafa*/
for (i=0; i<broj_cvorova; i++)
{ int br_suseda,j;

graf[i]=NULL;

printf("Koliko cvor %d ima suseda : ",i);


scanf("%d",&br_suseda);
for (j=0; j<br_suseda; j++)
{ int sused;
do
{
printf("Unesi broj %d.-tog suseda cvora %d : ",j,i);
scanf("%d",&sused);
} while (sused<1 && sused>broj_cvorova);
graf[i]=ubaci_u_listu(graf[i],sused-1);
}
}

/*Ispis grafa*/
for (i=0; i<broj_cvorova; i++)
{ printf("%d - ",i);
ispisi_listu(graf[i]);
printf("\n");

218
Milena VujosevicJanicic Grafovi

}
/*Koji su sve cvorovi dostupni iz cvora 0*/
poseti(0);

/*Oslobadjanje memorije*/
oslobodi_graf(graf, broj_cvorova);
}
Primer 12.4 MINESWEEPER - primer jednostavne igrice.
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

/* Dimenzija table */
int n;

/* Tabla koja sadrzi 0 i 1 u zavisnosti


od toga da li na polju postoji bomba */
int** bombe;

#define PRAZNO (-1)


#define ZATVORENO 0
#define ZASTAVICA 9

/* Tabla koja opisuje tekuce stanje igre.


Moze da sadrzi sledece vrednosti :
ZATVORENO - opisuje polje
koje jos nije bilo otvarano
PRAZNO - polje na kome ne
postoji ni jedna bomba
BROJ od 1-8 - polje koje je
otvoreno i na kome pise
koliko bombi postoji u okolini
ZASTAVICA - polje koje je korisnik
oznacio zastavicom
*/
int** stanje;

/* Ukupan broj bombi */


int broj_bombi;

/* Ukupan broj postavljenih zastavica */


int broj_zastavica = 0;

/* Pomocne funkcije za rad sa matricama */

219
Milena VujosevicJanicic Grafovi

int** alociraj(int n)
{
int i;
int** m=(int**)malloc(n*sizeof(int*));
if(m==NULL) {printf("Greska prilikom alokacije memorije\n"); exit(1);}
for (i=0; i<n; i++)
{
m[i]=(int *)calloc(n,sizeof(int));
if(m[i]==NULL)
{printf("Greska prilikom alokacije memorije\n"); exit(1);}
}
return m;
}

void obrisi(int** m, int n)


{ int i;
for (i=0; i<n; i++)
free(m[i]);

free(m);
}

/* Funkcija postavlja bombe */


void postavi_bombe()
{
broj_bombi=(n*n)/6;
int kolona;
int vrsta;
int i;

/* Inicijalizujemo generator slucajnih brojeva */


srand(time(NULL));

for (i=0; i<broj_bombi; i++)


{ /* Racunamo slucajni polozaj bombe */
kolona=rand()%n;
vrsta=rand()%n;

/* Ukoliko bomba vec postoji tu,


opet idemo u istu iteraciju */
if (bombe[vrsta][kolona]==1)
{ i--;
continue;

220
Milena VujosevicJanicic Grafovi

/* Postavljamo bombu */
bombe[vrsta][kolona]=1;
}
}

/* Funkcija ispisuje tablu sa bombama */


void ispisi_bombe()
{
int i,j;
for (i=0; i<n; i++)
{ for (j=0; j<n; j++)
printf("%d",bombe[i][j]);
printf("\n");
}
}

/* Funkcija ispisuje tekuce stanje */


void ispisi_stanje()
{ int i,j;
for (i=0; i<n; i++)
{ for (j=0; j<n; j++)
{ if (stanje[i][j]==ZATVORENO)
printf(".");
else if (stanje[i][j]==PRAZNO)
printf(" ");
else if (stanje[i][j]==ZASTAVICA)
printf("*");
else
printf("%d",stanje[i][j]);
}
printf("\n");
}
}

/* Funkcija postavlja zastavicu na


dato polje ili je uklanja
ukoliko vec postoji */
void postavi_zastavicu(int i, int j)
{
if (stanje[i][j]==ZATVORENO)
{ stanje[i][j]=ZASTAVICA;
broj_zastavica++;

221
Milena VujosevicJanicic Grafovi

}
else if (stanje[i][j]==ZASTAVICA)
{ stanje[i][j]=ZATVORENO;
broj_zastavica--;
}
}

/* Funkcija izracunava koliko bombi


postoji u okolini date bombe */
int broj_bombi_u_okolini(int v, int k)
{ int i, j;
int br=0;
/* Prolazimo kroz sva okolna polja */
for (i=-1; i<=1; i++)
for(j=-1; j<=1; j++)
{ /* preskacemo centralno polje */
if (i==0 && j==0)
continue;
/* preskacemo polja "van table" */
if (v+i<0 || k+j<0 || v+i>=n || k+j>=n)
continue;
if (bombe[v+i][k+j]==1)
br++;
}

return br;
}

/* Centralna funkcija koja vrsi otvaranje


polja i pritom se otvaranje "siri"
i na polja koja su oko datog */
void otvori_polje(int v, int k) {
/* Ukoliko smo "nagazili" bombu
zavrsavamo program */
if (bombe[v][k]==1)
{ printf("BOOOOOOOOOOOOOOOOM!!!!\n");
ispisi_bombe();
exit(1);
}
else
{
/* Brojimo bombe u okolini */
int br=broj_bombi_u_okolini(v,k);

222
Milena VujosevicJanicic Grafovi

/* Azuriramo stanje ovog polja */


stanje[v][k]=(br==0)?PRAZNO:br;

/* Ukoliko u okolini nema bombi,


rekurzivno otvaramo
sva polja u okolini koja su zatvorena */
if (br==0)
{
/* Petlje indeksiraju sva okolna polja */
int i,j;
for (i=-1; i<=1; i++)
for (j=-1; j<=1; j++)
{
/* Preskacemo centralno polje */
/* if (i==0 && j==0)
continue; */
/* Preskacemo polja van table */
if (v+i<0 || v+i>=n || k+j<0 || k+j>=n)
continue;
/* Ukoliko je okolno polje
zatvoreno, otvaramo ga */
if (stanje[v+i][k+j]==ZATVORENO)
otvori_polje(v+i, k+j);
}
}
}
}

/* Funkcija utrdjuje da li je partija gotova


Partija je gotova u trenutku kada su sve
bombe pokrivene zastavicama i
kada nijedno drugo polje nije
pokriveno zastavicom */
int gotova_partija()
{ int i,j;
for (i=0; i<n; i++)
for (j=0; j<n; j++)
{ /* Ukoliko postoji nepokrivena bomba,
partija nije zavrsena */
if (bombe[i][j]==1 && stanje[i][j]!=ZASTAVICA)
return 0;
}

/* Partija je zavrsena samo ukoliko je

223
Milena VujosevicJanicic Grafovi

broj zastavica jednak broj bombi */


return broj_zastavica==broj_bombi;
}

main() {

/* Unosimo dimenziju table */


printf("Unesite dimenziju table : ");
scanf("%d",&n);

/* Alociramo table */
bombe=alociraj(n);
stanje=alociraj(n);

/* Postavljamo bombe */
postavi_bombe();

/* Sve dok partija nije gotova */


while(!gotova_partija())
{ int v,k;
char akcija;

/* Ispisujemo tekuce stanje */


ispisi_stanje();

/* Sve dok korisnik ne unese o ili z


trazimo od njega da upise
odgovarajucu akciju */
do
{
getchar();
printf("Unesi akciju (o - otvaranje polja,
z - postavljanje zastavice) : ");
scanf("%c",&akcija);
} while (akcija!=o && akcija!=z);

/* Trazimo od korisnika da unese koordinate


polja sve dok ih ne unese ispravno
Korisnicke koordinate krecu od 1,
a interne od 0 */
do
{
printf("Unesi koordinate polja : ");
scanf("%d",&v);

224
Milena VujosevicJanicic Grafovi

scanf("%d",&k);
} while(v<1 || v>n || k<1 || k>n);

/* Reagujemo na akciju */
switch(akcija)
{ case o:
otvori_polje(v-1,k-1);
break;
case z:
postavi_zastavicu(v-1,k-1);
}
}

/* Konstatujemo pobedu */
ispisi_stanje();
printf ("Cestitam! Pobedili ste\n");
obrisi(stanje,n);
obrisi(bombe,n);
}

225
Ivan P. Stanimirovi Uvod u programiranje

0. ELEMENTI TEORIJE ALGORITAMA .............................................................. 5

0. 1. INTUITIVNA DEFINICIJA ALGORITMA ............................................................................................ 5

0. 2. OSOBINE ALGORITAMA ...................................................................................................................... 6

0.3. ZAPIS (OPIS) ALGORITMA...................................................................................................................... 8


0.3.1. Zapis algoritama skupom pravila ........................................................................................................... 8
0.3.2. Zapis algoritama dijagramom toka ......................................................................................................... 9

0.4. BEKUSOVA NORMALNA FORMA (BNF) ........................................................................................... 10


0. 4. 1. SINTAKSNI DIJAGRAMI ................................................................................................................ 13

1. OSNOVNI ELEMENTI PROGRAMSKIH JEZIKA ................................................ 13

1.1. Pseudojezik kao opti model viih programskih jezika ............................................................................ 13

1.2. Azbuka jezika ............................................................................................................................................... 15

1.3. Identifikatori i rezervisane rei ................................................................................................................... 15

1.4. Konstante ..................................................................................................................................................... 16

1.5. Promenljive ................................................................................................................................................... 17

1.6. Komentari ..................................................................................................................................................... 17

1.7. Struktura programa .................................................................................................................................... 18


1.7.1. Struktura programa u C .......................................................................................................................... 18

2. TIPOVI PODATAKA............................................................................................. 18
Statika i dinamika tipizacija ..................................................................................................................... 20

2.1. Koncept jakih tipova podataka ................................................................................................................... 21

2.2. Koncept slabih tipova ................................................................................................................................. 21

2.3. Ekvivalentnost tipova................................................................................................................................... 22

2.4. Elementarni tipovi podataka ..................................................................................................................... 22


2.4.1. Celobrojni tipovi (Integer ili int) ............................................................................................................ 22
2.4.2. Realni tip (float ili real) .......................................................................................................................... 23
2.4.3. Logiki tip podataka ............................................................................................................................... 23
2.4.4. Znakovni tipovi ...................................................................................................................................... 23

2.5. Tipovi podataka u jeziku C ......................................................................................................................... 24


Celobrojni tipovi u C ................................................................................................................................... 25
Realni tipovi podataka u C .......................................................................................................................... 26
Tip char........................................................................................................................................................ 27
Konverzija tipova podataka i kast................................................................................................................ 28
Vrste konverzije tipova ................................................................................................................................ 29
Konstante ..................................................................................................................................................... 29
Sizeof operator............................................................................................................................................. 30
Osnovne aritmetike operacije .................................................................................................................... 30
Operacije poreenja i logike operacije....................................................................................................... 33

1
Ivan P. Stanimirovi Uvod u programiranje

2.6. Diskretni tipovi podataka u programskim jezicima ................................................................................. 34


2.6.1. Nabrojivi tipovi u programskim jezicima ............................................................................................... 34

2.8. Upotreba typedef iskaza u C ....................................................................................................................... 34

3. ULAZ I IZLAZ PODATAKA.................................................................................. 35

3.1. Ulaz i izlaz podataka u jeziku C .................................................................................................................. 35


3.1.1. Funkcije printf() i scanf() ....................................................................................................................... 35
3.1.2. Direktive pretprocesora u C.................................................................................................................... 38

4. OSNOVNE UPRAVLJAKE STRUKTURE ........................................................ 40

4.1. naini predstavljanja algoritama ................................................................................................................ 41

4.2. Sekvenca naredbi i blok ............................................................................................................................... 47


4.2.1. Globalne i lokalne promenljive .............................................................................................................. 47

4.3. Struktura selekcije ....................................................................................................................................... 49


4.3.1. If-then struktura ...................................................................................................................................... 49
4.3.2. If-then-else struktura .............................................................................................................................. 50
4.3.3. Operator uslovnog prelaza u C ............................................................................................................... 56

4.4. Struktura viestruke selekcije ..................................................................................................................... 56


4.4.1. Viestruka selekcija u C ......................................................................................................................... 57

4.5. Programske petlje ........................................................................................................................................ 60


4.5.1. Programske petlje u C ............................................................................................................................ 61
While naredba u C ....................................................................................................................................... 61
Primena while ciklusa u obradi teksta u C .................................................................................................. 65
Do-while naredba u C .................................................................................................................................. 65
For naredba u C ........................................................................................................................................... 66

4.6. Formalizacija repetitivnih iskaza ............................................................................................................... 69

4.7. Nasilni prekidi ciklusa ................................................................................................................................. 71

4.8. Naredbe za bezuslovno grananje ................................................................................................................ 72


4.8.1. Oznake (labele) ...................................................................................................................................... 72

5. POTPROGRAMI ................................................................................................. 76

5.1. Funkcije ........................................................................................................................................................ 77


5.1.1. Poziv i definicija funkcija u C ................................................................................................................ 77
Return naredba............................................................................................................................................. 78
Prototip funkcije .......................................................................................................................................... 79
5.1.2. Makroi u jeziku C ................................................................................................................................... 84

5.2. Procedure ...................................................................................................................................................... 84

5.3. Prenos argumenata ...................................................................................................................................... 85


5.3.1. Prenos po vrednosti (Call by Value) ...................................................................................................... 85
Prenos parametara po vrednosti u C ............................................................................................................ 86
5.3.2. Prenos po rezultatu (Call by Result) ....................................................................................................... 87
5.3.3. Prenos po vrednosti i rezultatu (Call by Value-Result) .......................................................................... 87
5.3.4. Prenos po referenci (Call by Reference)................................................................................................. 87
Poziv po adresi pomou pokazivaa u C ..................................................................................................... 89
Prenos po referenci koristei reference u C++............................................................................................. 93

2
Ivan P. Stanimirovi Uvod u programiranje

Vraanje viestrukih vrednosti .................................................................................................................... 95


Vraanje viestrukih vrednosti po referenci ................................................................................................ 97
Predavanje po referenci, zbog efikasnosti ................................................................................................... 98

5.4. Globalne promenljive kao parametri potprograma ................................................................................ 105


Primeri ....................................................................................................................................................... 107

5.5. Rekurzivni potprogrami ............................................................................................................................ 110


5.5.1. Primeri rekurzivnih funkcija u C .......................................................................................................... 112

5.6. Implementacija potprograma ................................................................................................................... 115

5.7. Scope rules (domen vaenja) ..................................................................................................................... 118

5.8. Memorijske klase u C ................................................................................................................................ 119


5.8.1. ivotni vek objekata ........................................................................................................................ 121
5.8.2. Vrste objekata po ivotnom veku .................................................................................................... 121
Statiki i automatski objekti ...................................................................................................................... 121

6. STRUKTURNI TIPOVI PODATAKA .................................................................. 122

6.1. Polja u programskim jezicima .................................................................................................................. 122

6.2. Jednodimenzionalni nizovi u C ................................................................................................................. 123

6.3. Veza izmeu nizova i pointera u C ........................................................................................................... 133


6.3.1. Pointerska aritmetika ............................................................................................................................ 135

6.4. Nizovi i dinamika alokacija memorije u C ............................................................................................. 136

6.5. Viedimenzionalna polja ............................................................................................................................ 142


6.5.1. Viedimenzionalni nizovi u C .............................................................................................................. 143
6.5.2. Pokazivai i viedimenzionalni nizovi u C ........................................................................................... 143
6.5.3. Matrice i dinamika alokacija memorije .............................................................................................. 170

6.6. STRINGOVI ............................................................................................................................................... 173


6.6.1. Stringovi u C ........................................................................................................................................ 173
Inicijalizacija i obrada stringova ................................................................................................................ 173
Testiranje i konverzija znakova ................................................................................................................. 175
Uitavanje i ispis stringova........................................................................................................................ 176
Standardne funkcije za rad sa stringovima u C .......................................................................................... 181

6.7. Strukture i nabrojivi tipovi u c ................................................................................................................. 184


6.7.1. lanovi strukture .................................................................................................................................. 184
6.7.2 Strukturni tipovi i pokazivai u C ......................................................................................................... 189
6.7.3. Definicija strukturnih tipova pomou typedef ...................................................................................... 193
6.7.4. Unije ..................................................................................................................................................... 165

6.8. Nabrojivi tip podataka u c ......................................................................................................................... 168

6.9. Dinamike matrice i strukture .................................................................................................................. 170

6.10. Datoteke .................................................................................................................................................... 172


6.10.1. Pristup datotekama u C....................................................................................................................... 172
Otvaranje i zatvaranje datoteka ................................................................................................................. 173
Funkcije fgetc() i fputc()............................................................................................................................ 175
fputc ........................................................................................................................................................... 175
Funkcije fprintf() i fscanf() ........................................................................................................................ 176
Funkcija feof() ........................................................................................................................................... 178

3
Ivan P. Stanimirovi Uvod u programiranje

fclose, _fcloseall ........................................................................................................................................ 180


feof ............................................................................................................................................................ 180
6.10.2. Binarne datoteke ................................................................................................................................. 181
Direktni pristup datotekama ...................................................................................................................... 182

Literatura........................................................................................................................................................... 183

4
Ivan P. Stanimirovi Uvod u programiranje

0. ELEMENTI TEORIJE ALGORITAMA

0. 1. INTUITIVNA DEFINICIJA ALGORITMA


Algoritam jeste jedan od osnovnih pojmova matematike i raunarstva. Prve algoritme sreemo
kod starih Grka. Svima su poznati Euklidov algoritam i Eratostenovo sito (250. g. p. n.e.) Algoritam
predstavlja uputstvo za reavanje nekog zadatka u cilju dobijanja reenja (posle konano mnogo
vremena).
Pri reavanju nekog sloenog zadatka (problema) korsitimo rastavljanje (dekompoziciju) zadatka
na prostije podzadatke (podprobleme). Postupak moemo nastaviti sve dok se ne dobije jedan konaan
skup relativno jednostavnih podzadataka. Takve podzadatke nazvaemo elementarnim koracima ili
elementarnim operacijama. Svaki takav korak definie koju operaciju i kojim redosledom se takva
obrada izvrava u cilju dobijanja reenja datog problema. Ukoliko je elementarni korak relativno
sloen tada se on moe zadati u vidu uputstva (pravila) za reavanje takvog podproblema. Zato
elementarne korake nazivamo i (elementarnim) pravilima.
Opis toka odvijanja elementarnih operacija (koraka) u cilju reavanja nekog zadatka (problema)
naziva se procedura. Procedura se sastoji od konano mnogo elementarnih koraka koji se mogu
mehaniki izvravati u odreenom strogo definisanom redosledu i to za konano vreme.
Primena procedure moe dovesti do sledea tri sluaja:
1) Primena procedure predstavlja beskonaan proces. Reenje zadatka se u tom sluaju ne moe
dobiti posle konano mnogo koraka, odnosno, posle koanno mnogo vremena. Procedura ne
daje rezultat.
2) Primena procedure se prekida posle konano mnogo koraka i ne dobija se rezultat. Proces
raunanja se ne moe nastaviti jer se ne zna korak na koji se prenosi izvrenje. Uzrok ove
situacije mogu biti pogreni ulazni podaci (ili pogreno definisana procedura). U prethodna dva
sluaja kaemo da imamo nerezultativnu proceduru.
3) Proces primene procedure se prekida posle konano mnogo koraka sa dobijanjem rezultata.
Reenje zadatka postoji i moe se dobiti primenom procedure (rezultativne).
Samo u treem sluaju kaemo da procedura predstavlja algoritam koji se moe primeniti za reavanje
datog zadatka. Na slian nain uvedene su i stroge matematike definicije algoritama.
Na osnovu prethodnog moemo dati intuitivnu definiciju algoritma, gde umesto pojma
elementarni korak koristimo naziv algoritamski korak (pravilo).
Def. 1: Algoritam je konaan (ureen) skup strogo definisanih algoritamskih koraka
(pravila) ijom primenom na ulazne podatke (i meurezultate) dobijamo reenje zadatka posle
konano mnogo vremena.
Iz definicije uoavamo da svaki algoritam ima konano mnogo algoritamskih koraka (koij je
najee ureen). Svaki algoritamski korak mora biti strogo (nedvosmisleno) definisan (kao i ceo
algoritam) tako da se moe na isti nain razumeti i izvriti od strane bilo kog izvrioca.
Primena algoritma se zavrava posle konano mnogo vremena a to znai da svaki algoritamski
korak mora biti izvriv i da se mora primeniti konano mnogo puta.
Algoritam definie preslikavanje (funkciju) koje svakom izboru vrednosti ulaznih veliina
algoritma (zadatka) pridruuje odgovarajui rezultat. Kaemo da svaki algoritam ima svoju oblast

5
Ivan P. Stanimirovi Uvod u programiranje

primenljivosti (ulaz).

0. 2. OSOBINE ALGORITAMA
Intuitivna definicija algoritma je nestroga definicija. Zato navodimo neke osobine koje
karakteriu svaki algoritam. Na taj nain dodatno preciziramo ovaj pojam tako da je ekvivalentan sa
strogim matematikim definicijama algoritma.

1. Diskretnost. Svaki algoritam predstavlja konaan ureen skup algoritamskih koraka. To je


rezultat dekompozicije (diskretizacije) problema koji se reava od strane oveka. Pri tome,
algoritam nije skup algoritamskih koraka, ve ureen skup ili niz, jer je bitan redosled
algoritamskih koraka u zapisu algoritma. Takoe kamo da je proces izvrenja algoritma
diskretan u vremenu. To znai da se u svakom vremenskom trenutku (intervalu) izvrava samo
jedan algoritamski korak. Proces izvravanja algoritma jeste konaan niz algoritamskih koraka
koji se po strogo definisanom redosledu izvravaju. To je sluaj kada imamo jednog izvrioca
algoritma (jedan procesor). Postoje i paralelni algoritmi, koji omoguuju da se dva ili vie
algoritamskih koraka izvravaju istovremeno.
2. Determinisanost (odreenost). Svaki algoritamski korak treba da je definisan jasno, strogo
(tano) i nedvosmisleno. Tumaenje i izvravanje pravila algoritma ne sme zavisiti od volje
oveka ili maine. Posle izvrenja nekog algoritamskog koraka strogo je definisan prelaz na
sledei algoritamski korak. To znai da je izvrenje algoritma deterministiki proces i da se
moe automatski izvravati. Opis algoritma na prirodnom jeziku moe dovesti do
dvosmislenosti.
3. Izvrivost. Uspenu definiciju izvrivosti dao je D. Knut. On kae da je algoritamski korak
izvriv ako je ovek u stanju da ga izvri za konano vreme (pomou olovke i papira). Kod
algoritamski reivih zadataka nema neizvrivih koraka. Meutim, mogue je lako formulisati
pravilo koje nije izvrivo. Na primer: Ako razvoj broja sadri 7 uzastopnih devetki tada
sabrati sve preostale cifre.
4. Konanost. Osobina konanosti algoritma jeste zahtev da se izvrenje svakog algoritma zavri
posle konano mnogo vremena. Drugim reima,izvrenje svakog algoritma je postignuto posle
konano mnogo primena algoritamskih koraka. Zbog osobina 1. i 3. to znai da svaki
algoritamski korak ma kog algoritma mora da se izvri konano mnogo puta. U suprotnom,
nemamo algoritam. Takav je sledei primer procedure koja se nikad ne zavrava :
Korak 1 : Neka je i = 0 ;
Korak 2 : Neka i dobije vrednost i +1 ;
Korak 3 : Prei na korak 2 .
Iako imamo konano mnogo algoritamskih koraka, pri emu je svaki od njih strogo definisan i
izvriv, ovo nije algoritam. Kod sloenijih algoritama (zadataka)

javlja se potreba formalnog dokaza konanosti algoritma.


5. Ulaz i izlaz algoritma. Svaki algoritam ima dva posebno izdvojena (konana) skupa podataka
(veliina). Prva jeste skup ulaznih a druga skup izlaznih veliina. Broj veliina u ovim
skupovima moe biti i nula. Skup ulaznih veliina algoritma predstavlja polazne veliine
(podatke) zadatka koji se reava. Skup izlaznih veliina jeste traeno reenje (rezultat)
postavljenog zadatka. Ukratko, ove skupove nazivamo ulaz i izlaz algoritma. (Za podatke koji
na pripadaju skupu ulaznih podataka algoritma kaemo da algoritam nije primenljiv).
6. Masovnost (Univerzalnost). Univerzalnost je osobina algoritma da se moe primeniti na to
iru klasu problema. To upravo znai da ulazne veliine algoritma mogu uzimati poetne
vrednosti iz to obilnijih (masovnijih) skupova podataka. Algoritam jeste opte uputstvo koje
se moe primeniti na ma koji izbor vrednosti ulaznih veliina. Zbog ove osobine,moemo rei
da je algoritam bolji ukoliko je univerzalniji (termin masovnost manje odgovara ovoj osobini).

6
Ivan P. Stanimirovi Uvod u programiranje

7. Elementarnost algoritamskih koraka. Algoritam treba da sadri algoritamske korake koji


predstavljaju elementarne operacije koje korisnik algoritma moe da razume ili izvrilac
algoritma da izvri. Za potrebe oveka, algoritamski koraci mogu biti kompleksnije
fundamentalne ili logike celine u sloenom algoritmu. Meutim, za potrebe pisanja programa,
algoritam sadri elementarne algoritamske korake koji odgovaraju naredbama ili pozivima
potprograma, algoritam sadi elementarne algoritamske korake koji odgovaraju naredbama ili
pozivima potprograma programskog jezika.
8. Rezultativnost (usmerenost). Algoritam je tako definisan da polazei od proizvoljnih
vrednosti ulaznih veliina primena algoritamskih koraka vodi (usmerava) strogo ka dobijanju
traenog rezultata.
Analizom izvrenja algoritma mogu se uoiti tri naina izvravanja algoritamskih koraka:
sukcesivno (sekvencijalno), sa granicom i cikliko.
a) Sukcesivno izvravanje algoritamskih koraka jeste takvo da se koraci izvravaju jedanput i u
redosledu kako su napisani. Takvi algoritamski koraci ine prostu linijsku algoritamsku
strukturu ili sekvencu (nisku) algoritamskih koraka.
b) Izvravanje algoritamskih koraka tako da se neki izvre jedanput a neki nijednom predstavlja
primer izvravanja sa grananjem (ili prelazom). Takvu algoritamsku strukturu nazivamo
razgranatom linijskom algoritamskom strukturom.
c) Cikliko izvravanje se javlja kada se grupa algoritamskih koraka izvrava vie puta. Takvu
grupu naredbi nazivamo ciklikom algoritamskom strukturom ili ciklusom.
Korienjem (komponovanjem) ovakve tri algoritamske strukture moemo reiti ma koji zadatak.
Paralelnost (jednovremenost). Algoritam definiemo kao konaan skup algoritamskih koraka.
Taj skup je ureen jer se njime definie prirodan redosled izvravanja koraka sa mogunou grananja
ili ponovnog izvravanja. Za izvrenje algoritma kaemo da je niz primena algoritamskih koraka.
Postavlja se pitanje ta je pravilnije rei : skup ili niz. Prednost dajemo prvom terminu jer postoje
algoritmi u kojima se moe promeniti redosled nekih algoritamskih koraka a da se reenje ne
menja. Takve algoritamske korake moemo izvravati istovremeno (paralelno), pomou vie
izvrioca (procesora). Algoritmi koji definiu paralelno izvravanje algoritamskih koraka jesu
paralelni algoritmi, a paralelni procesori izvravaju takve algoritme.
Efikasnost (efektivnost). Dva razliita algoritma koji reavaju jedan isti zadatak moemo
uporeivati u odnosu na neki izbrani kriterijum. Rezultat uporeivanja moe biti da je jedan algoritam
bolji ili efikasniji od drugog. Izbor kriterijuma moe biti razliit. Najee se pravi kompromis
izmeu razliitih kriterijuma (vreme memorija, jednostavnost brzina ). esto puta neki
efikasni algoritmi zavise od izbora ulaznih podataka algoritma. Tako imamo efikasne algoritme
sortiranja podataka za sluajno izabrane (neureene) podatke ili pak za delimino ureene.
Elegantnost. Elegantnost moe biti subjektivan kriterijum za izbor algoritma, ali se esto koristi.
Elegantno reenje zadatka jeste ono koje je prosto (jednostavno) i originalno. Jednostavnost
reenja je uvek poeljno ali je pitanje da li su uvek mogua originalna reenja. Pod originalnou
reenja podrazumeva se njegova neoiglednost.
Originalno reenje za izmenu mesta (vrednosti) dveju promenljivih a i b moe biti sledei
algoritam :
Korak 1 : Neka je a = a+b ;
Korak 2 : Neka je b = a-b ;
Korak 3 : Neka je a = ab .
Meutim,ovo nije elegantno reenje jer nije jednostavno, a takoe nije efikasno niti univerzalno (ne
vai za sve mogue vrednosti a i b). Univerzalno reenje koristi pomonu promenljivu :
1) p = a ;
2) a = b ;
3) b = p .
Rekurzija. Nasuprot iteraciji, koja se najee koristi za reavanje zadataka ciklike prirode,

7
Ivan P. Stanimirovi Uvod u programiranje

rekurzija je razraena od strane specijalista funadamentalne matematike kao nain definisanja


funkcija. Ona se koristi i u (raunarstvu i) programiranju za rekurzivne definicije tipova i struktura
podataka, kao i za rekurzivne potprograme (funkcije i procedure). Rekurzivne definicije se karakteriu
time to objekat koji se definie figurie u samoj definiciji. Rekurzivna definicija funkcije f, koja
zavisi od prirodnog broja n, sadri dva dela. Najpre se definie veza izmeu funkcije f(n) i funkcije
f(n1). U drugom delu se definie vrednost funkcije f za posebnu vrednost argumenta n. Na slian
nain se iskazuju razliite rekurzivne definicije. Navedimo sledee rekurzivne definicije funkcija :
n (n1)! ,n>1
1) n-faktorijel : n! =
1 , n = 0, 1

a an1 , n>0
2) stepen : an =
1, n=0

f(n1)+f(n2) , n >1
3) Fibonaijev niz : f(n) =
1 ,n=0

4) najvei zajedniki delilac :


n, m=n
NZD(m,n) = NZD(nm, m), n > m
NZD(mn, n) , m > n

0.3. ZAPIS (OPIS) ALGORITMA


Opis algoritma ima dva osnovna cilja :
1) da je (algoritam) razumljiv raznim korisnicima (ljudima) tako da se moe koristiti ili prenositi;
2) da se na osnovu njega moe pisati program na nekom (algoritamskom) programskom jeziku u
cilju izvravanja na raunaru.
U tom cilju razvijeni su razliiti sistemi (dogovori) za zapis (opis, zadavanje, predstavljanje)
algoritama. Ovakvi sistemi zapisivanja algoritama treba da budu jednostavni ali (dovoljno) precizni
tako da ih ovek moe lako da razume. Takvi opisi algoritama predstavljaju univerzalne jezike, koji
su nezavisni od raunara. Postoji nekoliko najee korienih naina za zapis algoritama,a to su :
a) skup pravila (pomou prirodnog jezika);
b) dijagram toka (pomou grafikih tabela);
c) pseudokod.
Za taan zapis algoritama tako da se moe izvriti na raunaru koristimo algoritamske programske
jezike. Ekvivalentan zapis algoritma na programskom jeziku jeste program. Program predstavlja zapis
algoritma pomou naredbi koje su ekvivalentne odgovarajuim algoritamskim koracima.

0.3.1. Zapis algoritama skupom pravila


Najprirodniji nain zapisa algoritama jeste pomou prirodnog jezika kojim komuniciraju ljudi.
Tako se algoritam moe saoptiti govorom ili tekstualno. Primeri za to su razni kulinarski recepti,
uputstva za rukovanje mainama, koja jesu neka vrsta algoritama. Takvi opisi mogu biti neprecizni, pa
ak i dvosmisleni zbog sloenosti prirodnog jezika.
Meutim, zapis algoritama pomou skupa pravila ima zadatak da pregledno, jasno i tano opie
algoritamske korake pomou rei, simbola i reenica prirodnog jezika. Oblik pravila algoritma je na
odreen nain precizan tako da su ona jasna i razumljiva svakome. U zapisu algoritama skupom

8
Ivan P. Stanimirovi Uvod u programiranje

pravila moe se uvesti ime algoritma. Pored toga algoritamska pravila se najee oznaavaju rednim
brojevima (0,1,2,. . . ), sa dodatnom simbolikom oznakom u vidu slova ili rei. Izvrenje algoritma
poinje od pravila sa rednim brojem 0 ili 1. Zatim se pravila algoritma izvravaju prirodnim
redosledom (redno) dok se ne doe do pravila za grananje,prelaz ili pravila za cikliko izvravanje
algoritamskih koraka.
Navodimo neka najee upotrebljavana pravila za zapis algoritma :
1. Pravilo dodeljivanja : <promenljiva> := <izraz>
Izraunata vrednost izraza dodeljuje se promenljivoj sa leve strane simbola dodeljivanja := .
Alternativni simboli mogu biti = , , .
2. Pravilo uslovnog grananja : if <uslov> then <pravilo>
Ako je <uslov> ispunjen tada se izvrava <pravilo>,a u suprotnom prelazi se na sledee pravilo.
3. Pravilo grananja : if <uslov> then <pravilo1>
else <pravilo2>
Ako je <uslov> ispunjen izvrava se <pravilo1>,a u suprotnom <pravilo2>.
4. Pravilo bezuslovnog grananja (skoka) : go to <oznaka pravila>
Ovo pravilo ukazuje da se prekida prirodni redosled izvrenja pravila algoritma i zahteva prelaz na
pravilo oznaeno sa <oznaka pravila>.
5. Pravilo za prekid izvrenja algoritma : Kraj (Stop)
Posle izvrenja ovog pravila prekida se izvrenje algoritma.
6. Pravilo za ulaz podataka : Ulaz (<lista ulaznih veliina>)
7. Pravilo za izlaz podataka : Izlaz (<lista izlaznih veliina>)
8. Pravilo ciklusa : Ponavljaj
<pravilo 1>
<pravilo 2>
. . .
<pravilo n>
Sve dok se <uslov> ne ispuni
Ovo pravilo definie ponovljeno izvravanje niza pravila <pravilo 1>,. . . ,<pravilo n> sve dok
<uslov> nije ispunjen. Kada se <uslov> ispuni prelazi se na sledee pravilo.
Navedimo primer Euklidovog algoritma za nalaenje najveeg zajednikog delioca.
E0. Euklid
E1. Ulaz (m,n)
E2. r:= m MOD n ostatak deljenja
E3. Ako r=0 tada prei na E7
E4. m:=n
E5. n:=r
E6. Prei na E2
E7. nzd:=n
E8. Izlaz (nzd)
E9. Kraj
Slina algoritamska pravila imamo kod opisa algoritama pomou pseudo koda. Pseudo kod koristi
pravila bliska naredbama programskog jezika. Pravila su jednostavna, itljiva i nedvosmislena.

0.3.2. Zapis algoritama dijagramom toka


Jedan od najjednostavnijih i esto korienih naina zapisa algoritama jeste dijagram toka (ili
blok ema) algoritma (tokovnik). Dijagram toka predstavlja jednu varijantu grafikog opisa algoritma.

9
Ivan P. Stanimirovi Uvod u programiranje

Svaki algoritamski korak predstavljen je grafikim simbolom (blokom). Svi blokovi su povezani
linijama sa moguim strelicama. Na taj nain se zadaje struktura algoritma i redosled izvravanja
algoritamskih koraka. Oblik grafikog simbola ukazuje na vrstu algoritamskog koraka,odnosno
njegovu funkciju u algoritmu. U tabeli su dati najee korieni grafiki simboli i njihova funkcija.
Grafiki simbol algoritamskog koraka Funkcija algoritamskog koraka
(Definie) poetak algoritma

Ulazne veliine algoritma


(blok ulaza)
Obrada podataka
(blok obrade)
Uslovni algoritamski korak
(blok odluke)
Izlazne veliine algoritma
(blok izlaza)
Kraj algoritma

Proizvoljna algoritamska ema se u optem sluaju moe razloiti na elementarne eme (ili
elementarne algoritamske strukture). Postoje tri vrste elementarnih ema:
1) linijska (sekvenca)
2) razgranata (grananje)
3) ciklika (ciklus)
Pokazuje se da je dovoljno imati na raspolaganju jednu linijsku,jednu razgranatu i jednu cikliku
elementarnu emu da bi se realizovala proizvoljna algoritamska struktura. U praksi se esto koriste
razliiti oblici razgranatih i ciklikih elementarnih ema.
Moe se primetiti da svaka od ovih elementarnih ema ima jedinstven ulaz u emu i jedinstven
izlaz iz nje. To omoguuje lako komponovanje sloenih algoritamskih ema pomou elementarnih.
Takve eme zovemo dobro strukturiranim. Ukoliko se na izlaz jedne elementarne eme povee ulaz
druge elementarne eme i tako postupak nastavi dobijamo linijsku kompoziciju elementarnih ema.
Meutim,ako na izlaz nekog algoritamskog koraka u okviru ciklike eme nadoveemo ulaz
elementarne ciklike eme dobijamo koncentrinu kompoziciju ciklikih ema.
Viestruko grananje moemo realizovati kada (na izlaz nekog algoritamskog koraka) u okviru
jedne od grana umetnemo novu razgranatu emu.

0.4. BEKUSOVA NORMALNA FORMA (BNF)


Ovaj metajezik prvi je predloio Homski 56 za opis prirodnih jezika. Sistem zapisa koji
opisujemo i koristimo pripada Bekusu, po kome je ovaj metajezik dobio naziv. esto se koristi termin
Bekusova notacija (ili Bekus-Naurova forma to je donekle nepravilno). Ovim metajezikom opisana je
nepotpuno sintaksa jezika ALGOL 60. Prema miljenju Homskog, ovaj metajezik je pogodan za opis
jednostavnijih (kontekstno-nezavisnih) jezika. Zato su lingvisti pristupili definisanju i korienju
monijih metajezika.
Bekusova notacija je jednostavan metajezik. Osnovni pojmovi (konstrukcije) u ovom jeziku jesu:
metaformula, metaizraz, metaoperacije, metapromenljiva i metakonstanta. Pomou metaformula
opisujemo sve sintaksne konstrukcije (pojmove) u izvornom (programskom) jeziku. Opiimo sve ove
pojmove Bekusove notacije (polazei od najjednostavnijih).
Metakonstanta (terminal, terminalni simbol) jeste jedan simbol ili niska simbola azbuke jezika
koji opisujemo. Dakle, metakonstanta se na jedinstven nain zapisuje u metajeziku preuzimanjem iz
izvornog jezika. Da bi se to naglasilo (i ako ima potrebe) metakonstanta se moe uokviriti znacima
navoda () ili apostrofom ().

10
Ivan P. Stanimirovi Uvod u programiranje

Metapromenljiva (neterminal, neterminalni simbol) u Bekusovoj notaciji jeste pojam (sintaksna


jedinica) izvornog jezika. Metapromenljiva se mora definisati pomou metaformule, jer se ne moe
preuzeti iz izvornog jezika na jedan jedini nain kao metakonstanta. Metapromenljiva se zapisuje kao
fraza prirodnog stavljena izmeu ugalstih zagrada ( < , > ). Time se u Bekusovoj notaciji imenuje
pojam iz izvornog jezika (Npr. <program>,<naredba>,<izraz>,<slovo>).
Metaizraz je:
1. metakonstanta ,
2. metapromenljiva ili
3. konaan niz metakonstanti i/ili metapromenljivih koje su meusobno razdvojene
metaoperacijama.
Metaoperacija moe biti operacija spajanja (nadovezivanja, katenacije) ili razdvajanja (izbora,
alternacije).
Operacija spajanja (nadovezivanja) pie se u obliku i ita se za kojim sledi , gde su i
metakonstante ili metapromenljive (ili metaizrazi u optem sluaju sa zagradama ).
Operacija razdvajanja (izbora,alternacije) pie se u obliku i ita ili . Simbol operacije
razdvajanja je simbol metajezika. Operacija nadovezivanja ima vii prioritet od operacije
razdvajanja. Tako zapis predstavlja izbor od dve mogunosti ili , to znai da se najpre
realizuje spajanje.
Metaformula (definiciona jednaina, gramatiko pravilo, (pravilo) produkcija(e), pravilo
redukcije, pravilo zamene, itd.) jeste ureeni par (,) , koji se zapisuje u obliku
::= ,
i ita po definiciji je (ili to je ),gde je metapromenljiva , metaizraz a metasimbol ::=
jeste simbol (operacije) definisanja.
Alternativni simboli definisanja mogu biti : , , = , := .
Metapromenljiva na levoj strani metaformule predstavlja pojam (konstrukciju) u izvornom
jeziku koji se definie. Metaizraz definie postupak generisanja ispravne konstrukcije na osnovu
jednostavnijih pojmova (metaoperanada) primenjujui operacije izbora i nadovezivanja. Rezultujua
vrednost metaizraza jeste metakonstanta (niska terminalnih simbola) koja se moe dodeliti (upotrbiti)
matapromenljivoj sa leve strane metaformule.
Metaizraz se moe upotrebiti za generisanje svih moguih sintaksno korektnih terminalnih niski
koje predstavlja pojam .
Metaformule se mogu,dakle,upotrebiti kao gramatika pravila za graenje ispravnih konstrukcija
u izvornom jeziku (potreba programera). Druga njihova uloga je da se mogu koristiti za proveru
sintaksne korektnosti prethodno napisanih terminalnih niski (potreba prevodilaca).
Primer 1. Opisati pojam celog broja u programskom jeziku.
1. <ceo broj> ::= <znak broja> <ceo broj bez znaka> <ceo broj bez znaka>
2. <znak broja> ::= +
3. <ceo broj bez znaka> ::= <cifra> <ceo broj bez znaka> <cifra>
4. <cifra> ::= 0 1 2 3 4 5 6 7 8 9 .
Proirena Bekusova Normalna Forma (PBNF)
U literaturi se za opis sintakse razliitih jezika koriste i neki drugi naini zapisa (varijante
Bekusove notacije). Ukazaemo na neka korisna proirenja koja olakavaju i skrauju zapis
(metaformula). Ovakve nove mogunosti imaju istu mo kao i Bekusova normalna forma,ali su
pogodnije za korienje. Proirenja uvode ( male , srednje i velike ) zagrade kao i neke druge
mogunosti.
1. Male zagrade
Ukazali smo da operacija spajanja (nadovezivanja) ima vii prioritet od operacije razdvajanja. Ukoliko

11
Ivan P. Stanimirovi Uvod u programiranje

elimo da promenimo ovaj prioritet tada moemo upotrebiti male zagrade kao u aritmetikom izrazu.
Tako izraz ( ) znai izbor ili , ( za razliku od zapisa ). Na taj nain moemo rei da
je operacija spajanja distributivna u odnosu na operaciju razdvajanja. Obrnuto ne vai jer je () =
zbog uvedenog prioriteta.
Male zagrade moemo upotrebiti kao metasimbole u cilju skraivanja zapisa (faktorizacije) u
sledeem sluaju.
Metaformulu
::= xy xz . . . xt
moemo zapisati u obliku
::= x ( y z . . . t )
to je mnogo preglednije. I ovo je primena distribucije prema razdvajanju.
Zagrade se mogu i dalje umetati,na slian nain kao kod aritmetikih izraza. Na primer, ako je y
= f y1, z = f z1 , tada moemo zapisati
::= x ( f ( y1 z1 ) . . . t ).
2. Srednje zagrade
Srednje zagrade koristimo kada elimo da ukaemo na opcionu (fakultativnu) nisku (konstrukciju). To
znai da se takva niska moe ali ne mora upotrebiti. Tako u opisu celog broja znak broja je opciona
konstrukcija pa moemo pisati:
< ceo broj > ::= < znak > < ceo broj bez znaka > .
U optem sluaju moemo pisati :
= .
3. Velike zagrade
Pomou rekurzije (rekurzivnih pravila) u Bekusovoj normalnoj formi moemo definisati (opisati) listu
(spisak,niz) proizvoljno mnogo elemenata. Tako moemo pisati
( 1 ) < ceo broj bez znaka > ::= < cifra > < ceo broj bez znaka > < cifra >
( 2 ) <spisak imena> ::= < ime > < ime > , < spisak imena > .
Velike zagrade moemo upotrebiti kao metasimbole da bi ukazali da se niska uokvirena velikim
zagradama moe ponoviti proizvoljan broj puta i da se moe izostaviti. U tom sluaju gornja pravila
moemo napisati na sledei nain:
( 1 ) < ceo broj bez znaka > ::= < cifra > < cifra >
( 2 ) < spisak imena > ::= < ime > , < ime > .
Za proizvoljnu konstrukciju (nisku) moemo pisati
= . . .
To znai da zapis predstavlja drugi nain zapisa za iteraciju *= A* jednoelementnog skupa
A=, i piemo
*= . . .
= . . . .
Zato umesto moemo pisati i *. Takoe zapis za proizvoljnu iteraciju moemo upotrebiti
umesto . . . .
Pomou gornjuh i donjih indeksa moemo zadati maksimalni i minimalni broj ponavljanja neke
konstrukcije.
Sreu se i sledei zapisi za konane liste elemenata koji se ponavljaju pomou tri take:
e1 , e2 , . . . , en

12
Ivan P. Stanimirovi Uvod u programiranje

0. 4. 1. SINTAKSNI DIJAGRAMI
Sintaksni dijagrami su jedna vrsta grafikog metajezika jer koriste grafike simbole za opis
sintakse jezika. Zato su oni pregledniji i itljiviji od Bekusove notacije. Ovaj jedinstven metajezik je
ekvivalentan sa Bekusovom normalnom formom. I proirene Bekusove normalne forme se lako
realizuju pomou sintaksnih dijagrama.
Sintaksni dijagram je imenovani orijentisani graf sa jednim ulazom i jednim izlazom sa
vorovima grafa koji predstavljaju terminalne ili neterminalne simbole. Svaki prolaz kroz sintaksni
dijagram od ulaza prema izlazu generie jednu sintaksno pravilnu konstrukciju jezika. Linije (sa
strelicama) koje spajaju vorove grafa realizuju metaoperacije nadovezivanja i razdvajanja (izbora) na
prirodan nain.
Za terminalni simbol t koristimo grafiki simbol krunog ili elipsoidnog oblika. Za neterminalne
simbole predvien je pravougaoni simbol..
Metaoperacija iz Bekusove notacije i proirenja (upotreba zagrada) se realizuju na jedostavan
nain. U nastavku navodimo ekvivalentne realizacije operacija u oba metajezika.
1. Spajanje (nadovezivanje) :
12. . . n 12. . . n

1 2 n

2. Razdvajanje (izbor) :
1 2 . . . n 1

n
3. Iteracija (pozitivna iteracija) :
* = . . .
. . .
4. Opciona konstrukcija :
=
5. Ogranieno ponavljanje :
= . . . . . .
= . . . . . .

1. Osnovni elementi programskih jezika

1.1. Pseudojezik kao opti model viih programskih jezika


Za definiciju pseudojezika kao opteg modela viih programskih jezika neophodno je obuhvatiti
sledee etiri fundamentalne komponente:

13
Ivan P. Stanimirovi Uvod u programiranje

(1) Tipovi i strukture podataka koje pseudojezik podrava:


- statiki skalarni tipovi,
- statiki strukturirani tipovi,
- dinamiki tipovi sa promenljivom veliinom,
- dinamiki tipovi sa promenljivom strukturom.
(2) Osnovne kontrolne strukture koje se primenjuju u pseudojeziku:
- sekvenca,
- selekcije,
- ciklusi,
- skokovi.
(3) Operacije ulaza i izlaza podataka:
- ulaz/izlaz podataka za ulazno-izlazne ureaje i datoteke,
- konverzija tekstualnog i binarnog formata podataka.
(4) Tehnike modularizacije programa:
- nezavisne funkcije i procedure,
- interne funkcije i procedure,
- rekurzivne funkcije i procedure.
Razni tipovi podataka neophodni su u programskim jezicima da bi podraavali razne tipove
objekata koje sreemo u matematikim modelima. Podaci mogu biti skalarni ili strukturirani. Podatak
je strukturiran ukoliko se sastoji od vie komponenti koje se nalaze u precizno definisanom odnosu.
Primer strukturiranog objekta je pravougaona matrica realnih brojeva kod koje svaki element
predstavlja komponentu koja se nalazi u odreenom odnosu sa ostalim komponentama. Podatak je
skalaran ukoliko se ne sastoji od jednostavnijih komponenti. Jedan od skalarnih tipova podataka na
svim programskim jezicima je celobrojni tip podataka. Lako je uoiti da za svaki tip podataka postoje
operacije koje za njih vae, a ne vae za druge tipove podataka. Tako je na primer inverzija matrice
operacija koja se ne primenjuje na celobrojne skalare, na isti nain kao to se operacija celobrojnog
deljenja dva skalara ne moe primeniti na matrice.
Osnovne kontrolne strukture su izuzetno vana komponenta svakog programskog jezika. Pomou
njih se odreuje redosled izvravanja operacija koje raunar obavlja. Osnovni tipovi kontrolnih
struktura su sekvenca kod koje se instrukcije obavljaju onim redosledom kojim su napisane u
programu, i strukture sa grananjima, ciklusima i skokovima. Grananja se koriste za izbor jednog od
vie paralelnih programskih segmenata, ciklusi realizuju ponavljanje nekog niza instrukcija, a skokovi
slue za kontrolisani izlaz iz petlji, iz programa (kraj rada) i za realizaciju pojedinih osnovnih
kontrolnih struktura.
Da bi se omoguilo komuniciranje raunara sa spoljnim okruenjem potrebne su instrukcije ulaza i
izlaza podataka. Pri tome podaci mogu da se uitavaju sa tastature ili iz datoteka i da se prenose na
ekran, tampa, ili u datoteke.
Pod datotekom (file) podrazumevamo osnovnu organizaciju podataka koja obuhvata proizvoljan
broj manjih jednoobrazno strukturiranih celina koje se nazivaju zapisi. Svaki zapis sadri podatke o
jednoj jedinici posmatranja. Na primer, zapis moe sadrati strukturirane podatke o motornom vozilu
(tip, godina proizvodnje, snaga motora, vlasnik, itd.), dok skup veeg broja ovakvih zapisa predstavlja
datoteku motornih vozila. Alfanumeriki podaci (slova, cifre i specijalni znaci) se uvaju u tekst
datotekama, a numeriki podaci mogu da se uvaju bilo u tekstualnoj bilo u kompaktnoj binarnoj
formi. Za sve podatke postoji format kojim se odreuje njihova struktura, a pri nekim prenosima
podataka moe se automatski vriti i konverzija formata.
Ako bi programi bili formirani kao neprekidni nizovi instrukcija, onda bi kod velikih programa bilo
nemogue razumevanje naina rada celine, i na taj nain bilo bl znatno oteano odravanje programa.
Zbog toga su mehanizmi modularizacije programa od vitalnog znaaja za uspeh nekog programskog
jezika. Pod modularizacijom programa podrazumevamo razbijanje programa na manje (najee
nezavisne) celine kod kojih su precizno definisani ulazni i izlazni podaci, kao i postupak kojim se na

14
Ivan P. Stanimirovi Uvod u programiranje

osnovu ulaznih podataka dobijaju izlazni podaci. U ovu grupu spadaju nerekurzivne i rekurzivne
funkcije i procedure.

Prilikom definicije jezika polazi se od osnovnog skupa znakova, azbuke jezika koja sadri sve
zavrne simbole (terminalne simbole) jezika. Nad azbukom jezika definiu se ostali elementi jezika,
konstante, rezervisane rei, identifikatori od kojih se dalje grade druge sloene sintaksne kategorije
kao to su na primer opisi, upravljake naredbe i slino.

1.2. Azbuka jezika


Azbuka jezika predstavlja osnovni skup simbola (znakova) od kojih se grade sve sintaksne
kategorije jezika. Broj znakova azbuke se obino razlikuje od jezika do jezika i kree se od najmanje
48 do 90 znakova. Azbuka programskog jezika obino obuhvata skup velikih i malih slova engleske
abecede, skup dekadnih cifara i odreeni skup specijalnih znakova. Dok je kod starijih programskih
jezika bilo uobiajeno da se koriste samo velika slova (na primer FORTRAN IV), danas se skoro
redovno dozvoljava i ravnopravno korienje malih slova abecede. Azbuke programskih jezika se
najvie razlikuju po skupu specijalnih znakova koje obuhvataju. Narednih nekoliko primera azbuka
programskih jezika to ilustruje.
Azbuka jezika C
velika slova: A | B| C | D| E| F|G|H|I|J|K|L|M|N|0| P|Q| R|S|T|U|V|W|X|Y|Z
cifre: 0 |1 |2|3|4|5|6|7|8|9
specijalni znaci: + | - | * | / |= | ( | ) | { \ } \ [ | ] \ < | > | ' | " | ! | # | \ | % | & | | | | _ | ^ | | ~ \ , \ ; | : | ?
znak blanko
mala slova: a | b | c | d | e| f|g|h| i| j| k|l|m|n|o|p|q|r|s| t|u| v|w|x|y|z

Danas se obino skup specijalnih znakova azbuke programskog jezika standardizuje i svodi na skup
znakova meunarodnog standardnog koda ISO7 (ASCII kod).
b | ! | " | $ | % | & | ' | ( | ) | * | + | , | - | . | / | : | ; | < | = | > | ? | @ | [ | ] | \ | ^ ili _ | ` | { | } | ~
eto se pored osnovnog skupa specijalnih znakova koriste i sloeni simboli, obino dvoznaci,
kao na primer:
| ** | >= | <= | => | =< | << | <> | >< | := | -> | /* | */ |
U nekim programskim jezicima (FORTRAN), zbog nedovoljnog broja odgovarajuih znakova
umesto specijalnih znakova koriste se posebne simbolike oznake .EQ., .NE., .GT., .GE., .LT., .LE.,
kojima se oznaavaju relacije jednako, razliiti, vee, vee ili jednako, manje i manje ili jednako,
redom.

1.3. Identifikatori i rezervisane rei


Identifikatori su uvedene rei kojima se imenuju konstante, promenljive, potprogrami, programski
moduli, klase, tipovi podataka i slino.
U svim programskim jezicima postoji slina konvencija za pisanje identifikatora. Identifikatori su
nizovi koji se obino sastoje od slova i cifara i obavezno zapoinju slovom. Ovo ogranienje
omoguava jednostavniju implementaciju leksikog analizatora i razdvajanje identifikatora od drugih
sintaksnih kategorija (numerikih i znakovnih konstanti na primer). U nekim jezicima dozvoljeno je da
se i neki specijalni znaci pojave u okviru identifikatora. Najee je to crtica za povezivanje "_" kojom
se postie povezivanje vie rei u jedan identifikator. Na primer, u jeziku C crtica za povezivanje se
moe koristiti na isti nain kao i slova, to znai da identifikator moe da zapone ovim znakom. Slede
primeri nekih identifikatora:
ALFA A B1223 Max_vrednost PrimerPrograma
U jeziku C velika i mala slova se razlikuju. Programski jezik PASCAL ne razlikuje velika i mala
slova.

15
Ivan P. Stanimirovi Uvod u programiranje

Dobra je programerska praksa da identfikatori predstavljaju mnemonike skraenice.


Nizovi znakova azbuke koji u programu imaju odreeni smisao nazivaju se lekseme. Leksema
moe da bude i samo jedan znak.
Re jezika ije je znaenje utvreno pravilima tog jezika naziva se rezervisana re.
Rezervisane rei mogu da budu zabranjene, kada se ne mogu koristiti kao identifikatori u
programu. Takav je sluaj u programskom jeziku C. Meutim, i u jezicima u kojima je to dozvoljeno
ne preporuuje se korienje kljunih rei kao identifikatora jer moe da smanji preglednost programa,
a u nekim sluajevima da dovede i do ozbiljnih greaka u programu. Poznat je, na primer, sluaj
greke sa DO naredbom koji je doveo do pada letilice iz satelitskog programa Geminy 19. U programu
za upravljanje letilicom stajala je DO naredba napisana kao:
DO 10 I = 1.10
umesto ispravnog koda
DO 10 I = 1,10.
Greka pri prevoenju meutim nije otkrivena jer je leksiki analizator ovu liniju kda protumaio kao
naredbu dodeljivanja
DO10I = 1.10
u kojoj se promenljivoj D010I dodeljuje vrednost 1.10. Greka je otkrivena tek u fazi izvravanja
programa kada je prouzrokovala pad letilice.
Rezervisane rei jezika C:
auto, break, case, char, const, continue, default, do, double, else, enum, extern, float, for, goto, if, int, long,
register, return, short, signed, sizeof, static, struct, switch, typedef, union, unsigned, void, voatile, while.
U poreenju sa ostalim programskim jezicima, C poseduje mali broj slubenih rei.

1.4. Konstante
Bilo koji niz znakova u programu, posmatran nezavisno od njegovog logikog znaenja, nad
kojim se mogu izvravati odreena dejstva (operacije) naziva se podatak. Deo podatka nad kojim se
mogu izvravati elementarne operacije naziva se element podatka. Elementu podatka u matematici
priblino odgovara pojam skalarne veliine. Podatak je ureeni niz znakova kojim se izraava
vrednost odreene veliine.
Veliina koja u toku izvravanja programa uvek ima samo jednu vrednost, koja se ne moe
menjati, naziva se konstanta. Kao oznaka konstante koristi se ona sama.
U nekim programskim jezicima (Pascal, Ada, C) postoji mogunost imenovanja konstante.
Konstantama se dodeljuju imena koja se u programu koriste umesto njih. Na taj nain nastaju
simbolike konstante.
Tipovi konstanti koje se mogu koristiti u odreenom programskom jeziku odreeni su tipovima
podataka koje taj jezik predvia.
U jeziku C se koristi vie vrsta konstanti i to su:
- celobrojne konstante; 2, 3, +5, -123
- karakteri: 'a', 'b', ... ;
- stringovi: sekvence karaktera izmeu navodnika.
Slede neki primeri razliitih vrsta konstanti:
Celobrojne dekadne konstante: 1; 50; 153; +55; -55
Realne konstante u fiksnom zarezu: 3.14; 3.0; -0.314; -.314; +.314
Realne konstante u pokretnom zarezu:
3.14E0; -0.314E1; -.314E+0; +.314E-2 (FORTRAN, Pascal, Ada, C)
Realne konstante dvostruke tanosti:

16
Ivan P. Stanimirovi Uvod u programiranje

Oktalne konstante (C): 0567; 0753; 0104


Heksadecimalne konstante (C): 0X1F; 0XAA; 0X11
Long konstante (C): 123L; 527L;321L;+147L
Logike konstante: true; false (Pascal, Ada)
.TRUE.; .FALSE. (FORTRAN)
Znakovne konstante: 'A'; 'B' (Pascal, Ada, C)
String konstante: "Beograd"; "Alfa 1" (C)
String konstante: Beograd; Alfa 1 (Pascal)
Simbolike konstante: ZERO; ZEROS; SPACE (COBOL)
Pi, E (MATHEMATICA)
Racionalni brojevi: 2/3; -4/5 (MATHEMATICA)

1.5. Promenljive
Veliine ije se vrednosti menjaju u toku izvravanja programa nazivaju se promenljive.
Promenljivoj se u programu dodeljuje ime, i u svakom trenutku ona je definisana svojom vrednou.
Kaemo da je svaka promenljiva u programu povezana sa tri pojma:
imenom - identifikatorom promenljive.
referencom - pokazivaem koji odreuje mesto promenljive u memoriji i
vrednou - podatkom nad kojim se izvravaju operacije.
Veza izmeu imena, reference i vrednosti promenljive moe se predstaviti sledeim dijagramom:

ime referenca vrednost


Ovaj dijagram u sluaju imenovane konstante dobija oblik:

ime vrednost
Na primer naredbu dodeljivanja X:=3.141592 itamo: X dobija vrednost 3.141592, pri emu
imamo u vidu da je X simboliko ime memorijske lokacije gde se u toku izvravanja programa pamti
vrednost 3.141592. Pri tome je potrebno imati na umu sledee pojmove:
vrednost 3.141592, koja predstavlja vrednost promenljive X,
adresu memorijske lokacije u kojoj se pamti vrednost 3.141592,
ime promenljive X, identifikator koji se u datom programu koristi kao ime promenljive koja
ima datu brojnu vrednost.

1.6. Komentari
U svim programskim jezicima postoji mogunost proirenja izvrnog koda programa komentarima
kojima se kod dodatno pojanjava. Ovi komentari se u toku prevoenja programa ignoru od strane
kompilatora i ne ulaze u sastav izvrnog koda koji se generie prevoenjem programa. Meutim
komentari su veoma vaan deo programa kojim se podeava njegova dokumentarnost, i bitno utiu na
efikasnost analize programa. Konvencija za zapisivanje komentara se razlikuje od jezika od jezika.
Slede primeri komentara u nekim programskim jezicima:
/* Ovo je primer komentara u jeziku C */
// Kratak C++ komentar u okviru jednog reda

17
Ivan P. Stanimirovi Uvod u programiranje

1.7. Struktura programa


Globalna struktura programa zavisi od toga da li jezik zahteva deklaraciju tipova promenljivih kao i
da li su u jeziku zastupljeni stariji koncepti sa implicitnim definicijama tipova promenljivih ili je
zastupljen noviji koncept sa eksplicitnim definicijama.

1.7.1. Struktura programa u C


Programi pisani u C jeziku imaju strukturu bloka, ali se za ograniavanje bloka koriste vitiaste
zagrade umesto zagrada begin i end. Zastupljen je takoe stariji koncept bloka, poznat iz jezika Algol
60 i PL/1, gde se opisi elemenata koji pripadaju jednom bloku nalaze unutar zagrada { i }, za razliku
od novijeg koncepta koji se koristi u jeziku Pascal, kod kojih opisi elemenata bloka prethode zagradi
begin kojom se otvara blok. Svaki blok u C-u takoe moe da sadri opise promenljivih i funkcija.
C program se moe nalaziti u jednom ili vie fajlova. Samo jedan od tih fajlova (glavni programski
modul) sadri funkciju main kojom zapoinje izvrenje programa. U programu se mogu koristiti
funkcije iz standardne biblioteke. U tom sluaju se moe navesti direktiva pretprocesora oblika
#include <ime>.
esta je direktiva oblika #include<stdio.h> kojom se ukljuuju funkcije iz fajla stdio.h (standard
input/output header).
Glavni program, main(), takoe predstavlja jednu od funkcija. Opis svake funkcije se sastoji iz
zaglavlja i tela funkcije. U ovom sluaju, zaglavlje funkcije je najjednostavnije, i sadri samo ime
funkcije i zagrade (). Iza zaglavlja se navodi telo funkcije koje se nalazi izmeu zagrada { i }. Izmeu
ovih zagrada se nalaze operatori koji obrazuju telo funkcije. Svaki prost operator se zavrava znakom
';' a sloeni operator se pie izmeu zagrada { i }.
U jeziku C sve promenljive moraju da se deklariu. Opti oblik jednostavnog programa je:
void main()
{
<deklaracije>
<naredbe>
}

2. TIPOVI PODATAKA

Jedan od najznaajnijih pojmova u okviru programskih jezika je pojam tipa podataka. Atribut tipa
odreuje skup vrednosti koje se mogu dodeljivati promenljivima, format predstavljanja ovih vrednosti
u memoriji raunara, skup osnovnih operacija koje se nad njima mogu izvravati i veze sa drugim
tipovima podataka. Na primer, promenljivoj koja pripada celobrojnom tipu mogu se kao vrednosti
dodeljivati samo celi brojevi iz odreenog skupa. Nad tako definisanim podacima mogu se izvravati
osnovne aritmetike operacije sabiranja, oduzimanja, mnozenja, deljenja, stepenovanja, kao i neke
specifine operacije kao to je odreivanje vrednosti jednog broja po modulu drugog.
Koncept tipova podataka prisutan je, na neki nain, ve kod simbolikih asemblerskih jezika gde se
za definiciju tipa koriste implicitne definicije preko skupa specijalnih znakova kojima se odreuju
podaci razliitog tipa.
Neka je zadat skup T sainjen od n proizvoljnih apstraktnih objekata: T:={v1,...,vn}, n>1. Ukoliko
su svi objekti istorodni, u smislu da se u okviru nekog programskog jezika na njih moe primenjivati
jedan odreeni skup operatora, onda se T naziva tip podataka, Ako za promenljive x i y uvek vai xT
i yT onda su one tipa T. To u okviru programa formalno definiemo iskazom

18
Ivan P. Stanimirovi Uvod u programiranje

DEFINE x, y : T.
Vrednost je bilo koji entitet kojim se moe manipulisati u programu. Vrednosti se mogu
evaluirati, zapamtiti u memoriji, uzimati kao argumenti, vraati kao rezultati funkcija, i tako dalje.
Razliiti programski jezici podravaju razliite tipove vrednosti.
Jedna od klasifikacija osnovnih tipova podataka prikazana je na slici.

Tipovi podataka su podeljeni u dve osnovne grupe: statiki tipovi i dinamiki tipovi. Pod
statikim tipovima (ili tipovima sa statikom strukturom podrazumevamo tipove podataka kod kojih je
unapred i fiksno definisana unutranja struktura svakog podataka, a veliina (t.j. memorijska
zapremina) fiksno se definie pre (ili u vreme) izvravanja programa koji koristi podatke statikog
tipa.
Statiki tipovi podataka obuhvataju skalarne i strukturirane podatke. Pod skalarnim tipovima
podrazumevamo najprostije tipove podataka ije su vrednosti skalari, odnosno takve veliine koje se
tretiraju kao elementarne celine i za koje nema potrebe da se dalje razlau na komponente. U tom
smislu realne i kompleksne brojeve tretiramo kao skalare u svim programskim jezicima koji ih
tretiraju kao elementarne celine (neki jezici nemaju tu mogunost pa se tada kompleksni brojevi
tretiraju kao struktura koja se razlae na realni i imaginarni deo; na slian nain mogao bi se realni
broj razloiti na normalizovanu mantisu i eksponent). Pod strukturiranim tipovima podataka
podrazumevamo sve sloene tipove podataka koji se realizuju povezivanjem nekih elementarnih
podataka u precizno definisanu strukturu. U ulozi elementarnih podataka obino se pojavljuju skalari
ili neke jednostavnije strukture. Kompozitna vrednost ili struktura podataka (data structure) jeste
vrednost koja je komponovana iz jednostavnijih vrednosti. Kompozitni tip jeste tip ije su vrednosti
kompozitne. Programski jezici podravaju mnotvo kompozitnih vrednosti: strukture, slogove, nizove,
algebarske tipove, objekte, unije, stringove, liste, stabla, sekvuencijalni fajlovi, direktni fajlovi,
relacije, itd.
Skalarni tipovi podataka mogu biti linearno ureeni ili linearno neureeni. Linearno ureeni
tipovi podataka su tipovi kod kojih se vrednosti osnovnog skupa T preslikavaju na jedan interval iz
niza celih brojeva, t.j. za svaki podatak xT zna se redni broj podatka. Stoga svaki podatak izuzev
poetnog ima svog prethodnika u nizu, i slino tome, svaki podatak izuzev krajnjeg ima svog
sledbenika u nizu.

19
Ivan P. Stanimirovi Uvod u programiranje

Pod dinamikim tipovima podataka podrazumevamo tipove podataka kod kojih se veliina i/ili
struktura podataka slobodno menja u toku obrade. Kod dinamikih tipova sa promenljivom veliinom
podrazumevamo da je struktura podataka fiksna, ali se njihova veliina dinamiki menja tokom obrade
tako da se saglasno tome dinamiki menjaju i memorijski zahtevi. Na primer, dopisivanjem novih
zapisa u sekvencijalnu datoteku veliina datoteke raste uz neizmenjenu strukturu. Kod dinamikih
tipova sa promenljivom strukturom unapred je fiksno definisan jedino princip po kome se formira
struktura podataka dok se sama konkretna struktura i koliina podataka u memoriji slobodno
dinamiki menjaju.
Statika i dinamika tipizacija
Pre izvrenja bilo koje operacije, moraju se proveriti tipovi operanada da bi se spreila greka u tipu
podataka. Na primer, pre izvrenja operacije mnoenja dva cela broja, oba operanda moraju biti
proverena da bi se osiguralo da oni budu celi brojevi. Slino, pre izvrenja neke and ili or operacije,
oba operanda moraju biti proverena da bi se osiguralo da oni budu tipa boolean. Pre izvrenja neke
operacije indeksiranja niza, tip operanda mora da bude array (a ne neka prosta vrednost ili slog).
Ovakva provera se naziva proverom tipa (type checks). Provera tipa mora da bude izvrena pre
izvrenja operacije.
Meutim, postoji izvestan stepen slobode u vremenu provere: provera tipa se moe izvriti ili u
vremenu kompilacije (compile-time) ili u vremenu izvrenja programa (at run-time). Ova mogunost
lei u osnovi vane klasifikacije programskih jezika na statiki tipizirane (statically typed) i
dinamiki tipizirane (dynamically typed). U nekom statiki tipiziranom jeziku, svaka varijabla i
svaki izraz imaju fiksni tip (koji je ili eksplicitno postavljen od strane programera ili izveden od strane
kompajlera). Svi operandi moraju biti proverenog tipa (type-checked) u vremenu kompilovanja
programa (at compile-time). U dinamiki tipiziranim jezicima, vrednosti imaju fiksne tipove, ali
varijable i izrazi nemaju fiksne tipove. Svaki put kada se neki operand izraunava, on moe da
proizvede vrednost razliitog tipa. Prema tome, operandi moraju imati proveren tip posle njihovog
izraunavanja, ali pre izvrenja neke operacije, u vremenu izvrenja programa (at run-time). Mnogi
jezici visokog nivoa su statiki tipizirani. SMALLTALK, LISP, PROLOG, PERL, i PYTHON jesu
primeri dinamiki tipiziranih jezika.
S druge strane, moderni funkcionalni jezici (kao ML, HASKELL, MATHEMATICA)
omoguavaju da sve vrednosti, ukljuujui i funkcije, imaju slinu obradu.
Izbor izmeu statike i dinamike tipizacije je pragmatian:
Statika tipizacija je efikasnija. Dinamika tipizacija zahteva (verovatno ponovljenu) proveru tipova
u vremenu izvrenja programa (run-time type checks), to usporava izvrenje programa. Statika
tipizacija zahteva jedino proveru tipa u vremenu kompilacije programa (compile-time type checks),
ija je cena minimalna (i izvrava se jedanput). Osim toga, dinamika tipizacija primorava sve
vrednosti da budu etiketirane (tagged) (da bi se omoguila provera u vreme izvrenja), a ovakvo
oznaavanje poveava upotrebu memorijskog prostora. Statika tipizacija ne zahteva ovakvo
oznaavanje.
Statika tipizacija je sigurnija: kompajler moe da proveri kada program sadri greke u tipovima.
Dinamika tipizacija ne omoguava ovakvu sigurnost.
Dinamika tipizacija obezbeuje veliku fleksibilnost, to je neophodno za neke aplikacije u kojima
tipovi podataka nisu unapred poznati.
U praksi vea sigurnost i efikasnost statike tipizacije imaju prevagu nad veom fleksibilnou
dinamike tipizacije u velikoj veini aplikacija. Veina programskih jezika je statiki tipizirana.
Na osnovu toga kako je postavljen koncept tipova podataka, programski jezici mogu da se svrstaju
u dve grupe: na programske jezike sa slabim tipovima podataka i na jezike sa jakim tipovima
podataka.

20
Ivan P. Stanimirovi Uvod u programiranje

2.1. Koncept jakih tipova podataka


Koncept jakih tipova podataka obuhvata nekoliko osnovnih principa:
Tip podataka odreuju sledei elementi:
- skup vrednosti,
- format registrovanja podataka,
- skup operacija koje se nad podacima mogu izvravati,
- skup funkcija za uspostavljanje veza sa drugim tipovima podataka.
Sve definicije tipa moraju da budu javne, eksplicitne. Nisu dozvoljene implicitne definicije
tipova.
Objektu se dodeljuje samo jedan tip.
Dozvoljeno je dodeljivanje vrednosti samo odgovarajueg tipa.
Dozvoljene su samo operacije obuhvaene tipom.
Tip je zatvoren u odnosu na skup operacija koji obuhvata. Ove operacije se mogu primenjivati
samo nad operandima istog tipa. Meoviti izrazi nisu dozvoljeni.
Dodeljivanje vrednosti raznorodnih tipova mogue je samo uz javnu upotrebu funkcija za
transformaciju tipa.
Koncept jakih tipova poveava pouzdanost, dokumentarnost i jasnou programa. Kako se zahteva
eksplicitna upotreba operacija za transformaciju tipa, onda je nedvosmisleno jasno da je odreena
transformacija na nekom mestu namerna i potrebna. Ovaj koncept omoguava da se informacija o tipu
moe koristiti u fazi kompilovanja programa i na taj nain postaje faktor pouzdanosti programa.

2.2. Koncept slabih tipova


U sluaju jezika sa slabim tipovima podataka informacija o tipu promenljive koristi se, i korektna je
samo na mainskom nivou, u fazi izvrenja programa. Ovako postavljen koncept podrazumeva sledee
mogunosti:
(1) Operacija koja se od strane kompilatora prihvati kao korektna, na nivou izvornog koda
programa, moe da bude potpuno nekorektna. Razmotrimo sledei primer:
char c;
c = 4;
Promenljiva c definisana je da pripada tipu char, to podrazumeva da joj se kao vrednosti dodeljuju
znaci kao podaci. Meutim umesto korektnog dodeljivanja c = '4', promenljivoj c je dodeljena
vrednost broja 4 kao konstante celobrojnog tipa. Kod jezika sa slabim tipovima podataka kompilator
ne otkriva ovu greku i informaciju o tipu koristi samo na mainskom nivou kada promenljivoj c
dodeljuje vrednost jednog bajta memorijske lokacije u kojoj je zapisana konstanta 4. Oigledno je da
ovako postavljen koncept tipova moe da dovede do veoma ozbiljnih greaka u izvravanju programa
koje se ne otkrivaju u fazi kompilovanja programa.
(2) Koncept slabih tipova podrazumeva odreeni automatizam u transformaciji tipova podataka u
sluaju kada se elementi razliitih tipova nalaze u jednom izrazu ija se vrednost dodeljuje
promenljivoj odreenog tipa. Razmotrimo sledei primer:
float x, y;
int i, j, k;
i = x;
k = x-j ;
Promenljive x i y su realne (tipa float), a i, j i k celobrojne (tipa int). Naredbom i=x; vri se
dodeljivanje vrednosti tipa float promenljivoj celobrojnog tipa. Kod jezika sa slabim tipovima ovo
dodeljivanje je dozvoljeno iako se pri tome x svodi na drugi format i pravi greka u predstavljanju
njegove vrednosti. Kod ovako postavljenog koncepta tipova, da bi se napisao korektan program

21
Ivan P. Stanimirovi Uvod u programiranje

potrebno je tano poznavati mehanizme transformacije tipova. U drugoj naredbi iz primera (k = x-j;)
od broja x koji je tipa float treba oduzeti broj j, tipa int i rezultat operacije dodeliti promenljivoj tipa
int. Da bi smo bili sigurni u korektnost rezultata potrebno je da znamo redosled transformacija koje se
pri tome izvravaju, odnosno da li se prvo x prevodi u int i onda izvrava oduzimanje u skupu celih
brojeva i vrednost rezultata dodeljuje promenljivoj tipa int ili se j prevodi u tip float, izvrava
oduzimanje u skupu realnih brojeva, a zatim rezultat prevoi u tip int i dodeljuje promenljivoj k.
Koncept slabih tipova podataka doputa puno slobode kod zapisivanja izraza u naredbama
dodeljivanja; meutim cena te slobode je nejasan program sa skrivenim transformacijama, bez
mogunosti kontrole i korienja informacije o tipu u fazi kompilovanja programa.

2.3. Ekvivalentnost tipova


ta ekvivalentnost tipova oznaava zavisi od programskog jezika. (Sledea diskusija podrazumeva
da je jezik statiki tipiziran.) Jedna mogua definicija ekvivalentnosti tipova jeste strukturna
ekvivalentnost (structural equivalence): T1 T2 ako i samo ako T1 i T2 imaju isti skup vrednosti.
Strukturna ekvivalentnost se tako naziva zato to se ona moe proveriti poreenjem struktura tipova
T1 i T2. (Nepotrebno je, a u optem sluaju i nemogue, da se prebroje sve vrednosti ovih tipova.)
Kada kompilator jezika sa jakim tipovima podataka treba da obradi naredbu dodeljivanja oblika
x := izraz
on vri dodeljivanje samo u sluaju ekvivalentnosti tipa promenljive sa leve strane dodeljivanja i
rezultata izraza na desnoj strani naredbe, osim u sluaju kada je na desnoj strani celobrojni izraz a na
levoj strani promenljiva nekog realnog tipa.
Eksplicitnom ekvivalentnou tipova postie se vea pouzdanost jezika. U ovom sluaju nisu
potrebne posebne procedure po kojima bi se ispitivala strukturna ekvivalentnost. Meutim, kada je
potrebno vrednost promenljive ili izraza dodeliti promenljivoj koja mu ne odgovara po tipu ovaj
koncept zahteva korienje funkcija za transformisanje tipova.

2.4. Elementarni tipovi podataka


U okviru svakog programskog jezika, sistem tipova podataka zasniva se na skupu osnovnih tipova
podataka nad kojima se dalje definiu izvedeni tipovi, podtipovi, strukturni tipovi i specifini
apstraktni tipovi podataka. Skup osnovnih tipova podataka se obino svodi na tipove podataka za rad
sa elementarnim numerikim podacima (celi i realni brojevi), znakovnim podacima (pojedinani znaci
ASCII koda) i logikim vrednostima (true i false).

2.4.1. Celobrojni tipovi (Integer ili int)

Celobrojni tip podataka (tip INTEGER)


Podaci celobrojnog tipa pripadaju jednom lntervalu celih brojeva koji obuhvata pozitivne i
negativne brojeve i koji se obino oznaava na sledei nain:
T := {minint, minint+1, ... , -1, 0, 1, ,.. , maxint-1, maxint } .
Ovde je najmanji broj oznaen sa minint, a najvei sa maxint (od engl. maximum integer i
minimum integer) pri emu ove veliine nisu fiksne ve zavise od implementacije i prema tome
variraju od raunara do raunara.
Od nekoliko naina binarnog kodiranja celih brojeva izdvojiemo metod potpunog komplementa
koji se najee sree u praksi. Kod ovog postupka brojevi se binarno predstavljaju pomou sledee n-
bitne rei:
n-1 3 2 1 0
S

22
Ivan P. Stanimirovi Uvod u programiranje

Bit najstarijeg razreda oznaen sa S (sign) predstavlja predznak broja. Ako je S=0 onda je je broj
nenegativan, a ako je S=1 onda je broj negativan. Nula se oznaava sa nulama u svim bitovima:
0000 0000 0000 0000
Obino postoji osnovni (standardni) tip INTEGER ili int, koji se zavisno od realizacije odnosi na
odreeni opseg celih brojeva. Nekad je to opseg koji odgovara formatu jedne polurei ili formatu
jedne rei. U odnosu na ovaj osnovni celobrojni tip eto postoji mogunost definisanja i drugih
celobrojnih tipova koji se odnose na neki krai ili proireni format.

2.4.2. Realni tip (float ili real)


Promenljive ovih tipova uzimaju za svoje vrednosti podskupove skupa realnih brojeva. U
programskim jezicima postoji vie vrsta podataka realnog tipa, koji se razlikuju po tanosti
predstavljanja podataka.
Realni tip podataka obuhvata jedan konaan podskup racionalnih brojeva ograniene veliine i
tanosti. Naravno, moe se odmah postaviti pitanje zbog ega se koriste nazivi "realni tip" i "realni
broj" za neto to u optem sluaju nije u stanju da obuhvati ni iracionalne brojeve ni beskonane
periodine racionalne brojeve. Ipak, to je terminologija koja je prihvaena u praksi i opravdava se time
to je (float ili REAL) tip podataka koji se najblie pribliava pojmu realnog broja. Sa druge strane,
lako je razumeti da su sve memorijske lokacije konane duine, pa stoga i brojni podaci koji se u njih
smetaju moraju biti konane duine i tako po prirodi stvari otpadaju iracionalni brojevi. Potrebe
prakse nisu na ovaj nain ni malo ugroene jer se dovoljna tanost rezultata moe postii i sa
veliinama konane duine. Tip float najee obuhvata brojne vrednosti iz sledeih podintervala
brojne ose:

-maxreal -minreal 0 minreal maxreal


Ovde minreal oznaava najmanju apsolutnu vrednost veu od nule, koja se moe predstaviti na
raunaru, a maxreal predstavlja najveu apsolutnu vrednost koja se moe predstaviti na raunaru.
Realni brojevi iz intervala (-minreal, minreal) se zaokruuju i prikazuju kao 0, realni brojevi iz
intervala (-, -maxreal) i (maxreal, +) ne mogu se predstaviti u memoriji raunara, a - i + se
kodiraju specijalnim kodovima.

2.4.3. Logiki tip podataka


Logiki tipovi podataka postoje kao osnovni tipovi podataka u svim novijim jezicima. Obino nose
naziv LOGICAL (FORTRAN) ili BOOLEAN (Pascal, Ada). Obuhvataju samo dve vrednosti true i
false, nad kojima su definisane osnovne logike operaclje not, and, or i xor.
Takoe, vai i ureenost skupa vrednosti ovog tipa tako da je false < true.
Izrazi u kojima se primenjuju logike promenljive i konstante nazivaju se logiki izrazi. Ako se
logike konstante oznaavaju sa false i true onda podrazumevamo da svi izrazi moraju biti sainjeni
striktno od logikih veliina. Ha primer, izraz z := (x>0) and ( (y=1) or (y<0) ) je korektan pri emu se
podrazumeva da su x i y celobrojne ili realne veliine, a z je veliina logikog tipa. Podrazumeva se i
da su neispravni meoviti izrazi u kojima se koriste veliine true i false pomeane sa numerikim
konstantama i aritmetikim operacijama. Na primer, nije definisan izraz 4*fa1se + 2*true + true, ali
izraz 4*(x>0) + 2*(y>0) + (z>0) , koji je takoe besmislen kod logikih konstanti false i true, u sluaju
numerikog kodiranja T={0,1} redovno ima i smisla i upotrebnu vrednost kao generator veliina
0,1,2,3,4,5,6,7.

2.4.4. Znakovni tipovi


Korisnik raunara komunicira sa raunarom preko ulaznih i izlaznih ureaja i tu je bitno da se
pojavljuju podaci u formi koja je itljiva za oveka. To znai da se komuniciranje obavlja pomou

23
Ivan P. Stanimirovi Uvod u programiranje

znakova iz odreene azbuke koja redovno obuhvata abecedno poreana velika i mala slova, cifre,
specijalne znake i kontrolne znake. Pod specijalnim znacima se podrazumevaju svi oni znaci koji se
javljaju na tastaturama i mogu odtampati, ali nisu ni slova ni cifre (na tastaturi sa kojom je pisan ovaj
tekst specijalni znaci su ! # S % & *()_-+=:"; '<>?,/.). Pod kontrolnim znacima podrazumevaju se
znaci koji se ne mogu odtampati (ili prikazati na ekranu terminala), ve slue za upravljanje radom
ulazno/izlaznog ureaja (na primer tampaa). U ovu grupu spadaju specijalni znaci za pomeranje
papira, znak koji izaziva zvuni signal na terminalu i drugi).
Da bi se znaci razlikovali od simbolikih naziva promenljivih obino se umeu izmeu apostrofa
(na nekim programskim jezicima umesto apostrofa se koriste znaci navoda). Tako se, na primer,
podrazumeva da A predstavlja simboliki naziv promenljive, dok 'A' predstavlja binarno kodirano prvo
slovo abecede.
U praksi se primenjuje nekoliko metoda za binarno kodiranje znakova. Najpoznatiji metod je
ameriki standard ASCII (American Standard Code for Information Interchange). Ovim smenama su
neki manje vani znaci iz skupa ASCII znakova zamenjeni sa specifinim jugoslovenskim znacima
(na pr., umesto ASCII znakova \ | { } [ ] ~ @ i ^ u srpskoj varijanti se pojavljuju znaci
i ). Neki terminali imaju mogunost podesivog izbora skupa znakova tako da korisnik moe po
potrebi izabratl ameriku ili jugoslovensku varijantu skupa ASCII znakova.
Prva 32 znaka u ASCII skupu su kontrolni znaci. Nekl od njlh imaju jedinstvenu interpretaciju kod
svih ureaja, a kod nekih interpretacija se razlikuje od ureaja do ureaja. Ovde pominjemo sledee:
BEL (Bell) = zvuni signal
LF (Line Feed) = prelazak u naredni red
FF (Form Feed) = prelazak na narednu stranu
CR (Carriage /Return) = povratak na poetak reda
ESC (Escape) = prelazak u komandni reim
Skup ASCII znakova je baziran na sedmobitnim znacima, pa prema tome obuhvata ukupno 128
znakova. Kako se radi o linearno ureenom skupu svaki znak ima svoj redni broj i ti brojevi su u
opsegu od 0 do 127. Funkcija koja za svaki znak daje njegov redni broj (ordinal number) oznaava se
sa ord. Argument ove funkcije je tipa CHARACTER, a vrednost funkcije je tipa CARDINAL. Za
sluaj ASCII skupa imamo da vai sledee:
ord('0') = 48, ord('A') = 65. ord('a')=97.
Inverzna funkcija funkciji ord, koja od rednog broja znaka formira znak, (character) je funkcija chr:
chr(48) = '0', chr(65) = 'A', chr(97) = 'a' .
Ako je c promenljiva tipa CHARACTER, a n promenljiva tipa CARDINAL onda vai
chr(ord(c) ) = c , ord(chr(n) ) = n .

2.5. Tipovi podataka u jeziku C


Programski jezik C se svrstava u jezike sa slabim tipovima podataka iako su eksplicitne definicije
tipa obavezne. Mogu se koristiti samo unapred definisani tipovi podataka uz mogunost da im se daju
pogodna korisnika imena i na taj nain povea dokumentarnost programa.
Mehanizam tipa je opti i odnosi se i na funkcije i na promenljive. Tipovi podataka u jeziku C
mogu se globalno podeliti na osnovne i sloene (struktuirane). Osnovni tipovi podataka su celobrojni
(int), realni (float), znakovni (char), nabrojivi (enumerated) i prazan (void). Ovi tipovi podataka se
koriste u graenju sloenih tipova (nizova, struktura, unija, itd.).
U sledeoj tabeli su prikazani osnovni tipovi podataka ovog jezika sa napomenom o njihovoj
uobiajenoj primeni.
Tip Memorija u
Opseg Namena
bajtovima
char 1 0 do 255 ASCII skup znakova i mali brojevi

24
Ivan P. Stanimirovi Uvod u programiranje

signed char 1 -128 do 127 ASCII skup znakova i veoma mali brojevi
enum 2 -32.768 do 32.767 Ureeni skup vrednosti
int 4 -2.147.483.648 do 2.147.483.647 Mali brojevi, kontrola petlji
unsigned int 4 0 do 4.294.967.295 Veliki brojevi i petlje
short int 2 -32.768 do 32.767 Mali brojevi, kontrola petlji
long 4 -2.147.483.648 do 2.147.483.647 Veliki brojevi
unsigned long 4 0 do 4.294.967.295 Astronomska rastojanja
-38 38
float 4 3,4*10 do 3,4*10 Naune aplikaije (tanost na 6 decimala)
-308 308
double 8 1,7*10 do 1,7*10 Naune aplikaije (tanost na 16 decimala)
-4932 4932
long double 10 3,4*10 do 3,4*10 Naune aplikaije (tanost na 19 decimala)

U C-u postoji skup operatora za rad sa binarnim sadrajima koji su prikazani u tabeli koja sledi.
Operator Znaenje
&& Logika I operacija (AND)
|| Logika ILI operacija (OR)
^ Iskljuivo ILI (XOR)
>> Pomeranje udesno
<< Pomeranje ulevo
~ Komplement

U sluaju meovitih izraza u kojima se pojavljuju razliiti operatori takoe vae implicitna
pravila kojima je definisan prioritet operacija. Nabrojaemo osnovna:
Unarni operatori (na pr. ++) su uvek vieg prioriteta u odnosu na sve binarne.
Aritmetike operacije su vieg prioriteta u odnosu na relacije poreenja.
Operatori poredenja <= i >= (manje ili jednako i vee ili jednako) su vieg prioriteta u odnosu
na jednako i nejednako.
Poreenja su uvek vieg prioriteta u odnosu na operatore kojima se manipulie bitovima.
Operatori za manipulisanje bitovima su vieg prioriteta u odnosu na sve logike operatore.
Logiko I (&&) je vieg prioriteta u odnosu na logiko ILI ( | | ).
Celobrojni tipovi u C
Celobrojni tipovi su brojaki tipovi i javljaju se kao oznaeni ili neoznaeni.
Celobrojne vrednosti obuhvataju celobrojne konstante, celobrojne promenljive, izraze i funkcije.
Celobrojne konstante predstavljaju podskup skupa celih brojeva iji opseg zavisi od deklaracije ali i
od konkretne implementacije. U C jeziku celobrojne konstante se predstavljaju kao niske cifara. Ispred
koje moe da stoji znak '+' za pozitivne, a obavezan je znak '-' za negativne vrednosti.
Promenljivoj osnovnog celobrojnog tipa int obino se dodeljuje memorijski prostor koji odgovara
"osnovnoj" jedinici memorije. Na taj nain, opseg vrednosti tipa int u TURBO C na 16-bitnim
raunarima je [-32768, +32767] = [-215,215-1], a na 32-bitnim raunarima je
[-2147483648, +2147483647] = [-231,231-1].
Bitno je napomenuti da se mogu koristiti 3 brojna sistema, i to: dekadni (baza 10), oktalni (baza 8);
heksadekadni (baza 16). Heksadecimalni brojevi poinju sa 0x ili 0X. Dozvoljene cifre su 0, 1,.., 9 i
slova a, b, c, d, e, f (ili A, B, C, D, E, F). Oktalni brojevi poinju sa 0 a ostale cifre mogu biti 0, 1, ..7.
Na primer, 012 je dekadno 10, 076 je dekadno 62. Takoe, 0x12 je dekadni broj 18, 0x2f je dekadno
47, 0XA3 je dekadno 163. Celobrojne konstante koje ne poinju sa 0 su oktalne.
Opseg celih brojeva se moe menjati primenom kvalifikatora long i short. Kvalifikator long moe
da povea opseg vrednosti celobrojnih promenljivih tipa int. Opseg vrednosti tipa long int (ili
skraeno long) je [-2147483648, +2147483647] = [-231,+231-1].

25
Ivan P. Stanimirovi Uvod u programiranje

Tip long int (ili long) garantuje da promenljive tog tipa nee zauzimati manje memorijskog
prostora od promenljivih tipa int.
Celobrojne konstante koje su prevelike da bi bile smetene u prostor predvien za konstante tipa int
tretiraju se kao long konstante. Ove konstante se dobijaju dodavanjem znaka L (ili l) na kraj konstante,
kao na primer 1265378L. Ako program ne koristi velike cele brojeve ne preporuuje se deklarisanje
promenljivih sa long, jer se time usporava izvrenje programa.
Kvalifikator short int (ili skraeno short) smanjuje opseg celobrojnih promenljivih. Opseg
promenljivih tipa short uvek je [-215,215-1], tj. one se uvek smetaju u 2 bajta. Upotrebom promenljivih
ovog tipa ponekad se postie uteda memorijskog prostora. Meutim, upotreba ovih promenljivih
moe da uspori izvravanje programa, jer se pre korienja u aritmetikim izrazima ove promenljive
transformiu u tip int.
Ako smo sigurni da su vrednosti celobronih promenljivih nenegativne, one se mogu deklarisati na
jedan od sledeih naina:
unsigned int (skraeno unsigned),
unsigned short int (skraeno unsigned short),
unsigned long int (skraeno unsigned long).

Time se interval pozitivnih vrednosti proiruje, jer bit za registrovanje znaka gubi to znaenje.
Promenljive tipa unsigned int (skraeno unsigned) mogu uzimati samo pozitivne celobrojne
vrednosti. Promenljive tipa unsigned imaju rang [0, 2irina_rei-1]. Prema tome, na 16-bitnim raunarima
opseg promenljivih tipa unsigned int je [0,65535]=[0,216-1], dok je na 32-bitnim raunarima
odgovarajui opseg jednak [0,232-1]=[0,+4294967295].
Konstante tipa long se mogu cpecificirati eksplicitno dodajui sufiks L ili l posle broja. Na primer,
777L je konstanta tipa long. Slino U ili u se moe koristiti za konstante tipa unsigned. Na primer, 3U
je tipa unsigned, a 3UL je tipa unsigned long.
U sluaju greke integer overflov, program nastavlja da radi, ali sa nekorektnim rezultatom.
Promenljive celobrojnog tipa se deklariu navoenjem imena promenljivih iza imena nekog
celobrojnog tipa. Imena promenljivih se meusobno razdvajaju zarezima, a iza spiska se navodi ';'. U
operatorima opisa je dozvoljeno izvriti inicijalizaciju deklarisanih promenljivih.
Primer. Navedeno je nekoliko deklaracija promenljivih celobrojnih tipova.
long int x;
short int y;
unsigned int z,v,w;

Kljuna re int se moe izostaviti u deklaracijama, pa se moe pisati


long x;
short y, k=10;
unsigned z;
Realni tipovi podataka u C
Promenljive ovih tipova uzimaju za svoje vrednosti podskupove skupa realnih brojeva. U jeziku C
postoje tri vrste podataka realnog tipa, koji se razlikuju po tanosti predstavljanja podataka: float (za
jednostruku tanost), double (za dvostruku tanost) i long double. U TURBO C vrednosti tipa float se
pamte u 4 bajta (32 bita), a double u 8 bajtova (64 bita). Efekat je da vrednosti tipa float zauzimaju 6
decimalnih mesta, a double 16 decimalnih mesta. Vrednosti tipa long double se smetaju u 80 bitova.
U TURBO C, pozitivne vrednosti za float su iz opsega [3.4*10-38, 3.4*1038], dok su pozitivne
vrednosti za double iz opsega [1.7*10-308,1.7*10+308]. Pozitivne vrednosti tipa long double uzimaju
vrednosti iz opsega [3.4*10-4932,1.1*10+4932].
Za vrlo velike i vrlo male brojeve moe se koristiti eksponencijalni zapis, koji se sastoji iz sledeih
delova:

26
Ivan P. Stanimirovi Uvod u programiranje

celobrojnog dela - niz cifara,


decimalne take,
razlomljenog dela - niz cifara,
znaka za eksponent e ili E,
eksponenta koji je zadat celobrojnom konstantom.
Primeri realnih brojeva su: 45., 1.2345, 1.3938e-11, 292e+3.
Promenljive realnog tipa deklariu se navoenjem liste imena promenljivih iza imena tipa.
Primer. Deklaracije promenljivih realnih tipova:
float x,y;
double z;
float p=2.71e-34;

Tip char
Tip char je jedan od fundamentalnih tipova podataka u jeziku C. Konstante i promenljive ovog tipa
se koriste za reprezentaciju karaktera. Znakovni tip (tip char) definie ureen skup osnovnih znakova
jezika C. Takav skup obrazuje skup ASCII znakova. To znai da znakovnom tipu pripadaju i znaci
koji nemaju grafiku interpretaciju.
Svaki karakter se smeta u raunaru u jednom bajtu memorije. Ako je bajt izgraen od 8 bitova, on
moe da pamti 28=256 razliitih vrednosti. Promenlijve i konstante tipa char uzimaju za svoje
vrednosti karaktere odnosno cele brojeve duine jednog bajta. To znai da se znak u memoriji
registruje u jednom bajtu. Promenljive ovog tipa se deklariu pomou kljune rei char.
Ako ispred deklaracije char stoji rezervisana re signed, tada se specificira interval kodnih
vrednosti [-128,127]; ako je ispred char navedeno unsigned, tada se specificira kodni interval [0,255].
Primer. Iskazom
char ca, cb, cc;
promenljive ca, cb, cc deklariu se kao promenljive tipa char. Karakter konstanta se pie izmeu
apostrofa, kao: 'a', 'b', 'c'... U Turbo C se koriste ASCII kodovi karaktera, i oni predstavljaju njihovu
numeriku vrednost.
Promenljive tipa char se mogu inicijalizovati na mestu deklarisanja. Na primer, moemo pisati
char c='A', s='A', x;
int i=1;

Funkcije printf() i scanf() koriste %c za format karaktera.

Primer.
printf("%c", 'a');
printf("%c %c %c", 'A', 'B', 'C'); /* ABC */

Takoe, konstante i promenljive tipa char se mogu tretirati kao mali integeri.

Primer.
printf("%d", 'a'); /* 97 */
printf("%c",97); /* a */

Neke znakovne konstante se moraju specificirati kao ''escape'' sekvence, tj. moraju se navesti zajedno
sa znakom \ (backslash). Escape sekvence se koriste pri kreiranju izlaznih izvetaja u cilju
specificiranja upravljakih znakova.
'\n' prelazak na novu liniju u ispisu;
'\t' horizontalni tab (pomera kursor za 5 ili 8 pozicija);
'\b' vraa kursor za jednu poziciju (povratnik, backspace);
'\f' form feed (pomera hartiju tampaa na poetak sledee strane);
'\a' alarm;

27
Ivan P. Stanimirovi Uvod u programiranje

'\'' apostrof;
'\\' backslash.

Primer.
printf("\"ABC\""); /* "ABC" */

U stringu je single quote obian karakter:


printf("'ABC'"); /* 'ABC' */

Karakter konstante se takoe mogu prikazati pomou jednocifrene, dvocifrene ili trocifrene
sekvence. Na primer '\007', ' \07' ili '\7' predstavlja bell (alarm).
Za ulaz i izlaz karaktera se mogu koristiti funkcije getchar() i putchar(). Ovi makroi su definisani
u fajlu stdio.h. Za uitavanje karaktera sa tastature koristi se getchar(), dok se putchar() koristi za
prikazivanje karaktera na ekran.
C obezbeuje standardni fajl ctype.h koji sadri skup makroa za testiranje karaktera i skup
prototipova funkcija za konverziju karaktera. Oni postaju dostupni pomou preprocesorske direktive
#include <ctype.h>

Makroi u sledeoj tabeli testiraju karaktere, i vraaju vrednosti true (0) i false (=0).

makro vrednost 0 se vraa za


isalpha(c) c je slovo
isupper(c) c je veliko slovo
islower(c) c je malo slovo
isdigit(c) c je broj
isxdigit(c) c je heksadecimalan broj
isspace(c) c je blanko
isalumn(c) c je slovo ili broj
ispunkt(c) c je interpunkcijski znak
isprint(c) c je terminalni karakter
iscntrl(c) c je kontrolni karakter

Takoe, u standardnoj biblioteci <ctype.h> ukljuene su i funkcije toupper(c) i tolower(c) za


odgovarajuu konverziju karaktera. Ove funkcije menjaju vrednost argumenta c koja je smetena u
memoriji.
toupper(c) menja c iz malog u veliko slovo;
tolower(c) menja veliko slovo u malo;
toascii(c) menja c u ASCII kod;

Konverzija tipova podataka i kast


Mnogi jezici visokog nivoa imaju strogu tipizaciju Takvi jezici nameu tokom prevoenja slaganje
tipova podataka koji su upotrebljeni u aritmetikim operacijama, operacijama dodeljivanja i pozivima
funkcija. U jeziku C se mogu pisati operacije u kojima se koriste razliiti tipovi podataka (meovite
operacije). Svaki aritmetiki izraz poseduje vrednost i tip. Tip rezultata aritmetikih izraza zavisi od
tipova operanda. Ako su kod binarnih aritmetikih operatora oba operanda istog tipa, tada je tip
rezultata jednak tipu operanada. Kada to nije ispunjeno, vri se automatska konverzija operanda nieg
hijerarhijskog nivoa u tip operanda vieg nivoa. Osnovni tipovi podataka imaju sledei hijerarhijski
nivo
char<int<long<float<double.
Korienjem rezervisanih rei unsigned i long poviava se hijerarhijski rang, tako da je detaljniji
pregled hijerarhijskih nivoa sledei:
char< int <unsigned <long < unsigned long <float < double < long double.
Na primer, ako su oba operanda tipa int, svaki aritmetiki izraz koji je izgraen od njih uzima
vrednost tipa int. Ako je jedna od promenljivih tipa short, ona se automatski konvertuje u

28
Ivan P. Stanimirovi Uvod u programiranje

odgovarajuu vrednost tipa int.


Automatska konverzija tipova se javlja i pri dodeljivanju vrednosti. Kod operatora dodeljivanja
vrednosti, uvek se vrednost izraza sa desne strane konvertuje u vrednost prema tipu promenljive sa
leve strane operatora dodeljivanja. Ako je promenljiva d tipa double, a izraz i tipa int, tada se pri
dodeljivanju d=i vrednost promenljive i konvertuje u odgovarajuu vrednost tipa double. Ako je i
promenljiva tipa int, a d je neki izraz tipa double, tada u izrazu i=d, prevodilac vrednost izraza d
konvertuje u odgovarajuu vrednost tipa int, pri emu se gube vrednosti decimalnih pozicija.
Osim ve pomenute automatske konverzije tipova podataka moe se izvriti i eksplicitna konverzija
tipova. Eksplicitna konverzija se postie operatorom kast (cast), oblika (tip)<izraz>. Postoje situacije
kada je konverzija tipova poeljna, iako se ne izvrava automatska konverzija. Takva situacija nastaje
na primer pri deljenju dva cela broja. U takvim sluajevima programer mora eksplicitno da naznai
potrebne konverzije. Takve konverzije su neophodne da bi se izraz tao izraunao.

Primer. Ako je promenljiva i tipa int, tada se izrazom (double)i njena vrednost prevodi u
odgovarajuu vrednost tipa double.
Operator kast je istog prioriteta i asocijativnosti kao i ostali unarni operatori. Kast se moe
primenjivati na izraze.
Primer.
(float)i+3 je ekvivalentno sa ((float)i)+3
(double)x=77 je ekvivalentno sa ((double)x)=77

Takoe, moemo pisati


x=(float)((int)y+1)
(double)(x=77)

Posle izraza x=(int)2.3+(int)4.2 vrednost za x postaje 6.


Vrste konverzije tipova
Konverzija tipa moe biti:
- standardna ugraena u jezik ili
- korisnika definie je programer za svoje tipove.
Standardne konverzije su, na primer:
- konverzije iz tipa int u tip float, ili iz tipa char u tip int i slino.
Konverzija tipa moe biti:
- implicitna prevodilac je automatski vri, ako je dozvoljena,
- eksplicitna zahteva programer.
Jedan nain zahtevanja eksplicitne konverzije:
- pomou C operatora kast (cast): (tip)izraz.
Jezik C++ uvodi 4 specifina kast operatora.
Postoji i drugi mehanizam konverzije (konverzioni konstruktor).
Konstante
Konstantni tip je izvedeni tip. Dobija se iz nekog osnovnog tipa pomou specifikatora const.
Konstantni tip zadrava sve osobine osnovnog tipa, samo se podatak ne moe menjati.
- Primeri: const float pi=3.14; const char plus='+';
Konstanta mora da se inicijalizuje pri definisanju.
Prevodilac esto ne odvaja memorijski prostor za konstantu.
Konstante mogu da se koriste u konstantnim izrazima koje prevodilac treba da izrauna u toku
prevoenja. Na primer, konstante mogu da se koriste u izrazima koji definiu dimenzije nizova.
Umesto simbolikih konstanti koje se uvode sa #define preporuka je koristiti tipizirane
konstante koje se uvode sa const.
Dosledno korienje konstanti u programu obezbeuje podrku prevodioca u spreavanju
greaka.

29
Ivan P. Stanimirovi Uvod u programiranje

Sizeof operator
Unarni operator sizeof() daje za rezultat broj bajtova potrebnih za smetanje svog argumenta.
Vrednost izraza sizeof(obj) se izraunava za vreme kompilovanja. Argument moe biti ime
promenljive, ime tipa ili izraz. Ako je obj ime promenljive, tada je vrednost izraza sizeof(obj) broj
bajtova potrebnih za registrovanje te promenljive u memoriji. Ako je operand obj ime tipa, tada je
vrednost izraza sizeof(obj) duina tog tipa, odnosno broj bajtova potrebnih za registrovanje
elemenata tog tipa. Ako je argument neki tip, ime tog tipa se mora navesti izmeu zagrada. Naredba
sizeof se koristi kada se generie kd koji zavisi od veliine tipa.
Osnovne aritmetike operacije
Osnovne aritmetke operacije su:
+ sabiranje,
- oduzimanje,
* mnoenje,
/ deljenje,
Ako su oba operanda operacije deljenja / celi brojevi tada se iz realnog broja koji predstavlja njihov
kolinik odbacuje decimalna taka i razlomljeni deo.
Na primer, 15/2=7, 2/4=0, -7/2=-3, 15%2=1, 7./4=1.74.
Operacija - moe biti i unarna, i tada se koristi za promenu znaka svog argumenta (unarni minus).
Sve operacije poseduju prioritet i asocijativnost (redosled), kojima se determinie postupak
evaluacije izraza. Ako u izrazu postoje operacije razliitog nivoa prioriteta, operacije se izvravaju po
opadajuem nivou prioriteta. Prioritet se moe promeniti upotrebom zagrada. Asocijativnost odluuje
o redosledu izvravanja operacija istog prioriteta.
Levoasocijativne operacije se izvravaju s leva na desno a desnoasocijativne s desna na levo.
Najvii priorirtet ima operacija promene znaka, zatim levoasocijativni multiplikativni operatori *, /
i %, dok su najnieg nivoa prioriteta levoasocijativni aditivni operatori + i -.
Operacija inkrementiranja (uveanja) ++ i operacija dekrementiranja (umanjenja) -- su unarne
operacije sa asocijativnou s desna na levo. U tabeli prioriteta operatori zauzimaju sledee mesto:
najvieg prioriteta su unarni operatori - (promena znaka); ++, --;
nieg prioriteta su multiplikativni *, /, %; dok su najmanjeg prioriteta aditivni operatori +, -.
Operacije ++ i -- se mogu pisati ispred argumenta (prefiksno) ili iza argumenta (postfiksno). Mogu
se primenjivati nad promenljivima a ne mogu na konstantama ili izrazima.

Primer. Moe se pisati ++i, i++, --cnt, cnt-- a ne moe 777++, ++(a*b-1).
Svaki od izraza ++i, i++, --i, i-- ima odreenu vrednost. Izrazi ++i, i++ uzrokuju inkrementiranje
vrednosti promenljive i u memoriji za 1, dok izrazi --i, i-- uzrokuju dekrementiranje njene vrednosti za
1. Izrazom ++i vrednost za i se inkrementira pre nego to se upotrebi, dok se sa i++ vrednost za i
inkrementira posle upotrebe te vrednosti. Slina pravila vae za izraze --i, i--, samo to se radi o
dekrementiranju te vrednosti.
Operatori ++ i -- razlikuju se od operatora +, -, *, /, % po tome to menjaju vrednosti varijable u
memoriji, tj. operatori ++ i -- poseduju boni efekat.
Primer. Kompajler koristi tipove operanada kako bi odredio rezultat izraunavanja.

30
Ivan P. Stanimirovi Uvod u programiranje

Biblioteke aritmetike funkcije


Deo C jezika jesu standardne biblioteke koje sadre esto koriene funkcije. Biblioteka math.h
sadri deklaraciju funkcija iz matematike biblioteke. Sadraj ove datoteke se ukljuuje u program
naredbom
#include<math.h>.
Neke od funkcija iz ove biblioteke su date u nastavku.
Poznate su funkcije sin(x), cos(x), tan(x), exp(x), log(x), log10(x), sqrt(x), fabs(x)=|x|. Sledi opis
najvanijih funkcija iz ove bibilioteke.
ceil(x), rezultat je najmanja celobrojna vrednost ne manja od x (plafon od x).
Rezultat funkcije floor(x) je najvea celobrojna vrednost ne vea od x (pod od x).
pow(x,y)=x^y. Ako je x=0 mora da bude y>0. Ako je x<0 tada y mora da bude ceo broj.
asin(x) vrednost funkcije arcsin(x), x[-1,1].
acos(x) vrednost funkcije arccos(x), x[-1,1].
atan(x) vrednost funkcije arctg(x), x[-/2, /2].
atan2(x,y) vrednost funkcije arctg(x/y), x[-,]. Ne moe istovremeno da bude x=y=0.
sinh(x) vrednost funkcije sh(x).
cosh(x) vrednost funkcije ch(x).
tanh(x) vrednost funkcije th(x).
modf(x,&y) vrednost funkcije je razlomljeni deo realnog broja x sa predznakom tog broja. U
argumentu y, kao boni efekat, daje se celobrojni deo broja x sa predzankom tog broja. Argumenti x i
y su tipa double.
fmod(x,y) vrednost funkcije je ostatak realnog deljenja x/y sa predznakom argumenta x. Standard ne
precizira rezultat u sluaju y=0. Argumenti x i y su tipa double. Na primer, fmod(4.7,2.3)=0.1.
U biblioteci <stdlib.h> nalaze se funkcije razliite namene. Navedene su neke od njih.
abs(n) apsolutna vrednost, gde su vrednost argumenta i funkcije tipa int,
labs(n) apsolutna vrednost, gde su vrednost argumenta i funkcije tipa long,
rand() vrednost funkcije je pseudosluajni broj iz intervala [0,RAND_max], gde RAND_max
simbolika konstanta ija vrednost zavisi od raunara i nije manja od 32767,
srand(n) postavlja poetnu vrednost sekvence pseudosluajnih brojeva koju generie rand().
Podrazumevana poetna vrednost je 1. Tip argumenta je unsigned int. Funkcija ne daje rezultat.
atof(s) ova funkcija vri konverziju realnog broja iz niza ASCII cifara (karaktera) oblika
cc....cc... Eee
u binarni ekvivalent. Argument s je string a rezultat je tipa double. Pre konverzije se
briu poetne praznine. Konverzija se zavrava kod prvog znaka koji ne moe da bude deo broja.
atoi(s) ova funkcija vri konverziju celog broja iz niza ASCII cifara (karaktera) oblika cc... u
binarni ekvivalent. Argument s je string a rezultat je tipa int. Poetne praznine se ignoriu. Konverzija
se zavrava kod prvog znaka koji ne moe da bude deo broja.

31
Ivan P. Stanimirovi Uvod u programiranje

atol(s) ova funkcija vri konverziju celog broja iz niza ASCII cifara (karaktera) oblika cc... u
binarni ekvivalent tipa long. Argument s je string a rezultat je tipa long. Poetne praznine se ignoriu.
Konverzija se zavrava kod prvog znaka koji ne moe da bude deo broja.

Operacija dodeljivanja u C
U C jeziku se operator = tretira kao operator dodeljivanja. Njegov prioritet je manji od prioriteta do
sada razmatranih operacija, a njegova asocijativnost je ``s desna na levo''. Izraz dodeljivanja vrednosti
je oblika
<promenljiva> = <izraz>;
na ijoj je desnoj strani proizvoljan izraz. Kompletan izraz je zavren sa ; (semicolon). Vrednost izraza
na desnoj strani se dodeljuje promenljivoj sa leve strane. Ako su tipovi promenljive i izraza razliiti,
vri se konverzija vrednosti izraza u odgovarajuu vrednost saglasno tipu promenljive. Vrednost izraza
dodeljivanja jednaka je vrednosti izraza sa njegove desne strane.
Primer. Sledea sekvenca izraza
y=2; z=3; x=y+z;
moe se efikasnije zapisati u obliku
x=(y=2)+(z=3);
Primer. Zbog desne asocijativnosti operatora = je izraz x=y=z=0 ekvivalentan izrazu
x=(y=(z=0)).
Primer. Operator y=x++; je ekvivalentan sledeoj sekvenci operatora: y=x; x=x+1;
Operator y=--x je ekvivalentan sledeim operatorima x=x-1; y=x;

Posle izvravanja operatora


x=y=1; z=(x+(++y))*3;
dobijaju se sledee vrednosti promenljivih:
x=1, y=2, z=(1+2)*3=9.
Operatori
x=y=1; z=(x+(y++))*3;
x=y=1; t=(x+y++)*3;
daju sledee vrednosti promenljivih:
x=1, y=2, z=(1+1)*3=6, t=(1+1)*3=6.
Primer.

Operatori sloenog dodeljivanja su:


=, +=, -=, *=, /=, %=, ||=, &=,^=, |=
Svi ovi operatori imaju isti prioritet i asocijativnost s desna na levo. Ako su l i r proizvoljni izrazi, tada
je izraz l<op>=r jednak l=l<op> r.

Na primer,
x+=2; je ekvivalentno sa x=x+2;
x%=2; je ekvivalentno sa x=x%2;
Primer. ta se ispisuje posle izvrenja sledeeg programa?
#include<stdio.h>

32
Ivan P. Stanimirovi Uvod u programiranje

void main()
{ int x,y,z;
x=y=1;
z=(x+y++)*(y==1);
printf("%d, %d, %d\n",x,y,z);
int i=1,j;
i=i++*++i;
printf("%d\n",i);
i=j=2;
printf("%d\n",++j+i++);
printf("%d, %d\n",i,j);
}
Primer. ta se ispisuje posle izvrenja sledeeg programa?
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
void main()
{ int i,j=6;
if(j=0) i=5;
else i=1;
printf("%d\n%d\n",i,j);
}

Operacije poreenja i logike operacije


U jeziku C postoje samo numeriki tipovi. Ne postoji ak ni logiki tip podataka. Za predstavljanje
logikih vrednosti koriste se celobrojni podaci tipa int. Vrednost 0 se tumai kao logika neistina
(false), a bilo koja vrednost razliita od nule tumai se kao logika istina (true).
Operacije poreenja
Operacije poreenja su:
<, <=, >, >=, ==, !=.
Rezultat izvrenja ovih operacija je 1 ako je ispunjeno poreenje, a inae je 0. Ove operacije se
izvravaju s leva na desno. Operacije poreenja su nieg prioriteta od aritmetikih operacija.
Unutar operacija poreenja, operacije <, <=, >, >= su vieg prioriteta od operacija == i !=.
Na primer, x>y+3 je ekvivalentno sa x>(y+3).

Logike operacije
Postoje tri logike operacije:
! je operacija negacije,
&& je konjunkcija, i
|| predstavlja opreaciju disjunkcije.
Rezultat primene ovih operacija je 0 ili 1.
Operacija negacije ! je unarna, i daje rezultat 1 ako je vrednost operanda 0, a vrednost 0 ako je
vrednost operanda 1.
Operacija konjunkcije && je binarna, i daje 1 ako su oba operanda razliita od 0, a 0 u suprotnom.
Ako je levi operand jednak 0 pri izvrenju operacije konjunkcije desni operand se ignorie.
Operacija disjunkcije || je binarna, i daje 1 ako je bar jedan operand razliit od 0, a 0 inae. Ako je
vrednost levog operanda jednaka 1 pri izvrenju operacije disjunkcije desni operand se ignorie.
Najvii prioritet ima operacija negacije; sledeeg nivoa prioriteta je operator konjunkcije, dok je
najnieg nivoa prioriteta operator disjunkcije.
Prema tome,

33
Ivan P. Stanimirovi Uvod u programiranje

p||q && r je isto sa p||(q && r),


x<=y && r je isto sa (x<=y)&& r.
Primer. Napisati operatore dodeljivanja kojima se realizuje sledee:
a) Promenljivoj p se dodeljuje vrednost 1 ako se od odseaka x, y, z moe konstruisati trougao, a inae
0.
p=((x+y>z) && (x+z>y) && (y+z>x));

b) Promenljivoj p se dodeljuje vrednost 1 ako se pravougaonik sa stranicama a i b moe ceo smestiti u


pravougaonik sa stranicama c i d, a inae 0.
p=((a<c)&& (b<d) || (a<d)&& (b<c));

2.6. Diskretni tipovi podataka u programskim jezicima


Grupa diskretnih tipova obuhvata sve tipove podataka sa konanim, diskretnim skupom vrednosti.
U takvom skupu vrednosti je definisana relacija poretka. Diskretnost i ureenost skupa vrednosti
omoguava definisanje intervala i upotrebu nekih optih zajednikih funkcija i atributa u ovoj grupi
tipova. U diskretne tipove podataka svrstavaju se svi celobrojni tipovi podataka, kao i svi drugi
elementarni tipovi sa diskretnim skupom vrednosti kao to su znakovni i logiki tipovi. Posebno
znaajni u grupi diskretnih tipova su tipovi nabrajanja (enumerated types) i intervalni tipovi nekih
jezika.

2.6.1. Nabrojivi tipovi u programskim jezicima


U programskom jeziku C se u okviru definicija tipova nabrajanja eksplicitno koristi re enum. Gore
datim tipovima podataka u ovom jeziku odgovaraju sledee definicije:
enum BOJE {crvena,bela,zelena,plava};
enum DANI {ponedeljak,utorak,sreda,cetvrtak,petak,subota,nedelja};
enum MESECI {jan,feb,mar,apr,maj,jun,jul,avg,sep,okt,nov,dec};
enum STATUS {ON,OFF};
enum PRAVCI {sever,jug,istok,zapad};

2.8. Upotreba typedef iskaza u C


Kljuna re typedef dozvoljava dodeljivanje alternativnih imena postojeim tipovima podataka, kao
i definisanje novih tipova podataka.
Primer. Iskazom
typedef int celi;
definie se ime celi kao ekvivalentno kljunoj rei int. Sada se moe pisati
celi i, j, n;
Izraz
typedef double vektor[20];
definie tip vektor kao niz od 20 elemenata tipa double.
Analogno, tip matrica kao dvodimenzionalni niz elemenata tipa double moe se definisati na sledei
nain:
typedef double matrica[10][10];
Nakon ovih definicija tipova se imena vektor i matrica mogu koristiti kao tipovi podataka.

34
Ivan P. Stanimirovi Uvod u programiranje

3. ULAZ I IZLAZ PODATAKA

U programskim jezicima postoji vei broj funkcija za unoenje i izdavanje podataka. Pomou
naredbi ulaza i izlaza program dobija neophodne podatke i prikazuje dobijene rezultate. Ove funkcije
se koriste za standardni ulaz i izlaz podataka preko tastature i monitora. Postoje varijante ovih
funkcija koje se mogu koristiti za pristup datotekama.

3.1. Ulaz i izlaz podataka u jeziku C

3.1.1. Funkcije printf() i scanf()


Funkcija printf() se koristi za formatizovani izlaz podataka, a scanf() za formatizovano uitavanje
podataka. Ove funkcije se nalaze u standarnoj biblioteci stdio.h. Datoteka stdio.h sadri podake
neophodne za pravilno funkcionisanje ulazno-izlaznih funkcija. Njen sadraj se ukljuuje u program
naredbom
#include<stdio.h>.
Funkcija printf() se poziva izrazom oblika
printf(Upravljacki_string [, Arg1,Arg2,...]);
Lista argumenata moe da se izostavi. Tada je jedini argument funkcije printf() upravljaki string koji
se ispisuje na ekran. U optem sluaju, funkcija printf() se primenjuje na listu argumenata koja se
sastoji iz dva dela. Prvi argument funkcije printf() je kontrolni ili konverzioni string (upravljaki
string), a drugi je lista izlaznih podataka ije se vrednosti ispisuju. Konverzioni string odreuje format
za tampanje liste izlaznih podataka. Najprostija specifikacija formata poinje karakterom '%', a
zavrava se konverzionim karakterom (formatom ili konverzionom specifikacijom).
U sledeoj tabeli su prikazani konverzioni karakteri

konverzioni karakter konverzija izlaznog niza


c karakter char
d ceo broj int
u ceo dekadni broj bez znaka
o oktalni broj int
x, X heksadekadni broj int
ld dug ceo broj long int
lo dug oktalni broj long int
lx dug heksadekadni broj long int
f fiksni zarez za float
lf double
e, E pokretni zarez za float i double
g, G krai zapis za f ili e
s string
p vrednost pointera
Konverzija g i G su jednake konverzijama e i E ukoliko je eksponent prikazanog broja manji od -4 ili
je vei ili jednak preciznosti obuhvaene specifikacijom d.
Opti oblik konverzione specifikacije je:
%[+|-|][sirina][.tacnost]konverzioni_karakter
gde:
- konverzioni_karakter definie konverziju.

35
Ivan P. Stanimirovi Uvod u programiranje

- Znak - ukazuje da se argument poravnava na levoj strani zadate irine polja.


- Znakom + se kod numerikih konverzija oznaava da ispred pozitivnih vrednosti treba da se napie
predznak +.
- Znak razmaka oznaava da je predznak praznina umesto +.
Bez ovih parametara konverzije, pozitivne vrednosti se prikazuju bez predznaka.
- Parametar sirina zadaje minimalnu irinu polja. Polje se proiruje za potreban broj pozicija ako
izlazna vrednost zahteva vie pozicija nego to je specificirano parametrom sirina. Ako specifikacija
irine polja poinje nulom, tada se polje umesto prazninama popunjava nulama u neiskorienim
pozicijama ako je poravnanje po desnoj margini.
- Parametar tacnost se koristi za realne brojeve (float ili double) i odreuje broj decimala iza
decimalne take.
Primer. (a) Posle izraza
printf("Danas je sreda \b\b\b\b\b petak \n ");
na ekranu se ispisuje tekst
Danas je petak.
(b) printf("Vrednost za x = %f\n", x);
(c) printf("n = %d x = %f %f^ %d=%lf\n", n,x,x,n,pow(x,n));
Funkcija scanf() ima za prvi argument kontrolni string koji sadri formate koji odgovaraju ulaznim
veliinama. Drugi argument jeste lista adresa ulaznih veliina.
scanf(Upravljacki_string,Adresa1[,Adresa2,...]);
Upravljaki string sadri konverzione specifikacije koje odgovaraju ulaznim veliinama. Lista adresa
sadri adrese promenljivih u koje se smetaju uitane i konvertovane vrednosti. Operator adrese se
predstavlja simbolom &. Adresa promenljive se formira tako to se ispred imena promenljive pie
operator adresiranja &.

Na primer, u izrazu scanf("%d", &x); format %d uzrokuje da se ulazni karakteri interpretiraju


kao ceo broj i da se uitana vrednost smeta u adresu promenljive x.
Neka su deklarisane celobrojne promenljive i, j, k. Tada se tri celobrojne vrednosti mogu dodeliti
ovim promenljivim preko tastature pomou operatora
scanf("%d%d%d", &i,&j,&k);
Za razdvajanje ulaznih polja u funkciji scanf() koriste se sledei znakovi: praznina (blank),
tabulator (tab) i prelaz u novi red (enter) (tzv. beli znaci). Izuzetak se ini u sluaju ako neki od
ulaznih znakova odgovara konverzionom karakteru %c, kojim se uitava sledei znak ak i kada je on
nevidljiv.
Pri ulaznoj konverziji opte pravilo je da podatak ini niz znakova izmeu dva bela znaka. Odavde
sledi da jednim pozivom funkcije scanf mogu da se uitavaju podaci iz vie redova. Vai i obrnuto,
vei broj poziva funkcije scanf moe da u itava uzastopne podatke iz istog reda.
Znaci koji se pojavljuju u upravljakom stringu a nisu konverzioni moraju se pri uitavanju pojaviti
na odreenom mestu i ne uitavaju se. Na primer, ako se unese ulazni red oblika
1:23:456
tada se operatorom
scanf("%d:%d:%d", &i,&j,&k);
celobrojnim promenljivim i, j i k dodeljuju vrednosti 1, 23 i 456, redom.
Opti oblik konverzione specifikacije je:
%[*][sirina]konverzioni_karakter
gde je:
- znak * oznaava da se obeleeno ulazno polje preskae i ne dodeljuje odgovarajuoj promenljivoj.

36
Ivan P. Stanimirovi Uvod u programiranje

- sirina zadaje maksimalnu irinu polja. Ako je irina polja vea od navedene u konverzionoj
specifikaciji, koristi se onoliko znakova koliko je zadato maksimalnom irinom.
- konverzioni_karakter je jedan od konverzionih znakova iz sledee tabele:
konverzioni karakter tip argumenta
c pokaziva na char
h pokaziva na short
d pokaziva na int
ld, D pokaziva na long
o pokaziva na int
lo, O pokaziva na long
x pokaziva na int
lx, X pokaziva na long
f pokaziva na float
lf, F pokaziva na double
e pokaziva na float
le, E pokaziva na double
s pokaziva na string

Primer. (i) Neka je i celobrojna i x realna promenljiva.


Ako je ulazna linija oblika
57 769 98.
tada se operatorom
scanf("%2d%*d%f",&i,&x);
promenljivim i i x dodeljuju redom vrednosti 57 i 98.0.
(ii) Ako su i, j, k celobrojne promenljive i ako se unese ulazna linija 123 456 789, posle primene
operatora
scanf("%2d%3d%2d",&i,&j,&k);
promenljive i, j, k uzimaju vrednosti 12, 3, 45.
Primer. Jednostavan C program koji demonstrira komentare i pokazuje nekoliko promenljivih i
njihove deklaracije.
#include <stdio.h>
void main()
{ int i, j; /* Ove 3 linije deklariu 4 promenljive */
char c;
float x;
i = 4; /* i, j imaju pridruene celobrojne vrednosti */
j = i + 7;
c = 'A'; /* Karakteri su okrueni apostrofima */
x = 9.087; /* x zahteva neku realnu vrednost */
x = x * 4.5; /* Promena vrednosti u x */
/* Prikaz vrednosti promenljivih na ekran */
printf("%d %d %c %f", i, j, c, x);
}
Primer. Dekadni, oktalmi i heksadekadni sistem.
#include <stdio.h>
int main(void)
{ int dec = 20, oct = 020, hex = 0x20;
printf("dec=%d, oct=%d, hex=%d\n", dec, oct, hex);
printf("dec=%d, oct=%o, hex=%x\n", dec, oct, hex);
return 0;
}
Primer. Realni brojevi u naredbi printf.

37
Ivan P. Stanimirovi Uvod u programiranje

#include <stdio.h>
#include <float.h>
int main(void)
{ double f = 3.1416, g = 1.2e-5, h = 5000000000.0;
printf("f=%lf\tg=%lf\th=%lf\n", f, g, h);
printf("f=%le\tg=%le\th=%le\n", f, g, h);
printf("f=%lg\tg=%lg\th=%lg\n", f, g, h);
printf("f=%7.2lf\tg=%.2le\th=%.4lg\n", f, g, h);
return 0;
}
f=3.141600 g=0.000012 h=5000000000.000000
f=3.141600e+00 g=1.200000e-05 h=5.000000e+09
f=3.1416 g=1.2e-05 h=5e+09
f= 3.14 g=1.20e-05 h=5e+09

3.1.2. Direktive pretprocesora u C


Simbolika konstanta je konstanta kojoj je pridruen identifikator. U programu se kasnije koristi
identifikator, a ne vrednost konstante. Simbolike konstante u jeziku C se definiu korienjem
direktiva pretprocesora. Ovakva definicija poinje pretprocesorskom direktivom #define (sve
pretprocesorske direktive poinju znakom #). Iza direktive pretprocesora se navodi simboliko ime
konstante a zatim konstantna vrednost koja predstavlja vrednost te konstante. Vrednost konstante se
moe zadati na sledei nain:
- pomou imena ve definisane konstante;
- konstantom (celobrojnom, realnom, znakovnom, logikom);
- konstantnim izrazom.
Iza ove direktive ne koristi se znak ';' jer pretprocesorske direktive ne pripadaju jeziku C.
Pretprocesorske direktive se moraju navesti pre prvog korienja imena konstante u programu. U
praksi se direktive najee piu na poetku programa.
Direktive #define mora da se pie u posebnom redu. Jednom naredbom moe da se definie samo
jedna konstanta. Zajedno sa nekom ovakvom direktivom ne smeju da budu druge naredbe. Jedino je
dozvoljen komentar na kraju reda.
Identifikatori simbolikih konstanti piu se velikim slovima da bi se razlikovali od identifikatora
promenljivih koji se obino piu malim slovima. Ovo pravilo nije nametnuto sintaksom jezika C ve
stilom koji se ustalio u praksi.
Primer. Definisanje simbolikih konstanti.
#define PI 3.141592
#define N 100
#define NMIN -N
#define PIX2 (PI*2)
#define LIMT 5
#define BELL '\007'
#define PORUKA "Zdravo"

Mogunost da se konstanta definie pomou pretprocesorskih direktiva omoguuje da se vrednost


konstante jednostavno zapie i promeni na jednom mestu. Korienje konstanti u programu
navoenjem njihovih imena umesto odgovarajue vrednosti poveava itljivost programa.
Takoe, moe da se uvede promenljiva kojoj se dodeljuje vrednost konstante.
Primer. Umesto izraza
#define POREZ 15
moe se pisati
float POREZ=15
Metod koji koristi promenljive je neefikasan, jer se pri svakom korienju vrednosti promenljive
vri obraanje memoriji za izraunavanje njene vrednosti, ime se usporava izvrenje programa. Ovde

38
Ivan P. Stanimirovi Uvod u programiranje

se radi o smeni u ''vreme izvravanja'', za razliku od pretprocesorske direktive kojom se vri smena ''u
toku kompilacije''.

Imenovane konstante se mogu kreirati koristei naredbu const.

Primeri u jeziku C
Primer. Zbir dva broja u jeziku C.
#include <stdio.h>
main()
{ int x, y;
printf("Unesi dva cela broja");
scanf("%d %d", &x, &y);
printf("Njihov zbir je %5d\n",x+y);
}

Primer. Proizvod dva broja tipa long.


#include <stdio.h>
main()
{ long x=2345678, y=67890;
printf("Njihov proizvod je %ld\n",x*y);
}

Primer. Zadavanje i prikazivanje karaktera.


#include <stdio.h>
main()
{ char c='A';
printf("%c%d\n",c,c);
}

Primer. Rad sa odreenim brojem decimala.


#include <stdio.h>
void main()
{float x=23.45678888, y=7.8976789;
printf("Njihov proizvod je:%f,%0.16f,%0.20f\n", x*y,x*y,x*y);
}

Primeri. Napredno korienje #define.


Primer .
#include <stdio.h>
#define veci(X,Y) X>Y
#define kvad(X) X*X
#define kvadrat(X) ((X)*(X))
void main()
{printf("To su %d %d %d %d\n", veci(3,2),kvad(5),kvad(5+5),kvadrat(5+5));}

39
Ivan P. Stanimirovi Uvod u programiranje

Primer.
#include <stdio.h>
#define MAX 23
#define Ako if
#define Onda
#define Inace else
void main()
{ int n=24;
Ako (MAX > n) Onda printf("veci\n");
Inace printf("manji\n");
}

4. OSNOVNE UPRAVLJAKE STRUKTURE

Svaki program sadri naredbe dodeljivanja kojima se izraunavaju vrednosti odreenih izraza i
pamte (dodeljuju) kao vrednosti odgovarajuih promenljivih. Ipak, veoma retko se bilo koji program
sastoji samo od jedne sekvence naredbi dodeljivanja kao i naredbi ulaza/izlaza. Mnogo se ee
zahteva postojanje vie razliitih tokova u zavisnosti od odreenih uslova ili mogunost viestrukog
izvravanja dela programa. Naredbe koje omoguavaju definisanje toka programa nazivaju se
upravlajke naredbe.
Upravlajke naredbe u prvom imperativnom programskom jeziku FORTRAN bile su izvedene iz
osnovnih mainskih naredbi. To je period kada metodologija programiranja tek poinje da se razvija
tako da jo nije definisan neki osnovni skup upravljakih naredbi. Poetkom sedamdesetih Wirt
definie metodologiju strukturnog programiranja i programski jezik Pascal sa skupom upravljakih
struktura kojima se implementiraju osnovne algoritamske strukture. Ovaj koncept je iroko prihvaen,
tako da danas vii programski jezici iz grupe proceduralnih jezika obino raspolau skupom
upravljakih struktura kojima se upravlja tokom izvrenja programa u skladu sa konceptima
strukturnog programiranja. Iako se od jezika do jezika ovaj skup upravljakih struktura donekle
razlikuje, moe se rei da su ipak meu njima u ovom domenu male sutinske razlike. Smatra se da je
skup naredbi kojima se upravlja tokom programa dovoljan ako obezbeuje sledee tri osnovne
upravlajke strukture:
(1) Strukturu selekcije, koja omoguava izbor jedne od dve mogunosti. U Pascal-u se obino
implementira izrazom oblika:
If B then St else Sf ;
Struktura selekcije odreena je if-then i if-then-else izrazima.
(2) Strukturu viestruke selekcije, koja omoguava izbor jedne izmeu vie ponuenih grana. U
Pascal-u se koristi case izraz oblika:
case X of
xa : Sa;
xb : Sb;
end;
(3) Strukturu iteracije, koja omoguava viestruko izvravanje nekog bloka naredbi. U jeziku
Pascal se koristi while do petlja oblika:
while B do S;
Upravljake strukture jednog proceduralnog jezika bi trebalo da ispunjavaju sledee osobine:
smisao naredbi mora da bude jasan i jednoznaan;

40
Ivan P. Stanimirovi Uvod u programiranje

sintaksa naredbe treba da bude tako postavljena da dozvoljava hijerarhijsko ugraivanje drugih
naredbi, to mora da bude jednoznano definisano i jasno iz samog teksta programa;
potrebno je da postoji mogunost lake modifikacije naredbi.

4.1. naini predstavljanja algoritama


Tekstualni
Grafiki (pomou blok ema)
Pseudo kodom
Strukturogramom
Tekstualni nain
Koriste se precizne reenice govornog jezika
Koristi se za lica koja se prvi put sreu sa pojmom algoritma
Dobra osobina: razumljivost za iri krug ljudi
Loe: nepreciznost koja proistie iz nepreciznosti samog jezika
Primer 1. Zameniti sadraje dve memorijske lokacije, A i B
Reenje potrebna je trea, pomona, lokacija
1. sadraj lokacije A zapamtiti u pomonu lokaciju, P
2. sadraj lokacije B zapamtiti u lokaciju A
3. sadraj lokacije P zapamtiti u lokaciju B
4. kraj
2

A B

1 3

Primer 2
Cikliki pomeriti u levo sadraje lokacija A, B i C

P A B C

iz A u P
iz B u A
iz C u B
iz P u C
kraj

Primer 3. Cikliki pomeriti u levo sadraje lokacija a1, a2, ..., an.
1 2 3 n

41
Ivan P. Stanimirovi Uvod u programiranje

P a1 a2 a3 an-1 an

n+1

iz a1 u P
iz ai u ai-1, za i=2,...,n kako izvriti pomeranje
iz P u an za k mesta?
kraj

Euklidov algoritam za nalaenje NZD dva prirodna broja, m i n


1. Podeliti m sa n i ostatak zapamtiti u r;
2. Ako je r jednako 0, NZD je n i kraj, inae prei na korak 3;
3. Zameniti m sa n, n sa r, i prei na korak 1;

Grafiko predstavljanje algoritma


Koriste se odredjeni grafiki simboli za predstavljanje pojedinih aktivnosti u algoritmu
Ideja je pozajmljena iz teorije grafova
Algoritam se predstavlja usmerenim grafom
vorovi grafa predstavljaju aktivnosti koje se obavljaju u algoritmu
potezi ukazuju na sledeu aktivnost koja treba da se obavi
Polazni vor u usmerenom grafu koji predstavlja algoritam nema dolaznih potega, a ima samo
jedan izlazni poteg (granu) poetak

Krajnji vor u grafu koji predstavlja algoritam nema izlaznih potega, a ima samo jedan dolazni
poteg

kraj

Blok oblika romboida koristi se za oznaavanje ulaznih i izlaznih aktivnosti

ulaz: izlaz:

Blok obrade je pravougaonog oblika


obrada

Blok odluke

da ne
uslov

42
Ivan P. Stanimirovi Uvod u programiranje

Blok spajanja potega

Osnovne algoritamske strukture


Kombinovanjem gradivnih blokova dobijaju se osnovne algoritamske strukture
sekvenca
alternacija (selekcija)
petlja (ciklus)
Pomou osnovnih algoritamskih struktura moe se predstaviti svaki algoritam
Sekvenca
linijska struktura koja se dobija kaskadnim povezivanjem blokova obrade

A1 Algoritamski koraci se izvravaju redom, jedan za drugim


Algoritamski korak A , i=2,...,n ne moe da otpone sa izvrenjem
i
dok se korak Ai-1 ne zavri

sekvenca predstavlja niz naredbi dodeljivanja (:=)


A2

A3
oblik naredbe:
promenljiva:=vrednost
a:=b
n:=n+1

An

Alternacija (selekcija)
Omoguava uslovno izvrenje niza algoritamskih koraka

da
da ne uslov
uslov

S2 S2 S S1
S S1 1
1

Blokovi oznaeni sa S1 i S2 mogu sadrati bilo koju kombinaciju osnovnih algoritamskih


struktura.

43
Ivan P. Stanimirovi Uvod u programiranje

Primer 1. Nacrtati dijagram toka algoritama kojim se odredjuje vei od dva zadata broja korienjem
formule
a, a b
max{ a, b}
b, a b

Nai maksimum od tri zadata broja a, b i c


max{ a, b, c} max{max{ a, b}, c}

Petlja (ciklus)
Omogava da se algoritamski koraci ponavljaju vie puta.

Pravila
Ako petlja pone unutar then bloka ili else bloka, u tom bloku se mora i zavriti!
Dozvoljene su paralelne (ugnjedjene) petlje.
su dozvoljene petlje koje se seku!

Paralelne petlje

44
Ivan P. Stanimirovi Uvod u programiranje

Primer - Euklidov algoritam


poc poc

m, m,n
n

r:=ostatak od m/n
r:=ostatak od m/n
m:=n
ne
do-while n:=r
r 0
repeat-until
da

m:=n naredba koja ne


n:=r menja uslov! r=0
r:=ostatak od m/n
da

nzd:=m

nzd:=n
nzd

nzd
kraj

kraj

Predstavljanje algoritma pomou pseudo koda


Koristi se tekstualni nain dopunjen formalizmom
svaka od osnovnih algorotamskih struktura se predstavlja na tano definisani nain:
sekvenca se predstavlja kao niz naredbi dodeljivanja odvojenih simbolom ;
a:=5;
b:=a*b;
c:=b-a;
Alternacija
if (uslov) then ili if (uslov) then
niz_naredbi niz_naredbi
else endif;
niz_naredbi
endif;

if (a>b) then ili max:=a;


max:=a if (max<a) then
else max:=b
max:=b endif;
endif;
Alternacija, primer2

45
Ivan P. Stanimirovi Uvod u programiranje

max(a,b,c)
if (a>b) then
if (a>c) then
max:=a
else
max:=c
endif;
else
if (b>c) then
max:=b
else
max:=c
endif;
endif;
Petlje pseudo kod
while (uslov) do repeat
niz_ naredbi niz_naredbi
enddo; until (uslov);
Primer: Primer:
r:=ostatak od m/n
while (r0) do repeat
m:=n; r:=ostatak od m/n;
n:=r; m=n;
r:=ostatak od m/n; n:=r;
enddo; until (r=0);
nzd:=n; nzd:=m;

Strukturogrami
Kombinacija grafikog i pseudo koda;
Koriste se kao prikladna dokumentacija za ve zavrene programe.
Program se pie tako da se popunjavaju odreene geometrijske slike
if uslov
while uslov for i:=n1,n2,n3
else
sekvenca then telo
petlje
telo telo
S1 S2 petlje petlje
until uslov

Strukturogrami primer
if a>b if a>b
then else else
then

max:=a; max:=b; if a>c if b>c


then else then else

max:=c; max:=b; max:=c;


max:=a;
46
Ivan P. Stanimirovi Uvod u programiranje

4.2. Sekvenca naredbi i blok


Sekvenca naredbi je jedan od osnovnih koncepata u strukturnim jezicima, uveden radi lake
implementacije drugih upravljakih struktura. Prvi put se javlja u jeziku Algol 60, u kome se naziva i
sloena naredba, a definisan je kao niz naredbi ogranien zagradama begin i end:
begin
naredba_1;
.
naredba_n
end
Sekvenca naredbi se u Algol-u 60 moe pojaviti svuda gde je sintaksom dozvoljena naredba. Time
ovaj koncept postaje jako sredstvo apstrakcije naredbe.
U Algol-u 60 se prvi put javlja i koncept bloka kao uoptenje koncepta sekvence naredbi. Blok je
po definiciji upravljaka struktura koja sadri opise lokalnih promenljivih i sekvencu naredbi. Kao i
sekvenca, zatvara se zagradama begin i end.
begin
deklaracija_1;
.
deklaracija_m;
naredba_1;
.
naredba_n
end

4.2.1. Globalne i lokalne promenljive


Globalna promenljiva (global variable) je takva promenljiva koja je deklarisana za upotrebu kroz
ceo program. Trajanje globalne varijable je celokupno vreme izvrenja programa: varijabla se kreira
kada program startuje, a unitava odmah po zavretku programa.
Lokalna promenljiva (local variable) je takva promenljiva koja je deklarisana unutar nekog bloka,
za upotrebu samo unutar tog bloka. Trajanje lokalne varijable je aktivacija bloka koji sadri
deklaraciju te varijable: varijabla se kreira na ulasku u blok, i unitava se na izlasku iz bloka.
Blok (block) je programska konstrukcija koja ukljuuje lokalne deklaracije. U svim programskim
jezicima, telo neke procedure jeste blok. Neki jezici takoe imaju blok komande, kao na primer { . . .
} u C, C++, ili JAVA, ili declare . . . begin . . . end; u ADA. Aktivacija (activation) nekog bloka
je vremenski interval u kome se taj blok izvrava. Partikularno, aktivacija procedure je vreme interval
izmeu poziva i vraanja vrednosti. U toku jednog izvrenja programa blok moe biti aktiviran
nekoliko puta, tako da lokalna promenljiva moe imati nekoliko trajanja.
Promenljive opisane u jednom bloku su lokalne promenljive tog bloka, a globalne za sve blokove
sadrane u njemu. Ukoliko se u nekom bloku predefiniu promenljive ve definisane u spoljanjem
bloku, u unutranjem bloku vae te nove definicije kao lokalne definicije bloka. Van bloka prestaje
dejstvo lokalnih definicija unutranjeg bloka. Razmotrimo sledei primer, koji je konstruisan sa
idejom da ilustruje dejstvo lokalnih i globalnih definicija.
Primer. Globalne i lokalne promenljive.
A: begin real a; ... Pa;
B: begin real b; ... Pb end;
C: begin real c; .. PC;
D: begin real d; . .. Pd end;
E: begin real e; ... Pe end;
end;
F: begin real f; .. Pf;
G; begin real g; ... Pg end;
end;

47
Ivan P. Stanimirovi Uvod u programiranje

end;
U ovom primeru postoji sedam blokova (oznaeni oznakama A:, B:, C:, D:, E:, F: i G:) i u svakom
od ovih blokova opisana je po jedna promenljiva. Sledea tabela daje podatke o svim blokovima u
programu. Slovo L oznaava da je promenljiva lokalna, a G da je globalna.

Blok
Promenljiva A B C D E F G
a L G G G G G G
b L
c L G G
d L
e L
f L G
g L

U sledeem primeru dat je ilustrovan pojam bloka kao i pojam lokalnih i globalnih promenljivih.
Primer. Doseg i sakrivanje u C++.
int x=0; // globalno x
void f () {
int y=x, // lokalno y, globalno x;
x=y; // lokalno x, sakriva globalno x
x=1; // pristup lokalnom x
::x=5; // pristup globalnom x
{ int x; // lokalno x, sakriva prethodno x
x=2; // pristup drugom lokalnom x
}
x=3; // pristup prvom lokalnom x
}
int *p=&x; // uzimanje adrese globalnog x

#include<stdio.h>
int x=0; // globalno x
void main ()
{ int y=x, // lokalno y, globalno x;
x=y; // lokalno x, sakriva globalno x
printf("x = %d\n",x);
x=1; // pristup lokalnom x
printf("x = %d\n",x);
::x=5; // pristup globalnom x
printf("x = %d\n",x);
{ int x; // lokalno x, sakriva prethodno x
x=2; // pristup drugom lokalnom x
printf("x = %d\n",x);
}
// x=3; // pristup prvom lokalnom x
printf("x = %d\n",x);
int *p=&x;
printf("x = %d\n",*p);
}
Primer. Blok u jeziku C.
#include<stdio.h>
void main()
{ float a,b,c,d;
a=1.0; b=2.0; c=3.0; d=4.0;
printf("Spoljasnji blok a=%f b=%f c=%f d=%f\n",a,b,c,d);
{ float c,d,e,f;
c=a+10; d=b+20; e=c+30; f=d+40;

48
Ivan P. Stanimirovi Uvod u programiranje

printf("Unutrasnji blok a=%f b=%f c=%f d=%f e=%f f=%f\n",


a,b,c,d,e,f);
}
printf("Spoljasnji blok a=%f b=%f c=%f d=%f\n", a,b,c,d);
}
U ovom primeru postoje dva bloka: prvi u kome se definiu promenljive a, b, c i d i drugi u kome
su promenljive c i d predefinisane i promenljive e i f prvi put definisane. Kako je drugi blok unutar
prvog dejstvo ovih definicija je sledee:
a, b, c i d su lokalne promenljive prvog bloka.
c, d, e i f su lokalne promenljive drugog bloka.
a i b vae i u drugom bloku, ali kao globalne promenljive.
c i d su opisane i u prvom i u drugom bloku pa se u svakom od ovih blokova mogu koristiti
nezavisno od njihove namene u drugom bloku.
e i f se mogu koristiti samo u drugom bloku, dok su u prvom nedefinisane.
Kao posledicu ovako postavljenih definicija promenljivih naredbom za tampanje u umetnutom
bloku tampaju se brojevi 1.0, 2.0, 11.0, 22.0, 41.0 i 62.0, dok naredba za tampanje u spoljanjem
bloku daje: 1.0, 2.0, 3.0 i 4.0.
Kako dejstvo lokalnih promenljivih prestaje po izlasku iz bloka, kod ponovnog ulaska u isti blok
one su nedefinisane i potrebno je da im se ponovo dodele neke inicijalne vrednosti.
Sekvenca naredbi je u istom ovom obliku zastupljena i u Pascal-u, dok je struktura bloka
izostavljena. U C postoje oba koncepta ali su begin i end zamenjeni zagradama { i }. To ilistruje
sledei primer.
Kod novijih jezika kod kojih je zastupljen koncept kljunih rei kojima se otvaraju i zatvaraju
delovi upravlajke strukture, sekvenca naredbi ne postoji kao odvojena struktura ve je sastavni deo
drugih upravljakih struktura.

4.3. Struktura selekcije


Struktura selekcije omoguava definisanje vie moguih tokova programa i jedno je od osnovnih
sredstava za pisanje fleksibilnih programa. Strukture selekcije dele se u dve osnovne grupe. Jednoj
pripadaju takozvane if-selekcije, a drugoj viestruka selekcija.
If-selekcije se obino javljaju kao if-then i if-then-else struktura, pri emu prva omoguava izbor
posebnog toka u zavisnosti od odreenog uslova, a druga izbor jedne ili druge alternative u zavisnosti
od toga da li je odreeni uslov ispunjen.

4.3.1. If-then struktura


Na sledeoj slici prikazan je dijagram toka koji ilustruje grafiki prikaz ove strukture na nivou
algoritma.
true
uslov
false niz naredbi

If-then struktura se obino implementira kao poseban, jednostavniji sluaj if-then-else strukture.
Jedino kod nekih starijih jezika (BASIC, FOTRAN) ona postoji kao zasebna upravljaka struktura.
U FORTRAN-u se if-then struktura naziva logikom IF naredbom i ima sledeu formu:
IF (Iogiki izraz) naredba

49
Ivan P. Stanimirovi Uvod u programiranje

Naredba koja sledi iza logikog izraza izvrava se samo ako je vrednost logikog izraza jednaka
TRUE, inae se tok programa prenosi na sledeu naredbu.
Jedan od problema u primeni if naredbe jeste implementacija sluaja kada se izvrava vei broj
naredbi u jednoj ili then ili else grani. U programskim jezicima koji ne podravaju koncept sekvence
naredbi, ova struktura se implementira koristei GOTO naredbu.
Uobiajeni nain korienja ove naredbe u FORTRAN-u IV ilustruje sledei primer.
Primer. Logika IF naredba u FORTRAN-u. U naredbi je sa Uslov oznaena logika promenljiva.
IF (.NOT. Uslov) GO TO 20
I=1
J=2
K=3
20 CONTINUE
U ovom primeru, ako je vrednost promenljive Uslov jednaka FALSE program se nastavlja od
naredbe sa oznakom 20. Za vrednost TRUE iste promenljive program se nastavlja naredbom I=1 koja
sledi neposredno iza naredbe IF. Upotreba GO TO naredbe je bila neophodna s obzirom na
nepostojanje sekvence naredbi u FORTRANu IV.
Uvoenjem koncepta sekvence naredbi, if-then naredba u Algol-u dobija drugaiju sintaksu,
onakvu kakvu poznajemo u savremenim proceduralnim jezicima. U optem sluaju njena struktura je
definisana na sledei nain:
if (logiki izraz) then
begin
naredba_1;
...
naredba_n
end;
Sekvenca naredbi, obuhvaena zagradama zagradama ili izmeu begin i end, sastavni je deo if
naredbe. Ta sekvenca naredbi se izvrava za vrednost true logikog izraza. Za vrednost false sekvenca
naredbi se preskae i program nastavlja sa prvom naredbom koja sledi iza zagrade end.
Primer. If-then naredba u Algol-u 60.
if (uslov) then
begin
i:=1;
j:=2;
k:=3
end;
If-then struktura se javlja u razliitim oblicima u mnogim jezicima iji su koreni u Algol-u 60,
ukljuujui i FORTRAN 77 i FORTRAN 90.
U FORTRAN-u se moe koristiti IF-THEN struktura, prema sledeoj sintaksi:
IF(uslov)
naredba
END IF
Uoimo da se u ovom jeziku koriste kljune rei kojima se otvaraju i zatvaraju pojedini delovi
strukture.
U jeziku Pascal je if-then struktura preuzeta iz Algol-a. U jeziku C se umesto rei begin i end
koriste zagrade { i }, redom.

4.3.2. If-then-else struktura


Dijagram toka if-then-else strukture koji ilustruje smisao ove strukture na nivou algoritma prikazan je
na slici.

50
Ivan P. Stanimirovi Uvod u programiranje

false true
uslov

else-grana then-grana

Ova upravljaka struktura se prvi put javlja u Algol-u 60 i to u obliku:


if (logiki_izraz)
then naredba
else naredba;
Naredba koja sledi iza kljune rei then predstavlja then granu programa, a naredba iza else
predstavlja njenu else granu. Kada je vrednost logikog izraza true izvrava se then grana, a kada je
vrednost false - else grana programa.
Ova upravljaka struktura postoji u svim proceduralnim jezicima sa odreenim varijacijama u
sintaksi. U Pascal-u je prihvaena sintaksa iz Algol-a. Sledei primer ilustruje mogunosti njene
primene.
Primer.
if (broj = 0) then
res := 0
else
res := 1;
Ovako definisana if-then-else struktura ima niz nedostataka koji posebno dolaze do izraaja kada se
if naredbe ugrauju jedna u drugu. Na primer u Pascal-u je mogue napisati sledeu sekvencu naredbi:
if (sum = 0) then
if (broj = 0)
then res := 0
else res := 1;
Ova sekvenca naredbi moe da bude protumaena na dva razliita naina u zavisnosti od toga da li
else grana pripada prvoj ili drugoj if naredbi. U jezicima C, Pascal, kao i u vie drugih jezika koji
koriste isti koncept za razreavanje ovakvih situacija: primenjuje se semantiko pravilo da se else
grana uparuje sa najbliom neuparenom then granom. Oigledno je da u ovakvim sluajevima moe
da doe do pogrenog tumaenja pojedinih segmenata programa. U Algol-u se ovaj problem razreava
na sintaksnom nivou. Naime, u Algol-u nije dozvoljeno ubacivanje if naredbi u then granu ve se
nadovezivanje if naredbi moe vriti samo po else grani. Kada je neophodno da se po then grani vri
dalje grananje obavezna je upotreba zagrada kojima se naredba koja se ubacuje transformie u
takozvane proste naredbe koje se jedino mogu nai u then grani. Prethodni primer bi, u Algol-u, bio
napisan kao u sledeem primeru.
Primer. Umetanje if naredbi u Algol-u.
if sum = 0 then
begin
if broj = 0
then res := 0
else res := 1
end;
Ako u prethodnom primeru else grana treba da bude sastavni deo prve if naredbe dati deo programa
treba da bude napisan kao u primeru koji sledi.
Primer. Umetanje if naredbi u Algol-u (druga verzija).
if sum = 0 then
begin
if broj = 0
then res := 0

51
Ivan P. Stanimirovi Uvod u programiranje

end
else res := 1;
Napomena: Jedna od najeih greaka je da se test za jednakost == zameni sa dodeljivanjem =.

Primer. Else se pridruuje najbliem if.

Primeri u C.
Primer. Napisati program kojim se dati brojevi x, y, z udvostruuju ako je x>= y>= z, a u protivnom
menjaju znak.
main()
{ float x,y,z;
printf("Zadati x,y,z:\n"); scanf("%f%f%f",&x,&y,&z);
if((x>=y) && (y>=z)) { x*=2; y*=2; z*=2; }
else { x=-x; y=-y; z=-z; }
printf("x=%f y=%f z=%f", x,y,z);
}

Kod else-if iskaza je vano da rezervisana re else odgovara prethodnom slobodnom if, ukoliko to nije
drugaije odreeno velikim zagradama.

Primer. Izraunati
-5, x<0,
y= x+2, 0<=x<1,
3x-1, 1<=x<5,
2x, x>=5.
void main()
{ float x,y;
scanf("%f",&x);

52
Ivan P. Stanimirovi Uvod u programiranje

if(x<0) y=-5;
else if(x<1) y=x+2;
else if(x<5) y=3*x-1;
else y=2*x;
printf("y= %f\n", y);
}

Primer. Urediti tri zadata realna broja u poredak x < y < z.


#include<stdio.h>
main()
{ float x,y,z,p;
scanf("%f%f%f",&x,&y,&z);
if(x>y) { p=x; x=y; y=p; }
if(x>z) { p=x; x=z; z=p; }
if(y>z) { p=y; y=z; z=p; }
printf("x= %f y= %f z= %f\n",x,y,z);
}

Primer. Data su tri realna broja u poretku x < y < z. Umetnuti realni broj t tako da meu njima bude
odnos x < y < z < t.
void main()
{ float x,y,z,t,p;
scanf("%f%f%f%f",&x,&y,&z,&t);
if(t<x) { p=t; t=z; z=y; y=x; x=p; }
if(t<y) { p=t; t=z; z=y; y=p; }
if(t<z) { p=t; t=z; z=p; }
printf("x= %f y= %f z= %f t= %f\n",x,y,z,t);
}

Primer. Diskutovati reenje sistema linearnih jednaina


a1 x + b1 y = c1
a2 x + b2 y = c2.
void main()
{ float a1,b1,c1,a2,b2,c2,d,dx,dy,x,y;
printf("Koeficijenti prve jednacine?"); scanf("%f%f%f",&a1,&b1,&c1);
printf("Koeficijenti druge jednacine?");
scanf("%f%f%f", &a2,&b2,&c2);
d=a1*b2-a2*b1; dx=c1*b2-c2*b1; dy=a1*c2-a2*c1;
if(d!=0){x=dx/d; y=dy/d; printf("x=%f y=%f\n",x,y);}
else if(d==0 && dx==0 && dy==0)
{ printf("Sistem je neodreen ");
printf("resenje je oblika X,(%f-%fX)/%f\n",c1,a1,b1);
}
else printf("Sistem je nemoguc\n");
}
Primer. Reavanje jednaine ax2+bx+c=0 u jezicima Pascal i C.
program Kvadratna_Jednacina;

var a,b,c,D,x1,x2,x,Re,Im:real;

begin
readln(a,b,c);
if a<>0 then begin
D:=sqr(b)-4*a*c;
if(D>0) then begin
x1:=(-b+sqrt(D))/(2*a); x2:=(-b-sqrt(D))/(2*a);
writeln('x1= ',x1:0:3,' x2= ',x2:0:3);
end
else if D=0 then begin

53
Ivan P. Stanimirovi Uvod u programiranje

x1:=-b/(2*a); writeln('x1= ',x1:0:3,' x2= ',x1:0:3);


end
else begin
Re:=-b/(2*a); Im:=sqrt(-D)/(2*a);
write(Re:0:3,'+i*',Im:0:3); writeln(' ',Re:0:3,'-i*',Im:0:3);
end
end
else if b<>0 then begin
x1:=-c/b; writeln(x1:0:3);
end
else if(c<>0) then writeln('Jednacina nema resenja')
else writeln('Identitet');
end.

#include<stdio.h>
#include<math.h>
void main()
{ float a,b,c,D,x1,x2,Re,Im;
scanf("%f%f%f",&a,&b,&c);
if(a)
{ D=b*b-4*a*c;
if(D>0)
{ x1=(-b+sqrt(D))/(2*a); x2=(-b-sqrt(D))/(2*a);
printf("x1= %f x2= %f\n",x1,x2);
}
else if(D==0)
{ x1=-b/(2*a); printf("x1= %f x2= %f\n",x1,x1); }
else
{ Re=-b/(2*a); Im=sqrt(-D)/(2*a);
printf("%f+i*%f, %f-i*%f\n",Re,Im,Re,Im);
}
}
else if(b)
{ x1=-c/b; printf("%f\n",x1); }
else if(c) printf("Jednacina nema resenja\n");
else printf("Identitet\n");
}

Primer. U gradu A se nalazi zaliha goriva od V (0 < V < 2000000000) litara, od koje kamion-cisterna
treba da dostavi to je mogue veu koliinu u grad B. Od grada do gada B ima tano d (0 < d
2000) kilometara. Cisterna troi litar na jedan kilometar, a moe da primi ukupno C (0 < C 5000)
litara za prevoz i potronju.
Napisati program koji za date V, d, C, ispisuje koliko najvie goriva moe da se dostavi iz A u B, i
koliko PRI TOME najvie moe ostati u A. Cisterna moe ostati u gradu koji daje povoljniji ishod.
Test primer:
2000 100 1000 1700 0
#include <stdio.h>
void main ()
{ long V, d, C, A, B;
printf("Unesi kolicinu u gradu A: "); scanf ("%ld",&V);
printf("Unesi rastojanje izmeu gradova: "); scanf ("%ld",&d);
printf("Unesi kapacitet cisterne: "); scanf ("%ld",&C);
A=V; B=0;
if((C>d) &&(V>=C))
{ if(C>2*d)
{ A=V%C; B=(C-2*d)*(V/C);
if(A<=d) B=B+d;

54
Ivan P. Stanimirovi Uvod u programiranje

else
{ if(A-d>d){B=B+A-d; A=0;}
else B=B+d;
}
}
else {A=V-C; B=C-d;}
} y
printf ("A= %ld B= %ld\n", A, B);
5

Primer. Ispisana je sledea spirala brojeva oko zamiljenog koordinatnog sistema:

16 15 14 13 12

17 4 3 2 11

-5 18 5 0 1 10 5 x

19 6 7 8 9

20 21 22 23 24 25

Za proizvoljan prirodan broj n odrediti njegove koordinate u tom koordinatnom sistemu.


(PASCAL)
-5
PROGRAM spirala(input,output);
VAR n, r, x, y :integer;
BEGIN
read(n); r := trunc((sqrt(n) + 1)/2);
IF n<=4*sqr(r) - 2 * r THEN
BEGIN
x:=r; y:=n - (4 * sqr(r) - 3 * r)
END
ELSE IF n <=sqr(r) THEN
BEGIN
y:=r; x := (4*sqr(r) -r) - n
END
ELSE IF n<=4*sqr(r) + 2 * r THEN
BEGIN
x:=-r; y:=(4*sqr(r) + r) - n
END
ELSE BEGIN
y:=-r; x:= n - (4*sqr(r) + 3 * r)
END;
WRITE ('n = ',n,'x = ', x,'y = ', y)
END.
(C)
#include<stdio.h>
#include<math.h>
main()
{ int n,r,x,y;
scanf("%d", &n); r=(sqrt(n)+1)/2;
if(n<=4*r*r-2*r) { x=r; y=n-(4*r*r-3*r); }
else if(n<=4*r*r) { y=r; x=4*r*r-r-n; }
else if(n<=4*r*r+2*r) { x=-r; y=4*r*r+r-n; }
else { y=-r; x=n-(4*r*r+3*r); }
printf("\n Za n=%d koordinate su x=%d y=%d\n",n,x,y);
}

55
Ivan P. Stanimirovi Uvod u programiranje

4.3.3. Operator uslovnog prelaza u C


Operator uslovnog prelaza ?: je neobian. Pre svega, to je ternarni operator, jer uzima tri izraza za
svoje argumente. Nain na koji se on primenjuje je takoe neobian:
exp1 ? exp2 : exp3;
Prvi argument je pre znaka pitanja '?'. Drugi argument je izmeu '?' i ':', a trei posle ':'. Semantika
ovakvog izraza je sledea. Prvo se izraunava izraz exp1. Ako je njegova vrednost razliita od 0 (tj.
ako je jednaka true), tada se evaluira izraz exp2, i njegova vrednost je vrednost celog izraza. Ako je
vrednost izraza exp1 nula (false), tada se evaluira izraz exp3, i njegova vrednost se vraa kao rezultat.
Na taj nain, ovaj izraz predstavlja zamenu za if-then-else naredbu.
Primer. Umesto izraza
if(y<z) x=y;
else x=z;
kojim se izraunava x=min{y,z}, moe se pisati
x=(y < z) ? y:z;
Zagrade se mogu izostaviti.
Prioritet operatora uslovnog prelaza je vei od prioriteta operatora dodeljivanja, a njegova
asocijativnost je ''s desna na levo''.
Primer. Vrednost izraza
(6>2)?1:2
jednaka je 1, dok je vrednost izraza
(6<2)?1:2
jednaka 2.
Ako je izraz posle ':' takoe uslovni izraz, dobijamo else-if operator.

Primeri.
1. Vrednost izraza

s= -1, x < 0,
x * x, x>=0
moe se izraunati pomou
s=(x < 0) ? -1 : x*x;

2. Vrednost s = sgn(broj) se moe izraunati pomou izraza


s=(broj < 0) ? -1 : ((broj==0) ? 0 : 1);
3. Bez korienja operatora if napisati program koji za zadate x, y izraunava
z= min {x,y}, y>= 0,
max {x2,y2}, y<0.
z=(y>=0) ? ((x<y) ? x:y) : ((x*x>y*y) ? x*x : y*y);

4.4. Struktura viestruke selekcije


Struktura viestruke selekcije omoguava izbor jedne od vie moguih naredbi ili grupa naredbi u
zavisnosti od vrednosti odreenog uslova. Struktura viestruke selekcije se koristi kao zamena za
komplikovane upravljake strukture sledeeg oblika, u kojima se funkcija if mnogo puta ponavlja.
Graf na sledeoj slici ilustruje ovu upravljaku strukturu na nivou algoritma.

56
Ivan P. Stanimirovi Uvod u programiranje

Kako se svaka viestruka selekcija moe simulirati obinim if-then-else grananjem, na sledeoj slici
prikazan je dijagram toka koji odgovara viestrukom grananju.

Ova struktura koja je u svom razvoju pretrpela mnogo izmena do jednog modernog oblika koji se
danas u manje-vie slinim varijantama javlja u svim programskim jezicima.

4.4.1. Viestruka selekcija u C


U programskom jeziku C naredba za viestruko grananje ima dosta zastarelu koncepciju. To je
switch naredba koja u optem sluaju ima sledei oblik:
switch(izraz)
{ case vrednost11: [case vrednost12: ]
operator11
......
break;
case vrednost21: [case vrednost22: ]
operator21
......
break;
......
case vrednostn1: [case vrednostn2: ]
operatorn1
......
break;
default:
operator01
......
break;
}
sledea naredba;

57
Ivan P. Stanimirovi Uvod u programiranje

Semantika ove naredbe je sledea: izraunava se vrednost izraza izraz, koji se naziva selektor.
Vrednost izraza izraz mora da bude celobrojna (ili znakovna, koja se automatski konvertuje u
odgovarajuu celobrojnu vrednost). Dobijena vrednost se uporeuje sa vrednostima vrednost11,
vrednost12, ..., koji moraju da budu celobrojne konstante ili celobrojni konstantni izrazi. Ove
vrednosti se mogu posmatrati kao obeleja za odreenu grupu operatora. Ako je pronaeno obeleje
ija je vrednost jednaka vrednosti izraza izraz, izraunavaju se operatori koji odgovaraju toj vrednosti.
Kljuna re break predstavlja kraj jedne case grane, odnosno kraj grupe operatora sadranih u nekoj
case grani. Ako nije pronaena vrednost u case granama jednaka vrednosti izraza izraz, izraunavaju
se iskazi u default grani; ako je izostavljena alternativa default, nee se izvriti ni jedna od alternativa
operatora switch.
Izraz prema kome se vri selekcija i konstante u pojedinim granama treba da budu integer tipa.
Naredbe u granama mogu da budu obine ili sloene naredbe i blokovi.
Iako na prvi pogled ova naredba lii na ono to imamo u Pascal-u, radi se o nestrukturnoj naredbi
koja se izvrava tako to se izborom grane odreuje samo mesto odakle naredba poinje, a iza toga se
nastavlja njen sekvencijalni tok. To konkretno znai da se naredba u default grani izvrava uvek kao i
to da se naredba u k-toj grani izvrava uvek kada je selektovana neka od prethodnih grana. Da bi se
prekinulo upravljanje pod dejstvom ove naredbe kada se izvri selektovana grana, odnosno da bi se
postigla semantika case strukture u Pascal-u, potrebno je da se na kraju svake grane upravljanje
eksplicitno prenese na kraj cele switch naredbe. U te svrhe u C-u se koristi naredba break koja
predstavlja izlazak iz switch naredbe. Kdom iz primera u C-u je realizovano viestruko grananje iz
prethodnog primera gde je koriena case struktura iz Pascal-a.
Primer. Program kojim se simulira digitron. Uitavaju se dva operanda i aritmetiki operator.
Izraunati vrednost unetog izraza.
void main()
{ float op1, op2;
char op;
printf("Unesite izraz \n");
scanf("%f %c %f", &op1, &op, &op2);
switch(op)
{ case '+': printf("%f\n", op1+op2); break;
case '-': printf("%f\n", op1-op2); break;
case '*': printf("%f\n", op1*op2); break;
case '/': printf("%f\n", op1/op2); break;
default: printf("Nepoznat operator\n");
}
}

Operator break se koristi u okviru switch operatora (kasnije i u while, do, for operatorima) da bi se
obezbedio izlaz neposredno na naredbu iza switch strukture. Ukoliko se iza neke grupe operatora u
switch operatoru ispusti break operator, tada se u sluaju izbora te grupe operatora izvravaju i sve
preostale alternative do pojave break operatora ili do kraja switch operatora.

Primer. Posmatrajmo sledei program.


void main()
{ int ocena;
scanf("%d",&ocena);
switch(ocena)
{ case 5: printf("Odlican\n"); break;
case 4: printf("Vrlo dobar\n");
case 3: printf("Dobar\n");
case 2: printf("Dovoljan\n"); break;
case 1: printf("Nedovoljan\n"); break;
default: printf("Nekorektna ocena\n:");
}
}

58
Ivan P. Stanimirovi Uvod u programiranje

Ukoliko je ocena = 4 ispisuje se sledei rezultat:


Vrlo Dobar
Dobar
Dovoljan

Operator switch se moe realizovati pomou veeg broja if operatora. Meutim, programi napisani
pomou switch operatora su pregledniji.
Primer. Za zadati redni broj meseca ispisati broj dana u tom mesecu.
void main()
{ int mesec;
char ch; /* Da li je godina prestupna */
printf("Unesi redni broj meseca: ");
scanf("%d", &mesec);
switch(mesec)
{ case 1:case 3:case 5:case 7:case 8:case 10:case 12:
printf("31 dan\n");
break;
case 4: case 6: case 9: case 11:
printf("30 dana\n);
break;
case 2: printf("Da li je godina prestupna? ");
scanf("%c%c",&ch,&ch);
/* prvo ucitavanje je fiktivno, uzima enter */
if((ch=='D') || (ch=='d')) printf("29 dana\n);
else printf("28 dana\n");
break;
default: printf("Nekorektan redni broj\n");
}
}

Primer. Odrediti sutranji datum.


void main()
{unsigned int d,m,g,prestupna;
printf("Unesi datum u obliku ddmmgg:\t");
scanf("%2d%2d%4d",&d,&m,&g);
if(d<1 || d>31 || m<1 || m>12)
{ printf("Nepravilan datum\n"); exit(0); }
prestupna=((g%4==0) && (g%100!=0)) ||
((g%100==0) && (g%400==0));
if(m==2 && d>28+prestupna)
{ printf("Nepravilan datum\n"); exit(0); }
switch(d)
{ case 31:
switch(m)
{ case 1:case 3:case 5:case 7:case 8:case 10: d=1; m++; break;
case 12: d=1; m=1; g++; break;
default: { printf("%2d. mesec ne moze imati 31 dan\n",m);
exit(0);
}
}
break;
case 28: if(!prestupna && (m==2)) { d=1; m=3; }
else d=29;
break;
case 29: if(prestupna && (m==2)) { d=1; m=3; }
else d=30;
break;
case 30: switch(m)

59
Ivan P. Stanimirovi Uvod u programiranje

{ case 4: case 6: case 9: case 11:


d=1; m++;
break;
case 2:printf("Februar ne moze imati 30 ana\n");
exit(0);
default:d=31;
}
break;
default:d++;
}
printf("Sledeci dan ima datum:\t%2d\t%2d\t%4d\n",d,m,g);
}
Operator switch se moe koristiti umesto if operatora. Na primer, umesto operatora
if(a>b) max=a;
else max=b;
moe se pisati
switch(a>b)
{ case 0: max=b; break;
case 1: max=a;
}
Oigledno da ovo nije praktino.

4.5. Programske petlje


U svakom programskom jeziku obino postoje upravljake strukture kojima moe da se definie
viestruko ponavljanje odreene sekvence naredbi na istim ili razliitim podacima. To su programske
petlje ili strukture iteracije. Ciklusi omoguavaju da se skupovi srodnih podataka koji se odnose na isti
pojam obrauju na isti nain.
Prema jednoj podeli, programske petlje se mogu podeliti na:
brojake i
iterativne.
Kod brojakih petlji se unapred moe rei koliko puta se ponavlja telo petlje. Kod iterativnih
programskih ciklusa, nije unapred poznato koliko puta se izvrava telo petlje. Kod ovakvih ciklusa,
kriterijum za njihov zavretak je ispunjenje odreenog uslova.
Prema drugoj podeli, programske petlje se dele na:
petlje sa preduslovom i
petlje sa postuslovom.
Kod petlji sa preduslovom, izlazni kriterijum se proverava pre nego to se izvri telo petlje, dok se kod
petlji sa postuslovom prvo izvri telo petlje pa se zatim proverava izlazni kriterijum.
U savremenim programskim jezicima skoro bez izuzetaka postoje naredbe za definisanje petlji sa
unapred odreenim brojem prolaza. To su tzv. brojake petlje kod kojih postoji broja (indeks petlje)
kojim se upravlja izvravanjem petlje. Struktura brojake petlje u Pascal-u je prikazana na sledeoj
slici.

for I:= pocetni to krajnji

niz naredbi

U ovoj petlji se naredbe u telu petlje izvravaju za sve vrednosti brojake promenljive I izmeu
vrednosti izraza pocetni i vrednosti izraza krajnji.

60
Ivan P. Stanimirovi Uvod u programiranje

Sa prihvatanjem strukturnog programiranja u novijim jezicima se pojavljuje i logiki kontrolisana


petlja kojom se realizuje while (while-do) struktura. Ova struktura predvia ponavljanje izvravanja
tela petlje sve dok uslov u zaglavlju petlje ima vrednost true. Kod ovakvih petlji nije unapred poznat
broj izvravanja tela petlje. Za ove petlje se esto koristi i termin pretest petlje, jer se ispitivanje
uslova vri pre svakog izvravanja petlje.

ne
uslov
da
niz naredbi

Strukturnim programiranjem definisana je i until struktura (do-while struktura) koja predvia post-
test uslova, odnosno ispitivanje uslova posle izvrenja tela petlje. Repeat-until struktura je prikazana
na sledeoj slici.

niz naredbi

uslov
ne
da
Poseban oblik petlji sa postuslovom je do-while naredba u C. Ovakva struktura sa postuslovom se
zavrava kada uslov nije ispunjen.

4.5.1. Programske petlje u C


While naredba u C
Ovom naredbom se realizuju programski ciklusi sa nepoznatim brojem ponavljanja, zavisno od
odreenog uslova. Operator while se koristi prema sledeoj sintaksi:
while(izraz)
operator
Efekat ove naredbe je da se telo while ciklusa, oznaeno sa operator izvrava dok je vrednost izraza
izraz jednaka true (nenula). Kada vrednost izraza izraz postane false (nula), kontrola se prenosi na
sledeu naredbu. Telo ciklusa, oznaeno sa operator, izvrava se nula ili vie puta. Operator moe biti
prost ili sloen. Svaki korak koji se sastoji iz provere uslova i izvrenja operatora naziva se ''iteracija''.
Ako odmah po ulasku u ciklus izraz ima vrednost ''netano'' (nula), operator se nee izvriti.
Primer. Maksimum n unetih brojeva.
main()
{ int i, n;
float max, x;
printf("Koliko brojeva zelite? "); scanf("%d", &n);
while (n<=0)
{ printf("Greska, zahtevan je ceo pozitivan broj.\n");
printf("Unesite novu vrednost: "); scanf("%d", &n);
}
printf("\n Unesite %d realnih brojeva: ", n);
scanf("%f", &x); max = x; i=1;
while (i<=n)
{ scanf("%f", &x); if(max<x) max = x; ++i; }
printf("\n Maksimalni od unetih brojeva: %g\n",max);
}

61
Ivan P. Stanimirovi Uvod u programiranje

Primeri u jeziku C

Primer. Izraunati a prema iterativnoj formuli


x0 = a/2; xi+1 = xi - (xi2 - a)/(2xi) = xi +1/2*(a/xi - xi) , i = 0, 1, ...
Iterativni postupak prekinuti kada se ispuni uslov |xi+1 - xi|<10-5.
#include <stdio.h>
main()
{ float a,x0,x1;
scanf("%f",&a)
x0=a/2; x1=(x0*x0-a)/(2*x0);
while(fabs(x1-x0)<1E-5) { x0=x1; x1=(x0*x0-a)/(2*x0); }
printf("%f\n",x1);
}

Primer. Izraunati aritmetiku sredinu niza brojeva razliitih od nule. Broj elemenata u nizu nije
unpred poznat.
void main()
{ int brojac=0;
float suma=0, stopcode=0, broj;
printf("Daj niz znakova zavrsen sa %d\n",stopcode);
scanf("%f",&broj);
while(broj != stopcode)
{ suma+=broj; brojac++; scanf("%f",&broj); }
printf("Srednja vrednost= %f\n",suma/brojac);
}

Primer. Dejstvo operatora ++ i - - u ciklusima.


#include <stdio.h>
void main()
{ int i=0;
printf("Prva petlja :\n");
while(i<5) { i++; printf("%5d",i); } /* 1 2 3 4 5*/
printf("\nDruga petlja :\n");
i=0;
while(i++<5) printf("%5d",i); /* 1 2 3 4 5*/
i=0;
printf("\nTreca petlja :\n");
while(++i<5) printf("%5d",i); /* 1 2 3 4*/
}
Primer. Suma celih brojeva unetih preko tastature.
#include <stdio.h>
main()
{ int x,sum=0;
while(scanf("%d",&x)==1) sum+=x;
printf("Ukupan zbir je %d\n",sum);
}

Primer. Ispitati da li je zadati prirodan broj n prost.


#include <math.h>
void main()
{ int i,n,prost;
scanf("%d",&n);
prost=(n%2!=0) || (n==2); i=3;
while(prost && i<=sqrt(n))
{ prost = n%i!=0; i+=2; }

62
Ivan P. Stanimirovi Uvod u programiranje

if(prost) printf("%d je prost\n",n);


else printf("%d nije prost\n",n);
}
Primer. Dati su tegovi mase 3k kg, k = 0,1,2,... i to iz svake vrste po jedan. Napisati program koji
odreuje koje tegove bi trebalo postaviti levo a koje desno da bi se izmerio predmet teine A kg koji se
nalazi na levom tasu.
#include <stdio.h>
void main()
{ int dteg,lteg,s,a;
printf("Unesite tezinu\n");
scanf("%d",&a);
s=1;
while (a>0)
{ dteg=a%3;
if (dteg==2){ dteg=0; lteg=1; }
else lteg=0;
printf("Teg od %dkg staviti levo: %d, desno: %d\n",s,lteg,dteg);
s*=3;
a=(a+lteg)/3;
}
}

#include <stdio.h>

void main() {
int t, p = 0;
scanf("%d", &t);
while (t > 1) {
if (t % 3 == 1)
{ printf("3^%d ide na desnu\n", p); t--; }
else if (t % 3 == 2)
{ printf("3^%d ide na levu\n", p); t++; }
else { p++; t /= 3; }
}
printf("3^%d ide na desnu\n", p);
}

Primer. Izraunati

x 2k

k 0
(1) k
(2k )!
, x /2
.
Sumiranje prekinuti kada je apsolutna vrednost poslednjeg dodatog lana manja od zadate tanosti e.
Koristi se
x2
ak ak 1
2k (2k 1)
void main()
{ double c,a,e,x;
int k=0;
scanf("%lf%lf",&x, &e);
while(fabs(a)>=e)
{ k++; a=-(x*x/(2*k*(2*k-1)))*a; c+=a; }
printf("cos(%.2lf)=%.7lf",x,c);
}

Primer. Heksadekadni broj prevesti u dekadni. Unoenje heksadekadnog broja prekinuti kada se
unese karakter koji ne pripada skupu karaktera '0', ... , '9', 'A', ... , 'F'.

63
Ivan P. Stanimirovi Uvod u programiranje

#include <stdio.h>
void main()
{int broj,u,k;
char cif;
broj=0;u=1;
printf("unesi heksadekadni broj\n"); scanf("%c",&cif);
u=((cif<='F')&&(cif>='0'));
while (u)
{ if ((cif>='A')&&(cif<='F')) k=cif-55; else k=cif-48;
broj=broj*16+k; scanf("%c",&cif); u=((cif<='F')&&(cif>='0'));
}
printf("%d\n",broj);
}

Primer. Napisati program koji simulira rad depnog kalkulatora. Program uitava niz brojnih
vrednosti razdvojenih znakovima aritmetikih operacija +, -, *, / kao i izraunavanje vrednosti izraza
koji je definisan na ovaj nain. Aritmetike operacije se izvravaju s leva na desno, bez potovanja
njihovog prioriteta.
#include <stdio.h>
void main()
{ double result, num;
char op;
printf("\n\n"); scanf("%lf" , &num); scanf("%c" , &op);
result = num ;
while (op != '=')
{ scanf("%lf" , &num) ;
switch (op)
{ case '+' : result += num ; break;
case '-' : result -= num ; break;
case '*' : result *= num ; break;
case '/' : result /= num ; break;
}
scanf("%c" , &op);
}
printf("Rezultat je %.10lf." , result) ;
}

4. Dati su tegovi mase 3k kg, k = 0,1,2,... i to iz svake vrste po jedan. Napisati program koji odreuje
koje tegove bi trebalo postaviti levo a koje desno da bi se izmerio predmet teine A kg koji se nalazi na
levom tasu.
#include <stdio.h>
void main()
{
int dteg,lteg,s,a;
printf("Unesite tezinu\n");
scanf("%d",&a);
s=1;
while (a>0)
{ dteg=a%3;
if (dteg==2)
{
dteg=0;
lteg=1;
}
else lteg=0;
printf("Teg od %dkg staviti levo: %d, desno:
%d\n",s,lteg,dteg);
s*=3;
a=(a+lteg)/3;

64
Ivan P. Stanimirovi Uvod u programiranje

}
}

Primena while ciklusa u obradi teksta u C


esto puta se pri radu sa tekstovima umesto funkcija scanf() i printf() koriste biblioteke funkcije
getchar() i putchar(). Pre korienja ovih funkcija mora da se navede pretprocesorska direktiva
#include<stdio.h>. Ove funkcije se koriste za ulaz i izlaz samo jednog karaktera. Funkcija
putchar() ima jedan znakovni argument. Pri njenom pozivu potrebno je da se unutar zagrada navede
znakovna konstanta, znakovna promenljiva ili funkcija ija je vrednost znak. Ovaj znak se prikazuje
na ekranu. Funkcija getchar() nema argumenata. Rezultat njenog poziva je znak preuzet iz
tastaturnog bafera. Ovom funkcijom se ulazni znak unosi u program.
Primer. Izraunati koliko je u zadatom tekstu uneto znakova 'a', 'b', zajedno 'c' i 'C', kao i broj
preostalih karaktera.
#include <stdio.h>
void main()
{ int c, a_count=0, b_count=0, cC_count=0, other_count=0;
while((c=getchar()) != EOF)
switch (c)
{ case 'a': ++a_count; break;
case 'b': ++b_count; break;
case 'c': case 'C': ++cC_count; break;
default: ++other_count;
}

printf("\n%9s%5d\n%9s%5d\n%9s%5d\n%9s%5d\n%9s%5d\n",
"a_count:", a_count, "b_count:", b_count,
"cC_count:", cC_count, "other:", other_count,
"Total:", a_count+b_count+cC_count+other_count);
}

Primer. Unos teksta je zavren prelazom u novi red. Prebrojati koliko je u unetom tekstu znakova
uzvika, znakova pitanja a koliko taaka.
#include <stdio.h>
void main()
{ char c;
int uzv,upt,izj;
uzv=upt=izj=0;
while((c=getch())!='\n')
switch(c)
{ case '!':++uzv; break;
case '?':++upt; break;
case '.':++izj; break;
}
printf("\n"); printf("Uzvicnih ima %d\n",uzv);
printf("Upitnih ima %d\n",upt); printf("Izjavnih ima %d\n",izj);
}

Kod organizacije while ciklusa mora se voditi rauna o tome da telo ciklusa menja parametre koji
se koriste kao preduslov za ciklus, tako da posle odreenog broja iteracija postane netaan. U
protivnom, ciklus e biti beskonaan.
Do-while naredba u C
Do-while naredba je varijanta while naredbe. Razlikuje se od while naredbe po tome to je uslov na
kraju ciklusa:
do
operator
while(izraz);

65
Ivan P. Stanimirovi Uvod u programiranje

sledea naredba;
Telo ciklusa je oznaeno sa operator, i izvrava se jedanput ili vie puta, sve dok izraz ne dobije
vrednost 0 (false). Tada se kontrola prenosi na sledeu naredbu.

Primeri
Primer. Ispis celog broja s desna na levo.
void main()
{ long broj;
printf("Unesite ceo broj"); scanf("%ld",&broj);
printf("Permutovani broj");
do { printf("%d",broj%10); broj /= 10; } while(broj);
printf("\n");
}

Primer. Izraunati priblino vrednost broja = 3.14159 koristei formulu


/4 = 1-1/3+1/5-1/7+
Sumiranje prekinuti kada apsolutna vrednost lana koji se dodaje bude manja od zadate vrednosti eps.
void main()
{ int znak=1;
float clan,suma,eps,i=1.0;
scanf("%f",&eps); clan=suma=1.0;
do
{ clan=znak/(2*i+1); suma+=clan; znak=-znak; i++; }
while(1/(2*i+1)>=eps);
printf("Broj Pi=%f\n",4*suma);
}
For naredba u C
U leziku C, naredba for je povezana sa while naredbom. Preciznije, konstrukcija
for(pocetak; uslov; korekcija)
operator
sledea naredba
ekvivalentna je sa
pocetak;
while(uslov)
{ operator
korekcija
}
pod uslovom da uslov nije prazan.
Operator koji predstavlja telo ciklusa moe biti prost ili sloen.
For ciklus oblika
for(; uslov ;) operator
ekvivalentan je while ciklusu
while(uslov) operator

Takoe, ekvivalentni su sledei beskonani ciklusi:


for(;;) operator
i
while(1) operator.
For naredba oblika
for (pocetak; uslov; korekcija) operator
moe se predstaviti sledeim dijagramom toka

pocetak

66

netano
uslov <> 0
Ivan P. Stanimirovi Uvod u programiranje

Izrazi u zaglavlju petlje mogu da budu i izostavljeni. Na primer, petlja bez drugog izraza izvrava
se kao da je njegova vrednost true, to znai kao beskonana petlja. Ako su izostavljeni prvi i trei
izraz, telo ciklusa je prazno.
U jeziku C se za definisanje petlje sa unapred definisanim brojem izvrenja tela petlje moe
koristiti for naredba. Meutim, for naredba u C je mnogo fleksibilnija od odgovarajuih naredbi u
drugim jezicima. Naime, izrazi u zaglavlju petlje mogu da objedine vie naredbi. To znai da se u
okviru petlje moe istovremeno definisati vie uslova upravljanja vezanih za razliite promenljive koje
ak mogu da budu i razliitih tipova. Razmotrimo sledei primer.

Primeri
Primer. Suma prvih n prirodnih brojeva se moe izraunati na vie razliitih naina.
1. sum=0; for(i=1; i<=n; ++i) sum += i;
2. sum=0; i=1; for(; i<=n;) sum += i++;
3. for(sum=0, i=1; i<=n; sum += i, i++);
Primer. Faktorijel prirodnog broja uraen na dva slina naina.
void main()
{ int i,n;
long fak=1;
printf("\n Unesite broj"); scanf("%d",&n);
for(i=1; i<=n; ++i) fak *=i;
printf("%d! = %ld \n",n,fak);
}

void main()
{ int i,n;
long fak=1;
printf("\n Unesite broj"); scanf(" %d",&n);
for(fak=1,i=1; i<=n; fak*=i,++i);
printf("%d! = %ld \n",n,fak);
}

Primer. Izraunati 1! + 2! ++ n!.


void main()
{ int i,n; long fakt,s;
scanf("%d",&n);
for(s=0, fakt=1, i=1; i<=n; fakt*=i, s+=fakt, i++);
printf("Suma=%ld\n",s);
}

Isti izraz se moe izraunati na sledei nain


void main()
{ int n; long s;

67
Ivan P. Stanimirovi Uvod u programiranje

scanf("%d",&n);
for(s=0; n>0; s=s*n+n--);
printf("Suma=%ld\n",s);
}

Primer. Izraunati sve trocifrene Armstrongove brojeve.


void main()
{ int a,b,c, i;
for(i=100;i<=999;i++)
{ a=i%10; b=i%100/10; c=i/100;
if(a*a*a+b*b*b+c*c*c==i) printf("%d\n",i);
}
}

Primer. Program za odreivanje savrenih brojeva do zadatog prirodnog broja. Savren broj je jednak
sumi svojih delitelja.
void main()
{ int i,m,n,del,s;
scanf("%d",&m)
for(i=2;i<=m;i++)
{ n=i; s=1;
for(del=2; del<=i/2; del++) if(n%del==0) s+=del;
if(i==s) printf("%d\",i);
}
}

Primer. Tablica ASCII kodova.


void main()
{ signed char c; unsigned char d;
for(c=-128; c<=127; c++) printf("c = %d %c\n",c,c);
for(d=0; d<=255; d++) printf("d = %d %c\n",d,d);
}
Primer. (Pascal) Izraunati

x 2k
cos(x)
k 0 ( 2k )!

sa tanou . Sumiranje prekinuti kada bude ispunjen uslov


|(x2k)((2k)!)| < .
program suma;
var x,eps,a,s:real;
k:integer;
begin
writeln('Unesite promenljivu x i tacnost '); readln(x,eps);
k:=0; a:=1; s:=a;
while abs(a)>=eps do
begin
a:=sqr(x)/((2*k+1)*(2*k+2))*a; s:=s+a; k:=k+1;
end;
writeln('Suma = ',s:0:6);
end.

Primer. U ravni je dato N taaka svojim koordinatama (x, y). Napisati program na programskom
jeziku C, koji na svom izlazu daje ukupan broj taaka koje pripadaju oblastima I, II, III odnosno IV, i
broj taaka koje ne pripadju ni jednoj od naznaenih oblasti. Oblasti su definisane krunicom i
pravama kao na slici, a njihove jednaine glase:
K: x2 + (y-1)2 = 1
AB: y = x, BC: y = -x + 2, CD: y = x + 2, DA: y = -x.

68
Ivan P. Stanimirovi Uvod u programiranje

Broj taaka kao i njihove koordinate uneti sa tastature na poetku programa.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void main()
{ int n, i;
float x, y;
// Brojaci tacaka u odgovarajucim oblastima.
int br1 = 0, br2 = 0, br3 = 0, br4 = 0, brOstalo = 0 ;
// Promenljie koje definisu polozaje tacaka
int unutarK, ispodAB, iznadBC, iznadCD, ispodDA;
printf("Unesite broj tacaka\n"); scanf("%d", &n);
for (i = 0; i < n; i++)
{ printf("Unesite kordinate tacke %d\n", i + 1); scanf("%f %f", &x, &y);
unutarK = (x*x + (y-1)*(y-1)) < 1;
ispodAB = y < x;
iznadBC = y > -x + 2;
iznadCD = y > x + 2;
ispodDA = y < -x;
if (unutarK)
{ // Tacka je unutar kruznice
if (ispodAB) br1++;
else if (iznadBC) br2++;
else if (iznadCD) br3++;
else if (ispodDA) br4++;
}
}
brOstalo = n - br1 - br2 - br3 - br4;
printf("Brojevi tacaka u oblsatima I, II, III, IV respektivno iznose:
%d %d %d %d\n", br1, br2, br3, br4);
printf("Broj tacaka koje ne pripadaju ni jednoj oblasti iznosi: %d\n",
brOstalo);
}

4.6. Formalizacija repetitivnih iskaza


Neka je B logiki izraz, a S iskaz. Tada:
while B do S (1)
oznaava ponavljanje radnje definisane iskazom S sve dok izraunavanje izraza B daje vrednost true.
Ako je vrednost izraza B jednaka false na samom poetku procesa obavljanja radnje definisane sa (1),
iskaz S nee biti uopte izvren. Iskaz (1) se grafiki predstavlja na sledei nain:

(2)

69
Ivan P. Stanimirovi Uvod u programiranje

Efekat iskaza while B do S moe se rigorozno definisati tako to se kae da je on ekvivalentan


efektu iskaza:
if B then
begin
S;
while B do S (3)
end.

(4)

Ovakva definicija znai da dijagrami (2) i (4) opisuju ekvivalentne procese izvrenja (radnje).
Primer while B do S iskaza dat je u programu (5), koji izraunava sumu h(n) = 1+1/2+ . . . +1/n.
var n : integer; h : real;
h :=0;
while n>0 do (5)
begin
h := h+1/n; n := n1
end.
Drugi oblik repetitivnog iskaza je:
repeat S until B, (6)
gde je S niz iskaza a B logiki izraz. Iskaz (6) definie sledeu radnju: izvrava se iskaz S, a zatim se
izraunava izraz B. Ako je rezultat izraunavanja izraza B jednak false, ponovo se izvrava iskaz S, i
tako dalje. Proces ponavljanja radnje definisane sa S zavrava se kada izraunavanje izraza B da true.
Struktura ovako definisanog repetitivnog iskaza predstavlja se sledeim dijagramom:

(7)

Poreenjem (2) i (7) zakljuujemo da se u (7) iskaz S mora izvriti bar jednom, dok se u (2) on ne
mora uopte izvriti. Kako se u prvom sluaju B izraunava pre svakog izvrenja iskaza S, a u drugom
nakon svakog izvrenja iskaza S, razlozi efikasnosti nalau da B bude u to je mogue prostijoj formi.
Rigorozna definicija radnje odreene iskazom repeat S until B daje se na taj nain to se
kae da je ona ekvivalentna radnji koju odreuje iskaz:
begin
S;
if B then
repeat S until B

70
Ivan P. Stanimirovi Uvod u programiranje

end. (8)

(9)

Ovo znai da dijagrami (7) i (9) opisuju ekvivalentne radnje. Kako se u (2) i (7) pojavljuju
zatvorene putanje ili petlje, oba ova iskaza se esto i nazivaju petljama. U njima se S se naziva telom
petlje.
Primer repeat iskaza dat je u programu (10), koji izraunava sumu h(n)=1+1/2+ . . .+ 1/n:
var n: integer; h: real;
h:=0;
repeat
h:= h+1/n; n:=n-1 (10)
until not(n>0).
Fundamentalni problem vezan za repetitivnu kompoziciju iskaza ilustrovaemo primerima (5) i
(10). Proces izvrenja iskaza (10) je konaan samo ako u poetku vai n>0. Za n<0 (10) predstavlja
beskonanu petlju. S druge strane, program (5) se ponaa korektno, ak i ako je n<0, tj. proces
njegovog izvravanja je konaan. Vidimo, dakle, da pogreno koncipiran repetitivni iskaz moe
opisivati radnju beskonanog vremenskog trajanja.

4.7. Nasilni prekidi ciklusa


Petlje razmatrane u prethodnim primerima imaju zajedniku karakteristiku da se iz petlje izlazi ili
na kraju, kada se zavri sekvenca naredbi koja ini telo petlje, ili na samom poetku pre nego i
zapone ta sekvenca naredbi, zavisno od vrste petlje i ispunjenja uslova. U takvim sluajevima, petlja
se zavrava na osnovu izlaznog kriterijuma, koji je postavljen kao preduslov ili postuslov. Meutim, u
odreenim sluajevima pogodno je da programer sam odredi mesto izlaska iz petlje. U novijim
programskim jezicima, obino postoji jednostavan mehanizam za uslovni ili bezuslovni izlazak iz
petlje. U programskim jezicima C i Pascal takva naredba se naziva break.
U programskom jeziku C za bezuslovni izlazak iz najblie petlje koristi se naredba break. Tada je
njeno znaenjem slino kao i kod switch naredbe.
Primer. Naredba break za bezuslovni izlazak iz petlje u C.
sum=0;
while (sum < 2000)
{ scanf(%d, &podatak);
if(podatak < 0) break;
sum = sum + podatak;
}
U svakom prolazu kroz petlju u ovom primeru uitava se po jedan podatak i dodaje sumi. Zaglavljem
petlje je definisano da se sumiranje izvrava sve dok se sumiranjem ne dostigne vrednost 2000.
Meutim, ukoliko se uita negativni podatak, petlja se prekida i program se nastavlja sa prvom
naredbom iza petlje.

71
Ivan P. Stanimirovi Uvod u programiranje

U jeziku C postoji i naredba continue koja se takoe koristi za upravljanje tokom izvrenja petlje.
Ovom naredbom se samo preskae ostatak petlje i program nastavlja novim prolazom kroz petlju
poevi od prve naredbe petlje. Efekat te naredbe opisan je u narednom primeru.
Primer. Efekat naredbe continue u C.
sum=0;
while (sum < 2000)
{ scanf(%d, &podatak);
if (podatak < 0) continue;
sum = sum + podatak;
}
U ovom sluaju, kada se uita negativni podatak preskae se naredba za modifikovanje sume i
program nastavlja ponovnim prolaskom kroz petlju. To znai da e u ovom sluaju petlja uvek da se
zavri kada se dostigne vrednost sum >= 2000, to u prethodnom primeru nije uvek bio sluaj.

4.8. Naredbe za bezuslovno grananje


Za bezuslovno grananje u programu koristi se GOTO naredba. U sutini, to je jedna od najmonijih
naredbi koja u sprezi sa naredbom selekcije omoguava da se implementiraju i najsloeniji algoritmi.
Problem je jedino u tome, to tako definisan kd moe da bude veoma nepregledan, a takvo
programiranje podlono grekama.
Po konceptu strukturnog programiranja GOTO naredba je izbaena iz upotrebe, jer se nastoji da se
program definie umetanjem struktura jednu u drugu i da pri tome sve strukture imaju jedan ulaz i
jedan izlaz. Postoji nekoliko jezika u kojima GOTO naredba uopte ne postoji, na primer Modula 2.
Meutim u mnogim jezicima koji podravaju koncept strukturnog programiranja naredba GOTO je
zadrana i ostaje pogodno sredstvo za reavanje mnogih problema.

4.8.1. Oznake (labele)


Skok (jump) prenosi kontrolu na specificiranu taku u programu. Tipina forma bezuslovnog skoka
je izraz goto L;, ime se kontrola toka programa direktno prenosi na taku oznaenu sa L, to se
naziva obeleje (label).

72
Ivan P. Stanimirovi Uvod u programiranje

Primer. Sledei fragment programa (u C-like jeziku) sadri bezuslovni skok:


if (E1)
C1
else {
C2
goto X;
}
C3
while (E2) {
C4
X: C5
}
Ovde obeleje X oznaava partikularnu taku programa, preciznije, poetak komande C5. Na taj nain,
skok goto X; prenosi kontrolu na poetak komande C5.
Sledea slika prikazuje dijagram toka koji odgovara ovom fragmentu programa. Napomenimo da
jedna komanda if i komanda while imaju prepoznatljive poddijagrame, koji su oznaeni. Fragment
programa, kao celina ima jedan ulaz i jedan izlaz, ali komanda if ima dva izlaza, dok while komanda
ima dva ulaza.

Neogranieni skokovi omoguavaju komande koje imaju viestruke ulaze i viestruke izlaze. Oni
imaju tendenciju da produkuju pagetti kd, tako nazvan zato to je njihov dijagram toka zamren.
pagetti kd ima tendenciju da bude teko razumljiv. Veina glavnih programskih jezika
podrava skokove, ali su realno zastareli u modenim jezicima. ak i u jezicima koji podravaju
skokove, njihova upotreba je ograniena restrikcijom dometa svakog obeleja: skok goto L; je
legalan samo unutar dosega L. U C, na primer, doseg svakog obeleja je najmanje obuhvaen blok
komandom ({ . . . }). Prema tome, mogui su skokovi unutar blok komande, ili iz jedne blok
komande izvan neke ograene blok komande; meutim, nemogu je skok unutar neke blok komande
od spolja, niti iz jednog tela funkcije u drugo.
C skokovi nisu ogranieni da spree pagetti kodovanje.
Skok unutar blok komande je relativno jednostavan, dok je skok izvan blok naredbe
komplikovaniji. Takav skok mora da uniti lokalne promenljive bloka pre nego to se transfer prenese
na destinaciju skoka.
Primer. Skok izvan blok naredbe. Uoimo sledei (vetaki) C kod:
#include<stdio.h>
void main()
{ char stop = '.',ch='!';
do { char ch;

73
Ivan P. Stanimirovi Uvod u programiranje

ch = getchar();
if (ch == EOF) goto X;
putchar(ch);
} while (ch != stop);
printf("done");
X: printf("%c\n",ch);
}
Skok goto X; prenosi kontrolu izvan blok komande {. . .}. Prema tome, on takoe unitava lokalnu
promenljivu ch iz bloka. Po izlasku iz ciklusa, prikazuje se vrednost ! kao vrednost promenljive ch.
Skok izvan tela procedure je jo komplikovaniji. Takav skok mora da uniti lokalne promenljive i
da terminira aktivaciju procedure pre prenosa kontrole na takvu destinaciju. Velike komplikacije
nastaju kada je destinacija skoka unutar tela rekurzivne procedure: koje rekurzivne aktivacije se
terminiraju kada se skok izvri?
Prema tome, povrno su skokovi veoma jednostavni, dok u sutini oni uvode neeljenu
kompleksnost u semantiku jezika visokog nivoa.
Za oznaavanje naredbi, na koje se pod dejstvom GOTO naredbe prenosi upravljanje, u
programskim jezicima se koristi koncept oznaka (labela). Iskaz Goto je prost iskaz koji ukazuje na to
da dalju obradu treba nastaviti u drugom delu programskog teksta, to jest sa mesta na kome je labela.
U nekim jezicima (C-u, Algol-u 60 na primer) koriste se identifikatori kao oznake. U drugim
(FORTRAN i Pascal na primer) to su neoznaene celobrojne konstante. U Adi su oznake takoe
identifikatori, ali obuhvaeni zagradama << i >>, dok se za razdvajanje oznaka od naredbi na koje se
odnose u mnogim jezicima koristi dvotaka (:). Evo nekih primera:
Primer naredbe GOTO za skok na oznaenu naredbu u Adi.
goto KRAJ;

<<KRAJ>> SUM := SUM + PODATAK;
Isti primer napisan u C-u bio bi sledeeg oblika:
goto kraj;

kraj: sum := sum + podatak;

U svim programskim jezicima obino su definisana odreena pravila koja ograniavaju korienje
naredbe GOTO. Na primer, u Pascal-u oznake moraju eksplicitno da budu opisane u odeljku
deklaracije naredbi. One se ne mogu prenositi kao argumenti potprograma niti modifikovati. Kao deo
GOTO naredbe moe da bude samo neoznaena konstanta, ali ne i izraz ili promenljiva koja dobija
vrednost oznake.

Svaka labela poseduje sledee osobine:


1. mora se pojaviti u odeljku deklaracija labela, pre svog pojavljivanja u bloku,
2. mora prethoditi jednom i samo jednom iskazu koji se pojavljuje u iskaznom delu bloka.
3. ima oblast vaenja u celokupnom tekstu tog bloka, iskljuujui sve ugnjedene blokove koji
ponovo deklariu tu labelu.
Primer. U beskonanom ciklusu unositi dva realna broja i raunati njihov proizvod.
program mnozi;
uses crt;
label 1;
var a,b:real;
begin
1:
write(' Prvi broj? '); readln(a); write(' Drugi broj? '); readln(b);
writeln(' Njihov proizvod je '); writeln(a*b:20:0);

74
Ivan P. Stanimirovi Uvod u programiranje

goto 1;
end.
Primer. Primeri upotrebe Goto naredbe (programski deo):
label 1; { blok A }
...
procedure B; { blok B }
label 3, 5;
begin
goto 3 ;
3 : Writeln(Dobar dan');
5 : if P then
begin S; goto 5 end ; { while P do S }
goto 1 ;
{ ovo uzrokuje prevremen zavrsetak aktivacije procedure B}
Writeln('Dovienja')
end; { blok B }
begin
B;
1: Writeln(program')
{ "goto 3" nije dozvoljen u bloku A )
end { blok A }
Skokovi izvana u strukturirani iskaz nisu dozvoljeni. Stoga su sledei primeri nepravilni.
Primeri sintaksno nepravilnih programa:
a) for I := 1 to 10 do
begin
S1;
3: S2
end ;
goto 3
b) if B then goto 3;
...
if B1 then 3 : S
c) procedure P;
procedure Q;
begin ...
3 :S
end ;
begin ...
goto 3
end.
Iskaz Goto treba sauvati za neuobiajene ill retke situacije gde je potrebno razbiti prirodnu
strukturu algoritma. Dobro je pravilo da bi trebalo izbegavati upotrebu skokova pri izraavanju
pravilnih ponavljanja i uslovnih izvravanja iskaza, jer takvi skokovi unitavaju odraz strukture obrade
u tekstualnim (statikim) strukturama programa. tavie, nedostatak slaganja izmeu tekstualne i
obradne (tj. statike i dinamike) strukture poguban je po jasnou progama i ini proveru ispravnosti
programa mnogo teom. Postojanje iskaza Goto u Pascal programu esto ukazuje na to da programer
jo nije nauio "misliti" u Pascalu (jer je u nekim drugim programskim jezicima Goto neophodna
konstrukcija).

75
Ivan P. Stanimirovi Uvod u programiranje

5. POTPROGRAMI

U programiranju se esto javlja potreba da se neki deo programa vie puta ponovi u jednom
programu. Takoe, esto puta se ista programska celina javlja u vie razliitih programa. Ovakva
nepotrebna ponavljanja se izbegavaju pomou potprograma.
Potprogrami se uvek koriste sa idejom da se izbegne ponavljanje istih sekvenci naredbi u sluaju
kada u programu za to postoji potreba. Meutim, potprogrami su mnogo znaajniji kao sredstvo za
struktuiranje programa. Pri razradi programa metodom dekompozicije odozgo nanie, svaka
pojedinana aktivnost visokog nivoa moe da se zameni pozivom potprograma. U svakoj sledeoj
etapi ide se sve nie i nie u tom procesu dekompozicije sve dok se reenje kompleksnog programa ne
razbije na jednostavne procedure koje se konano implementiraju. Kako napredujemo u vetini
raunarskog programiranja, tako programe piemo u nizu koraka preciziranja. Pri svakom koraku
razbijamo na zadatak u vie podzadataka, definiui tako vie parcijalnih programa. Koncepti
procedure i funkcije omoguavaju da izloimo podzadatke kao konkretne potprograme.
Moe se rei da su potprogrami osnovno sredstvo apstrakcije u programiranju. Potprogramom se
definie skup izlaznih veliina u funkciji ulaznih veliina. Realizacija tih zavisnosti definisana je u
potprogramu.
Potprogrami se definiu kao programske celine koje se zatim po potrebi pozivaju i realizuju, bilo u
okviru istog programa u kome su i definisani, bilo u drugim programima.
Istaknimo neke opte karakteristike potprograma kakvi se najee sreu u savremenim
programskim jezicima.
(1) Svaki potprogram ima jednu ulaznu taku. Izuzetak od ovog pravila postoji jedino u
FORTRAN-u, gde je mogue definisati vie razliitih ulaza u potprogram.
(2) Program koji poziva potprogram prekida svoju aktivnost sve dok se ne zavri pozvani
potprogram. To znai da se u jednom trenutku izvrava samo jedan potprogram.
(3) Po zavretku pozvanog potprograma upravljanje se vraa programu koji ga je pozvao, i to na
naredbu koja sledi neposredno iza poziva potprograma.
Potprogram karakteriu sledei osnovni elementi:
ime potprograma,
lista imena i tipova argumenata (fiktivni argumenti),
lokalni parametri potprograma,
telo potprograma,
sredina (okruenje) u kojoj potprogram definisan.
Ime potprograma je uvedena re, odnosno identifikator, kojom se potprogram imenuje i kojim se
vri njegovo pozivanje.
Lista fiktivnih parametara: u nekim programskim jezicima ova lista moe da sadri samo imena
fiktivnih argumenata, ime je odreen njihov broj i redosled navoenja, Kod novijih programskih
jezika u listi argumenata se navode i atributi o tipu argumenata kao i o nainu prenoenja u
potprogram. Fiktivnim argumentima definie se skup ulazno-izlaznih veliina potprograma. Kod
poziva potprograma se fiktivni argumenti (parametri) zamenjuju stvarnim argumentima. Fiktivni i
stvarni argumenti moraju da se slau po tipu, dimenzijama i redosledu navoenja u listi argumenata.
Lokalni parametri. U samoj proceduri mogu da budu definisani lokalni elementi procedure i to
promenljive, konstante, oznake, a u nekim jezicima i drugi potprogrami.

76
Ivan P. Stanimirovi Uvod u programiranje

Telo potprograma ini sekvenca naredbi koja se izvrava nakon poziva potprograma. U telu
potprograma se realizuje kd potprograma.
Okolinu (okruenje) potprograma predstavljaju vrednosti globalnih promenljivih okruenja u
kome je potprogram definisan i koje se po mehanizmu globalnih promenljivih mogu koristiti u
potprogramu.
U programskim jezicima se obino sreu dva tipa potprograma:
funkcijski potprogrami (funkcije),
potprogrami opteg tipa (procedure).

5.1. Funkcije
Funkcijski potprogrami po konceptu odgovaraju matematikim funkcijama. Lista argumenata u
deklaraciji ovih potprograma se obino sastoji se samo od ulaznih argumenata, na osnovu kojih se u
telu potprograma izraunava vrednost koja se prenosi u pozivajuu programsku jedinicu. Ulazne
vrednosti se u funkciji ne menjaju.
U jezicima Pascal i FORTRAN se za prenoenje vrednosti iz potprograma u pozivajuu jedinicu
koristi promenljiva koja se identifikuje sa imenom funkcije. U telu takvih funkcija mora da postoji bar
jedna naredba dodele kojom se rezultat dodeljuje imenu funkcije. Kae se da funkcija prenosi vrednost
u glavni program preko svog imena.
U novijim programskim jezicima obino postoji naredba return kojom se eksplicitno navodi
vrednost koja se iz potprograma prenosi u glavni program. Naredba return se koristi u jeziku C. U
jeziku C se ne koristi re function, jer su svi potprogrami funkcije. Ako funkcija vraa jedan rezultat
naredbom return ispred njenog imena se pie tip rezultata, inae se pie slubena re void.
Funkcijski potprogrami se pozivaju slino matematikim funkcijama, tako to se u okviru izraza
navede ime funkcije sa imenima stvarnih parametara umesto fiktivnih. Koristei gore navedene
primere, suma prvih 999 celih brojeva se moe izraunati pozivom funkcije SUM na sledei nain:
SUMA := SUM(999) (Pascal)
ili
SUMA = SUM(999) (C, FORTRAN).
Funkcija se koristi u sluaju kada se vraa jedna veliina u rezultujuu programsku jedinicu.

5.1.1. Poziv i definicija funkcija u C


Program se sastoji iz jedne ili vie funkcija, pri emu se jedna od njih naziva main(). Kada
programska kontrola naie na ime funkcije, tada se poziva ta funkcija. To znai da se programska
kontrola prenosi na pozvanu funkciju. Kada se funkcija zavri upravljanje se prenosi u pozivajuu
programsku jedinicu. Izvrenje programa poinje sa main().
Funkcije se dele u dve grupe: funkcije koje vraaju vrednost u pozivajuu programsku jedinicu i
funkcije koje ne vraaju vrednost.
Za svaku funckiju moraju se definisati sledei elementi:
- tip vrednosti koju funkcija vraa,
- ime funkcije,
- lista formalnih parametara,
- deklaracija lokalnih promenljivih,
- telo funkcije.
Opta forma definicije funkcija je:
tip ime(lista_parametara)
{ deklaracije lokalnih promenljivih
operator1

77
Ivan P. Stanimirovi Uvod u programiranje


operatorN
}

Deo definicije koji se nalazi pre prve zagrade '{' naziva se zaglavlje funkcijske definicije, a sve
izmeu velikih zagrada se naziva telo funkcijske definicije.
Tip funkcije zavisi od tipa vrednosti koja se vraa. Takoe, koristi se slubena re void ako funkcija
ne vraa vrednost. Ako je tip rezultata izostavljen podrazumeva se int.
Parametri su po sintaksi identifikatori, i mogu se koristiti u telu funkcije (formalni parametri).
Navoenje formalnih parametara nije obavezno, to znai da funkcija moe da bude bez formalnih
parametara.
Poziv funkcije koja daje rezultat realizuje se izrazom
ime(spisak_stvarnih_parametara)
koji predstavlja element drugih izraza. U sluaju da funkcija ne vraa rezultat, dopisuje znak `;', ime
poziv funkcije postaje operator:
ime(spisak_stvarnih_parametara);
Izmeu formalnih i stvarnih parametara mora da se uspostavi odreena korespodencija po broju,
tipu i redosledu.
Kada se formalni parametri definiu u zaglavlju funkcije, tada se za svaki parametar posebno
navodi tip. Tada je zaglavlje funkcije sledeeg oblika:
tip ime(tip param1,...,tip paramn)
U programskom jeziku C, formalni parametri se mogu deklaristati ispod zaglavlja funkcije. Tada se
svi parametri istog tipa mogu deklarisati odjednom, koristei jedinstveno ime tipa.
Return naredba
Meu operatorima u telu funkcije moe se nalaziti operator return, koji predstavlja operator
povratka u pozivajuu funkciju. Ako se operator return ne navede, funkcija se zavrava izvrenjem
poslednjeg operatora u svom telu, i ne vraa rezultat.
Naredba return se koristi iz dva razloga:
- Kada se izvri naredba return, kontrola toka programa se vraa u pozivajuu jedinicu.
- Osim toga, ako neki izraz sledi iza kljune rei return, tj. ako se naredba return koristi u obliku
return izraz ili return(izraz), tada se vrednost izraza izraz vraa u pozivajuu programsku
jedinicu. Ova vrednost mora da bude u skladu sa tipom funkcije u zaglavlju funkcijske definicije.
Naredba return u jeziku C ima jednu od sledee dve forme:
return;
ili
return(izraz); odnosno return izraz;

Na primer, moe se pisati


return(3);
return(a+b);
Dobra je praksa da se izraz ija se vrednost vraa pie izmeu zagrada.
Opti oblik definicije funkcije:
<povratni_tip|void> ime(<tip> par1, <tip> par2, , <tip> parN)
{ <lokalne promenljive>
<blok instrukcija>
Return <povratna vrednost> // Izostavlja se ako je funkcija tipa void
}

78
Ivan P. Stanimirovi Uvod u programiranje

Primer. Uzmimo kao primer funkciju za izraunavanje sume prvih n prirodnih brojeva. Radi
poreenja isti potprogram napisan je u razliitim programskim jezicima:
Pascal
function SUM (n: integer) : integer;
var i, POM : integer; { Opis lokalnih promenljivih }
begin { Telo funkcije }
POM := 0:
for i := 1 to n do POM := POM + i;
SUM := POM {Vrednost koja se prenosi u glavni program}
end;
FORTRAN
INTEGER FUNCTION SUM(N)
INTEGER N
DO 10 I = 1, N
10 SUM = SUM + I
END
PROGRAM SUMA
INTEGER S,N
READ(*,10)N
10 FORMAT(I2)
S=SUM(N)
WRITE(*,20)S
20 FORMAT(I4)
C
#include<stdio.h>
int SUM (int n)
{ int POM = 0;
for(int i = 1; i <= n; i++)POM = POM + i ;
return POM;
}
void main()
{ int n;
scanf("%d",&n); printf("%d\n",SUM(n));
}
Prototip funkcije
U tradicionalnom stilu C jezika, funkcija se moe koristiti pre nego to je definisana. Definicija
funkcije moe da sledi u istom ili u nekom drugom fajlu ili iz biblioteke. Nepoznavanje broja
argumenata odnosno tipa funkcije moe da uzrokuje greke. Ovo se moe spreiti prototipom funkcije,
kojim se eksplicitno ukazuje tip i broj parametara koje funkcija zahteva i tip rezultujueg izraza. Opta
forma prototipa funkcije je sledea:
tip ime (lista_tipova_parametara);
U ovom izrazu je lista_tipova_parametara lista tipova odvojenih zarezima. Kada je funkcija pozvana,
argumenti se konvertuju, ako je mogue, u navedene tipove.
Na primer, sintaksno su ispravni sledei prototipovi:
void poruka1(int);
int min(int, int);
Takoe, prototip funkcije moe da ukljui i imena parametara, ime se moe obezbediti dodatna
dokumentacija za itaoca.
Na primer, moemo pisati
double max(duble x, double y);

Primeri

79
Ivan P. Stanimirovi Uvod u programiranje

Primer. Izraunati minimum dva cela broja. Funkcija min(x,y) vraa rezultat tipa int, te se eksplicitno
navoenje tipa rezultata moe izostaviti. U pozivajuoj funkciji (u ovom sluaju je to funkcija main())
naveden je prototip funkcije min.
#include<stdio.h>
void main()
{ int min(int,int);
int j,k,m;
printf("Unesi dva cela broja: ");scanf("%d%d",&j,&k);
m=min(j,k); printf("\n%d je minimum za %d i %d\n\n", m,j,k);
}
min(int x,int y)
{ if (x<y) return(x); else return(y); }

Primer. Minimum i maksimum sluajnih brojeva.


#include<stdio.h>
#include<stdlib.h>
void main()
{ int n;
void slucajni(int);
printf("Koliko slucajnih brojeva?"); scanf("%d",&n);
slucajni(n);
}

void slucajni(int k)
{ int i,r,mini,maxi;
int min(int, int), max(int, int);
srand(10);
r=mini=maxi=rand(); printf("%d\n",r);
for(i=1;i<k;++i)
{ r=rand();printf("%d\n",r);
mini=min(r,mini);maxi=max(r, maxi);
}
printf("Minimum: %7d\n Maximum:%7d\n", mini,maxi);
}
int min(int i, int j)
{ if(i<j) return(i); else return(j); }
int max(int i, int j)
{ if(i>j) return(i); else return(j); }
Primer. Izraunavanje broja kombinacija m-te klase od n elemenata po formuli
n n!
m
m!(n m)!
Pascal
program fakt1;

var m,n:integer;
bk:longint;

function fakt(k:integer):longint;
var i:integer; p:longint;
begin
p:=1;
for i:=2 to k do p:=p*i;
fakt:=p;
end;

begin
readln(n,m);
bk:=fakt(n) div fakt(m) div fakt(n-m);
writeln('Broj kombinacija je ',bk);

80
Ivan P. Stanimirovi Uvod u programiranje

end.
C
#include<stdio.h>
void main()
{ int m,n; long bk;
long fakt(int);
scanf("%d%d",&n,&m);
bk=fakt(n)/fakt(m)/fakt(n-m);
printf("Broj kombinacija je %ld\n",bk);
}

long fakt(int k)
{ int i; long p=1;
for(i=2; i<=k; i++) p*=i;
return(p);
}
Izraunavanje vrednosti n! se moe izdvojiti u posebnom potprogramu. Tada se prethodno napisani
potprogrami mogu napisati na sledei nain.
Pascal (II nain)
program fakt2;

var m,n:integer;
bk:longint;

function komb(p,q:integer):longint;
function fakt(k:integer):longint;
var i:integer;
p:longint;
begin {fakt}
p:=1;
for i:=2 to k do p:=p*i;
fakt:=p;
end;
begin {komb}
komb:= fakt(p) div fakt(q) div fakt(p-q)
end;

begin
readln(n,m);
bk:=komb(n,m); writeln('Broj kombinacija je ',bk);
end.
C (II nain)
#include<stdio.h>
void main()
{ int m,n; long bk;
long komb(int, int);
scanf("%d%d",&n,&m);
bk=komb(n,m); printf("Broj kombinacija je %ld\n",bk);
}

long komb(int p, int q)


{ long fakt(int);
return fakt(p)/fakt(q)/fakt(p-q);
}

long fakt(int k)
{ int i; long p=1;
for(i=2; i<=k; i++) p*=i;
return(p);
}

81
Ivan P. Stanimirovi Uvod u programiranje

Primer. Izraunati
x3 x5 x 2 n1
sin( x) x ... (1) n1 ...
3! 5! (2n 1)!
Sumiranje prekinuti kada se ispuni uslov |a/S| <= , gde je zadata tanost, S predstavlja tekuu
vrednost sume, dok a predstavlja vrednost lana koji se dodaje.
#include<stdio.h>
void main()
{ double x,eps;
double sinus(); scanf("%lf%lf",&x,&eps);
printf("Sinus je %lf\n", sinus(x,eps));
}

/* apsolutna vrednost */
double abs(x) { return (x>0)?x:-x; }

/* sinus */
double sinus(double x, double eps)
{ double sum, clan; int k; clan=x; k=0; sum=clan;
while(abs(clan)>eps*abs(sum))
{ k+=1; clan*=-(x*x)/(2*k*(2*k+1)); sum+=clan; }
return(sum);
}

Primer. Svi prosti brojevi do datog prirodnog broja n.


#include<stdio.h>
#include <math.h>
int prost(int k)
{ int i=3;
if(k%2==0) return(0);
if(k==3) return(1);
while((k%i!=0) && (i<=sqrt(k))) i+=2;
if(k%i==0) return(0); else return(1);
}

void main()
{ int i,n; int prost(int);
printf("Dokle? "); scanf("%d", &n);
for(i=3; i<=n; i++) if(prost(i)==1) printf("%d\n",i);
}

Primer. Trocifreni brojevi jednaki sumi faktorijela svojih cifara


#include<stdio.h>
long fakt(int k)
{ long f=1,i=1;
for(;i<=k;i++) f*=i;
return(f);
}

void main()
{ long i; unsigned a,b,c;
for(i=100;i<=999;i++)
{ a=i%10; b=i%100/10; c=i/100;
if(fakt(a)+fakt(b)+fakt(c)==i) printf("%d\n",i);
}
}

Primer. Unositi prirodne brojeve dok se ne unese vrednost <=0. Izraunati NZS unetih brojeva.
void main()
{int k,ns,nzs=0; scanf("%d", &k);
if(k<=0) printf("%d\n",nzs);

82
Ivan P. Stanimirovi Uvod u programiranje

else
{ ns=nzs=k; scanf("%d", &k);
while(k>0)
{nzs=funnzs(ns,k); ns=nzs; scanf("%d",&k); };
printf("nzs = %d\n",nzs);
} }
int funnzs(int a, int b)
{ int nz;
if(a>b)nz=a;
else nz=b;
while( ((nz % a) !=0) || ((nz % b)!=0) ) nz++;
return(nz);
}

Primer. Dekadni broj iz intervala [0, 3000] prevesti u rimski brojni sistem.
#define hi 'M'
#define ps 'D'
#define st 'C'
#define pd 'L'
#define ds 'X'
#define pe 'V'
#define je 'I'

void rim(int);
void main()
{ int n;
printf("Unesi prirodan broj -> "); scanf("%d", &n);
printf("\nOdgovarajuci rimski broj je: ");
rim(n); printf("\n");
}

void rim(int n)
{ while(n>= 1000) { printf("%c",hi); n-=1000; }
if(n>=900) {printf("%c",st); printf("%c",hi); n-=900;}
if(n>= 500) { printf("%c",ps); n-=500; }
if(n>=400)
{ printf("%c",st); printf("%c",ps); n-=400; }
while(n>=100) { printf("%c",st); n-=100; }
if(n>=90)
{ printf("%c",ds); printf("%c",st); n-=90; }
if(n>= 50) { printf("%c",pd); n-=50; }
if(n>=40)
{ printf("%c",ds); printf("%c",ps); n-=40; }
while(n>= 10) { printf("%c",ds); n-=10; }
if(n==9)
{ printf("%c",je); printf("%c",ds); n-=9; }
if(n>= 5) {printf("%c",pe); n-=5; }
if(n==4) {printf("%c",je); printf("%c",pe); n-=4; }
while(n>=1) { printf("%c",je); n--; } }

Primer. Najblii prost broj datom prirodnom broju.


#include<stdio.h>
int prost(int n)
{ int i=2,prosti=1;
while ((i<=(n/2))&&(prosti)) {prosti=(n%i)!=0; i++;}
return(prosti); }

void main()
{int m,n,i=1,prosti=1; int prost(int n);
printf("Broj za koji se racuna najblizi prost broj");
scanf("%d",&m);

83
Ivan P. Stanimirovi Uvod u programiranje

if(m==1) printf("najblizi prost broj je 2\n");


else if (prost(m))
printf("najblizi prost broj je%d\n",m);
else
{ while (i<=(m-1)&&(prosti))
{ if (prost(m+i))
{ prosti=0; printf("najblizi prost je%d\n",(m+i)); }
if(prost(m-i) && (!prosti))
{prosti=0; printf("najblizi prost je %d\n",(m-i)); }
i++;
} }
getch();
}

5.1.2. Makroi u jeziku C


Makro je ime kome je pridruena tekstualna definicija. Postoje dve vrste makroa: makro kao
objekat (koji nema parametre) i makro kao funkcija (koji ima parametre).
Primer. Primeri makroa kao objekata.
#define OPSEG "Greska: Ulazni parametar van opsega"
Makro kao funkcija se definie izrazom oblika
#define ime(lista_identifikatora) tekst_zamene
Pri definiciji makroa definie se lista njegovih formalnih parametara, dok se prilikom pozivanja
makroa koriste stvarni parametri.
Primer. Makro kojim se ispituje da li je njegov argument paran broj.
#define NETACNO 0
#define TACNO 1
#define PARAN(broj) broj%2 ? NETACNO : TACNO
void main()
{ int n1=33;
if(PARAN(n1)) printf("%d je paran\n",n1);
else printf("%d je neparan\n",n1);
}
U pozivu makroa paran(a+b) ispituje se parnost broja a+b pomou izraza a+b%2 umesto izraza
(a+b)%2. Da bi se ovakve greke izbegle, potrebno je da se formalni parametri piu izmeu zagrada.
U naem sluaju, pravilna je sledea definicija makroa PARAN:
#define PARAN(broj) ((broj)%2) ? NETACNO : TACNO

5.2. Procedure
Procedurama se definiu potprogrami opteg tipa, kojima se moe realizovati svaki algoritam koji
sm za sebe ima odreeni smisao. Procedurama se obino u glavni program prenosi jedan ili skup
rezultata.
Opis potprograma opteg tipa obino ima sledeu strukturu:
procedure IME_PROCEDURE (Lista argumenata)
Opisi lokalnih promenljivlh;
Telo procedure
end;
Opis poinje nekom kljunom rei kojom se eksplicitno navodi da definiemo proceduru. U
mnogim programskim jezicima koristi se re procedure, mada ima i izuzetaka, na primer u
FORTRAN-u se koristi SUBROUTINE. Identifikator IME_PROCEDURE je uvedena re kojom se
imenuje potprogram. Ime potprograma se koristi za poziv potprograma. Za razliku od funkcija, lista

84
Ivan P. Stanimirovi Uvod u programiranje

argumenata kod procedura moe da sadri ulazne, izlazne i ulazno-izlazne argumente. Obino se
zahteva da se u listi argumenata navede njihov tip i nain prenoenja vrednosti izmeu glavnog
programa i potprograma. U Adi na primer, argumenti mogu da budu ulazni, izlazni i ulazno-izlazni to
se eksplicitno navodi reima in, out i inout uz odgovarajue argumente.
Deklaracija procedure slui da definie programski deo i da ga pridrui identifikatoru, tako da se
moze aktivirati procedurnim iskazom. Deklaracija ima isti oblik kao i program, osim to zapoinje
zaglavljem procedure umesto zaglavljem programa.

5.3. Prenos argumenata


Funkcije i procedure se koriste tako to se tamo gde je potrebno u kdu programa, pozivaju sa
spiskom stvarnih argumenata. Pri tome stvarni argument zamenjuju fiktivne. Prenos argumenata
izmeu glavnog programa i potprograma moe da se ostvari na vie razliitih naina. Semanticki
posmatrano, to moe da bude po jednom od tri semantika modela. Potprogram moe da primi
vrednost od odgovarajueg stvarnog parametra (koji se stavlja na mesto ulaznog parametra), moe da
mu preda vrednost (ako se postavlja na mesto izlanog formalnog parametra) ill da primi vrednost i
preda rezultat glavnom programu (kada se stvarni parametar postavlja na mesto ulazno-izlaznog
parametra). Ova tri semantika modela nazivaju se in, out i inout, respektivno i prikazana su na slici.
Sa druge strane, postoje dva konceptualna modela po kojima se ostvaruje prenos parametara izmeu
glavnog programa i potprograma. Po jednom, vrednosti parametara se fiziki prebacuju (iz glavnog
programa u potprogram ili u oba smera), a po drugom prenosi se samo informacija o tome gde se
nalazi vrednost stvarnog parametra. Najee je to jednostavno pokaziva (pointer) na memorijsku
lokaciju parametra.

5.3.1. Prenos po vrednosti (Call by Value)


Sastoji se u tome to se pri pozivu funkcije vrednosti stvarnih argumenata kopiraju u pomone
memorijske lokacije fiktivnih argumenta koje su definisane u potprogramu. Funkcija preuzima kopije
vrednosti stvarnih parametara, dok su originali yatieni od promena. Zbog toga se ova tehnika
prenosa moe koristiti samo za prenos ulaznih argumenata potprograma, a ne i za vraanje rezultata
glavnom programu. Razmotrimo situaciju koja nastane kada se potprogram PP sa argumentima x i y
pozove sa stvarnim argumentima p i q. To znai imamo deklaraciju potprograma oblika
PP(x,y:integer) i njegov poziv PP(p,q). Za smetaj vrednosti parametara x i y u potprogramu su
rezervisane memorijske lokacije promenljivih p i q, iji je sadraj u trenutku prevoenja potprograma
nedefinisan. U glavnom programu, sa druge strane, postoje memorijske lokacije za smetaj stvarnih
vrednosti p i q. Vrednosti ovih memorijskih lokacija moraju da budu definisane pre poziva
potprograma. Kada se pozove potprogram, vri se kopiranje vrednosti iz memorijskih lokacija p i q u
lokacije fiktivnih argumenata x i y u potprogramu, to je ilustrovano na slici.
Glavni program Funkcija

85
Ivan P. Stanimirovi Uvod u programiranje

Osnovni nedostatak prenosa po vrednosti je u tome to se za formalne parametre potprograma


rezervie memorijski prostor. Uz to i sama operacija kopiranja vrednosti moe da utie na efikasnost
programa. Ovi nedostaci posebno dolaze do izraaja kada se prenose strukture podataka, kao na primer
veliki vektori i matrice.
Obino se u okviru programskih jezika implicitno ili eksplicitno navodi da se argumenti prenose po
vrednosti. U Algolu se to postie pomou rei value, u Adi sa in, dok se u Pascal-u ovaj nain
podrazumeva kada nije navedeno var uz sekciju formalnih argumenata. U FORTRAN-u se argumenti
prenose po vrednosti kada su stavljeni izmeu kosih crta. U jeziku C se prenos po vrednosti
podrazumeva za sve parametre koji nisu pokazivai.
Prenos parametara po vrednosti u C
Funkcija se moe pozvati stavljajui posle njenog imena odgovarajuu listu stvarnih argumenata
izmeu zagrada. Ovi argumenti se moraju slagati sa brojem i tipom formalnih parametara u definiciji
funkcije. Svaki argument se izraunava, i njegova vrednost se uzima umesto formalnog parametra.
Meutim, vrednost stvarnog parametra ostaje nepromenjena u pozivajuoj programskoj jedinici. Kada
se koristi poziv po vrednosti, u momentu kada se koristi izraz kao stvarni argument funkcije, pravi se
kopija njegove vrednosti, i ona se koristi u funkciji. Pretpostavimo da je v promenljiva, a f() funkcija.
Tada poziv funkcije f(v) ne menja vrednost promenljive v u funkciji f, jer se koristi kopija vrednosti v
u funkciji f().
Poziv po vrednosti je ilustrovan sledeim primerom.

Primer. Pronai sve brojeve-blizance do zadatog broja n. Dva broja su blizanci ako su prosti i
razlikuju se za 2.
#include<stdio.h>
#include<math.h>
void main()
{ int n,i;
int prost(int);
scanf("%d",&n);
for (i=3;i<=n;i++)
if ((prost(i)) && (prost(i-2))) printf("%d %d\n",i-2,i);

86
Ivan P. Stanimirovi Uvod u programiranje

int prost(int k)
{ int i=2,prosti=1;
while((i<=sqrt(k)) && (prosti)) { prosti=((k%i)!=0); i++; }
return(prosti);
}

U nekim drugim programskim jezicima (FORTRAN), takav poziv funkcije moe da promeni
vrednost za v. Mehanizam izvren u tom sluaju se naziva poziv po adresi (call by Reference). Da bi
se u C postigao efekat poziva po adresi moraju se koristiti pointeri promenljivih u listi parametara
prilikom definisanja funkcije, kao i adrese promenljivih koje su argumenti u pozivu funkcije.

5.3.2. Prenos po rezultatu (Call by Result)


Prenos po rezultatu je tehnika koji se primenjuje za prenos izlaznih (out) parametara u jeziku Ada.
Kada se argumenti prenose po rezultatu, njihove vrednosti se izraunavaju u lokalnim memorijskim
lokacijama formalnih argumenata potprograma, pri emu nema prenosa vrednosti parametara iz
glavnog programa u potprogram. Meutim, pre nego to se upravljanje tokom izvrenja prenese u
glavni program, ove vrednosti se kopiraju u memorijske lokacije stvarnih argumenata. Stvarni
argumenti u ovom sluaju moraju da budu promenljive. Kao i kod prenosa po vrednosti, za fiktivne
argumente potprograma rezerviu se lokalne memorijske lokacije.
Kod ovog naina prenosa mogui su i neki negativni efekti, kao to je na primer kolizija stvarnih
argumenata, koja nastaje u sluajevima kada se potprogram poziva tako da isti stvarni argument
zamenjuje vie fiktivnih argumenata. Razmotrimo sledei primer u kome se potprogram definisan kao
procedure PP(x,y:real) poziva sa PP(p1,p1).U ovom primeru problem je u tome to se u
potprogramu aktuelni parametar p1 dobija vrednost iz dve razliite memorijske lokacije (koje
odgovaraju formalnim parametrima x i y). Nije unapred poznato koju e od ovih vrednosti argument
p1 imati po zavretku potprograma. To zavisi od toga koja je vrednost poslednji put dodeljena
stvarnom argumentu.

5.3.3. Prenos po vrednosti i rezultatu (Call by Value-Result)


Prenos po vrednosti i rezultatu je nain prenosa ulazno-izlaznih (inout) argumenata. To je u sutini
kombinacija prenosa po vrednosti i prenosa po rezultatu. Vrednosti stvarnih argumenta kopiraju se u
memorijske lokacije fiktivnih argumenata potprograma. To su lokalne memorijske lokacije
potprograma i sve izmene nad argumentima pamte se u ovim lokacijama. Pre vraanja upravljanja
glavnom programu, rezultati potprograma se iz ovih lokalnih memorijskih lokacija ponovo kopiraju u
memorijske lokacije stvarnih argumenata. Ovaj nain prenosa se esto naziva i prenos kopiranjem
(call by copy) jer se stvarni argumenti najpre kopiraju u potprogram, a zatim ponovnim kopiranjem
rezultati vraaju u glavni program.
Nedostaci i negativni efekti koji su prisutni kod prenosa po vrednosti i prenosa po rezultatu ostaju i
kod ovog naina prenosa.

5.3.4. Prenos po referenci (Call by Reference)


Kod ovog naina prenosa nema kopiranja vrednosti parametara iz glavnog programa u potprogram
ill obrnuto. U potprogram se samo prenosi referenca (obino samo adresa) memorijske lokacije u kojoj
je sauvana vrednost stvarnog argumenta. Efekat je kao da se reference stvarnih argumenata
preslikavaju u reference fiktivnih. Potprogam pristupa istim memorijskim lokacijama kojima i glavni
program, nema rezervisanja memorijskih lokacija za fiktivne argumente u okviru potprograma. Sve
promene nad argumentima koje se izvre u okviru potprograma neposredno su vidljive i u glavnom
programu. Zbog toga je ovo nain prenosa koji se koristi za prenos ulazno-izlaznih argumenata. U
mnogim programskim jezicima to je osnovni nain prenosa argumenata i podrazumeva se implicitno

87
Ivan P. Stanimirovi Uvod u programiranje

(Algol, FORTRAN). U Pascal-u se koristi uvek kada uz argumente stoji var. U jeziku C se za prenos
po referenci koriste pokazivai.
Glavni program Funkcija

Prednosti prenosa po referenci su u njegovoj efikasnosti kako u pogledu vremena tako i u pogledu
memorijskog prostora. Nema potrebe za dupliranja memorijskog prostora niti se gubi vreme u
kopiranju vrednosti argumenata iz jednih memorijskih lokacija u druge. Meutim, treba imati u vidu
da se ovaj prenos implementira indirektnim adresiranjem pa se tu ipak neto gubi na efikasnosti.
Takoe, mogui su i odreeni boni efekti u odreenim posebnim sluajevima poziva potprograma.
Razmotriemo neke od njih.
Kao u sluaju prenosa po rezultatu i ovde je mogua kolizija izmeu stvarnih argumenata. Uzmimo
na primer potprogram PP u Pascal-u sa dva argumenta koji se prenose po vrednosti, ija je deklaracija
oblika
procedure PP(var x,y: integer);
Ako se ovaj potprogram pozove tako da se oba fiktivna argumenta zamene istim stvarnim
parametrom, na primer sa PP(m, m); , dolazi do kolizije jer se oba fiktivna argumenta referenciraju na
istu memorijsku lokaciju stvarnog argumenta m.
Kod prenosa po referenci kolizija moe da nastane izmeu elemenata programa koji se prenose kao
stvarni argumenti potprograma i onih koji se prenose kao globalni parametri. Razmotrimo sledei
primer u Pascal-u:
program LocalGlobal;
var global: integer;
procedure PPG(var local: integer);
begin
local := local+1; writeln('global = ',global);local := local+global;
end;
begin
global := 2; PPG(global); writeln(global);
end.
Odgovarajui primer u jeziku C je predstavljen sledeim kdom:
#include<stdio.h>
int global;
void PPG(int *local)
{ (*local)++;
printf("global = %d\n",global);
*local = *local+global;
}

void main()
{ global = 2;
PPG(&global);
printf("%d\n",global);
}

88
Ivan P. Stanimirovi Uvod u programiranje

Posle poziva potprograma PPG bie odtampana vrednost je 6. Zaista, vrednost 2 dodeljena
promenljivoj global u potprogramu najpre koriguje naredbom local:=local+1; (posle ega je
global=3), a zatim i naredbom local:=local+global; (posle ega je local=global=3).
Promenljiva global se u potprogramu koristi i kao globalna promenljiva i kao stvarni argument, pa se i
promene argumenta potprograma i promene same promenljive global registruju u istoj memorijskoj
lokaciji. Napomenimo da bi u ovom primeru prenos sa kopiranjem (call by value-result) dao drugaiji
rezultat. U tom sluaju, vrednost stvarnog argumenta global kopira se u memorijsku lokaciju fiktivnog
argumenta local i u potprogramu se sve promene argumenta registruju u toj lokaciji. U prvoj naredbi
dodeljivanja promenljiva local dobija vrednost 3, a u drugoj se ova vrednost inkrementira za 2, to je
vrednost globalne promenljive global (dodeljena pre ulaska u potprogram). Time argument local
dobija vrednost 5, i to je vrednost koja se po zavretku potprograma kopira natrag u memorijsku
lokaciju stvarnog argumenta global. To znai da se u ovom sluaju tampa vrednost 5. Slina analiza
istog programa mogua je i za sluaj prenosa argumenta potprograma po vrednosti. U tom sluaju
vrednost stvarnog argumenta global se kopira u potprogram ali su sve promene u potprogramu
nevidljive za glavni program, pa se po zavretku potprograma tampa vrednost 2 koja je dodeljena
promenljivoj global pre poziva potprograma.
Poziv po adresi pomou pokazivaa u C
Deklaracije pointera i dodeljivanje

Pointeri se koriste za pristup memoriji i manipulaciju adresama. Vrednosti pokazivaa jesu adrese
promenljivih. Do sada smo ve videli upotrebu adresa kao argumenata u naredbi scanf(). Ako je v
promenljiva, tada je &v adresa (lokacija) u memoriji u kojoj je smetena vrednost za v. Operator & je
unarni, ima asocijativnost sdesna na levo, a prioritet kao i ostali unarni operatori. Pointerske
promenljive se mogu deklarisati u programu, a onda koristiti tako da uzimaju adrese za svoje
vrednosti.
Na primer, deklaracija
int *p;
deklarie promenljivu p tipa ''pointer na int''. Rang vrednosti svakog pointera ukljuuje posebnu
adresu 0, definisanu kao NULL u <stdio.h>, kao i skup pozitivnih celih brojeva koji se
interpretiraju kao mainske adrese.
Primer. Pointeru p se vrednosti mogu dodeljivati na sledei nain:.
p=&i;
p=0;
p=NULL; /* isto to i p=0; */
p=(int*)1507 /* apsolutna adresa u memoriji */ }
U prvom primeru p je ''pointer na i'', odnosno ''sadri adresu od i''. Trei i drugi primer
predstavljaju dodelu specijalne vrednosti 0 pointeru p. U etvrtom primeru kast je nuan da bi se
izbeglo upozorenje kompajlera, a koristi se aktuelna memorijska lokacija kao vrednost promenljive p.
Ovakve naredbe se ne koriste u korisnikim programima, ve samo u sistemskim.
Adresiranje i operator indirekcije
Neka su date deklaracije
int i, *p;
Tada naredbe
p=&i; scanf("%d",p);
uzrokuju da se sledea uneta vrednost smeta u adresu zadatu pointerom p. Ali, s obzirom da p
ukazuje na i, to znai da se vrednost smeta u adresu od i.
Operator indirekcije * je unarni i ima isti prioritet i asocijativnost sa desna ulevo kao i ostali unarni
operatori. Ako je p pointer, tada *p predstavlja vrednost promenljive na koju ukazuje p. Direktna
vrednost za p je memorijska lokacija, dok je *p indirektna vrednost od p, tj. vrednost memorijske
lokacije sadrane u p. U sutini, * je inverzni operator u odnosu na operator &.

89
Ivan P. Stanimirovi Uvod u programiranje

Na taj nain, pointeri se mogu koristiti za dodelu vrednosti nekoj promenljivoj. Na primer, neka su
date deklaracije
int *p,x;

Tada se izrazima
p=&x; *p=6;
promenljivoj x dodeljuje vrednost 6.
Primer. Uoimo deklaracije
float x,y, *p;
i naredbe
p = &x; y=*p;
Prvom naredbom se adresa od x pridruuje pointeru p, a drugom se vrednost na koju ukazuje p
dodeljuje y. Ove dve naredbe su ekvivalentne sa
y=*&x;
odnosno
y=x.
Primer. Ilustracija pokazivaa.

Primer. Neka je dat sledei kd:


char c1,c2='A',*p,*q;
p=&c1; q=&c2; *p=*q;
Adrese od c1 i c2 pridruuju se promenljivima p i q u prva dva izraza. Poslednja naredba izjednauje
vrednost na koju ukazuje p i vrednost na koju ukazuje q. Ove tri naredbe su ekvivalentne sa c1=c2.

Primer.
void main()
{ int i=777,*p;
p=&i; printf("Vrednost za i:%d\n",*p);
printf("Adrese za i: %u ili %p\n",p,p);
}

Formati %u i %p se koriste za prikazivanje vrednosti promenljive p u obliku neoznaenog


decimalnog broja, odnosno heksadecimalnog broja, respektivno.
Primer. Izrazima
int i=777, *p=&i;
je inicijalizovano p, a ne *p. Promenljiva p je tipa ''pointer na int'', i njena poetna vrednost je &i.
Primer.
#include <stdio.h>
void main()
{ int x=7, y=10;

90
Ivan P. Stanimirovi Uvod u programiranje

printf("x=%d &x=%p\n", x,&x);


printf("y=%d &y= %p%u\n",y,&y, &y);
}

void main()
{ int i=5, *pi=&i; printf("i= %d ili = %d\n", i, *pi); }

Primer. Postoji velika razlika izmeu

Using pointers allows us to:


Achieve call by reference (i.e. write functions which change their parameters)
Handle arrays efficiently
Handle structures (records) efficiently
Create linked lists, trees, graphs etc.
Put data onto the heap
Create tables of functions for handling Windows events, signals etc.
Call by reference (poziv po adresi) koristei pokazivae
Prenos vrednosnih parametara je pogodan kada funkcija vraa jednu izlaznu veliinu bez izmene
svojih stvarnih parametara. Meutim, kada je potrebno da funkcija menja vrednosti svojih stvarnih
parametara, ili ukoliko funkcija vraa vie izlaznih veliina, moe se koristiti druga tehnika predaje
parametara: prenos adrese stvarnih parametara.
Adrese promenljivih se mogu koristiti kao argumenti funkcija u cilju izmene zapamenih vrednosti
promenljivih u pozivajuoj programskoj jedinici. Tada se pointeri koriste u listi parametara pri
definisanju funkcije. Kada se funkcija poziva, moraju se koristiti adrese promenljivih kao argumenti.

91
Ivan P. Stanimirovi Uvod u programiranje

Primer. Primer u jeziku C kojim se ilustruju globalna promenljiva i prenos po adresi. Rezultat je kao
u sluaju prenosa po adresi.
#include<stdio.h>
int global;
void PPG(int *local)
{ (*local)++; printf("global = %d\n",global); *local = *local+global;}
void main()
{ global = 2; PPG(&global); printf("%d\n",global); }

Primer. Date su vrednosti za dve celobrojne promenljive i i j. Urediti ih u poredak i<= j.


#include <stdio.h>
void upis(int *x, int *y);
void sredi(int *x, int *y);
void ispis(int x,int y);
void main()
{ int x,y;
upis(&x,&y); sredi(&x,&y); ispis(x,y);
}

void upis(int *x, int *y)


{ printf("Unesi dva cela broja"); scanf("%d%d",x,y); }

void sredi(int *x, int *y)


{ int pom;
if(*x>*y) { pom=*x; *x=*y; *y=pom; }
}

void ispis(int x, int y)


{ printf("\n To su brojevi %d %d\n",x,y); }

Tehnika predaje parametara po adresi (Call by reference) se sastoji iz sledeih baznih pravila:
1. deklarisati formalne parametre funkcije kao pointere;
2. koristiti operatore indirekcije u telu funkcije;
3. pri pozivu funkcije koristiti adrese kao argumente.
Kako sredi() radi sa pokazivaima? Kada predajete pokaziva, predajete adresu objekta i tako
funkcija moe manipulisati vrednou na toj adresi. Da bi sredi() promenila stvarne vrednosti,

92
Ivan P. Stanimirovi Uvod u programiranje

korienjem pokazivaa, funkcija sredi(), trebalo bi da bude deklarisana da prihvata dva int
pokazivaa. Zatim, dereferenciranjem pokazivaa, vrednosti x i y e, u stvari, biti promenjene.
Primer. Predavanje po referenci koricenjem pokazivaa.
1: // Prenos parametara po referenci
2:
3: #include <iostream.h>
4:
5: void swap(int *x, int *y);
6:
7: int main()
8: {
9: int x = 5, y = 10;
10:
11: cout << "Main. Pre swap, x:<<x<<" y: "<<y<<"\n";
12: swap(&x,&y);
13: cout<<"Main. Posle swap., x: "<<x<<" y: "<<y<<"\n";
14: return 0;
15: }
16:
17: void swap(int *px, int *py)
18: {
19: int temp;
20:
21: cout<<"Swap. Pre swap, *px: "<<*px<<" *py:"<<*py<<"\n";
22:
23: temp = *px;
24: *px = *py;
25: *py = temp;
26:
27: cout<<"Swap. Posle swap, *px: "<<*px<<" *py: "<<*py<<"\n";
28:
29: }
Izlaz:
Main. Pre swap, x:5 y: 10
Swap. Pre swap, *px: 5 *py:10
Swap. Posle swap, *px: 10 *py:5
Main. Posle swap, x:10 y: 5
U liniji 5 prototip funkcije swap() pokazuje da e njegova dva parametra biti pokazivai na int, a ne
int promenljive, Kada se pozove swap() u liniji 12, kao argumenti se predaju adrese od x i y. U liniji
19 lokalna promenljiva, temp, deklarisana je u funkciji swap() - nije potrebno da temp bude pokaziva;
ona e uvati samo vrednost od *px (to jest, vrednost promenljive x u pozivajuoj funkciji), tokom
ivota funkcije. Posle povratka iz funkcije, promenljiva temp vie nee biti potrebna.
U liniji 23 promenljivoj temp se dodeljuje vrednost memorijske lokacije koja je jednaka vrednosti
pokazivaa px. U liniji 24 vrednost na adresi px se dodeljuje vrednosti na adresi py. U liniji 25
vrednost uvana u temp (to jest, originalna vrednost na adresi px) stavlja se u adresu py.
Efekat ovoga je da e vrednosti u pozivajuoj funkciji, ije su adrese predate funkciji swap(), biti
zamenjene.
Prenos po referenci koristei reference u C++

Prethodni program radi, ali sintaksa funkcije swap() je problematina zbog dve stvari. Prvo,
ponavljajua potreba za dereferenciranjem pokazivaa unutar funkcije swap() ini je podlonom
grekama i tekom za itanje. Drugo, potreba da se preda adresa promenljivih u pozivajuoj funkciji
ini unutranji rad funkcije swap() vie nego oiglednim za korisnike.

93
Ivan P. Stanimirovi Uvod u programiranje

Cilj C++ je da sprei korisnika funkcije da se brine o tome kako ona radi. Zbog toga se prenos po
adresi u C++ moe uraditi pomou referenci.
Primer.
#include<iostream.h>
void f(int i, int &j){ // i je poziv po vrednosti, j po referenci
i++; // stvarni argument si se nee promeniti
j++; // stvarni argument sj e se promeniti
}
void main () {
int si=0,sj=0;
f(si,sj);
cout<<"si="<<si<<", sj="<<sj<<endl;
}
Izlaz: si=0, sj=1

Primer. Prepisana funkcija swap() sa referencama.


1: //Predavanje po referenci
2: // korienjem referenci!
3:
4: #include <iostream.h>
5:
6: void swap(int &rx, int &ry);
7:
8: int main()
9: {
10: int x = 5, y = 10;
11:
12: cout<<"Main. Pre swap, x: "<<x<<" y: "<<y<<"\n";
13: swap(x,y);
14: cout<<"Main. Posle swap, x: "<<x<<" y: "<<y<<"\n";
15: return 0;
16: }
17:
18: void swap (int &rx, int &ry)
19: {
20: int temp;
21:
22: cout<<"Swap. Pre swap, rx: "<<rx<<" ry: "<<ry<<"\n";
23:
24: temp =rx;
25: rx =ry;
26: ry =temp,
27:
28: cout<<"Swap. Posle swap, rx: "<<rx<<" ry: "<<ry<<"\n";
29:
30: }
Rezultat je isti kao u prethodnom primeru.
Kao i u primeru si pokazivaima, deklarisane su dve promenljive u liniji 10, a njihove vrednosti se
tampaju u liniji 12. U liniji 13 poziva se funkcija swap(), ali uoite da se predaju x i y, a ne njihove
adrese. Pozivajua funkcija main() jednostavno predaje promenljive, kao i u sluaju poziva po
vrednosti.
Kada se pozove swap(), izvrenje programa "skae" na liniiju 18, gde se promenljive rx i ry
identifikuju kao reference. Njihove vrednosti se tampaju u liniji 22, ali uoite da se za tampanje ne
zahtevaju posebni operatori. Promenljive rx i ry su alijasi za originalne vrednosti i mogu se samostalno
koristiti.

94
Ivan P. Stanimirovi Uvod u programiranje

U linijama 24-26 vrednosti se zamenjuju, a onda se tampaju u liniji 28, Izvrenje programa
"skae" u pozivajuu funkcuju i u liniji 14 vrednosti se tampaju u main(). Zato to su parametri za
swap() deklarisani kao reference, vrednosti iz main() se predaju po referenci i time se, takoe, menjaju
i u main().
Reference obezbeuju pogodnost i lakou upotrebe normalnih promenljivih, sa snagom i
sposobnou predavanja po referenci koju imaju pokazivai.
Primer. Prenos parametra na dva naina.
#include<iostream.h>
int* f(int* x) {
(*x)++;
return x; // Vrednost za x se prenosi u stvarni parametar
}

int& g(int& x) {
x++; // Isti efekat kao u f()
return x; // Vrednost za x se prenosi u stvarni parametar
}

int main() {
int a = 0;
f(&a); // Runo, ali eksplicitno
cout << "a = " << a << "\n";
g(a); // Jasno, ali sakriveno
cout << "a = " << a << "\n";
return 0;
}
Primer. Modifikacija prethodnog primera, koja se sastoji u upotrebi pokazivaa p. Naredbom
p=f(&a); identifikovani su p i &a.

#include<iostream.h>
int* f(int* x) {
(*x)++;
return x; // Vrednost za x se prenosi u stvarni parametar
}

int& g(int& x) {
x++; // Isti efekat kao u f()
return x; // Vrednost za x se prenosi u stvarni parametar
}

void main() {
int a = 0,*p;
p=f(&a); // Runo, ali eksplicitno
cout << "a = " << a << "\n"; //a=1
cout << "*p = " << *p << "\n"; //*p=1
g(a); // Jasno, ali sakriveno
cout << "a = " << a << "\n"; //a=2
cout << "*p = " << *p << "\n"; // *p=2
}
Vraanje viestrukih vrednosti
Kao to je reeno, pomou naredbe return funkcije mogu vratiti samo jednu vrednost. ta uiniti
ako je potrebno da vratite dve vrednosti iz funkcije? Jedan nain da reite ovaj problem je da funkciji
predate objekte po referenci. Kako predavanje po referenci dozvoljava funkciji da promeni originalne
objekte, ovo efektno dozvoljava funkciji da vrati vie informacija. Povratna vrednost funkcije se moe
rezervisati za izvetavanje o grekama.

95
Ivan P. Stanimirovi Uvod u programiranje

Ovo se moe ostvariti referencama, ili pokazivaima. Sledei primer demonstrira funkciju koja
vraa tri vrednosti: dve kao pokazivake parametre i jednu kao povratnu vrednost funkcije.
Primer. Vraanje vrednosti pomou pokazivaa.
1:
2: // Vraanje vie vrednosti iz funkcije
3:
4: #include <iostream.h>
5:
6: typedef unsigned short USHORT;
7:
8: short Factor(USHORT, USHORT*, USHORT*);
9:
10: int main()
11: {
12: USHORT number, squared, cubed;
13: short error;
14:
15: cout << "Unesite broj (0-20): ";
16: cin >> number;
17:
18: error = Factor(number, &squared, &cubed);
19:
20: if(!error)
21: {
22: cout << "broj: " << number << "\n";
23: cout << "kvadrat: " << squared << "\n";
24: cout << "kub: " << cubed << "\n";
25: }
26: else
27: cout << "Doslo je do greske!!\n";
28: return 0;
29: }
30:
31: short Factor(USHORT n, USHORT *pSquared, USHORT *pCubed)
32: {
33: short Value = 0;
34: if (n > 20)
35: Value = 1;
36: else
37: {
38: *pSquared = n*n;
39: *pCubed = n*n*n;
40: Value = 0;
41: }
42: return Value;
43: }
U liniji 12 number, squared i cubed su definisani kao USHORT. Promenljivoj number se dodeljuje
broj baziran na korisnikom ulazu. Ovaj broj i adresa od squared i cubed se predaju funkciji Factor().
Funkcija Factor() ispituje prvi parametar, koji se predaje po vrednosti. Ako je on vei od 20
(maksimalan broj kojim ova funkcija moe rukovati), ona postavlja povratnu vrednost (Value) na
jednostavnu vrednost greke (Value =1). Uoite da povratna vrednost 0 iz funkcije Factor() pokazuje
da je sve prolo dobro, i uoite da tunkcija vraa ovu vrednost u liniji 42.
Stvarne potrebne vrednosti, kvadrat i kub promenljive number, vraaju se menjanjem pokazivaa
koji su predati funkciji.
U linijama 38 i 39 pokazivaima se dodeljuju njihove povratne vrednosti. U liniji 40 return Value
dobija uspenu vrednost.
Jedno poboljanje u ovom programu bi moglo biti deklarisanje sledeeg:

96
Ivan P. Stanimirovi Uvod u programiranje

enum ERROR_VALUE {SUCCESS, ERROR};


Zatim, umesto vraanja 0, ilii, program bi mogao da vrati SUCCESS, ili ERROR.
Vraanje viestrukih vrednosti po referenci
Prethodni program se moe uiniti lakim za itanje i odravanje, korienjem referenci, umesto
pokazivaa. Sledei primer prikazuje isti program, prepisan radi korienja referenci i ukljuivanja
ERROR enumeracije.
Primer. Vraanje viestrukih vrednosti korienjem referenci.
1: //
2: // Vraanje vie vrednosti iz funkcije
3: // konenje referenci
4:
5: #include <iostream.h>
6:
7: typedef unsigned short USHORT;
8: enum ERR_CODE {SUCCESS, ERROR};
9:
10: ERR_CODE Factor(USHORT, USHORT &, USHORT &);
11:
12: int main()
13: {
14: USHORT number, squared, cubed;
15: ERR_CODE result;
16:
17: cout << "Unesite broj (0 - 20): ";
18: cin >> number;
19:
20: result = Factor(number, squared, cubed);
21:
22: if (result == SUCCESS)
23 {
24 cout << "broj: " << number << "\n";
25 cout << "kvadrat: " << squared << "\n";
26 cout << "kub: " << cubed << "\n";
27 }
28 else
29 cout << "Doslo je do greske!!\n";
30: return 0;
31: }
32:
33: ERR_CODE Factor(USHORT n, USHORT &rSquared, USHORT &rCubed)
34: {
35: if (n > 20)
36: return ERROR; // jednostavan kd za greku
37: else
38: {
39: rSquared = n*n;
40: rCubed = n*n*n;
41: return SUCCESS;
42: }
43: }
Ovaj program je identian prethodnom, uz dva izuzetka. Enumeracija ERR_CODE ini
izvetavanje o greci u linijama 36 i 41, kao i rukovanje grekama u liniji 22.
Ipak, vea promena je ta da je Factor() sada deklarisana da prihvata reference na squared i cubed, a
ne na pokazivae, to ini manipulaciju ovim parametrima daleko jednostavnijom i lakom za
razumevanje.

97
Ivan P. Stanimirovi Uvod u programiranje

Predavanje po referenci, zbog efikasnosti


Svaki put kada predate objekat funkciji po vrednosti, pravi se njegova kopija. Svaki put kada
vratite po vrednosti objekat iz funkcije, pravi se druga kopija.
Ovi objekti se kopiraju na stek. Zato ovo uzima vreme i memoriju. Za male objekte, kao to su
ugraene celobrojne vrednosti, to je trivijalna cena. Meutim, za vee korisniki kreirane objekte,
cena je vea. Veliina korisniki kreiranih objekata na steku je suma veliina svih njegovih
promenljivih lanica. Svaka od njih, dalje, moe biti korisniki kreiran objekat i predavanje tako
masivne strukture njenim kopiranjem na stek moe biti veoma skupo zbog performansi i korienja
memorije.
Postoji, takoe, i druga cena. Sa klasama koje kreirate, svaka ova privremena kopija se kreira kada
kompajler pozove specijalan konstruktor: konstruktor kopije. Za sada, dovoljno je da znate da se
konstruktor kopije poziva svaki put kada se privremena kopija objekta stavi na stek.
Primer. Urediti tri broja x, y, z u neopadajui poredak x<= y<= z.
void razmeni(int *a, int *b)
{ int pom; pom=*a; *a=*b; *b=pom; }

void main()
{ int x,y,z; void razmeni(int*, int*);
scanf("%d%d%d", &x,&y,&z);
if(x>y) razmeni(&x,&y); if(x>z) razmeni(&x,&z);
if(y>z) razmeni(&y,&z);
printf("x= %d y= %d z= %d\n",x,y,z);
}

Primer. Napisati proceduru kojom se izraunava najmanji zajedniki sadralac i najvei zajedniki
delilac dva prirodna broja.
#include<stdio.h>
void unos(int *,int *); void nzds(int,int, int *,int *);
void main()
{ int x,y, nzd,nzs;
unos(&x, &y); nzds(x,y,&nzd,&nzs);
printf("Nzd unetih brojeva = %d a nzs= %d\n",nzd,nzs);
}

void unos(int *a, int *b)


{ printf("\nZadati dva cela broja: "); scanf("%d%d",a,b); }

void nzds(int a, int b, int *nd, int *ns)


{ if(a>b) *ns=a; else *ns=b;
int v=*ns;
while(*ns%a !=0 || *ns%b !=0)(*ns)+=v;
while(a!=b) { if(a>b)a-=b; else if(b>a)b-=a; }
*nd=a;
}

Primer. Sa tastature se unosi jedan ceo broj, a za njim neodreen broj celih brojeva. Napisati
proceduru kojom se izraunava minimum i maksimum unetih brojeva.
#include<stdio.h>
void minmax(int *,int*);
void main()
{ int mn,mx; minmax(&mn,&mx);
printf("Minimum je %d a maksimum %d\n",mn,mx);
}

void minmax(int *min, int *max)


{ int n;
*min=*max=scanf("%d",&n);

98
Ivan P. Stanimirovi Uvod u programiranje

while(scanf("%d",&n)==1)
if(n<*min)*min=n;
else if(n>*max)*max=n;
}

Primer. Napisati funkciju za izraunavanje determinante kvadratnog trinoma ax2+bx+c. Napisati


proceduru kojom se izraavaju sledee aktivnosti:
a) Odreuje da li su reenja realna i razliita, realna i jednaka ili konjugovano-kompleksna;
b) u sluaju da su reenja realna izraunava njihove vrednosti, a u sluaju da su reenja
konjugovano-kompleksna izraunava realni i imaginarni deo tih reenja.
Napisati proceduru za tampanje odgovarajuih izvetaja. U glavnom programu unositi
koeficijente kvadratnih jednaina u beskonanom ciklusu i prikazivati odgovarajue rezultate
koristei proceduru za prikazivanje izvetaja.
#include<stdio.h>
#include<math.h>
float diskriminanta(float, float, float);
void solution(float, float, float, float *, float *,int *); void
rezultati(float, float, float, float *,float *,int *);
void main()
{ float a,b,c, x1,x2; int tip;
while(1)
{ printf("Unesi koeficijente -> "); scanf("%f%f%f", &a,&b,&c);
rezultati(a,b,c,&x1, &x2, &tip);
} }
float diskriminanta(float a, float b, float c)
{ return(b*b-4.0*a*c); }
void solution(float a,float b,float c, float *x,float *y,int *t)
{ float d;
d=diskriminanta(a,b,c);
if(d>0){*t=0; *x=(-b+sqrt(d))/(2*a);*y=(-b-sqrt(d))/(2*a); }
else if(d==0) { *t=1; *x=*y=-b/(2*a);}
else { *t=2; *x=-b/(2*a); *y=sqrt(-d)/(2*a); }
}
void rezultati(float a,float b,float c, float *x, float *y, int *t)
{solution(a,b,c,x,y,t);
if(*t==0)
{printf("Resenja su realna i razlicita\n");
printf("x1=%f x2=%f\n",*x,*y);}
else if(*t==1)
{printf("Resenja su realna i jednaka\n");
printf("x1=x2=%f\n",*x);}
else { printf("Resenja su konjugovano-kompleksna\n");
printf("x1 = %f + i* %f\n",*x,*y);
printf("x2 = %f -i* %f\n",*x,*y);
} }

Primer. Napisati proceduru za deljenje dva cela broja na proizvoljan broj decimala. Deljenik, delilac
i broj decimala zadati u posebnoj proceduri.
#include<stdio.h>
#include<conio.h>
void unos(int *, int*, int *);
void deljenje(int, int, int);
main()
{ int n,i,bdec, brojilac, imenilac;
clrscr(); printf("Koliko puta? "); scanf("%d", &n);
for(i=1; i<=n; i++)
{ unos(&brojilac, &imenilac, &bdec);

99
Ivan P. Stanimirovi Uvod u programiranje

deljenje(brojilac, imenilac, bdec);


} }
void unos(int *br, int *im, int *bd)
{ printf("Brojilac = ?"); scanf("%d",br);
printf("Imenilac = ? "); scanf("%d",im);
printf("Broj decimala = ? "); scanf("%d",bd);
}
void deljenje(int br, int im, int bd)
{ int i;
if(br*im<0) printf("-");
br=br<0?-br:br; im=im<0?-im:im;
printf("\n%d.",br/im); br %= im;
for(i=1; i<=bd; i++)
{ br *=10; printf("%d",br/im); br %=im; }
printf("\n");
}

Primer. a) Napisati proceduru za unoenje brojioca i imenioca jednog razlomka. U toj proceduri, po
potrebi, vrednost imenioca promeniti tako da bude pozitivan.
b) Napisati rekurzivnu funkciju za izraunavanje najveeg zajednikog delioca dva prirodna broja.
c) Napisati funkciju za izraunavanje najveeg zajednikog sadraoca dva prirodna broja.
d) Napisati proceduru za kraenje brojioca i imenioca zadatim prirodnim brojem.
e) Napisati proceduru za sabiranje dva razlomka. Pri sabiranju razlomaka koristiti najvei zajedniki
sadralac za imenioce jednog i drugog razlomka. Zatim skratiti brojilac i imenilac izraunatog
razlomka najveim zajednikim deliocem za brojilac i imenilac.
f) U glavnom programu uitati brojilac i imenilac za n razlomaka i izraunati zbir svih razlomaka.
#include<stdio.h>
#include<math.h>
#include<conio.h>
/* razlomci.c */
int nzd(int, int); int nzs(int, int); void unos(int *, int *);
void sabiranje(int, int,int, int, int *, int *);

void kracenje(int *, int*, int); main()


{ int i,n, broj,imen, brojilac, imenilac, brez, irez;
clrscr(); printf("Koliko razlomaka sabirate? ");
scanf("%d", &n);
for(i=1; i<=n; i++)
{unos(&brojilac, &imenilac);
if(i==1){ brez=brojilac; irez=imenilac; }
else
{broj=brez; imen=irez;
sabiranje(brojilac,imenilac,broj,imen, &brez,&irez);
}
printf("%d/%d\n", brez, irez);
}
void unos(int *br, int *im)
{ printf("Brojilac -> " ); scanf("%d",br);
printf("Imenilac -> " ); scanf("%d",im);
if(*im<0) {*br=-*br; *im=-(*im); }
}
int nzd(int br, int im)
{ if(br == im) return(br);
else if(br>im)return(nzd(br-im,im));
else return(nzd(br,im-br));
}
int nzs(int br, int im)
{ int ns;

100
Ivan P. Stanimirovi Uvod u programiranje

if(br>im) ns=br; else ns=im;


while((ns %br !=0) || (ns %im != 0))ns++;
return(ns);
}
void kracenje(int *br, int *im, int k)
{ *br /=k; *im /=k; }

void sabiranje(int pb,int pi,int db,int di,int *rb,int *ri)


{ int ns, nd;
ns=nzs(pi,di); *ri=ns; *rb=pb*ns/pi+db*ns/di;
nd=nzd(*rb, *ri);
kracenje(rb, ri, nd);
}

Primer. Napisati proceduru za uitavanje i ispis kompleksnih brojeva kao i procedure za izvoenje
osnovnih aritmetikih operacija sa kompleksnim brojevima. Napisati test program.
#include<stdio.h>
#include<math.h>
void unos(float *,float *, float *, float *);
void saberi(float, float, float, float, float *, float *);
void oduzmi(float, float, float, float, float *, float *);
void mnozi(float, float, float, float, float *, float *);
void deli(float, float, float, float, float *, float *);
void ispis(float, float);
void main()
{ float x1,y1,x2,y2,re,im;
unos(&x1,&y1,&x2,&y2);
saberi(x1,y1,x2,y2, &re,&im); printf("\nNjihov zbir je: ");
ispis(re,im); printf("\n");
oduzmi(x1,y1,x2,y2, &re,&im);
printf("\nNjihova razlika je: "); ispis(re,im); printf("\n");
mnozi(x1,y1,x2,y2,&re,&im);
printf("\nNjihov proizvod je: "); ispis(re,im); printf("\n");
deli(x1,y1,x2,y2,&re,&im);
printf("\nNjihov kolicnik je: "); ispis(re,im);
printf("\n");
}
void unos(float *re1, float *im1, float *re2, float *im2)
{ printf("Prvi kompleksni broj? "); scanf("%f%f", re1,im1);
printf("Drugi kompleksni broj? "); scanf("%f%f", re2,im2);
}
void saberi(float re1,float im1,float re2,float im2,
float *rez, float *imz)
{*rez=re1+re2; *imz=im1+im2; }
void oduzmi(float re1, float im1, float re2, float im2,
float *rez, float *imz)
{*rez=re1-re2; *imz=im1-im2; }
void mnozi(float re1, float im1, float re2, float im2,
float *rez, float *imz)
{*rez=re1*re2-im1*im2; *imz=re1*im2+re2*im1; }
void deli(float re1, float im1, float re2, float im2,
float *rez, float *imz)
{*rez=(re1*re2+im1*im2)/(re2*re2+im2*im2);
*imz=(-re1*im2+re2*im1)/(re2*re2+im2*im2);
}
void ispis(float x, float y)
{ printf("\n %f",x);
if(y<0) printf("-"); else printf("+");
printf("i*%f\n",fabs(y));
}

101
Ivan P. Stanimirovi Uvod u programiranje

Primer. a) Napisati funkciju NZD(a,b) kojom se izraunava najvei zajedniki delilac za prirodne
brojeve a i b.
b) Koristei funkciju NZD(a,b) izraunati NZD(a,b,c).
d) Napisati funkciju skratic(int a, int b, int *c, int *d) koja razlomak a/b (b0) dovodi do neskrativog
razlomka c/d.
e) Napisati funkciju skrati(int a, int b, int &c, int &d) koja razlomak a/b (b0) dovodi do neskrativog
razlomka c/d.
f) U funkciji main:
- Za tri uitana prirodna broja nai njihov NZD.
- Za dva razlomka koji su uitani preko tastature i uitani operacijski znak (+ za sabiranje, - za
oduzimanje, * za mnoenje, / za deljenje) odrediti rezultat raunanja u neskrativom obliku.
#include<stdio.h>
#include<math.h>

int NZD(int a, int b)


{ int r;
while(a%b) { r=a%b; a=b; b=r; }
return(b);
}

int NZD3(int a, int b, int c)


{ return(NZD(a,NZD(b,c))); }

void skratic(int a, int b, int *c, int *d) /* Verzija za C */


{ int nd=NZD(a,b);
*c=a/nd; *d=b/nd;
}

void skrati(int a, int b, int &c, int &d) /* Verzija za C++ */


{ int nd=NZD(a,b);
c=a/nd; d=b/nd;
}

int NZS(int a, int b)


{ int p, n;
if(a<b) { p=a; a=b; b=p; }
n=a;
while(n%b) n+=a;
return n;
}

void operacija(int a, int b, int c, int d, char ch, int &br, int &im)
{ int as, bs, cs, ds;
skrati(a,b,as,bs); skrati(c,d,cs,ds);
switch(ch)
{ case '+': im=NZS(bs,ds), br=as*im/bs+cs*im/ds; break;
case '-': im=NZS(bs,ds), br=as*im/bs-cs*im/ds; break;
case '*': br=as*cs; im=bs*ds; break;
case '/': br=as*ds; im=bs*cs; break;
}
int nd=NZD(br, im);
im= im/nd; br=br/nd;
}

void ispis(int br, int im)


{ if(br*im<0)printf("-");
printf("%d/%d\n",abs(br),abs(im));
}

102
Ivan P. Stanimirovi Uvod u programiranje

void main()
{ int a,b,c,d;
printf("a,b = ? "); scanf("%d%d",&a,&b);
printf("c= ? "); scanf("%d",&c);
printf("NZD3(%d,%d,%d)=%d\n",a,b,c,NZD3(a,b,c));
int br,im;
skratic(a,b,&br,&im); // skrati(a,b,br,im);
printf("Prvi razlomak? "); scanf("%d%d",&a,&b);
printf("Drugi razlomak? "); scanf("%d%d",&c,&d);
char op;
printf("Operacija = ? "); scanf("%c",&op); scanf("%c",&op);
operacija(a,b,c,d,op,br,im);
printf("Skraceni razlomak = "); ispis(br,im);
}
Primer. Napisati funkciju koja vraa n dana stariji datum.
Reenje u C++:
#include<stdio.h>

int prestupna(int g)
{ return ((g%4==0) && !(g%100==0))||(g%400==0); }

void sutra(int & d, int & m, int & g)


{ switch(m)
{ case 1: case 3: case 5: case 7: case 8: case 10: case 12:
if (d<=30) d++;
else
{ d=1;
if(++m==13)
{ m=1; g++; }
} break;
case 4: case 6: case 9: case 11:
if (d<30) d++;
else
{ d=1; m++; } break;
case 2:
if(++d>28+prestupna(g))
{ d=1; m++; } break;
}
}

void main()
{ int d,m,g,n;
scanf("%d%d%d",&d,&m,&g); scanf("%d",&n);
for(int i=1;i<=n;sutra(d,m,g),i++);
printf("%d. %d. %d.\n",d,m,g);
}

Reenje u C:
#include<stdio.h>
int prestupna(int g)
{ return ((g%4==0) && !(g%100==0))||(g%400==0); }

void sutra(int *d, int *m, int *g)


{ printf("Na pocetku %d. %d. %d.\n",*d,*m,*g);
switch(*m)
{ case 1: case 3: case 5: case 7: case 8: case 10: case 12:
if (*d<=30) (*d)++;
else
{ *d=1; if(++(*m)==13){ *m=1; (*g)++; }
} break;

103
Ivan P. Stanimirovi Uvod u programiranje

case 4: case 6: case 9: case 11:


if (*d<30) *d++;
else { *d=1; (*m)++; } break;
case 2: if(++(*d)>28+prestupna(*g))
{ *d=1; (*m)++; } break;
}
printf("U funkciji %d. %d. %d.\n",*d,*m,*g);
}

void main()
{ int d,m,g,n;
printf("Datum = ? "); scanf("%d%d%d",&d,&m,&g);
printf("Posle koliko dana ? "); scanf("%d",&n);
for(int i=1;i<=n;sutra(&d,&m,&g),i++);
printf("%d. %d. %d.\n",d,m,g);
}
Primer. Napisati funkciju
int* biggest_of_two(int*, int*);
koja vraa pokaziva na minimum dva cela broja.
U glavnom programu uitati tri cela broja a, b, c a zatim izraunati njihov minimum.
#include <stdio.h>
int* biggest_of_two(int*, int*);
int main(void)
{ int a, b, c;
int *p;
scanf("%d%d%d",&a,&b,&c);
p = biggest_of_two(&a, &b);
printf("the biggest of %i and %i is %i\n", a, b, *p);
printf("the biggest of %i %i and %i is %i\n", a, b, c,
*biggest_of_two(&a, biggest_of_two(&b, &c)));
return 0;
}

int* biggest_of_two(int * p, int * q)


{ return (*p > *q) ? p : q; }

C dozvoljava upotrebu pokazivaa na proizvoljni tip, ukljuujui i pokazivae.

Primer. ta se ispisuje izvrenjem sledeeg programa?


#include<stdio.h>
void main()
{ int i=10,j=7,k;
int *p = &i;
int *q = &j;
int **pp=&p;
**pp+=1;
*pp=&k;

104
Ivan P. Stanimirovi Uvod u programiranje

**pp=*q;
i=*q***pp;
printf("i = %d\n",i); // 49
i=*q/(**pp);
printf("i = %d\n",i); // 1
}

5.4. Globalne promenljive kao parametri potprograma


Sve promenljive definisane u okruenju u kome je definisan i sam potprogram mogu se koristiti i u
potprogramu po konceptu globalnih promenljivih. Potprogram moe da bude i bez spiska argumenata
i da sve veze sa okruenjem ostvaruje preko globalnih promenljivih.
Primer. Potrebno je napisati program kojim se izraunava izraz
tanh(a n b) tanh2 (a m b)
D .
tanh2 (a 2 b 2 ) tanh(a 2 b 2 )
Za izraunavanje vrednosti tanh(x) koristiti potprogram kojim se ova funkcija izraunava prema
jednoj od relacija:
e x ex e2x 1
tanh x ili tanh .
e ex e2x 1
Slede etiri mogua reenja ovog problema u kojima se koriste razliiti potprogrami sa i bez
parametara. Reenja su data u programskom jeziku Pascal.
(a) Reenje funkcijskim potprogramom bez argumenata. Rezultat se dodeljuje imenu funkcije.
Vrednost za x se unosi u funkciju preko globalnog parametra.
program TANH1;
var D,a,b,m,n,R1,R2,R3,x : real;
function th: real;
var R :real;
begin
R:=exp(2*x); th := (R-1)/(R+1)
end;
begin
read(a,b,m,n);
x:=a*n+b; R1:=th; x:=a+m*b; R2:=th;
x:=a*a+b*b; R3:=th; x:=a*a-b*b;
D:=R1/(R3*R3)-R2*R2/th; writeln(D);
end.

#include<stdio.h>
#include<math.h>

float D,a,b,m,n,R1,R2,R3,x;

float th()
{ float R;
R=exp(2*x); return ((R-1)/(R+1));
}

void main()
{ scanf("%f%f%f%f",&a,&b,&m,&n);
x=a*n+b; R1=th(); x=a+m*b; R2=th();
x=a*a+b*b; R3=th(); x=a*a-b*b;
D=R1/(R3*R3)-R2*R2/th(); printf("%f\n",D);
}

105
Ivan P. Stanimirovi Uvod u programiranje

(b) Reenje pomou procedure bez argumenata. Rezultat se dodeljuje globalnom parametrom. Takoe,
i vrednost za x se unosi preko globalnog parametra.
program TANH2;
var D,a,b,m,n,R1,R2,R3,x,y : real;
procedure th;
begin
y := exp(2*x); y := (y-1)/(y+1)
end;
begin
read(a,b,m,n);
x := a*n+b; th; R1 := y;
x := a+m*b; th; R2 := y;
x := a*a+b*b; th; R3 := y;
x := a*a-b*b; th;
D := R1/(R3*R3)- R2*R2/y; writeln(D);
end.

#include<stdio.h>
#include<math.h>

float D,a,b,m,n,R1,R2,R3,x,y;

void th()
{ y=exp(2*x); y=(y-1)/(y+1); }

void main()
{ scanf("%f%f%f%f",&a,&b,&m,&n);
x=a*n+b; th(); R1=y; x=a+m*b; th(); R2=y;
x=a*a+b*b; th(); R3=y; x=a*a-b*b; th();
D=R1/(R3*R3)- R2*R2/y; printf("%f\n",D);
}
(c) Program sa funkcijskim potprogramom sa argumentima. Rezultat se dodeljuje imenu funkcije.
Vrednost za x se unosi pomou parametra funkcije.
program TANH3;
var D,a,b,m,n : real;
function th(x: real):real;
var R : real;
begin
R := exp(2*x); th:= (R-1)/(R+1)
end;
begin
read(a,b,m,n);
D := th(a*n+b)/(th(a*a+b*b)*th(a*a+b*b))
th(a+m*b)*th(a+m*b)/th(a*a-b*b);
writeln(D)
end.

#include<stdio.h>
#include<math.h>

float D,a,b,m,n;

float th(float x)
{ float R=exp(2*x);
return ((R-1)/(R+1));
}

void main()
{ scanf("%f%f%f%f", &a,&b,&m,&n);
D= th(a*n+b)/(th(a*a+b*b)*th(a*a+b*b)) -

106
Ivan P. Stanimirovi Uvod u programiranje

th(a+m*b)*th(a+m*b)/th(a*a-b*b);
printf("%f\n",D);
}
(d) Reenje pomou procedure sa argumentima. Prvi argument je izlazni a drugi ulazni.
program TANH4;
var D,a,b,m,n,Rl,R2,R3,R4 :real;
procedure th(var y: real; x: real);
begin
y := exp(2*x); y := (y-1)/(y+1)
end;
begin
read(a,b,m,n);
th(Rl, a*n+b); th(R2, a+m*b); th(R3,a*a+b*b); th(R4,a*a-b*b);
D:=Rl/(R3*R3)-R2*R2/R4; writeln(D)
end.

#include<stdio.h>
#include<math.h>

float D,a,b,m,n,Rl,R2,R3,R4;
void th(float *y, float x)
{ *y=exp(2*x); *y=(*y-1)/(*y+1); }

void main()
{ scanf("%f%f%f%f", &a,&b,&m,&n);
th(&Rl, a*n+b); th(&R2, a+m*b); th(&R3,a*a+b*b); th(&R4,a*a-b*b);
D=Rl/(R3*R3)-R2*R2/R4; printf("%f\n",D);
}

#include<stdio.h>
#include<math.h>

float D,a,b,m,n,Rl,R2,R3,R4;
void th(float &y, float x)
{ y=exp(2*x); y=(y-1)/(y+1); }

void main()
{ scanf("%f%f%f%f", &a,&b,&m,&n);
th(Rl, a*n+b); th(R2, a+m*b); th(R3,a*a+b*b); th(R4,a*a-b*b);
D=Rl/(R3*R3)-R2*R2/R4; printf("%f\n",D);
}
U programskom jeziku FORTRAN konceptu globalnih promenljivih na neki nain odgovara
koncept COMMON podruja. Sve promenljive koje su zajednike za vie programskih modula
obuhvataju se sa COMMON i pamte se u zasebnom memoriskom bloku koji je dostupan svim
potprogramima koji se referenciraju na isto COMMON podruje.
Primeri

Primer. (C) Za paran broj N proveriti hipotezu Goldbaha. Prema toj hipotezi, svaki paran broj vei
od 2 moe se predstaviti zbirom dva prosta broja.
Reenje se sastoji u proveri da li je za svaki prost broj i (i = 3, ... , n/2) broj n-i takoe prost. Da li
je broj prost proverava se funkcijom prost.
#define nepar(x) ((x)%2)?1:0)
#include "math.h"

int prost(long n)
{ long i,koren; int q;
koren=floor(sqrt(n)); q=(nepar(n) || (n==2);

107
Ivan P. Stanimirovi Uvod u programiranje

i=3;
while ((q) && (i<=koren)) { q=((n % i) != 0); i=i+2; };
return (q);
};

void main()
{long n,i;
int q;
do { printf("\nunesite paran broj: "); scanf("%ld",&n); }
while((n<4) || ((n % 2) != 0));
i=2; q=0;
while ((i<= n/2) && (!q))
{ q=(prost(i) && prost(n-i));
if (q) printf("\nTo su brojevi %ld i %ld",i,n-i);
i++;
};
if (!q) printf("\n Hipoteza ne vazi za %ld ",n);
}
Primer. Napisati funkcijski potprogram koji izraunava n-ti stepen broja x koristei relaciju
1, n=0
xn = (xk)2, n=2k
x(xk)2, n=2k+1
Napisati program za stepenovanje koji u beskonanom ciklusu uitava realan broj x i prirodan broj n i
izraunava xn.
program Stepenovanje2;
type PrirodniBroj = O..Maxint;
var Pi, PiKvadrat : Real ;
function Stepen(Osnova:Real; Eksponent:PrirodniBroj): Real;
var Rezultat:Real;
begin
Rezultat := 1;
while Eksponent > 0 do
begin
while not Odd(Eksponent) do
begin
Eksponent := Eksponent div 2; Osnova := Sqr(Osnova)
end;
Eksponent:= Eksponent-1; Rezultat := Rezultat*Osnova
end;
Stepen:=Rezultat
end { Stepen };
begin
repeat
readln(x); readln(n);
Writeln(x:11:6, n:3, Stepen(x,n):11:6);
until false
end { Stepenovanje2 }.
Test primeri:
2.000000 7 128.000000
3.141593 2 9.869605
3.141593 4 97.409100
Primer. (PASCAL) Napisati funkciju koja izraunava vrednost verinog razlomka

108
Ivan P. Stanimirovi Uvod u programiranje

1
v ( m)
1
1
1
2
...
1
m2
1
m 1
m
Napisati program kojim se izraunava suma
1 1 1
S 1 ... (1) n .
v(3) v(5) v(2n 1)
program verizni_razlomci;
var s,znak:real;
i,n:integer;
function verizni(m:integer):real;
var s:real;
i:integer;
begin
s:=0;
for i:=m downto 1 do s:=1/(s+i);
verizni:=s;
end;

begin
readln(n);
s:=1.0; znak:=-1;
for i:=1 to n do
begin
s:=s+znak/verizni(2*i+1); znak:=-znak;
end;
writeln(s);
end.

Primer. Nai najvei, najmanji i drugi po veliini element izmeu unetih realnih brojeva, bez
korienja nizova.
program najveci;
var max1,max2,min,x:real;
n,i:integer;
begin
write('Koliko brojeva? '); readln(n);
if n>2 then
begin
writeln('Unesi ',n,' brojeva'); read(x);
max1:=x; min:=x; read(x);
if x>=max1 then
begin
max2:=max1; max1:=x
end
else if x>=min then max2:=x
else begin
max2:=min; min:=x;
end;
for i:=3 to n do
begin
read(x);
if x>=max1 then
begin
max2:=max1; max1:=x
end
else if x>max2 then max2:=x

109
Ivan P. Stanimirovi Uvod u programiranje

else if x<min then min:=x;


end;
writeln('Najveci je ',max1:10:6);
writeln('Drugi po velicini je ',max2:10:6);
writeln('Najmanji je ',min:10:6);
end
else writeln('Manjak brojeva')
end.
Primer. ta se ispisuje posle izvrenje sledeeg programa?
program UzgredniEfekat(Output);
var A, Z : Integer ;
function Skriven(X:Integer):Integer;
begin
Z := Z-X { uzgredni efekat na Z};
Skriven := Sqr(X)
end { Skriven } ;
begin
Z := 10; A := Skriven(Z); Writeln(A,' ', Z);
Z := 10 ; A := Skriven(10) ; A := A*Skriven(Z);
Writeln(A,' ', Z) ;
Z := 10; A := Skriven(Z); A := A*Skriven(10);
Writeln(A,' ', Z)
end { UzgredniEfekat}

#include<stdio.h>
int a,z;
int Skriven(int x)
{ z=z-x; // uzgredni efekat na z
return x*x;
}
void main()
{ z=10; a=Skriven(z); printf("%d %d\n",a,z);
z=10; a=Skriven(10); a*=Skriven(z);
printf("%d %d\n",a,z);
} // { UzgredniEfekat}

Rezultat:
100 0
0 0
10000 -10

5.5. Rekurzivni potprogrami


Funkcija, odnosno procedura je rekurzivna ako sadri naredbu u kojoj poziva samu sebe. Rekurzija
moe biti direktna, kada funkcija direktno poziva samu sebe. Takoe, rekurzija moe biti i indirektna,
kada funkcija poziva neku drugu proceduru ili funkciju, koja poziva polaznu funkciju (proceduru).
U realizaciji rekurzije moraju se potovati dva osnovna principa:
- Mora da postoji rekurentna veza izmeu tekueg i prethodnog (ili narednog) koraka u
izraunavanju.
- Mora da postoji jedan ili vie graninih uslova koji e prekinuti rekurzivno izraunavanje.
Neki programski jezici dozvoljavaju poziv potprograma u telu samog tog potprograma. Takvi
potprogrami nazivaju se rekurzivnim i pogodno su sredstvo za reavanje problema koji su rekurzivno
definisani.

110
Ivan P. Stanimirovi Uvod u programiranje

Tipian primer rekurzivnog potprograma je potprogram za izraunavanje faktorijela funkcije


definisanog sa:
n*(n-l)!, za n>0
n! =
1, za n = 0
Primer. Program za izraunavanje faktorijela realizovan u Pascal-u:
function FAKT(N:integer): integer;
begin
if N>0 then FAKT := N*FAKT(N-l)
else FAKT := 1
end;
Koncept rekurzivnih potprograma se najbolje moe sagledati pomou grafa poziva potprograma na
kome se predstavlja svaki od poziva potprograma. Na slici je prikazan graf poziva potprograma FAKT
za N = 4.

U praksi se esto sreu i problemi u kojima postoji viestruka rekurzija. Jedan od takvih je problem
izraunavanja lanova Fibonaijevog niza brojeva. Fibonaijeva funkcija je definisana kao:
f(n-l) + f(n-2), n>1
f(n) = 1, n=1
1, n=0
Potprogram za izraunavanje lanova Fibonaijevog niza bie dvostruko rekurzivan. Dajemo
implementaciju u Pascal-u:
function Fib(n: Integer): integer;
begin
if n > 1 then
Fib := Fib(n-l) + Fib(n-2)
else Fib := 1;
end;
U ovom potprogramu rekurzija dakle nije u stvaranju jedne, ve dve kopije iste funkcije. Mogue
su i trostruke, cetvorostruke, itd. rekurzije jer broj poziva kopija niim nije ogranien. Graf poziva
ovakve dvostruke rekurzije razlikuje se od grafika rekurzija iz prethodnog primera.

Jo jedan od klasinih rekurzivnih problema je uveni problem Hanojskih kula.

111
Ivan P. Stanimirovi Uvod u programiranje

Primer. Hanojske kule.


procedure Hanoj (n,sa,na,preko : integer);
begin
if n > 0 then
begin
Hanoj(n-1, sa preko, na);
Write(sa, ' ->, na);
Hanoj(n-1, preko, na, sa);
end
end;
Prema staroj indijskoj legendi, posle stvaranja sveta je Bog Brama (Brahma) postavio tri
dijamantska stuba i na prvi postavio 64 zlatna prstena razliitih prenika tako da svaki naredni bude
manji od prethodnog. Svetenici hrama moraju da prebacuju te prstenove sa prvog na trei stub
koristei pri tome drugi, all samo jedan po jedan i to tako da se vei prsten ne moe nai iznad manjeg.
Kad svi prstenovi budu prebaeni na trei stub nastupie kraj sveta.
Ovde ce biti prikazan primer programa koji vri ovu operaciju prebacivanja i koji ne zavisi od broja
prstenova. Meutim uobiajeno je da se ovaj primer izvodi za manji broj krugova 3 do 5 ve samim
tim to je najmanji broj potrebnih poteza 2n - 1. Za sluaj sa 64 kruga dolazimo do broja od
18.446.744.073.709.551.615 poteza.
U opstem sluaju, meutim, problem se sastoji u tome da se n prstenova prebaci sa prvog stuba (1)
na trei stub (3) preko drugog stuba (2). Cilj je, dakle, ostvarljiv u tri "koraka". Sve prstenove osim
najveeg (n-tog), prebaciti na drugi stub, koristei trei stub. Zatim n-ti prsten prebaciti na trei stub, a
onda na njega staviti pomonu gomilu sa drugog stuba, koristei prvi stub kao pomoni. Da bi se ovo
izvelo potrebno je ceo postupak izvesti za n -1 prsten, a za to je potrebno izvriti istu proceduru za n -
2 prstena itd. Tako dolazimo do rekurzije.
Procedura se poziva za naprimer Hanoj(3,1,3,2).
Razmotriemo jo primer rekurzivnog potprograma za generisanje svih moguih permutacija bez
ponavljanja skupa sa n elemenata P(n), dat kao prethodni primer.

5.5.1. Primeri rekurzivnih funkcija u C


Primer. Jedmostavni primeri rekurzivnih funkcija.

#include <stdio.h>
void fun1(int);
void fun2(int);
void fun3(int);
void main()
{ printf("\n fun1(5)\n"); fun1(5);
printf("\n fun2(5)\n"); fun2(5);
printf("\n fun3(5)\n"); fun3(5);
}

void fun1(int n)
{ printf("%2d",n); if(n) fun1(n-1); return; }

void fun2(int n)
{ if(n) fun2(n-1); printf("%2d",n); return; }

void fun3(int n)
{ printf("%2d",n); if(n) fun3(n-1); printf("%2d",n); return;
}

Test primeri:
fun1(5)
5 4 3 2 1 0

112
Ivan P. Stanimirovi Uvod u programiranje

fun2(5)
0 1 2 3 4 5

fun3(5)
5 4 3 2 1 0 0 1 2 3 4 5

Primer. Rekurzivno izraunavanje faktorijela.


#include <stdio.h>
long fact(short);
void main()
{ short n; long rezultat;
scanf("%d",&n); rezultat = fact(n);
printf("Faktorijel od %d = %ld\n", n,rezultat);
}

long fact(short n)
{ if(n<=1)return(1L); else return(n*fact(n-1)); }

Primer. Napisati rekurzivnu funkciju za izraunavanje n-tog lana Fibonaijevog niza:

fib(n)= 1, n=1 ili n=0,


fib(n-1)+fib(n-2), n>1 .

#include <stdio.h>
long fib(short);
void main()
{ short n;
scanf("\n %d", &n);
printf("%d-ti clan Fibonacijevog niza = %ld\n", n,fib(n));
}

long fib(short n)
{ if(n<=1)return((long)1); else return(fib(n-1)+fib(n-2));}

Broj rekurzivnih poziva pri izraunavaju Fibonaijevih brojeva moe se smanjiti na sledei nain:
long fib(long a, long b, short n);
{ if(n==2)return b;
else { b=a+b; a=b-a; n--; return fib(a,b,n); }
}

Primer. Zadati broj tipa int ispisati znak po znak.


#include <stdio.h>
void printd(int n)
{ if(n<0) { putchar('-'); n=-n; }
if(n/10) printd(n/10);
putchar(n%10+'0');
}
void main()
{int n; scanf("%d", &n); printd(n); }

Primer. Rekurzivno izraunavanje najveeg zajednikog delioca dva cela broja.


#include <stdio.h>
int nzd(int n, int m)
{ if(n==m) return(m);
if(n<m) return(nzd(n,m-n));
else return(nzd(n-m,m));
}
void main()
{ int p,q;
scanf("%d%d",&p,&q); printf("nzd(%d,%d)=%d\n",p,q,nzd(p,q));

113
Ivan P. Stanimirovi Uvod u programiranje

Primer. Rekurzivno izraunati Akermanovu funkciju A(n,x,y), koja je definisana na sledei nain:
A(n, x, y) = x+1, za n=0
A(n, x, y) = x, za n=1, y=0,
A(n, x, y) = 0, za n=2, y=0
A(n, x, y) = 1, za n=3, y=0
A(n, x, y) = 2, za n>3, y=0
A(n, x, y) = A(n-1, A(n, x, y-1), x), inae.

#include <stdio.h>
long aker(int,int,int);
void main()
{ int x,y,n;
printf("Unesit n"); scanf("%d",&n); printf("Unesit x");
scanf("%d",&x); printf("Unesit y"); scanf("%d",&y);
printf("A(%d,%d,%d)=%ld\n",n,x,y,aker(n,x,y));
}
long aker(int n, int x, int y)
{ int pom;
if(n==0)return(x+1); if(n==1 && y==0) return(x);
if(n==2 && y==0) return(0); if(n>3 && y==0) return(2);
else { pom=aker(n,x,y-1); return(aker(n-1,pom,x)); }
}
Primer. Koristei rekurzivnu definiciju proizvoda dva prirodna broja napisati odgovarajuu funkciju.
#include <stdio.h>
long p(int a, int b)
{ if(b==1) return(a); return(a+p(a,b-1)); }
void main()
{ int x,y;
printf("Unesi dva prirodna broja "); scanf("%d%d",&x,&y);
printf("%d*%d=%ld\n",x,y,p(x,y));
}

Primer. Napisati rekurzivni program za izraunavanje sume cifara zadatog prirodnog broja.
#include <stdio.h>
int sumacif(long n)
{ if(!n)return(0); else return(n%10+sumacif(n/10)); }

void main()
{ long k;
printf("Unesi dug ceo broj "); scanf("%ld",&k);
printf("Suma cifara od %ld=%d\n",k,sumacif(k));
}

Primer. Napisati rekurzivni program za izraunavanje kolinika dva prirodna broja na proizvoljan
broj decimala.
#include <stdio.h>
void kolicnik(int ind, int n, int m, int k)
{ if(ind) printf("%d.",n/m);
else printf("%d",n/m);
if(k) kolicnik(0,(n%m)*10,m,k-1); }

void main()
{ int n,m,k;
printf("Brojilac? "); scanf("%d",&n);
printf("Imenilac? "); scanf("%d",&m);

114
Ivan P. Stanimirovi Uvod u programiranje

printf("Broj decimala? "); scanf("%d",&k);


kolicnik(1,n,m,k);
}

Primer. Hanojske kule.


#include <stdio.h>
void main()
{ int bd; void prebaci();
printf("Broj diskova = ? "); scanf("%d",&bd);
prebaci(bd,1,3,2);
}

void prebaci(int n, int sa, int na, int preko)


{ if(n) { prebaci(n-1,sa,preko,na);
printf("%d->%d ",sa,na); prebaci(n-1,preko,na,sa);
}

Primer. Sa tastature se uitava bez greke formula oblika


<formula>::=<cifra>|M(<formula>,<formula>)|m(<formula>,<formula>)
<cifra>::=0|1|2|3|4|5|6|7|8|9
M- maksimum, m-minimum.
Napisati rekurzivnu funkciju kojim se izraunava vrednost izraza.
Na primer, M(4,m(6,9))=6.
#include<iostream.h>
#include<stdio.h>
int f()
{ char ch,z;
int x,y;
ch=getchar(); if(ch>='0' && ch<='9') return ch-'0';
//sada je ch= M ili m
z=getchar(); // cita otvorenu zagradu
x=f();
z=getchar(); // cita zarez
y=f();
z=getchar(); // cita zatvorenu zagradu
switch(ch)
{ case 'M': return (x>y)?x:y;
case 'm': return (x>y)?y:x;
}
}

void main()
{ cout<<"----> "<<f()<<endl; }

5.6. Implementacija potprograma


Prilikom prevoenja programa kompilator vri planiranje memorijskog prostora koji e biti
dodeljen programu (Storage allocation). Pored toga to treba da se rezervie memorijski prostor za
smetaj kda programa i podataka koji se obrauju u njemu, za svaki od potprograma koji se poziva iz
programa generie se i jedan aktivacioni slog u koji se smetaju podaci koji se preuzimaju od glavnog
programa, lokalni podaci potprograma i takozvane privremene promenljive koje generie kompilator
prilikom generijsanja mainskog koda. Struktura jednog aktivacionog sloga data je na slici.
Rezultati koje vraa potprogram
Stvarni argumenti
Opcioni upravljaki linkovi aktivacionog sloga glavnog programa
Opcioni linkovi za pristup podacima u drugim aktivacionim slogovima

115
Ivan P. Stanimirovi Uvod u programiranje

Podaci o statusu
Lokalni podaci
Privremene promenljive koje generie kompilator

Za smetaj aktivacionih slogova koristi se jedna od sledee tri strategije: statika, pomou steka i
dinamika. U zavisnosti od toga koja je strategija primenjena zavisi da li e ill ne biti mogui
rekurzivni pozivi potprograma.
Kod statikog smetanja aktivacionih slogova, kompilator unapred rezervie fiksan memorijski
prostor iji se sadrzaj obnavlja kod svakog poziva potprograma. To znai da kod ovakvog smestanja
nisu mogui rekurzivni pozivi potprograma jer se kod svakog novog poziva potprograma gubi
informacija o prethodnom pozivu. Ovakva tehnika primenjuje se na primer kod realizacije kompilatora
za programski jezik FORTRAN, pa se u njemu zbog toga ne mogu koristiti rekurzije.
Kod strategije koja se zasniva na primeni steka za smetaj aktivacionih slogova koristi se stek u
koji se za svaki poziv potprograma smeta jedan aktivacioni slog. Ova tehnika dozvoljava rekurziju jer
se kod svakog novog poziva potprograma generie novi slog i smeta u stek. Na kraju potprograma
slog se izbacuje iz steka. To znai da je u toku izvravanja programa ovaj stek dinamiki zauzet
aktivacionim slogovima onih potprograma koji su trenutno aktivni. Od veliine memorijskog prostora
koji je dodeljen steku zavisi i dubina rekurzivnih poziva potprograma. Na slici ispod prikazana je
promena strukture steka u toku izvravanja programa u kome se poziva rekurzivni potprogram za
izraunavanje Fibonaijevih brojeva za n = 4.

116
Ivan P. Stanimirovi Uvod u programiranje

117
Ivan P. Stanimirovi Uvod u programiranje

Trea, dinamika strategija sastoji se u tome da se za svaki poziv potprograma generie aktivacioni
slog koji se smeta u poseban deo memorije nazvan Heap. U ovom sluaju aktivacioni slogovi
potprograma povezuju se u dinamiku strukturu podataka koja odgovara stablu poziva potprograma.
Oigledno je da i ova tehnika dozvoljava rekurziju.

5.7. Scope rules (domen vaenja)


Komponovana naredba (blok) je serija deklaracija iza koje sledi serija naredbi izmeu zagrada { i }.
Funkcije se mogu tretirati kao imenovani blokovi sa parametrima i dozvoljenom return naredbom.
Bazino pravilo domena vaenja je da su identifikatori dostupni samo u bloku u kome su
deklarisani. Jedno ime u spoljaanjem bloku vai dok se ne redefinie u unutranjem. Tada je ime u
spoljanjem bloku skriveno (ili maskirano) tim imenom unutranjeg bloka.

Primer.
/* spoljasnji blok */
int a=2; printf("%d\n",a) /* 2 */
/* unutranji blok */
int a=3; print("%d\n",a); /* 3 */

118
Ivan P. Stanimirovi Uvod u programiranje

printf("%d\n",a); /*2 */

5.8. Memorijske klase u C


Svaka promenljiva i funkcija u C ima dva atributa: tip i memorijsku klasu. Memorijske klase su
definisane kljunim reima auto, extern, static ili register
Promenljive deklarisane unutar tela funkcije jesu, podrazumevano (by default), memorijske klase
automatic. promenljive ove klase deklariu se eksplicitno kljunom reju auto.
Primer. Deklaracija unutar nekog bloka
char c; int i,j,k;
je ekvivalentna sa
auto char c; auto int i,j,k;
Kada je blok unet, sistem rezervie adekvatnu memoriju za promenljive klase auto. Ove promenljive
se tretiraju kao ''lokalne'' za blok. Kada se izae iz bloka sistem vie ne pamti vrednosti ovih
promenljivih.
Sve funkcije i promenljive deklarisane izvan tela funkcija imaju memorijsku klasu external, i one
su globalne za sve funkcije deklarisane posle njih.

Primer.
#include<stdio.h>
int a=7;
void main()
{ void f(void);
void g(void);
{ printf("%d\n",a); /* 7 */
f(); printf("%d\n",a); /* 8 */
g(); printf("%d\n",a); /* 8 */
}

void f()
{ printf("%d\n",a); /*7 */
a++; printf("%d\n",a); /* 8 */
}

void g()
{ int a=10;
printf("%d\n",a); /* 10 */
}

Promenljiva je globalna na nivou modula ako je deklarisana van svih funkcija u modulu.
memorijski prostor se trajno dodeljuje, a memorijska klasa te promenljive je extern. Globalnost je
odreena mestom deklaracije. Globalna promenljiva moe da bude maskirana lokalnom
promenljivom istog imena.
Da bi globalna promenljiva bila dostupna iz drugih modula, ona mora da se u tim modulima
definie pomou kljune rei extern.
Primer. Izrazom oblika
extern int a;
promenljiva a se ne deklarie, ve definie, tj. ne dodeljuje se memorijski prostor, nego se C
prevodilac informie o tipu promenljive. Eksterna promenljiva se moe inicijalizovati iskljuivo na
mestu svoje deklaracije.
Primer. Dat je sledei program koji se nalazi u dve datoteke (dva modula). U datoteci modul1.c se
nalazi program

119
Ivan P. Stanimirovi Uvod u programiranje

#include <stdio.h>
#include modul2.c
char c='w';
void main()
{ void f();void g();
printf("pre funkcije f: c= %c\n",c);
f(); printf("posle funkcije f: c= %c\n",c);
g(); printf("posle funkcije g: c= %c\n",c);
}
Promenljiva c je globalna, pa se njoj moe pristupiti iz drugih modula pomou kljune rei extern.
Neka je datoteka modul2.c sledeeg sadraja
extern char c;
void f()
{ c = 'a'; }

void g()
{ char c='b'; }
Dobijaju se sledei rezultati:
Pre funkcije f: c=w
Posle funkcije f: c=a
Posle funkcije g: c=a

Funkcija f menja vrednost eksterne promenljive c, a to mogu i druge funkcije iz ove datoteke
(modula).
Ako datoteka modul2.c ima sadraj
f() { extern char c; c='a'; }
takoe se menja vrednost promenljive c. Meutim, to nebi mogle da uine druge funkcije iz datoteke
modul2.c.
Statike promenljive se koriste u dva sluaja. U prvom sluaju, omoguava lokalnoj promenljivoj
da zadri vrednost kada se zavri blok u kome je deklarisana. Druga primena je u vezi sa globalnom
deklaracijom, i omoguuje mehanizam privatnosti globalnih promenljivih.
Primer. (1.primena)
#include<stdio.h>
void fun1()
{ static int x=0; int y=0;
printf("static=%d auto = %d\n",x,y); ++x,++y;
}
void main()
{ int i; for(i=0; i<3; ++i) fun1(); }

Izlaz je:
static=0 auto=0
static=1 auto=0
static=2 auto=0

U vezi sa drugom primenom, koristi se injenica da su statike promenljive lokalne u okviru


modula, jer im mogu pristupiti samo funkcije iz istog modula.

Pored promenljivih, i funkcije mogu da se definiu kao extern ili static. Memorijska klasa extern
se uzima po definiciji. Statike funkcije su dostupne samo funkcijama iz istog modula.

Korienje registarskih promenljivih omoguava programeru da utie na efikasnost izvrenja


programa. Ako funkcija esto koristi neku promenljivu, moe se zahtevati da se njena vrednost
memorie u brzim registrima centralne procesorske jedinice (CPU), uvek kada se funkcija izvrava.
Registarske promenljive su najee promenljive za kontrolu petlje i lokalne promenljive u

120
Ivan P. Stanimirovi Uvod u programiranje

funkcijama. Promenljiva se moe uiniti registarskom pomou kljune rei register.

Primer.
register char c;
register int i;

Promenljiva deklarisana kao registarska takoe je i automatska. Ako nema slobodnih registara u
CPU, C prevodilac ne prepoznaje greku.
Primer. Promenljiva i deklarie se kao registarska neposredno pre upotrebe u for petlji.
register int i;
for(i=0;i<5;++i) ...
Zavretak bloka u kome je deklarisana registarska promenljiva oslobaa registar.
5.8.1. ivotni vek objekata
ivotni vek objekta: vreme u toku izvravanja programa u kojem objekat postoji i za koje mu se
moe pristupati. Na poetku ivotnog veka, objekat se kreira, poziva se njegov konstruktor, ako ga
ima. Na kraju ivotnog veka se objekat unitava, poziva se njegov destruktor, ako ga ima.
5.8.2. Vrste objekata po ivotnom veku
Po ivotnom veku, objekti se dele na:
statike, automatske, dinamike, tranzijentne (privremene).
Vek atributa klase = vek objekta kome pripadaju.
Vek formalnog argumenta = vek automatskog objekta.
Formalni parametri se inicijalizuju vrednostima stvarnih argumenata.
Statiki i automatski objekti
Automatski objekat je lokalni objekat koji nije deklarisan kao static.
ivotni vek: od njegove definicije, do naputanja oblasti vaenja.
Kreira se iznova pri svakom pozivu bloka u kome je deklarisan.
Prostor za automatske objekte se alocira na stack-u.
Statiki objekat je globalni objekat ili lokalni deklarisan kao static.
ivotni vek: od izvravanja definicije do kraja izvravanja programa.
Globalni statiki objekti:
kreiraju se samo jednom, na poetku izvravanja programa,
kreiraju se pre korienja bilo koje funkcije ili objekta iz istog fajla,
nije obavezno da se kreiraju pre poziva funkcije main(),
prestaju da ive po zavretku funkcije main().
Lokalni statiki objekti poinju da ive pri prvom nailasku toka programa na njihovu
definiciju.
Primer.
int a=1;
void f() {
int b=1; // inicijalizuje se pri svakom pozivu
static int c=1; // inicijalizuje se samo jednom
cout<<"a="<<a++<<" b="<<b++<<" c="<<c++<<endl;
}
void main() {
while (a<3) f();
}

izlaz:
a = 1 b = 1 c = 1
a = 2 b = 1 c = 2

121
Ivan P. Stanimirovi Uvod u programiranje

6. STRUKTURNI TIPOVI PODATAKA

Pojam struktura podataka, nizova, slogova, skupova i datoteka je poznat i prisutan u viim
programskim jezicima od samog njihovog nastanka. U okviru strukturnih tipova podataka, vrednosti
koje tip obuhvata definisane su kao jednorodne ili raznorodne strukture podataka. U jeziku Pascal
postoji mogunost definisanja strukturnih tipova koji omoguavaju rad sa nizovima, slogovima,
skupovima i datotekama. Skupovi se kao strukturni tipovi podataka ree sreu kod drugih programskih
jezika, dok su nizovi, slogovi i datoteke postali standardni koncept, prisutan u mnogim programskih
jezicima (Ada, C).

6.1. Polja u programskim jezicima


Niz (Polje) (array) je indeksirana sekvenca komponenti istog tipa. Polja u programskim jezicima
jesu jednodimenzionalne ili viedimenzionalne strukture podataka koje obuhvataju vie vrednosti istog
tipa. Moe se rei, da jednodimenzionalna polja odgovaraju pojmu vektora, a viedimenzionalna
pojmu matrica. Bilo koji niz koji ima komponente nekog tipa T pri emu su vrednosti indeksa iz
nekog tipa S predstavlja preslikavanje S T. Duina (length) niza jeste broj njegovih komponenti,
koji se oznaava sa #S. Nizovi se mogu nai u svakom imperativnom i objektno orijentisanom jeziku.
Tip S mora da bude konaan, tako da je niz konano preslikavanje. U praksi, S je uvek rang uzastopnih
vrednosti, to se naziva rang indeksa niza (arrays index range). Granice opsega indeksa nazivaju se
donja granica (lower bound) i gornja granica (upper bound).
Kao i sve druge promenljive u programu, i niz se mora deklarisati pre nego to se upotrebi.
Deklaracijom niza kompajleru se saoptavaju sledei podaci o nizu: ime (koje je predstavljeno nekim
identifikatorom), tip elemenata niza i veliinu niza (broj elemenata tog niza). Bazine operacije nad
nizovima jesu:
konstruisanje (construction) niza iz njegovih komponenti;
indeksiranje (indexing), tj. selektovanje partikularne komponente niza, kada je zadat njegov
indeks. Indeks koji se koristi za selekciju komponente niza jeste vrednost koja se izraunava.
Programski jezici C i C++ ograniavaju indeks niza na celobrojne vrednosti ija je donja granica 0.
Opti oblik deklaracije niza u jeziku C je
<tip elemenata> <ime tipa> [<celobrojni izraz>];

PASCAL omoguava da rang za indeks niza moe biti odabran od strane programera, jedina
restrikcija je rang indeksa mora da bude diskretan primitivni tip.
Za opis ovih struktura u nekim programskim jezicima se koristi kljuna re array. Takav je sluaj u
jeziku PASCAL. Opti oblik deklaracije niza u PASCALu je
array[<tip indeksa>] of <tip elemenata>;
Razmotrimo sledei primer u jeziku PASCAL:
type VEKTOR = array [1..10] of real;
var A,B : VEKTOR;
Ovom definicijom definisan je tip VEKTOR, kao niz od 10 elemenata tipa real. Promenljive A i B
su deklarisane kao promenljive tipa VEKTOR. Svakoj od promenljivih A i B odgovara struktura
podataka koja se sastoji od 10 komponenti tipa real. Svakoj od komponenti vektora opisanog na ovaj
nain moe se pristupiti preko indeksa. U nekim jezicima (Pascal) koristi se i notacija sa uglastim
zagradama na primer A[3] i A[J]. U ovakvim sluajevima indeks moe da bude definisan i kao
celobrojni izraz. Ove indeksirane promenljive mogu se u programu upotrebiti svuda gde se javljaju i
proste promenljive odgovarajueg tipa. U datom primeru A(J) i B(J) su promenljive tipa real. Evo
nekih primera koji ilustruju upotrebu niza:
A[3]:= 0.0; - Treem elementu vektora A dodeljuje se vrednost 0;

122
Ivan P. Stanimirovi Uvod u programiranje

X := A[3]; - promenljiva X dobija vrednost treeg elementa vektora A.


Polja se realizuju kao statike strukture podataka, to znai da se za svaki odreeni vektor rezervie
unapred definisani prostor u memoriji raunara. Granice indeksa u definiciji tipa mogu da budu date i
preko promenljivih ili ak i preko izraza, ali ove vrednosti treba da budu poznate u taki programa u
kojoj se pojavljuje definicija tipa. Evo nekih definicija takvog oblika u jeziku Pascal:
type VEKTOR1 = array [1 .. N] of float;
type VEKTOR2 = array [N .. N+M] of float;
U svim ovim primerima, za definisanje indeksa je iskorien interval u skupu celih brojeva
(integer). To je i prirodno, jer se najee za indeksiranje i u matematici koriste celobrojne vrednosti.
U Pascal-u i Adi se za definisanje indeksa moe koristiti bilo koji diskretni tip podataka. Razmotrimo
sledei primer u kome se kreira tabela sa podacima o koliini padavina u svakom mesecu jedne godine
u jeziku Ada:
type PADAVINE is delta 0.1 range 0.0 .. 200.0;
type MESECI is JAN,FEB,MAR,APR,MAJ,JUN,JUL,AVG,SEP,OKT,NOV,DEC);
type KOL_PAD is array [MESECI] of PADAVINE;

U programu se mogu koristiti promenljive tipa KOL_PAD.


PODACI: KOL_PAD;
Analogni tip podataka u jeziku Pascal je dat sledeim definicijama:
type MESECI = (JAN,FEB,MAR,APR,MAJ,JUN,JUL,AVG,SEP,OKT,NOV,DEC);
type KOL_PAD = array [MESECI] of real;
var PODACI: KOL_PAD;
U ovom primeru definisan je strukturni tip podataka KOL_PAD, za ije indeksiranje se koristi
diskretni tip nabrajanja MESECI, tako da vektor PODACI ima ukupno 12 komponenti, od kojih svaka
odgovara jednom mesecu u godini. Svakoj od ovih komponenti pristupa se preko imena meseca kao
indeksa. Na taj nain, u programu e PODACI[MART] biti promenljiva kojoj se dodeljuje vrednost
koja odgovara padavinama u mesecu martu. Diskretni tipovi podataka se mogu koristiti za definisanje
opsega indeksa, tako to se u okviru skupa vrednosti odreenog diskretnog tipa koristi samo interval
vrednosti. Na primer, u razmatranom primeru moglo je da bude postavljeno ogranienje da se
razmatraju padavine u letnjem periodu godine. U tom sluaju, pogodno je indeks vektora PODACI
definisati tako da ima samo komponente koje odgovaraju letnjim mesecima.

6.2. Jednodimenzionalni nizovi u C


Deklaracija jednodimenzionalnog niza se sastoji od imena tipa iza koga sledi identifikator (ime
niza) i na kraju celobrojni izraz izmeu srednjih zagrada. Vrednost ovog izraza mora da bude
pozitivan ceo broj i predstavlja veliinu niza. Indeksiranje elemenata niza poinje od 0.
Opta forma izraza kojom se deklarie niz je sledea:
<tip elemenata> <ime> [<celobrojni izraz>];
Veliina niza zadaje se konstantom ili konstantnim celobrojnim izrazom. Na primer, izrazom
int b[100] deklarie se niz sa 100 celobrojnih vrednosti. Niz b se sastoji od 100 celobrojnih
(indeksiranih) promenljivih sa imenima b[0], ..., b[99].
Komponentama niza se pristupa navoenjem imena niza i celobrojnog izraza izmeu srednjih
zagrada. Ovim izrazom se definie indeks eljenog elementa niza. Ako je indeks manji od 0 ili vei ili
jednak od broja elemenata u nizu, nee se pristupiti elementu niza.

Nizovi mogu da imaju memorijsku klasu auto, extern, static, a ne mogu biti memorijske klase
register.
Nizovi se mogu inicijalizovati u naredbi deklaracije.
Primer. Posle inicijalizacije

123
Ivan P. Stanimirovi Uvod u programiranje

float x[7]={-1.1,0.2,33.0,4.4,5.05,0.0,7.7};
dobija se
x[0]=-1.1, x[1]=0.2, x[6]=7.7.
Lista elemenata koji se koriste za inicijalizaciju vektora moe biti manja od broja njegovih
elemenata. Ako je niz memorijske klase static ili extern, njegovi preostali elementi postaju 0. U
sluaju da je niz memorijske klase auto, za ove vrednosti e biti neke vrednosti koje su zaostale od
ranije u delu memorije koja se koristi za smetanje elemenata niza. Ako extern ili static niz nije
inicijalizovan, tada kompajler automatski inicijalizuje sve elemente na 0.
Ako je niz deklarisan bez preciziranja duine, i pritom inicijalizovan, tada se duina niza implictno
odreuje prema broju inicijalizatora.
Na primer, izraz int a[]={3,4,5,6}; proizvodi isto dejstvo kao i izraz
int a[4]={3,4,5,6};
Primer. Deklaracije nizova.

Primer. Pristup elementima nizova.

Primeri.
Primer. Izraunati broj pojavljivanja svakog velikog slova u unetom tekstu.
#include <stdio.h>
#include <ctype.h>
void main()
{ int c,i, slova[26];
for(i=0;i<26;++i) slova[i]=0;
while((c=getchar()) !=EOF)
if(isupper(c)) ++slova[c-'A'];
for(i=0;i<26;++i)

124
Ivan P. Stanimirovi Uvod u programiranje

{ if(i%6==0) printf("\n");
printf("%5c:%4d", 'A'+i, slova[i]);
}
printf("\n\n");
}

Primer. Napisati program kojim se izraunava n-ti stepen broja 2, gde je n<= 500, i traeni stepen
nema vie od 200 cifara.
void main()
{ int i,n,d=0,j,p, x[200]; // d+1 je broj cifara u stepenu, p je prenos
printf("\n Unesi stepen --> "); scanf("%d",&n);
x[0]=1;
for(i=0; i<n; i++)
{ p=0;
for(j=0; j<=d; j++){x[j]=x[j]*2+p; p=x[j]/10; x[j] %=10; }
if(p!=0) { d++; x[d]=p; }
}
printf("%d. stepen broja 2 je ",n);
for(i=d; i>=0; i--)printf("%d",x[i]);
}
Primer. Binarno traenje.
Posmatra se sledei matematiki problem: zadat je ureen realni niz a[0]<a[1]<<a[n-1] i realan
broj b; ustanoviti da li se b nalazi u nizu, i ako se nalazi odrediti indeks p za koji vai a[p]=b.
Najjednostavnije, ali i najneefikasnije je takozvano linearno pretraivanje: redom se uporeuju
elementi niza a sa brojem b, do prvog elementa niza a za koji je a[i]>=b. Ako je a[i]=b, tada je p = i
traeni indeks. Ako je a[i]>b, tada se broj b ne nalazi u nizu a.
Za brzo pretraivanje se koristi algoritam binarnog pretraivanja.
Pretpostavimo da postoji p[0, n-1] takav da je a[p] = b. Izaberemo srednji element niza a sa
indeksom s = (0+n-1)/2. Ako je a[s]=b, tada je p=s traeni indeks, a pretraivanje se prekida. Ako je
ispunjen uslov b < a[s], tada se indeks p nalazi u intervalu [0,s-1], a inae se nalazi u intervalu [s+1,n-
1]. U oba sluaja, prepolovljen je interval pretraivanja.
Napisati funkciju koja prema opisanom algoritmu odreuje indeks onog elementa rastueg niza a
koji je jednak zadatoj vrednosti b, a inae vraa rezultat -1.
#include<stdio.h>
void main()
{ float br, a[100];
int n,i,p;
int bintra(float a[], int n, float b);
printf("\nBroj elemenata? "); scanf("%d",&n);
printf("Elementi niza "); for(i=0; i<n; i++)scanf("%f", &a[i]);
printf("Jedan realan broj? "); scanf("%f",&br);
p=bintra(a, n, br);
printf("Pozicija broja %f u nizu je %d\n",br,p);
}

int bintra(float a[], int n, float b)


{ int l,d,s;
l=0; d=n-1;
while(l<=d)
{ s=(l+d)/2;
if(b==a[s]) return(s);
else if(b<a[s])d=s-1;
else l=s+1;
}
return(-1);

125
Ivan P. Stanimirovi Uvod u programiranje

Odgovarajua rekurzivna funkcija je


#include<stdio.h>
main()
{ float br, a[100];
int n,i,p;
int bintra1(float a[], int l, int d, float b);
printf("\nBroj elemenata? "); scanf("%d",&n);
printf("Elementi niza ");
for(i=0; i<n; i++)scanf("%f", &a[i]);
printf("Jedan realan broj? "); scanf("%f",&br);
p=bintra1(a, 0, n-1, br);
printf("Pozicija broja %f u nizu je %d\n",br,p);
}

int bintra1(float a[], int l, int d, float b)


{ int s;
if(l>d) return(-1);
else
{ s=(l+d)/2;
if(b==a[s]) return(s);
else if(b<a[s])return bintra1(a,l,s-1,b);
else return bintra1(a,s+1,d,b);
}
}
1. (C) Napisati funkciju koja uitava broj elemenata u nizu kao i elemente niza. Napisati funkciju
koja od dva neopadajua niza a[0..m-1] i b[0..n-1] formirati rastui niz c[0..k-1] u kome se elementi
koji se ponavljaju u polaznim nizovima pojavljuju samo jednom. Napisati test program.
#include<stdio.h>
int a[50], b[50], c[50];

void citaj(int x[], int *n)


{ printf("Broj elemenata = ? "); scanf("%d",n);
printf("Elementi?\n"); for(int i=0; i<*n; i++)scanf("%d",x+i);
}

void formiraj(int a[], int b[], int c[], int m, int n, int *k)
{ int i=0,j=0,last;
last = ((a[0]<b[0])?a[0]:b[0])-1;
*k=0;
while(i<m || j<n)
if(i==m){ for(int l=j; l<n; l++)c[(*k)++]=b[l]; j=n;}
else if(j==n){ for(int l=i; l<m; l++)c[(*k)++]=a[l]; i=m; }
else if(a[i]<b[j])
{ if(a[i]!=last) {c[(*k)++]=a[i]; last=a[i];}
i++;
}
else if(b[j]<a[i])
{ if(b[j]!=last){ c[(*k)++]=b[j]; last=b[j]; }
j++;
}
else
{ if(a[i]!=last) {c[(*k)++]=a[i]; last=a[i];}
i++; j++;
}
}

void main()
{ int i,m,n,k;

126
Ivan P. Stanimirovi Uvod u programiranje

citaj(a,&m); citaj(b,&n);
formiraj(a,b,c,m,n,&k);
for(i=0; i<k;i++)printf("c[%d] = %d\n",i,c[i]);
}
Primer. Postupkom Eratostenovog sita ispisati sve proste brojeve od 2 do n. Postupak se sastoji u
sledeem:
Formira se niz koji sadri prirodne brojeve 2 do n.
Iz niza se izbacuju svi brojevi koji su deljivi sa 2, 3. Brojevi deljivi sa 4 su izbaeni zbog
deljivosti sa 2, i tako dalje.
U nizu ostaju prosti brojevi.
#include <stdio.h>
void main() {
int a[1001], n, i, j;
scanf("%d",&n);
for (i=2; i<=n; i++) a[i]=1;
for (i=2; i<=n; i++)
if (a[i]) {
j=2*i; while (j<=n) { a[j]=0; j+=i; }
}
for (i=2; i<=n; i++) if (a[i]) printf("%d\n",i);
}
Primer. Napisati funkciju za deljenje polja P na dva dela, pri emu u polje P1 ulaze svi elementi polja
P vei od zadatog broja k, a u polje P2, svi elementi polja P manji od k. Elementi polja P1 i P2 treba
da budu sortirani.
#include<stdio.h>
#include<iostream.h>

void main(void){
int p[20],p1[20],p2[20],n,i,j,zadati,br1,br2;

cout<<"\n Unesite dimenziju niza:"; cin>>n;


cout<<"\n Unesite elemente niza:\n";
for(i=0; i<n; i++) cin>>p[i];
cout<<"\n Unesite zadati element:"; cin>>zadati;
br1=0; br2=0;
for(i=0; i<n; i++)
{ if(p[i]>zadati) { p1[br1]=p[i]; br1++; }
else { p2[br2]=p[i]; br2++; };
};
for(i=0; i<br1-1; i++)
{ for(j=i+1; j<=br1-1; j++)
{ if(p1[i]>p1[j]){ zadati=p1[i]; p1[i]=p1[j]; p1[j]=zadati; };
};
};

for(i=0; i<br2-1; i++)


{ for(j=i+1; j<=br2-1; j++)
{ if(p2[i]>p2[j]){ zadati=p2[i]; p2[i]=p2[j]; p2[j]=zadati; };
};
};
cout<<"\n Polje P1\n";
for(i=0; i<br1; i++) cout<<"\n P1["<<i<<"]="<<p1[i];
cout<<"\n\n\n Polje P2\n";
for(i=0; i<br2; i++) cout<<"\n P2["<<i<<"]="<<p2[i];
cout<<"\n\n";
}
Primer. Definisati sve varijacije sa ponavljanjem i varijacije bez ponavljanja.

#include <stdio.h>

127
Ivan P. Stanimirovi Uvod u programiranje

bool mark[33];

void ispisi_varijacije_sa_ponavljanjem(int x, int n, int k, int a[], int


v[]) {
int i;
if (x==k) {
printf(" ");
for(i=0; i<k; i++) printf("%d ", v[i]);
printf("\n");
} else {
for(i=0; i<n; i++) {
v[x]=a[i];
ispisi_varijacije_sa_ponavljanjem(x+1,n,k,a,v);
}
}
}

void ispisi_varijacije_bez_ponavljanja(int x, int n, int k, int a[], int


v[]) {
int i;
if (x==k) {
printf(" ");
for(i=0; i<k; i++) printf("%d ", v[i]);
printf("\n");
} else {
for(i=0; i<n; i++) if (!mark[i]) {
mark[i]=true;
v[x]=a[i];
ispisi_varijacije_bez_ponavljanja(x+1,n,k,a,v);
mark[i]=false;
}
}
}

int main() {
int n,i,k,a[33],v[33];
scanf("%d", &n);
for(i=0; i<n; i++) scanf("%d", &a[i]);

printf("unesite k: "); scanf("%d", &k);

printf("Sve varijacije(n,k) sa ponavljanjem: \n");


ispisi_varijacije_sa_ponavljanjem(0,n,k,a,v);

printf("Sve varijacije(n,k) bez ponavljanja: \n");


ispisi_varijacije_bez_ponavljanja(0,n,k,a,v);

//printf("Sve kombinacije: \n");


//ispisi_sve_kombinacije(n,a);

return 0;
}

Problem ranca
#include <cstdio>

int main (){


int C, m, d[1000], t[100], v[100], uzeti[1000];
scanf("%d%d", &C, &m);

128
Ivan P. Stanimirovi Uvod u programiranje

for (int i=0; i<m; i++) scanf("%d%d", t+i, v+i);

d[0]=0;
uzeti[0]=0;

for (i=1; i<=C; i++){


d[i]=0;
for (int j=0; j<m; j++){
if (i-t[j]>=0) {
int tmp=d[i-t[j]]+v[j];
if (tmp>d[i]) {
d[i]=tmp;
uzeti[i]=j;
}
}
}
}

printf("Optimalna vrednost ranca sa nosivoscu %d je: %d\n", C, d[C]);


printf("Uzeti predmeti redom su: \n");
i=C;
int k=1;
while (i>0){
k++;
printf("Tezina %d-tog predmeta je: %d i vrednost %d-tog
predmeta je: %d\n", k, t[uzeti[i]], k, v[uzeti[k]]);
i-=t[uzeti[i]];
}

return 0;
}

Primer (C) Dat je skup S od n (n 100) razliitih prirodnih brojeva od kojih ni jedan nije vei od 200.
Napisati program koji pronalazi jedan podskup A datog skupa S koji zadovoljava sledea dva uslova:
a) Suma elemenata skupa A je deljiva sa tri;
b) Od svih podskupova skupa S koji zadovoljavaju osobinu a), podskup A ima najveu sumu
svojih elemenata.
Ulazni podaci se uitavaju iz fajla zad1.dat. U prvom redu fajla se nalazi broj n, a u nastavku
fajla se nalazi n elemenata skupa S (svaki element je naveden u posebnom redu fajla).
Program treba da napravi fajl zad1.res i u njega treba da upie sumu elemenata podskupa A (u
prvom redu fajla) i sve elemente podskupa A (u nastavku fajla, svaki element se upisuje u posebnom
redu fajla).
Primer:
zad1.dat zad1.res
4 147
29 29
15 15
11 103
103

#include <stdio.h>
int main(){
FILE *f,*g;
int am1,am2,bm1,bm2,n,i,a[100],ost,i1,i2,i3,i4;
long sumaniza;
f=fopen("zad12.dat","r");
g=fopen("zad12.res","w");
fscanf(f,"%d",&n);
am1=am2=bm1=bm2=ost=0;

129
Ivan P. Stanimirovi Uvod u programiranje

sumaniza=0;
i1=i2=i3=i4=-1;
for(i=0;i<n;i++)
{
fscanf(f,"%d",&a[i]);
if(((a[i]%3)==1)&&((am1==0)||(am1>a[i])))
{
am2=am1;
am1=a[i];
i1=i;
}
else if(((a[i]%3)==1)&&((am2==0)||(am2>a[i])))
{
am2=a[i];
i2=i;
}
if(((a[i]%3)==2)&&((bm1==0)||(bm1>a[i])))
{
bm2=bm1;
bm1=a[i];
i3=i;
}
else if(((a[i]%3)==1)&&((bm2==0)||(bm2>a[i])))
{
bm2=a[i];
i4=i;
}
sumaniza+=a[i];
ost=((ost+a[i])%3);
}
if(((ost==1)&&(i1==-1)&&(i4==-1))||
((ost==2)&&(i2==-1)&&(i3==-1)))
{
fprintf(g,"0\n0\n");
fclose(f);
fclose(g);
return 0;
}
if(ost==0)
{
fprintf(g,"%ld\n",sumaniza);
for(i=0;i<n;i++)
fprintf(g,"%d\n",a[i]);
}
else if(ost==1)
{
if(am1<bm1+bm2)
{
fprintf(g,"%ld\n",sumaniza-am1);
for(i=0;i<n;i++)
if(i!=i1)
fprintf(g,"%d\n",a[i]);
}
else
{
fprintf(g,"%ld\n",sumaniza-bm1-bm2);
for(i=0;i<n;i++)
if((i!=i3)&&(i!=i4))
fprintf(g,"%d\n",a[i]);
}
}

130
Ivan P. Stanimirovi Uvod u programiranje

else
{
if(bm1<am1+am2)
{
fprintf(g,"%ld\n",sumaniza-bm1);
for(i=0;i<n;i++)
if(i!=i3)
fprintf(g,"%d\n",a[i]);
}
else
{
fprintf(g,"%ld\n",sumaniza-am1-am2);
for(i=0;i<n;i++)
if((i!=i1)&&(i!=i2))
fprintf(g,"%d\n",a[i]);
}
}
fclose(f);
fclose(g);
return 0;
}

Kratko objanjenje reenja.


Prvo postavimo sve promenljive na odgovarajue poetne poloaje. Zatim iz datoteke najpre uitamo broj
elemenata skupa S a zatim i sve elemente skupa S. Pri uitavanju izdvajamo po dva najmanja elementa skupa S
koji pri deljenu sa tri daju ostatke jedan odnosno dva. Ova dva elementa su bitna jer e mo odgovarajui skup A
dobiti zapravo izbacivanjem najvie dva elementa skupa S koji daju potrebne ostatke pri deljenju sa tri, a da bi
suma elememenata novodobijenog skupa A bila maksimalna potrebno je da elementi koje izbacujemo budu
najmanji mogui. Zatim ispitujemo ostatak zbira elemenata skupa S pri deljenju brojem tri i u zavisnosti od tog
ostatka ispitujemo najmanje elemente koji daju odgovarajui ostatak i u izlaznu datoteku tampamo skup S bez
elemenata koje smo izbacili.
Zadatak 1. Dato je n tegova (n 20), ije su mase realni brojevi. Podeliti tegove u dve grupe, tako da
ukupne mase tegova u grupama budu to priblinije. tampati minimalnu razliku, i za svaku od grupa
mase tegova u toj grupi, kao i ukupnu masu tegova u grupi.
#include<stdio.h>
#include<math.h>
main()
{ float teg[20];
int grupa[20], grupa1[20];
int i,j,k,n;
float razlika, minrazlika, suma,suma1, minsuma1;
printf("\n Broj tegova? "); scanf("%d", &n);
printf("\nMase tegova? \n");
for(i=0; i<n; i++) scanf("%f", &teg[i]);
suma=0;
for(i=0; i<n; i++)
{ grupa[i]=0; suma += teg[i]; }
minrazlika = suma;
printf("suma = %f\n", suma);
do { suma1=0;
for(i=0; i<n; i++) if(grupa[i]) suma1 += teg[i];
razlika=fabs(suma-2*suma1);
if(razlika < minrazlika)
{ minrazlika=razlika;
minsuma1=suma1;
for(i=0; i<n; i++) grupa1[i]=grupa[i];
}
j=n;
while(j>=0 && grupa[j]) { grupa[j]=0; j--; }

131
Ivan P. Stanimirovi Uvod u programiranje

if(j>=0) grupa[j]=1;
}
while(j>=0);
printf("\nMinimalna razlika =
%f\n",minrazlika);
printf("Prva grupa ima sledece tegove:\n");
for(i=0; i<n; i++) if(grupa1[i])printf("%f ",teg[i]);
printf("\nUkupna masa tegova prve grupa je %f",
minsuma1);
printf("\nDruga grupa ima sledece tegove:\n");
for(i=0; i<n; i++) if(!grupa1[i])printf("%f ",teg[i]);
printf("\nUkupna masa tegova druge grupa je %f",
(suma-minsuma1));
}

Primer. Pretpostavimo da elite da postavite broj sobe na vratima. U prodavnici je mogue kupiti
skup plastinih cifara. Svaki skup sadri po jednu cifru od 0 do 9. Broj sobe je izmeu 1 i 1,000,000.
Odrediti koliko skupova cifara je potrebno kupiti u prodavnici da bi ste ispisali broj sobe, imajui u
vidu da 6 moete iskoristiti i kao 9 i obrnuto. U prvom redu datoteke zad1.in se nalazi broj n, a u
ostalih n redova po jedan broj koji oznaava broj koji bi trebalo ispisati. U datoteci zad1.out upisati
minimalni broj skupova cifara koji uz pomo kojih moemo ispisati dati broj.

zad1.in zad1.out
4 2
122 2
9999 l
12635 6
888888
Primer. U prvom redu datoteke 'zadl.in' nalazi se ceo broj n (1 n 1000). U svakom od sledeih n
redova nalaze se po dva cela broja x i y (-10000 x,y 10000) koji predstavljaju koordinate take u
ravni. Napisati program koji u datoteku 'zadl.out' upisuje, na dve decimale, rastojanje od koordinatnog
poetka take koja je najblia koordinatnom poetku. Iza rastojanja, odvojeno prazninom, upisati redni
broj te najblie take u datoteci.
zad1.in zad1.out
7 5.00 5
-9 12
-12 -16
5 12
15 8
3 4
-8 -6
20 -15
Primer. Meteoroloka stanica meri temperaturu jednom u minutu. Stanica ima termometar koji ne daje
uvek tane rezultate pri merenju temperature. Zbog nedostatka sredstava, odlueno je da se umesto
novog termometra finansira izrada programa koji uklanja netane rezultate merenja i kao rezultat daje
prosenu temperaturu. Merenje se rauna u netano u dva sluaja:
a. Izmerena temperatura je manja od-50 stepeni;
b. Izmerena temperatura se od svake od temperatura merenih u prethodna 2 minuta i
sledea dva minuta razlikuje za vie od 2.
Napisati program koji za zadati niz izmerenih temperatura izraunava srednju vrednost ispravnih
temperatura.
U ulaznoj datoteci 'zad2.in' dati su broj n (1 n 1000) koji predstavlja broj merenja, kao i brojevi t1,
..., tn koji predstavljaju izmerene vrednosti (- 60 ti 50, i {1,...,n}). U izlaznu datoteku 'zad2.out'
upisati, na dve decimale, srednju vrednost ispravno izmerenih temperatura.

132
Ivan P. Stanimirovi Uvod u programiranje

zad2.in zad2.out
5 12.00
9 11 12 13 15
7 0.16
0 0 0 2 5 0 10

6.3. Veza izmeu nizova i pointera u C


Ime niza je konstantni pokaziva na poetak niza, tj. adresa njegovog nultog elementa. Ime niza je
samo po sebi jedna adresa, ili vrednost pointera (pointer je promenljiva koja uzima adrese za svoje
vrednosti). Kada je niz deklarisan, kompajler alocira baznu adresu i dovoljan memorijski prostor za
smetanje svih elemenata niza. Kompajler jezika C sam prevodi oznake niza u pokazivae, pa se
korienjem pokazivaa poveava efikasnost u radu sa nizovima.
Primer. Neka je data deklaracija
#define N 100
long a[N], *p;
Pretpostavimo da je prva adresa za smetanje niza a jednaka 300 (ostale su 304,308,,696).
Naredbe
p = a; p=&a[0];
su ekvivalentne. U oba sluaja promenljiva p uzima za svoju vrednost adresu nultog elementa niza a.
Preciznije, promenljivoj p se dodeljuje vrednost 300.
Takoe, naredbe
p=a+1; p=&a[1];
su ekvivalentne i dodeljuju vrednost 304 promenljivoj p. Analogno, naredbe p = a + i i p = &a[i] su
ekvivalentne, za svaki element a[i] niza a. Ako su elementima niza a pridruene vrednosti, one se
mogu sumirati koristei pointer p, na sledei nain:
sum=0;
for(p=a; p<&a[N]; sum += *p, ++p);

Isti efekat se moe postii sledeim postupkom:


sum=0;
for(i=0;i<N;++i) sum += *(a+i);

Napomenimo da je izraz *(a+i) ekvivalentan sa a[i]. Takoe, moe se pisati p = &(*(a+i)) umesto
izraza p = a + i, odnosno p = &a[i].
Primer. Jo jedan nain sumiranja nizova.
p=a; sum=0;
for(i=0;i<N;++i) sum += p[i];

Meutim, postoji razlika izmeu pointera i nizova. Kako je ime niza a konstantni pointer, a ne
promenljiva, ne mogu se koristiti izrazi
a = p++a a+=2.
To znai da se adresa niza ne moe menjati.
Primer. Napisati program koji transformie niz celih brojeva tako da na poetku budu negativni a na
kraju nenegativni elementi tog niza.
#include<stdio.h>
void main(void)
{ int niz[100], p,i,k,n;
printf("\nBroj elemenata --> "); scanf("%d",&n);
for(i=0; i<n; i++)
{ printf("niz[%d]=--> ",i+1); scanf("%d",niz+i); }

133
Ivan P. Stanimirovi Uvod u programiranje

p=0; k=n-1;
while(p<k)
{ while(niz[p]<0 && p<k)p++;
while(niz[k]>=0 && p<k)k--;
if(p<k)
{ int pom=niz[p]; niz[p]=niz[k]; niz[k]=pom; }
}
for(i=0; i<n; i++)printf("niz[%d] = %d ",i,niz[i]); printf("\n");
}
Dato je jedno reenje koje koristi ime niza kao pokaziva.
#include<stdio.h>
void main(void)
{ int niz[100], *p,*k,i,n;
printf("\nBroj elemenata --> "); scanf("%d",&n);
for(i=0; i<n; i++){printf("niz[%d]= --> ",i+1); scanf("%d",niz+i); }
p=niz; k=niz+n-1;
while(p<k)
{ while(*p<0 && p<k)p++;
while(*k>=0 && p<k)k--;
if(p<k) { int pom; pom=*p; *p=*k; *k=pom; }
}
for(i=0; i<n; i++)printf("niz[%d]= %d ",i,*(niz+i)); printf("\n");
}
Neka je, za ovaj primer zadat broj elemenata n = 4, i neka su elementi -1,2,-3,4. Neka je vrednost
pokazivaa p=&a[0] jednaka heksadekadnom broju 0x0012fdf0. Ako je program napisan u
programskom jeziku C++, tada svaka vrednost tipa int zauzima po 4 bajta, pa je vrednost pokazivaa
k=&a[3] jednaka heksadekadnom broju 0x0012fdfc. Adrese i sadraj lokacija koje su zauzete
zadatim elementima niza predstavljene su u sledeoj tabeli:
Element niza Adresa prvog bajta Adresa drugog bajta Adresa treeg bajta Adresa etvrtog bajta
a[0] 0x0012fdf0= &a[0] 0x0012fdf1 0x0012fdf2 0x0012fdf3
a[1] 0x0012fdf4= &a[1] 0x0012fdf5 0x0012fdf6 0x0012fdf7
a[2] 0x0012fdf8= &a[2] 0x0012fdf9 0x0012fdfa 0x0012fdfb
a[3] 0x0012fdfc= &a[3] 0x0012fdfd 0x0012fdfe 0x0012fdff

Primer. Sortiranje niza pointerskom tehnikom. Kao algoritam izabrano je sortirane izborom
uzastopnih minimuma.
#include<stdio.h>
void upis(int *a, int *n)
{ int i;
printf("Broj elemenata? "); scanf("%d",n);
printf("Elementi? ");
for(i=0; i<*n; i++) scanf("%d",a+i);
}

void ispis(int *a, int n)


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

void ureenje(int *a, int n)


{ int i,j,pom;
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(*(a+i)>*(a+j))
{pom=*(a+i); *(a+i)=*(a+j); *(a+j)=pom; }
}

void main()

134
Ivan P. Stanimirovi Uvod u programiranje

{ void upis(int *, int*); void ispis(int *, int);


int x[100],k;
upis(x, &k); ureenje(x,k); ispis(x,k);
}

6.3.1. Pointerska aritmetika


U jeziku C dozvoljene su aritmetike operacije nad pokazivaima. Dozvoljeno je:
- dodeliti pokazivau adresu promenljive ili nulu (vrednost NULL);
- uveati ili umanjiti vrednost pokazivaa;
- dodati vrednosti pokazivaa neki ceo broj;
- oduzeti od vrednosti pokazivaa neki ceo broj;
- porediti dva pokazivaa pomou operacija ==, !=, i tako dalje;
- oduzeti od jednog pokazivaa drugi, ako ukazuju na objekte istog tipa.
Pointerska aritmetika predstavlja veliku prednost jezika C u odnosu na druge jezike visokog nivoa.
U sledeoj tabeli su uvedene pretpostavke:
a: vektor sa elementima tipa T,
n: celobrojni izraz,
v: zraz tipa T,
pa1, pa2: ukazatelj na tip T, kojima se ukazuje na elemente vektora a.
U njoj su prikazana neka pravila pointerske (adresne) aritmetike:

Oznaka Znaenje Tip rezultata


a ukazatelj na prvi element vektora a ukazatelj na T
&a[0] ukazatelj na prvi element vektora a ukazatelj na T
&a[n] ukazatelj na n+1 element vektora a ukazatelj na T
*pa1 element vektora na koji pa1 ukazuje T
*pa1 = v dodeljuje vrednost v elementu na koji pa1 ukazuje T
++pa1 postavlja pa1 na sledei element vektora a ukazatelj na T
--pa1 postavlja pa1 na prethodni element vektora a ukazatelj na T
*++pa1 inkrementira pa1, a zatim pristupa elementu na koji pa1 ukazuje T
pristupa elementu vektora a na koji pa1 ukazuje, zatim
*pa1++ T
inkrementira pa1
ukazuje na n-ti naredni (prethodni) element poev od elementa
pa1n ukazatelj na T
na koji pa1 ukazuje
vrednost v dodejluje n-tom narednom elementu u odnosu na
*(pa1+n) = v T
element na koji pa1 ukazuje
ispituje vrednosti adresa u pa1 i pa2 pomou relacionih
pa1>pa2 int
operatora
*(a+n) n-ti element vektora a T

Primer.
void main()
{ double a[2], *p, *q;
p=&a[0]; q=p+1;
printf("%d\n",q-p); /* 1 */
printf("%d\n",(int)q-(int)p); /* 8 */
}

Primer. Date su deklaracija


int x[4], *pti;
i dodela
pti=x;

135
Ivan P. Stanimirovi Uvod u programiranje

Ako je niz x smeten poev od adrese 56006(=&x[0]), odrediti lokacije i elemente niza x na koji
ukazuju pti, pti+1, pti+2 i pti+3.

Reenje. Dodavanje jedinice pokazivau pti automatski uveava adresu na koju on ukazuje za 2, jer
se radi o pokazivau na tip int. Znai, pti, pti+1, pti+2 i pti+3 ukazuju redom na adrese 56006, 56008,
56010, 56012 i na elemente x[0], x[1], x[2], x[3] niza x.
Iz prethodnog primera zakljuujemo
*(x+2)=x[2], x+2=&x[2].
Izraz *x+2 jednak je izrazu (*x)+2 i predstavlja uveanje vrednosti nultog elementa niza x za 2.

U sledeoj tabeli je prikazan odnos izmeu * i ++.

6.4. Nizovi i dinamika alokacija memorije u C


Za razliku od vektora i skalarnih promenljivih, kojima se implicitno dodeljuje memorija prilikom
njihovog stvaranja i oslobaa prilikom brisanja, nezavisno od volje programera, dinamike strukture
zahtevaju eksplicitno dodeljivanje i oslobaanje memorije.
U biblioteci stdlib.h nalaze se definicije funkcija malloc, calloc, free i realloc, kojima se moe
eksplicitno upravljati memorijom. Definicija i semantika ovih funkcija je sledea:
1. char *malloc(size)
rezervie memorijski blok veliine size uzastopnih bajtova. Argument size je tipa unsigned. U sluaju
da rezervacija memorije uspe, ova funkcija vraa pointer na tip char, koji ukazuje na rezervisani
memorijski blok, a inae vraa 0. Ova funkcija ne menja sadraj memorije koja je izdvojena.
2. char *calloc(n, size)
rezervie memorijski blok dovoljan za smetanje n elemenata veliine size bajtova, tj. rezervie n*size
uzastopnih bajtova. Rezervisani memorijski prostor se inicijalizuje na 0. Ako je rezervacija uspena,
rezultat je pointer na char, koji ukazuje na rezervisani memorijski blok, a inae 0.
3. void free(point)
oslobaa memorijski prostor koji je rezervisan funkcijama calloc ili malloc. Argument point je pointer
na char, koji ukazuje na memorijski prostor koji se oslobaa. Ova funkcija ne vraa vrednost.
Pokaziva point mora da ima vrednost koja je dobijena primenom funkcija malloc() i calloc().
4. char *realloc(point, size)
oslobaa rezervisani memorijski blok i rezervie novi, veliine size bajtova. Argument point je pointer
na char i ukazuje na memorijski blok koji se realocira. Argument size je tipa unsigned i odreuje
veliinu realociranog memorijskog prostora.
Primer. Naredbama
int *pint;
pint = (int *)malloc(400);
izdvaja se 400 uzastopnih bajtova. Ovaj memorijski prostor je dovoljan za smetanje 200 celih brojeva
u jeziku C, odnosno 100 celih brojeva u C++.

136
Ivan P. Stanimirovi Uvod u programiranje

Takoe, vrednost izraza


pint = (int*)malloc(400);
je pokaziva na tip int, koji se dobija konverzijom pokazivaa na char pomou kast operatora. Ako tip
int zauzima 4 bajta, tada pint+1 uveava pokaziva za 4 bajta, i predstavlja adresu sledeeg celog
broja. Na taj nain, 400 bajtova se koristi za smetanje 100 celih brojeva.
Ako elimo da izdvojimo onoliko memorije koliko je potrebno za za uvanje vrednosti izraza ili
podataka odreenog tipa, koristi se operator sizeof na jedan od sledea dva naina:
sizeof(izraz); - vraa memorijski prostor koji je dovoljan za smetanje izraza izraz;
sizeof(T); - vraa memorijski prostor koji je dovoljan za uvanje vrednosti tipa T.

Primer. Pomou operatora


pint = (int *)malloc(sizeof(int));
izdvaja se memorijski prostor za celobrojnu vrednost. Adresa te oblasti se dodeljuje promenljivoj pint.
Noviji C prevodioci ne zahtevaju promenu tipa pokazivaa koji vraa funkcija malloc(), jer je njen
rezultat tzv. generiki pokaziva oblika void *, koji pokazuje na objekat bilo kog tipa.
Primer. Operatorima
long *plong;
plong = (long*)calloc(100, sizeof(long));
izdvaja se (i inicijalizuje na 0) memorijski prostor dovoljan za smetanje 100 vrednosti tipa long (400
uzastopnih bajtova).
Primer. Izostavljanje uzastopno jednakih elemenata niza.
#include<stdio.h>
#include<stdlib.h>
void redukcija (float *a, int *n)
{ int i, j;
for (i=1, j=0; i<*n; i++) if (a[j] != a[i]) a[++j] = a[i];
*n = j + 1;
}

/* Ispitivanje potprograma "redukcija" */

void main ()
{ float *a; int n, i;
while (1) {
printf ("n? "); scanf ("%d", &n);
if (n < 0) break;
a=(float *)malloc(n*sizeof(float));
printf ("A? "); for (i=0; i<n; scanf ("%f", &a[i++]));
redukcija (a, &n);
a=(float *)realloc(a,n*sizeof(float));
printf ("A= "); for (i=0; i<n; printf("%f ", a[i++]));
printf ("\n\n");
}
}
Primer. Iz zadatog niza izbaciti sva pojavljivanja njegovog maksimalnog elementa. Zadatak uraditi
dinamikom alokacijom memorije.
#include<stdio.h>
#include<stdlib.h>
void main()
{ int i,n,im,k=0;
float max, *a;
scanf("%d",&n);

137
Ivan P. Stanimirovi Uvod u programiranje

a=(float *)malloc(n*sizeof(float));
for(i=0;i<n;scanf("%f",&a[i++]));
im=0; max=a[0];
for(i=1;i<n;i++) if(a[i]>max) { max=a[i];im=i; }
k=im-1;
for(i=im+1; i<n; i++) if(a[i]!=max)a[++k]=a[i];
a=(float *)realloc(a,(k+1)*sizeof(float));
for(i=0;i<=k;printf("a[%d]=%f ",i,a[i++]));
}
Primer. Uitavanje, sortiranje i ispis nizova pomou potprograma.
#include <stdio.h>
#include <stdlib.h>

void ucitaj(int *a, int &n) {


scanf("%d",&n);
for (int i=0; i<n; i++)scanf("%d",a+i);
}

void razmeni(int &a, int &b) {


int p=a; a=b; b=p;
}

void SORT(int **a, int n) {


int *A;
A=*a;
for (int i=0; i<n-1; i++)
for (int j=i+1; j<n; j++)
if (*(A+i)>*(A+j)) razmeni(*(A+i),*(A+j));

int ispisi(int *a, int n) {


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

int main() {
int n,*a;
a=(int *)malloc(2000*sizeof(int));
ucitaj(a,n);
SORT(&a,n);
ispisi(a,n);
return 0;
}

Bubble sort
#include <stdio.h>
#include <math.h>
void bubbleSort(float *a, int n)
{int i,j; float p;
j=(n-1);
while(j>=1)
{for(i=0;i<j;i++)
if(a[i]>a[i+1])
{ p=a[i]; a[i]=a[i+1]; a[i+1]=p; }
j=j-1;
}
}
void main()
{int i,n;float a[10];

138
Ivan P. Stanimirovi Uvod u programiranje

scanf("%d",&n);
for(i=0;i<n;i++)scanf("%f",&a[i]);
bubbleSort(a,n);
for(i=0;i<n;i++) printf("%f ",a[i]);
}

Drugi oblici funkcije SORT:

void SORT(int **a, int n) {


for (int i=0; i<n-1; i++)
for (int j=i+1; j<n; j++)
if (*(*a+i)>*(*a+j)) razmeni(*(*a+i),*(*a+j));

void SORT(int **a, int n) {


for (int i=0; i<n-1; i++)
for (int j=i+1; j<n; j++)
if (*(&(*a)[i])>*(&(*a)[j]))
razmeni(*(&(*a)[i]),*(&(*a)[j]));

#include <stdio.h>
#include <stdlib.h>

void ucitaj(int *a, int &n) {


scanf("%d",&n);
for (int i=0; i<n; i++)scanf("%d",a+i);
}

void razmeni(int &a, int &b) {


int p=a; a=b; b=p;
}

void SORT(int ***a, int n) {


for (int i=0; i<n-1; i++)
for (int j=i+1; j<n; j++)
if ((*(*a))[i]>(*(*a))[j])
razmeni((*(*a))[i],(*(*a))[j]);

int ispisi(int *a, int n) {


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

int main() {
int n,*a,**b;
a=(int *)malloc(2000*sizeof(int));
ucitaj(a,n);
b=&a;
SORT(&b,n);
ispisi(a,n);
return 0;
}

Primer. Nizovi kao skupovi pomou dinamike alokacije memorije.

139
Ivan P. Stanimirovi Uvod u programiranje

#include<stdio.h>
#include<stdlib.h>
int sadrzi(const float *s1, int n1, float b);
void dodaj(float **s1, int *n1, float b);
void presek(const float *s1, int n1, const float *s2, int n2,
float **s3, int *n3);
void unija(const float *s1, int n1, const float *s2, int n2,
float **s3, int *n3);
/* void razlika(const float *s1, int n1, const float *s2, int n2,
float **s3, int *n3); n*/
void citaj(float **s, int *n);
void pisi(const float *s, int n, const char *f);

int sadrzi(const float *s1, int n1, float b)


{ int d=0, g=n1-1,p;
while(d<=g)
if(s1[p=(d+g)/2]==b)return 1;
else if(s1[p]<b)d=p+1;
else g=p-1;
return 0;
}

void dodaj(float **s1, int *n1, float b)


{ float *s=*s1; int n=*n1,i;
if(!sadrzi(s,n,b))
{ *s1=s=(float *)realloc(s,(n+1)*sizeof(float));
for(i=n-1; i>=0&&s[i]>b;i--)s[i+1]=s[i];
s[i+1]=b; *n1=n+1;
}
}

void presek(const float *s1, int n1, const float *s2, int n2,
float **s3, int *n3)
{ int n=0,i1=0,i2=0;
float *s=(float *) malloc((n1<n2 ? n1 : n2)*sizeof(float));
while(i1<n1 && i2<n2)
if(s1[i1]<s2[i2])i1++;
else if(s1[i1]>s2[i2])i2++;
else s[n++]=s1[i1++],i2++;
*s3=(float *)realloc(s,(*n3=n)*sizeof(float));
}

void unija(const float *s1, int n1, const float *s2, int n2,
float **s3, int *n3)
{ int n=0, i1=0, i2=0;
float *s=(float *)malloc((n1+n2)*sizeof(float));
while(i1<n1 || i2<n2)
if(i1==n1) s[n++]=s2[i2++];
else if(i2==n2)s[n++]=s1[i1++];
else if(s1[i1]<s2[i2])s[n++]=s1[i1++];
else if(s2[i2]<s1[i1])s[n++]=s2[i2++];
else s[n++]=s1[i1++],i2++;
*s3=(float *)realloc(s,(*n3=n)*sizeof(float));
}

void citaj(float **s1, int *n1)


{ int n,i;
float *s;
scanf("%d",&n); *n1=n;
if(n>=0)
{ *s1=s=(float *)malloc(n*sizeof(float));
for(i=0; i<n; scanf("%f",&s[i++]));

140
Ivan P. Stanimirovi Uvod u programiranje

}
else *s1=0;
}
void pisi(const float *s, int n, const char *f)
{ int i;
putchar('{');
for(i=0;i<n; i++)
{ if(i>0) putchar(','); printf(f,s[i]); }
putchar('}');
}

void main()
{ float *s1, *s2, *s3;
int n1,n2,n3;
while(1)
{ citaj(&s1,&n1); if(n1<0)break;
citaj(&s2,&n2); if(n2<0)break;
printf("s1 "); pisi(s1,n1,"%.2f"); putchar('\n');
printf("s2 "); pisi(s2,n2,"%.2f"); putchar('\n');
presek(s1,n1,s2,n2,&s3, &n3);
printf("s1*s2 "); pisi(s3,n3,"%.2f"); putchar('\n');
unija(s1,n1,s2,n2,&s3, &n3);
printf("s1+s2 "); pisi(s3,n3,"%.2f"); putchar('\n');
free(s1); free(s2); free(s3);
}
}
Primer. Za svaku vrstu robe u magacinu belei se njena ifra i koliina, kao dva cela broja. Za
magacin A dati su nizovi sa i ka od na elemenata, sa znaenjem da robe sa ifrom sa[i] ima u koliini
ka[i], i da ukupno ima na vrsta robe u magacinu. Za magacin B dati su analogni podaci u nizovima sb i
kb od nb elemenata. Podaci o robi su ureeni po rastu ifara. Formirati nizove sz i kz koji daju podatke
o zbirnom stanju u magacinima A i B, i koji su takoe ureeni po siframa artikala. Koristiti dinamiku
alokaciju nizova.
#include<stdio.h>
#include<stdlib.h>
void main()
{ int *sa,*ka,*sb,*kb, *sz,*kz;
int i,ia,ib,iz,na,nb,nz;
printf("Broj vrsta robe u magacinu A? "); scanf("%d",&na);
sa=(int *)malloc(na*sizeof(int)); ka=(int *)malloc(na*sizeof(int));
for(i=0; i<na; i++)
{ printf("cifra i kolicina za %d. artikal? ",i);
scanf("%d%d", &sa[i], &ka[i]);
}
printf("Broj vrsta robe u magacinu B? "); scanf("%d",&nb);
sb=(int *)malloc(nb*sizeof(int)); kb=(int *)malloc(nb*sizeof(int));
for(i=0; i<nb; i++)
{ printf("cifra i kolicina za %d. artikal? ",i);
scanf("%d%d", &sb[i], &kb[i]);
}
sz=(int *)malloc((na+nb)*sizeof(int)); kz=(int *)malloc((na+nb)*sizeof(int));
ia=ib=iz=0;
while (ia<na && ib<nb)
if(sa[ia]<sb[ib])
{ sz[iz]=sa[ia]; kz[iz++]=ka[ia++]; }
else if(sa[ia]>sb[ib])
{ sz[iz]=sb[ib]; kz[iz++]=kb[ib++]; }
else // sa[ia]=sb[ib]
{ sz[iz]=sa[ia]; kz[iz++]=ka[ia++]+kb[ib++]; }
while(ia<na)
{ sz[iz]=sa[ia]; kz[iz++]=ka[ia++]; }
while(ib<nb)
{ sz[iz]=sb[ib]; kz[iz++]=kb[ib++]; }

141
Ivan P. Stanimirovi Uvod u programiranje

nz=iz-1;
sz=(int *)realloc(sz,nz*sizeof(int));
kz=(int *)realloc(kz,nz*sizeof(int));
for(i=0;i<nz; printf("sifra %d kolicina %d\n",sz[i],kz[i++]));
free(sa); free(sb); free(ka); free(kb); free(sz); free(kz);
}

Primer. Napisati program kojim se zamenjuje prvo pojavljivanje stringa s1 u stringu s stringom s2.
Stringovi s1 i s2 mogu biti razliitih duina. Sve stringove pamtiti u dinamikoj zoni memorije i za
svaki od njih rezervisati onoliko memorijskog prostora koliko je neophodno.

#include <stdio.h>
#include <stdlib.h>

void main()
{ char *s,*s1,*s2,c;
int n,n1,n2,i,j,k;
printf("Duzine stringova = ? "); scanf("%d%d%d",&n,&n1,&n2);
scanf("%c",&c);
s=(char *)malloc(n+1); s1=(char *)malloc(n1+1); s2=(char *)malloc(n2+1);
printf("Unesite stringove\n");
gets(s); gets(s1); gets(s2);

//Pronalazi s1 u s
//i je pocetna adresa od koje trazimo u s,
// j je broj pronadjenih znakova iz s1 u s
for(i=0,j=0;i<=n-n1 && j<n1; )
{ if(s[i+j]==s1[j])j++;
else {j=0; i++; }
}

if(j<n1)printf("s1 se ne sadrzi u s\n");


else
{ if(n2>n1) //s se prosiruje
{ k=n2-n1;
realloc(s,n+k+1);
for(j=n; j>=i+n1; j--)s[j+k]=s[j];
}
else if(n1>n2)// s se smanjuje
{ k=n1-n2;
for(j=i+n1; j<=n; j++)s[j-k]=s[j];
realloc(s,n-k+1);
}
printf("i = %d\n",i);
for(j=0; j<n2; j++) s[i+j]=s2[j];
printf("Transformisani string je %s\n",s);
}
}

Test primer.
Duzine strigova = ? 9 3 2
Unesite stringove
rat i mir
mir
mi
Transformisani string je rat i mi

6.5. Viedimenzionalna polja


Kod reavanja mnogih problema postoji potreba za radom sa viedimenzionalnim strukturama

142
Ivan P. Stanimirovi Uvod u programiranje

podataka. U programskim jezicima se za rad sa ovakvim strukturama podataka mogu definisati


viedimenzionalna polja, kao jednorodne strukture podataka u okviru kojih se pojedinanim
elementima pristupa preko dva ili vie indeksa. Posebno su znaajne dvodimenzionalne strukture, koje
odgovaraju pojmu matrica i omoguavaju reavanje veoma iroke klase problema u kojima se koriste
matrine reprezentacije podataka.

6.5.1. Viedimenzionalni nizovi u C


Jednim parom zagrada definiu se jednodimenzionalni nizovi. Svaki par zagrada definie jednu
dimenziju niza. Na primer, sledee deklaracije su korektne:
int a[100]; int b[3][5]; int c[7][9][2];

U jeziku C proizvoljni k-dimenzionalni niz poseduje veliinu svake od svojih k dimenzija.


Primer. Zadavanje elemenata matrice na mestu njene deklaracije.
#include <stdio.h>
main()
{ int i,j,a[2]={1,2}, b[2][3]={{45,67,88},{67,777,54}}, s=0;
for(i=0;i<2;++i) s+=a[i];
printf("\nSuma elemenata niza je:%d\n",s);
for(i=0;i<2;i++)
for(j=0;j<3;j++) printf("b[%d%d]=%d\n",i,j,b[i][j]);
}
Primer. Program za mnoenje matrica koji koristi korisniki tip mat za definiciju matrica reda 33.
void main()
{int i, j, k;
typedef double mat[3][3];
static mat m1={{1.0,2.0,3.0},{4.0,5.0,6.0},{7.0,8.0,9.0}},
m2={{9.0,8.0,7.0},{6.0,5.0,4.0},{3.0,2.0,1.0}};
mat m3;
for(i=0; i<3; ++i)
for(j=0; j<3; ++j)
for(m3[i][j]=0, k=0; k<3; ++k)
m3[i][j]+= m1[i][k]*m2[k][j];
printf("\nProizvod matrica\n");
for (i=0; i<3; ++i)
for (j=0; j<3; ++j)
printf("%15.2f%c", m3[i][j], (j==2) ? '\n' : ' ');
}

6.5.2. Pokazivai i viedimenzionalni nizovi u C


Dvodimenzionalni nizovi (matrice) se u memoriji registruju po vrstama, koristei uzastopne
memorijske lokacije. Na primer, dvodimenzionalni niz int a[3][2] se u memoriji rasporeuje u
sledeem poretku:
a[0][0], a[0][1], a[1][0], a[1][1], a[2][0], a[2][1] .
Ako se deklarie pokaziva p pomou
int *p
posle dodele p = a pointer p uzima za svoju vrednost adresu elementa koji lei u nultoj vrsti i nultoj
koloni matrice a (tj. adresu prvog elementa matrice a). Takoe, vae sledee pointerske jednakosti:
p=&a[0][0], p+1=&a[0][1], p+2=&a[1][0], p+3 =&a[1][1], p+4=&a[2][0], p+5=&a[2][1].

Dvodimenzionalni nizovi jesu jednodimenzionalni nizovi jednodimenzionalnih nizova. Na primer,


ako je r ime dvodimenzionalnog niza, tada je r[i] jednodimenzionalni niz koji sadri elemente i-te
vrste matrice r.

143
Ivan P. Stanimirovi Uvod u programiranje

U naem sluaju, vrste matrice a date su izrazima a[0], a[1] i a[2]. S obzirom na poznata svojstva
jednodimenzionalnih nizova, vae sledee jednakosti:
a[0]=&a[0][0], a[1]=&a[1][0], a[2]=&a[2][0] .
Osim toga, vae sledee jednakosti:
a[i]=&a[i][0], a[i] + j = &a[i][j], a[i][j] = *( a[i] + j), &a[i][j] = a+i*2+j.
Takoe je
a[j][k]=*(a+j*duzina_vrste +k).

Neka je mat[][7] dvodimenzionalni niz. Tada je


mat[i][j]=*(mat[i]+j)=(*(mat+i))[j]=*(mat+i*7+j)= *(&mat[0][0]+i*7+j)= *((*(mat+i))+j).
U gornjim primerima zagrade su neophodne zbog toga to operator selekcije ima vii prioritet u
odnosu na operator indirekcije.
Primer. Definisan je tip Matrica u jeziku C++. Napisane su funkcije za ispis i upis elemenata
matrice, za transponovanje matrice, za sabiranje dve matrice, kao i funkcija za ciklino pomeranje
vrsta u matrici.
#include<stdio.h>

typedef float matrica[10][20];

void main()
{ int m,n;
matrica a,b,c;
void pisi(int, int, matrica);
void citaj(int &, int &, matrica);
void saberi(int, int, matrica, matrica,matrica);
void rotiraj(int, int, matrica);
void transponuj(int, int, matrica);
citaj(m,n,a);
citaj(m,n,b);
saberi(m,n,a,b,c); pisi(m,n,c);
rotiraj(m,n,c); pisi(m,n,c);
transponuj(m,n,c); pisi(n,m,c);
}
void citaj(int &k, int &l, matrica x)
{ int i,j;
scanf("%d%d",&k,&l);
for(i=0;i<k; i++)
for(j=0; j<l; j++)
scanf("%f",x[i]+j);
}

void pisi(int k, int l, matrica x)


{ int i,j;
for(i=0;i<k; i++)
{ for(j=0; j<l; j++)
printf("%.2f ",x[i][j]);
printf("\n");
}
printf("\n");
}

void saberi(int k, int l, matrica x, matrica y, matrica z)


{ int i,j;
for (i=0;i<k;i++)
for (j=0;j<l;j++)
z[i][j]=x[i][j]+y[i][j];
}

144
Ivan P. Stanimirovi Uvod u programiranje

void uzmi(int n, float *x, float *y)


{ int j;
for(j=0; j<n; j++)x[j]=y[j];
}

void rotiraj(int m, int n, matrica a)


{ int i;
float p[20];
uzmi(n,p,a[m-1]);
for(i=m-2;i>=0;i--)
uzmi(n,a[i+1],a[i]);
uzmi(n,a[0],p);
}

void transponuj(int m, int n, matrica a)


{ int i,j;
for(i=0; i<m; i++)
for(j=i+1; j<n; j++)
{ float p=a[i][j]; a[i][j]=a[j][i]; a[j][i]=p; }
}
Primer. Napisati potprogram koji pronalazi minimalni element niza i njegov indeks. U glavnom
programu uitati matricu mn i uz pomo formiranog potprograma nai minimalni element u matrici i
njegove indekse.
#include <stdio.h>
void minunizu(int a[], int n, int *mn, int *k)
{ int i;
*k=0; *mn=a[0];
for(i=1; i<n; i++)if(a[i]<*mn) { *k=i; *mn=a[i]; }
}

void main()
{ int m,n,i,j, min, ind; int a[10][10], b[10], p[10];
printf("Dimenzije matrice?: "); scanf("%d%d", &m,&n);
printf("\nElementi matrice?: ");
for(i=0; i<m; i++)
for(j=0; j<n; j++) scanf("%d", &a[i][j]);
for(i=0; i<m; i++)
minunizu(a[i], n, &b[i], &p[i]);
// Moze i minunizu(a[i], n, b+i, p+i);
minunizu(b,m, &min, &ind);
i=ind; j=p[ind];
printf("Minimal-ni je na poziciji [%d,%d] i jednak je %d\n",i,j,min);
}

Primer. Konstruisati magini kvadrat dimenzija nn, za n neparno.


#include<stdio.h>
void main()
{ int i,j,k,n, mag[29][29];
printf("Dimenzije kvadrata? ");
scanf("%d", &n);
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
mag[i][j]=0;
i=1; j=(n+1)/2; k=1;
while(k<=n*n)
{ mag[i][j]=k++;
if(i==1 && j==1) i++;
else if(i==1) { i=n; j--; }

145
Ivan P. Stanimirovi Uvod u programiranje

else if(j==1) { j=n; i--; }


else if(mag[i-1][j-1]!=0) i++;
else { i--; j--; }
}
for(i=1; i<=n; i++)
{ for(j=1; j<=n; j++) printf("%4d",mag[i][j]); printf("\n"); }
}
Primer. Data je celobrojna matrica A reda nn, gde je n neparan broj. Matrica A predstavlja magini
kvadrat sa jednim pogrenim brojem. Napisati program koji pronalazi greku, ispravlja je, tampa
odgovarajuu poruku i ispravljeni magini kvadrat.
void main()
{ int i,j,n, ik,iv, s1,s2,s3,s,suma, mag[29][29];
printf("Dimenzije kvadrata? "); scanf("%d", &n);
printf("Zadati magicni kvadrat sa jednom greskom\n");
for(i=1; i<=n; i++)
for(j=1; j<=n; j++) scanf("%d", &mag[i][j]);
s1=s2=s3=0;
for(j=1; j<=n; j++)
{ s1 += mag[1][j]; s2 += mag[2][j]; s3 += mag[3][j]; }
if(s1==s2 || s1==s3) suma=s1;
else suma=s2;
i=0;
do
{ i++; s=0; for(j=1; j<=n; j++)s+=mag[i][j]; }
while(s==suma);
iv=i;
j=0;
do
{j++; s=0; for(i=1; i<=n; i++)s+=mag[i][j];}
while(s==suma);
ik=j;
printf("Greska je u vrsti %d i koloni %d\n",iv,ik);
printf("Pogresna vrednost je %d\n",mag[iv][ik]);
printf("Pravilna vrednost je %d\n",mag[iv][ik]+suma-s);
mag[iv][ik]=mag[iv][ik]+suma-s;
printf("Pravilni magicni kvadrat je:\n");
for(i=1; i<=n; i++)
{ for(j=1; j<=n; j++) printf("%4d",mag[i][j]);
printf("\n");
}
}

Primer. Napisati program koji najefikasnijim postupkom izraunava n-ti stepen matrice A. Takav
stepen se moe izraunati rekurzivno sa najmanjim brojem matrinih mnoenja na sledei nain:
A, n=1
An = (Ak)2, n = 2k
A(Ak)2, n = 2k+1
#include<stdio.h>
void mnozi(int n, int a[10][10], int b[10][10], int c[10][10])
{ int i,j,k;
int s;
for(i=0; i<n; i++)
for(j=0; j<n; j++)
{ s=0;
for(k=0; k<n; k++) s+=a[i][k]*b[k][j];
c[i][j]=s;
}
}

146
Ivan P. Stanimirovi Uvod u programiranje

void kopi(int n, int a[10][10], int b[10][10])


{ int i,j;
for(i=0; i<n; i++)
for(j=0; j<n; j++) b[i][j]=a[i][j];
}

void citaj(int n, int a[10][10])


{ int i,j;
printf("Unesi %d*%d elemenata matrice\n", n,n);
for(i=0; i<n; i++)
for(j=0; j<n; j++) scanf("%d",&a[i][j]);
}

void pisi(int n, int a[10][10])


{ int i,j;
for(i=0; i<n; i++)
{ for(j=0; j<n; j++) printf("%d ",a[i][j]);
printf("\n");
}
}

void stepen(int m, int n, int a[10][10], int b[10][10])


{ int c[10][10], p[10][10];
if(m==1) kopi(n,a,b);
else { stepen(m/2,n,a,c);
mnozi(n,c,c,p);
if(m%2==1)mnozi(n,p,a,b);
else kopi(n,p,b);
}
}

void main()
{ int n,m;
int a[10][10], b[10][10];
printf("Red kvadratne matrice = "); scanf("%d", &n);
citaj(n,a);
printf("Stepen = "); scanf("%d", &m);
stepen(m,n,a,b); pisi(n,b);
}

Primer. Svaki element matrice koji predstavlja maksimum svoje vrste i minimum svoje kolone
naziva se sedlasta taka. Pronai sve sedlatse take u zadatoj matrici.
#define MAXX 100
#define MAXY 100
#include<stdio.h>
#include<conio.h>
#include<limits.h>
#include<stdlib.h>
int a[MAXX][MAXY], mini[MAXX], maxi[MAXY],m,n;

void main()
{ int i,j;
printf("Dimenzije matrice? "); scanf("%d%d",&m,&n);
printf("Elementi?\n");
for(i=0;i<m;i++)
for(j=0;j<n;j++) scanf("%d", &a[i][j]);
for(i=0;i<m;i++)maxi[i]=maximum(i);
for(j=0;j<n;j++)mini[j]=minimum(j);
for(i=0;i<m;i++)
for(j=0;j<n;j++)

147
Ivan P. Stanimirovi Uvod u programiranje

if(maxi[i]==a[i][j] && mini[j]==a[i][j])


printf("a[%d][%d]=%d ",i,j,a[i][j]);
}

int minimum(int kol)


{ int i,rez=INT_MAX;
for(i=0;i<m;i++) rez=min(rez,a[i][kol]);
return(rez);
}

int maximum(int vrs)


{ int j,rez=INT_MIN;
for(j=0;j<n;j++) rez=max(rez,a[vrs][j]);
return(rez);
}
Jo jedno reenje:
void main()
{ int a[100][100],p[100], q[100];
int m,n,i,j,k;
scanf("%d%d", &m,&n);
for(i=0;i<m;i++)
for(j=0;j<n;j++) scanf("%d", &a[i][j]);
for(i=0; i<m; i++)
{ k=0;
for(j=1;j<n;j++) if(a[i][j]>a[i][k])k=j;
p[i]=k;
}
for(j=0; j<n; j++)
{ k=0;
for(i=1;i<m;i++)
if(a[i][j]<a[i][k])k=i;
q[j]=k;
}
for(i=0;i<n;i++)
if(q[p[i]]==i) printf("%d %d\n",i,p[i]);
}
Primer. Data je matrica Amn celih brojeva. Element a[i,j] je vrh ako je vei od svojih susednih
elemenata koji su iznad, ispod, sa leve i sa desne strane. Visina vrha je razlika izmeu elementa i
njegovog najvieg suseda. Napisati program koji e formirati niz vrhova sortiran u nerastui redosled
po visini.
#include<stdio.h>
int vrh(int i, int j, int m, int n, int a[10][10])
{ if(i==0 && j==0)
return(a[i][j]>a[i][j+1] && a[i][j]>a[i+1][j]);
else if(i==m-1 && j==n-1)
return(a[i][j]>a[i-1][j] && a[i][j]>a[i][j-1]);
else if(i==0 && j==n-1)
return(a[i][j]>a[i][j-1] && a[i][j]>a[i+1][j]);
else if(i==m-1 && j==0)
return(a[i][j]>a[i-1][j] && a[i][j]>a[i][j+1]);
else if(i==0)
return(a[i][j]>a[i][j-1] &&
a[i][j]>a[i+1][j] && a[i][j]>a[i][j+1]);
else if(j==0)
return(a[i][j]>a[i-1][j] && a[i][j]>a[i][j+1]&&
a[i][j]>a[i+1][j]);
else if(i==m-1)
return(a[i][j]>a[i-1][j] && a[i][j]>a[i][j-1] &&

148
Ivan P. Stanimirovi Uvod u programiranje

a[i][j]>a[i][j+1]);
else if(j==n-1)
return(a[i][j]>a[i-1][j] && a[i][j]>a[i][j-1] &&
a[i][j]>a[i+1][j]);
else return(a[i][j]>a[i-1][j] && a[i][j]>a[i][j-1] &&
a[i][j]>a[i+1][j] && a[i][j]>a[i][j+1]);
}

int min2(int x, int y)


{if(x<y) return(x); else return(y); }

int min3(int x, int y, int z)


{ int min;
min=x; if(y<min) min=y; if(z<min) min=z;
return(min);
}

int min4(int x, int y, int z, int w)


{ int min;
min=x; if(y<min) min=y; if(z<min) min=z; if(w<min)min=w;
return(min);
}

int visina(int i, int j, int m, int n, int a[10][10])


{ int min2(int,int);
int min3(int,int,int);
int min4(int,int,int,int);
if(i==0 && j==0)
return(min2(a[i][j]-a[i][j+1],a[i][j]-a[i+1][j]));
else if(i==m-1 && j==n-1)
return(min2(a[i][j]-a[i-1][j],a[i][j]-a[i][j-1]));
else if(i==0 && j==n-1)
return(min2(a[i][j]-a[i][j-1],a[i][j]-a[i+1][j]));
else if(i==m-1 && j==0)
return(min2(a[i][j]-a[i-1][j],a[i][j]-a[i][j+1]));
else if(i==0)
return(min3(a[i][j]-a[i][j-1],a[i][j]-a[i+1][j],
a[i][j]-a[i][j+1]));
else if(j==0)
return(min3(a[i][j]-a[i-1][j],a[i][j]-a[i][j+1],
a[i][j]-a[i+1][j]));
else if(i==m-1)
return(min3(a[i][j]-a[i-1][j],a[i][j]-a[i][j-1],
a[i][j]-a[i][j+1]));
else if(j==n-1)
return(min3(a[i][j]-a[i-1][j],a[i][j]-a[i][j-1],
a[i][j]-a[i+1][j]));
else return(min4(a[i][j]-a[i-1][j],a[i][j]-a[i][j-1],
a[i][j]-a[i+1][j],a[i][j]-a[i][j+1]));
}

void main()
{ int vrh(int i, int j, int m, int n, int a[10][10]);
int visina(int i, int j, int m, int n, int a[10][10]);
int i,j,a[10][10], vrhovi[25],visine[25], pom,k=0,m,n;
scanf("%d%d", &m,&n);
for(i=0;i<m;i++)
for(j=0;j<n;j++) scanf("%d",&a[i][j]);
for(i=0;i<m;i++)
for(j=0;j<n;j++)
if(vrh(i,j,m,n,a))
{ vrhovi[k]=a[i][j]; visine[k]=visina(i,j,m,n,a); k++;}

149
Ivan P. Stanimirovi Uvod u programiranje

for(i=0;i<k-1;i++)
for(j=i+1;j<k;j++)
if(visine[i]<visine[j])
{ pom=visine[i]; visine[i]=visine[j]; visine[j]=pom;
pom=vrhovi[i]; vrhovi[i]=vrhovi[j]; vrhovi[j]=pom;
}
printf("\nNiz vrhova i visina:\n");
for(i=0;i<k;i++)printf("Vrh: %d visina: %d\n",vrhovi[i],visine[i]);
}

Primer. Dat je niz a0,... , ak-1 celih brojeva. Napisati program kojim se formira kvadratna matrica reda
n takva da je niz ai, i = 0,... , k-1 upisan spiralno u tu matricu u smeru kretanja kazaljke na satu.
Ukoliko niz ima manje od n2 elemenata, posle svakih k upisanih elemenata poeti upisivanje od
prvog.
#include <stdio.h>
int dodi[4]={0,1,0,-1};
int do[4]={1,0,-1,0}; /* desno, dole, levo, gore */

void main()
{ int a[10], k, mat[20][20], n, n1, smer, i,j,br,pombr,broj;
printf("Broj elemenata u nizu? "); scanf("%d", &k);
printf("elementi niza?\n"); for(i=0;i<k;i++) scanf("%d",&a[i]);
printf("Dimenzija matrice? "); scanf("%d", &n);
n1=n; i=j=br=smer=0;
for(broj=1; broj<=n*n; broj++)
{ /* ciklus za postavljanje elemenata u matricu */
mat[i][j]=a[br];
/* i, j su indeksi matrice, a br je indeks niza */
br++;
if(br==k)br=0; /* kad br doe do k, vraca se na 0 */

i+=dodi[smer]; j+=do[smer];
if(i==n1 || j==n1 || (i==n-n1&&smer>0) || j==n-n1-1)
/* sada se menja smer dodavanja */
{ if(i==n1) i=n1-1; if(j==n1) j=n1-1;
if(i==n-n1 && smer>0) i=n-n1+1;
if(j==n-n1-1)j=n-n1;
smer++; /* sledeci smer */
if(smer==4) /* upotrebljeni su svi smerovi */
{ smer=0; /* ponovo na desno */
n1--;
}
i+=dodi[smer]; j+=do[smer];
}
}
for(i=0;i<n;i++)
{for(j=0;j<n;j++) printf("%d ",mat[i][j]); printf("\n"); }
}
Primer. Neka je dato n koncentrinih krugova takvih da svaki od njih ima m otvorenih vrata.
Prolaskom kroz bilo koja vrata dobija se izvestan broj nenegativnih poena. Ako je data matrica A
dimenzije nm iji element a[i,j] oznaava broj poena koji se osvaja prolaskom kroz j-ta vrata i-tog
kruga, napisati program koji trasira put kroz n vrata tako da se sakupi dati broj poena s.
Kroz svaka vrata se prolazi tano jedanput.

program krugovi;
type opseg=0..10;
niz=array[opseg] of integer;
matrica=array[opseg,opseg] of integer;
var a:matrica;

150
Ivan P. Stanimirovi Uvod u programiranje

x:niz;
i,j,m,n,s:integer;
q:boolean;
function suma(x:niz; k:opseg):integer;
var i,j,s1:integer;
begin
s1:=0;
for i:=1 to k do s1:=s1+a[i,x[i]];
suma:=s1;
end;

procedure pisi(x:niz; n:integer);


var i:integer;
begin
for i:=1 to n do
begin
write('Na ',i,'. krugu vrata ',x[i],' poeni ',a[i,x[i]],' ');
writeln;
end;
end;

procedure trazi(k:opseg);
var i:opseg;
begin
i:=1;
while (i<=n) and not q do
begin
x[k]:=i;
if suma(x,k)<=s then
begin
if (k=n) and (suma(x,k)=s) then
begin
pisi(x,n); q:=true;
end
else trazi(k+1);
end;
i:=i+1;
end;
end;

begin
write('Uneti broj krugova i broj vrata na svakom krugu ');
readln(n,m); write('Unesi sumu '); readln(s);
writeln('Unesi broj poena na vratima ');
for i:=1 to n do
begin
for j:=1 to m do read(a[i,j]); readln;
end;
q:=false;
trazi(0); if not q then writeln('Nema resenja ');
end.
Primer. Problem n dama.
#include <stdio.h>

int a[50][50],n;
void cepaj(int);
int radi(int,int);
void ispis();

void main()

151
Ivan P. Stanimirovi Uvod u programiranje

{ scanf("%d",&n); radi(0); }

void ispis()
{
int i,j;
for (i=0; i<n; i++)
{ for (j=0; j<n; j++) printf("%d ",a[i][j]); printf("\n"); }
printf("\n\n\n");
}

void radi(int j)
{ for (int i=0; i<n; i++)
if (cepa(i,j))
{ a[i][j]=1;
if (j<n-1) dalje(j+1);
else ispis();
a[i][j]=0;
}
}

int dalje(int i, int j)


{ for (int k=0; k<j; k++)
{ if ((a[i][k]==1) || (a[i-j+k][k]==1) || (a[i+j-k][k]==1))
return(0); }
return(1);
}
Primer. Data je sahovska tabla dimenzija nm. Na polju sa koordinatama (i,j) je data figura. jedan
potez se sastoji u pomeranju figure za jedno polje gore, dole, levo ili desno. Napisati program koji za
date n,m,i,j odreuje najmanji broj poteza kojim se figura dovodi u ugao table.
#include<stdio.h>
#include<math.h>
void plusOne(int a[], int n, int k)
{ int i,j;
if(a[k-1]<n-1) a[k-1]++;
else
{ i=k-2; j=1;
while((a[i]>=n-1-j) && (i>0))
{ i--; j++; }
a[i]++;
for(j=i+1;j<k;j++)a[j]=a[j-1]+1;
}
}

int jedanRed(int x[], int n)


{ int i,j,min=2000000000,rast;
for(i=0;i<n;i++)
{ rast=0;
for(j=0;j<n;j++)
if(i!=j) rast+=abs(x[i]-x[j]);
if(rast<min) min=rast;
}
return min;
}

int main()
{ int n,potezi[50],x[50],y[50],pomx[50],pomy[50],nizIndexa[50],i,j;
scanf("%d",&n);
for(i=0;i<n;i++)scanf("%d%d",&x[i],&y[i]);
potezi[0]=0; potezi[1]=0;
int min,rez;
for(i=2;i<=n;i++)

152
Ivan P. Stanimirovi Uvod u programiranje

{ min=2000000000;
nizIndexa[0]=0;
for(j=1;j<i;j++)
nizIndexa[j]=nizIndexa[j-1]+1;
while(nizIndexa[0]<=(n-i))
{ rez=0;
for(j=0;j<i;j++)
{pomx[j]=x[nizIndexa[j]]; pomy[j]=y[nizIndexa[j]]; }
rez+=jedanRed(pomx,i)+jedanRed(pomy,i);
if(rez<min) min=rez;
plusOne(nizIndexa,n,i);
}
potezi[i]=min;
}
for(i=0;i<=n;i++)printf("%4d", potezi[i]);
printf("\n");
return 0;
}

Primer. Na obali nekog ostrva nalazi se n gradova oznaenih brojevima od 0 do n-1. Oko celog ostrva
je izgraen autoput koji prolazi kroz svaki od gradova. U nizu d su data rastojanja izmeu gradova,
tako da d[i] predstavlja duinu autoputa izmeu gradova i i i+1 (d[n-1] predstavlja duinu puta izmeu
grada n-1 i 0). Napisati program koji za sve gradove odreuje niz najkraih rastojanja do ostalih
gradova.
#include<stdio.h>
float rastojanje(int i, int j, int n, float d[10])
{ float rl,rd;
int k;
rl=rd=0;
for(k=i; k<=j-1;k++)rl=rl+d[k];
for(k=j; k<=n-1; k++)rd=rd+d[k];
for(k=0;k<=i-1;k++)rd=rd+d[k];
if(rl<rd) return(rl);
else return(rd);
}

void main()
{ float rastojanje(int i, int j, int n, float d[10]);
int k,n,i,j;
float d[10], rastojanja[10][10];
printf("Broj gradova? "); scanf("%d",&n);
printf("Rastojanja?\n"); for(k=0;k<n;k++) scanf("%f",&d[k]);
for(i=0; i<n-1;i++)
for(j=i+1;j<n;j++)
{ rastojanja[i][j]=rastojanje(i,j,n,d);
rastojanja[j][i]=rastojanja[i][j];
}
for(j=0;j<n;j++)rastojanja[j][j]=0;
for(i=0;i<=n-1;i++)
{for(j=0;j<=n-1; j++)
printf("Rastojanje izmeu %d i %d = %f\n",i,j,rastojanja[i][j]);
printf("\n");
}
}
51. (PASCAL) Napisati funkciju kojom se utvrdjuje da li je zadata matrica A dimenzija m x n
ortonormirana. Matrica je ortonormirana ako je skalarni proizvod svakog para razliitih vrsta jednak 0,
a skalarni proizvod vrste sa samom sobom 1.
Ulaz: Dva pozitivna cela broja m i n koji predstavljaju dimenzije matrice.
Izlaz: Tekst Matrica je ortonormirana, ako je matrica ortonormirana, a inae tekst Matrica nije ortonormirana.

153
Ivan P. Stanimirovi Uvod u programiranje

program ortomormirana;
type opseg=1..10;
niz=array[opseg]of real;
matrica=array[opseg]of niz;
var a:matrica; m,n:opseg;ort:boolean;

function skalpr(n:opseg; v1,v2:niz):real;


var i:opseg;
s:real;
begin
s:=0;
for i:=1 to n do s:=s+v1[i]*v2[i];
skalpr:=s
end;

function isort(m,n:opseg; a:matrica):boolean;


var lg:boolean;
i,j:opseg;
sp:real;
begin
lg:=true;
for i:=1 to m do
for j:=i to m do
begin
sp:=skalpr(n,a[i],a[j]);
if ((i=j)and(sp<>1))or((i<>j)and(sp<>0)) then
lg:=false;
end;
isort:=lg;
end;

procedure ucitaj(m,n:opseg; var x:matrica);


var i,j:opseg;
begin
for i:=1 to m do
begin
for j:=1 to n do read(x[i,j]);
readln
end;
end;

begin
readln(m,n);
ucitaj(m,n,a);
ort:=isort(m,n,a);
if ort then writeln('Matrica je ortonormirana ')
else writeln('Matrica nije ortonormirana ');
end.
Test primeri:
3 3 3 3
1 0 0 1 1 0
0 1 0 0 1 0
0 0 1 0 0 1
Matrica je ortonormirana Matrica nije ortonormirana

54. (PASCAL) Data je matrica A(nn) iji su elementi:


true, ako postoji direktan jednosmeran put izmeu gradova i i j,
a[i,j] =
false, u suprotnom.

154
Ivan P. Stanimirovi Uvod u programiranje

Napisati program kojim se formira i ispisuje matrica iz koje se vidi koji gradovi imaju vezu sa
najmanje jednim presedanjem.
Ulaz: Matrica A(nn).

Izlaz: Matrica veze C(nn).


program gradovi;
const g=10;
type matrica=array[1..g,1..g] of boolean;
var n:integer;veza,jednopres:matrica;
procedure citajveze(n:integer; var veza:matrica);
var i,j,v:integer;
begin
writeln('Unesi veze (1-da,0-ne) izmedju gradova');
for i:=1 to n do
begin
for j:=1 to n do
begin
read(v);
if v=1 then veza[i,j]:=true
else veza[i,j]:=false;
end;
readln;
end;
end;

procedure pisiveze(brgradova:integer;a:matrica);
var i,j:integer;
begin
writeln('Matrica veze (1-da, 0-ne)');
for i:=1 to brgradova do
begin
for j:=1 to brgradova do
if a[i,j] then write('1':2)
else write('0':2);
writeln;
end;
end;

procedure pro(brgradova:integer;a,b:matrica;var c:matrica);


var log:boolean;
i,j,k:integer;
begin
for i:=1 to brgradova do
for j:=1 to brgradova do
begin
log:=false;
for k:=1 to brgradova do
log:=log or (a[i,k] and b[k,j]);
c[i,j]:=log;
end;
end;

begin
write('Broj gradova? '); readln(n);
writeln('Veze izmeu gradova?');
citajveze(n,veza);
pro(n,veza,veza,jednopres);

155
Ivan P. Stanimirovi Uvod u programiranje

pisiveze(n,jednopres);
end.
Test primer:
Broj gradova? 3
Unesi veze (1-da,0-ne) izmedju gradova
1 0 1
0 1 0
0 1 1
Matrica veze (1-da,0-ne)
1 1 1
0 1 0
0 1 1
116. (PASCAL) Rasporeeno je 15 kuglica na sledei nain: u prvoj vrsti se nalazi 5 kuglica, u drugoj
4, u treoj 3, u etvrtoj 2 i u petoj 1. Obeleiti svaku kuglicu jednim od brojeva 1,...,15, tako da svaka
kuglica ima jedinstven broj i da vai jednakost
aij=|ai-1,j-ai-1,j+1|, i= 2,3,4,5, j=1,5-i+1.

program kuglice;
type niz=array[1..15] of integer;
matrica =array[1..5,1..5] of integer;
var i,j,k,l,m,br,indu :1..15;
upotrebljen:niz;
a:matrica;
procedure ispis(a:matrica);
var i,j:1..5;
begin
for i:=1 to 5 do
begin
for j:=1 to 5-i+1 do write(a[i,j]:3);writeln
end;
end;

function razliciti(k:integer; a:niz):boolean;


var i,j:1..15;
bol:boolean;
begin
bol := true;
for i:=1 to k do
for j:=i+1 to k do
if a[i]=a[j] then bol:=false;
razliciti:=bol;
end;

begin
for i:=1 to 15 do
for j:=1 to 15 do
for k:=1 to 15 do
for l:=1 to 15 do
for m:=1 to 15 do
begin
a[1,1]:=i;a[1,2]:=j;
a[1,3]:=k;a[1,4]:=l;a[1,5]:=m;

for br:=1 to 5 do
upotrebljen[br]:=a[1,br];
indu:=5;
for br:=1 to 4 do
begin
a[2,br]:=abs(a[1,br]-a[1,br+1]);
indu:=indu+1;

156
Ivan P. Stanimirovi Uvod u programiranje

upotrebljen[indu]:=a[2,br];
end;
for br:=1 to 3 do
begin
a[3,br]:=abs(a[2,br]-a[2,br+1]);
indu:=indu+1;
upotrebljen[indu]:=a[3,br];
end;
for br:=1 to 2 do
begin
a[4,br]:=abs(a[3,br]-a[3,br+1]);
indu:=indu+1;
upotrebljen[indu]:=a[4,br];
end;
a[5,1]:=abs(a[4,1]-a[4,2]);
indu:=indu+1;
upotrebljen[indu]:=a[5,1];
if razliciti(indu,upotrebljen) then
begin
writeln;writeln;
ispis(a);readln;
end;
end;
end.
Test primer:
Resenje 1 Resenje 2
6 14 15 3 13 13 3 15 14 6
8 1 12 10 10 12 1 8
7 11 2 2 11 7
4 9 9 4
5 5

117. (PASCAL) Zadata je crno-bela matrica (0 definie belu boju, a 1 crnu). Napisati program kojim
se bele oblasti te matrice boje razliitim bojama (boje se definiu sa 2,3,...). Ispisati obojenu matricu.
program bojenje;
const k=20; l=20;
type matrica = array[1..k,1..l] of integer;
var m,n,i,j,boja:integer;
tabla:matrica;
prx,pry:array[1..4] of integer;
procedure ispis(m,n:integer; a:matrica);
var i,j:integer;
begin
for i:=1 to m do
begin
for j:=1 to n do write(a[i,j]:3);
writeln;
end;
end;
procedure upis(m,n:integer; var a:matrica);
var i,j:integer;
begin
for i:=1 to m do
begin
for j:=1 to n do read(a[i,j]);readln;
end;
end;
function moze(x,y:integer; a:matrica):boolean;
begin

157
Ivan P. Stanimirovi Uvod u programiranje

if(x>=1)and(x<=m)and(y>=1)and(y<=n) then
moze:=a[x,y]=0
else moze:=false;
end;
procedure oboji(x,y,boja:integer; var a:matrica);
var i:integer;
begin
a[x,y]:=boja;
for i:=1 to 4 do
if moze(x+prx[i],y+pry[i],a) then
oboji(x+prx[i],y+pry[i],boja,a)
end;

begin
write('Dimenzije? '); readln(m,n);
upis(m,n,tabla);
prx[1]:=-1; pry[1]:=0; { gore }
prx[2]:=0; pry[2]:=1; { desno }
prx[3]:=1; pry[3]:=0; { dole }
prx[4]:=0; pry[4]:=-1; { levo }
boja:=1;
for i:=1 to m do
for j:=1 to n do
if tabla[i,j]=0 then
begin
boja:=boja+1; oboji(i,j,boja,tabla);
end;
ispis(m,n,tabla);
end.
Test primer:
Dimenzije? 3 4 Dimenzije? 4 5
0 0 1 0 0 0 0 0 1
0 1 1 0 0 0 1 1 0
0 0 0 1 0 0 0 0 0
2 2 1 3 1 0 0 0 1
2 1 1 3 2 2 2 2 1
2 2 2 1 2 2 1 1 2
2 2 2 2 2
1 2 2 2 1

118. (PASCAL) Napisati program kojim se odreuje minimalan broj (P,Q) konja kojima se mogu
kontrolisati sva polja ahovske table dimenzije mn. (P,Q) konj je figura koja se u jednom skoku
premeta za P polja po horizontali i Q polja po vertikali. Obian ahovski konj je (1,2) konj.
program konj;
const k=30; l=30;
type matrica =array[1..k,1..l] of boolean;
var m,n,p,q,x,y,mink:integer;
tabla:matrica;
skokpox,skokpoy:array[1..8] of integer;
function moze(x,y:integer):boolean;
begin
if (x>=1)and(x<=m)and(y>=1)and(y<=n) then
moze := not tabla[x,y]
else moze:=false
end;

procedure konjana(x,y:integer);
var i:integer;
begin
tabla[x,y]:=true;

158
Ivan P. Stanimirovi Uvod u programiranje

for i:=1 to 8 do
if moze(x+skokpox[i],y+skokpoy[i]) then
konjana(x+skokpox[i],y+skokpoy[i]);
end;

begin
write('p,q= ? ');readln(p,q); write('m,n= ? ');
readln(m,n);
for x:=1 to m do
for y:=1 to n do tabla[x,y]:=false;
skokpox[1]:=-q;skokpoy[1]:=p;skokpox[2]:=-p;
skokpoy[2]:=q;skokpox[3]:=p; skokpoy[3]:=q;
skokpox[4]:=q; skokpoy[4]:=p;
skokpox[5]:=q; skokpoy[5]:=-p;
skokpox[6]:=p; skokpoy[6]:=-q;
skokpox[7]:=-p; skokpoy[7]:=-q;
skokpox[8]:=-q; skokpoy[8]:=-p;
mink:=0;
for x:=1 to m do
for y:=1 to n do
if not tabla[x,y] then
begin
konjana(x,y); mink:=mink+1;
end;
writeln('Minimalni broj konja je ',mink);
end.
Test primer:
p,q= ? 1 1 p,q= ? 3 3
m,n= ? 8 8 m,n= ? 8 8
minimalan broj konja je 2 minimalan broj konja je 18
p,q= ? 1 3 p,q= ? 4 4
m,n= ? 8 8 m,n= ? 8 8
minimalan broj konja je 2 minimalan broj konja je 32

119. (PASCAL) Data je realna matrica X dimenzije mn i celi brojevi Ip i Jp, (1<= Ip<=m,
1<=Jp<=n). Svakom elementu matrice pridruuje se jedno polje na tano odreen nain. Polje je
odreeno sa tri elementa: koordinatama (i,j) i realnim brojem koji predstavlja njegovu visinu. Broj
X[i,j] odreuje visinu polja sa koordinatama (i,j). U polju sa koordinatama (Ip,Jp) nalazi se loptica.
Loptica prelazi sa polja A na polje B ako vae sledei uslovi:
- polja A i B su susedna, to znai da imaju zajedniku stranicu;
- visina polja B je strogo manja od visine polja A, i
- polje B ima najmanju visinu u odnosu na sva polja susedna u odnosu na A.
Loptica se zaustavlja u polju u odnosu na koje ne postoji polje na koje moe da pree. Takvo polje se
naziva zavrno. Odrediti polje na kome e se loptica zaustaviti kao i put od poetnog polja (Ip, Jp) do
zavrnog.
program lopta1;
type matrica=array[1..30,1..30] of integer;
var x:matrica;
m,n,i,j,ip,jp:integer;
function moze(a,b:integer):boolean;
begin
moze:= (a>=1)and(a<=m)and(b>=1)and(b<=n)
end;
procedure uradi(ip,jp:integer; x:matrica; m,n:integer);
var q:boolean;
poz,poz1,a,b,min,min1:integer;
begin
q:=true; poz:=ip; poz1:=jp;

159
Ivan P. Stanimirovi Uvod u programiranje

writeln('Put: ');
while q do
begin
min:=x[poz,poz1]; a:=poz; b:=poz1; min1:=min;
if moze(a-1,b)and(x[a-1,b]<x[poz,poz1])
and(x[a-1,b]<min) then
begin
if poz1<>b then
poz1:=b; poz:=a-1;
min:=x[a-1,b];
end;
if moze(a+1,b)and(x[a+1,b]<x[poz,poz1])
and(x[a+1,b]<min)then
begin
if poz1<>b then
poz1:=b; poz:=a+1;
min:=x[a+1,b];
end;
if moze(a,b-1)and(x[a,b-1]<x[poz,poz1])
and(x[a,b-1]<min) then
begin
if poz<>a then
poz:=a; poz1:=b-1;
min:=x[a,b-1];
end;
if moze(a,b+1)and(x[a,b+1]<x[poz,poz1])
and(x[a,b+1]<min) then
begin
if poz<>a then
poz:=a; poz1:=b+1;
min:=x[a,b+1];
end;
q:=min<>min1;min:=min1;
if q then
writeln(poz:6,poz1:6,' ',x[poz,poz1]);
end;
writeln('Zavrsno polje: ');
writeln(poz:6,poz1:6,' ',x[poz,poz1]);
end;

begin
writeln('Unesite dimenzije matrice');readln(m,n);
writeln('Unesite elemente');
for i:=1 to m do
begin
for j:=1 to n do read(x[i,j]);
readln;
end;
writeln('Unesite ip i jp:');
readln(ip,jp); uradi(ip,jp,x,m,n);
end.
Test primer:
Unesite dimenzije matrice Unesite ip i jp:
3 3 1 3
Unesite elemente Put:
1 2 3 1 2 2
6 5 4 1 1 1
7 8 9 Zavrsno polje:
1 1 1

120. (PASCAL) Napisati funkcije (rekurzivnu i iterativnu verziju) koje za datu relaciju nad

160
Ivan P. Stanimirovi Uvod u programiranje

maksimalno devetolanim skupom ispituju refleksivnost, simetrinost i tranzivnost. Relacija je


opisana matricom istinitosnih vrednosti: ako je element aij matrice A jednak true, to znai da je i-ti
element skupa u relaciji sa j-tim elementom. Data je tekstualna datoteka. Svaki red datoteke ima oblik
n i1 j1 i2 j2 ... ik jk,
gde je n dimenzija matrice, a il i jl (l=1,...,k) indeksi elemenata koji su u relaciji. Dakle, jedan
red datoteke opisuje jednu relaciju.
Napisati program koji prebrojava nekorektne redove u datoteci, redove koji opisuju relaciju
ekvivalencije, kao i redove koji opisuju relaciju poretka (ureenja).
program pmfokt22;
const maxn=9;
type relacija = array[1..maxn,1..maxn] of boolean;

function ucitaj(var dat:text;var n:integer;


var r:relacija):boolean;
var i,j:integer;
ind:boolean;
begin
ind:=true;
read(dat,n);
for i:=1 to n do
for j:= 1 to n do r[i,j]:=false;
while not eoln(dat) do
begin
read(dat,i);
if(i<1) or (i>n) or eoln(dat) then ind:=false;
if ind then
begin
read(dat,j);
if (j<1) or (j>n) then ind:=false;
end;
if ind then r[i,j]:=true;
end;
ucitaj:=ind;
end;

(* Iterativne funkcije *)
function refleks(n:integer; r:relacija):boolean;
var i:integer;
ind:boolean;
begin
ind:=true;
for i:=1 to n do ind:=ind and r[i,i];
refleks:=ind;
end;

function simet(n:integer; r:relacija):boolean;


var i,j:integer;
ind:boolean;
begin
ind:=true;
for i:=1 to n-1 do
for j:=i+1 to n do
ind:=ind and r[i,j]=r[j,i];
(* if r[i,j]<>r[j,i] then ind:=false *)
simet:=ind;
end;

function antisimet(n:integer; r:relacija):boolean;


var i,j:integer;

161
Ivan P. Stanimirovi Uvod u programiranje

ind:boolean;
begin
ind:=true;
for i:=1 to n-1 do
for j:=i+1 to n do
if (i<>j) and r[i,j] and r[j,i] then ind:=false;
antisimet:=ind;
end;

function tranzit(n:integer; r:relacija):boolean;


var i,j,k:integer;
ind:boolean;
begin
ind:=true;
for i:=1 to n do
for j:=1 to n do
for k:=1 to n do
if r[i,j] andr [j,k] and (not r[i,k]) then
ind:=false;
tranzit:=ind;
end;

(* Rekurzivne verzije funkcija *)


function refleksr(n:integer; r:relacija):boolean;
begin
if n=1 then
refleksr:= r[1,1]
else refleksr:=refleksr(n-1,r)and r[n,n];
end;

function simetr(n:integer; r:relacija):boolean;


var i:integer;
ind:boolean;
begin
if n<=1 then simetr:=true
else begin
ind:=true;
for i:=1 to n do ind:=ind and (r[i,n]=r[n,i]);
simetr:=simetr(n-1,r) and ind;
end;
simetr:=ind;
end;

function antisimetr(n:integer; r:relacija):boolean;


var i,j:integer;
ind:boolean;
begin
if n<=1 then antisimetr:=true
else begin
ind:=true;
for i:=1 to n-1 do
if r[i,n] and r[n,i] and (i<>n) then
ind:=false;
antisimetr:=ind and antisimetr(n-1,r);
end;
end;

function tranzitr(n:integer; r:relacija):boolean;


var i,j:integer;
ind:boolean;
begin

162
Ivan P. Stanimirovi Uvod u programiranje

if n<=2 then tranzitr:=true


else
begin
ind:=true;
for i:=1 to n do
for j:=1 to n do
if r[i,j] and r[j,n] and(not r[i,n]) then
ind:=false;
tranzitr:=ind and tranzitr(n-1,r);
end;
end;

procedure uradi;
var brekv, brpor, brnekor:integer;
f:text;
r:relacija;
n:integer;
ref,sim,asim,tr,refr,simr,asimr,trr:boolean;
begin
brekv:=0; brpor:=0; brnekor:=0;
assign(f,'c:\relacije'); reset(f);
while not eof(f) do
begin
if not ucitaj(f,n,r) then
brnekor:=brnekor+1
else
begin
ref:=refleks(n,r); (* ref:=refleksr(n,r *)
sim:=simet(n,r); (* sim:=simetr(n,r); *)
asim:=antisimet(n,r);
(* asim:=antisimetr(n,r); *)
tr:=tranzit(n,r); (* tr:=tranzitr(n,r); *)
if ref and sim and tr then brekv:=brekv+1;
if ref and asim and tr then brpor:=brpor+1;
end;
end;
writeln('Iterativna verzija: ');
writeln('Bilo je ',brekv,' relacija ekvivalencije');
writeln('Bilo je ',brpor,' relacija poretka');
writeln('Bilo je ',brnekor,' nekorektnih relacija');
close(f);
end;

begin
uradi;
end.

156. (PASCAL) Mali urica je poeo da skija. urica je egzibicionista i ne skija po stazama, ve
skija kako stigne. Zbog toga, sluba spasavanja je reila da napravi program koji e izraunati sva
mogua mesta na kojima se urica moe nai. Mapa terena se zadaje kao matrica dimenzija m n,
gde svaki element matrice h[i, j], predstavlja visinu mesta sa koordinatama (i, j). urica se spusta
uvek u pravcu samo jedne koorditane (ne dijagonalno), i to iskljuivo sa mesta koje je vie, na mesto
koje je nie (h[istart, jstart] > > h[i, j] > > h[ikraj, jkraj]). Za zadato startno mesto i mapu
terena, treba odtampati broj mesta na kojima se urica moe nai (ukljuujui i startno mesto).
Ulazni podaci nalaze se u fajlu ZAD2.DAT. U prvom redu ulaznog fajla nalaze se celi brojevi m i n (1
m 100, 1 n 100), gde je m broj redova, a n broj kolona mape terena. U sledeih m redova nalazi
se po n celih brojeva koji predstavljaju elemente matrice h[i, j] (0 h[i, j] 10000). U sledeem redu
nalaze se brojevi r i k koji predstavljaju red i kolonu startnog mesta (1 r m, 1 k n).

163
Ivan P. Stanimirovi Uvod u programiranje

Izlazne podatke treba upisati u fajl ZAD2.RES. Fajl treba da sadri samo jedan broj x, koji predstavlja
broj mesta na kojima se urica moe nalaziti:

{A+,B-,D+,E+,F+,G+,I+,L+,N-,O+,P-,Q+,R+,S+,T-,V+,X+,Y+}
{M 65520,300000,600000}

const inp='zad2.dat';
out='zad2.res';

var a:array[0..101,0..101] of 0..10000;


mark:array[0..101,0..101] of boolean;
n,m,i,j,r,k,br:integer;
f:text;

procedure radi(x,y:byte);
begin
inc(br);
mark[x,y]:=true;
if x<m then
if (a[x+1,y]<a[x,y]) and not mark[x+1,y] then
radi(x+1,y);
if y<n then
if (a[x,y+1]<a[x,y]) and not mark[x,y+1] then
radi (x,y+1);
if x>1 then
if (a[x-1,y]<a[x,y]) and not mark[x-1,y] then
radi(x-1,y);
if y>1 then
if (a[x,y-1]<a[x,y]) and not mark[x,y-1] then
radi(x,y-1);
end;

begin
assign(f,inp); reset(f);
read(f,m,n);
for i:=1 to m do
for j:=1 to n do read(f,a[i,j]);
read(f,r,k); br:=0; close(f);
radi (r,k);
assign(f,out); rewrite(f);
write(f,br); close(f);
end.
Test primeri:
ZAD2.DAT ZAD2.RES Objanjenje: Sva mesta na
kojima se urica moe nai su
podvuena.
6 7 14 0 0 0 10 10 10 10
0 0 0 10 10 10 10 0 0 0 10 10 10 10
0 0 0 10 10 10 10 10 2 10 6 10 0 1
10 2 10 6 10 0 1 10 3 10 7 7 4 2
10 3 10 7 7 4 2 10 4 5 7 8 10 10
10 4 5 7 8 10 10 10 3 10 10 9 10 10
10 3 10 10 9 10 10
6 5

60. (C) Napisati proceduru kojom se uitavaju elementi pravougaone matrice x dimenzija mn, gde je
m i n <=10. Napisati funkciju koja odreuje najduu rastuu seriju brojeva u nizu celih brojeva.
Koristei ovu funkciju, napisati funkciju koja odreuje indeks vrste u matrici x koja sadri najduu
rastuu seriju.
Ulaz: Pozitivni celi brojevi m i n koji predstavljaju dimenzije matrice x, a zatim m n elemenata matrice x.
Izlaz: Redni broj vrste u matrici x koja sadri najduu rastuu seriju brojeva.

164
Ivan P. Stanimirovi Uvod u programiranje

#include<stdio.h>
int naj(int x[], int n)
{ int i;
float s, max;
s=max=1;
for(i=1;i<n; i++)
if(x[i]>x[i-1]) s++;
else
{
if (s>max) max=s;
s=1;
}
if(s>max) max=s;
return(max);
}
void ucitaj(int x[][10], int m, int n)
{ int i,j;
for(i=0; i<m; i++)
for(j=0; j<n; j++) scanf("%d", &x[i][j]);
}
int najduza(int a[][10], int m, int n)
{ int i,max=0, k, ind;
for(i=0; i<m; i++)
{ k=naj(a[i],n);
if(k>max)
{ max=k; ind=i; }
}
return(ind+1);
}

void main()
{ int x[10][10];
int mx, m, n;
scanf("%d%d", &m,&n);
ucitaj(x,m,n);
mx=najduza(x,m,n);
printf("Vrsta sa najduzom serijom je %d.\n",mx);
}
Test primeri:
3 5 2 3
2 7 -2 3 4 2 3 4
1 1 0 -2 3 2 1 3
2 3 4 5 0

Vrsta sa najduzom serijom je 3. Vrsta sa najduzom serijom je 1.

152. (C) Napisati program koji kvadratnu matricu dimenzije dimdim popunjava prirodnim brojevima
od 1 do dim2 po spirali. Oigledno je da e maksimalni upisan broj biti dim2. Sutina zadatka je nai
uslov koji treba da ispunjavaju vrste i kolone da bi dolo do skretanja u odreenom pravcu. Za
skretanje udesno uslov je da je i+j<dim+1. Za skretanje nanie uslov je da je i<j. Za skretanje ulevo
uslov je da je i+j<>dim+1. Za skretanje navie uslov je da je i>j+1.

void main()
{ int i,j,dim,brojac,kraj;int spirala[21][21];
do { printf("\nUnesite dimenziju matrice: ");
scanf("%d",&dim); }
while (dim<1 || dim>20);
brojac=0;i=1;j=0;kraj=dim*dim;
do
{

165
Ivan P. Stanimirovi Uvod u programiranje

while ((brojac < kraj) && (i+j<dim+1))


{ j++;brojac++; spirala[i][j]=brojac;}
while ((brojac < kraj) && (i<j))
{ i++;brojac++; spirala[i][j]=brojac;}
while ((brojac < kraj) && (i+j!=dim+1))
{ j--;brojac++; spirala[i][j]=brojac;}
while ((brojac < kraj) && (i>j+1))
{ i--;brojac++; spirala[i][j]=brojac;}
}
while (brojac!=kraj);

printf("\n");
for (i=1;i<=dim;i++)
{ for (j=1;j<=dim;j++)
printf("%3d ",spirala[i][j]);
printf("\n");
}
}
Reenje 2.
#include <stdio.h>
void main()
{ int a[100][100]; int i,j,p,q,b,n,z,m,k,e,k2,e2,r;
scanf("%d%d",&n,&m);
for (i=1;i<=n;i++)
for (j=1;j<=m;j++) a[i][j]=0;
i=1;j=1;b=1;k=n;e=m;p=0;q=1;k2=1;e2=1;z=n*m;
while (b<=z)
{ a[i][j]=b;
if((j==e)&&(i==k2)) { p=1; q=0; };
if((i==k)&&(j==e)) { q=-1; p=0; };
if((i==k)&&(j==e2)) { p=-1; q=0; };
if((j==e2)&&(i==k2)) { p=0; q=1;};
if((j==e2)&&(i==k2+1))
{ p=0;q=1;k2++;e2++;e--;k--; };
b++; i=i+p; j=j+q;
}
for (i=1;i<=n;i++)
{ printf("\n");
for (j=1;j<=m;j++) printf("%4d",a[i][j]);
}
}
Test primer:

Unesite dimenziju matrice:15


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
56 57 58 59 60 61 62 63 64 65 66 67 68 69 16
55 104 105 106 107 108 109 110 111 112 113 114 115 70 17
54 103 144 145 146 147 148 149 150 151 152 153 116 71 18
53 102 143 176 177 178 179 180 181 182 183 154 117 72 19
52 101 142 175 200 201 202 203 204 205 184 155 118 73 20
51 100 141 174 199 216 217 218 219 206 185 156 119 74 21
50 99 140 173 198 215 224 225 220 207 186 157 120 75 22
49 98 139 172 197 214 223 222 221 208 187 158 121 76 23
48 97 138 171 196 213 212 211 210 209 188 159 122 77 24
47 96 137 170 195 194 193 192 191 190 189 160 123 78 25

153. (C) Napisati program kojim se u matrici dimenzija mn upisuju brojevi do zadatog broja, pratei
put kuglice koja polazi od elementa sa koordinatama (0,0) i odbija se od zidova matrice. Ostali
elementi matrice su 0.

166
Ivan P. Stanimirovi Uvod u programiranje

#include<stdio.h>
main()
{ int a[100][100];
int i,j,p,q,n,m,b,k;
scanf("%d",&n); scanf("%d",&m);
for (i=0;i<n;i++)
for (j=0;j<m;j++) a[i][j]=0;
scanf("%d",&k);
i=0;j=0; p=q=1; b=2;
a[i][j]=1;i=j=1;
while (b<=k)
{ a[i][j]=b; b++;
if ((i==(n-1))||(i==0)) p=p*(-1);
if ((j==(m-1))||(j==0)) q=q*(-1);
i=i+p; j=j+q;
}
for (i=0;i<n;i++)
{ printf("\n");
for (j=0;j<m;j++)
printf("%d\t",a[i][j]);
}
}
Test primeri:
2 4 4 3 3 4

1 0 3 0 1 0 0
0 2 0 4 0 4 0
0 0 3
Jo jedno reenje
#include <stdio.h>

typedef int mat[100][100];

void ispis( int m, int n, mat a)


{ int i,j;
for (i=0;i<m; i++)
{for (j=0;j<n; j++)
printf("%d\t", a[i][j]);
printf("\n");}
}

void main()
{ int n,m;
mat a = {{0,0}};
int cnt;
scanf("%d %d %d", &m, &n, &cnt);
int dx=1;
int dy=1;
int cx=0;
int cy=0;
int curr=0;
while (cnt--)
{
a[cx][cy] = ++curr;
cx+=dx;
cy+=dy;
if ((cx>=m)||(cx<0))
{
dx*=-1;

167
Ivan P. Stanimirovi Uvod u programiranje

cx+=2*dx;
}
if ((cy>=n)||(cy<0))
{
dy*=-1;
cy+=2*dy;
}
}

ispis(m, n, a);

}
154. (C) Napisati program koji uitava dimenziju ahovske table (broj kvadrata) i veliinu svakog
kvadrata na tabli, a zatim generie matricu koja odgovara uokvirenoj ahovskoj tabli. U gornjem
levom uglu ahovske table uvek je crni kvadrat. Crnom polju odgovara znak '*', a belom znak ' '.
#include<stdio.h>

void promeni(char *ch)


{ if((*ch)== '*') *ch=' ';
else *ch='*';
}

void generisi(int d,int v, char a[80][80])


{ int i,j,k,l,p,q;
char znak,znak1;
p=1; q=1; znak1='*';
for(i=1; i<=d; i++)
{ for(k=1; k<=v; k++)
{ znak=znak1;
for(j=1; j<=d; j++)
{ for(l=1; l<=v; l++)
{ if(q>d*v) q=1;
a[p][q]=znak; q=q+1;
}
promeni(&znak);
}
p=p+1;
}
promeni(&znak1);
}
a[0][0]=(char)201;
a[0][d*v+1]=(char)187;
a[d*v+1][0]=(char)200;
a[d*v+1][d*v+1]=(char)188;
for(j=1; j<=d*v; j++)
{ a[0][j]=(char)205;a[d*v+1][j]=(char)205; }
for(i=1; i<=d*v; i++)
{ a[i][0]=(char)186;a[i][d*v+1]=(char)186; }
}

void main()
{ char a[80][80];
int i,j,dim,vel;
clrscr();
scanf("%d%d",&dim,&vel);
generisi(dim,vel,a);
for(i=0; i<=dim*vel+1; i++)
{ for(j=0; j<=dim*vel+1; j++) putchar(a[i][j]);
printf("\n");
}

168
Ivan P. Stanimirovi Uvod u programiranje

}
Reenje 2.
#include<stdio.h>

void generisi(int d,int v, char a[80][80])


{ int i,j;
for(i=1; i<=d*v; i++)
for(j=1; j<=d*v; j++)
if( ((i-1)/v+(j-1)/v)%2==0)
a[i][j]='*';
else a[i][j]=' ';
a[0][0]=(char)201;
a[0][d*v+1]=(char)187;
a[d*v+1][0]=(char)200;
a[d*v+1][d*v+1]=(char)188;
for(j=1; j<=d*v; j++)
{ a[0][j]=(char)205;
a[d*v+1][j]=(char)205;
a[j][0]=(char)186;
a[j][d*v+1]=(char)186; }
}

void main()
{ char a[80][80];
int i,j,dim,vel;
clrscr();
scanf("%d%d",&dim,&vel);
generisi(dim,vel,a);
for(i=0; i<=dim*vel+1; i++)
{ for(j=0; j<=dim*vel+1; j++)
putchar(a[i][j]);
printf("\n");
}
}
Test primeri:

Primer. (C) U svakom od tri kontejnera se nalazi izvesna koliina smeih, zelenih i belih boca koje
treba da se recikliraju. Da bi staklo moglo da se reciklira u svakom kontejneru moraju da se nalaze
boce iste boje. Napisati program koji odreuje minimalni broj premetanja boca tako da posle
premestanja u svakom kontejneru budu boce iste boje. Pri jednom premetanju se prebacuje jedna
boca iz bilo kog u neki drugi kontejner, a kontejneri su dovoljno veliki da mogu da sadre sve boce.
U tekstualnom fajlu zad2.dat nalaze se 3 reda sa po 3 broja u svakom, koji opisuju poetno
stanje: broj smeih, zelenih i belih boca u prvom kontejneru, zatim u drugom i na kraju u treem. U

169
Ivan P. Stanimirovi Uvod u programiranje

izlazni fajl zad2.res ispisati minimalan broj premetanja koji je potreban da se postigne to zavrno
stanje.

Test Primer:
zad2.dat zad2.res
1 2 3 30
4 5 6
7 8 9

#include<stdio.h>
int main(){
FILE *f,*g;
int i,j,k,m[3][3],r,a;
f=fopen("zad2.dat","r");
g=fopen("zad2.res","w");
for(i=0;i<3;i++)
for(j=0;j<3;j++)
fscanf(f,"%d",&m[i][j]);
r=-1;
for(i=0;i<3;i++)
for(j=0;j<3;j++)
for(k=0;k<3;k++)
if ((i!=j)&&(i!=k)&&(j!=k)){

a=m[0][i]+m[1][i]+m[0][j]+m[2][j]+m[1][k]+m[2][k];
if(a<r) r=a;
else if(r==-1) r=a;
}
fprintf(g,"%d",r);
fclose(f);
fclose(g);
return 0;
}

Kratko objanjenje reenja


Za reavanje ovog zadatka dovoljne su nam 2. Prva for petlja koja se sastoji iz dve for petlje slui za
uitavanje broja flaa koje se nalaze u kontejnerima i za smetanje tih brojeva u matricu m dimenzije 33.
Druga sloena petlja, koja se sastoji od tri for petlje ispituje sva mogua premestanja flaa tako da
novodobijeni raspored zadovoljava postavljeni uslov. Od svih premestanja bira se premestanje sa najmanjim
brojem poteza i broj premetanja se smesta u promenljivu r, koja se zatim i upisuje u izlaznu datoteku kao
krajnji i tani rezultat naeg programa.

6.5.3. Matrice i dinamika alokacija memorije


1. Dinamika matrica se predstavlja strukturom koja sadri dimenzije i pokaziva na elemente
matrice. Sastaviti na jeziku C program za transponovanje matrice celih brojeva. Polaznu matricu a i
transponovanu matricu b smestiti u dinamiku zonu memorije i deklarisati ih sa
int **a, **b.
Program bi trebalo da u beskonanom ciklusu obrauje proizvoljan broj poetnih matrica. Beskonani
ciklus prekinuti kada se za dimenzije ulazne matrice zada vrednost koja je 0.

#include<stdio.h>
#include<stdlib.h>

void main()
{ int **a, **b, m,n,i,j;

170
Ivan P. Stanimirovi Uvod u programiranje

while(1)
{ printf("\nBroj vrsta i kolona? "); scanf("%d%d", &m,&n);
if(m<=0 || n<=0)break;
a=(int **)malloc(m*sizeof(int *));
for(i=0; i<m; i++)
{ a[i]=(int *)malloc(n*sizeof(int));
printf("Elementi %2d. vrste:\n",i+1);
for(j=0; j<n; scanf("%d",&a[i][j++]));
}
b=(int **)malloc(n*sizeof(int *));
for(i=0; i<n; i++)
{ b[i]=(int *)malloc(m*sizeof(int));
for(j=0; j<m; j++)b[i][j]=a[j][i];
}
printf("Transponovana matrica:\n");
for(i=0;i<n;i++)
{ for(j=0;j<m;printf("%d ",b[i][j++]));
printf("\n");
}
}
for(i=0; i<m; free(a[i++])); free(a);
for(i=0; i<n; free(b[i++])); free(b);
}

U programu koji sledi reen je isti problem, samo to su napisane funkcije za uitavanje elemenata
matrice kao i za transponovanje matrice.

#include <stdio.h>
#include <stdlib.h>

void Citaj(int*** a, int* n, int* m)


{ int i, j;
scanf("%d%d", n, m);

*a = (int**) malloc(*n*sizeof(int*));
for (i = 0; i < *n; i++)
(*a)[i] = (int*) malloc(*m*sizeof(int));
for (i = 0; i < *n; i++)
for (j = 0; j < *m; j++)
scanf("%d", *(*a+i)+j); // ili &((**a)[i][j])

void Transponuj(int*** at, int** a, int n, int m)


{ int i, j;
*at = (int**) malloc(m*sizeof(int*));
for (i = 0; i < m; i++)
(*at)[i] = (int*) malloc(n*sizeof(int));
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
(*at)[i][j] = a[j][i];
}

int main()
{ int n, m, i, j;
int** a; int** at;
Citaj(&a, &n, &m);
for (i = 0; i < n; i++)
{ for (j = 0; j < m; j++)printf("%d ", a[i][j]);
printf("\n");
}

171
Ivan P. Stanimirovi Uvod u programiranje

printf("\n");

Transponuj(&at, a, n, m);

for (i = 0; i < m; i++)


{ for (j = 0; j < n; j++) printf("%d ", at[i][j]);
printf("\n");
}

for (i = 0; i < n; i++) free(a[i]);


free(a);
for (i = 0; i < m; i++) free(at[i]);
free(at);
return 0;
}

#include <stdio.h>
#include <stdlib.h>

void Citaj(int*** a, int* n, int* m)


{ int i, j;
scanf("%d%d", n, m);

*a = (int**) malloc(*n*sizeof(int*));
for (i = 0; i < *n; i++)
(*a)[i] = (int*) malloc(*m*sizeof(int));
for (i = 0; i < *n; i++)
for (j = 0; j < *m; j++)
scanf("%d", *(*a+i)+j); // ili &((**a)[i][j])

void Transponuj(int** at, int** a, int n, int m)


{ int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
at[i][j] = a[j][i];
}

int main()
{ int n, m, i, j;
int** a; int** at;
Citaj(&a, &n, &m);
at = (int**) malloc(m*sizeof(int*));
for (i = 0; i < m; i++)
at[i] = (int*) malloc(n*sizeof(int));

for (i = 0; i < n; i++)


{ for (j = 0; j < m; j++)printf("%d ", a[i][j]);
printf("\n");
}
printf("\n");

Transponuj(&at, a, n, m);

for (i = 0; i < m; i++)


{ for (j = 0; j < n; j++) printf("%d ", at[i][j]);
printf("\n");
}

172
Ivan P. Stanimirovi Uvod u programiranje

for (i = 0; i < n; i++) free(a[i]);


free(a);
for (i = 0; i < m; i++) free(at[i]);
free(at);
return 0;
}

6.6. STRINGOVI
U programskim jezicima, string je sekvenca karaktera. String konstanta moe da ima proizvoljan broj
karaktera, ukljuujui i string bez karaktera. Broj karaktera u stringu se naziva duina stringa.
Jedinstveni string koji ne sadri karaktere naziva se prazan string.
Stringovi su podrani u svim modernim programskim jezicima. Tipine operacije nad stringovima
su:
duina (length);
uporeenje na jednakost (equality comparison);
leksikografsko poreenje (lexicographic comparison);
selekcija karaktera u stringu (character selection);
selekcija podstringa (substring selection);
nadovezivanje (concatenation);
konverzija stringa u numeriku vrednost i obratno.

6.6.1. Stringovi u C
U jeziku C, string je jednodimenzionalni niz elemenata tipa char koji se zavrava karakterom '\0'.
String se moe posmatrati i kao pointer na char.
Inicijalizacija i obrada stringova
Karakteru u stringu moe da se pristupi ili kao elementu niza ili pomou pointera na char. Svaki
string se zavrava karakterom '\0'. String konstanta je proizvoljan niz znakova izmeu navodnika. Svi
znaci zahvaeni znacima navoda, kao i null znak '\0' smetaju se u uzastopnim memorijskim
lokacijama.
Na primer, string s = "ABC" moe da se zapamti u memoriju kao sekvenca od 4 karaktera s[0] =
'A', s[1] = 'B', s[2] = 'C', s[3] = '\0', od kojih je poslednji null karakter '\0'. Bez poslednjeg karaktera '\0'
niz nije kompletiran, te predstavlja samo niz karaktera.
Primer. Dodeljivanje poetne vrednosti string promenljivoj.
#define MAXREC 100
void main()
{ char w[MAXREC];

w[0]='A'; w[1]='B'; w[2]='C'; w[3]='\0';
}

Sada je jasno da su karakter 'a' i string "a" dva razliita objekta. String "a" je niz koji sadri dva
karaktera: 'a' i '\0'.
Stringovi su nizovi karaktera, pa se mogu inicijalizovati na mestu deklaracije, kao i nizovi brojeva.
Osim toga, praktinije je da se string inicijalizuje konstantnom vrednou tipa string umesto znak po
znak.

Primer. Moemo pisati


char s[]="abc"; umesto char s[]={'a', 'b', 'c', '\0'};

173
Ivan P. Stanimirovi Uvod u programiranje

Takoe, moe se inicijalizovati pointer na char kao konstantni string:


char *p="abc";

Efekat ove naredbe da se string "abc" smeta u memoriju, a pointer p se inicijalizuje baznom adresom
tog stringa.
U sluaju kada se niz znakova zadate duine inicijalizuje string konstantom, tada se neiskorieni
elementi niza inicijalizuju null znakom '\0'.

Primer. Transformacija stringa: u stringu koji se uitava zameniti svaki znak 'e' znakom 'E', dok se
svaka praznina zamenjuje prelazom u novi red i tabulatorom. Uitavanje znakova u stringu se
zavrava prelazom u novi red.
#include <stdio.h>
#define MAX 50
void main()
{ char line[MAX], *change(char *);
void read(char *);
printf("Unesi jedan red: ");
read(line);
printf("\n%s\n\n%s\n\n","Posle promene red je: ", change(line));
}

void read(char *s)


{ int c, i=0;
while ((c=getchar()) !='\n') s[i++]=c;
s[i]='\0';
}

char *change(char *s)


{ static char new_string[MAX];
char *p=new_string;
/* pointer p je inicijalizovan na baznu adresu od new_string */
for (; *s != '\0'; ++s)
if(*s=='e') *p++='E';
else if(*s==' ') { *p++='\n'; *p++='\t'; }
else *p++=*s;
*p='\0';
return(new_string);
}

#include <stdio.h>

char s[105];

174
Ivan P. Stanimirovi Uvod u programiranje

int main()
{
//scanf("%[^\n]s",s);
gets(s);
int p=0;
int cnt=0;
while (s[p])
cnt+=s[p++]==' ';
p=0;
while (s[p]) p++;
int pl=p+cnt-1;
while (p)
{
if (s[p-1]=='e')
s[p-1]='E';
if (s[p-1]==' ')
{
p--;
s[pl]='\t';
pl--;
s[pl]='\n';
pl--;
}
else
{
p--;
s[pl]=s[p];
pl--;
}
}
puts(s);
}

Testiranje i konverzija znakova


Standardna biblioteka <ctype.h> sadri deklaracije funkcija za testiranje znakova. Sve funkcije iz
te biblioteke imaju jedan argument tipa int, ija vrednost je ili EOF ili je predstavljena kao unsigned
char. Rezultat svake od ovih funkcija je tipa int. Funkcije vraaju rezultat razliit od nule (tano), ako
argument zadovoljava opisani uslov, a 0 ako ne zadovoljava. Najee koriene funkcije iz ove
biblioteke su:
isdigit(c) ispituje da li je c decimalna cifra;
islower(c) ispituje da li je c malo slovo;
isupper(c) ispituje da li je c veliko slovo;
isalpha(c) ispituje da li je islower(c) ili isupper(c) tano;
isalnum(c) ispituje da li je isalpha(c) ili isdigit(c) tano;
iscntrl(c) ispituje da li je c kontrolni znak (kontrolni znaci imaju kodove 0... 31);
isspace(c) razmak, novi red, povratnik, vertikalni ili horizontalni tabulator.
Takoe, postoje i dve funkcije za promenu veliine slova.
int tolower(int c) konvertuje c u malo slovo;
int toupper(int c) konvertuje c u veliko slovo.
Ako je karakter c veliko slovo, tada funkcija tolower(c) vraa odgovarajue malo slovo, a inae vraa
c. Ako je karakter c malo slovo, tada funkcija toupper(c) vraa odgovarajue veliko slovo, a inae
vraa nepromenjeno c.
Primer. Prebrojavanje rei unutar stringa. String se zavrava prelazom u novi red ili karakterom EOF.
Rei unutar stringa su razdvojene prazninama.

175
Ivan P. Stanimirovi Uvod u programiranje

#include <stdio.h>
#include <ctype.h>
#define MAX 30
void main()
{ char line[MAX];
void read(char *);
int cnt(char *);
printf("\n Unesi string : "); read(line);
printf("\n Broj reci = %d\n", cnt(line));
}

void read(char *s)


{ int c,i=0;
while ((c=getchar()) !=EOF && c!='\n') s[i++]=c;
s[i]='\0';
}

int cnt(char *s)


{ int br=0;
while (*s!='\0')
{ while (isspace(*s)) ++s;
/* preskoci praznine izmedju reci na pocetku */
if(*s!='\0') /* naci rec */
{ ++br;
while(!isspace(*s)&& *s!='\0') /*preskoci rec*/
++s;
}
}
return(br);
}

Primer. String je deklarisan kao statiki niz karaktera a zatim je inicijalizovan nekom string
konstantom. Napisati program koji ispisuje string u direktnom i inverznom poretku.
#include<stdio.h>
void main()
{ static char s[]="Konstantni string";
char *p;
p=s; printf("\nIspis stringa:\n");
while(*p) putchar(*p++);
printf("\nIspis u inverznom poretku:\n");
while(--p>=s) putchar(*p);
putchar('\n');
}
Uitavanje i ispis stringova

Vrednosti stringova se mogu i uitavati. Pri uitavanju stringova bitno je da se rezervie dovoljno
memorijskog prostora za smetanje stringova. Program ne moe da predvidi maksimalnu duinu
stringa i da rezervie potreban memorijski prostor. Zbog toga je programer obavezan da predvidi
maksimalnu duinu stringova koji se uitavaju. String moe da dobije vrednost pomou funkcije
scanf(), koristei format %s. Na primer, moemo pisati:
scanf("%s", w);
Svi znaci, do prvog znaka EOF ili do prve praznine se uzimaju kao elementi stringa w. Posle toga se
null karakter stavlja na kraj stringa. Napomenimo da nije koriena adresa &w u drugom argumentu
funkcije scanf(). Kako je ime niza u stvari bazna adresa niza, oigledno je w ekvivalentno sa &w[0].
Stoga je operator adresiranja ispred imena niza w nepotreban.
Za uitavanje stringova najee se koristi funkcija gets(). Ovom funkcijom se prihvataju svi znaci
sa tastature, sve dok se ne unese znak za novi red '\n'. Znak za prelaz u novi red se ignorie, dok se svi

176
Ivan P. Stanimirovi Uvod u programiranje

ostali karakteri dodeljuju stringu koji se uitava. Kao poslednji znak uitanog stringa uvek se postavlja
null karakter '\0'.
Prototip funkcije gets() je oblika char *gets(char *)

Ukoliko je uitavanje zavreno korektno, vrednost ove funkcije je pokaziva na adresu u kojoj je
smeten prvi znak stringa s. U suprotnom sluaju, vraena vrednost je NULL (nulta adresa, koja je u
datoteci stdio.h definisana sa 0). To znai da se kontrola pravilnosti ulaza moe kontrolisati izrazom
while(gets(ime)==NULL);

Primer. Uitavanje stringa i njegovo prikazivanje na ekran.


#include<stdio.h>
void main()
{ char ime[100]; char *pok;
pok=gets(ime);
printf("1. nacin: %s\n",ime); printf("2. nacin: %s\n",pok);
}

Primer. Re je data kao niz od n karaktera (n<300). Napisati program koji nalazi najdui palindrom u
toj rei. Palindrom je podniz od uzastopnih elemenata koji se jednako ita s leva i s desna.

177
Ivan P. Stanimirovi Uvod u programiranje

#include <stdio.h>
void main()
{ char a[300];
int i,j,n,maxi,maxl,maxj,l;
int pal(char *, int, int);
printf("Unesi broj karaktera reci\n"); scanf("%d",&n);
printf("Unesi rec:\n"); scanf("%c", &a[0]);
for (i=0; i<n; i++) scanf("%c", &a[i]);
a[i]='\0';
maxl=0;
for (i=0; i<n; i++)
for (j=i; j<n; j++)
{ if(pal(a,i,j))
{ l=(j-i)+1; if (l>maxl){ maxl=l; maxj=j; maxi=i; }
}
}
printf("\nNajduzi palindrom je od pozicije %d do %d\n", maxi,maxj);
for (i=maxi; i<=maxj; i++) printf("%c",a[i]);
printf("\n");
}

int pal (char *a, int i, int j)


{ int p; int l,k,m; char b[300];
l=(j-i)+1; k=0;
for (m=i; m<=j; m++) b[++k]=a[m];
p=1; k=1;
while(p && k<=l/2)
if(b[k] != b[l-k+1]) p=0;
else k++;
return(p);
}

Jo jedno reenje za funkciju pal dato je u sledeem kodu


int pal (char *a, int i, int j)
{ int m; char *p, *q;
p=q=a;
for(m=0; m<i; m++){ p++; q++; }
for(m=i; m<j; m++)q++;
while(q>=p)
if(*q != *p) return 0;
else { p++; q--; }
return 1;
}

Primer. U beskonanom ciklusu se uitavaju stringovi i ispituje da li su palindromi. Stringovi se


tretiraju kao pointeri na karaktere.
void main()
{ char s[30];
printf("\n Stringovi u beskonanom ciklusu\n");
while(1)
{ printf("Zadati string\n"); gets(s);
if(palindrom(s)) printf("Jeste palindrom\n");
else printf("Nije palindrom\n");
}
}

int palindrom(char *strpok)


{ char *strpok1=strpok;
while(*strpok1)++strpok1;

178
Ivan P. Stanimirovi Uvod u programiranje

--strpok1;
while(strpok < strpok1) if(*strpok++ != *strpok1--) return(0);
return(1);
}
Primer. Ispitati da li je uneti string palindrom
#include<cstdio>
#include<cstring>
#include<algorithm>

void main()
{
char s[100], s2[100];
int i,j,n,b;
scanf("%s",s);
n=strlen(s);
i=0; b=0;
j=n-1;
while ((i<n/2)&&(j>n/2)&&(b==0))
{
if (s[i]!=s[j]) b++;
i++;
j--;
}
if (b==0) printf("Palindrom je.\n");
else printf("Nije palindrom\n");

char *a,*c;
a=s;
c=s;
while (*c) c++;
c--;
b=1;
while ((a<c)&&b)
{
if (*a!=*c) b=0;
else {a++; c--;}
}
if (b) printf("Palindrom je.\n");
else printf("Nije palindrom\n");

strcpy(s2,s);
std::reverse(s2,s2+strlen(s2)-1);
printf("%s\n",
(!strcmp(s, s2)) ? "Nije palindrom." : "Jeste palindrom.");
}

Primer. Uitava se tekst, sve do znaka ENTER. tampati izvetaj, u kome se nalaze duine rei
sadranih u tekstu, kao i broj rei date duine.
#include<stdio.h>
#define MAX 80
int separator(char ch)
{ return(ch==','||ch==' '||ch==';'||ch=='('||ch==')'||
ch==' '||ch=='!'||ch=='?')||ch=='\n'; }
void main()
{ char ch;
int i,l=0;
int b[MAX];
for(i=1; i<=MAX; i++)b[i]=0;
while((ch=getchar()) != '\n')
{ if(!separator(ch)) l++;

179
Ivan P. Stanimirovi Uvod u programiranje

else if(l>0) { b[l]++; l=0; }


}
ch=getchar();
if(l>0) { b[l]++; l=0; }
printf("%s %s\n","Duzina reci","Broj ponavljanja");
for(i=1;i<=MAX;i++)
if(b[i]>0) printf("%d %d\n",i,b[i]);
}

Ve je pokazano da se vrednosti stringova mogu ispisivati pomou funkcije printf, koristei format
%s. Takoe, za ispis stringova se moe koristiti standardna funkcija puts. Funkcija puts ima jedan
argument, koji predstavlja pokaziva na poetnu adresu stringa koji se ispisuje. Funkcija puts ispisuje
sve karaktere poev od pozicije odreene argumentom funkcije do zavrnog karaktera \0'.
Primer. Zadati string s koristei funkciju gets(). Napisati funkciju za izbacivanje svih nula sa kraja
stringa, kao i funkciju za izbacivanje nula sa poetka uitanog stringa. U glavnom programu izbaciti
sve poetne i zavrne nule u zadatom stringu.
#include <stdio.h>
void main()
{ char s[30];
void ukloni_kraj(char *);
void ukloni_pocetak(char *);
printf("\n Zadati string:\n"); gets(s);
ukloni_kraj(s);
printf("\nString bez zadnjih nula = "); puts(s);
ukloni_pocetak(s);
printf("\nString bez pocetnih i zadnjih nula = "); puts(s);
}

void ukloni_pocetak(char *s)


{ char *t=s;
while(*t && *t=='0') t++;
/* Naen je prvi karakter razlicit od \0 */
while(*t) *s++=*t++;
/* Kopira preostale karaktere na pocetak stringa */
*s='\0';
}

void ukloni_kraj(char *s)


{ char *t=s;
while(*t)t++;
t--;
while(*t=='0')t--;
t++; *t='\0';
}
Primer. Napisati program kojim se u jednoj liniji unosi korektno zapisan postfiksni izraz, a zatim
izraunava njegova vrednost. Operandi u izrazu su prirodni brojevi razdvojeni blanko simbolom, a
operacije su iz skupa {+, -, *, /}, pri emu je / celobrojno deljenje.
Na primer, postfiksnom izrazu 3 2 7 + - 4 * odgovara infiksni izraz (3-(2+7))*4=-24.
#include<stdio.h>
#include<string.h>
#include<stdio.h>
void main()
{ char izraz[80], *s;
int a[41],n,greska,x,st;
while(1)
{ gets(izraz); n=0; greska=0; s=izraz;
while(*s && !greska)

180
Ivan P. Stanimirovi Uvod u programiranje

{ if(*s>='0' && *s<='9')


{ x=0; st=1;
while (*s>='0' && *s<='9')
{ x+=(*s-'0')*st; st*=10; s++; }
a[n++]=x;
}
else if(*s!=' ')
{ switch(*s)
{ case '+': a[n-2]+=a[n-1]; break;
case '-': a[n-2]-=a[n-1]; break;
case '*': a[n-2]*=a[n-1]; break;
case '/': if(a[n-1]) a[n-2]/=a[n-1];
else greska=1;
}
n--;
}
s++;
}
if(!greska) printf("%d\n",a[0]);
else printf("greska, deljenje nulom\n");
}
}

Standardne funkcije za rad sa stringovima u C


Standardna biblioteka sadri vei broj funkcija za manipulaciju stringovima. Ove funkcije nisu deo C
jezika, ali su napisane u jeziku C. U njima su esto promenljive deklarisane u memorijskoj klasi
register, da bi se obezbedila njihovo bre izvravanje. Sve te funkcije zahtevaju da se string zavrava
null karakterom, a njihov rezultat je integer ili pointer na char. Prototipovi ovih funkcija su dati u
header fajlu <string.h>.
unsigned strlen(char *s) Prebrojava sve karaktere pre '\0' u s, i vraa naeni broj.
int strcmp(char *s1, char *s2) Rezultat je ceo broj <0, =0 ili >0, zavisno od toga da li je s1
u leksikografskom poretku manje, jednako ili vee od s2.
int strncmp(char *s1, char *s2, int n) Slina je funkciji strcmp, osim to ova funkcija uporeuje
najvie n karaktera niske s1 sa odgovarajuim karakterima
niske s2.
char *strcat(char *s1, char *s2) Stringovi s1 i s2 se spajaju, a rezultujui string se smeta u
s1. Rezultat je pointer na s1. U stvari, povezuje nisku s2 sa
krajem niske s1. Mora da se alocira dovoljno memorije za s1.
char *strncat(char *s1, char *s2, int n) Nadovezuje najvie n znakova niske s2 sa krajem niske s1.
Nisku s1 zavrava karakterom \0 i vraa s1.
char *strcpy(char *s1, char *s2) String s2 se kopira u memoriju, poev od bazne adrese na
koju ukazuje s1. Sadraj od s1 se gubi. Rezultat je pointer s1.
char *strncpy(char *s1, char *s2, int n) Kopira najvie n znakova stringa s2 u memoriju, poev od
bazne adrese na koju ukazuje s1. Rezultat je pointer s1.
char *strchr(char *s, char c) Rezultat primene ove funkcije je pointer na prvo
pojavljivanje karaktera c u stringu s, ili NULL ako se c ne
sadri u s.
char *strstr(char *s1, char *s2) Ova funkcija vraa pokaziva na prvi znak u s1 poev od
koga se s2 sadri u s1.
int atoi(char *s) Ova funkcija prevodi string s sastavljen od ASCII znakova u
ekvivalentan ceo broj. Ispred decimalnog broja koji je
sadran u s moe da stoji proizvoljan broj nula, praznina ili

181
Ivan P. Stanimirovi Uvod u programiranje

znakova tabulacije, i ono se ignoriu. String s moe poinjati


znakom minus (-), i tada je rezultat konverzije negativni ceo
broj. Broj se zavrava null karakterom \0 ili bilo kojim
znakom koji nije cifra. Ova funkcija se nalazi u standardnoj
biblioteci stdlib.h.
float atof(char *s) Ova funkcija prevodi string s sastavljen od ASCII znakova u
ekvivalentan realni broj. Ova funkcija se nalazi u standardnoj
biblioteci stdlib.h.

Funkcija strlen moe da se implementira na sledei nain:


unsigned strlen(register char *s)
{ register unsigned n;
for (n=0; *s!='\0'; ++s) ++n;
return(n);
}
Primer.
char s1[100], s2[100], t[100];
strcpy(s1, "recenica 1"); strcpy(s2, "rec 2");
strlen(s1); /* 10 */
strlen(s1+9); /* 1 */
strcmp(s1, s2); /* pozitivan broj */
s3=strcpy(t,s1+9); /* t="1" */
strcat(t," "); /* t="1 " */
strcat(t,s1+9); /* t="1 1"*/
printf("%s",s3); /* 1 1*/
printf("%s",t); /* 1 1*/

Primer. Funkcija strcpy se moe implementirati na sledei nain:


char *strpy(char *s1, char *s2)
{ char u;
u=s2;
while(s1++=s2++);
return(u);
}

Primer. Kaemo da se string U pojavljuje u stringu T sa pomakom s, ili da se U pojavljuje u T poev


od pozicije s ako su ispunjeni sledei uslovi:
0 <= s <= Tn - Un,
T[s+j] = U[j] za 0 <= j < Un,
gde je Tn broj elemenata u stringu T a Un duina stringa U.
Odrediti sva pojavljivanja stringa U u stringu T.
#include<string.h>
void sekv_sm (char *t, char *u)
{ int s, j;
int tn, un;
tn = strlen(t); un = strlen(u);
for (s = 0; s <= tn-un; s++)
{ for (j = 0; j < un; j++) if (t[s+j] != u[j]) break;
if(j == un) printf("Uzorak se pojavljuje sa pocetkom %d.\n", s);
}
}

void main()
{ char *s1, *s2;

182
Ivan P. Stanimirovi Uvod u programiranje

printf("Prvi string? "); gets(s1);


printf("Drugi string? "); gets(s2);
sekv_sm(s1,s2);
}
Primer. Napisati C program za ureivanje niza imena po abecednom redosledu. Broj imena nije
unapred poznat. Svako ime se uitava u posebnom redu. Niz imena se zavrava imenom koje je
jednako ....
#include<stdio.h>
#include<string.h>
#define N 100
#define D 40

void main()
{ char ljudi[N][D+1], osoba[D+1];
int i,j,m,n=0;
//Citanje neuredjenog niza imena
do
gets(ljudi[n]);
while(strcmp(ljudi[n++],"...")!=0);
n--;

//Uredjivanje niza imena


for(i=0;i<n-1;i++)
{ m=i;
for(j=i+1; j<n; j++)
if(strcmp(ljudi[j],ljudi[m])<0)m=j;
if(m!=i)
{ strcpy(osoba,ljudi[i]); strcpy(ljudi[i],ljudi[m]);
strcpy(ljudi[m],osoba);
}
}

//Ispisivanje uredjenog niza imena


for(i=0; i<n; puts(ljudi[i++]));
}

II nain
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 100
#define D 40

void main()
{ char **ljudi, osoba[D+1];
int i,j,m,n=0;
ljudi=(char **)malloc(N*sizeof(char *));
//Citanje neuredjenog niza imena
do
{ ljudi[n]=(char *)malloc((D+1)*sizeof(char));
gets(ljudi[n]);
}
while(strcmp(*(ljudi +n++),"...")!=0);
n--;

//Uredjivanje niza imena


for(i=0;i<n-1;i++)
{ m=i;
for(j=i+1; j<n; j++)
if(strcmp(ljudi[j],ljudi[m])<0)m=j; // *(ljudi+i)=ljudi[i]

183
Ivan P. Stanimirovi Uvod u programiranje

if(m!=i)
{ strcpy(osoba,ljudi[i]); strcpy(ljudi[i],ljudi[m]);
strcpy(ljudi[m],osoba);
}
}

//Ispisivanje uredjenog niza imena


for(i=0; i<n; puts(ljudi[i++]));
}

Primer. Na krunom putu duine mn kilometara postoji n benzinskjh stanica (1 < n < 100, 1 < m <
1000). Na stanici i ima ukupno si litara benzina. Izmeu svake dve stanice je rastojanje m kilometara.
Automobil polazi iz jedne od stanica, a moe da zapone kretanje u bilo kom od dva smera. Na poetku
mu je rezervoar prazan, a pri prolazu kroz svaku od stanica uzima celokupnu koliinu goriva iz stanice
(rezervoar ima neogranienu zapreminu). Automobil troi b (1 b 10) litara po kilometru. Odrediti
da li postoji stanica iz koje automobil moe da zapone kretanje i obie celu stazu.
U ulaznoj datoteci 'zad3.in' dati su, redom, brojevi n, m, b, s1, ..., sn. U izlaznu datoteku 'zad3.out'
upisati re 'MOGUE' ako postoji traena stanica, a u suprotmom re 'NEMOGUE'.
zad3.in zad3.out Objanjenje
3 1 1 MOGUE Na putu su tri stanice. Automobil moe da
2 2 0 krene iz bilo koje od prve dve.
3 1 2 NEMOGUE Poto automobil troi 21 na kilometar, iz
4 0 1 koje god stanice da pode, ne moe da obie
celu stazu.

6.7. Strukture i nabrojivi tipovi u c


Strukture su sloeni tipovi podataka koje se, za razliku od nizova, sastoje od komponenti
(segmenata) razliitog tipa. Komponente sloga se obino nazivaju polja. Svako polje poseduje ime i
tip. Imena polja se grade kao i drugi identifikatori.

6.7.1. lanovi strukture


Slino slogovima u Pascalu, strukture dozvoljavaju da se razliite komponente ujedine u
pojedinanu strukturu. Komponente strukture su takoe imenovane i nazivaju se lanovi (odnosno
elementi ili polja). Elementi struktura su razliitih tipova generalno, i mogu se prilagoavati problemu.
Strukture se definiu pomou kljune rei struct. U najoptijem obliku, strukture se opisuju na sledei
nain:
struct [oznaka]
{ tip ime_elementa1[, ime_elementa2...];

}[<ime_promenljive 1>[, <ime_ promenljive 2>...]];

Rezervisana re struct slui kao informacija kompajleru da neposredno iza nje sledi opis neke
strukture. Zatim sledi neobavezni identifikator, oznaen sa oznaka, koji predstavlja ime strukture. Ime
dodeljeno strukturi se moe kasnije koristiti pri deklaraciji promenljivih strukturnog tipa. Iza imena
strukture, izmeu velikih zagrada, deklariu se pojedini delovi strukture. Elementi strukture mogu biti
proizvoljnih tipova, pa i nove strukture. Iza poslednje zagrade pie se znak ';'. Izmeu zatvorene
zagrade } i znaka ; opciono se mogu navesti imena promenljivih strukturnog tipa.
Primer. Sledeom definicijom strukture opisani su osnovni podaci o studentu: ime, broj indeksa i
upisana godina studija.
struct student { char *ime;
int indeks;

184
Ivan P. Stanimirovi Uvod u programiranje

int godina;
} s1,s2,s3;
Osim toga, promenljive s1, s2, s3 se deklariu kao promenljive koje mogu da sadre konkretne
vrednosti saglasno tipu struct student, tj. podatke o studentima. Svaki slog o studentu sadri tri
komponente: ime, indeks i godina. Komponenta ime je string, dok su komponente indeks i godina
celobrojnog tipa.

Struktura moe da se koristi kao ablon za deklaraciju tipova podataka. Na primer, neka je
deklarisana struktura student na sledei nain:
struct student { char *ime;
int indeks;
int godina;
};

Sada se mogu deklarisati strukturne promenljive strukturnog tipa struct student. Na primer, moemo
pisati
struct student pom, razred[100];

Tek posle ovakvih deklaracija se alocira memorija za promenljivu pom i niz razred.
Objedinjavanje opisa strukture ije je ime izostavljeno sa deklaracijama promenljivih koristi se
kada se ablon strukture ne koristi na drugim mestima u programu. Na primer, moemo pisati
struct
{ char *ime;
int indeks;
int godina;
} s1,s2,s3;

Strukturna promenljiva se moe inicijalizovati na mestu svoje deklaracije:


static struct student pom= { "Milan", 1799, 3};

lanovima strukture se direktno pristupa pomou operatora '.'.


Na primer, vrednosti lanovima strukture student mogu se dodeljivati na sledei nain:
strcpy(pom.ime, "Milan");
pom.indeks= 1799;
pom.godina= 3;

Takoe, lanovima strukture se mogu zadati eljene vrednosti pomou funkcija scanf() i gets():
gets(pom.ime);
scanf("%d",&pom.indeks);
scanf("%d",&pom.godina);

Ako se opis strukture navede van svih funkcija, ta struktura se moe koristiti u svim funkcijama
koje su definisane posle opisa strukture. Uobiajeno je da se definicija strukture navede na poetku
izvornog programa, pre opisa promenljivih i funkcija. U velikim programima opisi struktura se obino
piu u posebnom fajlu.

185
Ivan P. Stanimirovi Uvod u programiranje

186
Ivan P. Stanimirovi Uvod u programiranje

Primer. Prebrojati studente tree godine.


Moe se prvo napisati fajl cl.h:
#define N 10
struct student { char ime[30];
int indeks;
int godina;
};

Ovaj header fajl moe se koristiti kao informacija u modulima koje ine program.
#include "cl.h"
#include<stdio.h>
#include<string.h>
void main()
{ int broji(student *);
student s[10];
int i;
for(i=0; i<N; i++)
{ printf("%d ti student : ",i);
gets(s[i].ime);
scanf("%d", &s[i].indeks); scanf("%d", &s[i].godina);
getchar();
}
printf("Studenata trece godine ima %d\n", broji(s));
}

int broji(student *sts)


{ int i, cnt=0;
for (i=0; i<N; ++i)
cnt += sts[i].godina==3;
return(cnt);
}
Drugi nain:
#include "cl.h"
#include<stdio.h>
#include<string.h>
void main()
{ int broji(student *);
void ucitaj(student *s);
student s[10];
ucitaj(s);
printf("Studenata trece godine ima %d\n", broji(s));
}

void ucitaj(student *s)


{ int i;
for(i=0; i<N; i++)
{ printf("%d ti student : ",i);
gets(s[i].ime);
scanf("%d", &s[i].indeks); scanf("%d", &s[i].godina);
getchar();
}
}

int broji(student *sts)


{ int i, cnt=0;
for (i=0; i<N; ++i)
cnt += sts[i].godina==3;
return(cnt);
}

187
Ivan P. Stanimirovi Uvod u programiranje

Trei nain:
#include "cl.h"
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void main()
{ int broji(student *);
void ucitaj(student *);
student *s=(student *)malloc(N*sizeof(student));
ucitaj(s);
printf("Studenata trece godine ima %d\n", broji(s));
}

void ucitaj(student *s)


{ int i;
for(i=0; i<N; i++)
{ printf("%d ti student : ",i);
gets(s[i].ime);
scanf("%d", &s[i].indeks); scanf("%d", &s[i].godina);
getchar();
}
}

int broji(student *sts)


{ int i, cnt=0;
for (i=0; i<N; ++i)
cnt += sts[i].godina==3;
return(cnt);
}

Strukture se mogu inicijalizovati od strane programera na mestu svoje deklaracije.


Primer. U sledeem kdu je definisan nabrojivi tip Month i strukturni tip Date.
enum Month {jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec};
struct Date {Month m; byte d;};
Ova struktura ima skup vrednosti
Date = MonthByte = {jan,feb, ..., dec}{0, ..., 255}.

#include<stdio.h>

enum Month {jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec};


struct Date {
Month m;
unsigned short d;
};
void main()
{ struct Date someday = {jan, 1}; // deklaracija i incijalizacija
//Sledeci kod ilustruje selekciju elemenata strukture
printf("%d/%d\n", someday.m + 1, someday.d);
someday.d = 29; someday.m = feb;
printf("%d/%d\n", someday.m+1, someday.d);
}
Primer. Primeri inicijalizacije struktura.
1. Struktura datum:
struct datum
{ int dan, mesec, godina; };
struct datum d={11, 4, 1996};
1. Struktura karta:

188
Ivan P. Stanimirovi Uvod u programiranje

enum tip {p,h,k,t};


struct karta
{ int vrednost;
tip boja;
};
struct karta k={12, 't'};
Primer. Deklaracija strukture datum i inicijalizacija strukturne (i statike) promenljive danas.
#include <stdio.h>
void main()
{ struct datum
{ int dan;
int mesec;
int godina;
} danas={9, 4, 1996};
printf("%d.%d.%d.\n",danas.dan,danas.mesec,danas.godina);
}

Primer. Program za korekciju tekueg vremena u sekundama.


void main()
{ struct vreme
{ int sat;
int minut;
int sekund;
} tekuce,naredno;
printf("Unesi tekuce vreme [cc:mm:ss]:");
scanf("%d:%d:%d",&tekuce.sat,&tekuce.minut,&tekuce.sekund);
naredno=tekuce;
if (++naredno.sekund==60)
{ naredno.sekund=0;
if(++naredno.minut==60)
{ naredno.minut=0;
if(++naredno.sat==24) naredno.sat=0;
}
}
printf("Naredno vreme: %d:%d:%d\n", naredno.sat,
naredno.minut, naredno.sekund);
}

6.7.2 Strukturni tipovi i pokazivai u C


Mogu se definisati pokazivake promenljive koje e pokazivati na strukturne promenljive.
Vrednosti ovakvih pokazivakih promenljivih jesu adrese strukturnih promenljivih na koje pokazuju.
Na primer, za definisani strukturni tip podataka student moe se definisati pokazivaka promenljiva
pstudent:
struct student *pstudent;
Sada se elementima strukture student moe pristupiti koristei operator indirekcije '*' i operator '.':
(*pstudent).ime
(*pstudent).indeks
(*pstudent).godina

U cilju pristupa elementima strukturne promenljive pomou pokazivaa na tu promenljivu uveden


je operator ''strelica u desno'' ->. Generalno pravilo je sledee: ako je pokazivakoj promenljivoj
pointer_strukture dodeljena adresa neke strukture, tada je izraz
pointer_strukture ->ime_lana
ekvivalentan izrazu

189
Ivan P. Stanimirovi Uvod u programiranje

(*pointer_strukture).ime_lana
U poslednjem izrazu zagrade nisu neophodne.

Operatori -> i '.' imaju asocijativnost sleva udesno.


Na primer elementima strukture pstudent pristupa se na sledei nain:
pstudent->ime
pstudent->indeks
pstudent->godina

Sve eksterne i statike promenljive, ukljuujui strukturne promenljive, koje nisu eksplicitno
inicijalizovane, automatski se inicijalizuju na vrednost nula.
Primer. Neka je definisana struktura licnost na sledei nain:
struct licnost
{ char ime[30];
char adresa[50];
unsigned starost;
}

Takoe, neka je definisana pokazivaka promenljiva osoba:


struct licnost *osoba;
Elementima strukture osoba moe se pristupiti pomou operatora indirekcije '*' i operatora '.':
(*osoba).ime
(*osoba).adresa
(*osoba).starost

Takoe, elementima strukturne promenljive na koju ukazuje pointer osoba, moe se pristupiti i na
sledei nain:
osoba->ime
osoba->adresa
osoba->starost

Formalni parametar funkcije moe biti promenljiva nekog strukturnog tipa S kao i pokaziva na
strukturu S. Ukoliko je formalni parametar strukturna promenljiva, tada se kao stvarni parametar
navodi strukturna promenljiva ili neka konstantna vrednost strukturnog tipa S. U pozivu te funkcije,
kao stvarni parametar, predaje se kopija vrednosti te strukturne promenljive. Na taj nain, ne menja se
vrednost strukturne promenljive koja je predata kao stvarni parametar. U sluaju kada je formalni
parametar funkcije pointer na strukturu, tada se kao stvarni parametar predaje adresa strukturne
promenljive koja se koristi kao stvarni parametar. Time je omogueno ne samo korienje vrednosti
pokazivake promenljive (pomou operatora indirekcije), ve i promena tih vrednosti.
Takoe, strukture se mogu koristiti kao elementi nizova. Nizovi struktura se deklariu analogno
ostalim nizovima. Na primer, za definisane strukture licnost i student mogu se koristiti nizovi
struct licnost osobe[20]
struct student studenti[50]

Ovakvim deklaracijama opisan je niz struktura osobe od najvie 20 elemenata, kao i niz struktura
studenti sa najvie 50 elemenata. Svaki element niza osobe predstavlja jednu strukturnu promenljivu
tipa licnost.
Primer. U ovom primeru je definisana matrica kompleksnih brojeva i dodeljene su poetne vrednosti
njenim elementima. Svaki element matrice predstavljen je parom realnih brojeva.
static struct complex
{ double real;
double imag;
} m[3][3]=
{ { {1.0,-0.5}, {2.5,1.0}, {0.7,0.7} },
{ {7.0,-6.5}, {-0.5,1.0}, {45.7,8.0} },

190
Ivan P. Stanimirovi Uvod u programiranje

};

Elementi strukture mogu biti nove strukture. Struktura koja sadri bar jedan element strukturnog
tipa naziva se hijerarhijska struktura.
Primer. Definisana je struktura licnost koja sadri element datumrodjena strukturnog tipa datum:
struct datum
{ unsigned dan;
unsigned mesec;
unsigned godina;
}
struct licnost
{ char *ime;
datum datumrodjenja;
}

Strukturna promenljiva danas moe se definisati pomou izraza


struct datum danas;
Pointer p na ovu strukturu deklarie se iskazom
struct datum *p;

Postavljanje pointera p na adresu strukturne promenljive danas ostvaruje se naredbom


p=&danas;
Sada se strukturnoj promenljivoj danas moe pristupiti indirektno, pomou pointera p na jedan od
sledea dva ekvivalentna naina:
(*p).godina=1996; p->godina=1996;
(*p).mesec=4; p->mesec=4;
(*p).dan=11; p->dan=11;

Takoe, pointeri mogu biti lanovi strukture.


Primer. Izraz
struct pointeri
{ int *n1;
int *n2;
};

definie strukturu pointeri sa dva ukazatelja n1 i n2 na tip int. Sada se moe deklarisati strukturna
promenljiva ukaz:
struct pointeri ukaz;
void main()
{ int i1, i2;
struct { int *n1;
int *n2;
}ukaz;
ukaz.n1=&i1; ukaz.n2=&i2;
*ukaz.n1=111; *ukaz.n2=222;
/* indirektno dodeljivanje vrednosti promenljivim i1, i2 */
printf("i1=%d *ukaz.n1=%d\n", i1, *ukaz.n1);
printf("i2=%d *ukaz.n2=%d\n", i2, *ukaz.n2);
}
Primer. Dva ekvivalentna pristupa elementima strukture.
struct Simple { int a; };
int main() {
Simple so, *sp = &so;
sp->a;
so.a;
}

191
Ivan P. Stanimirovi Uvod u programiranje

Primer. Prebrojavanje studenata tree godine.


#include "cl.h"
#include<stdio.h>
#include<string.h>
void main()
{ int i;
student s[10];
int broji(student *);
void citaj(student *,int);
for(i=0; i<N; i++)
citaj(&s[i],i);
printf("Studenata trece godine ima %d\n", broji(s));
}

int broji(student *sts)


{ int i, cnt=0;
for (i=0; i<N; ++i)
cnt += sts[i].godina==3;
return(cnt);
}

void citaj(student *st, int i)


{ printf("%d ti student : ",i);
gets(st->ime); scanf("%d", &(st->indeks));
scanf("%d", &(st->godina));
getchar();
}

192
Ivan P. Stanimirovi Uvod u programiranje

6.7.3. Definicija strukturnih tipova pomou typedef


Mogu se uvesti i strukturni tipovi podataka pomou operatora typedef. Novi strukturni tipovi se
definiu izrazom oblika
typedef struct
{ <tip polja> <ime polja>;
...
} <ime>;
Primer. Definicija strukturnog tipa datum.
typedef struct
{ int dan;
int mesec;
int godina;
} datum;

Sada se identifikator datum moe koristiti kao samostalan tip podataka. Na primer, iskazom
datum rodjendan[10];
deklarie se vektor rodjendan kao jednodimenzionalni vektor sa elementima tipa datum.
Primer. Ime string kao tip za pokazivae na tip char uvodi se pomou operatora typedef na sledei
nain:
typedef char *string;
Sada je
string str1, str2;
ekvivalentno sa
char *str1, *str2;

Primer. Implementacija osnovnih aritmetikih operacija nad kompleksnim brojevima. Kompleksni


brojevi su predstavljeni strukturom kom.
#include <stdio.h>
#include <math.h>
/* UVEDENI TIPOVI */
struct kom
{ float prvi,drugi; };
/* NAJAVE FUNKCIJA */
void upis(struct kom *p);
void ispis(struct kom p);
struct kom zbir(struct kom p,struct kom q);
struct kom proiz(struct kom p,struct kom q);
void main()
{
struct kom a,b,c;
upis(&a);upis(&b);
c=zbir(a,b);
printf("Njihov zbir je ");ispis(c);
c=proiz(a,b);
printf("Njihov proizvod je ");ispis(c);
}
void upis(struct kom *p)
/* Da bi upisani kompleksan broj bio zapamcen
koriste se pointeri. Prema tome, koriste se oznake
(*p).prvi=p->prvi, (*p).drugi=p->drugi */
{
float x,y;
scanf("%f%f",&x,&y); p->prvi=x;p->drugi=y;
}

193
Ivan P. Stanimirovi Uvod u programiranje

void ispis(struct kom p)


{ if(p.drugi>0) printf("\n %f + i*%f\n",p.prvi,p.drugi);
else printf("\n %f i*%f\n",p.prvi,fabs(p.drugi));
}

struct kom zbir(struct kom p,struct kom q)


/* U C-jeziku vrednost funkcije MOZE DA BUDE struct tipa */
{ struct kom priv;
priv.prvi=p.prvi+q.prvi;priv.drugi=p.drugi+q.drugi;
return(priv);
}

struct kom proiz(struct kom p,struct kom q)


{ struct kom priv;
priv.prvi=p.prvi*q.prvi-p.drugi*q.drugi;
priv.drugi=p.prvi*q.drugi+p.drugi*q.prvi;
return(priv);
}

Ovaj zadatak se moe uraditi uz korienje typedef izraza. Kompleksni brojevi se reprezentuju novim
tipom kompl.
#include <stdio.h>
#include <math.h>
typedef struct
{ float prvi,drugi; } kompl;
void upis(kompl *p); void ispis(kompl p);
kompl zbir(kompl p,kompl q); kompl proiz(kompl p,kompl q);
void main()
{ kompl a,b,c;
upis(&a); upis(&b); c=zbir(a,b); ispis(c);
c=proiz(a,b); ispis(c);
}

void upis(kompl *p)


{ float x,y;
printf(" Daj dva broja :\n"); scanf("%f%f",&x,&y);
p->prvi=x;p->drugi=y;
}

void ispis(kompl p)
{ printf("\n %f *i+ %f\n",p.prvi,p.drugi); }

kompl zbir(kompl p,kompl q)


{ kompl priv;
priv.prvi=p.prvi+q.prvi;priv.drugi=p.drugi+q.drugi;
return(priv);
}

kompl proiz(kompl p,kompl q)


{ kompl priv;
priv.prvi=p.prvi*q.prvi-p.drugi*q.drugi;
priv.drugi=p.prvi*q.drugi+p.drugi*q.prvi;
return(priv);
}
Primer. Taka u ravni je definisana kao strukturom Tacka koja sadri dva broja tipa double. Krug je
definisan strukturom koja sadri centar tipa Tacka i poluprenik tipa double. Napisati funkciju koja
ispitatuje da li se dva kruga seku. U funkciji main je dato n krugova. Sa ulaza se uitava n, a u

194
Ivan P. Stanimirovi Uvod u programiranje

narednih n redova su zadati centar i poluprenik svakog kruga. Ispisati redne brojeve svaka dva kruga
koji se seku.
#include<stdio.h>
#include<math.h>

typedef struct
{double x,y; } Tacka;

typedef struct
{ Tacka O; double R; } Krug;

int intersect(Krug a, Krug b)


{ double d;
d=sqrt(pow(a.O.x-b.O.x,2)+ pow(a.O.y-b.O.y,2));
return (d<a.R+b.R)&& (d>fabs(a.R-b.R));
}

void main()
{ int i,j,n;
Krug a[100];
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%lf%lf%lf",&a[i].O.x,
&a[i].O.y,&a[i].R);
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
if(intersect(a[i],a[j]))
printf("%d %d\n",i,j);
}

#include<stdio.h>
#include<math.h>
struct Tacka{ double x,y; };
struct Krug{ Tacka O; double R; };

void CitajKrug(Krug *K)


{ scanf("%lf%lf%lf", &K->O.x,
&K->O.y,&K->R);
}

int Intersect(Krug K1, Krug K2)


{ double
d=sqrt(pow(K1.O.x-K2.O.x,2)+
pow(K1.O.y-K2.O.y,2));
return ((d<K1.R+K2.R) &&
(d>fabs(K1.R-K2.R)));
}

void main()
{ int i,j,n;
Krug K[5];
scanf("%d",&n);
for(i=0; i<n; i++) CitajKrug(&K[i]);
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(Intersect(K[i],K[j])) printf("(%d,%d)\n",i+1,j+1);
}

195
Ivan P. Stanimirovi Uvod u programiranje

Primer. Retka matrica se moe predstaviti brojem ne-nula elemenata kao i sledeim informacijama za
svaki ne-nula element:
- redni broj vrste tog elementa,
- redni broj kolone tog elementa, i
- realan broj koji predstavlja vrednost tog elementa.
Predstaviti retku matricu brojem ne-nula elemenata i nizom slogova, u kome svaki slog sadri redni
broj vrste i kolone kao i vrednost svakog ne-nula elementa.
Napisati procedure za formiranje niza slogova koji predstavljaju reprezentaciju retke matrice A.
Napisati proceduru za ispis matrice.
Napisati proceduru za formiranje sparse reprezentaciju predstavlja matricu AT.
Napisati funkciju koja za zadate vrednosti i, j preko tastature izraunava vrednost elementa A[i,j].
#include<stdio.h>

struct slog
{ int i,j;
float aij;
};

void pravimatricu(struct slog x[10], int *n)


{ int p,q,i;
float xpq;
printf("Broj ne-nula elemenata? "); scanf("%d", n);
printf("Pozicije i vrednosti ne-nula elemenata?\n");
for(i=1; i<=*n; i++)
{ scanf("%d%d%f", &p,&q,&xpq);
x[i].i=p; x[i].j=q; x[i].aij=xpq;
}
}

void transponuj(struct slog x[10], int n, struct slog y[10])


{ int i;
for(i=1; i<=n; i++)
{ y[i].i=x[i].j; y[i].j=x[i].i; y[i].aij=x[i].aij; }
}

void pisimatricu(struct slog y[10], int n)


{ int i;
printf("%d\n",n);
for(i=1; i<=n; i++)
printf("(%d %d): %10.3f\n",y[i].i, y[i].j,y[i].aij);
}

float vrednost(int n, struct slog x[10], int k, int l)


{ int i;
for(i=1; i<=n; i++)
if((x[i].i==k) && (x[i].j==l))
return(x[i].aij);
return(0);
}

void main()
{ int i,j,n;
struct slog p[10], q[10];
pravimatricu(p, &n);
printf("Matrica je: \n");
pisimatricu(p,n);
transponuj(p,n,q);
printf("Transponovana matrica: \n");

160
Ivan P. Stanimirovi Uvod u programiranje

pisimatricu(q,n);
printf("i,j= ? "); scanf("%d%d", &i,&j);
printf("%10.3f\n",vrednost(n,p,i,j));
}
Primer. Modifikacija prethodnog primera. Matrica se zadaje brojem vrsta, brojem kolona, brojem ne-
nula elemenata kao i nizom slogova koji odgovaraju ne-nula elementima. Svaki takav slog je odreen
sledeim informacijama za ne-nula element:
- redni broj vrste tog elementa,
- redni broj kolone tog elementa, i
- realan broj koji predstavlja vrednost tog elementa.
Napisati funkciju za formiranje retke matrice A.
Napisati funkciju za ispis nenula elemenata matrice.
Napisati funkciju za uobiajeni ispis matrice.
Napisati funkciju za formiranje sparse reprezentaciju matrice AT.
Napisati funkciju koja za zadate vrednosti i, j preko tastature izraunava vrednost elementa A[i,j].
#include<stdio.h>

struct slog
{ int i,j;
float aij;
};

struct matrica
{ int m,n,bn;
slog sp[10];
};

void pravimatricu(matrica *a)


{ int i;
printf("Dimenzije matrice: "); scanf("%d%d",&a->m,&a->n);
printf("Broj ne-nula elemenata? "); scanf("%d", &a->bn);
printf("Pozicije i vrednosti ne-nula elemenata?\n");
for(i=0; i<a->bn; i++)
scanf("%d%d%f", &a->sp[i].i,&a->sp[i].j,&a->sp[i].aij);
}

void transponuj(matrica x, matrica *y)


{ int i;
y->m=x.n; y->n=x.n;
y->bn=x.bn;
for(i=0; i<x.bn; i++)
{ y->sp[i].i=x.sp[i].j; y->sp[i].j=x.sp[i].i;
y->sp[i].aij=x.sp[i].aij; }
}

void pisimatricu(matrica x)
{ int i;
for(i=0; i<x.bn; i++)
printf("(%d %d): %10.3f\n",x.sp[i].i, x.sp[i].j,x.sp[i].aij);
}

float vrednost(matrica x, int k, int l)


{ int i;
for(i=0; i<x.bn; i++)
if((x.sp[i].i==k) && (x.sp[i].j==l))
return(x.sp[i].aij);
return(0);
}

161
Ivan P. Stanimirovi Uvod u programiranje

void pisigusto(matrica x)
{ int i,j;
for(i=0;i<x.m; i++)
{ for(j=0; j<x.n; j++)
printf("%5.2f ",vrednost(x,i,j));
printf("\n");
}
}

void main()
{ int i,j;
matrica p, q;
pravimatricu(&p);
printf("Matrica je: \n"); pisimatricu(p); pisigusto(p);
transponuj(p,&q);
printf("Transponovana matrica: \n"); pisimatricu(q); pisigusto(q);
printf("i,j= ? "); scanf("%d%d", &i,&j);
printf("%10.3f\n",vrednost(p,i,j));
}
Primer. Definisana je struktura koja predstavlja datum:
type datum=record
dan:1..31;
mesec:1..12;
godina:0..maxint;
end;
Zatim je definisana je struktura koja sadri jedno polje tipa datum i jedno polje tipa sting:
praznik=record
d:datum;
naziv:string[30];
end;
Ova struktura reprezentuje jedan praznik. U programu formirati niz datuma koji predstavljaju
praznike.
program Praznici;

type datum=record
dan:1..31;
mesec:1..12;
godina:0..maxint;
end;
praznik=record
d:datum;
naziv:string[30];
end;
procedure CitajPraznik(var p:praznik);
begin
with p do
begin
with d do
begin
write('Dan = ? '); readln(dan);
write('Mesec = ? '); readln(mesec);
write('Godina = ? '); readln(godina);
end;
write('Naziv praznika ? '); readln(naziv);
end; {with }
end;

procedure PisiPraznik(p:praznik);

162
Ivan P. Stanimirovi Uvod u programiranje

begin
writeln(p.naziv); writeln;
writeln(p.d.dan,'.',p.d.mesec,'.',p.d.godina,'.'); writeln;
end;

var
i,n:integer;
a:array[1..30] of praznik;

begin
readln(n); writeln('Zadati podatke za ',n,' praznika:');
for i:= 1 to n do CitajPraznik(a[i]);
writeln; writeln;
for i:=1 to n do
begin
writeln(i,'. praznik:'); PisiPraznik(a[i]);
end;
end.
Reenje u jeziku C:
#include<stdio.h>
#include<string.h>
typedef struct
{ int dan, mesec, godina; }datum;
typedef struct
{ char naziv[30];
datum d;
}praznik;

void CitajPraznik(praznik *p)


{ int d,m,g;
printf("Dan = ? "); scanf("%d", &d);
printf("Mesec = ? "); scanf("%d", &m);
printf("Godina = ? "); scanf("%d", &g);
p->d.dan=d; p->d.mesec=m; p->d.godina=g;
printf("Naziv praznika ? ");
gets(p->naziv); gets(p->naziv);
}
void PisiPraznik(praznik p)
{ puts(p.naziv);
printf("\n%d.%d.%d.\n\n",p.d.dan,p.d.mesec,p.d.godina);
}
void main()
{ int i,n;
praznik a[30];
scanf("%d",&n); printf("Zadati podatke za %d praznika:\n",n);
for(i=0;i<n;i++)CitajPraznik(a+i);
printf("\n\n");
for(i=0;i<n;i++)
{ printf("%d. praznik:\n",i+1); PisiPraznik(a[i]); }
}
Primer. Polinom se moe predstaviti strukturom koja sadri red polinoma i niz njegovih koeficijenata.
Napisati funkcije za izraunavanje zbira, razlike, proizvoda i kolinika dva polinoma koji su zadati
odgovarajuim strukturama. Napisati program za testiranje napisanih funkcija.
#include<stdio.h>

typedef struct
{ double a[30]; int n; } Poli;

Poli zbir(Poli p1, Poli p2)


{ Poli p; int i;

163
Ivan P. Stanimirovi Uvod u programiranje

p.n=(p1.n>p2.n)? p1.n : p2.n;


for(i=0;i<=p.n; i++)
if(i>p2.n)p.a[i]=p1.a[i];
else if(i>p1.n)p.a[i]=p2.a[i];
else p.a[i]=p1.a[i]+p2.a[i];
while(p.n>=0 && p.a[p.n]==0)p.n--;
return p;
}

Poli razlika(Poli p1, Poli p2)


{ Poli p; int i;
p.n=(p1.n>p2.n)? p1.n : p2.n;
for(i=0;i<=p.n; i++)
if(i>p2.n)p.a[i]=p1.a[i];
else if(i>p1.n)p.a[i]=-p2.a[i];
else p.a[i]=p1.a[i]-p2.a[i];
while(p.n>=0 && p.a[p.n]==0)p.n--;
return p;
}

Poli proizvod(Poli p1, Poli p2)


{ Poli p; int i,j;
p.n=p1.n+p2.n;
for(i=0;i<=p.n; p.a[i++]=0);
for(i=0; i<=p1.n; i++)
for(j=0; j<=p2.n; j++) p.a[i+j]+=p1.a[i]*p2.a[j];
return p;
}

Poli kolicnik(Poli p1, Poli p2, Poli *ostatak)


{ Poli p; int i,j;
p.n=p1.n-p2.n;
for(i=p.n; i>=0; i--)
{ p.a[i]=p1.a[p2.n+i]/p2.a[p2.n];
for(j=0; j<=p2.n; j++) p1.a[i+j]-= p.a[i]*p2.a[j];
}
while(p1.n>=0 && p1.a[p1.n]==0)p1.n--;
*ostatak=p1;
return p;
}

Poli citaj()
{ Poli p; int i;
printf("Stepen = ? "); scanf("%d", &p.n);
printf("Koeficijenti?\n"); for(i=p.n; i>=0; scanf("%lf", &p.a[i--]));
return p;
}

void pisi(Poli p)
{ int i;
putchar('{');
for(i=p.n; i>=0; i--){ printf("%.2lf", p.a[i]); if(i>0)putchar(','); }
putchar('}');
}
void main()
{ Poli p1, p2, p3;
while(1)
{ p1=citaj(); p2=citaj();
printf("P1 = "); pisi(p1); putchar('\n');
printf("P2 = "); pisi(p2); putchar('\n');
printf("P1+P2 = "); p3=zbir(p1,p2); pisi(p3); putchar('\n');
printf("P1-P2 = "); pisi(razlika(p1,p2)); putchar('\n');

164
Ivan P. Stanimirovi Uvod u programiranje

printf("P1*P2 = "); pisi(proizvod(p1,p2)); putchar('\n');


printf("P1/P2 = "); pisi(kolicnik(p1,p2, &p3)); putchar('\n');
printf("P1%%P2 = "); pisi(p3); putchar('\n'); putchar('\n');
}
}

6.7.4. Unije
Unija je tip podataka koji moe da sadri (u raznim situacijama) objekte razliitih tipova. Unije
odreuju nain manipulisanja razliitim tipovima podataka u istoj memorijskoj oblasti. Svrha njihovog
postojanja je uteda memorije. One su analogne slogovima promenljivog tipa u Pascal-u, a sintaksa im
je zasnovana na strukturama jezika C. Svrha unije je da postoji samo jedna promenljiva koja moe da
sadri bilo koju od vrednosti razliitih tipova. Unije se razlikuju od struktura po tome to elementi
unije koriste isti memorijski prostor, i to se u svakom trenutku koristi samo jedan element unije.
Primer. Pretpostavimo da u tabeli simbola nekog kompajlera, konstanta moe da bude int, float ili
char. Najvea uteda memorije se postie ako je vrednost ma kog elementa tabele memorisana na
istom mestu, bez obzira na tip. U naem sluaju je potrebna sledea deklaracija
union tag
{ int ival;
float fval;
char *sval;
};
union tag u;

Ekvivalentna deklaracija je data kako sledi:


union tag
{ int ival;
float fval;
char *sval;
} u;

Promenljivoj koja je deklarisana kao unija prevodilac dodeljuje memorijski prostor dovoljan za
memorisanje onog lana unije koji zauzima najvei memorijski prostor. Programer mora da vodi
rauna o tome koji tip se trenutno memorie u uniji, jer je vaei tip onaj koji je najskorije memorisan.

lanovi unije se selektuju identino lanovima strukture:


unija.clan

ili
pointer_unije->clan.
Ako je int tip tekueg lana unije u, njegova vrednost se prikazuje izrazom
printf("%d\n",u.ival);
ako je aktivni lan tipa float piemo
printf("%f\n",u.fval);
a ako je tipa char
printf("%s\n",u.sval);
Elementima strukturne promenljive u vrednosti se mogu dodeliti, na primer, iskazima
u.ival=189; ili u.fval=0.3756; ili u.sval="string";

Primer. Jednostavna unija koja sadri jedno celobrojno i jedno realno polje.
void main()
{ union { int i;
float f;
} x;

165
Ivan P. Stanimirovi Uvod u programiranje

x.i=123; printf("x.i=%d x.f=%f\n",x.i,x.f);


x.f=12.803; printf("x.i=%d x.f=%f\n",x.i,x.f);
}

Unije mogu da se pojavljuju u strukturama i nizovima. Kombinacijom strukture i unije grade se


promenljive strukture.
Primer. Tablica simbola
struct { char*name;
int flags;
int utype;
union { int ival;
float fval;
char *sval;
} u;
} symtab[100];

Sada moemo pristupiti lanu ival i-tog elementa tablice simbola pomou izraza
symtab[i].u.ival;

Prvi znak stringa sval i-tog elementa tablice simbola se dobija jednim od sledea dva ekvivalentna
izraza:
*symtab[i].u.sval;
symtab[i].u.sval[0];

Unija se moe inicijalizovati samo pomou vrednosti koja odgovara tipu njenog prvog lana. Stoga
se unija opisana u prethodnom primeru moe inicijalizovati samo pomou celobrojne vrednosti.
Primer. Osnovne geometrijske figure se mogu okarakterisati sledeom strukturom:
struct figura
{ float povrsina, obim; /* Zajednicki elementi */
int tip; /* Oznaka aktivnog elementa */
union
{ float r; /* Poluprecnik kruga */
float a[2]; /* Duzine strana pravougaonika */
float b[3]; /* Duzine strana trougla */
} geom_fig;
} fig;
Primer. Napisati program za izraunavanje rastojanja izmeu dve take u ravni, pri emu postoji
mogunost da svaka od taaka bude definisana u Dekartovom ili polarnom koordinatnom sistemu.
Obuhvaeni su svi sluajevi: kada su obe take zadate Dekartovim koordinatama, jedna od taaka
Dekartovim, a druga polarnim koordinatama i sluaj kada su obe take definisane polarnim
koordinatama.
#include<stdio.h>
#include<math.h>
typedef enum { Dekartove, Polarne }TipKor;

typedef struct
{ double x,y; } Dek;
typedef struct
{ double r,fi; } Pol;
typedef struct
{ TipKor tip;
union
{ Dek DK;
Pol PK;
};

166
Ivan P. Stanimirovi Uvod u programiranje

} koordinate;

void ucitaj(koordinate *Q)


{ int ch;
double u,v;
printf("Tip koordinata? 1 za Dekartove, 2 za polarne: ");
scanf("%d", &ch);
printf("Koordinate? ");
switch (ch)
{ case 1: Q->tip=Dekartove; scanf("%lf%lf", &u, &v);
Q->DK.x=u; Q->DK.y=v;
break;
case 2: Q->tip=Dekartove; scanf("%lf%ld", &u,&v);
Q->PK.r=u, Q->PK.fi=v;
break;
}
}

void main()
{ koordinate A,B;
double d;
ucitaj(&A); ucitaj(&B);
switch(A.tip)
{
case Dekartove:
switch(B.tip)
{ case Dekartove:
d=sqrt(pow(A.DK.x-B.DK.x,2)+pow(A.DK.y-B.DK.y,2));
break;
case Polarne:
d=sqrt(pow(A.DK.x-B.PK.r*cos(B.PK.fi),2)+
pow(A.DK.y-B.PK.r*sin(B.PK.fi),2));
break;
}
break;
case Polarne:
switch(B.tip)
{case Dekartove:
d=sqrt(pow(A.PK.r*cos(A.PK.fi)-B.DK.x,2)+
pow(A.PK.r*sin(A.PK.fi)-B.DK.y,2));
break;
case Polarne:
d=sqrt(pow(A.PK.r*cos(A.PK.fi)-B.PK.r*cos(B.PK.fi),2)+
pow(A.PK.r*sin(A.PK.fi)-B.PK.r*sin(B.PK.fi),2));
break;
}
break;
}
printf("%.4lf\n",d);
}
Primer. Napisati program za sumiranje povrina n geometrijskih figura. Figura moe biti krug
(odreen duinom poluprenika), pravougaonik (odreen duinama susednih stranica) ili trougao
(odreen duinama svojih stranica).
#include<stdio.h>
#include<math.h>
void main()
{ struct pravougaonik
{ double a,b;};
struct trougao
{ double a,b,c; };

167
Ivan P. Stanimirovi Uvod u programiranje

struct figura
{ int tip;
union
{ double r;
struct pravougaonik p;
struct trougao t;
};
} figure[50];

int i,n;
double pov=0,s;
scanf("%d",&n);
for(i=0; i<n; i++)
{ printf("Tip figure (0 - krug, 1-pravougaonik, 2-trougao): ");
scanf("%d",&figure[i].tip);
switch(figure[i].tip)
{ case 0:
scanf("%lf",&figure[i].r);break;
case 1:
scanf("%lf%lf",&figure[i].p.a,&figure[i].p.b);break;
case 2:

scanf("%lf%lf%lf",&figure[i].t.a,&figure[i].t.b,&figure[i].t.c);
break;
}
}
for(i=0;i<n;i++)
{ switch(figure[i].tip)
{ case 0:
pov+=3.14*figure[i].r*figure[i].r;break;
case 1:
pov+=figure[i].p.a*figure[i].p.b;break;
case 2:
s=(figure[i].t.a+figure[i].t.b+figure[i].t.c)/2;
pov+=sqrt(s*(s-figure[i].t.a)*(s-figure[i].t.b)*(s-
figure[i].t.c));
}
}
printf("Povrsina svih figura je %lf\n",pov);
}

6.8. Nabrojivi tip podataka u c


Pomou kljune rei enum deklariu se nabrojivi (enumerisani) tipovi podataka. Promenljive
nabrojivog tipa mogu da imaju samo konaan skup vrednosti. Deklaracija promenljivih nabrojivog
tipa se sastoji od kljune rei enum, imena enumerisanog tipa, eventualno liste dozvoljenih vrednosti i
liste enumerisanih promenljivih koje se deklariu.
Primer. Iskazom
enum flag{true,false};
definisan je nabrojivi tip enum flag. Promenljive ovog tipa mogu da imaju samo vrednosti true ili
false. Kljuna re enum oznaava da se radi o nabrojivom tipu podataka, a identifikator flag
predstavlja ime definisanog nabrojivog tipa. Izmeu zagrada se nalazi lista vrednosti.
Sada se mogu deklarisati promenljive nabrojivog tipa enum flag:
enum flag file_end, input_end;
Ime nabrojivog tipa se moe izostaviti, ime se dobija neimenovani nabrojivni tip. Na primer,
sledea deklaracija je analogna prethodnoj:
enum {true,false} file_end, input_end;

168
Ivan P. Stanimirovi Uvod u programiranje

Dodeljivanje vrednosti enumerisanoj promenljivoj je analogno dodeljivanju vrednosti


promenljivima ostalih tipova. Sledei iskazi su legalni:
file_end=false;
if(input_end == true)

U sledeem primeru se definie nabrojivi tip enum dani:


enum dani {pon,uto,sre,cet,pet,sub,ned};
Vrednosti nabrojivog tipa se tretiraju kao celobrojne konstante. Preciznije, C kompajler dodeljuje
sekvencijalne celobrojne vrednosti elementima liste vrednosti, startujui od prvog elementa liste,
kome se dodeljuje vrednost 0. Na primer, izrazom
ovaj_dan=sreda;
dodeljena je vrednost 2 (ne ime sreda) promenljivoj ovaj_dan (tipa enum dani).
Sekvencijalni nain dodeljivanja celobrojnih vrednosti elementima iz liste imena moe se promeniti
eksplicitnim dodeljivanjem eljene celobrojne vrednosti nekom elementu iz liste imena. Pri tome se
mogu koristiti i negativni celi brojevi.
Primer. Moemo pisati
enum dani{pon,uto,sre=10,cet,pet,sub=100,ned} ;
Sada je
pon=0, uto=1, sre=10, cet=11, pet=12, sub=100, ned=101.
Ako se eli eksplicitno dodeljivanje celobrojne vrednosti nabrojivog promenljivoj, mora da se
koristi kast operator.
Na primer, izraz
ovaj_dan=pon
ekvivalentan je sa
ovaj dan=(enum dani)0;

Primer. Program odreivanje sledeeg dana u nedelji


#include<stdio.h>
void main()
{ int k;
enum dani{pon,uto,sre,cet,pet,sub,ned} sledeci;
printf("unesite danasnji dan:\n"); scanf("%d",&k);
k+=1; k%=7;
sledeci=(enum dani)k;
printf("\nSledeci dan je %d.dan u nedelji\n", (int)sledeci);
}

Ista konstanta se ne moe koristiti u deklaracijama razliitih nabrojivih tipova podataka. Na primer,
definicije tipova
enum radnidani {pon,uto,sre,cet,pet};
enum vikend {pet,sub,ned};
su nekorektne, jer se konstanta pet pojavljuje u definiciji oba tipa. Nabrojivi tip se moe definisati
koristei operatore typedef i enum. Na primer, sledeim definicijama su uvedena dva nabrojiva tipa,
samoglasnik i dani:
typedef enum {A,E,I,O,U} samoglasnik;
typedef enum {pon,uto,sre,cet,pet,sub,ned} dani;

Posle definicije ovih tipova mogu se deklarisati promenljive uvedenih tipova:


samoglasnik slovo;
dani d1,d2;

169
Ivan P. Stanimirovi Uvod u programiranje

Promenljivoj nabrojivog tipa se moe dodeliti bilo koja vrednost koja je sadrana u definiciji
nabrojivog tipa:
slovo=U;
d1=sre;
Ako se vrednosti promenljivih nabrojivog tipa ispisuju pomou funkcije printf(), ispisuju se
celobrojne vrednosti koje su dobile na osnovu definicije nabrojivog tipa.
Za razliku od Pascala, promenljive nabrojivog tipa se ne mogu koristiti kao brojake promenljive u
operatorima FOR ciklusa.

6.9. Dinamike matrice i strukture


Primer. Dinamika matrica se predstavlja strukturom koja sadri dimenzije i pokaziva na elemente
matrice. Sastaviti na jeziku C paket funkcija za rad sa dinamikim matricama realnih brojeva koji
sadri funkcije za:
dodeljivanje memorije matrici datih dimenzija,
oslobaanje memorije koju zauzima matrica,
kopiranje matrice,
itanje matrice preko glavnog ulaza,
ispisivanje matrice preko glavnog izlaza,
nalaenje transponovane matrice za datu matricu,
nalaenje zbira, razlike i proizvoda dve matrice.
Sastaviti na jeziku C glavni program za proveru ispravnosti rada gornjih funkcija.
Reenje:
#include <stdlib.h>
#include <stdio.h>

typedef enum {MEM, DIM} Greska; /* ifre greaka. */


typedef struct { float **a; int m, n; } Din_mat; /* Struktura matrice. */

Din_mat stvori (int m, int n); /* Dodela memorije. */


void unisti (Din_mat dm); /* Oslobadjanje memorije. */
Din_mat kopiraj (Din_mat dm) ; /* Kopiranje matrice. */
Din_mat citaj (int m, int n) ; /* Citanje matrice. */
void pisi (Din_mat dm, const char *frm, int max); /* Ispisivanje matrice.*/
Din_mat transpon (Din_mat dm); /* Transponovana matrica*/
Din_mat zbir (Din_mat dm1, Din_mat dm2); /* Zbir matrica. */
Din_mat razlika (Din_mat dm1, Din_mat dm2); /* Razlika matrica. */
Din_mat proizvod (Din_mat dm1, Din_mat dm2); /* Proizvod matrica. */

/* Definicije paketa za rad sa dinamickim matricama. */

const char *poruke[] = /* Poruke o grekama.*/


{ "Neuspela dodela memorije", "Neusaglasene dimenzije matrica" };

static void greska (Greska g) { /* Ispisivanje poruke greci. */


printf("\n*** %s ! ***\n\a", poruke[g]);
exit(g+1);
}

Din_mat stvori (int m, int n) { /* Dodela memorije. */


int i; Din_mat dm;
dm.m = m; dm.n = n;
if((dm.a = (float **)malloc(m*sizeof(float*))) == NULL) greska (MEM);
for(i=0; i<m; i++)
if((dm.a[i] = (float *)malloc(n*sizeof(float))) == NULL) greska (MEM);

170
Ivan P. Stanimirovi Uvod u programiranje

return dm;
}

void unisti (Din_mat dm) { /* Oslobadjanje memorije. */


int i;
for (i=0; i<dm.m; free(dm.a[i++]));
free (dm.a);
}

Din_mat kopiraj (Din_mat dm) { /* Kopiranje matrice. */


int i, j;
Din_mat dm2 = stvori (dm.m, dm.n);
for (i=0; i<dm.m; i++)
for (j=0; j<dm.n;j++)
dm2.a[i][j] = dm.a[i][j];
return dm2;
}

Din_mat citaj(int m, int n){ /* Citanje matrice. */


int i,j;
Din_mat dm = stvori(m,n);
for(i=0; i<m; i++)
for(j = 0; j<n; scanf("%f",&dm.a[i][j++]));
return dm;
}

void pisi(Din_mat dm, const char *frm, int max){ /* Ispis matrice. */
int i,j;
for(i=0; i<dm.m; i++) {
for(j=0; j<dm.n; j++) {
printf(frm,dm.a[i][j]);
putchar ((j%max==max-1 || j==dm.n-1) ? '\n' : ' ');
}
if(dm.n > max)putchar ('\n');
}
}

Din_mat transpon(Din_mat dm) { /* Transponovana matrica*/


int i, j;
Din_mat dm2 = stvori(dm.n, dm.m);
for (i=0; i<dm.m; i++)
for(j=0; j<dm.n; j++) dm2.a[j][i] = dm.a[i][j];
return dm2;
}

Din_mat zbir(Din_mat dm1, Din_mat dm2) { /* Zbir matrica. */


int i,j;
Din_mat dm3;
if(dm1.m!=dm2.m || dm1.n != dm2.n) greska(DIM);
dm3 = stvori(dm1.m, dm1.n);
for(i=0; i<dm3.m;i++)
for(j=0; j<dm3.n;j++)
dm3.a[i][j]= dm1.a[i][j] + dm2.a[i][j];
return dm3;
}

Din_mat razlika (Din_mat dm1, Din_mat dm2) { /* Razlika matrica.*/


int i,j; Din_mat dm3;
if(dm1.m!=dm2.m || dm1.n != dm2.n) greska (DIM);
dm3 = stvori (dm1.m, dm1.n);
for(i=0; i<dm3.m;i++)
for(j=0; j<dm3.n;j++)
dm3.a[i][j] = dm1.a[i][j] - dm2.a[i][j];

171
Ivan P. Stanimirovi Uvod u programiranje

return dm3;
}

Din_mat proizvod (Din_mat dm1, Din_mat dm2) { /* Proizvod matrica. */


int i, j, k; Din_mat dm3;
if (dm1.n!=dm2.m) greska (DIM);
dm3 = stvori(dm1.m, dm2.n);
for(i=0; i<dm3.m; i++)
for(k=0; k<dm3.n; k++)
for(dm3.a[i][k]=j=0; j<dm2.m; j++)
dm3.a[i][k] +=dm1.a[i][j] * dm2.a[j][k];
return dm3;
}

int main() {
while (1) {
Din_mat dm1, dm2, dm3; int m, n;
printf ("m1, n1? "); scanf ("%d%d", &m, &n);
if (m<=0 || n<=0) break;
printf("Matrl?\n"); dm1 = citaj(m,n);
printf ("m2, n2? "); scanf ("%d%d", &m, &n);
if(m<=0 || n<=0) break;
printf ("Matr2?\n"); dm2 = citaj(m,n);
if(dm1.m==dm2.m && dm1.n==dm2.n) {
dm3 = zbir(dm1, dm2); printf ("ZBIR:\n");
pisi(dm3,"%8.2f", 8); unisti(dm3);
dm3 = razlika(dm1, dm2); printf ("RAZLIKA:\n");
pisi(dm3, "%8.2f", 8); unisti (dm3);
}
if(dm1.n == dm2.m) {
dm3 = proizvod(dm1,dm2); printf("PROIZVOD:\n");
pisi(dm3, "%8.2f", 8); unisti (dm3);
}
putchar('\n');
unisti(dm1); unisti(dm2);
}
return 0;
}

6.10. Datoteke
Programi koje smo do sada koristili imali su jedan ozbiljan nedostatak. Naime, rezultati obrade
ulaznih veliina prestankom izvravanja programa su nepovratno nestajali. Jedan od naina da se
sauvaju podaci bio bi da se posredstvom tampaa ispiu na hartiji. Meutim, ako postoji potreba da
podaci budu pristupani nekom programu, treba ih sauvati na magnetnim nosiocima informacija, na
primer na disku ili traci. Na taj nain, na disku ili traci se mogu uvati datoteke sa podacima koje
moemo obraivati koliko god hoemo puta, a da ih ne moramo uitavati sa tastature.
Datoteke su sekvencijalne strukture jednorodnih zapisa iji broj nije unapred poznat, i koje se
zapisuju na nekom od spoljanjih memorijskih medijuma. Ovakvi strukturni tipovi opisuju se sa file i
postali su standardni u programskim jezicima posle pojave ovog koncepta u jeziku Pascal.
Datoteke su jednorodne strukture podataka, slino poljima ali za razliku od polja, broj elemenata
datoteke se ne definie unapred i podrazumeva se da one fiziki postoje van programa na nekom od
spoljanjih memorijskih medijuma (disku, traci, disketi itd.).

6.10.1. Pristup datotekama u C


Datoteke omoguavaju da se ulazne veliine i rezultati obrade podataka trajno sauvaju na disku.
Datoteka se tretira kao sekvencijalni niz karaktera. Datotekama se pristupa korienjem ukazatelja na
strukturu FILE, koja je definisana u biblioteci stdio.h. U datoteci stdio.h su definisane i konstante EOF

172
Ivan P. Stanimirovi Uvod u programiranje

i NULL. Konstanta EOF oznaava kraj datoteke i ima vrednost -1. Konstanta NULL ima vrednost 0 i
vraa se kao rezultat neuspenog poziva nekih funkcija za upravljanje datotekama.
Otvaranje i zatvaranje datoteka

Programski jezik C koristi dva osnovna tipa fajlova: tekstualni i binarni tip.
Rad sa fajlovima odvija se kroz nekoliko osnovnih aktivnosti: otvaranje fajla, itanje i upis u fajl,
kretanje po fajlu, zatvaranje fajla.
Datoteka mora da bude otvorena pre bilo kakvog procesiranja. Prilikom otvaranja datoteke mora se
specificirati njeno ime i tip eljene ulazno-izlazne operacije. Moe se koristiti reim itanja (read
mode), reim upisa (write mode), odnosno reim dodavanja (append mode). Za otvaranje datoteka
koristi se funkcija fopen iz C biblioteke. Zaglavlje ove funkcije je oblika
FILE *fopen(const char *filename, const char *mode);

Funkcija fopen() vraa pointer na otvoreni fajl. Vraena vrednost NULL indicira greku prilikom
otvaranja fajla. Parametar filename ime fajla, a parametar mode predstavlja nain na koji se fajl otvara.
Mogui naini su opisani u nastavku:
"r" Otvara za itanje. Ako fajl ne postoji ili ne moe biti pronaen poziv ne uspeva.
"w" Otvara prazan fajl za pisanje. Ako dati fajl postoji njegov sadraj se brie.
"a" Otvara fajl za pisanje na kraju fajla (appending) bez brisanja EOF markera pre pisanja novih
podataka na kraju postojeeg fajla. Ukoliko fajl ne postoji, kreira se novi.
"r+" Otavara fajl za itanje i pisanje. Fajl mora da postoji.
"w+" Otvara prazan fajl za itanje i pisanje. Ako dati fajl postoji, njegov sadraj je obrisan.
"a+" Otvara fajl za itanje i appednovanje. Operacija apendovanja ukljuuje brisanje EOF markera
pre nego se novi podaci upiu u fajl. Marker EOF se restaurira posle kompletiranja pisanja.
Ukoliko fajl sa specificiranim imenom ne postoji, on se prvo kreira.
Kad je fajl otvoren sa pristupom "a" ili "a+" sve opracije upisa se deavaju na kraju fajla. Fajl
pointer moe biti repozicioniran korienjem fseek ili rewind, ali se uvek vraa na kraj fajla pre bilo
koje operacije upisa u fajl. Na taj nain se obezbeuje da preko postojeih podataka nema upisa.
Mod "a" ne brie EOF marker pre dodavanja podataka u fajl. Ako se to desi MSDOS komanda
TYPE samo pokazuje podatke do originalnog EOF markera i ne pokazuje podatke dodate fajlu. Mod
"a+" brie EOF marker pre dodavanja fajlu. Posle dodavanja MSDOS komanda TYPE pokazuje sve
podatke dodate fajlu. Mod "a+" se zahteva za dodavanje stream fajlu koji je terminiran CTRL+Z EOF
markerom. Kad je specificiran neki od "r+", "w+" ili "a+" i itanje i pisanje su dozvoljeni, a kae se da
je fajl otovren za update. Potrebno je da se prilikom prebacivanja izmeu itanja i pisanja uradi
intervencija u obliku poziva fflush, fsetpos, fseek, ili rewind operacije. Tekua pozicija moe biti
specificirana fsetpos ili fseek operacijom.
Sledei karakteri mogu biti ukljueni u mod radi specifikacije prevoenja newline karaktera.
t Otvara fajl u tekstualnom modu. CTRL+Z se interpretira kao end-of-file karakter na ulazu. U
fajlu otvorenom za itanje - pisanje sa "a+" fopen proverava CTRL+Z na kraju fajla i brie ga ako je
mogue. Ovo se radi jer korienje fseek i ftell za kretanje unutara fajla koji se zavrava sa CTRL+Z,
moe da uslovi nekorektno ponaanje fseek blizu kraja fajla. Takoe, u tekstualnom modu carriage
return - line feed kombinacije na ulazu se prevode u jedan linefeeds na ulazu i obratno linefeed
karakter na izlazu se prevode u carriage return line feed kombinacije.
b Otvara fajl u binarnom neprevedenom modu. Prevoenja koja ukljuuju carriage-return i
linefeed kraktere se ne vre.
Ako je otvaranje neuspeno, tj. ako fopen() ne moe da pronae eljenu datoteku, ona vraa
vrednost NULL.
Primer. Niz iskaza

173
Ivan P. Stanimirovi Uvod u programiranje

#include<stdlib.h>
FILE *infile,*fopen();
infile=fopen("file","r"); }
otvara datoteku pod imenom file u reimu itanja.
Funckija fopen() vraa ukazatelj na strukturu FILE, koja se dodeljuje promenljivoj infile istog tipa.
Neuspeno otvaranje datoteke infile se moe ispitati izrazom oblika
if(infile==NULL)
printf("datoteka file ne moze se otvoriti\n");
Poziv funkcije fopen() i ispitivanje vraenog rezultata se moe ujediniti
if((infile=fopen("file","r"))==NULL)
printf("datoteka file ne moze biti otvorena\n");

Funkcijom fclose() zatvara se datoteka otvorena za itanje ili upis. Zatvorenoj datoteci se ne moe
pristupiti pre ponovnog otvaranja. Zaglavlje ove funkcije je
int fclose(FILE *file_pointer);
gde je file_pointer ukazatelj kojim se identifikuje datoteka.
Funkcija
fclose(file_pointer)
vraa vrednost EOF ako ukazatelj file_pointer nije povezan sa nekom datotekom.
Na primer, otvorena datoteka infile zatvara se izrazom
fclose(infile);

Primer.
/* FOPEN.C: This program opens files named "data"
and "data2".It uses fclose to close "data" and
_fcloseall to close all remaining files. */
#include <stdio.h>
FILE *stream, *stream2;
void main(void)
{ int numclosed;
/* Open for read (will fail if file "data" does not exist) */
if( (stream = fopen("data", "r")) == NULL )
printf("The file 'data' was not opened\n" );
else printf( "The file 'data' was opened\n" );
/* Open for write */
if( (stream2 = fopen( "data2", "w+")) == NULL )
printf("The file 'data2' was not opened\n");
else printf("The file 'data2 was opened\n");
/* Close stream */
if(!fclose(stream))
printf( "The file 'data2' was not closed\n" );
/* All other files are closed: */
numclosed = _fcloseall();
printf("Number of files closed by _fcloseall: %u\n", numclosed);
}
Output
The file 'data' was opened
The file 'data' was opened
Number of files closed by _fcloseall : 1

174
Ivan P. Stanimirovi Uvod u programiranje

Funkcije fgetc() i fputc()


Funkcija fgetc() uitava jedan po jedan karakter iz specificirane datoteke. Slina je funkciji getchar().
Ulazni argument funkcije fgetc() je ukazatelj na strukturu FILE, a rezultat je vrednost tipa int.
Zaglavlje ove funkcije je oblika:
int fgetc(FILE *infile)
Pretpostavimo da promenljiva infile dobija vrednost pomou funkcije fopen(), koristei opciju "r".
Ako je c promenljiva tipa int, tada se iskazom
c=fgetc(infile);
uitava jedan znak datoteke koja je povezana sa pointerom infile.
Ako je dostignut kraj datoteke, funkcija getc() vraa vrednost EOF.
Funkcija fputc() upisuje karakter u specificiranu datoteku. Poziva se izrazom oblika
int fputc(char c, FILE *outfile)

fputc

Zaglavlje ove funkcije je oblika


int fputc( int c, FILE *stream );
i pie karakter c u stream.
Vrednost koju ova funkcija vraa je karakter koji se upisuje, ako je upisivanje uspeno, ili EOF ako
je nesupeno upisivanje.
Primer. Izrazima
FILE *outfile;
outfile=fopen("file","w");
fputc('z', outfile);
u datoteku outfile upisuje se znak 'z'.
Primer. Napisati program kojim se sadraj datoteke "ulaz" (formiran od velikih slova azbuke) ifrira i
upisuje u datoteku "izlaz". ifriranje se sastoji u tome da se svaki znak razliit od 'Z' zamenjuje
sledeim ASCII znakom, dok se znak 'Z' zamenjuje znakom 'A'.
#include<stdio.h>
void main()
{ FILE *infile, *outfile;
int c;
infile = fopen("ulaz","r"); outfile= fopen("izlaz","w");
while((c=fgetc(infile)) != EOF)
{ if('A' <= c && c < 'Z')c++;
else c='A';
fputc(c,outfile);
}
fclose(infile); fclose(outfile);
}
Primer:
/* FGETC.C: This program uses getc to read the first
* 80 input characters (or until the end of input)
* and place them into a string named buffer.
*/
#include<stdio.h>
#include<stdlib.h>
void main(void)
{ FILE *stream;

175
Ivan P. Stanimirovi Uvod u programiranje

char buffer[81];
int i, ch;
/* Open file to read line from: */
if( (stream = fopen("fgetc.c", "r")) == NULL ) exit(0);
/* Read in first 80 characters and place them in "buffer": */
ch = fgetc(stream);
for( i=0; (i<80) && (feof(stream)==0); i++)
{ buffer[i] = (char)ch; ch = fgetc( stream }; }
/* Add null to end string */
buffer [i] = '\0' ;
printf("%s\n", buffer); fclose(stream);
}

Primer. Kopiranje sadraja ulazne datoteke u izlaznu datoteku. Imena datoteka data su kao parametri
funkcije main().
#include<stdio.h>
void main(int argc,char *argv[]);
{ int c; FILE *infile,*outfile;
if((infile=fopen(argv[1],"r"))==NULL)
printf("datoteka %s ne moze biti otvorena\n",argv[1]);
else if((outfile=fopen(argv[2],"w"))==NULL)
printf("datoteka %s ne moze biti otvorena\n",argv[2]);
else
{ while((c=getc(infile))!=EOF) putc(c,outfile);
printf("\n");
}
fclose(infile); fclose(outfile);
}
Primer.
/* FPUTC.C: This program uses fputc
* to send a character array to stdout.
*/
#include<stdio.h>
void main(void)
{ char strptrl[] = "This is a test of fputc!!\n";
char *p;
/* Print line to stream using fputc. */
p = strptrl;
while((*p != '\0') && fputc(*(p++), stdout)!= EOF);
}

Funkcije fprintf() i fscanf()


Ove funkcije obavljaju analogne operacije kao i funkcije printf() i scanf(), s tim to zahtevaju
dodatni argument za identifikaciju datoteke u koju se upisuju ili iz koje se itaju podaci. Zaglavlje
ovih funkcija je sledeeg oblika:
fprintf(file_pointer,konverzioni_niz,lista_argumenata)
fscanf(file_pointer,konverzioni_niz,lista_argumenata)
pri emu je:
file_pointer ukazatelj na tip FILE,
konverzioni_niz je lista formata po kojima se upisuju ili itaju podaci, dok je lista_argumenata lista
vrednosti koje se upisuju u datoteku, odnosno itaju iz datoteke koja je identifikovana pointerom
file_pointer.
Funkcije fprintf() i fscanf() imaju promenljivi broj argumenata, zavisno od broja vrednosti koje se
upisuju u datoteku, odnosno itaju iz datoteke.

176
Ivan P. Stanimirovi Uvod u programiranje

Na primer, izrazom
fprintf(outfile,"string u datoteku\n");
upisuje se string "string u datoteku\n" u datoteku koja je identifikovana pomou pointera outfile.
Takoe, u istu datoteku se moe upisati i sledei sadraj:
fprintf(outfile,"string sadrzaja %s u datoteku\n",x);
Primer. Izrazom oblika
fscanf(infile,"%f",&x);
iz datoteke koja je identifikovana sa infile uitava se vrednost u formatu %f i dodeljuje promenljivoj x.
Primer. Procedure za uitavanje celog broja iz datoteke "zad2.dat" i upis istog broja u datoteku
"zad2.res".
#include<stdio.h>
void citaj(long *n)
{ FILE *f;
f=fopen("d:\\zad2.dat","r"); fscanf(f,"%ld",n); fclose(f);
}

void upis(long n)
{ FILE *f;
f=fopen("d:\\zad2.res","w"); fprintf(f,"%ld",n); fclose(f);
}

void main()
{ void citaj(long *); void upis(long);
long n;
citaj(&n); upis(n);
}

Primer. Iz prvog reda datoteke uitati broj timova. U svakom od sledeih redova datoteke zadati
sledee podatke za svaki tim:
- naziv tima,
- broj pobeda,
- broj nereenih rezultata, i
- broj poraza.
Sortirati tabelu prema broju osvojenih bodova. Ako dva tima imaju isti broj osvojenih bodova, sortirati
ih prema broju pobeda.
#include<stdio.h>
#include<string.h>
#define broj 10
struct klub
{ char naziv[30];
int izgubljene;
int neresene;
int dobijene;
} tabela[broj];

void ucitaj(int *n, struct klub a[broj])


{ int i; FILE *f;
f=fopen("klubovi.dat","r");
fscanf(f,"%d",n); fgetc(f);
for(i=0; i<*n; i++)
{ fgets(a[i].naziv,30,f);

fscanf(f,"%d%d%d",&a[i].dobijene,&a[i].neresene,&a[i].izgubljene);
fgetc(f);
}

177
Ivan P. Stanimirovi Uvod u programiranje

fclose(f);
}

void ispis(int n, struct klub a[broj])


{ int i;
for(i=0; i<n; i++)
{ printf("%-20s %d %d %d\n",a[i].naziv, a[i].dobijene,
a[i].neresene,a[i].izgubljene);
}
}

void main()
{ int i,j,n, bodovi[broj]; klub as; int pb;
ucitaj(&n,tabela);
for(i=0;i<n;i++)
tabela[i].naziv[(int)strlen(tabela[i].naziv)-1]='\0';

for(i=0;i<n;i++)
bodovi[i]=tabela[i].neresene+3*tabela[i].dobijene;
for(i=0; i<n-1;i++)
for(j=i+1;j<n;j++)
if((bodovi[i]<bodovi[j])||
((bodovi[i]==bodovi[j]) &&
(tabela[i].dobijene<tabela[j].dobijene))
)
{
as=tabela[i]; tabela[i]=tabela[j];tabela[j]=as;
pb=bodovi[i];bodovi[i]=bodovi[j];bodovi[j]=pb;
}
ispis(n,tabela);
}
Funkcija feof()
Ova funkcija ispituje da li je dostignut broj datoteke. Njen opti oblik je
int feof(FILE *file pointer)
Funkcija feof() vraa nenultu vrednost ako je dostignut kraj datoteke.

Primer. Funkcija feof se koristi za ispitivanje kraja datoteke.


if(feof(infile)) printf("kraj datoteke\n");
Primer. Retka matrica se moe predstaviti brojem ne-nula elemenata kao i sledeim informacijama za
svaki ne-nula element:
- redni broj vrste tog elementa,
- redni broj kolone tog elementa, i
- realan broj koji predstavlja vrednost tog elementa.
Predstaviti retku matricu brojem ne-nula elemenata i nizom slogova, u kome svaki slog sadri redni
broj vrste i kolone kao i vrednost svakog ne-nula elementa.
Napisati procedure za formiranje niza slogova koji predstavljaju reprezentaciju retke matrice A.
Podaci za matricu A se uitavaju iz datoteke 'sparse.dat'.

Napisati proceduru za ispis matrice.


Napisati proceduru za formiranje sparse reprezentaciju predstavlja matricu AT.
Napisati funkciju koja za zadate vrednosti i, j preko tastature izraunava vrednost elementa A[i,j].
#include<stdio.h>

struct slog
{ int i,j;

178
Ivan P. Stanimirovi Uvod u programiranje

float aij;
};

void pravimatricu(struct slog x[10], int *n)


{ int p,q,i;
float xpq;
FILE *infile;
infile=fopen("sparse.dat","r");
fscanf(infile,"%d", n);
for(i=1; i<=*n; i++)
{ fscanf(infile,"%d%d%f", &p,&q,&xpq);
x[i].i=p; x[i].j=q; x[i].aij=xpq;
}
fclose(infile);
}

void transponuj(struct slog x[10], int n, struct slog y[10])


{ int p,q,i;
float xpq;
for(i=1; i<=n; i++)
{ y[i].i=x[i].j; y[i].j=x[i].i; y[i].aij=x[i].aij;
}
}

void pisimatricu(struct slog y[10], int n)


{ int p,q,i;
float xpq;
printf("%d\n",n);
for(i=1; i<=n; i++)
printf("(%d %d): %10.3f\n",y[i].i, y[i].j,y[i].aij);
}

float vrednost(int n, struct slog x[10], int k, int l)


{ int i;
for(i=1; i<=n; i++)
if((x[i].i==k) && (x[i].j==l))
return(x[i].aij);
return(0);
}

void main()
{ int i,j,n;
struct slog p[10], q[10];
pravimatricu(p, &n);
printf("Matrica je : \n"); pisimatricu(p,n);
transponuj(p,n,q);
printf("Transponovana matrica: \n"); pisimatricu(q,n);
printf("i,j= ? "); scanf("%d%d", &i,&j);
printf("%10.3f\n",vrednost(n,p,i,j));
}

Funkcije fgets() i fputs()


Funkcija fgets() ima sledee zaglavlje:
char *fgets(char *string, int maxl, FILE *infile);
Ovom funkcijom se, iz datoteke na koju ukazuje pointer infile, uitava string koji se zavrava
prelazom u novi red ili sadri maxl-1 znakova. Prema tome, drugi argument, oznaen sa maxl,
predstavlja maksimalnu duinu uitanog stringa. Na kraj uitanog stringa postavlja se znak '\0'. U
sluaju da linija iz koje se uitava sadri vie od maxl karaktera, linija se ne ignorie, ve se preostali
znakovi uitavaju sledeim pozivom funkcije fgets().

179
Ivan P. Stanimirovi Uvod u programiranje

Razlika izmeu funkcija gets() i fgets() je u tome da gets() zamenjuje znak za prelaz u novi red
null karakterom '\0', dok fgets() ostavlja znak za prelaz u novi red, pa tek onda postavlja znak '\0'.
Funkcija fgets() vraa vrednost NULL kada naie na znak EOF.
Funkcija fputs() poziva se izrazom
int fputs(char *string, FILE *outfile);
Pozivom ove funkcije upisuje se niz karaktera, sadrani u vrednosti parametra string, u datoteku na
koju ukazuje pointer outfile. U sluaju I/O greke ova funkcija vraa rezultat EOF. Funkcije puts() i
fputs() ne dopisuju karakter '\0' na kraj upisanog stringa. Za razliku od funkcije puts(), funkcija fputs()
ne dopisuje znak za prelaz u novi red na kraj stringa koji se upisuje.
fgets
ita string iz fajla
char *fgets( char *string, int n, FILE *stream );
Vraa string inae NULL ako je greka ili je dolo do kraja fajla.
Koristiti feof ili ferror za odreivanje da li je dolo do greke.
Parametri:
string Mesto za smetanje podataka
n Maksimalni broj karaktera za itanje
stream Pointer na FILE strukturu
Funkcija ita string sa ulaza zadatog argumentom stream i patmi ga u stringu. ita karaktere od
tekue pozicije u fajlu do i ukljuujui prvi newline karakter, do kraja fajla ili do broja karaktera
jednakog n-1, ta se prvo desi. Rezultat zapamen u stringu je zavren null karakterom. Newline
karakter ako je proitan je ukljuen u string. Funkcija fgets je slina gets funkciji, mada gets zamenjuje
newline karakter sa NULL.
/* FGETS.C: This program uses fgets to display
* a line from a file on the screen.n*/
#include <stdio.h> void main( void )
{ FILE *stream;
char line[100];
if((stream = fopen("fgets.c", "r")) != NULL)
{ if(fgets(line, 100, stream) == NULL)
printf("fgets error\n");
else
printf("%s" , line);
fclose( stream );
}
}
fclose, _fcloseall
Zatvara fajl ili sve otvorene fajlove. int fclose( FILE *stream ); int _fcloseall( void );
feof

Testira end-of-file na streamu:


int feof( FILE *stream );
The feof routine (implemented both as a function and as a macro) determines whether the end
ofstream has been reached. When end of file is reached, read operations return an end-of-file indicator
until the stream is closed or until rewind, fsetpos, fseek, or clearerr is called against it.

180
Ivan P. Stanimirovi Uvod u programiranje

6.10.2. Binarne datoteke

fread
ita podatke iz streama.
size_t fread(void *buffer, size_t size, size_t count, FILE *stream );
Funkcija fread vraa broj zaista proitanih itema, to moe biti manje ili jednako parametru count ako
se desi greka ili se stigne do kraja fajla. Koristiti feof ili ferror da bi se razlikovao uzrok.
Parametri:
buffer Loakcija za podatke
size Veliina jednog itema u bajtovima
count Maximalni broj itema za itanje stream pointer na FILE strukturu.
Funkcija ita do count itema a svaki je size bajtova sa ulaznog strima u buffer. File pointer povezan
sa streamom je povean za broj bajtova koji je zaista proitan. Ako je stream otvoren u tekstualnom
modu carriage return-linefeed par je zamenjen ejdnom linefeed characterom. File pointer nije odreen
ako se desila greka.
fwrite
Upisuje podatke u stream.
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
fwrite vraa broj potopunih itema koji su upisani, a sve ostalo je slino funkciji fread.
Primer.
/* FREAD.C: This program opens a file named FREAD.OUT and
* writes 25 characters to the file. It then tries to open
* FREAD.OUT and read in 25 characters. If the attempt succeeds,
* the program displays the number of actual items read.
*/
#include <stdio.h>
void main()
{ FILE *stream;
char list[30];
int i, numread, numwritten;
/* Open file in text mode: */
if((stream = fopen("fread.out" , "w+t")) != NULL)
{ for ( i=0; i<25; i++ )
list[i] = (char)('z' - i);
/* Write 25 characters to stream */
numwritten = fwrite(list, sizeof(char), 25, stream);
printf("Wrote %d items\n", numwritten);
fclose(stream);
}
else printf("Problem opening the file\n");
if((stream = fopen("fread.out", "r+t" )) != NULL)
{ /* Attempt to read in 25 characters */
numread = fread(list, sizeof(char), 25, stream );
printf("Number of items read = %d\n", numread);
printf("Contents of buffer = %.25s\n", list);
fclose(stream);
}
else printf("File could not be opened\n");
}
fseek
Premeta file pointer na specificiranu lokaciju.

181
Ivan P. Stanimirovi Uvod u programiranje

int fseek( FILE *stream, long offset, int origin );


Ako uspe fseek vraa inae vraa vrednost razliitu od 0.
Parametri:
stream Pointer na strukturu FILE.
offset Broj bajtova od izvorita (Number of bytes from origin).
origin Startna pozicija.
fseek funkcija pomera file pointer asociran sa streamom na novu lokaciju koja je offset bajtova od
ohgin.
Tako sledea operacija na streamu uzima poyiciju od nove lokacije.
Argument origin mora biti jeadn od:
SEEK CUR Current position of file pointer
SEEK END End of file
SEEK_SET Beginning of file
ftell
Vraa tekuu poziciju fajl pointera. long ftell( FILE *stream );
Za rad sa tekstualnim fajlovima na raspolaganju su i funkcije pandani poznatim funkcijama prontf i
scanf.
int fprintf(
FILE *stream,
const char * format[,
argument ] . . .
)
int fscanf(
FILE *stream,
const char *format [,
argument ]...
)

Direktni pristup datotekama


Primer. U binarnoj datoteci je ureen niz od m celih brojeva, dodati prirodan broj n na
odgovarajue mesto. Koristiti sekvencijalno pretraivanje.
#include <stdio.h>
#include <stdlib.h>

void main()
{ int niz[21], m,n,i;
FILE *f=fopen("file.txt", "w+b");
niz[0]=0;
printf("Koliko brojeva u nizu?\n"); scanf("%d",&m);
for(i=1; i<m; i++) niz[i]=niz[i-1]+2;
fwrite(niz, sizeof(int), m, f);
fclose(f);

printf("Formirana je sledeca datoteka:\n");


f=fopen("file.txt", "r+b");
fread(niz, sizeof(int), m, f);
for(i=0; i<m; i++) printf("%d ", niz[i]); printf("\n");
printf("Broj koji se umece? "); scanf("%d",&n);
i=0; while((niz[i]<n)&&(i<m)) i++;
fseek(f, i*sizeof(int), SEEK_SET);

fwrite(&n, sizeof(int), 1, f);


fwrite(niz+i, sizeof(int),m-i, f);

182
Ivan P. Stanimirovi Uvod u programiranje

fclose(f); f=fopen("file.txt", "r+b");


printf("Datoteka sa umetnutim brojem %d:\n",n);
fread(niz, sizeof(int), m+1, f);
for(i=0; i<=m; i++) printf("%d ", niz[i]);
fclose(f);
}

Literatura

[1] Literatura sa predavanja.


[2] M. abarkapa, C, Osnovi programiranja, Biblioteka Algoritam, 2000.
[3] M. abarkapa, S. Matkovi, C/C++, Biblioteka Algoritam, Krug, Beograd, 2005.
[4] S. Stojkovi, Programski jezik C sa reenim zadacima, Elektronski fakultet u Niu, Edicija
pomoni udbenici, Ni, 2005.
[5] V. Vujii, Uvod u C jezik, Univerzitet u Beogradu, Institut za nuklearne nauke Boris Kidri,
Vina, 1996.
[6] L. Kraus, Programski jezik C sa reenim zadacima, Akademska Misao, Beograd, 2004.
[7] D. Uroevi, Algoritmi u programskom jeziku C, Mikro Knjiga, Beograd, 1996.
[8] M. Vugdelija, Programiranje & Programiranje,
[9] M. Stankovi, Programski jezici, Elektronski fakultet u Niu, Edicija: osnovni udbenici, 2000.
[10] J.J. Dujmovi, Programski jezici i metode programiranja, Akademska misao, Beograd, 2003.
[11] Mike Grant, Christian Skalka, Scott Smith, Programming Languages, Version 1.01,
http://www.cs.jhu.edu/plbook, 2003.
[12] D.A. Watt, William Findlay, Programming language design concept, John Wiley & Sons Ltd.,
2004.

183
Darko Drakuli

Osnove programskog jezika C sa zbirkom zadataka


-skripta-
Rad u Code::Blocks okruenju

Da bi se napisao i izvrio program napisan na programskom jeziku C, potreban je tekst


editor u kojem e program biti napisan, kompajler i bilder koji e napisani kod kompajlirati i
prevesti u mainski kod, razumljiv raunaru. Postoji dosta aplikacija koji u sebi integriu ove
alate i one nose zajedniko ime IDE (integrated development environment). One u sebi sadre
pomenute alate kod editor, kompajler ili interpreter, bilder i alat za testiranje programa
(debugger). Jedan od takvih alata je Code::Blocks IDE, open source alat koji je besplatan i
koji se moe skinuti sa adrese http://www.codeblocks.org. Ovdje e ukratko biti opisano kako
napisati, kompajlirati i pokrenuti program u pomenutom alatu. Da bi se program mogao
kompajlirati i pokrenuti, sa pomenute adrese je potrebno skinuti instalaciju codeblocks-xxx-
mingw-setup koja u sebi sadri GCC kompajler i GDB dibager. xxx predstavlja trenutnu
verziju alata.
Nakon uspjene istalacije i pokretanja programa Code::Blocks dobija se sljedei izgled
ekrana

Slika 1

Da bi napisali i pokrenuli program u programskom jeziku C, potrebno je kreirati novi


projekat (File->ew->Project) zatim izabrati Console application (slika 2). U polju za izbor
jezika izabrati C (slika 3), i konano dati ime projektu kao i lokaciju na koju e se kod
sauvati (slika 4).

Slika 2.
Slika 3.

Slika 4.

Nakon ovih koraka, klikom na dugme Finish, u lijevom dijelu ekrana u dijelu Projects
pojavie se projekat koji je kreiran, kao i datoteka (main.c) u kojoj se nalazi glavna (main)
funkcija kreiranog projekta.

Otvaranjem te datoteke, dobija se kod najprostijeg C-programa, koji na ekran ispisuje


tekst Hello world.
Osnove programskog jezika C

Struktura programa

Program koji Code::Blocks automatski kreira ima sljedei kod


#include <stdio.h>
#include <stdlib.h>

int main()
{
printf("Hello world!\n");
return 0;
}

Na ovom primjeru e biti objanjena struktura programa napisanog u programskom


jeziku C.
C je tzv. case-sensitive programski jezik, to znai da razlikuje mala i velika slova.
Naredbe return 0 i RETURN 0 su dvije razliite naredbe.
Nakon svake naredbe u C-u mora se nalaziti karakter ;.
C ne poznaje razmake u kodu, tako da se prelazak u novi red nakon svake komande
vri samo iz estetskih razloga, radi lakeg itanja koda.
Komentari se mogu pisati na dva naina: ukoliko se komentar nalazi u jednom redu,
dovoljno je na poetak tog reda staviti karaktere //, a ukoliko se komentar nalazi u vie
redova, potrebno je komentar ograniiti parovima karaktera /* i */. Primjeri komentara su

// Komentar u jednom redu


/* Komentar
u vie redova */

Prva dva reda reda programa


#include <stdio.h>
#include <stdlib.h>
u postojei kod ukljuuju datoteke za prevoenje, u kojma se nalaze funkcije koje su nam
potrebne za uspjeno izvravanje naeg programa. U datoteci stdio.h se nalaze funkcije za
ulaz/izlaz, a u datoteci stdlib.h se nalazi veina funkcija koje su u najeoj upotrebi. O
ovim funkcijama e kasnije biti vie rijei.

Funkcija
int main()
je glavna funkcija programa i izvravanje programa poinje od prve linije koda ove funkcije.
Svaki projekat mora u nekom od fajlova imati ovu funkciju. Ona moe imati drugaiju
definiciju (moe biti nekog drugog tipa, npr. void ili moe imati listu argumenata).

Par vitiastih zagrada


{}
predstavlja granice bloka naredbi, kao begin i end u programskom jeziku PASCAL.
Posljednji red programa
return 0;
predstavlja izlaz iz glavnog programa, odnosno kraj glavnog programa. U ovom sluaju,
glavni program vraa vrijednost 0.

Red
printf("Hello world!\n");
tampa tekst Hello world na ekran. Funkcija printf je definisana u datoteci stdio.h i
ona na standardni izlaz (ekran) ispisuje niz karaktera koji je njen argument. Nizovi karaktera
su ogranieni dvostrukim navodnim znacima (""). Karakter \n koji se nalazi na kraju ovog
niza je specijalni karakter koji oznaava novi red. Osim karaktera za novi red, postoje sljedei
specijalni karakteri:
\t tabulator,
\b backspace,
\ dvostruki navodnici,
\\ - obrnuta kosa crta (backslash).

Promjenljive i konstante

Definisanje promjenljivih

Promjenljive su objekti koji imaju svoje ime i ija se vrijednost moe mijenjati tokom
izvrenja programa.
Definisanje promjenljivih u C-u vri se na sljedei nain:
tip_promjenljive ime_promjenljive;

Tip promjenljive mora biti neki od ugraenih tipova u C jezik ili neki od korisniki
definisanih tipova.
etiri osnovna tipa podataka su
int - cjelobrojni tip,
float - realni tip jednostruke tanosti,
double - realni tip dvostruke tanosti,
char - znakovni tip, karakter.
Iz osnovnog cjelobrojnog tipa se mogu dobiti izvedeni tipovi:
short int (short),
long int (long),
unsigned int (unsigned) pozitivan cijeli broj.

Ime promjenljive je proizvoljan niz karaktera koji ispunjava sljedee zahtjeve:


 ime se sastoji od karaktera, cifara i donje crte _,
 ime ne smije poinjati cifrom,
 ime ne moe biti neka od rezervisanih rijei jezika C (tabela 1.)
Pravila koja vae za imena promjenljivih, vae i za imena konstanti, funkcija i korisnikih
tipova.

auto break case char const continue default do


double else enum extern float for goto if
int long register return short signed sizeof static
struct switch typedef union unsigned void volatile while
Tabela 1. Lista rezervisanih rijei programskog jezika C

Prema opisanom, sljedee definicije promjenljivih su ispravne


int x;
char karakter;
float realni_broj1;
double realni_broj2;

Ukoliko je potrebno definisati vie promjenljivih istog tipa, to se moe uiniti u jednoj
naredbi. Naredba za definisanje cjelobrojnih promjenljivih x, y i z je
int x, y, z;

Definisanje alternativnih imena tipovima podataka

Da bi se definisalo alternativno ime postojeem tipu podatka koristi se kljuna rije


typedef. Sintaksa je sljedea
typdef ime_tipa novo_ime_tipa;

Tako, npr. moemo definisati tip "cijeli_broj" i dvije promjenljive tog "novog" tipa na
sljedei nain
typedef int cijeli_broj;
cijeli_broj a;
cijeli_broj b;

Dodjela vrijednosti promjenljivima

Da bi se dodjelila neka vrijednost nekoj promjenljivoj, koristi se operator =. Naredba


za dodjelu ima oblik
ime_promjenljive = vrijednost;

Ukoliko se radi o cijelim brojevima (tip int), vrijednosti se mogu zadati u tri
razliita brojna sistema. Ukoliko vrijednost poinje cifrom koja nije nula, broj se tretira kao
dekadni. Ukoliko poinje nulom, broj se tretira kao oktalni a ukoliko poinje sa 0x ili 0X broj
se tretira kao heksadekadni.
int x, y, z;
x = 123; // dekadni broj
y = 0123; // oktalni broj
z = 0x123; // heksadekadni broj

Ukoliko se radi o realnim brojevima, vrijednosti se mogu pisati samo u dekadnom


sistemu, a za decimalni zarez se koristi taka (.). Vrijednosti se mogu i pisati u obliku oEk
(oek), gdje je o osnova a k eksponent.
float x, y, z;
x = 123;
y = 123.456;
z = 123E+2; // broj 12300

Ukoliko je promjenljiva tipa char, vrijednost mora biti jedan karakter, ogranien
jednostrukim navodnim znacima ('). Specijalni karakteri (\n, \t..) se tretiraju kao jedan
karakter, iako se, praktino sastoje od dva karaktera. Tip char je ustvari cjelobrojna
vrijednost ASCII koda karaktera.
char a, b, c, d;
a = 'a';
b = '\n';
c = '1';
d = '.';
Mogue je u istoj naredbi definisati promjenljivu i dodjeliti joj vrijednost
int x = 5;
float y = 1.2, z = 234e-1;
char c1, c2 = 'a';

tampanje vrijednosti promjenljivih

Na poetku je bilo rijei o funkciji printf koja tampa proizvoljan niz karaktera na
standardni izlaz. Ista funkcija se koristi za tampanje vrijednosti uz odreene izmjene.
Funkcija ima sljedei oblik
printf("niz_znakova_za_ispis", ime_promjenljive1, ...);

Niz znakova za ispis predstavlja niz karaktera, pri emu se znakom % pokazuje mjesto
gdje treba da se upiu vrijednosti promjenljivih koje se nalaze iza niza znakova za ispis.
Nakon znaka % ide odgovarajue slovo, koje zavisi od tipa promjenljive:
%d cijelobrojni tip, zapisan u dekadnom sistemu,
%o cijelobrojni tip, zapisan u oktalnom sistemu,
%x cijelobrojni tip, zapisan u heksadekadnom sistemu,
%f realni tip (float i double)
%c karakter.

Primjeri naredbi za tampanje


printf(%d, x); // tampa promjenljive x u dekadnom sistemu
printf(%f %f, a, b); // tampa realnih promjenljivih a i b
printf(%d %o %x, x, x, x); /* tampa promjenljive x u
dekadnom, oktalnom i heksadekadnom sistemu */
printf(%c, c); // tampa vrijednosti promjenljive c tipa char

printf(Vrijednost promjenljive x je %d, x);

Opseg vaenja promjenljivih


U jednom bloku naredbi nije dozvoljeno definisanje vie promjenljivih istog imena.
Tako, na primjer, kompajliranje sljedeeg koda bi javilo greku
{
int x;
char x;
}
dok je sljedei kod ispravan
{
int i = 1;
{
int i = 2;
printf("Unutrasnje i = %d\n", i);
}
printf("Spoljasnje i = %d\n", i);
}
i njegovo izvravanje daje rezultat
Unutrasnje i = 2
Spoljasnje i = 1

Veliina memorijskog prostora za promjenljive

Nakon svake definicije promjenljive, alocira se potrebna memorija za njeno uvanje.


Veliina te memorije zavisi od tipa promjenljive, ali i sistema na kojem se program izvrava.
U C-u je ugraen operator sizeof koji odreuje veliinu promjenljive ili tipa u bajtovima.
Ukoliko se eli odtampati veliina (u bajtovima) tipa int, kod bi izgledao
int velicina = sizeof(int);
printf(%d, velicina);

Vrijednost se moe odtampati i bez uvoenja nove promjenljive, izraunavanjem


veliine direktno u argumentu funkcije printf.
printf(%d, sizeof(int));

Cjelobrojne promjenljive se zapisuju u formatu potpunog komplementa, realne u


zapisu IEEE754 a karakteri u ASCII kodu. Za vie informacija o ovim zapisima pogledati [?].

Primjer 1. Napisati program koji definie dvije cjelobrojne promjenljive, dodjeljuje


im vrijednost i tampa njihov zbir.

Rjeenje 1
#include <stdio.h>
#include <stdlib.h>

int main()
{
int a, b;
a = 5;
b = 7;
int c = a+b;
printf("Zbir je %d\n", c);
return 0;
}
Rjeenje 2
#include <stdio.h>
#include <stdlib.h>

int main()
{
int a = 5, b = 7;
printf("Zbir je %d\n", a+b);
return 0;
}

Primjer 2. Napisati program koji tampa veliine memorijskog prostora za osnovne


tipove podataka.

Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
printf("int: %d\n", sizeof(int));
printf("short: %d\n", sizeof(short));
printf("long: %d\n", sizeof(long));
printf("unsigned: %d\n", sizeof(unsigned));
printf("float: %d\n", sizeof(float));
printf("double: %d\n", sizeof(double));
printf("char: %d\n", sizeof(char));
return 0;
}

Izlaz ovog programa nam daje odgovor na veliinu osnovnih tipova u C-u
int: 4
short: 2
long: 4
unsigned: 4
float: 4
double: 8
char: 1

Konstante

Slino promjenljivima, konstante su objekti koji imaju svoje ime ali im se vrijednost
ne moe mijenjati tokom izvrenja programa. Za definisanje konstanti koristi se kljuna rije
const ispred tipa i imena konstante.
const int x = 5;

Drugi nain definisanja konstante je korienje preprocesorske direktive #define.


Ona ima oblik
#define ime_konstante vrijednost_konstante
Ova preprocesorska direktiva se pie na poetku programa, ispod direktiva
#include a ove konstante se nazivaju simbolike konstante.

Uitavanje vrijednosti promjenljivih sa tastature

Jasno je da loe rjeenje da se vrijednosti promjenljivim dodjeljuju u samom kodu.


Takav nain dodjele zahtjeva promjenu koda svaki put kada se mijenja vrijednost
promjenljivih. Osnovna ideja je da se korisniku omogui dodjela vrijednosti promjenljivima u
toku izvravanja programa. Za tu svrhu se koristi funkcija scanf oblika
scanf(format, lista_promjenljivih,...);

format i lista_promjenljivih predstavljaju argumente sline kao kod


funkcije printf. Prvi je niz karaktera koji u sebi sadri oznaku tipa koji se unosi - % i
odgovarajue slovo koje je identino kao kod funkcije printf. to se tie liste
promjenljivih, razlika u odnosu na funkcije printf je ta da se ispred svake promjenljive
mora napisati karakter &. Zato ba on, bie objanjeno u dijelu kada se bude govorilo o
pokazivaima i referencama.
Unos vrijednosti cjelobrojne promjenljive x i karaktera c se vri na sljedei nain
scanf(%d, &x);
scanf(%c, &c);

Primjer 3. Napisati program koji sa tastature uitava dva cijela broja i tampa njihov
zbir.

Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
int a, b;
scanf("%d", &a);
scanf("%d", &b);
printf("Zbir je %d\n", a+b);
return 0;
}

Operatori
Aritmetiki operatori

Aritmetiki operatori, kao to im samo ime govori, slue za izvravanje aritmetikih


operacija. Do sada je ve korien operator sabiranja, a postoji ukupno pet aritmetikih
operatora:
+ sabiranje,
- oduzimane,
* mnoenje,
/ dijeljenje,
% ostatak pri djeljenju (samo za cijele brojeve).
Svi ovi operatori su binarni, to znai da imaju dva argumenta i njihova svrha je jasna,
osim moda posljednjeg. Npr. izraz 8%3 daje ostatak pri dijeljenju broja 8 sa brojem 3, tj.
daje vrijednost 2.

Primjer 4. Napisati program koji sa tastature ita dva cijela broja i ispisuje njihov zbir,
razliku, proizvod i kolinik.

Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
int a, b;
scanf("%d", &a);
scanf("%d", &b);
printf("a + b = %d\n", a+b);
printf("a - b = %d\n", a-b);
printf("a * b = %d\n", a*b);
printf("a / b = %f\n", (float)a/b);
printf("a % b = %d\n", a%b);
return 0;
}
Svi redovi u kodu su poznati i jasni, osim
printf("a / b = %f\n", (float)a/b);
odnosno, izraza (float)a/b. U ovom izrazu se koristi tzv. cast operator.

Cast operator

U programskom jeziku C postoji ugraena automatska konverzija tipova. To znai da


je mogue nekoj promjenljivoj dodijeliti vrijednost nekog drugog tipa. Npr. kod
int a = 5;
float b = a;
je ispravan, iako se u drugom redu promjenljivoj b tipa float dodjeljuje vrijednost
promjenljive a koja je tipa int. Tu dolazi do automatske konverzije tipa int u float. U
ovom sluaju ne postoji nikakav gubitak podataka, dok bi, recimo konverzija tipa float u
int dovela do gubitka podataka, i to cifara iza decimalnog zareza.
Mogua je i eksplicitna konverzija tipova, kada neki izraz elimo konvertovati u
odgovarajui tip. Takva konverzije je mogua korienjem unarnog operatora koji se naziva
cast a ima oblik
(tip) izraz;
Izraz (float)a/b je upravo konvarzija rezultata a/b u tip float. To je
neophodno jer su a i b tipa int i da nema eksplicitne konverzije, i rezultat a/b bi bio tipa
int i ne bi bio taan.

Relacijski i logiki operatori

Ovi operatori imaju isti smisao kao i u matematici. U ovu grupu operatora spadaju
> vee,
< manje,
<= vee ili jednako,
>= manje ili jednako,
== jednako (dvostruko jednako - jednostruko jednako je operator dodjele),
!= razliito (! je znak negacije).
Osim ovih, u ovu grupu spadaju i logiki vezinici.
&& logiko I,
|| logiko ILI.
Rezultat primjene ovih operatora je logika vrijednost koja moe biti tana ili netana,
npr.
(x>4) && (x%2 == 0)
Ovaj izraz ispituje da li je x paran broj vei od 4.
O prioritetima operatora ovdje nee biti govora, za detaljnije pogledati [?].

Bitovni operatori

Bitovni operatori su operatori koji manipuliu sa cjelobronim tipovima podataka, na


nivou bitova. Za potpuno razumjevanje rada ovih operatora potrebno je poznavati nain
zapisivanja cijelih brojeva u potpunom komplementu[?]. Postoji 6 operatora za rad s bitovima
& binarno I,
| binarno ILI,
^ binarno ekskluzivno ILI,
<< lijevi pomak (lijevi shift),
>> desni pomak (desni shift),
~ unarna negacija.

Primjer 5. Izraunati vrijednosti izraza 24&12, 17|12, 8^11, 17>>2, 21<<3,


~11.

Rjeenje.
Zbog zapisa, veliina podataka e biti ograniena na 8 bitova.
00011000 = 24 00010001 = 17 00001000 = 8
00001100 = 12 00001100 = 12 00001011 = 11
&00001000 = 8 | 00011101 = 29 ^ 00000011 = 12

17 >> 2 = 00010001 >> 2 = (00)000100|01 = 00000100 = 4


21 << 3 = 00010101 << 3 = 000|10101(000) = 10101000 = 168
~11 = ~(00001011) = 11110100 = -12

Primjer 6. Napisati program koji izraunava vrijednosti izraza iz primjera 5.

Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
printf("24&12 = %d\n", 24&12);
printf("17|12 = %d\n", 17|12);
printf("8^11 = %d\n", 8^11);
printf("17>>2 = %d\n", 17>>2);
printf("21<<3 = %d\n", 21<<3);
printf("~11 = %d\n", ~11);
return 0;
}

Operatori uveavanja i umanjivanja

U C-u postoje dva uobiajena operatora uveavanja i umanjivanja za jedan. To su


operatori ++ i --. Operator inkrementiranja ++ uveava svoj operand za jedan, dok operator
dekrementiranja -- umanjuje svoj operand za jedan.
To znai da izrazi a=a+1 i a++, odnosno a=a-1 i a-- imaju isto znaenje.
Oba operatora se mogu koristiti i kao prefiksni (++a) i kao sufiksni (a++). Razlika je
to se u prefiksnom korienju vrijednost promjenljive a uvea prije njenog korienja, a u
sufiksnom obrnuto.

Operatori i izrazi dodjeljivanja vrijednosti

Slino kao kod operatora inkrementiranja i dekrementiranja, postoje skraeni zapisi i


za operatore u kojima je promjenljiva na lijevoj strani a neki od operatora na desnoj, kakav je
i=i+2. Skraeni zapis za ovaj izraz je i+=2.
Ovakvi skraeni zapisi su mogui za operatore +, -, *, /, %, <<, >>, &, ^ i |.
Kontrola toka
ifelse izraz

Uslovni if izraz ima sljedei oblik


if(uslov)
naredba1;
else
naredba2;

uslov mora biti neki logiki izraz. U sluaju da je uslov taan, izvrava se
naredba1 a u suprotnom naredba2. if izraz se moe pojaviti i bez else izraza. Ako je
potrebno da se izvri vie naredbi, tada je potrebno da se stave u blok, ogranien sa vitiastim
zagradama

if(uslov)
{
naredba1_1;
naredba1_2;
naredba1_3;
...
}
else
{
naredba2_1;
naredba2_2;
naredba2_3;
...
}

Primjer 7. Ispraviti rjeenje primjera 4. tako da iskljuuje mogunost dijeljenja nulom.

Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
int a, b;
scanf("%d", &a);
scanf("%d", &b);
printf("a + b = %d\n", a+b);
printf("a - b = %d\n", a-b);
printf("a * b = %d\n", a*b);
if(b != 0)
printf("a / b = %f\n", (float)a/b);
else
printf("Greska! Dijeljenje nulom\n");
printf("a % b = %d\n", a%b);
return 0;
}

ifelse ifelse izraz

ifelse naredba ima samo dvije grane kada je uslov ispunjen i kada nije.
Meutim nekada je potrebno ispitati vie uslova i u zavisnosti od njihovih vrijednosti
izvravati odreene naredbe. U tim sluajevima se koristi if-else if-else izraz, koji e
biti prikazan na sljedeem primjeru.

Primjer 8. Napisati program koji ispituje da li je uneseni broj pozitivan, negativan ili je
jednak nuli.

Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
int x;
scanf("%d", &x);
if(x > 0)
printf("Broj je pozitivan\n");
else if(x < 0)
printf("Broj je negativan\n");
else
printf("Broj je jednak nuli\n");
return 0;
}

Operator ?

U programskom jeziku C postoji operator ? i to je jedini ternani operator, tj. ima tri
operanda. Izgled operatora je
(logicki_izraz) ? vrijednost1 : vrijednost2
Ovaj operatoj provjerava istinitost logikog izraza i u sluaju njegove tane vrijednosti
vraa vrijednost1 a u suprotnom vraa vrijednost2.

switch

Ovaj izraz je slian izrazu ifelse ifelse i provjerava da li izraz odgovara


nekoj od konstantnih cjelobrojnih vrijednosti (ili karaktera). switch izraz ima sljedei oblik
switch(izraz)
{
case vrijednost1:
naredbe1
break;
case vrijednost2:
naredbe2
break;
...
default:
naredbeN;
}

U sluaju da izraz ima vrijednost vrijednost1, tada se izvravaju naredbe1, u


sluaju da ima vrijednost2 tada se izvravaju naredbe2, a u sluaju da nema nijednu
od ponuenih vrijednosti tada se izvravaju naredbeN.

Primjer 9. Napisati program koji provjerava da li je uneseni karakter razmak, taka ili
neki neki drugi znak.

#include <stdio.h>
#include <stdlib.h>

int main()
{
char c;
scanf("%c", &c);
switch(c)
{
case ' ':
printf("Uneseni karakter je razmak\n");
break;
case '.':
printf("Uneseni karakter je tacka\n");
break;
default:
printf("Uneseni karakter nije ni tacka ni
razmak\n");
}

return 0;
}

Petlje
for

Primjer 8. Napisati program koji tampa prvih 5 prirodnih brojeva.

Rjeenje
U ovom programu je potrebno izvriti 5 slinih naredbi, tj. 5 poziva funkcije printf
sa razliitim argumentima. U sluajevima kada se trebaju izvriti sline naredbe koriste se
petlje. Jedan od naina da se rijei ovaj zadatak je sljedei
#include <stdio.h>
#include <stdlib.h>

int main()
{
int i;
for(i=1; i<=5; i=i+1)
printf("%d\n", i);
return 0;
}

Ovdje je korien izraz for koji ima sljedei oblik


for(inicijalizacija; uslov; korak)
inicijalizacija izraz u kojem se promjenljivima dodjeljuju poetne
vrijednosti,
uslov logiki izraz koji uslovljava izvrenje for petlje petlja se izvrava sve dok
ovaj logiki izraz taan,
korak izraz u kojem se vri uveavanje brojaa. U prethodnom primjeru, u svakom
se izvravanju for petlje vrijednost brojaa i poveava za jedan.

Sva tri izraza u for petlji su opcioni, to znai da ne moraju postojati. Izraz
for( ; ; )
je ispravan izraz i predstavlja beskonanu petlju.

Treba primjetiti da iza linije u kojoj se nalazi for petlja ne nalazi karakter ;. To je
zato to je kraj komande tek u sljedeem redu. Kao i kod if naredbe, ukoliko se for petlja
odnosi na vie komandi, potrebno ih je ograniiti vitiastim zagradama {}.

while

while petlja ima iste osobine kao for petlja i sve to se moe uraditi preko for
petlje moe i preko while i obrnuto. while petlja ima sljedei oblik
while(uslov)
{
komande...
}
Slino kao for petlja, samo to nema dijela za inicijalizaciju i korak, ve se
inicijalizacija mora mora obaviti prije a korak u samoj petlji.

Primjer 9. Prethodni zadatak rijeiti korienjem while petlje.

Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
int i=1;
while(i<=5)
{
printf("%d\n", i);
i++;
}
return 0;
}

do-while

Kao i while petlja, samo to se kod do-while petlje prvo izvravaju naredbe pa se
onda provjerava uslov. do-while petlja ima sljedei oblik
do
{
komande...
} while(uslov);

Za razliku od while petlje, komande u do-while petlji e se izvriti bar jednom.

Primjer 10. Prethodni zadatak rijeiti korienjem do-while petlje.

Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
int i=1;
do
{
printf("%d\n", i);
i++;
} while(i<=5);
return 0;
}

break i continue

Nekada postoji potreba izlaska iz petlje prije potpunog ispunjenja potrebnog uslova za
izlazak. Za to se koristi naredba break.

Primjer 11. Odtampati prvi broj (ako postoji) koji je manji od 500 a djeljiv sa brojevima 3, 4,
5 i 7.

Rjeenje
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i;
for(i=1; i<=500; i++)
if(i%3 == 0 && i%4 == 0 && i%5 == 0 && i%7 == 0)
{
printf("%d\n", i);
break;
}
return 0;
}

Naredba continue je slina naredbi break, a njen poziv otpoinje sljedeu


iteraciju petlje.

Primjer 12. Odtampati sve brojeve manje od 20 koji nisu djeljivi sa brojem 3.

#include <stdio.h>
#include <stdlib.h>

int main()
{
int i;
for(i=1; i<=20; i++)
{
if(i%3 == 0)
continue;
printf("%d\n", i);
}
return 0;
}

goto i labele

C ima mogunost rada sa labelama, ali se ne preporuuje njihovo korienje osim u


sluajevima kada je potrebno izai iz vie petlji odjednom, kao u sljedeem primjeru

for(...)
for(...)
{
if(...)
goto kraj;
}
...

kraj:
...
Rad sa karakterima

Kao to je ve pomenuto, u programskom jeziku C tip char je ustvari cjelobrojna


vrijednost ASCII koda datog karaktera. To znai da se char moe tampati i kao karakter i
kao cijeli broj
char c = 'A';
printf("%d\n", c); // tampa ASCII kod karaktera
printf("%c\n", c); // tampa izgled karaktera

Primjer 13. Napisati program koji tampa ASCII tabelu karaktera.

Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
char i;
for(i=1; i<127; i++)
printf("%d %c\t", i, i);

return 0;
}

Ako se pogleda ASCII tabela, vidi se da, recimo karakter 'A' ima vrijednost 65,
karakter 'B' vrijednost 66, karakter 'a' ima vrijednost 97, karakter 'b' ima vrijednost
98 itd. Tako da vrijednost izraza 'A' + 10 daje vrijednost 75 odnosno karakter 'K'.

Znakovni ulaz i izlaz

U standardnoj biblioteci, osim funkcija printf i scanf postoje funkcije koje slue
za ulaz odnosno izlaz znakovnog tipa podataka. To su funkcije getchar i putchar.
Funkcija getchar() ita jedan karakter sa standardnog ulaza (tastature) i kao
rezultat vraa njegovu ASCII vrijednost, npr. kod
char c = getchar();
ita jedan karakter sa tastature i njegovu vrijednost dodjeljuje promjenljivoj c.

Funkcija putchar(c) tampa vrijednost karaktera c na standardnom izlazu, npr


putchar(c);

Kod unosa teksta, kao indikator za kraj unosa se koristi znak za kraj datoteke, koji se
oznaava EOF (end of file). Ako je u pitanju unos sa tastature, znak EOF se dobija
kombinacijom tastera ctrl i z.
Primjer 14. Napisati program koji sa tastature ita karaktera sve dok se ne unese
karakter EOF i ispisuje ih na ekranu.

Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
char c;
int i;
while(c!=EOF)
{
c = getchar();
putchar(c);
}
return 0;
}
Rijeeni zadaci

Zadatak 1. Napisati program koji za uneseno n tampa sumu prvih n prirodnih brojeva i n!

Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
int n, i, suma=0, fakt=1;
scanf("%d", &n);
for(i=1; i<=n; i++)
suma += i;
printf("Suma prvih %d je %d\n", n, suma);

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


fakt *= i;
printf("%d! = %d\n", n, fakt);

return 0;
}

Zadatak 2. Odtampati sve djelioce unesenog broja.

Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
int n, i;
scanf("%d", &n);

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


if (n%i == 0)
printf("%d ", i);

return 0;
}

Zadatak 3. Odtampati sve savrene brojeve manje od 10000 (broj je savren ako je jednak
zbiru svojih djelilaca, osim sebe samog).
Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
int n, i,suma;

for(n=1; n<10000; n++)


{
suma = 0;
for (i=1; i<n; i++)
if (n%i == 0)
suma+=i;

if (suma==n)
printf("broj %d je savrsen\n", n);
}

return 0;
}

Zadatak 4. Napisati program koji za uneseni prirodni broj tampa zbir njegovih cifara.

Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
int n, suma = 0;
scanf("%d", &n);
while(n > 0)
{
suma += n % 10; // sa n%10 se dobija posljednja cifra
n /= 10;
}
printf("%d", suma);
return 0;
}

Zadatak 5. Napisati program koji za uneseni prirodan broj ispisuje broj ije su cifre u
obrnutom redoslijedu.
Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
int n, obrnuti = 0;
scanf("%d", &n);
while(n > 0)
{
obrnuti = obrnuti*10 + n % 10;
n /= 10;
}
printf("%d", obrnuti);
return 0;
}

Zadatak 6. Izraunati kvadratni korjen datog broja Njutnovom metodom sa zadatom tanosti.

Rjeenje
1 x
Njutnova formula glasi yi +1 = y i + , gdje je x broj za koji se trai korjen, a
2 yi
poetna iteracija y 0 = x + 1 . Za rjeavanje ovog zadatka potrebna je funkcija koja rauna
apsolutnu vrijednost datog broja. To je funkcija abs(float) koja je definisana u datoteci
math.h1.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
float x, y, z, eps;
scanf("Unesite broj i tacnost: ");
scanf("%f", &x);
scanf("%f", &eps);
y = x+1;
do
{
z = y;
y = .5 * (y + x/y);
} while(abs(z-y) > eps);
printf("Korjen iz %.2f je %f", x, y);
return 0;
}

1
Pregled naajnijih funkcija standardne biblioteke je prikazano u dodatku A
Zadatak 7. Napisati program koji simulira rad kalkulatora sa osnovnim operacijama +, -, *,
/. Izraz se unosi u obliku operator operand1 operand2.

Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
float op1,op2;
char op;
scanf ("%c", &op);
scanf ("%f", &op1);
scanf ("%f", &op2);
printf("izraz: %.2f %c %.2f\n",op1,op,op2);

switch(op)
{
case '+':
printf("vrijednost: %.2f\n", op1 + op2);
break;
case '-':
printf("vrijednost: %.2f\n", op1 - op2);
break;
case '*':
printf("vrijednost: %.2f\n", op1 * op2);
break;
case '/':
if (op2 == 0)
printf("Greska! Dijeljenje nulom\n");
else
printf("vrijednost: %.2f\n", op1 / op2);
break;
default:
printf("Greska! Pogresan operator\n");
}
return 0;
}

Zadatak 8. Napisati program koji pronalazi rjeenja kvadratne jednaine ax 2 + bx + c = 0

Rjeenje
Za rjeavanje ovog zadatka potrebna je funkcija koja rauna kvadratni korjen datog
broja, a to je funkcija sqrt(float) koja je definisana u datoteci math.h
Mogua su tri sluaja jednaina nema realna rjeenja (D<0), ima dvostruko rjeenje
(D=0) i ima dva razliita rjeenja (D>0).
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
float a, b, c;
scanf("%f", &a);
scanf("%f", &b);
scanf("%f", &c);
printf("Jednacina: %.2f*x^2 + %.2f*x + %.2f\n", a, b, c);

float D = b*b - 4*a*c;


if(D < 0)
printf("Rjesenja nisu realna\n");
else if(D == 0)
{
float x = -b/(2*a);
printf("Jednacina ima jedno dvostruko rjesenje x =
%.2f\n", x);
}
else
{
float x1 = (-b + sqrt(D))/(2*a);
float x2 = (-b - sqrt(D))/(2*a);
printf("Rjesenja su x1=%.2f, x2=%.2f\n", x1, x2);
}

return 0;
}

Zadatak 9. Napisati program koji ispituje da li se dvije prave y=a1x+b1 i y=a2x+b2 sijeku.

Rjeenje
Mogua su tri sluaja prave su paralelne, prave se poklapaju ili se sijeku u jednoj
taki.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
float a1,a2,b1,b2;
scanf ("%f",&a1);
scanf ("%f",&b1);
scanf ("%f",&a2);
scanf ("%f",&b2);
printf("y =%5.2fx + %5.2f\n",a1,b1);
printf("y =%5.2fx + %5.2f\n",a2,b2);
if (a1 == a2 && b1== b2)
printf ("prave se poklapaju\n");
else if (a1 == a2 && b1 != b2 )
printf ("prave su paralelne\n");
else
{
float x=(b2-b1)/(a1-a2);
float y=a1*x+b1;
printf ("prave se sijeku u tacki
(%5.2f,%5.2f)\n",x,y);
}

return 0;
}

Zadatak 10. Podaci o krugovima se sastoje od koordinata centra i duine poluprenika.


Napisati program koji ispituje u kom su poloaju dati krugovi.

Rjeenje
Mogua su tri sluaja. Da se krugovi ne sijeku (udaljenost meu centrima je vea od
zbira poluprenika), da se dodiruju (udaljenost meu centrima je jednaka zbiru poluprenika)
i da se dijeku (udaljenost meu centrima je manja od zbira poluprenika).

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
int x1,x2,y1,y2,r1,r2;
scanf ("%d", &x1);
scanf ("%d", &y1);
scanf ("%d", &r1);
scanf ("%d", &x2);
scanf ("%d", &y2);
scanf ("%d", &r2);

float d = sqrt((x2-x1)*(x2-x1)+ (y2-y1)*(y2-y1));

if (d>r1+r2)
printf ("kruznice se ne sijeku");
else if (d<r1+r2)
printf ("kruznice se sijeku");
else
printf ("kruznice se dodiruju");

return 0;
}
Zadatak 11. Napisati program koji za uneseno n tampa romb ija je duina stranice n, kao na
slici (na slici n=2)
*
* *
*

Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
int n, i, j, k;
scanf("%d", &n);
for(i=1; i<=n; i++)
{
for(k=n; k>i; k--)
printf(" ");
for(j=0; j<i; j++)
printf("* ");
printf("\n");
}
for(i=n-1; i>0; i--)
{
for(k=n; k>i; k--)
printf(" ");
for(j=0; j<i; j++)
printf("* ");
printf("\n");
}

return 0;
}

Zadatak 12. Napisati program koji tampa sve trocifrene brojeve kod kojih je druga cifra za
dva vea od prve a trea za jedan vea od druge.

Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
int i, j, k;
for(i=1; i<=9; i++)
for(j=3; j<=9; j++)
for(k=4; k<=9; k++)
if(j == i+2 && k == j+1)
printf("%d%d%d\n", i, j, k);
return 0;
}

Zadatak 13. Napisati program koji uneseno mali slovo pretvara u veliko.

Rjeenje
Ideja: vrijednost izmeu malog slova i njemu odgovarajueg velikoj je konstantna za
sva slova.
#include <stdio.h>
#include <stdlib.h>

int main()
{
char maliC;
scanf("%c", &maliC);

char velikiC = maliC - ('a' - 'A');


printf("%c", velikiC);

return 0;
}

Zadatak 14. Napisati program koji za uneseni karakter provjerava da li je malo slovo, veliko
slovo, cifra ili neki drugi karakter.

Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
char c;
scanf("%c", &c);

if(c >= 'A' && c <= 'Z')


printf("Uneseni karakter je veliko slovo\n");
else if(c >= 'a' && c <= 'z')
printf("Uneseni karakter je malo slovo\n");
else if(c >= '0' && c <= '9')
printf("Uneseni karakter je cifra\n");
else
printf("Uneseni karakter nije slovo ni cifra\n");

return 0;
}

Zadatak 15. Napisati program koji sa tastature ita karaktera sve dok se ne unese karakter
EOF i broji unesenie samoglasnike i suglasnike.
Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
char c;
int i, suglasnici=0, samoglasnici=0;
while(c!=EOF)
{
c = getchar();
if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
if(c == 'a' || c == 'e' || c == 'i' || c == 'o'
|| c == 'u' || c == 'A' || c == 'E' || c == 'I' || c == 'O' ||
c == 'U')
samoglasnici++;
else
suglasnici++;
}
printf("Samoglasnika: %d, suglasnika: %d", samoglasnici,
suglasnici);

return 0;
}
Zadaci za vjebu

2
n
k 2
1. Napisati program koji za uneseno n izraunava sumu
k =1

2. Napisati program koji za zadatu tanost eps izraunava broj e =
1
k = 0 k!
m
3. Napisati program koji za unesene n i m rauna broj n (bez korienja funkcije
pow) .
n
4. Napisati program koji za uneseno n i m (n > m) rauna
m
5. Napisati program koji uitava n, zatim uitava n brojeva i izraunava njihovu
aritmetiku sredinu.
6. Napisati program koji odreuje za koliko procenata je porasla cijena C1 ako ona
sad iznosi C2.
7. Napisati program koji izraunava sumu i proizvod dva kompleksna broja x1+iy1 i
x2+iy2
8. Napisati program koji rauna zbir, razliku i proizvod razlomaka a/b i c/d.
9. Napisati program koji za uneseno n izraunava n-ti stepen kompleksnog broja,
korienjem De Moavrove formule3
10. Napisati program koji uitava brojeve m i n i pravi Dekartov proizvod skupova
{1,2,...,n} i {1,2,...,m}.
11. Napisati program koji za uneseno n ispisuje trougao kao na slici (na slici n=3)
1
22
333
12. Napisati program koji za uneseno n tampa kvadrate brojeva 1, 2, ... , n-1.
13. Napisati program koji za uneseno x izraunava vrijednost y po formuli
1
,x > 0
x
y = 0, x = 0
1
- , x < 0
x
14. Napisati program koji izraunava aritmetiku sredinu cifara datog broja.
15. Napisati program koji u datom etverocifrenom broju izraunava razliku izmeu
prve i poslednje cifre.
16. Napisati program koji za unesene n i m (m<n) izraunava sumu posljednjih m
cifara broja n.
17. Napisati program koji za unesene n i m uitava n brojeva i izraunava aritmetiku
sredinu brojeva koji su vei od m.
18. Napisati program koji uitava broj m i zatim uitava brojeve sve dok im suma ne
pree m.
19. Napisati program koji za n unijeti cijelih brojeva rauna zbir negativnih.
20. Napisati program koji za uneseno n rauna n-ti lan Fibonaijevog niza
21. Napisati program koji za unesena tri cijela broja ispisuje najvei.

2
Za funkciju stepenovanja pogledati dodatak A
3
Za funkcije sin i cos pogledati dodatak A
22. Napisati program koji za unesena tri cijela broja ispituje da li ine Pitagorinu
trojku.
23. *Napisati program koji nalazi NZD za dva broja korienjem Euklidovog
algoritma.
1 1
24. *Napisati program koji za uneseno n izraunava 1 + + ... +
2 n
25. Napisati program koji za uneseno n uitava n brojeva i odreuje najvei i najmanji
meu njima.
26. Napisati program koji rjeava jednainu ax+b=0.
27. Napisati program koji ispituje da li je prava y=kx+n tangenta parabole y2=2px
(vrijednosti k, n i p se unose sa tastature).
28. Napisati program koji ispituje da li se sijeku prava y=kx+n i krunica x2+y2=r2
(vrijednosti k, n i r se unose sa tastature).
29. Napisati program koji ispituje da li je vrijednost polinoma 2x3+x2-2x+1 pozitivna
ili negativna u taki n koja se unosi sa tastature.
30. Napisati program koji ispituje da li je uneseni broj Armstrongov. Amrstrongov
broj je jednak zbiru kubova svojih cifara.
31. Napisati program koji ispituje da li je uneseni broj Nivenov. Nivenov broj je broj
koji je djeljiv sumom svojih cifara.
32. Napisati program koji uitava broj b i osnovu o < 10 i zatim ispisuje broj o u
dekadnom brojnom sistemu.
33. Napisati program koji izraunava povrinu pravougaonika ije su stranice
paralelne koordinatnim osama, a zada je preko dijagonalnih tjemena (x1, y1) i (x2,
y2)
34. Napisati program koji ispituje da li take A(x1, y1), B(x2, y2), C(x3, y3) i D(x4, y4)
ine paralelogram ABCD.
35. Napisati program koji tampa kvadrant u kojem se nalazi taka (x1, y1).
36. Napisati program koji uitava vrijednost n (n < 180) i ispituje da li je ugao od n
stepeni otar, prav ili tup.
37. Napisati program koji rauna maksimim za unesena etiri broja.
38. Napisati program koji ispituje da li tri unesene dui mogu da naprave trougao
(koristiti nejednakost trougla).
39. Napisati program koji rauna povrinu trougla datog preko svojih tjemena (x1, y1),
(x2, y2), (x3, y3) (koristiti Heronov obrazac).
40. Napisati program koji provjerava da li je uneseni karakter slovo, taka ili razmak.
41. Napisati program koji za uneseni broj n ispisuje n-ti dan u nedjelji (npr. za 1 se
ispisuje Ponedjeljak.
42. Napisati program koji provjerava da li tri cijela broja koja se unose sa tastature h,
m i s ine ispravno vrijeme (h:m:s).
43. Napisati program koji provjerava da li tri cijela broja koja se unose sa tastature d,
m i g ine ispravan datum (d.m.g).
44. Napisati program koji za uneseni broj n ispisuje n-ti mjesec u godini.
45. Napisati program koji provjerava da li je unesena godina prestupna.
46. Napisati program koji ispisuje ocjenu koju je student dobio na ispitu na osnovu
osvojenih bodova (5 od 0 do 50, 6 od 51 do 60 itd).
Funkcije

Do sada je bilo rijei o funkcijama. Pominjane su funkcije za ulaz/izlaz (printf,


scanf, getchar, putchar...), matematike funkcije (fabs, sqrt, sin, cos...) itd.
Mogue je da korisnici sami definiu funkcije koje su im neophodne za izvravanje programa.
Deklaracija funkcije izgleda
tip_funkcije ime_funkcije(lista_argumenata...)

tip_funkcije predstavlja tip rezultata kojeg funkcija vraa. To moe biti bilo koji
od standarnih ili korisniki definisanih tipova programskog jezika C ili tip void
ime_funkcije je proizvoljan identifikator funkcije za koje vae ista pravila kao i
za davanje imena promjenljivima
lista_argumenata je niz od nijednog, jednog ili vie argumenata funkcije. Svaki
argument mora imati svoje ime i tip. U sluaju da postoji vie argumenata svaki novi
je potrebno odvojiti zarezom od prethodnog.

Primjeri deklaracija funkcija


int funkcija();
float funkcija1(int x);
void funkcija2(intx, char y, float z);

Osim deklaracije funkcije potrebno je definisati ta ta funkcija radi. Definicija funkcije


se pie u bloku naredbi ogranienim {}. Npr. za prvu funkciju bi to izgledalo
int funkcija()
{
Tijelo funkcije
...
}

Deklaracija funkcije mora biti iznad main() funkcije, dok definicija moe biti i
ispod, ali u prostijim programima je lake napisati definiciju funkcije odmah iza deklaracije.

U definiciji funkcije mora postojati (osim eventualno u funkcijama tipa void)


naredba koja prekida izvravanje funkcije i vraa njenu vrijednost. To je naredba return.

Funkcija za sabiranje dva realna broja bi izgledala


float saberi(float x, float y)
{
float rezultat = x+y;
return rezultat;
}

Pozivu ove funkcije je potrebno kao argumente zadati dva realna broja a ona kao
rezultat vraa njihov zbir
float rezultat = saberi(2.4, 3.5);

U sluaju da je funkcija tipa void, ona ne vraa nikakv rezultat. Ukoliko je potrebno
izai iz te funkcije, moe se pozvati komanda return bez vrijednosti iza nje.
Bitno je napomenuti da kod ovakvog definisanja funkcija argumenti ne mijenjaju
svoje vrijednosti nakon poziva funkcije, tj. njihova vrijednost ostaje nepromjenjena. U
sljedeem programu vrijednost promjenljive n ostaje nepromjenjena u nakon pozova funkcije
f, iako se u funkciji vrijednost argumenta uveava za jedan.
void f(int n)
{
n++;
}

int main()
{
int n = 1;
f(n);
printf("%d\n", n);
return 0;
}

Primjer 15. Napisati funkciju koja izraunava faktorijel datog broja.

Rjeenje
int faktorijel(unsigned int broj)
{
int i, fakt=1;

for(i=1; i<=broj; i++)


fakt *= i;
return fakt;
}

Primjer 16. Napisati funkciju koja ispituje da li je dati broj prost.

Rjeenje
int prost(unsigned int broj)
{
int i;
for(i=2; i<broj; i++)
if(broj % i == 0)
return 0;

return 1;
}

Obzirom da u C-u ne postoji logiki tip, ukoliko se radi o nekoj funkciji koja treba da
vrati vrijednost tano/netano, kao to je sluaj sa ovom, tada je ona tipa int i vraa 1 ako
treba da vrati tano a 0 ako treba da vrati netano.
Iz tog razloga ova funkcija je tipa int i u zavisnosti od (ne)ispunjenja uslova vraa se
vrijednost 0 ili vrijednost 1.
Primjer 17. Napisati program koji tampa sve proste brojeve manje od 1000.

Rjeenje
Ovdje emo iskoristiti funkciju iz prethodnog primjera. Za svaki broj od 1000
pozivanjem funkcije iz prethodnog primjera emo ispitati da li je prost.

#include <stdio.h>
#include <stdlib.h>

int prost(unsigned int broj)


{
int i;
for(i=2; i<broj; i++)
if(broj % i == 0)
return 0;
return 1;
}

int main()
{
int i;
for(i=1; i<=1000; i++)
if(prost(i) == 1)
printf("%d\t", i);

return 0;
}

Primjer 18. Napisati program koji ispisuje sve brojeve manje od 500 koji su Nivenovi i
Armstrongovi.

Rjeenje
Kod zadataka koji su kompleksniji, najlake je problem razbiti na podprobleme i za
svaki od njih uvesti funkciju. Ovdje e biti uvedene etiri funkcije za raunanje sume cifara
datog broja, za raunanje sume kubova cifara datog broja i funkcija koje ispituju da li je broj
Nivenov odnosno Armstrongov.

#include <stdio.h>
#include <stdlib.h>

int sumacifara(int n)
{ //
int suma = 0 ;
for ( ; n>0; n/=10)
suma += n%10;
return suma;
}

int sumakubova(int n)
{
int suma = 0 ;
for ( ; n>0; n/=10)
suma += pow(n%10, 3);
return suma;
}

int nivenov(int n)
{
if(n % sumacifara(n) == 0)
return 1;
return 0;
}

int armstrongov(int n)
{
if(n == sumakubova(n))
return 1;
return 0;
}

int main()
{
int i;
for(i=1; i<=500; i++)
if(armstrongov(i) && nivenov(i))
printf("%d\t", i);

return 0;
}

Rekurzija

U programskom jeziku C mogue je pisati rekurzivne funkcije. To znai da funkcija


moe pozivati samu sebe, bilo direktno ili indirektno. Kod rekurzivnih funkcija bitno je
obezbijediti izlaz iz rekurzije, tj. uslov u kojem se rekurzija prekida.

Primjer 19. Napisati rekurzivnu funkciju koja izraunava faktorijel datog broja.

Rjeenje
Funkcija faktorijela se rekurzivno moe predstaviti kao f(n) = n*f(n-1) sa
poetnim uslovom f(1) = 1.
int faktorijel(unsigned int n)
{
if(n == 1)
return 1;
return n*faktorijel(n-1);
}

Primjer 20. Napisati rekurzivnu funkciju koja tampa prvih n prirodnih brojeva u
obrnutom redoslijedu.

Rjeenje
void stampa(unsigned int n)
{
if(n == 0)
return;
printf("%d\n", n);
stampa(n-1);
}

Nizovi

Deklaracija niza u programskom jeziku C ima sljedei oblik


tip_niza ime_niza[maksimalna_veliina]
Sljedee deklaracije nizova su ispravne
int niz_cijelih_brojeva[10];
int niz_realnih_brojeva[5];
char niz_karaktera_brojeva[15];
Elementima niza se pristupa preko njihovih indeksa koji se navode u uglastim
zagradama iza imena niza, s tim to prvi element niza ima indeks nula. Tako, prvom elementu
niza iz prolog primjera emo dodijeliti neki vrijednost na sljedei nain
niz_cijelih_brojeva[0] = vrijednost;
Inicijalizacija elemenata niza moe se izvriti pri samoj deklaraciji niza tako to se
nakon deklaracije niza u uglu vitiastih zagrada navedu vrijednosti elementa niz. Izraz
int niz[5] = {1, 2, 3, 4, 5};
deklarie niz od pet elemenata ije su poetne vrijednosti 1, 2, 3, 4 i 5, odnosno dobija se niz
promjenljivih
int niz[0] = 1;
int niz[1] = 2;
int niz[2] = 3;
int niz[3] = 4;
int niz[4] = 5;

U radu s nizovima, ondnosno njihovim indeksima prirodno se namee korienje for


petlji, pri emu se brojai petlje koriste za indekse u nizu. U takvim petljama brojai idu od 0
do duzina_niza1.
Sljedei primjer pokazuje kako deklarisati niz od 10 cijelih brojeva, uitati mu
vrijednosti elemenata sa tastature i odtampati ih
int niz[10], i;
for(i=0; i<10; i++)
scanf(%d, &niz[i]);
for(i=0; i<10; i++)
printf(%d , niz[i]);

U C se mogu na slian nain definisati i viedimenzioni nizovi, samo je potrebno pri


deklaraciji niza navesti veliine svake od dimenzija. Dovodimenzioni niz cijelih brojeva
dimenzija 2x2 bi definisali na sljedei nain
int dvo_niz[2][2];
Indeksi viedimenzionalnih nizova imaju iste osobine kao i kod jednodimenzionih.
Primjer 21. Uitati niz sa tastature i izraunati aritmetiku sredinu elemenata, i minimalni i
maksimalni element.

Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
int a[10], i, suma=0, min, maks;
for(i=0; i<10; i++)
scanf("%d", &a[i]);
min = maks = a[0];

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


{
suma += a[i];
min = (a[i] < min) ? a[i] : min;
maks = (a[i] > maks) ? a[i] : maks;
}

printf("Artimeticka sredina je %.2f\n", (float)suma/10);


printf("Minimalni element %d\n", min);
printf("Maksimalni element %d\n", maks);

return 0;
}

Primjer 22. Uitati niz sa tastature dvije matrice 3x3 pronai njihov zbir i odtampati ga na
ekranu.

Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
int mat1[3][3], mat2[3][3], zbir[3][3];

int i, j;
printf("Unesite elemente matrice 1\n");
for(i=0; i<3; i++)
for(j=0; j<3; j++)
scanf("%d", &mat1[i][j]);

printf("Unesite elemente matrice 2\n");


for(i=0; i<3; i++)
for(j=0; j<3; j++)
scanf("%d", &mat2[i][j]);
printf("Zbir matrica je\n");
for(i=0; i<3; i++)
{
for(j=0; j<3; j++)
printf("%d ", mat1[i][j] + mat2[i][j]);
printf("\n");
}

return 0;
}

Primjer 23. Napisati rekurzivnu i iterativnu funkciju koja izraunava n-ti lan (n < 20)
Fibonaijevog niza.

Rjeenje:
n-ti lan Fibonaijevog niza zadat je rekurentnom relacijom fn = fn-1 + fn-2.

int fib_rek(int n)
{
if(n > 20)
{
printf("Greska! n mora biti manje od 20\n");
return -1;
}
if(n == 1 || n == 2)
return 1;
return fib_rek(n-1) + fib_rek(n-2);
}

int fib_iter(int n)
{
if(n > 20)
{
printf("Greska! n mora biti manje od 20\n");
return -1;
}

int niz[20], i;
niz[0] = niz[1] = 1;
for(i=2; i<20; i++)
niz[i] = niz[i-1] + niz[i-2];
return niz[n];
}

Nizovi karaktera

U programskom jeziku C, nizovi karaktera se ponaaju drugaije od nizova brojeva.


Na kraju svakog niza karaktera se automatski dodaje karakter '\0' koji predstavlja kraj niza.
Tako niz karaktera abcd u C se predstavlja kao [a,b,c,d,\0].
Ova injenica nam omoguava da koristimo nizove karaktera, ak i kada ne znamo
njihovu duinu, kretanjem kroz niz sve dok se ne doe do karaktera '\0'.
Osim toga, niz karaktera se moe unijeti i tampati u cjelini, a ne element po element
kao nizovi brojeva. Konverzija za niz karaktera je %s.
Sljedei primjer pokazuje kako sa tastaure moemo uitati niz karaktera i odrediti mu
duinu
char niz[10];
scanf(%s, &niz);
int i, duzina = 0;
for(i=0; niz[i] != '\0'; i++)
duzina++;
printf(%d, duzina);

Nizovi kao argumenti funkcija

Ukoliko elimo da definiemo funkciju koja za argument ima niz, niz kao argument
funkcije moemo prenijeti na jedan od sljedeih naina
tip_funkcije f1(tip_niza ime_niza[]);
tip_funkcije f2(tip_niza* ime_niza);

Funkcija koja rauna duinu niza karaktera izgledala bi


int duzina(char niz[])
{
int i, duzina = 0;
for(i=0; niz[i] != '\0'; i++)
duzina++;
return duzina;
}

Kada je niz argument funkcije, vrijednost elemenata se moe promjeniti u funkciji, za


razliku od argumenata osnovnih tipova. Nakon izvravanja sljedeeg programa vrijednost
elemenata niza postaju 2 i 3.
void f(int a[])
{
a[0]++;
a[1]++;
}

int main()
{
int niz[2] = {1, 2};
f(niz);
printf("%d\n%d", niz[0], niz[1]);
return 0;
}

Razlozi za ovo bie objanjeni kada se bude govorilo o pokazivaima.

Primjer 24. Napisati funkciju koja dopisuje jedan niz karaktera na drugi.
Rjeenje
#include <stdio.h>
#include <stdlib.h>

void prepis(char prvi[], char drugi[], char rezultat[])


{
int i, j=0;
for(i=0; prvi[i] != '\0'; i++)
rezultat[j++] = prvi[i];
for(i=0; drugi[i] != '\0'; i++)
rezultat[j++] = drugi[i];
rezultat[j] = '\0';
}

int main()
{
char prvi[10], drugi[10], rezultat[20];
scanf("%s", &prvi);
scanf("%s", &drugi);
prepis(prvi, drugi, rezultat);
printf("%s", rezultat);
return 0;
}
Rijeeni zadaci

Zadatak 16. Napisati funkciju koja provjerava da li dat niz karaktera predstavlja ispravan
hekdasecimalni broj u obliku #broj i funkciju koja pretvara dati niz karaktera koji predstavlja
heksadekadni broj u dekadni.
Rjeenje:
Radi lakeg rjeavanja ovog zadatka, uveemo pomone funkcije koje ispituju da li
dati karakter predstavlja cifru, slovo izmeu a i f i slovo izmeu A i F. U rjeenju se koristi
funkcija strlen(char s[]) biblioteke string.h4 koja vraa duzinu niza karaktera s i
koja je analogna funkciji int duzina(char s[]).
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

int cifra(char c)
{
if(c >= '0' && c <= '9')
return 1;
return 0;
}

int slovoa_f(char c)
{
if(c >= 'a' && c <= 'f')
return 1;
return 0;
}

int slovoA_F(char c)
{
if(c >= 'A' && c <= 'F')
return 1;
return 0;
}

int ispravan(char hex[])


{
if(hex[0] != '#')
return 0;
int i;
for(i=1; hex[i] != '\0'; i++)
if(cifra(hex[i]) == 0 && slovoa_f(hex[i]) == 0 &&
slovoA_F(hex[i]) == 0)
return 0;
return 1;
}

4
Opis datoteke string.h dat je u dodatku A
int hexudek(char hex[])
{
int i, rez = 0;
int d = strlen(hex);
for(i=1; hex[i] != '\0'; i++)
{
if(cifra(hex[i]) == 1)
rez += (hex[i] - '0') * (int) pow(16, d-i-1);
else if(slovoa_f(hex[i]) == 1)
rez += (hex[i] - 'a' + 10) *
(int) pow(16, d-i-1);
else
rez += (hex[i] - 'A' + 10) *
(int) pow(16, d-i-1);
}
return rez;
}

int main()
{
char niz[10];
scanf("%s", &niz);
if(ispravan(niz) == 0)
printf("Broj nije ispravan\n");
else
printf("%s = %d", niz, hexudek(niz));
return 0;
}

Zadatak 17. Sa tasture se unosi niz karaktera oblika <broj1><operator><broj2>, pri


emu su broj1 i broj2 dvocifreni brojevi a operator +, -, * ili /. Napisati program koji uitava
niz karaktera, ispituje da li je ispravan izraz i izraunava vrijednost unesenog izraza.

Rjeenje
U programu emo koristiti ugraenu funkciju isdigit(char c) koja je definisana
u datoteci ctype.h5 koja ispituje da li je dati karakter cifra i analogna je funkciji
cifra(char c) iz prethodnoh zadatka.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int ispravan(char izraz[])


{
if(!isdigit(izraz[0]) || !isdigit(izraz[1])
|| !isdigit(izraz[3]) || !isdigit(izraz[4]))
return 0;
if(izraz[2] != '+' && izraz[2] != '-'
&& izraz[2] != '*' && izraz[2] != '/')
return 0;

5
Opis datoteke ctype.h dat je u dodatku A
return 1;
}

int main()
{
char izraz[5];
scanf("%s", &izraz);
if(ispravan(izraz) == 0)
{
printf("Izraz nije ispravan!\n");
return -1;
}

int broj1 = (izraz[0] - '0') * 10 + (izraz[1] - '0');


int broj2 = (izraz[3] - '0') * 10 + (izraz[4] - '0');

printf("%s = ", izraz);


switch(izraz[2])
{
case '+':
printf("%d", broj1 + broj2);
break;
case '-':
printf("%d", broj1 - broj2);
break;
case '*':
printf("%d", broj1 * broj2);
break;
case '/':
printf("%.2f", (double)broj1 / broj2);
break;
}
return 0;
}

Zadatak 18. Napisati program koji sa tastature uitava polinom (stepen < 10 i koeficijente),
tampa ga na ekran, uitava vrijednost v i tampati vrijednost polinoma u taki v.
Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
float koef[11];
int stepen, i;
printf("Unesite stepen polinoma:");
scanf("%d", &stepen);

for(i=0; i<=stepen; i++)


{
printf("Unesite koeficijent a[%d]: ", i);
scanf("%f", &koef[i]);
}

printf("P(x) = ");
for(i=0; i<=stepen; i++)
printf("%.2f*x^%d + ", koef[i], i);
printf("\n");

float v, vr = 0;
printf("Unesite vrijednost v: ");
scanf("%f", &v);

for(i=0; i<=stepen; i++)


vr += koef[i] * pow(v,i);

printf("P(%.2f) = %.2f\n", v, vr);

return 0;
}

Zadaci za vjebu

1. Sa ulaza se unosi osnova <= 10 i broj. Provjeriti da li je taj broj ispravan broj za datu
osnovu i ako jeste izraunati njegovu vrijednost u osnovi 10.
2. Sa ulaza se unosi broj u osnovi deset i osnova <= 10. Odtampati vrijednost datog
broja u datoj osnovi
3. Napisati program koji sa tastature ita broj n (najvie 100), niz od n cijelih brojeva i
vrijednost n a zatim provjerava da li je v u nizu, na kom je mjestu i koliko u nizu ima
brojeva manjih od n
4. Za dati niz realnih brojeva ispitati da li je testerast (niz je testarast ako vai
x1<x2>x3<x4>... ili x1>x2<x3>x4<...)
5. Napisati program koji ispisuje sve proste brojeve manje od 10000 koristei
Eratostenovo sito.
6. Zadatu matricu ispisati spiralno, u smjeru kazaljke na satu, poevi od A11.*
7. Napisati program koji uitava dvije realne kvadratne matrice (prvo dimenzije pa
elemente, najvie 10x10) i ispisuje njihov proizvod.
8. Napisati program koji uitava dva polinoma i ispiruje nihov proizvod.
9. Napirati program koji izraunava n-ti stepen datog polinoma.
10. Napirati program koji izraunava n-ti izvod datog polinoma.
11. Napisati rekurzivnu funkciju koja ispisuje romb ija je duina stranice n, kao na slici
(na slici n=2)
*
* *
*
12. Napisati program koji sa tastature uitava broj n i tampa sve permutacije tih n
elemenata.
13. Napisati funkciju koja dati realni broj prevodi u odgovarajui niz karaktera, npr.
123.123 u 123,123
14. Napisati funkcije koje ispituju da li su sva niza karaktera jednaka i da li su jednaki na
prvih n mjesta (ne koristiti datoteku string.h)
15. Napisati funkciju koja koja dati niz karaktera razbija na dva niza karaktera date
duine.
16. Data su dva niza karaktera. Ispitati da li je drugi niz karaktera podniz prvog.
17. Data su dva niza karaktera. Napisati program koji pravi novi niz karaktera koji se
sastoji od karaktera koji se pojavljuju u oba niza.
18. Data su dva niza karaktera. Napisati program koji pravi novi niz karaktera koji se
sastoji od karaktera koji se pojavljuju u prvom, a ne pojavljuju se u drugom nizu.
19. Napisati program koji vri ifrovanje ulaznog teksta: svako slovo sa ulaza zamjenjuje
se sa slovom koje je na tri mjesta udaljeno od njega u abecedi.
20. Napisati funkciju koja na osnovu date rei formira ifru koja se dobija tako to se
svako slovo u rijei zameni sa naredna tri slova koja su mu susedna u abecedi. Na
primer, re "tamo" treba da bude zamenjena sa "uvwbcdnoppqr".
21. Napisati program koji u datom tekstu uklanja sve viestruke razmake.
22. Napisati program koji iz datog teksta tampa rijei (neprekidne nizove karaktera).
Svaka rije treba da se nalazi u novom redu.
23. Napisati funkcije koje dati niz slova pretvara u mala, odnosno u velika slova.
24. Napisati program koji radi s dvodimenzionim matricama koristei nizove (uitavanje,
tampa i sabiranje)
25. Napisati funkciju koja provjerava da li je data matrica simetrina
26. Napisati funkciju koja provjerava da li je data matrica magini kvadrat (magini
kvadrat je kadratna matrica kod koje je suma brojeva u svakom redu i koloni jednaka)
27.
a. Napisati funkciju koja za datu matricu rauna transponovanu matricu
b. Napisati funkciju koja provjerava da li je data matrica jedinina
28. Za datu matricu ispitati da li je ortogonalna (matrica je ortogonalna ako vai
AAT = E)
Pokazivai

Osnovni tipovi koji su do sada korieni sadre vrijednosti promjenljivih. Pokazivai


su promjenljive koja sadre memorijsku adresu promjenljive. Za razumjevanje principa rada
pokazivaa potrebno je poznavati osnovne principe organizacije memorije raunara.
Memorija je, ustvari, niz lokacija u koje moemo upisivati vrijednosti ili iz kojih moemo
itati vrijednosti. Svaka lokacija predstavlja prostor u koji se moe zapisati jedan bajt (osam
binarnih cifara) ima svoju adresu. Tako se tip char moe zapisati na jednu memorijsku
lokaciju, int na etiri i double na osam lokacija (o veliini osnovnih tipova je bilo govora
u dijelu o tipovima podataka).
Da bi se dobila adresa nekog objekta koristi se unarni operator &.

Sljedei kod prikazuje kako odtampati adresu neke promjenljive x.


int x;
printf("Adresa promjenljive: %x", &x);

U principu, vrijednost same adrese nas i ne zanima, ali pomou ovoga moemo
provjeriti jednu vanu injenicu vezanu za alokaciju memorije za nizove.

Primjer 24. Napisati program koji tampa memorijske lokacije lanova niza od 10 cijelih
brojeva.

Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
int niz[10], i;
for(i=0; i<5; i++)
printf("Adresa clana %d: %d\n", i, &niz[i]);

return 0;
}

Rezultat izvravanja ovog programa izgleda ovako6:


Adresa clana 0: 2293520
Adresa clana 1: 2293524
Adresa clana 2: 2293528
Adresa clana 3: 2293532
Adresa clana 4: 2293536
Adresa clana 5: 2293540
Adresa clana 6: 2293544
Adresa clana 7: 2293548
Adresa clana 8: 2293552
Adresa clana 9: 2293556

Ovo nam pokazuje da se elementi niza u memoriji nalaze na susjednim lokacijama, tj.
drugi element se nalazi iza lokacije na kojoj se nalazi prvi itd.
6
Rezultat ovog programa nee biti uvijek isti, mogue je da se razlikuju vrijednosti adresa.
Ako u kodu pokuamo odtampati vrijednost promjenljive niz, tj.
printf("Vrijednost promjenljive \"niz\": %d\n", niz);
dobiemo
Vrijednost promjenljive "niz": 2293520
Ovim je pokazano, da je promjenljiva koja oznaava niz, ustvari pokaziva koji
pokazuje na prvi element niza.

Da bi se definisala promjenljiva koja sadri pokaziva na neki tip, potrebno je iza tipa
promjenljive dodati znak *. Tako dobijamo etiri tipa pokazivaa, na svaki od osnovnih
tipova:
char*
int*
float*
double*

Potrebno je napomenuti da ako u jednom redu definiemo vie pokazivaa, potrebno je


ispred imena svakog od njih dodati *. Tako, npr. kod
int *a, *b;
definie dva pokazivaa tipa int, a kod
int *a, b;
definie promjenljivu a koja je pokaziva tipa int i promjenljivu b koja je tipa int.

Kada definiemo pokaziva (promjenljivu pokazivakog tipa) u nju moemo smjestiti


adresu neke promjenljive. Sljedei kod pokazuje kako se pokazivau p moe dodjeliti adresa
objekta x.
int x = 5;
int* p = &x;

Izrazom p=&x promjenljivoj p se dodjeljuje adresa promjenljive x i ukoliko


pristupamo promjenljivoj p mi ustvari pristupamo adresi na kojoj se nalazi promjenljiva x,
odnosno adresi gdje se nalazi njena vrijednost. Ukoliko elimo da pristupimo vrijednosti na
koju pokazuje pokaziva p, moramo koristiti unarni operator dereferenciranja *. U kodu
printf("%d\n", p);
printf("%d\n", *p);
prvi red tampa adresu na koju p pokazuje, a drugi red tampa vrijednost koja se
nalazi u memoriji na koju pokazuje p (tj. vrijednost 5).

Nakon ovoga, postaje jasno ta je karakter & ispred imena promjenljive u funkciji
scanf - funkcija za argument ima adresu promjenljive a ne njenu vrijednost. Razlozi za to
bie detaljno objanjeni u dijelu u kojem e se govoriti o pokazivaima kao argumentima
funkcija.

Dinamika alokacija memorije


Kada se pokaziva definie, on ne sadri adresu lokacije kojoj moemo pristupiti i da
bi radili sa njim neophodno je dodjeliti mu adresu neke lokacije. Pokazivau moe biti
dodjeljena adresa neke ve postojee promjenljive ili mu se moe dodjeliti adresa neke
lokacije u memoriji. Da bi mogli pristupati toj adresi neophodno je alocirati memoriju na toj
lokaciji, tj. "rei" operativnom sistemu tu memorijsku lokacija dodjeljuje programu koji se
izvrava. Ova operacija se naziva dinamika alokacija memorije, i ona se vri u vrijeme
izvravanja programa. Kod korienja "nepokazivakih" tipova se ne vri dinamika
alokacija, tj. automatski se alocira potreban prostor za memorisanje promjenljivih i nakon
zavretka izvravanja program se taj prostor oslobaa.
Da bi se memorija dinamiki alocirala, koristi se funkcija
void *malloc(size_t size);

Ova funkcija ima jedan argument, a to je veliina memorijskog prostora koji se


alocira, u bajtima. Rezultat funkcije je pokaziva na alociranu memoriju ili NULL pokaziva
ukoliko je alokacija nemogua. Obzirom da se ovom funkcijom alokacija vri za sve tipove
pokazivaa, njen rezultat je tipa void*, pa ja potrebno da se uradi cast-ovanje rezultata u
potreban tip.
Definisanje pokazivaa na cijeli broj i alokacija memorije na koju on pokazuje
izgledae
int *p = (int*) malloc(sizeof(int));

Obzirom da veliina tipova nije ista na svim sistemima, dobra praksa je da se pri
alokaciji koristi operator sizeof o kojem je ranije bilo govora.
U optem sluaju, definisanje pokazivaa i alokacija memorije za proizvoljan tip
podataka izgleda
TIP *p = (TIP*) malloc(sizeof(TIP));
pri emu TIP moe biti bilo koji od osnovnih ili koriniki-definisanih tipova.

Nakon izvrenja programa koji koristi dinamiku alokaciju memorije ta memorija se


ne oslobaa automatski. Da bi program bio potpuno ispravan, potrebno je tu memoriju runo
osloboditi. Ukoliko se to ne uini, program e raditi bez greaka, ali e nakon izvravanja
programa dinamiki alocirana memorija ostati zauzeta. Ovaj problem je poznat kao "curenje
memorije" ili ne engleskom "memory leak". Da bi se dealocirala memorija na koju pokazuje
neki pokaziva koristi se funkcija
void free(void *pointer);
pri emi je pointer pokaziva na memorijsku alokaciju koju elimo dealocirati.
Funkcije malloc i free se uvijek trebaju pojavljivati u paru, tj. koliko imamo fukncija
malloc, moramo imati toliko i funkcija free.

Primjer 25. Napisati program koji sa tastature ita dva broja i ispisuje njihov zbir na ekranu.
Memoriju za brojeve alocirati dinamiki.
Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
int *p1, *p2;
p1 = (int*) malloc(sizeof(int));
p2 = (int*) malloc(sizeof(int));
scanf("%d", p1);
scanf("%d", p2);
printf("%d + %d = %d", *p1, *p2, *p1 + *p2);
free(p1);
free(p2);
return 0;
}
U ovom primjeru u funkciji scanf ne postoji karakter & ispred imena promjenljivih,
jer su promjenljive p1 i p2 pokazivai, pa oni u sebi sadre adrese - a to je upravo ono ta
funkcija scanf oekuje za argument.

Nizovi i pokazivai

Dosadanje korienje pokazivaa i nije bilo tako efektno, tj. za svaku promjenljivu
smo morali definisati pokaziva i alocirati potrebnu memoriju a to se automatski deava kada
ne koristimo pokazivae. Pokazivai pokazuju svoju snagu i svrsishodnost korienja kada je
potrebno alocirati memoriju za nizove. Do sada je svaki niz imao ogranienu veliinu - pri
definisanju niza smo navodili maksimalnu veliinu koliku niz moe da ima. Ovo je loe iz dva
razloga. Prvi od njih je postojanje mogunosti da je korisniku potreban vei niz, a drugi
razlog je da postoje memorijske lokacije koje alociramo bez potrebe. Nrp. ako definiemo niz
od maksimalno 100 elemenata, naem korisniku moe zatrebati niz od vie elemenata, ili pak,
korisniku je moda potreban niz od samo nekoliko elemenata pri emu svi ostali elementi
zazumaju memoriju bez potrebe.
Pokazivai omoguavaju i dinamiku alokaciju nizova, tanije omoguavaju alokaciju
memorije za proizvoljan niz u toku izvravanja programa. Osobina niza da mu se svi elementi
nalaze jedan za drugim i da je ime promjenljive koja oznaava niz ustvari pokaziva na prvi
element omoguava vrlo laku alokaciju memorije za nizove.
Dovoljno je definisati pokaziva odreenog tipa i alocirati onoliko memorije koliko je
potrebno za smjetanje cijelog niza. U optem sluaju, alokacija memorije za niz od n
elemenata niza proizvoljnog tipa izgleda
TIP* niz = (TIP*) malloc(sizeof(TIP)*n);
pri emu TIP moe biti bilo koji od osnovnih ili definisanih tipova.

Sa ovako definisanim nizom se radi kao i sa "obinim" nizovima - mogue je


indeksiranje lanova niza pri emu prvi element niza ima indeks nula.

Primjer 26. Napisati program koji sa tastature ita proizvoljan broj n, zatim definie niz od n
cijelih, uitava elemente niza i pronalazi im aritmetiku sredinu.
Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
int n, i;
scanf("%d", &n);
int *niz = (int*) malloc(sizeof(int)*n);
for(i=0; i<n; i++)
scanf("%d", &niz[i]);

double zbir=0.0;
for(i=0; i<n; i++)
zbir += niz[i];

printf("%3.2f", zbir/n);
free(niz);
return 0;
}

lanovima niza je mogue pristupati i drugaiji nain - preko operatora +. Ukoliko


imamo neku promjenljivu p koja je pokazivakog tipa i na nju primjenimo operator + sa
argumentom n, kao rezultat dobiemo memorijsku lokaciju koja se nalazi na
(n*veliina_tipa) mjesta od mjesta na koje pokazuje pokaziva p. Prostije, ako imamo
pokaziva koji pokazuje na neki niz, elementi niza se nalaze na memorijskim lokacijama
niz+1, niz+2, ...
a vrijednosti elemenata niza na lokacijama
*(niz+1), *(niz+2), ...

Primjer 27. Napisati program koji sa tastature ita proizvoljan broj n, zatim definie niz od n
realnih brojeva, uitava i tampa elemente niza pristupajui im preko njihovih adresa.
Rjeenje
#include <stdio.h>
#include <stdlib.h>

int main()
{
int n, i;
scanf("%d", &n);
float *niz = (float*) malloc(sizeof(float)*n);
for(i=0; i<n; i++)
scanf("%f", niz+i);

for(i=0; i<n; i++)


printf("%.2f ", *(niz+i));

free(niz);
return 0;
}

Pokazivai kao argumenti funkcija

Do sada je bilo govora da funkcija scanf za argument zahtjeva adresu promjenljive,


a ne njeno ime (odnosno vrijednost), dok recimo funkcija printf zahtjeva ime (vrijednost) a
ne adresu. Koja je razlika?

Funkciji se argumenti mogu proslijediti na dva naina - po vrijednosti i po adresi.

U prvom sluaju se kao argument funkcije zadaje ime promjenljive a funkciji se


prosljeuje vrijednost te promjenljive. Funkcija radi sa vrijednosu promjenljive i ne postoji
nain da izmjeni stvarnu vrijednost promjenljive. Sljedei kod
int x = 5;
f(x);
se tumai kao:
- promjenljiva x ima vrijednost 5
- funkcija f se poziva sa argumentom 5, tj. f(5) i daje rezultat.
Pri prenosu adrumenata po adresi funkciji se prosljeuje adresa promjenljive i funkcija
barata sa adresom na kojoj se nalazi promjenljiva. U tom sluaju stvarna vrijednost
promjenljive se moe promjeniti nakon izvravanja funkcije.

Sljedei primjer to najbolje ilustruje:


#include <stdio.h>
#include <stdlib.h>

void fv(int x)
{
x++;
}

void fa(int* x)
{
(*x)++;
}

int main()
{
int x = 5;

fv(x);
printf("%d\n", x);

fa(&x);
printf("%d\n", x);

return 0;
}
Funkcija fv za argument dobija vrijednost promjenljive x, tj. broj 5 i ona ustvari samo
tu vrijednost poveava za jedan dok vrijednost promjenljive x ostaje 5 i nakon izvravanja
funkcije fv. Funkcija fa za argument dobija adresu promjenljive x i komandom (*x)++ se
poveava za jedan vrijednost koja se nalazi na lokaciji x, tj. mijenja se stvarna vrijednost
promjenljive x.
Poziv prve funkcije ne mjenja vrijednost promjenljive x, a poziv druge je mijenja.
Rezultat izvravanja ovog programa je
5
6

Ova osobina se naziva boni efekat ili side-effect jer omoguava mjenjanje vrijednosti
promjenljivih kroz pozivanje funkcija. Ova osobina omoguava da funkcija vrati vie od
jedne vrijednosti. Potrebno je u glavnom programu definisati promjenljive, proslijediti
funkciji njihove adrese i nakon izvravanja programa u tim promjenljivima dobijamo
odreene rezultate.

Primjer 27. Napisati funkciju koja za dati niz nalazi minimum, maksimum i aritmetiku
sredinu.
Rjeenje
#include <stdio.h>
#include <stdlib.h>

void mmas(int* niz, int d, int* min, int* max, float* as)
{
int i, suma = 0;
int mi=niz[0], ma=niz[0];
for(i=0; i<d; i++)
{
if(mi > niz[i])
mi = niz[i];
if(ma < niz[i])
ma = niz[i];
suma += niz[i];
}
*as = (float) suma / d;
*min = mi;
*max = ma;
}

int main()
{
int niz[5] = {4, 2, 8, 6, 1};
int min, max;
float as;

mmas(niz, 5, &min, &max, &as);

printf("Minimalni elemenat: %d\n", min);


printf("Maksimalni elemenat: %d\n", max);
printf("Aritmeticka sredina: %f\n", as);

return 0;
}

Kada su opisivani nizovi kao argumenti funkcija reeno je da kada je niz argument
funkcije, vrijednost elemenata niza se moe promjeniti u funkciji. Sada je jasno i zato - ime
niza je, ustvari, pokaziva na prvi elemenat niza, pa je argument ustvari adresa prvog
elementa a to omoguava i mijenjanje vrijednosti niza.

Strukture

Struktura je skup jedne ili vie promjenljivih koje su grupisane radi lake manipulacije
sa njima. Sintaksa definisanja strukture je
struct ime_strukture
{
tip1 ime1;
tip2 ime2;
...
};
Definicijom strukture se, ustvari, definie tip imena struct ime_strukture i u
programu se mogu praviti promjenljive ovoga tipa. Svaka promjenljiva ovog tipa se sastoji od
skupa promjenljivih koje su definisane u strukturi. Tim promjenljivim se pristupa preko
operatora taka (.) i sa njima se radi kao sa obinim promjenljivim.

Primjer 28. Napisati strukturu za uvanje podataka o takama u ravni, funkciju za tampanje
take i funkciju za izraunavanje udaljenosti izmeu dvije take.
Rjeenje
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

struct tacka
{
float x;
float y;
};

double udaljenost(struct tacka t1, struct tacka t2)


{
return sqrt((t1.x-t2.x)*(t1.x-t2.x) + (t1.y-t2.y)*(t1.y-
t2.y));
}

void odstampaj(struct tacka t)


{
printf("(%.2f, %.2f)\n", t.x, t.y);
}

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


{
struct tacka t1, t2;

scanf("%f", &t1.x);
scanf("%f", &t1.y);
scanf("%f", &t2.x);
scanf("%f", &t2.y);

odstampaj(t1);
odstampaj(t2);

printf("d = %.2f\n", udaljenost(t1, t2));

system("PAUSE");
return 0;
}

U praksi se najee definie tip koji predstavlja tip strukture, da se ne bi svaki put
morala navoditi kljuna rije struct. Tako bi npr. u prolom primjeru mogli definisati tip
Tacka pomou kljune rijei typedef:
typedef struct tacka Tacka;
i onda bi koristili tip Tacka umjesto struct tacka. Korienjem ovog novog
naziva tipa moemo definisati dvije promjenljive tipa taka na sljedei nain:
Tacka t1, t2;

Jo krai zapis je da se pri definiciji strukture definie i tip, u prolom primjeru bi to


izgledalo
typedef struct tacka
{
float x;
float y;
} Tacka;

Pokazivai na strukture

Kao i na svaki drugi tip, moemo definisati pokaziva i na strukturu. Sintaksa je


identina kao sa ostalim tipovima, jedina razlika je u nainu pristupanja lanovima strukture.
Kod obinih promjenljivih operator pristupa lanovima je taka (.) a kod pokazivaa
lanovima se pristupa preko operatora minus vee (->). Korienje strukture iz prolog
primjera preko pokazivaa izgledalo bi
Tacka *p = (Tacka*) malloc(sizeof(Tacka));
p->x = 10.0;
p->y = 5.0;
odstampaj(*p);
free(p);

Zadaci za vjebu
Algoritmi sortiranja i pretrage
Binarna pretraga
Primjer 29. Napisati funkciju koja pretrauje dati neopadajui niz pomou algoritma binarne
pretrage
Rjeenje
int BinPretraga(int* niz, int d, int x)
{ // Iterativna binarna pretraga
int lijevi = 0;
int desni = d-1;
while(lijevi <= desni)
{
int m = (lijevi+desni) / 2;
if(x == niz[m])
return m;
else if(x < niz[m])
desni = m-1;
else
lijevi = m+1;
}
return -1;
}

int BinPretragaR(int* niz, int lijevi, int desni, int x)


{ // Rekurzivna binarna pretraga
if(lijevi >= desni)
return -1;
int m = (lijevi + desni) / 2;
if(x < niz[m])
return BinPretragaR(niz, lijevi, m, x);
else if(x > niz[m])
return BinPretragaR(niz, m, desni, x);
else
return m;
}

Bubble sort
Primjer 30. Napisati funkciju koja dati niz sortira pomou algoritma Bubble sort
Rjeenje
void SortBubble(int* niz, int duzina)
{
int i, j;
for(i=0; i<duzina; i++)
for(j=i; j<duzina; j++)
if(niz[i] > niz[j])
{
int x = niz[i];
niz[i] = niz[j];
niz[j] = x;
}
}

Sortiranje umetanjem
Primjer 31. Napisati funkciju koja dati niz sortira pomou algoritma sortiranja umetanjem.
Rjeenje
void SortUmetanje(int* a, int d)
{ // Osnovna varijanta sortiranja umetanjem
int i, j;
for(i=1; i<d; i++)
{
int x = a[i];
j = i-1;
while(j>0 && x > a[j])
{
a[j+1] = a[j];
j = j-1;
}
a[j+1] = x;
}
}

void SortBinUmetanje(int* a, int d)


{ // Poboljsana varijanta, pri cemu se binarnom pretraga
pronalazi mjesto na koje se umece elemenat
int i, j;
for(i=1; i<d; i++)
{
int x = a[i];
int lijevi = 0;
int desni = i-1;
while(lijevi <= desni)
{
int m = (lijevi+desni) / 2;
if(x < a[m])
desni = m-1;
else
lijevi = m+1;
}
for(j=i-1; j>=lijevi; j--)
a[j+1] = a[j];
a[lijevi] = x;
}
}

Sortiranje izborom
Primjer 32. Napisati funkciju koja dati niz sortira pomou algoritma sortiranja izborom.
Rjeenje
void SortIzborom(int* a, int d)
{ // Varijanta 1
int i, j, indexNajmanjeg;
for(i=0; i<d-1; i++)
{
indexNajmanjeg = i;
int najmanji = a[i];
for(j=i+1; j<d; j++)
{

if(a[j] < najmanji)


{
indexNajmanjeg = j;
najmanji = a[j];
}
}
a[indexNajmanjeg] = a[i];
a[i] = najmanji;
}
}

void SortIzborom1(int* a, int d)


{ // Varijanta 2
int i, j, indexNajmanjeg;
for(i=0; i<d-1; i++)
{
indexNajmanjeg = i;
for(j=i+1; j<d; j++)
if(a[j] < a[indexNajmanjeg])
indexNajmanjeg = j;
int najmanji = a[indexNajmanjeg];
a[indexNajmanjeg] = a[i];
a[i] = najmanji;
}
}

QuickSort
Primjer 33. Napisati funkciju koja dati niz sortira pomou algoritma QuickSort.
Rjeenje
void swap(int v[], int i, int j)
{
int temp;
temp = v[i];
v[i] = v[j];
v[j] = temp;
}

void QuickSort(int v[], int lijevi, int desni)


{
int i, zadnji;

if (lijevi >= desni)


return;
swap(v, lijevi, (lijevi + desni)/2);
zadnji = lijevi;
for (i = lijevi + 1; i <= desni; i++)
if (v[i] < v[lijevi])
swap(v, ++zadnji, i);
swap(v, lijevi, zadnji);
QuickSort(v, lijevi, zadnji-1);
QuickSort(v, zadnji+1, desni);
}

MergeSort
Primjer 34. Napisati funkciju koja dati niz sortira pomou algoritma MergeSort.
Rjeenje
void Merge(int* a, int d1, int d2)
{ // Funkcija koja spaja dva podniza tako da se dobije
sortirani niz
int* novi = (int*) malloc(sizeof(int) * (d1+d2));
int i=0, j1=0, j2=0;

while(j1 < d1 && j2 < d2)


novi[i++] = (a[j1] <= a[d1+j2]) ? a[j1++] :
a[d1+j2++];
while(j1 < d1)
novi[i++] = a[j1++];
while(j2 < d2)
novi[i++] = a[d1+j2++];

for(i=0; i<d1+d2; i++)


a[i] = novi[i];

free(novi);
}

void SortMerge(int* a, int d)


{ // Funkcija koja sortira niz
if(d>1)
{
int d1 = d/2;
int d2 = d - d1;
SortMerge(a, d1);
SortMerge(a+d1, d2);
Merge(a, d1, d2);
}
}

U svakom algoritmu sortiranja niz koji se sortira moe biti proizvoljan: niz cijelih
brojeva, niz realnih brojeva, niz karaktera ili pak niz promjenljivih nekog korisniki
definisanog tipa. Jedini uslov je da postoji kriterijum po kojem se elementi niza mogu
uporeivati.
Primjer 35. Podaci o vektoru se sastoje od koordinata x, y i z. Napisati strukturu za uvanje
podataka o vektoru. Sa tastature uitati broj n a zatim uitati n vektora i sortirati ih po
intenzitetu korienjem sortiranja umetanjem.

#include <stdio.h>
#include <stdlib.h>

typedef struct v
{ float x;
float y;
float z;
}vektor;

void ucitaj(vektor *niz,int d)


{
int i;

for(i=0;i<d; i++)
{
scanf("%f", &niz[i].x);
scanf("%f", &niz[i].y);
scanf("%f", &niz[i].z);
}
}

void ispisi(vektor *niz,int d)


{
int i;
for(i=0;i<d; i++)
printf("(%.2f, %.2f, %.2f) ", niz[i].x, niz[i].y,
niz[i].z);
}

float intenzitet(vektor v)
{
return (float) sqrt(v.x*v.x+v.y*v.y+v.z*v.z);
}

void sort(vektor* a, int d)


{
int i, j;
for(i=1; i<d; i++)
{
vektor x = a[i];
j = i-1;
while(j>0 && intenzitet(x) < intenzitet(a[j]))
{
a[j+1] = a[j];
j = j-1;
}
a[j+1] = x;
}
}

int main()
{
int n;
scanf("%d", &n);
vektor *niz=(vektor*)malloc(sizeof (vektor)*n);
ucitaj(niz,n);

sort(niz,n);

ispisi(niz,n);

free(niz);
return 0;
}
Stek i red

Stek je struktura podataka koja predstavlja kontejner promjenljivih istog tipa. Nad
stekom su definisane dvije operacije: push (dodaj) i pop (ukloni). Osobina steka je da se
posljednje dodat elemenat prvi uklanja sa steka. Zato se stek naziva LIFO (last-in-first-out)
struktura podataka.
Ovdje e biti prikazana dva naina implementacije steka - statiki, preko niza
unaprijed definisane maksimalne duine i dinamiki - preko pokazivaa na strukturu koja
predstavlja jedan elemenat steka. Stek se sastoji od elemenata koji meusobno ine povezanu
listu, kao na slici.

El1 El2 El3 NULL

Svaki lan liste se sastoji od nekog podatka i pokazivaa na sljedei lan liste.
Posljednji lan pokazuje na NULL

Primjer 36. Napisati program koji omoguava rad sa stekom cijelih brojeva.

Rjeenje - statiko, preko niza


#include <stdio.h>
#include <stdlib.h>
#define MAXVALUE 100

int stek[MAXVALUE];
int brElem = 0;

void Push(int v)
{
if(brElem == MAXVALUE)
{
printf("Stek je pun\n");
return;
}
stek[brElem++] = v;
printf("Dodaje se element %d\n", v);
}

void Pop()
{
if(brElem == 0)
{
printf("Stek je prazan\n");
return;
}
printf("Uklanja se element %d\n", stek[brElem--]);
}

void Print()
{
int i;
printf("Stek: ");
for(i=0; i<brElem; i++)
printf("%d ", stek[i]);
printf("\n");
}

int main()
{
Push(5);
Push(10);
Push(0);
Print();
Pop();
Print();
return 0;
}

Rjeenje - dinamiko, preko pokazivaa na strukturu


#include <stdio.h>
#include <stdlib.h>

typedef struct el
{
int v;
struct el* sljedeci;
} Elem;

Elem* stek;

void Push(int v)
{
Elem* novi = (Elem*) malloc(sizeof(Elem));
novi->v = v;
novi->sljedeci = stek;
stek = novi;
printf("Dodaje se element %d\n", v);
}

void Pop()
{
if(stek == NULL)
{
printf("Stek je prazan\n");
return;
}
int v = stek->v;
Elem* prvi = stek;
stek = stek->sljedeci;
free(prvi);
printf("Uklanja se element %d\n", v);
}
void Print()
{
Elem* t = stek;
printf("Stek: ");
while(t != NULL)
{
printf("%d ", t->v);
t = t->sljedeci;
}
putchar('\n');
}

int main()
{
Push(5);
Push(7);
Push(6);
Print();
Pop();
Print();
Push(1);
Print();
return 0;
}

Primjer 37. Napisati program koji omoguava rad sa redom cijelih brojeva.
Red je slina struktura steku, s tim da se iz reda uklanja onaj element koji je prvi doao
u red, zato se red naziva FIFO (first-in-first-out) struktura. Red e se implementirati na dva
naina kao i stek.

Rjeenje - statiko, preko niza


#include <stdio.h>
#include <stdlib.h>
#define MAXVALUE 100

int red[MAXVALUE];
int brElem = 0;

int Push(int v)
{
if(brElem == MAXVALUE)
{
printf("Red je pun\n");
return;
}
red[brElem] = v;
brElem++;
printf("Dodaje se element %d\n", v);
}
void Pop()
{
if(brElem == 0)
{
printf("Red je prazan\n");
return -1;
}
int v = red[0];
int i;
for(i=0; i<brElem; i++)
red[i] =red[i+1];
brElem--;
printf("Uklanja se element %d\n", v);
}

void Print()
{
int i;
printf("Red: ");
for(i=0; i<brElem; i++)
printf("%d ", red[i]);
printf("\n");
}

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


{
Push(3);
Push(6);
Push(4);
Print();
Pop();
Print();
return 0;
}

Rjeenje - dinamiko, preko pokazivaa na strukturu


#include <stdio.h>
#include <stdlib.h>

typedef struct el
{
int v;
struct el* sljedeci;
} Elem;

Elem* red;

void Push(int v)
{
Elem* novi = (Elem*) malloc(sizeof(Elem));
novi->v = v;
novi->sljedeci = red;
red = novi;
printf("Dodaje se element %d\n", v);
}

void Pop()
{
if(red == NULL)
printf("Red je prazan\n");
else if(red->sljedeci == NULL)
{
int v = red->v;
free(red->sljedeci);
red = NULL;
}
else
{
Elem *e = red;
while(e->sljedeci->sljedeci != NULL)
e = e->sljedeci;
int v = e->sljedeci->v;
free(e->sljedeci);
e->sljedeci = NULL;
printf("Uklanja se element %d\n", v);
}
}

void Print()
{
Elem* t = red;
printf("Red: ");
while(t != NULL)
{
printf("%d ", t->v);
t = t->sljedeci;
}
putchar('\n');
}

int main()
{
Push(5);
Push(7);
Push(6);
Print();
Pop();
Print();

return 0;
}
Jednostruko povezane liste

Implementacija steka i reda preko pokazivaa na strukture predstavljaju jedno


korienje jednostruko povezane liste. Jednostruko povezana lista moe imati mnogo vie
operacija osim dodavanja elementa i uklanjanja elementa s vrha (kod steka), odnosno sa dna
(kod reda). U jednostruko povezanoj listi se moe uklanjati elemenat s proizvoljne pozicije u
listi, moe se vriti pretraga liste, vriti ubacivanje elemenata tako da lista bude sortirana po
nekom kriterijumu itd. Ovdje e biti prikazane implementacije nekih od ovih operacija.

Primjer 38. Napisati program koji omoguava rad sa jednostruko povezanim listama iji su
elementi parovi (kljuc, vrijednost). Implementirati funkcije za dodavanje elementa u listu (na
proizvoljno mjesto), pretragu liste po kljuu i tampu elemenata liste.
Rjeenje
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct el
{
int kljuc;
char vrijednost[10];
struct el* sljedeci;
} Elem;

Elem* lista = NULL;

void dodaj(Elem* e, int k, char* v)


{
Elem *novi = (Elem*) malloc(sizeof(Elem));
novi->kljuc = k;
strcpy(novi->vrijednost, v);
novi->sljedeci = lista;
lista = novi;
}

void pronadji(Elem* e, int k)


{
if(e == NULL)
{
printf("Ne postoji element sa kljucem %d\n", k);
return;
}
else if(k == e->kljuc)
{
printf("Vrijednost s kljucem %d: %s\n", k,
e->vrijednost);
return;
}
else
pronadji(e->sljedeci, k);
}

void odstampaj(Elem* e)
{
if(e == NULL)
{
printf("---Kraj liste---\n");
return;
}
printf("%d %s\n", e->kljuc, e->vrijednost);
odstampaj(e->sljedeci);
}

void oslobodi_memoriju(Elem* e)
{
if(e == NULL)
return;
Elem *n = e->sljedeci;
free(e);
oslobodi_memoriju(n);
}

int main()
{
dodaj(lista, 3, "tri");
dodaj(lista, 2, "dva");
dodaj(lista, 6, "sest");
dodaj(lista, 4, "cetiri");
odstampaj(lista);

pronadji(lista, 6);
pronadji(lista, 12);

oslobodi_memoriju(lista);

return 0;
}

Primjer 39. Napisati program koji omoguava rad sa jednostruko povezanim listama iji su
elementi parovi (kljuc, string). Implementirati funkcije za dodavanje elementa u listu tako da
lista bude sortirana po kljuu i funkciju za izbacivanje elementa iz liste sa zadatim kljuem
kao i tampu elemenata liste.
Rjeenje
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct el
{
int kljuc;
char string[10];
struct el* sljedeci;
} Elem;

Elem* lista = NULL;

void dodaj(Elem* e, int k, char* s)


{
if(lista == NULL)
{ // lista je prazna
Elem* novi = (Elem*) malloc(sizeof(Elem));
novi->kljuc = k;
strcpy(novi->string, s);
novi->sljedeci = NULL;
lista = novi;
return;
}
else if(k < lista->kljuc)
{ // element koji se dodaje ide na prvo mjesto
Elem* novi = (Elem*) malloc(sizeof(Elem));
novi->kljuc = k;
strcpy(novi->string, s);
lista = novi;
novi->sljedeci = e;
return;
}
else if(e->sljedeci == NULL)
{ // dodaje se na posljednje mjesto u listi
Elem* novi = (Elem*) malloc(sizeof(Elem));
novi->kljuc = k;
strcpy(novi->string, s);
novi->sljedeci = NULL;
e->sljedeci = novi;
return;
}
else if(k < e->sljedeci->kljuc)
{
Elem* novi = (Elem*) malloc(sizeof(Elem));
novi->kljuc = k;
strcpy(novi->string, s);
novi->sljedeci = e->sljedeci;
e->sljedeci = novi;
return;
}
else
dodaj(e->sljedeci, k, s);
}

void izbaci(Elem* e, Elem* p, int k)


{
if(e == NULL)
{
printf("Lista je prazna!\n");
return;
}
else if(k == lista->kljuc)
{
Elem* e = lista;
lista = lista->sljedeci;
free(e);
return;
}
else if(k == e->kljuc)
{
p->sljedeci = e->sljedeci;
free(e);
return;
}
else if(e == NULL)
{
printf("Ne postoji element sa zadatim kljucem!\n");
return;
}
else
izbaci(e->sljedeci, e, k);
}

void odstampaj(Elem* e)
{
if(e == NULL)
{
printf("---Kraj liste---\n");
return;
}
printf("%d %s\n", e->kljuc, e->string);
odstampaj(e->sljedeci);
}

void oslobodi_memoriju(Elem* e)
{
if(e == NULL)
return;
Elem *n = e->sljedeci;
free(e);
oslobodi_memoriju(n);
}

int main()
{
dodaj(lista, 3, "tri");
dodaj(lista, 2, "dva");
dodaj(lista, 6, "sest");
dodaj(lista, 4, "cetiri");
dodaj(lista, 1, "jedan");
dodaj(lista, 8, "osam");
dodaj(lista, 9, "devet");
dodaj(lista, 7, "sedam");
dodaj(lista, 5, "pet");
odstampaj(lista);
izbaci(lista, NULL, 6);
odstampaj(lista);
izbaci(lista, NULL, 1);
odstampaj(lista);
izbaci(lista, NULL, 9);
odstampaj(lista);
oslobodi_memoriju(lista);

return 0;
}

Grafovi

Graf se definie kao ureeni par G=(V,E), gde je V konaan, neprazan skup vorova, a
E je skup grana (veza izmeu vorova).
Osnovni pomjovi vezani za graf su:
Stepen vora grafa je broj grana koje uparuju taj vor.
Dve grane su susjedne ako imaju isti vor.
Grana koja spaja vor sa samim sobom naziva se petljom.
Graf koji nema nijednu petlju nazivaju se prostim grafom.
Graf je regularan ako su svi vorovi istog stepena.
Graf je usmjeren ukoliko su mu grane usmjerene, odnosno ukoliko se zna koji vor je
poetak a koji vor je kraj grane.

Svaki graf se moe grafiki prikazati kao crte koji se sastoji od taaka i linija koje
predstavljaju vorove i grane grafa.
Na slici ... je prikazan jedan neusmjeren graf a na slici ... usmjeren graf.

1 2
1 2
3
3
4
4 5
5
6
6
Postoje dva naina da se predstavi graf - preko matrica povezanosti i preko lista
povezanosti.
Matrica povezanosti za graf G koji ima n vorova je matrica dimenzija nxn pri emu je
element aij = 1 akko postoji grana izmeu vorova ci i cj, a aij=0 ako ne postoji grana izmeu
tih vorova. Jasno je da su matrice povezanosti neusmjerenih grafova simetrine.
Matrice povezanosti grafova sa slika ... i ... su
0 0 0 1 1 0 0 1 0 1 1 0
0 0 1 1 0 1 0 0 1 0 0 0

0 1 0 0 0 0 0 1 0 0 1 0

1 1 0 0 0 0 1 0 0 0 0 1
1 0 0 0 0 1 0 0 0 0 0 1

0 1 0 0 1 0 1 0 0 0 1 0

Primjer 40. Implementirati graf preko matrice povezanosti.

Rjeenje
#include <stdio.h>
#include <stdlib.h>

int **matp;

void OdstampajMatricu(int **m, int stepen)


{
int i, j;
for(i=0; i<stepen; i++)
{
for(j=0; j<stepen; j++)
printf("%d\t", m[i][j]);
printf("\n");
}
}

void UcitajMatricu(int stepen)


{
int i, j, pov;
matp = (int **) malloc(stepen*sizeof(int*));
for(i=0; i<stepen; i++)
matp[i] = (int*) malloc(stepen*sizeof(int));

for(i=0; i<stepen; i++)


for(j=0; j<stepen; j++)
matp[i][j] = 0;

for(i=0; i<stepen; i++)


{
printf("Unesite cvorove koji su povezani sa %d.
cvorom:\n", i);
for(; ;)
{
scanf("%d", &pov);
if(pov < 0 || pov >= stepen)
break;
matp[i][pov] = 1;
matp[pov][i] = 1;
}
}
}

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


{
int stepen, i;
printf("Unesite broj cvorova grafa: ");
scanf("%d", &stepen);

UcitajMatricu(stepen);
OdstampajMatricu(matp, stepen);

for(i=0; i<stepen; i++)


free(matp[i]);
free(matp);

return 0;
}

Drugi nain predstavljanja grafa je preko liste povezanosti. U takvoj implementaciji se


pravi lista vorova pri emo svaki vor pokazuje na vorove sa kojima je povezan. Tako npr,
lista povezanosti za graf na slici ... izgleda

1 2 4 5 NULL
2 3 NULL
3 2 5 NULL
4 1 6 NULL
5 6 NULL
6 1 5 NULL

Primjer 41. Implementirati graf preko liste povezanosti.


Rjeenje
#include <stdio.h>
#include <stdlib.h>

typedef struct c
{
int v;
struct c* s;
} Cvor;

Cvor* UcitajGraf(int brCvorova)


{
Cvor *graf;
int i, j, pov;
for(i=0; i<brCvorova; i++)
graf = (Cvor*) malloc(brCvorova*sizeof(Cvor));
for(i=0; i<brCvorova; i++)
{
graf[i].v = i;
graf[i].s = NULL;
Cvor* p = &graf[i];
printf("Unesite cvorove koji su povezani sa %d.
cvorom:\n", i);
for( ; ;)
{
scanf("%d", &pov);
if(pov < 0 || pov >= brCvorova)
break;
Cvor* c = (Cvor*) malloc(sizeof(Cvor));
c->v = pov;
c->s = NULL;
p->s = c;
p = c;
}
}
return graf;
}

void OdstampajGraf(Cvor* graf, int brCvorova)


{
int i, j;
for(i=0; i<brCvorova; i++)
{
Cvor* c = &graf[i];
printf("%d->", graf[i].v);
while(c->s != NULL)
{
c = c->s;
printf("%d, ", c->v);
}
printf("\n");
}
}

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


{
Cvor *graf;
int brCvorova, i;
printf("Unesite broj cvorova grafa: ");
scanf("%d", &brCvorova);
graf = UcitajGraf(brCvorova);
OdstampajGraf(graf, brCvorova);
return 0;
}

Stabla
Zadaci za vjebu

1. Podaci o procesu se sastoje od naziva procesa i vremena izvravanja. Implementirati


stek koji uva podatke o procesima.
2. Napisati program koji uitava jednostruko povezanu listu i iz nje uklanja najvei
element.
3. Napisati program koji uitava jednostruko povezanu listu i pronalazi aritmetiku
sredinu pozitivnih elemenata te liste.
4. Napisati program koji uitava jednostruko povezanu listu i od pozitivnih elemenata te
liste pravi novu listu.
5. Napisati program koji uitava jednostruko povezanu listu i ispisuje njene elemente u
obrnutom redoslijedu.
6. Napisati program koji uitava dvije jednostruko povezane liste i provjerava da li su te
dvije date liste identine.
7. Napisati program koji uitava i tampa jednostruko povezanu listu. Lista ne smije
sadravati jednake elemente.
8. Napisati program koji uitava jednostruko povezanu listu i tampa elemente koji se
nalaze na neparnim mjestima.
9. Napisati program koji uitava jednostruko povezanu listu i od nje pravi dvije
jednostruko povezane liste tako da se u prvoj nalazi polovina elemenata a druga
polovina u drugoj listi.
10. Napisati program koji uitava i tampa ciklinu jednostruko povezanu listu.
11. Napisati program koji uitava dva grafa i ispituje da li su identini.
12. Napisati program koji uitava graf i ispituje da li je usmjeren.
13. Napisati program koji uitava graf i ispituje da
14. Napisati program koji uitava ureeno binarno stabla i izraunava koliko njegovih
vorova ima tano dva podvora.
15. Dodatak A

Pregled vanijih funkcija biblioteke math.h


Ime funkcije Opis
acos Inverzni kosinus
acosh Inverzni hiperboliki kosinus
asin Inverzni sinus
asinh Inverzni hiperboliki sinus
atan Inverzni tangens
atanh Inverzni hiperboliki tangens
cbrt Kubni korjen
cos Kosinus
cosh Hiperboliki kosinus
exp Eksponencijalna funkcija
exp2(x) 2x
fabs Apsolutna vrijednost realnog broja
fmax(x,y) Vraa veu vrijednost od x i y
fmin(x,y) Vraa manju vrijednost od x i y
hypot(x,y) Hipotenuza - sqrt(x2 + y2)
log Prirodni logaritam
log2 Logaritam po bazi 2
log10 Lograitam po bazi 10
pow(x,y) xy
round Zaokruivanje realnog broja
sin Sinus
sinh Hiperboliki sinus
sqrt Kvadratni korjen
tan Tangens
tanh Hiperboliki tangens

Pregled vanijih funkcija biblioteke string.h

Pregled vanijih funkcija biblioteke ctype.h


00 UVOD

PLAN VEBI

1. UVOD
2. TIPOVI PODATAKA
3. GRANANJA, CIKLUSI UVOD
4. CIKLUSI NASTAVAK
5. FUNKCIJE
6. NIZOVI
7. NIZOVI NASTAVAK
8. I KOLOKVIJUM
9. MATRICE
10. MATRICE NASTAVAK
11. STRINGOVI
12. STRUKTURE
13. STRUKTURE NASTAVAK
14. II KOLOKVIJUM

NAIN POLAGANJA

I KOL II KOL
UL ZA UL ZA DOL+AKT UKUPNO
MAX 10 35 10 35 10 100
MIN 5 20 5 20 5 55

ISPIT SE MOE POLOITI PREKO KOLOKVIJUMA SA MINIMUM 55 BODOVA.

ZA DOBIJANJE POTPISA NEOPHODNO JE OSTVARITI MINIMUM PO 5 BODOVA NA


ULAZNIM TESTOVIMA

POMONI MATERIJAL KAO I MATERIJAL SA VEBI BIE DOSTUPAN NA FORUMU


LABORATORIJE ZA RAUNARSKU TEHNIKU (Computer Science Laboratory)
csl.ftn.kg.ac.rs/forum u okviru nastavnih predmeta pa pod predmetom Uvod u programiranje.

http://csl.ftn.kg.ac.rs/forum/index.php/board,23.0.html

1
RAZVOJNO OKRUENJE Code::Blocks
Preuzeti sa sledeeg linka:
http://www.codeblocks.org/downloads/26
odabrati veu verziju sa ukljuenim MinGW GCC kompajlerom (codeblocks-12.11mingw-setup.exe)

Za lino vebanje mogue je koristiti i druga dostupna razvojna okruenja.

KREIRANJE PROJEKTA

ODABRATI Console application

2
ODABRATI C JEZIK I NAKON TOGA UPISATI IME PROJEKTA I ODABRATI LOKACIJU

NA SLEDEEM PROZORU NE MENJATI PODEAVANJA I KLIKNUTI FINISH

3
NAKON TOGA DOBIJAMO FAJL main.c SA UPISANIM HELLO WORLD PROGRAMOM

REZULTAT IZVRENJA PROGRAMA

4
U SLUAJU NE PREPOZNAVANJA MinGW KOMPAJLERA U OKVIRU
Settings=>Compiler and debugger, TAB Tolchain Executables

Odabrati Auto detect ili podesiti putanju do MinGW kompajlera

5
UVOD U ALGORITME

Simboli koji se koriste u algoritamskim emama:

Povezivanjem simbola usmerenim strelicama, koje oznaavaju tokove obrade, dobijaju se


algoritamske eme.

Primer 1. Nacrtati algoritam za sabiranje brojeva x i y.

6
Primer 2. Nacrtati algoritam za izraunavanje sledee funkcije:

7
01 - Tipovi podataka
Podaci u programu mogu da se predstave pomou vrednosti ili pomou identifikatora. Podaci predstavljeni
pomou vrednosti ne mogu da promene svoje vrednosti u toku izvravanja programa i nazivaju se konstantama.
Podacima koji su smeteni u memoriji raunara, obino, mogu da se promene vrednosti u toku izvravanja
programa. Takvi podaci nazivaju se promenljivim podacima ili krae promenljivama. Podaci mogu da budu
prosti ili sloeni.
Prosti podaci ne mogu da se rastave na manje elemente koji bi mogli nezavisno da se obrauju. Zato se kae da
oni nemaju strukturu. Nazivaju se i nestrukturiranim podacima ili skalarnim podacima.
Sloeni podaci se sastoje od nekoliko elemenata koji mogu da se nezavisno obrauju. Elementi sloenih podataka
mogu da budu prosti, ali i sami mogu da budu sloeni. Na taj nain broj razliitih sloenih tipova podataka, koji
mogu da se izvode polazei od prostih tipova podataka, je neogranien. Poto sloeni podaci imaju imaju odreenu
strukturu, nazivaju se i strukturiranim podacima.

Duina [bit] Opseg vrednosti


Oznaka tipa
standard tipino standard tipino
signed char -128127
char 8 -128127 ili 0255
unsigned char 0255
short int 2i-12i-1-1 -3276832767
unsigned short int
i (i 16) 16 02i-1 065535
int 2j-12j-1-1
j (k j i) 16 ili 32
unsigned int 02j-1
long int -2147483648
2k-12k-1-1
k (k 32) 32 2147483648
unsigned long int 02k-1 04294967295

Tabela 1. Osobine celobrojnih podataka


Duina Znaajne Proireni opseg
Oznaka tipa Opseg vrednosti Relativna greka
[bit] cifre (smanjena tanost)
float 32 1,17*10-38<|x|<3,40*10+38 <1,19*10 -7 67 1,39*10-45<|x|
double 64 2,22*10-308<|x|<1,79*10+308 <2,22*10-16 1516 4,93*10-324<|x|
Tabela 2. Osobine realnih podataka
Logiki podaci
U jeziku C za predstavljanje logikih vrednosti koriste se celobrojni podaci tipa int, s tim da se vrednost 0 tumai
kao logika neistina (false), a bilo koja nenulta vrednost kao logika istina (true).

Simbolike konstante
Simbolika konstanta je konstanta kojoj je dodeljen identifikator. Kasnije se u programu koristi identifikator, a ne
vrednost konstante. Simbolika konstanta se definie direktivom define iji je opti oblik:

#define IME_KONSTANTE vrednost_konstante

IME_KONSTANTE je identifikator koji u nastavku programa predstavlja navedenu konstantnu vrednost. Direktiva
define mora da se pie u zasebnom redu. Jednom direktivom moe da se definie samo jedna konstanta. Komentar
na kraju reda je dozvoljen. Evo nekoliko primera definisanja simbolikih konstanti:

#define MIN 0
#define MAX 1000
#define PI 3.14159

1
Biblioteke funkcije
Ako ele da se koriste neke od bibliotekih funkcija, potrebno je na poetku programa to saoptiti prevodiocu
jezika C ime odgovarajueg zaglavlja direktivom include iji je opti oblik:
#include <naziv_datoteke>
Primer:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

Konverzioni karakteri
Konverzioni Opis konverzije
karakter (q)
d decimalna koncerzija oznaenih brojeva (tip int)
c Konverzija jednog karaktera (tip char)
s Konverzija niza karaktera (tip char[])
f konverzija realnih decimalnih brojeva u jednostrukoj tanosti
(tip float)
lf konverzija realnih decimalnih brojeva u dvostrukoj tanosti
(tip double)

Ulazna konverzija
Ulazna konverzija podataka vri se pozivanjem biblioteke funkcije scanf pomou naredbe iji je opti oblik:

scanf(format , &podatak, ... , &podatak);


scanf(%f , &a);
scanf(%d%d , &a, &b);

Prvi argument funkcije scanf je format kojim se odreuju konverzije koje treba da se izvravaju u toku unosa
podataka. Svaki podatak predstavlja identifikator numerike promenljive u koju e biti smeten rezultat konverzije
pojednog unetog podatka. Operator & ispred identifikatora promenljive oznaava da se funkciji scanf dostavlja
adresa navedene promenljive. Format je tekstualni podatak (niz znakova) oblika tekst. Pojedinane konverzije se
iskazuju podnizovima opteg oblika:
%nq
koji poinju znakom % i zavravaju se oznakom za vrstu konverzije (q). Izmeu njih moe da bude i izvestan broj
dopunskih parametara konverzije (n).

Izlazna konverzija
Izlazna konvrzija podataka vri se pozivanjem biblioteke funkcije printf pomou naredbe iji je opti oblik:

printf(format , izraz, ... , izraz);


printf(Pozdrav svima!!!);
printf(Suma je %d a kolicnik je %f, suma, kolicnik);

Prvi argument funkcije printf je format kojim se odreuju konverzije koje treba da se izvravaju u toku ispisivanja
podataka. Svaki izraz predstavlja numeriki izraz ija e vrednost da se ispisuje. Treba da se skrene panja da
skalarna promenljiva i numerika konstanta predstavljaju specijalne sluajeve numerikih izraza. Format je
tekstualni podatak (niz znakova) oblika tekst.

2
ZADATAK 1: Napisati program koji na standardnom izlazu ispisuje pozdravnu poruku.

#include <stdio.h>
main () {
printf ("Pozdrav svima!");
return 0;
}

ZADATAK 2: Napisati program koji uitava dva cela broja i ispisuje njihov zbir na standardnom izlazu..

#include <stdio.h>
main () {
int a, b, c;
printf ("Uneti dva cela broja:");
scanf ("%d%d", &a, &b);
c=a+b;
printf ("Zbir unetih brojeva je: %d\n", c);
return 0;

MATEMATIKE FUNKCIJE ( #include <math.h> )


Mat.simbol C simbol
cos (x) cos (x)
sin (x) sin (x)
tan (x) tan (x)
ln (x) log (x)
ex exp (x)
xy pow (x,y)
koren (x) sqrt (x)
|x| abs (x) za int, fabs(x) za float i double
Prvi veci ceo broj ceil(x), ceil(2.2)=3, ceil(2.8)=3
Prvi manji ceo broj floor(x), floor(2.2)=2, floor(2.8)=2
Zaokruzivanje round (x), round(2.2)=2, round(2.8)=3

ZADATAK 3: Napisati program koji uitava stranicu kvadrata i izraunava obim, povrinu, dijagonalu kvadrata i
ispisuje rezultat na standardnom izlazu..

#include <stdio.h>
#include <math.h>
main () {
double a, o, p, d;
printf ("Unesi stranicu: ");
scanf ("%lf", &a);
o=4*a;
p=pow (a, 2);
d=(sqrt (2))*a;
printf ("Obim je: %.2lf\n Povrsina je: %.2lf\n Dijagonala je: %.2lf\n", o, p, d);
return 0;
}

3
ZADATAK 4. : D,
. : .

#include <stdio.h>
#include <math.h>
main(){
float a, b, c; //stranice kvadra
float P, V; //povrsina, zapremina
double D; //glavna dijagonala
printf("Unesi stranice kvadra: ");
scanf("%f%f%f", &a, &b, &c);

D = sqrt(a*a + b*b + c*c);


P = 2*(a*b + b*c + a*c);
V = a*b*c;

printf("Glavna dijagonala je: %.2lf\nPovrsina je: %.2f\nZapremina je: %.2f\n", D, P, V);


return 0;
}
DELJENJA U C programskom jeziku

U C jeziku postoje dva simbola za deljenje pomou kojih se mogu postii 3 tipa deljenja.
Celobrojno (int a)/(int b) = 5 / 3 = 1, daje ceo deo realnog broja
Po modulu (int a)%(int b) = 5 % 3 = 2, daje celobrojni ostatak pri deljenju
Realno (int a)/(int b) = (float) 5 / 3 = 1.67, daje realan rezultat pri deljenju celih brojeva, mora se uraditi
kastovanje u eljeni tip rezultata pored jedne od celobrojnih promenljivih (float)

ZADATAK 5: Napisati program koji ucitava dva cela broja a ispisuje zadnju cifru prvog broja, rezultat
celobrojnog deljenja, ostatak pri deljenju kao i realan rezultat na standardnom izlazu.

#include <stdio.h>
main () {
int a, b, c, d, e;
float f;
printf ("Unesi dva cela broja: ");
scanf ("%d%d", &a, &b);
c = a%10;
printf ("Zadnja cifra unetog broja %d je: %d\n", a, c);
d = a / b;
e = a % b;
f = (float) a / b;
printf ("d = %d, e = %d, f = %f \n", d, e, f);
return 0;
}

4
02 - Grananja
Osnovna selekcija: if else

Osnovnom selekcijom se vri uslovno izvravanje jedne od dve mogue naredbe. Standardni i strukturirani
dijagrami toka ove upravljake strukture prikazani su na slikama 2a i 2b, respektivno. Ukoliko logiki izraz uslov
ima vrednost logike istine (0), izvrava se naredba 1. Ako je vrednost uslova logika neistina (=0), izvrava se
naredba 2.
LOGIKE OPERACIJE
== provera identinosti
!= ne identino
<= manje ili jednako
>= vece ili jednako
! negacija
&& i
|| ili

Naini pisanja naredbe if

if (uslov) if (uslov){
naredba_1; naredba_1;
else naredba_2;
naredba_2; } // nema else
if (uslov){ if(uslov_1)
naredba_11; naredba_1;
naredba_12; else if(uslov_2)
... naredba_2;
naredba_1M; else if( ... )
}else{ ...
naredba_21; else if(uslov_N)
naredba_22; naredba_N-1;
... else
naredba_2N; naredba_N;
}

1
ZADATAK 6: Napisati algoritam i program koji uitava dva cela broja i na standardnom izlazu ispisuje koji je
vei od ta dva broja.

#include <stdio.h>
main (){
int a, b;
printf ("Uneti dva cela broja:");
scanf ("%d%d", &a, &b);
if (a>b)
printf("Veci je broj %d\n", a);
else if(b>a)
printf("Veci je broj %d\n", b);
else
printf("Brojevi su jednaki\n);
return 0;
}

2
ZADATAK 7: Napisati program koji uitava ceo broj, proverava da li je uitani broj paran ili neparan i ispisuje
odgovarajuu poruku na standardnom izlazu.

#include <stdio.h>
main (){
int a;
printf ("Unesi ceo broj: ");
scanf ("%d", &a);
if (a%2 == 0)
printf ("Broj je paran\n");
else
printf ("Broj je neparan\n");
return 0;
}

ZADATAK 8: Napisati C program koji uitava ceo broj c i realan broj x pri emu je x > 0 . Zatim izraunava i
tampa vrednost funkcije f i to na sledei nain
- ukoliko je c < 0 rauna se i tampa f = sin x 2 x 5 + x 2
- ukoliko je 0 c 8 rauna se i tampa f =| sin 31x x 3 | + | x 2 3 x | +1
- ukoliko je c > 8 rauna se i tampa f = log 2 x + e 3 x
NAPOMENA: abs(x) za int, fabs(x) za float i double
#include <stdio.h>
#include <math.h>

int main(){
int C;
float X;
double f;

printf("Uneti ceo broj C!\n");


scanf("%d", &C);

printf("Uneti realan broj X, veci od 0!\n");


scanf("%f", &X);

if (C<0) {
f = sin( pow( X, 2 )) - pow( X, 5 ) + X - 2;
}else if (C<=8) {
f = fabs(sin( 31 * X) - pow( X, 3 )) + sqrt( fabs( pow( X, 2 ) - 3*X )) + 1;
}else {
f = log( 2*X ) + exp( -3*X );
}
printf("\nVrednost funkcije je %lf \n", f);
return 0;
}

3
ZADATAK 9: Napisati program koji ucitava 3 cela broja a ispisuje na standardnom izlazu najmanji od njih.

#include <stdio.h> //standardni nacin // skraceni uslov


main (){ if (a<b)
int a, b, c; (a<c) ? printf ( " Najmanji je: %d\n", a):
printf("Uneti tri cela broja: "); printf ( " Najmanji je: %d\n", c);
scanf ("%d%d%d", &a, &b, &c); else
if(a<b){ (b<c) ? printf ( " Najmanji je: %d\n", b):
if(a<c) printf ( " Najmanji je: %d\n", c);
printf("Najmanji broj je: %d\n", a);
else // najbolji nacin za bilo koji broj elemenata
printf("Najmanji broj je: %d\n", c); min = a; /* min je prvi element iz skupa u kojem se
}else{ trazi resenje*/
if(b<c) if (b < min) /* proci kroz ostale elemente i pitati da li
printf("Najmanji broj je: %d\n", b); ima ko manji*/
else min = b; /*ako ima onda on postaje najmanji*/
printf("Najmanji broj je: %d\n", c); if (c < min)
} min = c;
return 0; printf (Minimalni je %d \n, min);
}
Selekcija pomou skretnice: switch
Selekcija pomou skretnice se sastoji od niza naredbi i celobrojnog izraza ija vrednost odreuje prvu naredbu u
nizu odakle poinje izvravanje. Mogu se switch-ovati samo celobrojne promenljive ili izrazi ili znakovi.
Celokupan niz naredbi je razbijen u podnizove niz_naredbi_1,niz_naredbi_2, ,niz_naredbi_N. Opti oblik:
switch (izraz) {
case konstanta1: operator1
break;
case konstanta2: operator2
break;
default : operatorn
break;
}

4
Primer 2. Nacrtati algoritam za izraunavanje sledee funkcije:

ZADATAK 10: Napisati program koji unosi dva cela broja a i b i jedan ceo broj n na osnovu koga se izvrsava
odredjena operacija nad brojevima a i b i to ako je:
n=1, c=a+b
n=2, c=a-b
n=3, c=a/b
n=4, c=a%b
n=6, c=a*b

#include<stdio.h>
int main(){
int n;
int a, b, c;

printf("Uneti cele brojeve a i b\n");


scanf("%d %d",&a,&b);
printf("Uneti ceo broj n\n");
scanf("%d",&n);
switch(n){
case 1:

5
c=a+b;
printf("\nZbir je %d \n", c);
break;
case 2:
c=a-b;
printf("\nRazlika %d\n", c);
break;
case 3:
c=a/b; // 2=5/2
printf("\nCelobrojno deljenje %d\n", c);
break;
case 4:
c=a%b; //1=5/2
printf("\nDeljenje po modulu %d\n", c);
break;
case 6: //brojevi ne mora da idu po redu
c=a*b;
printf("\nMonozenje %d\n", c);
break;
default: printf("Nekorektna operacija\n");
}
return 0;
}

ZADATAK 11: Napisati program koji za uneti broj meseca (na primer, 1=Januar, 2=Februar, itd.) ispisuje njegov
broj dana. U sluaju unete vrednosti 2 pitati korisnika da li je godina prestupna.

#include<stdio.h>
int main(){
int mesec, ch;
printf("Uneti redni broj meseca\n");
scanf("%d",&mesec);
switch(mesec){
case 1:case
1 case 3:case
3 case 5:case
5 case 7:case
7 case 8:case
8 case 10:
10 case 12:
12 printf("31 dan\n"); break;
break
case 4:
4 case 6:
6 case 9:
9 case 11:
11 printf("30 dana\n"); break;
break
case 2:
2 printf("Da li je godina prestupna (d-1/n-0)?\n");
scanf("%d",&ch);
if(ch == 1)
printf("29 dana\n");
else
printf("28 dana\n");
break;
break
default:
default printf("Nekorektan broj meseca\n");
break;
break
}
return 0;
}

6
CIKLUSI UVOD
Ciklusi
Ciklusi su upravljake strukture koje omoguavaju ponovljeno izvravanje neke naredbe. Broj ponavaljanja moe
biti poznat a moe i zavisiti od ispunjenja odreenog logikog uslova.

Generalizovani ciklus sa izlazom na vrhu: FOR


U praksi su vrlo esti ciklusi sa sledeom strukturom:
postavljanje poetne vrednosti jedne ili vie promenljivih pre ulaska u ciklus,
ispitivanje da li treba izvravati sadraj ciklusa pre svakog prolaska kroz ciklus,
menjanje vrednosti jedne ili vie promenljivih na kraju svakog prolaska kroz ciklus.
Standardni i strukturirani dijagrami toka osnovnog ciklusa sa izlazom na vrhu kao i programska sintaksa prikazani
su na slici.

for(izraz_1; uslov_2; izraz_3){


naredba_1;
naredba_2;
...
naredba_N;
}

IZRAZ 1 predstavlja predstavlja pripremu za ulazak u ciklus (moe da obuhvata i vie radnji razdvojenih
zarezom). Slui za postavljanje potrebnih poetnih vrednosti.
USLOV 2 je logiki izraz koji predstavlja uslov za nastavljanje ciklusa.
IZRAZ 3 predstavlja zavrne radnje na kraju svakog prolaska kroz ciklus, tj. pripremne radnje za naredni prolazak
kroz ciklus. Te radnje, najee, predstavljaju menjanje brojaa koji kontrolie broj prolazaka kroz ciklus.

NAPOMENA: idealna je kada je poznat broj ponavaljanja nekog skupa naredbi

Primeri for iteracije:

for (i = 0; i< 5; i++) KORAK I


1 0
2 1
3 2
4 3
5 4
6 5 ( i<5 = false)

for (i = 0, j = 10; i< 50 && j<200; i+=3, j*=2) KORAK I j


1 0 10
2 3 20
3 6 40
4 9 80
5 12 160
6 15 320 (j<200 = false)

7
Ciklus sa izlaskom na vrhu: WHILE
Standardni i strukturirani dijagrami toka osnovnog ciklusa sa izlazom na vrhu kao i programska sintaksa prikazani
su na slici.

while (uslov){
naredba_1;
naredba_2;
...
naredba_N;
}

Na poetku svakog prolaska kroz ciklus izraunava se vrednost logikog izraza uslov, i ako se dobija logika istina
(0), izvrava se naredba. Ciklus se zavrava kada vrednost uslova postane logika neistina (=0). Treba da se uoi,
moe se desiti da naredba ne bude ni jednom izvravana.

NAPOMENA: idealna je kada je nepoznat broj ponavaljanja nekog skupa naredbi


Ciklus sa izlazom na dnu: DO - WHILE
Standardni i strukturiran dijagram toka ciklusa sa izlazom na dnu prikazan je na slici

do{
naredba_1;
naredba_2;
...
naredba_N;
}while(uslov);

Kod ciklusa sa izlazom na dnu prvo se izvrava naredba koja ini sadraj ciklusa pa se proverava vrednost
logikog izraza uslov, i ako se dobija logika istina (0), skoi se na ponovno izvravanje naredbe. Ciklus se
zavrava kada vrednost uslova postane logika neistina (=0). Naredba se uvek izvrava bar jednom.

NAPOMENA: idealan kada je potrebno prvo izvriti naredbu pa proveriti da li je ispunje uslov, to treba raditi
sve dok se ne ispuni uslov

PRIMER 1 : Ispisati sve brojeve od 1 do n pomou svih petlji osiguravajui da je n minimum 4.


#include <stdio.h>
#include <stdlib.h>

int main(){
int n;
int i; // iterator kroz petlje

do{
printf("Unesi n!\n");
scanf("%d",&n);
}while(n<4);

8
printf("\nPOMOCU FOR PETLJE!\n");
for(i=1; i<=n; i++)
printf("%d ", i);

printf("\nPOMOCU WHILE PETLJE!\n");


i = 1;
while(i<=n) { // uslov
printf("%d ", i);
i++; // promena iteratora
}

printf("\nPOMOCU DO - WHILE PETLJE!\n");


i = 1;
do{
printf("%d ", i);
i++; // promena iteratora
} while(i<=n); // uslov

return 0;
}
Primer 2. Nacrtati algoritam za mnoenje dva prirodna broja koristei operaciju sabiranja.

9
VEBE 03
CIKLUSI

ZADATAK 11: Program za izraunavanje faktorijela

#include<stdio.h>
int main(){
int i,n;
int fakt=1; /*obavezno postavljanje promenljive na vrednost
koja ne utice na operaciju koja se nad njom obavlja*/
printf("Izracunavanje n!\nUkucajte broj (<33)?");
scanf("%d",&n);
for(i=1; i<=n; i++)
fakt*=i;
printf("%d!=%d\n",n,fak);
return 0;
}

1
ZADATAK 12: Napisati program kojim se na ekranu dobijaju permutovane cifre unetog celog broja.

#include<stdio.h>
int main(){
int broj, cifra;
printf("Ukucajte ceo broj?\n");
scanf("%d",&broj);
printf("Permutovan broj je\n");

while(broj != 0){ // ili while(broj);


cifra = broj%10;
broj /= 10;
printf("%d", cifra);
}
return 0;
}

ZADATAK 13: Napisati program za odreivanje srednje vrednosti n celih brojeva

#include<stdio.h>
int main() {
int n, i;
float suma=0; /*obavezno postavljanje promenljive na vrednost
koja ne utice na operaciju koja se nad njom obavlja*/
float x;
printf("Ukupno brojeva?\n");
scanf("%d",&n);
for (i=0; i<n; i++){
printf("Ukucajte %d. broj?", i+1);
scanf("%f",&x);
suma+=x;
}

printf("Srednja vrednost ovih brojeva je %f\n",suma/n);


return 0;

2
}

ZADATAK 14: Napisati program kojim se unosi jedan ceo broj sa tastature i ukoliko je broj vei od 10 zahteva se
ponovni unos sve dok se ne unese odgovarajui broj.

#include<stdio.h>
int main(){
int broj;
do {
printf ("Ukucajte ceo broj?\n");
scanf ("%d",&broj);
}
while(broj>10);
printf("\nKonacno je unet broj %d", broj);
return 0;
}

ZADATAK 15: Napisati program koji ucitava cele brojeve dok se ne ucita nula i koji prikazuje njihov zbir na
standardnom izlazu.

#include <stdio.h> /*Ucitavanje brojeva razlicitih od nule i izracunavanje njihovog zbira*/


int main (){
int a, zbir=0; /*obavezno postavljanje promenljive na vrednost
koja ne utice na operaciju koja se nad njom obavlja*/
do{
printf ("Unesi broj: ");
scanf ("%d", &a);
zbir += a;
}while (a!=0);
printf("Zbir je: %d\n", zbir);
return 0;
}

3
Upravljake stukture ciklusa: break i continue

Iskakanje iz upravljake strukture izvrava se naredbom:


break;
Korienjem naredbe break se postie:
prevremeni zavretak ciklusa (while,for,do) skakanjem na prvu naredbu neposredno iza ciklusa, ili
preskakanje preostalih naredbi unutar selekcije pomou skretnice (switch) skakanjem na prvu naredbu
neposredno iza selekcije.
U sluaju uklopljenih upravljakih struktura, izlazi se samo iz najdublje strukture, tj. iz strukture koja neposredno
obuhvata datu naredbu break.

Naredba continue prosleuje tok kontrole na sledeu iteraciju najblie do, for ili while naredbe u kojoj se
pojavljuje, ime se preskau preostale naredbe u telu petlje.

Korienjem naredbe continue se postie:


- Unutar do ili while petlje, sledea iteracija poinje proveravanjem uslova u do ili while naredbi;
- U for petlji, continue naredba uzrokuje da se proveri uslov u for naredbi. Potom kompajler ponovo
proverava uslov i u zavisnosti od rezultata provere, ili prekida izvravanje petlje ili nastavlja njeno
izvravanje.

4
ZADATAK 16a: Napisati program koji ucitava ceo pozitivan broj a ispituje da li je on prost ili ne i rezultat
ispisuje na standardnom izlazu.
#include <stdio.h>
main (){
int a, i=2, prost = 1; // 1 je logicki taan izraz, 0 je logicki netaan
printf("Unesi ceo pozitivan broj: ");
scanf("%d", &a);

while(i<a) for (i=2; i<a; i++)


if(a % i == 0){ if(a% i == 0){
prost = 0; prost = 0;
break; break;
}else }
i ++;

if( prost )
printf("Broj %d je prost\n", a);
else
printf("Broj %d je slozen\n", a);
return 0;
}

5
ZADATAK 16b: Napisati program koji nalazi proizvod 4 cela broja koja unosi korisnik. U sluaju da korisnik
unese nulu, preskoiti je.

#include <stdio.h>
int main(){
int i,broj,proizvod;
for(i=1,proizvod=1;i<=4;++i){
printf("Unesite broj %d:",i);
scanf("%d",&broj);
if(broj==0)
continue; / *Kada je broj jednak nuli, preskae se sledea naredba proizvod*=broj i nastavlja se ciklus. */
proizvod*=broj;
}
printf("Proizvod iznosi %d",proizvod);
return 0;
}

ZADATAK 17: Napisati program koji ucitava cele brojeve a, b, c i prebrojava i ispisuje na standardnom izlazu
cele brojeve iz intervala [a,b] koji su deljivi sa c. Demonstrirati reenje pomou while i for cikljusa.

#include <stdio.h> #include <stdio.h>


main (){ main (){
int a, b, c, i; int a, b, c, i;
int br = 0; // pocetna vrednost int br = 0; // pocetna vrednost
printf("Uneti brojeve: "); printf("Uneti brojeve: ");
scanf("%d%d%d", &a, &b, &c); scanf("%d%d%d", &a, &b, &c);
i=a; // startna vrednost for(i=a; i<=b; i++){
while(i<=b){ if(i%c==0){
if(i%c==0){ printf("%d,", i);
printf("%d,", i); br++;
br++; }
} }
i++; // korak printf(br= %d, br);
} }
printf(br= %d, br);
}
Domai : Prepraviti kod da broj b mora biti vei od a a da broj c mora biti manji od b i da c ne sme biti 0.

ZADATAK 18: Napisati program koji ucitava cele brojeve dok se ne ucita pozitivan broj deljiv sa 4 a da nije
manji od 10 a prikazuje na standardnom izlazu srednju vrednost svih brojeva koji su neparni ili deljivi sa 3 i 6.

#include <stdio.h>
#include <math.h>
int main () {
int a, broj=0;
float srvr=0;

printf("Unesi broj: ");


scanf("%d", &a);

6
do{
printf("Unesi broj: ");
scanf("%d", &a);

if (a%2==1 || (a%3==0 && a%6==0)){


srvr+=a;
broj++;
}
} while(!(a>0 && a%4==0 && a>10));

printf("Srednja vrednost je: %.2f\n", (srvr/broj));


return 0;
}

ZADATAK 19: Napisati program koji za zadati prirodan pozitivan broj n ispisuje najpre da li je deljiv i sa 6 i sa 7.
Ako je deljiv izraunava se suma oblika , ako nije a paran je rauna se suma oblika
S=sin(1)-sin(2)++sin(n). Za sve ostale rauna se suma oblika S=
#include <stdio.h>
#include <math.h>
int main(){
int n,i,z; // z predstavlja operaciju (+ , -) koja ce u svakom ciklusu menjati (z=-z)
double s=0;

int j; //za stepen za poslednji else


printf("Uneti prirodan broj n");
scanf("%d",&n);
if (n%6==0 && n%7==0){
for (i=1; i<=n; i++)
s+= pow(i,4);
}else if (n%2==0){
z=1;
for(i=1; i<=n; i++){
s+=z*sin(i);
z=-z; // promena znaka
}
}else {
for (i=2, j=2; i<=n; i+=2, j++) //for petlja sa vise iteratora koji zajedno menjaju vrednost
s+= pow(i,j)/pow(i+1,j);
}
printf("Suma je %lf\n",s);
return 0;
}

Domaci: Napisati program koji izraunava sumu S3 koja samo umesto sume razlomaka ima jednu razlomaku crtu

7
04 FUNKCIJE

Kada je re o funkcijama prvo treba objasniti funkciju Main(). Ova funkcija kao rezultat vraa void ili
int, a moe se ukljuiti string[] args parametar, pa su mogue sledee verzije ove funkcije:
void main(){}

void main(int argc, char* argv){}

int main(){ ... return 0;}

int main(int argc, char* argv) { ... return 0;}

NAPOMENA:
int argc broj ulaznih argumenata od kojih je ime programa uvek jedan
char* argv niz stringova prosledjenih prilikom poziva programa

Funkcije su programske celine koje imaju ulogu da odrade jedan deo ili eventualno ceo problem koji
se trai u zadatku. Definicija funkcije sastoji se od zaglavlja i tela funkcije. Zaglavlje funkcije sadri
identifikator (ime funkcije), par zagrada ( i ) izmeu kojih se opcionalno nalazi lista argumenata
funkcije sa definicijama argumenata funkcije. Telo funkcije je skup izvrnih iskaza i deklaracija
promenljivih korienih u funkciji.

tipRezultata imeFunkcije(argumenti){ //primer funkcije koja sabira dva broja


Definicija lokalnih promenljivih; int zbir (int a, int b){
Naredba1; int c;
c = a + b;
NaredbaN; return c;
return rezultat; }
}
Funkcija koje prenose parametre preko vrednosti mogu da vrate maksimalno jedan rezultat a takodje
funkcija moe i da ne vrati rezultat to se vidi na sledeem primeru funkcije koja samo ispisuje
pozdravnu poruku;

void poruka(){ /*Zaglavlje funkcije*/


printf(Zdravo!\n); /*Telo funkcije su svi iskazi izmedju { i }*/
}

Preporuka je da se funkcije definiu pre glavnog dela programa (funkcije main).


U glavnom delu programa FUNKCIJE SE POZIVAJU POMOCU IMENA FUNKCIJE SA
ISTIM BROJEM, TIPOM I REDOSLEDOM STVARNIH ARGUMENATA.
Definicija funkcije void test(int a){} int test2(int a, int b){}
Main funkcija i poziv pomone main(){ main(){
funkcije int a = 5; int a = 5, b = 6, c = 7, d;
test (5); d = test2 (a, b); // ok
test(a); d = test2 (b, c); // ok
test(a+5) a = test2(a+5, c); // ok
} }

1
ZADATAK 18: Napisati program koji rauna hipotenuzu pravouglog trougla pomou funkcije.

#include <stdio.h>
#include <math.h>
double hipotenuza (float a, float b){
double c;
c = sqrt ( pow(a, 2) + pow (b, 2));
return c;
}

int main(){
float a, b;
printf(Uneti stranice pravouglog trugla \n);
scanf(%f%f, &a, &b);
printf (Hipotenuza je: %lf \n, hipotenuza(a, b));
return 0;
}
ZADATAK 19. Napisati program za izraunavanje sume kvadrata od 1 do n za dva cela broja.

Reenje: Funkcija int suma_kvadrata(int n) je deklaracija funkcije, koja kao rezultat vraa int i zove se
suma_kvadrata. Int n predstavljaju formalne ulazne argument funkcije. To znai da funkciuja prihvata
jedan int a ali se on pri pozivu ne mora zvati n. Kada funkcija vraa neki rezultat (nije void) unutar
funkcije (najee na kraju) mora da postoji komanda return kojom se vraa vrednost rezultata; gde se kao
rezultat funkcije vraa vrednost promenljive. Funkcija se poziva tako to se u glavnom programu napie
ime funkcije sa odgovarajuim argumentima funkcije. Kada se pozove funkcija, u zagradi stoje stvarni
argumenti.

#include<stdio.h>
int suma_kvadrata(int n){
int i;
int suma = 0;
for(i=1; i <= n; i++){
suma += i*i;
}
return suma;
}
int main(){
int n, m, rezN, rezM;
printf(Uneti dva cela broja \n);
scanf(%d%d, &n,&m);
rezN = suma_kvadrata (n); // funkcije se mogu neograniceno puta pozivati
printf("Suma kvadrata od 1 do %d : %d\n", n, rezN);
rezM = suma_kvadrata (m);
printf("Suma kvadrata od 1 do %d : %d\n", m, rezM);

printf("Suma kvadrata od 1 do %d : %ld\n", 15, suma_kvadrata(15));


printf("Suma kvadrata od 1 do %d : %ld\n", 10, suma_kvadrata(10));
return 0;

2
}

ZADATAK 20. Napisati program u kome se definie funkcija prost() koja ispituje da li je broj prost i
funkcija main() koja njenim korienjem tampa sve proste brojeve do datog prirodnog broja n.

#include<stdio.h>
#include<math.h>
int prost(int n){
int i;
for (i=2; i<=sqrt(n); i++) //dovoljno je ici do koren iz 3
if(n%i == 0)
return 0; //nije prost = 0
return 1; //jeste prost = 1
}
int main() {
int i, n;
printf("Uneti broj\n");
scanf("%d", &n);
printf("Prosti brojevi su\n");
for( i=2; i <= n; i++)
if(prost(i) == 1) //isto kao i if(prost(i)),
if(prost(i)) ne mora da se stavi ==1,
printf("%d\n", i);
return 0;
}

ZADATAK 21: Napisati funkciju koja izracunava faktorijel datog prirodnog broja a potom glavni
program koji ucitava brojeve a i b a ispisuje (a!/b!.)2. Napomena: faktorijal negativnih brojeva je 0,
faktorijal od 0 i 1 je 1.

#include <stdio.h>
#include <math.h>

int Faktorijel(int n) {
if(n<0)
return 0;
else if(n==0 || n==1)
return 1;
else{
int f=1, i=2;
for(i=2; i<=n; i++){
f *= i;
}
return f;
}
}
main(){

3
int a, b;
double c;
printf("Unesi dva cela broja: ");
scanf("%d %d", &a, &b);
c = pow((double)Faktorijel(a)/Faktorijel(b), 2);
printf("Vrednost je %.4lf \n", c);
return 0;
}
VEBA: Izraunati sledei izraz: r= (a!+b!)/(a+b)!

ZADATAK 22: Napisati funkciju koja izraunava povrinu trougla. Poznate su koordinate temena
trougla u X-Y koordinatnom sistemu. Funkcija treba da ima jedan argument, a koordinate se zadaju
pre poziva funkcije kao celi brojevi.
gde je S poluobim trougla tj.
#include<stdio.h>
#include<math.h>

double povrsinaTrougla (int x1, int y1, int x2, int y2, int x3, int y3 ){
double a, b, c, s;
a = sqrt(pow((x1 - x2), 2) + pow((y1 - y2), 2));
b = sqrt(pow((x2 - x3), 2) + pow((y2 - y3), 2));
c = sqrt(pow((x3 - x1), 2) + pow((y3 - y1), 2));
s = (a + b + c)/2;
return sqrt(s * (s-a) * (s-b) * (s-c));
}
int main (){
int x1, y1, x2, y2, x3, y3;

printf ("Uneti koordinate prve tacke: \n");


scanf ("%d%d", &x1, &y1);
printf ("Uneti koordinate druge tacke: \n");
scanf ("%d%d", &x2, &y2);
printf ("Uneti koordinate trece tacke: \n");
scanf ("%d%d", &x3, &y3);

printf("\nPovrsina trogla je :%.2lf \n", povrsinaTrougla(x1, y1, x2, y2, x3, y3));
return 0;
}
ZADATAK 23: Napisati program kojim se stampaju svi petocifreni brojevi(ako ih ima) koji su
jednaki sumi faktorijala svojih cifara. U programu koristiti funkcije.
#include <stdio.h>
int fakt(int n){
int i, f=1;
for ( i=1; i <= n; i++ )
f *= i;
return f;

4
}
int sumaFakt(int n){
int suma = 0, zadCifra;
while(n!=0){
zadCifra = fakt(n % 10);
suma += zadCifra;
n /= 10;
}
return suma;
}
int main(){
int i;
for(i=10000; i <= 99999; i++)
if (i == sumaFakt(i))
printf("%d ", i);
return 0;}

5
VEBE 05 NIZOVI

Podatak nizovnog tipa predstavlja niz podataka meusobno ISTIH tipova. Oni se nazivaju elemetima niza i
identifikuju se pomou rednog broja (indeksa) elemenata niza. Prvi element niza u jeziku C obavezno ima indeks
0, drugi 1 itd.
Definisanje nizova vri se pomou sledee naredbe:

TIP ime_niza [Max broj elemenata]

Max broj elemenata mora da bude konstantan izraz.


Evo nekoliko primera za definisanje nizova:
float vekt[50];
int niz[100];

Inicijalizacija poetne vrednosti pri definisanju piu u obliku niza vrednosti meusobno razdvojenih zarezima
stavljenih izmeu para vitiastih zagrada ({}). To treba da su konstante koje po tipu odgovaraju osnovnom tipu
navedenom u opisu tipa na poetku naredbe za definisanje podataka.
Evo nekoliko primera za definisanje jednodimenzionalnih nizova sa inicijalizatorima:

int dani1[12] = {31,28,31,30,31,30,31,31,30,31,30,31};


int dani1[] = {31,28,31,30,31,30,31,31,30,31,30,31};
long a1[5] = {1,2,3};
long a2[5] = {1,2,3,0,0};
long a3[5] = {1,2,3,4,5,6}; /* GRESKA! */
const int tablica[] = {1,5,3,4,2};

Indeksi u jeziku C su celi brojevi od 0 do n1, gde je n broj elemenata (tj. duina) niza. Pristup elementima niza
naziva se indeksiranjem. Indeksiranje u jeziku C smatra se binarnim operatorom i obeleava se sa [].

int a1[3] = {4,2,8}; pa je a[1]=2

a [i] je vrednost elementa koji se nalazi u nizu a na poziciji i

1
ZADATAK 20: Napisati program kojim se ucitava niz n celih brojeva n<=20 i ispisuje ga na standardnom
izlazu uz sumu svih elemenata niza. (a bez funkcija, b preko funkcija)

Unos dimenzije niza (n)

Proci kroz niz

Unos a[i] elementa niza

Pocetak problematike sume

Proci kroz niz

Dodati vrednost svakog elementa a[i] na sumu

Ispis izracunate sume

Proci kroz niz

ispis a[i] elementa niza

2
A) Bez funkcija
#include <stdio.h>
#include <stdlib.h>
#define DIM 20
main (){
int a[DIM], suma;
int i, n;

printf ("\nDuzina niza (najvise %d)je: ", DIM);


scanf ("%d", &n);

if (n<=0 || n>DIM) // provera dimenzije niza


exit (1); // prekid u slucaju netacne dimenzije. Nije lose ali bolje sa do while !!!

//unos elemenata niza


printf ("Unesite clanove niza: \n");
for (i=0;i<n;i++){
printf(\n a[%d]=, i);
scanf ("%d", &a[i]);
}

// sumiranje elemenata niza


suma = 0;
for (i=0;i<n;i++)
suma += a[i];

printf ("Zbir svih elemenata niza je: %.d\n ", suma);

// ispis elemenata niza


printf ("\nElementi niza: \n");
for (i=0;i<n;i++)
printf(%d , a[i]);
return 0;
}
B) Preko funkcija

#include <stdio.h>
#include <stdlib.h>
#define DIM 20

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


int i;
printf ("Unesite clanove niza: \n");
for (i=0; i<n; i++){
printf(\n a[%d]=, i);
scanf ("%d", &a[i]);
}
} // treba je pozvati u main-u

3
void ispis(int a[], int n){
int i;
printf ("\nElementi niza: \n");
for (i=0; i<n; i++)
printf(%d ,a[i]);
} // treba je pozvati u main-u

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


int i, s;
s = 0;
for (i=0; i<n; i++)
s += a[i];
return s;
} // treba je pozvati u main-u

main (){
int a[DIM], s;
int i, n;

do{
printf ("\nDuzina niza (najvise %d)je: ", DIM);
scanf ("%d", &n);
}while (n<=0 || n>DIM); // unos odgovarajuce dimenzije niza preko do while

unos(a, n);

s = suma(a, n);

printf ("Zbir svih elemenata niza je: %.d\n ", s);

ispis (a, n);

return 0;
}

ZADATAK 20a : Napisati program kojim se ucitava niz n realnih brojeva n<=20 a ispisuje na standardnom
izlazu zbir i srednju vrednost svih pozitivnih elemenata.

#include <stdio.h>
#include <stdlib.h>
#define DIM 20
main (){
double a[DIM], zbir;
int i, n, poz;

printf ("\nDuzina niza (najvise %d)je: ", DIM);


scanf ("%d", &n);

4
if (n<=0 || n>DIM) // provera dimenzije niza
exit (1); // prekid u slucaju netacne dimenzije. Nije lose ali bolje sa do while !!!

//unos elemenata niza void unos(double a[], int n){ // pre main-a
int i;
printf ("Unesite clanove niza: \n"); printf ("Unesite clanove niza: \n");
for (i=0;i<n;i++){ for (i=0; i<n; i++){
printf(\n a[%d]=, i); printf(\n a[%d]=, i);
scanf ("%lf", &a[i]); scanf ("%lf", &a[i]);
} }
} // treba je pozvati u main-u
// sumiranje elemenata niza double srvr(double a[], int n){ // pre main-a
zbir = 0; poz = 0; int i, zbir = 0, poz = 0;
for (i=0;i<n;i++){ for (i=0; i<n; i++){
if (a[i]>0){ if (a[i]>0){
zbir += a[i]; zbir += a[i];
poz++; poz++;
} }
} }
return zbir/poz;
} // treba je pozvati u main-u
printf ("Zbir pozitivnih elemenata je: %.2lf\nSrednja vrednost pozitivnih je: %.2lf\n", zbir, zbir/poz);
return 0;
}

ZADATAK 21: Napisati program koji ucitava niz n realnih brojeva n<=20 a ispisuje na standardnom izlazu
najveci clan niza.

#include <stdio.h>
#include <stdlib.h>
#define DIM 20
main (){
double a[DIM], max;
int i, n;

printf("\nDuzina niza (najvise %d)je: ", DIM);


scanf("%d", &n);

if(n<=0 || n>DIM)
exit(1);

printf("Unesite clanove niza: ");

for (i=0;i<n;i++){//unos elemenata niza


printf(\na[%d]=, i);
scanf ("%lf", &a[i]);
}

5
//max obavezno postaviti na PRVI element iz double maxf(double a[], int n){ // pre main-a
skupa u kojem se trazi resenje. int i;
max = a[0];
max=a[0]; for (i=1; i<n; i++)
for (i=1; i<n; i++){ if(a[i]>max)
if(a[i]>max) max=a[i];
max=a[i]; return max;
} }
printf("Najveci element je: %.2f\n", max); printf("Najveci element je: %.2f\n", maxf(a,n));
return 0;
}
ZADATAK 22: Napisati program koji ucitava niz n realnih brojeva n<=20 a ispisuje na standardnom izlazu
elemente niza sortirane u neopadajuem poretku.

NAPOMENA: diskutovanje petlji

int n = 6; KORAK I j
1 0 1
for (i = 0, j = i+1; i< n-1; i++, j++) 2 1 2
3 2 3
4 3 4
5 4 5
6 5(i<n-1 = false) 6

int n = 6; KORAK I j
1 0 1
for (i = 0; i< n-1; i++) 2 0 2
for (j = i+1; j<n; j++) 3 0 3
4 0 4
j uvek vece od i 5 0 5
6 0 6 (j<6 = false)
zavrsi se cela unutrasnja petlja (j) pa se tek 7 1 2
8 1 3
onda spoljna (i) uveca za 1
9 1 4
10 1 5
11 1 6 (j<6 = false)
12 2 3
13 2 4
14 2 5
15 2 6 (j<6 = false)
16 3 4
17 3 5
18 3 6 (j<6 = false)
19 4 5
20 4 6 (j<6 = false)
21 5 6 (j<6 = false)

6
#include <stdio.h>
#include <stdlib.h>
#define DIM 20
void unos(int a[], int n){
int i;
printf ("Unesite clanove niza: \n");
for (i=0; i<n; i++){
printf(\n a[%d]=, i);
scanf ("%d", &a[i]);
}
}
void ispis (int a[], int n){
inti;
for (i=0;i<n;i++)
printf(%d, ,a[i]);
}
main (){
int a[DIM], max;
int i, j, n, tmp;

// provera dimenzije niza


do{
printf("\nDuzina niza (najvise %d)je: ", DIM);
scanf("%d", &n);
}while (n<=0 || n>DIM);
unos(a, n); // unos preko funkcije
// sortiranje elemenata niza void sort(int a[], int n){ // pre main-a
// I uvek levo od J jer J krece od I+1 int i, j, tmp;
for (i=0; i<n-1 i++)
for (i=0; i<n-1; i++) for (j=i+1; j<n; j++)
for (j=i+1;j<n; j++) if(a[i] > a[j]){
if(a[i] > a[j]){ tmp = a[i];
tmp = a[i]; a[i] = a[j];
a[i] = a[j]; a[j] = tmp;
a[j] = tmp; }
} } // treba je pozvati u main-u
ispis(a,n); // ispis preko funkcije
return 0;
}

ZADATAK 23: Napisati program koji uitava 2 niza od n elemenata n<=20 a ispisuje na standardnom
izlazu skalarni proizvod odgovarajuih lanova datih nizova.
#include <stdio.h>
#include <stdlib.h>
#define DIM 20

7
void unos(int a[], int n){
int i;
printf ("Unesite clanove niza: \n");
for (i=0; i<n; i++){
printf(\n a[%d]=, i);
scanf ("%d", &a[i]);
}
}
main (){
int a[DIM], b[DIM], sp=0;
int i, n;

printf("Uneti broj clanova niza (najvise je %d): ", DIM);


scanf("%d", &n);

unos(a, n);
unos(b, n);

for(i=0; i<n; i++)


sp+=a[i]*b[i];

printf("Skalarni proizvod je: %d", sp);


return 0;
}

ZADATAK 24: Napisati C program koji formira niz A[8] od celih brojeva koji se uitavaju jedan po jedan sa
tastature. Program treba da sve elmente niza A koji su izmedju 5 I 10 a nalaze se na neparnim pozicijama prekopira
u niz B.

#include <stdio.h>
#include <stdlib.h>
#define DIM 20
main (){
int n, a[DIM], b[DIM], i, k;

printf("\nDuzina niza (max %d): ", DIM);


scanf("%d", &n);

printf("\nPocetni niz:\n");
for(i=0; i<n; i++){
printf("\na[%d]=", i);
scanf("%d", &a[i]);
}

k = 0; // na pocetku nema prebacenih elemenata


for(i=0; i<n; i++)
if(a[i]>5 && a[i]<10 && i%2==1)
b[k++] = a[i]; // po prebacivanju se k uvecava za 1 (k++)

printf("\nElementi niza B su:\n");

8
for(i=0; i<k; i++) // dimenzija niza B je K
printf("%d ", b[i]);
}

DOPUNA: funkcija prebaci


int prebaci(int a[], int n, int b[]){ // vraca broj prebacenih elemenata, to ce biti i dimenzija niza B
k = 0; // na pocetku nema prebacenih elemenata
for(i=0; i<n; i++) // proci kroz sve elemente niza
if(a[i]>5 && a[i]<10 && i%2==1) // pitati
b[k++] = a[i]; // po prebacivanju se k uvecava za 1
return k;
}

9
VEBE 06

NASTAVAK NIZOVI

ZADATAK 25: Napisati program koji uitava niz od n elemenata n<=20 i cele brojeve K i X a
ispisuje niz koji nastaje kada se na K-to mesto datog niza umetne broj X.

#include <stdio.h>
#include <stdlib.h>
#define DIM 20
main (){
int a[DIM],k ,x;
int i, n;

printf("\nDuzina niza (najvise %d)je: ", DIM);


scanf("%d", &n);

printf("Uneti elemente niza: ");


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

printf("Unesi dva cela broja: ");


scanf("%d %d", &k, &x);

k--; /*smanjivanje za 1 jer indeks niza krece od nule*/


for(i=n-1; i>=k; i--) /*Pomeranie elemenata niza u desno za jedno mesto da bi se
ubacio X*/
a[i+1]=a[i];
a[k] = x; /*ubacivanje elementa u niz*/

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


printf(" %d", a[i]);

return 0;
}

ZADATAK 25 :a: Napisati program koji uitava niz od n elemenata n<=20 i ceo broj K. Iz niza
treba izbaciti element na K-toj poziciji i prikazati dobijeni niz.

k--; /*smanjivanje za 1 jer indeks niza krece od nule*/


for(i=k+1; i<n; i++) /*Pomeranie elemenata niza u levo za jedno mesto da bi se izbacio a[k]*/
a[i-1] = a[i];
n--; /*smanjivanje dimenzije niza za 1 jer smo izbacili jedan element.
NAPOMENA: poslednji element u nizu a[n-1] i dalje postoji
*/

1
ZADATAK 26: Napisati program koji uitava niz od n elemenata n<=50, obre ga i ispisuje
novodobijeni niz na standardnom izlazu.

#include <stdio.h>
#include <stdlib.h>
#define DIM 50
main(){

int a[DIM], n, i, j;
printf("\nDuzina niza (max %d): ", DIM);
scanf("%d", &n);
if(n <= 0 || n > DIM) exit(1);

printf("Uneti elemente niza: ");


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

for(i=0,j=n-1; i<j; i++,j--){ // ici do pola niza i menjati prvi sa poslednjim


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

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

printf("\n");
}

ZADATAK 27: Napisati program koji stvara i ispisuje sluajan celobrojni niz zadate duine koji
se sastoji od jednocifrenih decimalnih brojeva, izvri ureivanje niza po neopadajuem redosledu
vrednosti brojeva i ispisuje rezultujui niz.

#include <stdio.h>
#include <stdlib.h>
#define DIM 500

main (){
int n, a[DIM], i, j;

printf("\nRAND_MAX = %d, RAND= %d", RAND_MAX, rand());


//ispis u konzoli: RAND_MAX = 32767, RAND= 41 (bilo koja vrednosti od 0 do MAX)

printf("\nDuzina niza (max %d): ", DIM);


scanf("%d", &n);

2
printf("\nPocetni niz:\n\n");
for(i=0; i<n; i++)
a[i] = rand() / ((double)RAND_MAX + 1) * 10;

/*Sortiranje niza*/
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(a[i] > a[j]){
int b = a[i];
a[i] = a[j];
a[j] = b;
}

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

return 0;
}
VEZBA : NAPRAVITI LOTO IZVLACENJE (6 od 39, da se ne ponavljaju)
A[i]=(rand()%39)+1

ZADATAK 28: Napisati C program koji formira niz C[8] od celih brojeva koji se uitavaju
jedan po jedan sa tastature. Program treba da nae sumu svih parnih elemenata DO PRVE
NULE U NIZU.

#include <stdio.h>

int main(){
int C[8];
int i, s;

printf ("\nUneti elemente niza ! \n");


for(i=0; i<8; i++){
printf("\nC[%d]= ",i);
scanf("%d", &C[i]);
}
// umesto for koristiti while
i=0;
s=0;
while(i<8 && a[i]!=0){
if (a[i]%2==0) //ovde se moze resavati bilo koja problematika
s += a[i]; //koja ide dok je neki uslov tacan a ne do kraja niza

i++;
}

3
printf("Suma = %d \n", s);

return 0;
}
ZADATAK 29: Iz niza a u niz B prebaciti sve PROSTE brojeve koji se nalaze ISPRED
PRVOG PARNOG BROJA U NIZU.

#include <stdio.h>
#include <stdlib.h>
#define DIM 20

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


int i;
printf ("Unesite clanove niza: \n");
for (i=0; i<n; i++){
printf("\n a[%d]=", i);
scanf ("%d", &a[i]);
}
}
void ispis(int a[], int n){
int i;
printf("\n Elemenni niza su :\n");
for(i=0; i<n; i++)
printf("%d ", a[i]);
}

int prost(int n){


int i;
for(i=2; i<=sqrt(n); i++)
if(n%i==0) // ako je n deljivo sa bilo kojim i
return 0; // vrati 0, nije prost
return 1; // ako se to nikad ne desi, vrati 1, jeste prost
}

int prebaci(int a[], int n, int b[]){


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

while(i<n && a[i]%2!=0){ // do provog parnog elementa = dok nisu parni


if(prost(a[i])) // ako je a[i] prost => prebaciti ga u niz b
b[k++] = a[i];
i++;
}
return k;
}

4
main (){
int a[DIM], b[DIM];
int i, n;

printf("Uneti broj clanova niza ");


scanf("%d", &n);

unos(a, n);

int k;
k= prebaci(a,n,b);

ispis(b,k);

return 0;
}

5
VEBE 07
MATRICE

Matrice predstavljaju dvodimenzionalne nizove (nizove nizova) koje pored stadardnih nizova karakterie i jo
jedna dimenzija. Definicija matrica izvava se u sledeem formatu:
TIP naziv_matrice [BR_VRSTA][BR_KOLONA]
gde su BR_VRSTA i BR_KOLONA maksimalno dozvoljene dimenzije koje se mogu koristiti u programu za rad.
Anotacija je ista kao i kod nizova i kree od 0. Kvadratne matrice ( BR_VRSTA = BR_KOLONA ) imaju dve
dijagonale, glavnu i sporednu.

VRSTE => for(i=0; i<n; i++)//po vrsti Dve petlje za matricu.


Prvo se izmenjaju svi elementi unutrasnje petlje, pa
KOLONE =>

for(j=0; j<n; j++)


A00 A01 A02 .. se tek onda uvea iterator spoljasnje petlje za 1 tj.:
for(j=0; j<n; j++)//po koloni A00, A01, A02, i fiksno, uveava se j
A10 A11 A12 for(i=0; i<n; i++) A10, A11, A12 uvea se i,ponovo se uveava j
A[i][j] vrednost elementa u vrsti i i koloni j
A20 A21 A22 Elementi u istoj vrsti imaju isto i a elementi u istoj koloni imaju isto j

ZADATAK 29. Napisati program za sabiranje matrica a i b dimenzije n i tampanje rezultujue matrice c.

#include <stdio.h> int main(){


void unos(int
unos a[][10],int n, int m){ int a[10][10], b[10][10], c[10][10];
int i, j; int n, m;
for(i=0; i<n; i++)
for(j=0; j<m; j++){ printf("Uneti broj vrsta i kolona\n");
printf("\n a[%d][%d]=", i,j); scanf("%d %d", &n, &m);
scanf("%d", &a[i][j]);
} printf("Uneti elemente matrice a\n");
} unos(a, n, m);

void ispis(int
ispis a[][10],int n, int m){ printf("Uneti elemente matrice b\n");
int i,j; unos(b, n, m);
for(i=0; i<n; i++){
for(j=0; j<m; j++) printf("Zbir matrica a i b je:\n");
printf("%d\t", a[i][j]); zbir(a, b, c, n, m);
printf("\n");
} ispis(c, n, m);
} return 0;
}
void zbir(int a[][10], int b[][10], int c[][10], int n, int m){
int i, j;
for(i=0; i<n; i++){
for(j=0; j<m; j++){
c[i][j] = a[i][j] + b[i][j];
}
}
}

1
ZADATAK 29. Napisati C program koji uitava jedan po jedan realan broj i formira matricu A[5][5]. Zatim
program treba da odredi sumu svih elemenata prve kolone i sumu druge vrste ove matrice i da ispita koja je suma
vea. Zatim odtampati poruku o tome koja je suma vea.

#include <stdio.h>
int main(){
float a[5][5];
int i,j;
float spk, sdv;

printf("Uneti elemente matrice A\n");


for(i=0;i<5;i++)
for(j=0; j<5; j++)
scanf("%f",&a[i][j]);

spk=0.0;
for(i=0; i<5; i++) // i se menja a j = 0 (fiksno pa ne treba petlja)
spk+=a[i][0];
sdv=0.0;
for(j=0; j<5; j++) // j se menja a i = 1 (fiksno pa ne treba petlja)
sdv+=a[1][j];
printf("Suma elemenata prve kolone je: %f\n\n", spk);
printf("Suma elemenata druge kolone je: %f\n\n", sdv);

if (spk > sdv)


printf("Veca je suma prve kolone i iznosi: %f\n\n",spk);
else if (sdv > spk)
printf("Veca je suma druge vrste i iznosi: %f\n\n",sdv);
else
printf("Sume kolona su iste i iznose %f",spk);
return 0;
}

2
ZADATAK 30. Napisati C program koji uitava jedan po jedan realan broj i formira matricu A[7][5]. Program
treba da izrauna u kojoj koloni je najmanji element (pretpostavka da ima samo jedan najmanji element u celoj
matrici), da odtampa tu najmanju vrednost i da odtampa tu kolonu.

#include <stdio.h>
int main(){
float a[7][5];
int i, j, k, v;

printf("Uneti elemente matrice A\n");


for(i=0; i<7; i++)
for(j=0; j<5; j++)
scanf("%f", &a[i][j]);

float min=a[0][0];
v=0;
k=0;
for(i=0; i<7; i++)
for(j=0; j<5; j++)
if(min>a[i][j]) {
min=a[i][j];
v=i;
k=j;
}

printf("Minimalni element je %f a nalazi se u koloni %d i vrsti %d \n", min, k, v);

printf("Izgled kolone %d ",k);


for (i=0;i<7;i++) // i se menja a j = k (fiksno pa ne treba petlja)
printf("%f ",a[i][k]);
printf("\n");

printf("Ispis matrice \n ");


for (i=0; i<7; i++){
for (j=0; j<5; j++)
printf("%f ", a[i][j]);
printf("\n");
}
return 0;
}

Primer: vise vrsta ili kolona odjednom


for(i=0; i<n; i++) //proci kroz matricu
for(j=0; j<m; j++)
if (i ==1 || i==3) //odbrati samo potrebne vrste ili kolone

3
ZADATAK 31. Napisati program kojim se za random generisanu matricu sumu elemenata i-te vrste upisuje na i-tu
poziciju niza b, a srednja vrednost pozitivnih elemenata i-te kolone se upisuje na i-tu pozciju niza c.
#include <stdio.h>
A00 A01 A02 B0
#include <math.h> A10 A11
A11 A12 B1
#define DIM 20
void ispisMat (int a[][DIM], int n, int m){ C0 C1 C2
printf ("Elementi matrice su \n");
for (int i =0;i<n;i++){
for (int j=0;j<m;j++)
printf("%d\t", a[i][j]);
printf("\n"); for(i=0; i<m; i++){ //po vrstama
} s=0;
} for(j=0; j<n; j++)
s+=a[i][j];
void ispisNiz (int a[], int n){
b[i]=s;
printf ("Elementi niza su \n");
}
for (int i =0;i<n;i++)
printf("%d\t",a[i]);
for(j=0; j<n; j++){ //po kolonama
printf("\n");
sr=0;
}
br=0;
for(i=0; i<m; i++)
int main(){
if (a[i][j]>0){
int a[DIM][DIM], int b[DIM], int c[DIM];
sr+=a[i][j];
int i, j, m, n, s, sr, br;
br++;
}
printf("Uneti dimenzije matrice A\n");
c[j]=sr/br;
scanf(%d %d, &m, &n);
}
// unos elemenata pomocu rand
ispisNiz(b,m);
for(i=0; i<m; i++)
ispisNiz(c,n);
for(j=0; j<n; j++)
a[i][j]=rand();
ispisMat(a,n,m);
return 0;
}

4
ZADATAK 32. Napisati program kojim se nakon to se unesu elementi matrice unose i indeksi dve vrste iji
elementi treba da se zamene.

#include<stdio.h> void zamena(int a[][5], int m, int v1, int v2){


int j, pom;
void unos(int a[][5], int n, int m){ for(j=0; j<m; j++){ // po kolonama
int i, j; pom = a[v1][j];
for(i=0;i<n;i++) a[v1][j] = a[v2][j];
for(j=0;j<m;j++){ a[v2][j] = pom;
printf("a[%d][%d]= ", i, j); }
scanf("%d", &a[i][j]); }
} int main(){
} int a[5][5], n, m, v1, v2;
printf("Unesi dimenziju matrice: \n");
void ispis(int a[][5], int n, int m){ scanf("%d%d", &n, &m);
int i,j; unos(a, n, m);
for(i=0; i<n; i++){ printf("Unesi dve vrste koje menjas: \n");
for(j=0; j<m; j++) scanf("%d%d", &v1, &v2);
printf("%d\t", a[i][j]); zamena(a, m, v1, v2);
printf("\n"); ispis(a, n, m);
} return 0;
} }
VEBA: Prebaciti proste brojeve iz matrice a u niz b.
#include <stdio.h> #include <stdlib.h> int prebaci(int a[][10], int n, int m, int b[]){
#define DIM 20 int i,j,k;
void unos (int a[][10], int n, int m){
int i, j; k=0;
printf("Uneti elemente matrice\n"); for(i=0;i<n;i++)
for(i=0;i<n;i++) for(j=0;j<m;j++)
for(j=0;j<m;j++){ if(prost(a[i][j]))
printf("a[%d][%d]=", i,j); b[k++] = a[i][j];
scanf("%d", &a[i][j]); return k;
} }
} void ispisNiz (int a[], int n){a
void ispis (int a[][10], int n, int m){ int i;
int i, j; printf("element niza su\n");
printf("element matrice su\n"); for(i=0;i<n;i++)
for(i=0;i<n;i++){ printf("%d\t", a[i]);
for(j=0;j<m;j++) }
printf("%d\t", a[i][j]); main (){
printf("\n"); int a[10][10],n,m, k, b[100];
}
} printf("Uneti dimenizje\n");
int prost(int n){ scanf("%d%d",&n,&m);
int i; unos(a,n,m);
for(i=2;i<=sqrt(n);i++)
if(n%i==0) ispis(a,n,m);
return 0; k = prebaci(a,n,m,b);
return 1; ispisNiz(b, k);
} }

5
VEBE 08
MATRICE - DIJAGONALE

VRSTE =>
GLAVNA DIJAGONALA SPOREDNA DIJAGONALA
KOLONE =>

A00 A01 A02 1. Na ( i == j), max = a[0][0] 1. Na ( i + j == n-1 ) , max = a[0][n-1]


2. Iznad ( i < j ) , max = a[0][1] 2. Iznad ( i + j < n-1 ) , max = a[0][0]
A10 A11 A12 3. Ispod ( i > j ) , max = a[1][0] 3. Ispod ( i + j > n-1 ) , max = a[1][n-1]
Pozicionirati se na pravi deo matrice sa dve for petlje i sa jednim if uslovom od
A20 A21 A22 prethodnih 6 ili nekom njihovom kombinacijom.

ZADATAK 32: Napisati program koji uitava n (vrsta) i m (kolona) matrice a potom uitava elemente matrice,
ispisuje zbir elemenata na glavnoj i sporednoj dijagonali te matrice.
#include <stdio.h>
#include <stdlib.h>
#define N 5

void unos (int a[][4], int n){


int i,j;
printf ("Uneti elemente matrice\n");
for (i=0; i<n; i++){
for (j=0; j<n; j++){
printf("a[%d][%d]= ", i, j);
scanf ("%d", &a[i][j]);
}
}
}

void ispis (int a[][4], int n){


int i,j;
printf ("Elementi matrice su \n");
for (i =0; i<n; i++){
for (j=0; j<n; j++)
printf("%d\t", a[i][j]);
printf("\n");
}
}
main (){
int a[N][N];
int i, j, m, n, glavnadija, sporedna;
printf("Unesi dimenziju matrice \n");
scanf("%d%d", &n, &m);
unos(a, n, m);
glavnadija=0;
sporedna=0;
//prvi nacin //drugi EFIKASNIJI nacin
for (i=0; i<n; i++)
for (j=0; j<m; j++) for (i=0; i<n; i++)
if(i==j) glavnadija+=a[i][i];
glavnadija+=a[i][j];
//prvi nacin //drugi EFIKASNIJI nacin
for (i=0; i<n; i++) for(i=0, j=n-1; i<n; i++, j--)
for (j=0; j<m; j++) sporedna+=a[i][j];
if(i+j==n-1)
sporedna +=a[i][j];

printf("Zbir na glavnoj dijagonali je: %d\nZbir na sporednoj dijagonali je: %d\n", glavnadija, sporedna);
}

ZADATAK 33: Napisati program kojim se uitava matrica nxm. Nai aritmetiku sredinu svih elemenata matrice,
nai maksimalni element ISPOD sporedne dijagonale matrice, aritmetiku sredinu elemenata na sporednoj
dijagonali i najmanji element na glavnoj dijagonali.
#include <stdio.h> main (){
#include <stdlib.h>
#define N 5 int a[N][N], max, min;
void unos (int a[][4], int n){ } int i, j, n, zbir, sp;
void ispis (int a[][4], int n){ }
int maxis (int a[][4], int n){ printf("Unesi dimenzije matrice ");
/* max ispod sporedne dijagonale*/ scanf("%d %d", &n);
/*vazno je postaviti max na prvi iz skupa u kojem
se trazi maksimalni*/ unos(a, n);
int i, j,, max=a[1][n-
max=a[1][n-1]; ispis(a, n);

for(i=0; i<m; i++) zbir=0; // zbir svih elemenata


for(j=0; j<n; j++) for (i =0; i<n; i++)
if( i+j > n-1) for (j=0; j<n; j++)
if ( a[i][j] > max) zbir += a[i][j];
max = a[i][j]; printf("Ar. sr. je: %.2lf", zbir/(double)(m*n));
return max;
max
}
int mingd (int a[][4], int n){ printf("\nMAX ispod SD = %d\n", maxis
maxis(a,n));
is
//minimalni na glavnoj dijagonali
int min = a[0][0], i, j; printf("MIN na GD = %d\n", mingd(a,n);
mingd
//kraci i efikasniji nacin
for(i=0; i<n; i++) printf("Ar. sr. na sp = %.2lf\n", arsd(a,n);
arsd
if(a[i][i]<min)
min = a[i][i];
return min; return 0;
} }
double arsd (int a[][4], int n){
//aritmeticka sredina na sporednoj dijagonali
int i, j;
double sp = 0;
for(i=0; i<m; i++)
for(j=0; j<n; j++)
if( i+j == n-1)
sp += a[i][j];
return sp/n;
}
ZADATAK 34: Napisati program koji u kvadratnoj matrici vrsi izdvajanje elemenata ispod glavne dijagonale
ukljuujui i elemente na glavnoj dijagonali u niz B. Ispisati novo dobijeni niz.

#include <stdio.h>
#include <stdlib.h>
#define N 20

main (){
int a[N][N], b[N];
int i, j, n, k;
printf("Unesi dimenziju matrice \n");
scanf("%d", &n);

printf("Unesi elemente matrice \n");


for(i=0; i<n; i++)
for(j=0; j<n; j++){
printf("Element a[%d][%d] = ", i, j);
scanf("%d", &a[i][j]);
}

//premestanje elemenata u niz B


k=0; //indeks prvog elementa u nizu B, na kraju dimenzija niza B
for(i=0; i<n; i++)
for(j=0; j<n; j++)
if(i>j || i==j) // || za uniju a && za presek
b[k++] = a[i][j];
printf ("Elementi matrice su \n");
for (i=0; i<n; i++){
for (j=0; j<n; j++)
printf("%d\t", a[i][j]);
printf("\n");
}

printf("Elementi niza su\n");


for(i=0; i<k; i++)
printf("%d, ",b[i]);
return 0;
}

ZADATAK 32: Napisati funkcije za transponovanje matrice a dimenzije n I kreiranje jedinicne matrice.
void transponovanje(int a[][DIM], int n){ void jedinicna(int a[][DIM],int n ){
for(i = 0; i < n; i++) int i,j;
for(j = i; j < n; j++) { for(i=0;i<n;i++)
int p = a[i][j]; for(j=0;j<n;j++)
a[i][j] = a[j][i]; if (i==j)
a[j][i] = p; a[i][j]=1;
} else
} a[i][j]=0;
}

3
4
VEBE 09
STRINGOVI ( nizovi karaktera )

Nizovi karaktera su jednodimenzionalni nizovi tipa char.

U standardnom zaglavlju stdio.h definisane su sledee funkcije:


a = getchar() - ita sledei znak, ukljuujui i bele znakove, i simboliku konstantu EOF (end of file)
ukoliko je proitan signal za kraj datoteke kao i u sluaju greke u toku itanja.
putchar(c) - funkcija za ispisivanje znaka c na ekranu.
gets(s) - funkcija za itanje jednog reda teksta i smetanje u string s
puts(s) - funkcija za ispisivanja jednog reda teksta
a = getc(c) - itanje jednog karaktera sa ulaza c, to moe biti stdin (tastatura) ili neki fajl
putc(c, izlaz) - ispis karaktera C na izlaz, to moe biti stdout (tastatura) ili neki fajl
stdin - standardni ulazni tok
stdout - standardni izlazni tok
stderr - standardne greke
EOF - end of file
sprintf(s,format, arg1,...)-tampanje u string s
sscanf(s,format, &ime1,...)-unos iz stringa s

U standardnom zaglavlju string.h definisane su sledee funkcije:


n = strlen(s) - vraa duzinu s-a.
strcpy(s, c) - kopira niz c u niz s.
strncpy(s, c,n) - kopira niz c u niz s prvih n karaktera.
strcat(s, c) - povezuje niz karaktera c iza niza s
strncat(s, c, n) - povezuje niz karaktera c iza niza s poevi od n-tog karaktera
strcmp(s, st) - uporeuje niz s sa nizom st; vraa <0 za s<st, 0 za s=st ili >0 ako je s>st.
srtncmp(s, c, n) - uporeuje prvih n karaktera niza s sa nizom c
strchr(s, c) - pokaziva na prvi karakter niza c u nizu s
strrchr(s, c) - pokaziva na poslednji karakter niza c u nizu s
strstr(s, c) vraa pokaziva na prvo pojavljivanje stringa c u stringu s
strtok(s, c) razbija string s na tokene sa delimiterom c
memcpy(s, c, n) - kopira n karaktera iz niza c u niz s
memmove(s, c, n) - kopira n karaktera iz niza c u niz s sa mogunou preklapanja
memchr(s, c, n) - pozakizva na prvi c u privih n karaktera u nizu s
memset(s, c, n) - smeta c u prvih n karaktera niza s

U standardnom zaglavlju ctype.h definisane su sledee funkcije:


isalnum(c) - ispituje da li je c alfanumeriki karakter
isalpha(c) - ispituje da li je c alfabetski karakter
iscntrl(c) - ispituje da li je c kontrolni karakter
isdigit(c) - ispituje da li je c cifra
isgraph(c) - ispituje da li je c tampani karakter (ne ukljuuje prazninu)
islower(c) - ispituje da li je c malo slovo
isupper(c) - ispituje da li je c veliko slovo
isspace(c) - ispituje da li je c praznina, formfeed, nova linija, vertikalni, horizontalni karaker
isprint(c) - ispituje da li je c karakter (samo da nije praznina)
ispunct (c) - ispituje da li je c izuzimajui praznine, slovo ili broj
isxdigit(c) - ispituje da li je c heksadecimalni broj
tolower(c) - pretvara c u malo slovo
toupper(c) - pretvara c u veliko slovo

1
ZADATAK 58. Napisati program koji uitava jedan znak sa tastature i proverava da li je slovo ili cifra.

#include <stdio.h> #include <stdio.h>


void main(){ #include <ctype
ctype.h>
ctype
char a; void main(){
printf("Unesi jedan znak: "); char a;
scanf(%c, &a); printf("Unesi jedan znak: ");
a = getchar();
getchar
if(a>='0' && a<='9') if(isdigit
isdigit(a))
isdigit
printf("Znak %c je cifra!\n", a); printf("Znak %c je cifra!\n", a);
else else
printf("Znak %c nije cifra!\n", a); printf("Znak %c nije cifra!\n", a);
if((a>='a' && a<='z') || (a>='A' && a<='Z')) if(isalpha
isalpha(a))
isalpha
printf("Znak %c je slovo!\n", a); printf("Znak %c je slovo!\n", a);
else else
printf ("Znak %c nije slovo!\n", a); printf("Znak %c nije slovo!\n", a);
} }

ZADATAK 59: Napisati program koji uitava jedan znak i ispituje li je on malo slovo, veliko slovo,
samoglasnik ili suglasnik.
#include <stdio.h>
#include <ctype.h>
void main (){
char a, b;
printf("Unesi jedan znak: ");
a = getchar();
getchar
if(isalpha(a)) {
if(isupper
isupper(a))
isupper
printf("Znak %c je veliko slovo!\n", a);
else if(islower
islower(a))
islower
printf("Znak %c je malo slovo!\n", a);
b = tolower(a);
tolower
if(b=='a' || b=='e' || b=='i' || b=='o' || b=='u')
printf("Znak %c je samoglasnik!\n", a);
else printf("Znak %c je suglasnik!\n", a);
}
}
ZADATAK 60 : Napisati program koji uitava string (niz karaktera) ne dui od 40 karaktera. Ispisati
koliko ima karaktera (tj. koliko je dugaak string), cifara, slova i praznih mesta u tom stringu.

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define DIM 40
void main (){
char a[DIM];
int n, i=0, s=0, c=0, b=0;
printf("Unesi string ne duzi od 40 karaktera: ");
gets(a);
gets
n = strlen(a);
strlen

2
printf("U nizu '%s' ima %d karaktera!\n", a, n);
for(i=0; i<n; i++) {
if(isalpha
isalpha(a[i]))
isalpha
s++;
else if(isdigit
isdigit(a[i]))
isdigit
c++;
else if(isspace
isspace(a[i]))
isspace
b++;
}
printf("U nizu '%s' ima %d slova, %d cifara i %d praznih mesta!\n", a, s, c, b);
}

ZADATAK 61: Napisati program koji uitava string (niz karaktera) ne dui od 80 karaktera. Ispisati isti
string samo sva mala slova u njemu zameniti velikim.

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define DIM 80
int main (){
char a[DIM];
int i = 0;
printf("Unesi string ne duzi od %d: ", DIM);
gets(a);
gets

for(i=0; i< strlen(a);


strlen i++)
a[i] = toupper(a[i]);
toupper

printf("Posle izmene string je: '%s'!\n", a);

return 0;
}

ZADATAK 62: Napisati program koji uitava string (niz karaktera) ne dui od 80 karaktera i jo jedan
karakter. Ispisati string koji nastaje izbacivanjem uitanog karaktera.

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define DIM 80
void main (){
char a[DIM], b;
int i=0;
printf("Unesi string ne duzi od %d znakova: ", DIM);
gets(a);
gets
printf("Unesi znak koji treba izbaciti iz stringa: ");

3
b = getchar();
getchar
for(i=0; i< strlen(a);
strlen i++) {
if(a[i] != b)
putchar(a[i]);
putchar
}
putchar('\n');
}

Mnogo taniji nain sa promenom dimenzije niza


#include <stdio.h> for(i=0; i< strlen(a);
strlen i++) {
#include <ctype.h> if(a[i] != b){
#include <string.h> a[k] = a[i];
#define DIM 80 k++;
}
int main (){ }
char a[DIM], b,k = 0;
unsigned int i = 0; a[k] = '\
'\0';//obavezno
0';//obavezno zatvoriti string

printf("Unesi string \n); printf("Duzina novog stringa je %d \n",


gets(a); strlen(a));

printf("Duzina stringa je %d \n", strlen(a)); printf("Novi string je \n\n");


puts(a);
printf("Unesi znak koji treba izbaciti: \n");
b = getchar(); printf("\n");
return 0;
}

ZADATAK 63. Prikazivanje tablice ASCII kodova sa po 19 znakova u jednoj koloni.

#include<stdio.h>
int main() {
char c;
int i;
printf("\t\t Tablica ASCII kodova\n\n");
for(c=' ';c<' '+19;++c){
for(i=0;i<95;i+=19)
printf("%3d %c ",c+i,c+i);
putchar('\n');
}
return 0;
}
// moze I prostije
// for(i=0;i<127;i++)
// printf("%d = %c ", i, i);

4
VEBE 10
STRUKTURE

Struktura je skup jedne ili vie promenljivih, koje mogu biti razliitih tipova, grupisanh zajedno radi lake
manipulacije. Strukture pomau pri organizaciji kompleksnih podataka, posebno u velikim programima, jer one
omoguuju obradu grupe meusobno povezanih promeljivi kao jedne cjeline. Primer strukture Tacka vidi se na
slici. Taka je definirana ureenim parom koordinata, pravougaonik se moe definisati parom taaka i sl.

Te dve komponente mogu se smestiti u strukturu koja je ovako deklarisana


struct IME_STRUKTURE{ struct Tacka {
tip IME_CLANA1; int x;
tip IME_CLANA2; int y;
}; };
typedef struct Tacka TACKA;
//dalje umesto struct Tacka => TACKA
struct Tacka A; //deklaracija promenljive
TACKA A; //ako je koriscen typedef struct Tacka TACKA;

typedef komandom se definie da se u daljem delu koda umesto struct Tacka koristi skraeno TACKA kao i bilo
koji drugi standardan tip promenljive.
lanu odreene strukture pristupa se sledeim izrazom
IME_STRUKTURE. IME_ CLANA // pristup preko operatora .
Operatorom "." povezujemo ime strukture i ime lana. Ispis koordinata za sturkturu TACKA A, npr.,
printf("%d, %d", A.x, A.y);

Takoe mogua je kombinacija typedef i deklaracije structure u jednom koraku kao u sledeem primeru:

typedef struct Tacka{


double x, y;
}TACKA;

main(){
TACKA t1, t2, t3;
}

Strukture moemo ugnjezditi. Pravougaonik moemo predstaviti parom taaka koje oznaavaju dijagonalno
suprotne take.
typedef struct rect{
struct point pt1;
struct point pt2;
}RECT;
main{
rect a;
printf(%d, a.p1.x)
}
//ispisuje X koordinatu tacke p1 pravougaonika a

1
ZADATAK 64: Definisati strukturu za teme trougla a zatim izracunati povrsinu trougla ako su date koordinate
temena trougla.

#include <stdio.h>
#include <math.h>

struct Tacka{
double x, y;
};

typedef struct Tacka TACKA;

main(){
TACKA t1, t2, t3;
double povrsina, a, b, c, s;
printf("Unesi kordinate prve tacke: ");
scanf("%lf %lf", &t1.x, &t1.y);
printf("Unesi kordinate druge tacke: ");
scanf("%lf %lf", &t2.x, &t2.y);
printf("Unesi kordinate trece tacke: ");
scanf("%lf %lf", &t3.x, &t3.y);
a=sqrt(pow(t1.x-t2.x,2)+pow(t1.y-t2.y,2));
b=sqrt(pow(t1.x-t3.x,2)+pow(t1.y-t3.y,2));
c=sqrt(pow(t2.x-t3.x,2)+pow(t2.y-t3.y,2));
s=(a+b+c)/2;
povrsina=sqrt(s*(s-a)*(s-b)*(s-c));
printf("Povrsina trougla je: %.2lf!\n", povrsina);
}

ZADATAK 65: Definisati strukturu za rad sa kompleksnim brojevima a potom napisati program koji ucitava 2
kompleksna broja a prikazuje njihov zbir, razliku, proizvod, kolicnik, moduo prvog i konjugovano kompleksan
drugom. VEZBA

#include <stdio.h>
#include <math.h>

struct Kb{
double x, y;
};

main(){
struct Kb z1, z2, zbir, razlika, pr, ko, kk;
double mo;
printf("Unesi prvi kompleksan broj: ");
scanf("%lf %lf", &z1.x, &z1.y);
printf("Unesi drugi kompleksan broj: ");
scanf("%lf %lf", &z2.x, &z2.y);
zbir.x=z1.x+z2.x;
zbir.y=z1.y+z2.y;

2
razlika.x=z1.x-z2.x;
razlika.y=z1.y-z2.y;
pr.x=z1.x*z2.x-z1.y*z2.y;
pr.y=z1.y*z2.x+z1.x*z2.y;
ko.x=(z1.x*z2.x+z1.y*z2.y)/(pow(z2.x, 2)+pow(z2.y, 2)) ;
ko.y=(z1.y*z2.x-z1.x*z2.y)/(pow(z2.x, 2)+pow(z2.y, 2)) ;
mo=sqrt(pow(z1.x, 2)+pow(z1.y, 2));
kk.x=z2.x;
kk.y=-z2.y;
printf("Zbir je (%.2lf,%.2lf)\nRazlika je (%.2lf,%.2lf)\n", zbir.x, zbir.y, razlika.x, razlika.y);
printf("Proizvod je (%.2lf,%.2lf)\nKolicnik je (%.2lf,%.2lf)\n", pr.x, pr.y, ko.x, ko.y);
printf("Moduo prvog broja je: %.2lf\nKonjugovano kompleksan sa drugim je (%.2lf,%.2lf)\n", mo, kk.x,
kk.y);
}

ZADATAK 66: Deklarisati strukturu za rad sa razlomcima a potom napisati program koji ucitava 3 razlomka a, b,
c i prikazuje razlomak a2-b/c. VEZBA

#include <stdio.h>
#include <math.h>

struct Razlomak{
int br, im;
};

main() {
struct Razlomak a, b, c, d, e, f;
printf("Unesi brojilac i imenilac prvog razlomka: ");
scanf("%d %d", &a.br, &a.im);
printf("Unesi brojilac i imenilac drugog razlomka: ");
scanf("%d %d", &b.br, &b.im);
printf("Unesi brojilac i imenilac treceg razlomka: ");
scanf("%d %d", &c.br, &c.im);
d.br=pow(a.br, 2);
d.im=pow(a.im, 2);
e.br=b.br*c.im;
e.im=b.im*c.br;
f.br=d.br*e.im-e.br*d.im;
f.im=d.im*e.im;
printf("Rezultat izraza a*a-b/c=%d/%d!\n", f.br, f.im);
}

ZADATAK 67: Deklarisati strukturu tacka a potom strukturu pravougaonik (opisuje se pomocu 2 tacke, gornjeg
levog i donjeg desnog temena), pretpostavlja se da su stranice paralelne koordinatnim osama a potom napisati
program koji ucitava 2 pravougaonika a prikazuje njihove povrsine.

#include <stdio.h>

typedef struct Tacka {


double x, y;

3
}TACKA;

typedef struct Pravougaonik{


TACKA gl, dd;
}PRAVOUGAONIK;

main(){
PRAVOUGAONIK p1, p2;
double p;
printf("Unesi temena prvog pravougaonika: ");
scanf("%lf %lf %lf %lf", &p1.gl.x, &p1.gl.y, &p1.dd.x, &p1.dd.y);
printf("Unesi temena drugog pravougaonika: ");
scanf("%lf %lf %lf %lf", &p2.gl.x, &p2.gl.y, &p2.dd.x, &p2.dd.y);
p=(p1.gl.y-p1.dd.y)*(p1.dd.x-p1.gl.x);

printf("Povrsina prvog pravougaonika je: %.2lf\n", p);


p= (p2.gl.y-p2.dd.y)*(p2.dd.x-p2.gl.x);

printf("Povrsina drugog pravougaonika je: %.2lf\n", p);


}

ZADATAK 68. Napisati program koji za zadato tekue vreme odreuje naredno vreme.
#include<stdio.h>

typedef struct vreme{


int sat;
int minut;
int sekund;
}VREME;

int main(){
VREME tekuce, naredno;

printf("Unesite tekuce vreme?[hh:mm:ss]\n");


scanf("%d:%d:%d",&tekuce.sat,&tekuce.minut,&tekuce.sekund);

naredno = tekuce;

if(++naredno.sekund==60){
naredno.sekund=0;
if(++naredno.minut==60){
naredno.minut=0;
if(++naredno.sat==24)
naredno.sat=0;
}
}

printf("Naredno vreme je %02d:%02d:%02d\n", naredno.sat, naredno.minut, naredno.sekund);


return 0;
}

4
ZADATAK 69. Napisati program koji za dva studenta opisana preko imena, i proseka ispisuje podatke o onom sa
boljim prosekom sa napomenom o duzini imena (strlen).

#include <stdio.h>
#include <string.h>
#define DIM 20

typedef struct Student{


char ime[DIM];
float prosek;
}STUD;

main(){
STUD a, b;

printf("\nUnesite podatke o prvom studentu:\n");

printf("Ime studenta: ");


scanf("%s", a.ime);

printf("Srednja ocena studenta: ");


scanf("%f", &a.prosek);

printf("\nUnesite podatke o drugom studentu:\n");

printf("Ime studenta: ");


scanf("%s", b.ime);

printf("Srednja ocena studenta: ");


scanf("%f", &b.prosek);

if (a.prosek > b.prosek)


printf("PODACI: %s %.2f, duzina imena= %d\n",a.ime, a.prosek, strlen(a.ime));
else if (b.prosek > a.prosek)
printf("PODACI: %s %.2f, duzina imena= %d\n",b.ime, b.prosek, strlen(b.ime));
else
printf ("\n Studenti imaju iste proseke %d\n", a.prosek);

5
VEBE 11
Nastavak struktura

ZADATAK 46. Napisati program za formiranje strukture student sa karakteristikama: Ime, Prezime, broj indeksa,
srednja ocena. Za uneti broj studenata n, sortirati studente prema srednjoj oceni i ispisati na ekranu.

#include <stdio.h>
#define DIM 20

struct Student{
char ime[DIM];
char prezime[DIM];
int br_indeksa;
float sred_ocena;
};

typedef struct Student STUD;

void unos (STUD a[], int n){


int i;
printf("Unesite podatke o studentima:\n\n");

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


printf("Ime studenta: ");
scanf("%s", a[i].ime);
printf("Prezime studenta: ");
scanf("%s", a[i].prezime);
printf("Broj indeksa: ");
scanf("%d", &a[i].br_indeksa);
printf("Srednja ocena studenta: ");
scanf("%f", &a[i].sred_ocena);
}
}

void ispis (STUD a[], int n){


int i;

for(i=0; i<n; i++)


printf("[%d]. %s %s,\t%d,\t%3.2f\n",i+1, a[i].ime, a[i].prezime, a[i].br_indeksa, a[i].sred_ocena);
}
void sort(STUD a[], int n){
int i,j;
STUD pom;

for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
if(a[i].sred_ocena < a[j].sred_ocena) {
pom = a[i];
a[i] = a[j];
a[j] = pom;

1
}
}
main(){
int n, i, j;
STUD a[DIM];
printf("Unesite broj studenata: ");
scanf("%d", &n);

unos(a,n);

sort(a,n);

ispis(a,n);
}

2
ZADATAK 47. Definisati strukturu GRAD sa podacima lanovima: ime, broj stanovnika, prosean dohodak
radnika. Napisati program kojim se unose podaci o gradovima u Srbiji i tampati na ekranu ime grada sa najveim
brojem stanovnika. Izraunati ukupan dohodak svih unetih gradova.

#include <stdio.h>
#define DIM 10
#define N 20

typedef struct Grad{


char ime[N];
int br_stan;
float dohodak;
}GRAD;

main(){
GRAD NizGradova[DIM];
int i, n, max, max_index = 0;
float uk_dohodak = 0.0;
printf("Unesi broj gradova(max %d): ", DIM);
scanf("%d", &n);

printf("Unesi podatke o gradovima:\n");


for(i=0;i<n;i++) {
printf("Ime grada: ");
scanf("%s", NizGradova[i].ime);
printf("Broj stanovnika: ");
scanf("%d", &NizGradova[i].br_stan);
printf("Dohodak grada: ");
scanf("%f", &NizGradova[i].dohodak);

uk_dohodak += NizGradova[i].dohodak;
}

max = NizGradova[0].br_stan;
for(i=0;i<n;i++)
if(NizGradova[i].br_stan > max) {
max = NizGradova[i].br_stan;
max_index = i;
}

printf("Grad sa najvise stanovnika je: %s.\n",NizGradova[max_index].ime);


printf("Ukupan dohodak svih gradova je: %5.3f.\n", uk_dohodak);
}

3
ZADATAK 48. Napisati program koji ispisuje podatke o najskupljem mercedesu iz niza auta opisanih preko
marke i cene.
#include <stdio.h>
#define DIM 20

struct Auto{
char marka[DIM];
int cena;
};

typedef struct Auto AUTO;

void unos (AUTO a[], int n){


int i;
printf("Unesite podatke o automobilima:\n\n");

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


printf("Marka: ");
scanf("%s", a[i].marka);
printf("Cena: ");
scanf("%d", &a[i].cena);
}
}

int maxMerc(AUTO a[], int n){ // vraca poziciju najveceg mercedesa ako postoji ili -1 ako ne postoji
int i,j, poz;
AUTO max;

poz = -1; // nema mercedesa


i = 0; // trazimo prvi mercedes, idemo sve dok nije mercedes
while(i<n && strcmp(a[i].marka,"mercedes")!=0){
i++;
}

if (i<n){ // ima mercedesa u nizu


poz = i; // i je stalo na prvom mercedesu
max = a[poz]; // moramo da postavimo max na prvog mercedesa
for(i=0; i<n; i++)
if(a[i].cena > max.cena && strcmp(a[i].marka,"mercedes")==0) {
max = a[i];
poz = i;
}
}
return poz;
}
main(){
int n, poz;
AUTO a[DIM];
printf("Unesite broj Auta: ");
scanf("%d", &n);

4
unos(a,n);

poz = maxMerc(a,n);

if(poz != -1)
printf("\n Cena najskupljeg mercedesa je %d \n", a[poz].cena);
else
printf("\n Nema mercedesa u nizu !!! \n");
}

5
Zadaci sa vebi iz
Programskog jezika C
Tehniki Fakultet aak, kolska 2007/2008 godina

Vebe odrao: Vlade Maksimovi


VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

Zadatak1.NapisatiprogramkojiispisujesvetrocifreneAmstrongovebrojeve,Amstrongovi
brojevisuonibrojevikojisujednakizbirukubovasvojihcifara.

#include<stdio.h>

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


{
int c1,c2,c3,n;
for(n=100;n<=999;n++){
c1=n%10;
c2=n/10%10;
c3=n/100;
if(c1*c1*c1+c2*c2*c2+c3*c3*c3==n)
printf("%d\n",n);
}
return 0;
}

Zadatak 2. Objanjenje rada switch-a, ta ispisuje sledeci program.

#include<stdio.h>

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


{
int x = 0,i;
for(i=0;i<8;i++)
{
switch(i)
{
case 1: x++;
case 2: x+=2; break;
case 3: x+=1; break;
default: x-=1;
}
}
printf("x=%d",x);
return 0;
}

Zadatak 3. Napisati program koji za uneti mesec ispisuje broj dana u mesecu.

#include<stdio.h>

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


{
int mesec;
char ch;

2
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

printf("Uneti redni broj meseca\n");


scanf("%d",&mesec);

switch(mesec)
{
case 1:case 3:case 5:case 7:case 8:case 10: case 12: printf("31 dan\n"); break;
case 4: case 6: case 9: case 11: printf("30 dana\n"); break;
case 2: printf("Da li je godina prestupna (d/n)?\n"); scanf("%c",&ch); scanf("%c",&ch);
if((ch=='d')||(ch=='D'))
printf("29 dana\n");
else
printf("28 dana\n"); break;
default: printf("Nekorektan broj meseca\n");
}
return 0;
}

Zadatak 4. Napisati program koji za uneti datum ispisuje datum sledeeg dana.

#include<stdio.h>

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


{
int d, m, g, p=0, brdana;
printf("Unesi datum(d m g): ");
scanf("%d%d%d",&d,&m,&g);

if ((g%100 !=0 && g%4==0) || (g%400 == 0))


p++;

switch (m) {
case 1: case 3: case 5: case 7: case 8: case 10: case 12: brdana=31; break;
case 4: case 6: case 9: case 11: brdana=30; break;
case 2: brdana=28+p; break;
}

if ( d < brdana )
d++;
else if (m!=12) {
d=1;
m++;
}
else {
d=1;
m=1;
g++;
}
printf("Datum sledeceg dana je: %d/%d/%d\n",d,m,g);

3
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

return 0;
}

Zadatak 5. Nalaenje korena kvadratne jednaine.

#include<stdio.h>
#include<math.h>

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


{
double a,b,c,d,x1,x2,y1,y2;
typedef enum {Realni,Kompleksni,Dvostruki,Linearna,Pogresna} Vrsta;
Vrsta vrsta;

printf("Unesi koeficijente kvdratne jednacine:" );


scanf("%lf%lf%lf",&a,&b,&c);

if(a){
d=b*b-4*a*c;
if(d>0){
vrsta=Realni;
x1=(-b+sqrt(d))/(2*a);
x2=(-b-sqrt(d))/(2*a);
}
else if (d==0){
vrsta=Dvostruki;
x1=(-b/(2*a));
}
else {
vrsta=Kompleksni;
x1=(-b/(2*a));
x2=x1;
y1=sqrt(-d)/(2*a);
y2=-y1;
}
}
else if(b){
vrsta=Linearna;
x1=-c/b;
}
else
vrsta = Pogresna;

switch(vrsta){
case Realni: printf("Realni koreni su %lf i %lf\n",x1,x2);break;
case Dvostruki: printf("Dvostruki realni koren je: %lf",x1);break;
case Kompleksni: printf("Kompleksni koreni su:(%lf + %lf) i (%lf - %lf)",x1,y1,x2,y2);
break;

4
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

case Linearna: printf("Resenje linearne jednacine je: %lf",x1);break;


case Pogresna: printf("Podaci nemaju smisla!!!");break;
}
printf("\n");
return 0;
}

Zadatak 6. Mnozenje broja sa 2 bez upotrebe operacija sabiranja i mnozenja.

#include<stdio.h>

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


{
int d;
printf("Unesi broj: "); scanf("%d",&d);
d= d<<1;
printf("Novi broj je: %d\n",d);
return 0;
}

Zadatak 7. Predsavljanje brojeva u binarnom brojnom sistemu.

#include<stdio.h>

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


{
int broj,i;
printf("Unesi decimalni broj: ");
scanf("%d",&broj);
for (i=1;i<=8;i++)
{
if ((broj & 0x80) != 0) {
broj <<= 1;
printf("1");
}
else {
broj <<= 1;
printf("0");
}
if (i%4 == 0)
printf(" ");
}
printf("\n");
return 0;
}

5
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

Zadatak 8. Permutovanje cifara broja.

#include<stdio.h>

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


{
int broj;
printf("Ukucajte ceo broj?\n");
scanf("%d",&broj);
printf("Permutovan broj je\n");
do
{
printf("%d",broj%10);
broj/=10;
}
while(broj);
printf("\n");
return 0;
}

Zadatak 9. Ispisivanje sluajnih brojeva pritiskom na taster SPACE.

#include <stdio.h>
#include <conio.h>
#include <ctype.h>
#include <time.h>
#include <stdlib.h>

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


{
int ch;
ch = -1;

srand( (unsigned)time(NULL) );

while ( ch != 0x1B )
{
if ( kbhit() )
{
ch = getch();
switch ( ch )
{
case 0x20: printf( "%d\n",rand()%100 ); break;
default: printf( "Greska!\n" ); break;
}
}
}

6
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

return 0;
}

Zadatak 10. Napisati program u kome se definie funkcija prost() koja ispituje da li je broj
prost i funkcija main() koja njenim korienjem tampa sve proste brojeve do datog prirodnog
broja n.

#include<stdio.h>
#include<math.h>

int prost(int n)
{
int i;
for (i=2;i<=sqrt(n);i=i+1)
if(n%i==0)
return 0;
return i;
}

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


{
int i,n;
printf("Uneti broj\n");
scanf("%d",&n);
printf("Prosti brojevi su\n");
for(i=2;i<=n;i=i+1)
if(prost(i)) printf("%d\n",i);
return 0;
}

Zadatak 11. Napisati program kojim se tampaju svi trocifreni brojevi (ako ih ima) koji su
jednaki sumi faktorijela svojih cifara.

#include<stdio.h>

int fakt(int n)
{
int p=1,i;
for(i=2;i<=n;i++)
p*=i;
return p;
}

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


{
int n,a,b,c;

7
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

printf("Trocifreni brojevi jednaki sumi faktorijela svojih cifara su:\n");


for(n=100;n<1000;n++)
{
a=n%10;
b=n/10%10;
c=n/100;
if(n==fakt(a)+fakt(b)+fakt(c)) printf("%d\n",n);
}
return 0;
}

Zadatak 12. Pomeranje elemenata niza za jedno mesto u levo.

#include<stdio.h>

void upis(int a[], int n)


{
int i;

for(i=0;i<n;i++)
{
printf("a[%d]= ",i+1);
scanf("%d",&a[i]);
}
}

void ispis(int a[], int n)


{
int i;

for(i=0;i<n;i++)

printf(" a[%d]= %d",i+1,a[i]);


}

void pomerilevo(int a[], int n)


{
int i,pom;
pom = a[0];
for(i=1;i<n;i++)
a[i-1]=a[i];
a[n-1]=pom;
}

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


{
int a[25],n;
n=5;
upis(a,n);

8
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

pomerilevo(a,n);
ispis(a,n);
printf("\n");
return 0;
}

Zadatak 13. Izdvajanje niza iz k-te paralele dijagonale kvadratne matrice, i njegovo sortiranje.

#include<stdio.h>

void upis(int a[][25],int n)


{
int i,j;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
printf("a[%d][%d]=",i+1,j+1);
scanf("%d",&a[i][j]);
}
}

void ispis(int a[],int n)


{
int i;

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

int izdvoj (int a[][25],int b[],int n,int k)


{
int i,j,p=0;
/*za k-tu paralelu iznad sporedne dijagonale */
for(i=0;i<=n-1-k;i++)
for(j=0;j<=n-1-k;j++)
if(i+j==n-1-k)
b[p++]=a[i][j];

/*za k-tu paralelu ispod sporedne dijagonale


for(i=k;i<=n-1;i++)
for(j=k;j<=n-1;j++)
if(i+j==n-1+k)
b[p++]=a[i][j]; */

/*za k-tu paralelu iznad glavne dijagonale


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

9
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

if(j-i == k)
b[p++]=a[i][j];*/

/*za k-tu paralelu ispod glavne dijagonale


for(i=k;i<=n-1;i++)
for(j=0;j<=n-1-k;j++)
if(i-j == k)
b[p++]=a[i][j];*/
return p;
}

void sort(int b[],int n)


{
int i,j,pom;
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
if(b[i]>b[j])
{
pom=b[i];
b[i]=b[j];
b[j]=pom;
}
}

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


{
int a[25][25],b[25],n,k,br;
n=4;
k=1;
upis(a,n);
br=izdvoj(a,b,n,k);
sort(b,br);
ispis(b,br);
return 0;
}

Zadatak 14. Napisati program koji od unete matrice formira niz na taj nain to od
maksimalnog elementa oduzme minimalan u svakoj vrsti matrice.

#include<stdio.h>

void unos(int a[][25], int v, int k)


{
int i,j;
for(i=0;i<v;i++)
for(j=0;j<k;j++)
{
printf("a[%d,%d]= ",i+1,j+1);

10
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

scanf("%d",&a[i][j]);
}
}

void ispis(int a[], int v)


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

void razlika(int a[][25], int v, int k, int b[])


{
int i,j, max[25], min[25];
for(i=0;i<v;i++)
{
max[i]=a[i][0];

for(j=0;j<k;j++)
if(a[i][j]>max[i])
max[i]=a[i][j];
}

for(i=0;i<v;i++)
{
min[i]=a[i][0];
for(j=0;j<k;j++)
if(a[i][j]<min[i])
min[i]=a[i][j];
}

for(i=0;i<v;i++)
b[i]= max[i]-min[i];
}

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


{
int a[25][25],k,v,b[25];
printf("Unesi dimenziju matrice(npr: 3x4): ");
scanf("%d%d",&v,&k);
unos(a,v,k);
razlika(a,v,k,b);
ispis(b,v);
return 0;
}

Zadatak 15. Napisati program koji menja elemente iz dve vrste matrice.

11
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

#include<stdio.h>

void unos(int a[][25], int v, int k)


{
int i,j;
for(i=0;i<v;i++)
for(j=0;j<k;j++)
{
printf("a[%d,%d]= ",i+1,j+1);
scanf("%d",&a[i][j]);
}
}

void ispis(int a[][25], int v, int k)


{
int i,j;
for(i=0;i<v;i++)
{
for(j=0;j<k;j++)
printf("%d ",a[i][j]);
printf("\n");
}
}

void zamena(int a[][25], int k, int m, int n)


{
int i,pom;
for(i=0;i<k;i++)
{
pom = a[m][i];
a[m][i] = a[n][i];
a[n][i] = pom;
}
}

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


{
int a[25][25],k,m,n,v;
printf("Unesi dimenziju matrice(npr: 3x4): ");
scanf("%d%d",&v,&k);
unos(a,v,k);
printf("Unesi dve vrste koje menjas: ");
scanf("%d%d",&m,&n);
zamena(a,k,m,n);
ispis(a,v,k);
return 0;
}

12
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

Zadatak 16. Napisati program koji za uneti niz brojeva odreuje koliko ih ima do prvog
negativnog.

#include<stdio.h>

void upis(int a[], int n)


{
int i;
for(i=0;i<n;i++)
scanf(%d,&a[i]);
}

void ispis(int a[], int n)


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

int brojpozitivnih(int a[], int n)


{
int k=0,i;
for(i=0;i<n && a[i]>=0;i++)
if(a[i]>0)
k++;
return k;
}

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


{
int a[100],n;
printf(Unesite dimenziju niza: );
scanf(%d,&n);
printf(Unesite clanove niza: );
upis(a,n);
printf(Broj pozitivnih do prvog negativnog je: %d, brojpozitivnih(a,n));
return 0;
}

Zadatak 17. Napisati program koji sve negativne elemente niza stavlja na kraj tog niza.

#include <stdio.h>

void citaj(float a[],int n)


{
int i;
printf("Uneti niz \n");
for(i=0;i<n;i++)

13
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

{
printf("a[%d]=",i);
scanf("%f",&a[i]);
}
}

void uredi(float a[],int n)


{
float pom;
int i,j;
i=0; j=n-1;
while(i<j)
if(a[i]>0) i++;
else
{
if(a[j]>0)
{
pom=a[i];
a[i]=a[j];
a[j]=pom; }
j--;
}
}

void pisi(float a[],int n)


{
int i;
printf("Formirani niz\n");
for(i=0;i<n;i++)
printf("a[%d]=%5.2f\n",i,a[i]);
}
int main(int argc, char *argv[])
{
float a[100];
int n;
printf("Uneti broj elemenata niza\n");
scanf("%d",&n);
citaj(a,n);
uredi(a,n);
pisi(a,n);
}

Zadatak 18. Napisati program koji za sluajno uneti niz brojeva, saima niz na taj nain to
sve iste elemente koji su jedan za drugim sabira i postavlja na prvo mesto pojavljivanja tog
broja u nizu.

14
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

void upis (int a[], int n)


{
int i;
srand((unsigned)time(NULL));
for(i=0;i<n;i++)
{
a[i]=rand()%10;
}
}

void ispis (int a[], int n)


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

int sazimanje(int a[], int b[], int n)


{
int i,j,k,p=0,pom;

for(i=0;i<n;i++)
{
k=i;
j=i+1;
pom=a[k];

while(a[k] == a[j])
{
pom=pom+a[j];
j++;
i++;
}
b[p++]=pom;
}
return p;
}

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


{
int n,a[50],b[50],br;
printf("Unesi dimenziju niza: ");
scanf("%d",&n);

15
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

printf("\nUnesi elemente niza");


upis(a,n);
br = sazimanje(a,b,n);
printf("\n");
ispis(a,n);
printf("\n");
ispis(b,br);
printf("\n");
}

Zadatak 19. Napisati program koji na poetak niza stavlja one elemente koji se pojavljuju
samo jedanput u nizu, a zatim ostale elemente po redosledu po kome su uitani u niz.

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

void upis (int a[], int n)


{
int i;
srand((unsigned)time(NULL));
for(i=0;i<n;i++)
{
a[i]=rand()%10;
}
}

void ispis (int a[], int n)


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

int brponavljanja(int a[], int n, int w)


{
int i,k=0;
for(i=0;i<n;i++)
{
if (a[i] == w)
k++;
}

return k;
}

16
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

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


{
int n,a[50],b[50],c[50],k=0,e=0,i;

printf("Unesi dimenziju niza: ");


scanf("%d",&n);
printf("\nUnesi elemente niza");
upis(a,n);

for(i=0;i<n;i++)
{
if (brponavljanja(a,n,a[i]) == 1)
b[k++]=a[i];
else
c[e++]=a[i];
}

printf("\n");
ispis(a,n);
printf("\n");
ispis(b,k);
printf(" ");
ispis(c,e);
}

Zadatak 20. ta nedostaje u sledeem opisu, da bi predstavljao opis stringa?

char ime[]={F, A, L, S, E};

Reenje: Nedostaje null znak na kraju stringa.

Zadatak 21. ta ispisuje sledi program?

#include<stdio.h>
int main(int argc, char *argv[])
{
char film[]=Tango argentino;
char *pok;
pok=film;
puts(pok);
puts(++pok);
film[5]=\0;
puts(film);
puts(++pok);
}

Reenje:
Tango argentino
ango argentino

17
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

Tango
ngo

Zadatak 22. ta ispisuje sledei program?

#include<stdio.h>
#include<string.h>
int main(int argc, char *argv[])
{
char ime[]=Bingo;
char *pok;
pok=ime+strlen(ime);
while(--pok >= ime)
puts(pok);
}

Reenje:
o
go
ngo
ingo
Bingo

Zadatak 23. ta ispisuje sledei program?

#include<stdio.h>
#include<string.h>
int main(int argc, char *argv[])
{
char s1[28]=ani ceo;
char s2[40]=Ko rano r;
char *s3=dan zeva.;
strcat(s1,s3);
strcat(s2,s1);
puts(s2);
}

Reenje: Ko rano rani ceo dan zeva.

Zadatak 24. Napisati funkciju koja:


a) kopira string s1 u s2;
b) proverava da li je string s2 palindrom;
c) vraa pokaziva na prvo pojavljivanje znaka c u stringu s
d) brise svako pojavljivanje znaka c;
e) vraa poziciju prvog pojavljivanja stinga s2 u stringu s1, ako string s2 nije prisutan
u stringu s1 funkcija treba da vrati -1.

18
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

a)
void kopi(char *s1, char *s2)
{
while (*s2=*s1)
{
s1++;
s2++;
}
}

b)
int palindrom(char *s)
{
char *p=s+strlen(s)-1;
while(s<p && *s==*p)
{s++; p--;}
return (s>=p);
}

c)
char *nadji_prvi(char *s, char c)
{
while(*s && *s!=c) s++;
if(*s) return s
}

d)
void brisi_znak(char *s, char c)
{
char *p=s;
while(*p)
{
if(*p!=c) *s++=*p;
p++;
}
*s=\0;
}

e)
int pos(char *s1, char *s2)
{
if(strstr(s1,s2)!=NULL) return strstr(s1,s2) s1;
else return -1;
}

Zadatak 25. Napisati funkciju kojom se iz stringa s brie d znakova poev od pozicije p, pri
emu poev od pozicije p u stringu s ima barem d znakova.

19
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

#include< stdio.h >


#include<string.h>
void brisi(char *s, int d, int p)
{
char *q;
for(q=s+p;*(q+d);q++) *q=*(q+d);
*q=\0;
}

Zadatak 26. Napisati program koji za uneti string i neki broj ispisuje samo one karaktere sa
pozicija gde se u broju u njegovom binarnom zapisu javlja broj 1.

#include <stdio.h>

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


{
short int M, maska;
char S1[17], *s1, S2[17], *s2;
printf("%Unesi string S1 i broj M:\n");
scanf("%s%d", &S1, &M);
s1 = S1;
s2 = S2;
maska = 1;
while (maska)
{
if (M & maska) {*s2 = *s1; s2++; };
s1++; maska<<=1;
}
*s2 = '\0';
printf("Novi string S2: %s\n", S2);
}

Zadatak 27. Objanjenje nizovia i pokazivaa.

/*Nizovi i pokazivaci*/
#include<stdio.h>
int main(int argc, char *argv[])
{
float a,b,c,fniz[5]={0.01,0.1,0.5,1.0,10.0};
float *p_fniz;
char tekst[]={"Ovo je znakovni niz\n"};
char *p_tekst;
int i;

20
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

p_fniz=fniz;
a=*p_fniz; // a=fniz[0]
b=*(p_fniz+2); // b=fniz[2]
p_fniz=&fniz[2];
c=*(p_fniz+2); // c=fniz[4]
printf("a=%f b=%f c=%f\n",a,b,c);

//ispis stinga
for(i=0;tekst[i]!='\0';++i)putchar(tekst[i]);
// ispis stringa na drugi nacin
for(p_tekst=tekst;*p_tekst!='\0';++p_tekst)putchar(*p_tekst);

return 0;
}

Zadatak 28. Stranice a i b pravougaonika su prirodni brojevi. Odrediti, na koliko se kvadrata


maksimalne povrine moe isei dati pravougaonik. Ispisati dimenzije kvadrata. Na primer za
a=12 i b=7 se ispisuje:
1 kvadrata stranice: 7
1 kvadrata stranice: 5
2 kvadrata stranice: 2
2 kvadrata stranice: 1

#include<stdio.h>

void razmeni(int *a, int *b)


{
int t;
t=*a;
*a=*b;
*b=t;
}

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


{
int a,b;
printf("Uneti stranice pravougaonika\n");
scanf("%d%d",&a,&b);
if(a==b)
printf("Jedan kvadrat stranice %d\n",a);
else
while(a)
{
if(a<b) razmeni(&a,&b);
printf("%d kvadrata stranice: %d\n",a/b,b);
a=a%b;
}
return 0;
}

21
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

Zadatak 29. Napisati program kojim se iz stringa s brise svaki znak koji odgovara bilo kom
znaku stringa t.

#include <stdio.h>
#include <string.h>

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


{
char s[50], t[50];
int i,j;
gets(s);
gets(t);
for(i=j=0;*(s+i);i++)
if(!strchr(t,*(s+i)))
{
*(s+j)=*(s+i);
j++;
}
*(s+j)='\0';
puts(s);
}

Zadatak 30. Program za odredjivanje duine stringa koji se uitava sa komnadne linije.

#include<stdio.h>

int duzina(char *p_string);

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


{
int i;
for(i=1;i<argc;i++)
printf("argument%d %s\n",i,argv[i]);
i=duzina(argv[2]);
printf("duzina stringa je %d\n",i);
return 0;
}

// funkcija koja kao rezultat vraca duzinu stringa


int duzina(char *p_string)
{
int l=0;
char *p;
p=p_string;
while(*p!='\0')
{

22
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

++l;
++p;
}
return l;
}

Zadatak 31. Napisati program koji iz datog stringa s izbacuje sve komentare, s tim to u
komentaru nema komentara.

#include <stdio.h>
#include <string.h>

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


{
char s[100], *p,*q;
gets(s);
while(p=strstr(s,"/*"))
{
q=strstr(s,"*/");
strcpy(p,q+2);
}
puts(s);
}

Zadatak 32. Napisati program koji odredjuje broj rei u stringu s i duinu najdue rei, reci su
razdvojene blanko simbolima.

#include<stdio.h>

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


{
char s[80];
int i,brojreci,brojslovaureci,maksimalnarec;
gets(s);
maksimalnarec=brojslovaureci=brojreci=0;

for(i=0;*(s+i);i++)
if(*(s+i)==' ')
{
if(brojslovaureci>maksimalnarec) maksimalnarec=brojslovaureci;
brojslovaureci=0;
}

23
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

else
{
if(!brojslovaureci)brojreci++;
brojslovaureci++;
}

if(brojslovaureci>maksimalnarec) maksimalnarec=brojslovaureci;
printf("%d %d\n",brojreci,maksimalnarec);
return 0;
}

Zadatak 33. Napisati program koji odredjuje prosean broj slova u reima parne duine.

#include<stdio.h>

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


{
char s[80];
// br broj reci parne duzine,
// q broj smibola u recima parne duzine
int k,br=0,q=0,i;
gets(s);
k=0;
for(i=0;*(s+i);i++)
if(*(s+i)!=' ')
k++;
else
if(k>0)
{
if(k%2==0)
{
br++;
q+=k;
}
k=0;
}

if(k>0)
if(k%2==0)
{
br++;
q+=k;
}

printf("Prosecan broj simbola u recima parne duzine je %2.0f\n",(float)q/br);


return 0;
}

24
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

Zadatak 34. Nalaenje unije dva skupa.

#include<stdio.h>
#include<stdlib.h>

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


{

int n1,n2,n3,i,j;
double *s1, *s2, *s3;

printf("Unesi broj elemenata skupova: ");


scanf("%d%d",&n1,&n2);

s1=malloc(n1*sizeof(double));
printf("Elementi prvog skupa su: ");
for(i=0;i<n1;scanf("%lf",&s1[i++]));
if (n1==0) putchar('\n');

s2=malloc(n2*sizeof(double));
printf("Elementi drugog skupa: ");
for(i=0;i<n2;scanf("%lf",&s2[i++]));
if (n2==0) putchar('\n');

s3=malloc((n1+n2)*sizeof(double));
for(n3=0;n3<n1;n3++)
s3[n3]=s1[n3];
for(j=0;j<n2;j++){
for(i=0;i<n1;i++)
if(s2[j]==s1[i]) break;
if(i==n1) s3[n3++]=s2[j];
}

s3=realloc(s3,n3*sizeof(double));

printf("Unija pocetnih skupova: ");


for(i=0;i<n3;i++)
printf("%lf ",s3[i]);

free(s1);
free(s2);
free(s3);
}

Zadatak 35. Sortiranje imena smetenih u dinamiku matricu.

#include<stdio.h>

25
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

#include<string.h>
#include<stdlib.h>

#define MAX_IME 100


#define MAX_DUZ 30

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


{

char **imena, *ime;


int br_imena=0,duz,i;

printf("\nNeuredjeni niz imena: \n");


imena = malloc(MAX_IME*sizeof(char *));

do {

ime=malloc(MAX_DUZ*sizeof(char));
gets(ime);

if((duz=strlen(ime))==0)
{
free(ime);
break;
}

for(i=br_imena-1;i>=0;i--)
if( strcmp(imena[i],ime) > 0 )
imena[i+1]=imena[i];
else break;
imena[i+1]=ime;

}
while(++br_imena<MAX_IME);

imena = realloc(imena, br_imena*sizeof(char *));


printf("Uredjeni niz imena:\n");
for(i=0;i<br_imena;i++)
puts(imena[i]);
free(imena);
}

Zadatak 36. Odrediti broj linija u tekstualnom fajlu sa imenom knjiga.txt.

#include<stdio.h>

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


{
int k=0;

26
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

FILE *fp;
char s[256];
if((fp=fopen("knjiga.txt","r"))==NULL)
{
perror("Greska");
return;
}
while(fgets(s,256,fp)!=NULL)k++;
printf("Fajl ima %d linija\n",k);
fclose(fp);
}

Zadatak 37. Napisati program kojim se sadraj fajla test.dat formiran od velikih slova alfabeta
ifriran alje u fajl sifra.dat. Znak se ifrira tako to se zamenjuje sledeim ASCII znakom, a
znak Z zamenjuje sa A.

#include<stdio.h>

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


{
int c;
FILE *inf,*outf;
inf=fopen("test.dat","r");
outf=fopen("sifra.dat","w");
while((c=fgetc(inf))!=EOF)
{
if('A'<=c&&c<'Z')
c++;
else c='A';
putc(c,outf);
}
fclose(inf);
fclose(outf);
}

Zadatak 38. U tekstualnom fajlu odrediti najduu liniju. Ako ima vie linija najvee duine
odrediti prvu meu njima.

#include<stdio.h>
#include<string.h>

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


{
unsigned k=0,maxl;
42
char s[256],maxs[256];
FILE *fp;

27
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

if((fp=fopen("test.txt","r"))==NULL)
{
printf("Greska\n ");
return;
}
maxl=0;
while(fgets(s,256,fp)!=NULL)
if(strlen(s)>maxl)
{
maxl=strlen(s);
strcpy(maxs,s);
}
printf("Najduza linija\n%s\n ima duzinu %d\n",maxs,maxl);
fclose(fp);
}

Zadatak 39. Napisati program za uitavanje datoteke pod imenom ulaz.dat i formiranje
datoteke sa nazivom izlaz.dat koja sadri samo one redove ulazne datoteke ulaz.dat u kojima
se nalazi re fakultet.

#include<stdio.h>
#include<string.h>

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


{
FILE *ulaz;
FILE *izlaz;
char buffer[80];
char trazenaRec[]="fakultet";
if((ulaz=fopen("ulaz.dat","r"))==NULL)
printf("Datoteka ulaz.dat nije otvorena.");
if((izlaz=fopen("izlaz.dat","w"))==NULL)
printf("Datoteka izlaz.dat nije otvorena.");
while(!feof(ulaz)){
fgets(buffer,80,ulaz);
if(strstr(buffer,trazenaRec)!=NULL){
printf("%s",buffer); /*stamanje na ekranu*/
fprintf(izlaz,"%s",buffer);
}
}
fclose(ulaz);
fclose(izlaz);
}

28
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

Zadatak 40. Napisati program koji ita podatke iz datoteke ULAZ.TXT (ime studenta, broj
bodova na prijemnom ispitu), broji sve studente koji imaju broj bodova vei od proseka i
upisuje podatke o takvim studentima u datoteku IZLAZ.TXT.

#include<stdio.h>

#define DIM 10
typedef struct student{
char ime[20];
int brBodova;
};

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


{
struct student nizStudenata[DIM];
int i;
int brojStudenata=0;
int suma=0;
float prosek;
FILE *ulaz;
FILE *izlaz;
ulaz=fopen("ulaz.txt", "r");
if(ulaz==NULL){
printf("Ulazna datoteka nije otvorena!\n");
return 1;
}
izlaz=fopen("izlaz.txt", "w");
if(izlaz==NULL){
printf("Izlazna datoteka nije kreirana!\n");
return 1;
}
while(!feof(ulaz)){
fscanf(ulaz, "%s%d", &nizStudenata[brojStudenata].ime,
&nizStudenata[brojStudenata].brBodova);
suma+=nizStudenata[brojStudenata].brBodova;
brojStudenata++;
}
prosek=(float)suma/brojStudenata;
for(i=0; i<brojStudenata; i++)
if(nizStudenata[i].brBodova>prosek)
fprintf(izlaz, "%s\t%d\n", nizStudenata[i].ime, nizStudenata[i].brBodova);
fclose(ulaz);
fclose(izlaz);
return 0;
}

29
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

Zadatak 41. U datoteci IMENIK.TXT nalaze se sledeci podaci: ime, prezime i broj telefona
telefonskog pretplatnika. Napisati program koji vrsi sortiranje imenika prema prezimenu
pretplatnika i za zadato prezime prikazuje telefonski broj pretplatnika na standardnom izlazu.

#include<stdio.h>
#include<string.h>
#define DIM 10

typedef struct telefonski_imenik{


char ime[10];
char prezime[20];
char broj[10];
};
void razmeni(struct telefonski_imenik *a, struct telefonski_imenik *b){
struct telefonski_imenik tmp;
tmp=*a;
*a=*b;
*b=tmp;
}

void sort(struct telefonski_imenik niz[], int n){


int i, j;
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(niz[i].prezime<niz[j].prezime)
razmeni(&niz[i], &niz[j]);
}

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


{
struct telefonski_imenik nizImenik[DIM];
int n, i;
FILE *in;
char trazi[20];
in=fopen("imenik.txt", "r");
if(in==NULL){
printf("Ulazni fajl nije otvoren!");
return 1;
}
i=0;
while(!feof(in)){
fscanf(in, "%s%s%s", &nizImenik[i].ime, &nizImenik[i].prezime, &nizImenik[i].broj);
i++;
}
fflush(in);
n=i+1;
sort(nizImenik, n);
printf("\nTelefonski imenik sortiran po prezimenu pretplatnika je:\n\n");
for(i=0; i<n; i++)

30
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

printf("%s\t%s\t%s\n", nizImenik[i].prezime, nizImenik[i].ime, nizImenik[i].broj);


printf("Ukupan broj telefonskih pretplatnika je: %d\n",n);
printf("Zadati prezime pretplatnika: ");
scanf("%s", &trazi);
for(i=0; i<n; i++){
if(strcmp(nizImenik[i].prezime,trazi)==0){
printf("Broj telefoma trazenog pretplatnika je:\n");
printf("%s\t%s\t%s\n", nizImenik[i].prezime, nizImenik[i].ime, nizImenik[i].broj);
}
}
fclose(in);
return 0;
}

31
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

REENI ZADACI SA PRVOG KOLOKVIJUMA IZ PROGRAMSKIH JEZIKA

Zadatak 1. Napisati program koji za uneti broj ispisuje koliko ima jedinica u njegovom
binarnom zapisu.

#include<stdio.h>

int brjedinica(int broj)


{
int i,br=0;
for(i=0;i<8;i++)
{
if(broj & 128)
br++;
broj<<=1;
}
return br;
}
int main(int argc, char *argv[])
{
int broj;
printf("Unesi broj: ");
scanf("%d",&broj);
printf("Broj jedinica je %d\n",brjedinica(broj));
return 0;
}

Zadatak 2. Napisati program koji uneti niz pomera za n cifara u desno. Zadatak reiti preko
funkcija.

#include<stdio.h>
void unosniza(int a[],int n)
{
int i;
for(i=0;i<n;i++)
{
printf("a[%d]=",i+1);
scanf("%d",&a[i]);
}
}
void ispisniza(int a[],int n)
{
int i;
for(i=0;i<n;i++)
printf("%d ",a[i]);
printf("\n");
}
void pomeri(int a[], int n, int koliko)

32
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

{
int i,pom,j;
for(j=0;j<=koliko;j++)
{
pom=a[n-1];
for(i=n-1;i>=0;i--)
a[i]=a[i-1];
a[0]=pom;
}
}
int main(int argc, char *argv[])
{
int a[25],n,k;
printf("Unesi broj elemenata niza: ");
scanf("%d",&n);
unosniza(a,n);
printf("Unesi broj za koji pomeras niz u desno: ");
scanf("%d",&k);
printf("Niz posle pomeranja u desno je:\n");
pomeri(a,n,k);
ispisniza(a,n);
return 0;
}

Zadatak 3. Napisati program koji za unetu matricu vri razmenu elemenata po vrstama na taj
nain to negativne elemente stavlja na kraj svake vrste.

#include<stdio.h>
void unosmatrice(int a[][20],int v,int k)
{
int i,j;
for(i=0;i<v;i++)
for(j=0;j<k;j++)
{
printf("a[%d][%d]=",i+1,j+1);
scanf("%d",&a[i][j]);
}
}
void ispismatrice(int a[][20],int v,int k)
{
int i,j;
for(i=0;i<v;i++)
{
for(j=0;j<k;j++)
printf("%d ",a[i][j]);
printf("\n");
}

33
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

}
void uredimatricu(int a[][20], int v, int k)
{
int i,j,pom,vrsta;
for (vrsta=0;vrsta<v;vrsta++)
{
i=0;
j=k-1;
while(i<j)
{
if(a[vrsta][i]>0)
i++;
else
if(a[vrsta][j]>0)
{
pom=a[vrsta][i];
a[vrsta][i]=a[vrsta][j];
a[vrsta][j]=pom;
j--;
}
}
}
}
int main(int argc, char *argv[])
{
int a[20][20],v,k;
printf("Unesi broj vrsta i kolona matrice: ");
scanf("%d %d",&v,&k);
unosmatrice(a,v,k);
uredimatricu(a,v,k);
ispismatrice(a,v,k);
return 0;
}

Zadatak 4. Napisati program koji za uneti broj ispisuje koliko ima nula u njegovom binarnom
zapisu.

#include<stdio.h>
int brnula(int broj)
{
int i,br=0;
for(i=0;i<8;i++)
{
if((broj & 128)==0)
br++;
broj<<=1;
}
return br;
}

34
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

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


{
int broj;
printf("Unesi broj: ");
scanf("%d",&broj);
printf("Broj nula je %d\n",brnula(broj));
return 0;
}

Zadatak 5. Napisati program koji uneti niz pomera za 2. cifre u desno, pa za 3. cifre u levo.
Zadatak raditi prko funkcija.

#include<stdio.h>
void unosniza(int a[],int n)
{
int i;
for(i=0;i<n;i++)
{
printf("a[%d]=",i+1);
scanf("%d",&a[i]);
}
}
void ispisniza(int a[],int n)
{
int i;
for(i=0;i<n;i++)
printf("%d ",a[i]);
printf("\n");
}
void pomeri(int a[], int n, int smer, int koliko)
{
int i,pom,j;
switch(smer)
{
/*pomeranje u levo */
case 1:{
for(j=0;j<koliko;j++)
{
pom=a[0];
for(i=0;i<n-1;i++)
a[i]=a[i+1];
a[n-1]=pom;
}
} break;
/*pomeranje u desno */
case 2: {
for(j=0;j<koliko;j++)
{
pom=a[n-1];

35
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

for(i=n-1;i>=0;i--)
a[i]=a[i-1];
a[0]=pom;
}
} break;
}
}
int main(int argc, char *argv[])
{
int a[25],n;
printf("Unesi broj elemenata niza: ");
scanf("%d",&n);
unosniza(a,n);
pomeri(a,n,2,2);
printf("Niz posle pomeranja u desno za dve pozicije:\n");
ispisniza(a,n);
pomeri(a,n,1,3);;
printf("Niz posle pomeranja u levo za tri pozicije:\n");
ispisniza(a,n);
return 0;
}

Zadatak 6. Napisati program koji za unetu matricu vri razmenu elemenata po kolonama na taj
nain to negativne elemente stavlja na kraj svake kolone.

#include<stdio.h>
void unosmatrice(int a[][20],int v,int k)
{
int i,j;
for(i=0;i<v;i++)
for(j=0;j<k;j++)
{
printf("a[%d][%d]=",i+1,j+1);
scanf("%d",&a[i][j]);
}
}
void ispismatrice(int a[][20],int v,int k)
{
int i,j;
for(i=0;i<v;i++)
{
for(j=0;j<k;j++)
printf("%d ",a[i][j]);
printf("\n");
}
}

void uredimatricu(int a[][20], int v, int k)


{

36
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

int i,j,pom,kolona;
for (kolona=0;kolona<k;kolona++)
{
i=0;
j=v-1;
while(i<j)
{
if(a[i][kolona]>0)
i++;
else
if(a[j][kolona]>0)
{
pom=a[i][kolona];
a[i][kolona]=a[j][kolona];
a[j][kolona]=pom;
j--;
}
}
}
}

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


{
int a[20][20],v,k;
printf("Unesi broj vrsta i kolona matrice: ");
scanf("%d %d",&v,&k);
unosmatrice(a,v,k);
uredimatricu(a,v,k);
ispismatrice(a,v,k);
return 0;
}

Zadatak 7.
. (d.m.g.).
, ,
, , . n ,
. ,
.

#include<stdio.h>

int broj_cifara(int n)

int s=0;

while(n)

37
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

s++;

n=n/10;

return s;

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

int dan,mesec,godina,n,s,brdana;

printf("Unesite dan, mesec i godinu: ");

scanf("%d%d%d",&dan,&mesec,&godina);

printf("Unesite broj cifara n: ");

scanf("%d",&n);

s=broj_cifara(dan)+broj_cifara(mesec)+broj_cifara(godina)+3;

do

switch(mesec)

case 1: case 3: case 5: case 7: case 8: case 10: case 12: brdana=31;break;

case 4: case 6: case 9: case 11: brdana=30; break;

case 2: brdana=29; break;

if ( dan < brdana )

dan++;

else if (mesec!=12) {

dan=1;

mesec++;

38
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

else {

dan=1;

mesec=1;

godina++;

s = s+ broj_cifara(dan) + broj_cifara(mesec) + broj_cifara(godina) + 3;

while( s < n );

printf("Olovka je prestala da pise kod datuma: %d %d %d\n",dan,mesec,godina);

return 0;

39
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

REEI ZADACI SA DRUGOG KOLOKVIJUMA IZ PROGRAMSKIH JEZIKA

Zadatak 1. n , 0, 1, 2... , n-1.


. nxn [i][j]=1 i
, a[i][j]=0.
(a[i][j]=a[j][i]).
.

#include <stdio.h>
#include <stdlib.h>

int provera(int m[][6],int a[],int x[],int k,int i, int n)


{
int brneprijatelja=0,s,t;
for(s=0;s<k;s++){
for(t=0;t<n;t++)
if(a[s]==x[t])
if(m[t][i]==1)
brneprijatelja++;
}
return brneprijatelja;
}

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


{
int x[6]={2,8,4,7,5,10};
int m[6][6]= { 0,1,1,0,0,1,
1,0,1,0,1,0,
1,1,0,1,0,0,
0,0,1,0,0,0,
0,1,0,0,0,1,
1,0,0,0,1,0};
int a[6],b[6],c[6];
int i,j=0,k=0,l=0,n=6;

40
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

for (i=0;i<n;i++) {
if (provera(m,a,x,j,i,n)==0)
a[j++]=x[i];
else
if (provera(m,b,x,k,i,n)==0)
b[k++]=x[i];
else
c[l++]=x[i];
}

printf("Prvi niz je:\n");


for(i=0;i<j;i++)
printf("%d ",a[i]);
printf("\nDrugi niz je:\n");
for(i=0;i<k;i++)
printf("%d ",b[i]);
printf("\nTreci niz je:\n");
for(i=0;i<l;i++)
printf("%d ",c[i]);
printf("\n");
system("PAUSE");
}

Zadatak 2. magacin.txt n (,
, ).
, . sredjeno.txt

.

#include<stdio.h>
#include<string.h>

struct Roba{

41
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

int sifra;
char naziv[20];
int kolicina;
float cena;
};

void sredi(struct Roba roba[], int n)


{
int i,j,k,p=0,pom;
FILE *out;
out=fopen("sredjeno.txt","w");

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

pom=roba[k].kolicina;

while(roba[k].sifra == roba[j].sifra) {
pom=pom+roba[j].kolicina;
j++;
i++;
}
fprintf(out,"%d %s %d %.2fdin\n",roba[k].sifra,roba[k].naziv,pom,roba[k].cena);
}
}

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

int i,n,p; FILE *in;


struct Roba roba[20];
printf("Unesi broj zapisa koje citas: "); scanf("%d",&n);

42
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

in=fopen("magacin.txt", "r");

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

fscanf(in,"%d%s%d%f",&roba[i].sifra,&roba[i].naziv,&roba[i].kolicina,&roba[i].cena
);
}
sredi(roba,n);
}

Zadatak 3. C
() S1 , S2
.
8- , 8
. , S2.

#include <stdio.h>

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


{
short int M, maska;
char S1[9], *s1, S2[9], *s2;
printf("%Unesi string S1 i broj M:\n");
scanf("%s%d", &S1, &M);
s1 = S1;
s2 = S2;
maska = 1;
while (maska)
{
if (M & maska == 0) {*s2 = *s1; s2++; };
s1++; maska<<=1;
}
*s2 = '\0';

43
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

printf("Novi string S2: %s\n", S2);


}

, .
Zadatak 4. Izraunati i ispisati vrednost z po formuli: , 16.8 2 ,
ako se x menja od x1 do x2 sa korakom 1. Ako nije ispunjen uslov definisanosti, uzeti da je
vrednost promenljive z jednaka 1. Koristiti funkcije kod kojih se vri prenoenje parametara
po referenci.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define min 19.2
#define max 16.8

void min3(float x, float *k)


{
if (x<min) *k=pow(x,3);
else *k=pow(min,3);
}

void max2(float x, float *k)


{
if (x<max) *k=pow(max,2);
else *k=pow(x,2);
}
void koren(float x, float *k)
{
float p;
max2(x,&p);
*k=sqrt(p-2);
}

void razl(float x, float *k)


{
float p;
min3(x,&p);
*k=p/(1+pow(x,3));
}

void ispis(float a[],int n)


{
int i;
for(i=0;i<n;i++)
printf("%f\n",a[i]);
}

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


{

44
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

float x1,x2,h,d1,d2,z[30];
int j=0;
printf("Unesi granice x1, x2 i korak h: ");
scanf("%f%f%f",&x1,&x2,&h);
while( x1 <= x2 )
{
if (x1==-1)
z[j]=1;
else
{
koren(x1,&d1);
razl(x1,&d2);
z[j]=d1*d2;
}
j++;
x1=x1+h;
}
ispis(z,j);
system("PAUSE");
}

Zadatak 5. C
() S1 m, S2
S1 p- q-, a
k( S2) m.
41*m ,
.
.

#include<stdio.h>
#include<string.h>

void seci(char *s,int p,int q)


{
char *t;
t=s;
while( p<q )
{
*s=*(t+p);
s++;
p++;
}
*s='\0';
}

45
VEBEIZPROGRAMSKOGJEZIKAC 2007/2008

void sredi(char *s)


{
char *t;
t=s;
while(*s && *s!='a')
{
*s=*t;
t++;
s++;
}
*s='\0';
}

void kv(char *s, int m,float *k,int dim)


{
int i;
for(i=0;i<dim;i++)
*k=*k + *(s+i);
}

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


{
char s1[50];
int m,p,q,dim;
float kvadrat=0;
FILE *out;
out=fopen("sredjeno.txt","w");

printf("Unesite string:");
gets(s1);
printf("unesite p,q i m:");
scanf("%d%d%d",&p,&q,&m);
seci(s1,p,q);
sredi(s1);
dim=strlen(s1);
kv(s1,m,&kvadrat,dim);
if (kvadrat>41*m)
fprintf(out,"%f je vece od %d",kvadrat,41*m);
else
fprintf(out,"%f nije vece od %d",kvadrat,41*m);

46
C

1
1. (++)

/* Upotreba operatora inkrementa */

#include <stdio.h>

/* funkcija main, mesto pocetka izvrsenja programa */


int main()
{
int c=5; /* definisanje promenljive */
int x;

/* demonstracija operatora inkrementa NAKON imena promenljive (postincrement) */


printf( "Vrednost promenljive c je %d\n", c );

x=c; /* dodela vrednosti */

/* ispis vrednosti promenljive x */


printf( "\nNakon naredbe x=c, vrednost promenljive x je %d\n", x );

x=c++;
printf( "\nNakon naredbe x=c++\n");
printf("\tvrednost promenljive x je %d\n", x );
printf("\tvrednost promenljive c je %d\n\n", c );

/* demonstracija operatora inkrementa PRE imena promenljive (preincrement) */


c = 5; /* dodela vrednosti */
printf( "\nVrednost promenljive c je %d\n", c );

x=++c;
printf( "\nNakon naredbe x=++c\n");
printf("\tvrednost promenljive x je %d\n", x );
printf("\tvrednost promenljive c je %d\n\n", c );

return 0;

} /* kraj funkcije main */

2
2. (--)

/* Upotreba operatora dekrementa */

#include <stdio.h>

/* funkcija main, mesto pocetka izvrsenja programa */


int main()
{
int c=5; /* definisanje promenljive */
int x;

/* demonstracija operatora dekrementa NAKON imena promenljive (postdecrement) */


printf( "Vrednost promenljive c je %d\n", c );

x=c; /* dodela vrednosti */


printf( "\nNakon naredbe x=c, vrednost promenljive x je %d\n", x );

x=c--;
printf( "\nNakon naredbe x=c--\n");
printf("\tvrednost promenljive x je %d\n", x );
printf("\tvrednost promenljive c je %d\n\n", c );

/* demonstracija operatora dekrementa PRE imena promenljive (predecrement) */


c = 5; /* dodela vrednosti */
printf( "\nVrednost promenljive c je %d\n", c );

x= --c;
printf( "\nNakon naredbe x= --c\n");
printf("\tvrednost promenljive x je %d\n", x );
printf("\tvrednost promenljive c je %d\n\n", c );

return 0;

} /* kraj funkcije main */

3
3. + -. 10.
.

1:

/* Upotreba while petlje i operatora "?" */


#include <stdio.h>

/* funkcija main, odavde pocinje izvrsavanje programa */


int main()
{
int brojac = 1; /* inicijalizacija promenljive brojac */
char znak; /* definisanje promenljive znak */

while ( brojac <= 10 ) /* sve dok je brojac manji ili jednak 10, radi */
{
znak = (brojac % 2) ? ('-') : ('+'); /* parne vrednosti +, neparne - */

/* Ispis na ekran */
printf( "%c \n", znak );

brojac++; /* inkrement brojaca, isto sto i brojac=brojac+1 */


} /* kraj while petlje */

return 0; /* povratna vrednost uspesnog zavrsetka programa */

} /* kraj funkcije main */

2. (He znak)

/* Upotreba while petlje i operatora "?" */


#include <stdio.h>

/* funkcija main, odavde pocinje izvrsavanje programa */


int main()
{
int brojac = 1; /* inicijalizacija promenljive brojac */

while ( brojac <= 10 ) /* sve dok je brojac manji ili jednak 10, radi */
{
/* Ispisi na ekran */
printf("%c\n",(brojac % 2) ? ('-'):('+')); /* parni +, neparni - */

brojac++; /* inkrement brojaca, isto sto i brojac=brojac+1 */


}/* kraj while petlje */

return 0; /* povratna vrednost uspesnog zavrsetka programa */

}/* kraj funkcije main*/

4
4.

/* Sabiranje dva broja */


#include <stdio.h>

/* funkcija main, odavde pocinje izvrsavanje programa */


int main()
{
int integer1; /* prvi broj koji unosi korisnik */
int integer2; /* drugi broj koji unosi korisnik */
int sum; /* promenljiva u kojoj ce biti smesten rezultat */

printf( "Unesite prvi broj\n" ); /* Prikazivanje poruke */


scanf( "%d", &integer1 ); /* ucitavanje unetog broja u promen. integer1 */

printf( "Unesite drugi broj\n" ); /* Prikazivanje poruke */


scanf( "%d", &integer2 ); /* ucitavanje unetog broja u prom. integer2 */

sum = integer1 + integer2; /* racunanje zbira i dodel vrednosti prom. sum */

printf( "Zbir je %d\n", sum ); /* Prikazi vrednost zbira (sum) */

return 0; /* povratna vrednost uspesnog zavrsetka programa */

} /* kraj funkcije main */

2. (He sum)

/* Sabiranje dva broja */


#include <stdio.h>

/* funkcija main, odavde pocinje izvrsavanje programa */


int main()
{
int integer1; /* prvi broj koji unosi korisnik */
int integer2; /* drugi broj koji unosi korisnik */

printf( "Unesite prvi broj\n" ); /* Prikazivanje poruke */


scanf( "%d", &integer1 ); /* ucitavanje unetog broja u promen. integer1 */

printf( "Unesite drugi broj\n" ); /* Prikazivanje poruke */


scanf( "%d", &integer2 ); /* ucitavanje unetog broja u prom. integer2 */

/* racunanje zbira i dodel vrednosti prom. integer1 */


integer1 = integer1 + integer2;

printf( "Zbir je %d\n", integer1 ); /* Prikazi vrednost zbira */

return 0; /* povratna vrednost uspesnog zavrsetka programa */

} /* kraj funkcije main */

5
3. (He sum)
/* Sabiranje dva broja */
#include <stdio.h>

/* funkcija main, odavde pocinje izvrsavanje programa */


int main()
{
int integer1; /* prvi broj koji unosi korisnik */
int integer2; /* drugi broj koji unosi korisnik */

printf( "Unesite prvi broj\n" ); /* Prikazivanje poruke */


scanf( "%d", &integer1 ); /* ucitavanje unetog broja u promen. integer1 */

printf( "Unesite drugi broj\n" ); /* Prikazivanje poruke */


scanf( "%d", &integer2 ); /* ucitavanje unetog broja u prom. integer2 */

/* racunanje zbira i prikaz vrednosti */


printf( "Zbir je %d\n", integer1 + integer2); /* Prikazi vrednost zbira */

return 0; /* povratna vrednost uspesnog zavrsetka programa */

} /* kraj funkcije main */

6
5.
(==, !=, <,<=, >, >=) .

1.
/* Upotreba if naredbe, relacionih operatora i operatora dodele */
#include <stdio.h>

/* funkcija main, odavde pocinje izvrsavanje programa */


main()
{
int num1; /* prvi broj koji unosi korisnik */
int num2; /* drugi broj koji unosi korisnik */

printf( "Unesite dva cela broja a ja cu Vam reci\n" );


printf( "u kom su oni odnosu: " );

scanf( "%d%d", &num1, &num2 ); /* citanje dva cela broja */

if( num1 == num2 )


{
printf( "%d je jednako sa to %d\n", num1, num2 );
} /* kraj if naredbe */

if( num1 != num2 )


{
printf( "%d nije jednako sa %d\n", num1, num2 );
} /* kraj if naredbe */

if( num1 < num2 )


{
printf( "%d je manje od %d\n", num1, num2 );
} /* kraj if naredbe */

if( num1 > num2 )


{
printf( "%d je vece od %d\n", num1, num2 );
} /* kraj if naredbe */

if( num1 <= num2 )


{
printf( "%d je manje ili jednako sa %d\n", num1, num2 );
} /* kraj if naredbe */

if( num1 >= num2 )


{
printf( "%d je vece ili jednako sa %d\n", num1, num2 );
} /* kraj if naredbe */

return 0; /* povratna vrednost uspesnog zavrsetka programa */

} /* kraj funkcije main */

7
2. ( if )
/* Upotreba if naredbe, relacionih operatora i operatora dodele */
#include <stdio.h>

/* funkcija main, odavde pocinje izvrsavanje programa */


main()
{
int num1; /* prvi broj koji unosi korisnik */
int num2; /* drugi broj koji unosi korisnik */

printf( "Unesite dva cela broja a ja cu Vam reci\n" );


printf( "u kom su oni odnosu: " );

scanf( "%d%d", &num1, &num2 ); /* citanje dva cela broja */

if( num1 == num2 )


printf( "%d je jednako sa to %d\n", num1, num2 );

if( num1 != num2 )


printf( "%d nije jednako sa %d\n", num1, num2 );

if( num1 < num2 )


printf( "%d je manje od %d\n", num1, num2 );

if( num1 > num2 )


printf( "%d je vece od %d\n", num1, num2 );

if( num1 <= num2 )


printf( "%d je manje ili jednako sa %d\n", num1, num2 );

if( num1 >= num2 )


printf( "%d je vece ili jednako sa %d\n", num1, num2 );

return 0; /* povratna vrednost uspesnog zavrsetka programa */

} /* kraj funkcije main */

8
6. while ++
$ $ $ $ $, # # # # #.

/* upotreba while petlje, operatora "?", ++ i -- operatora */

#include <stdio.h>

/* funkcija main, odavde pocinje izvrsavanje programa */


int main()
{
int vrsta = 10; /* definisanje i inicijalizacija promenljive vrsta */
int kolona; /* definisanje promenljive kolona */

while ( vrsta >= 1 ) /* kruzi u while petlji dve dok vrsta ne bude < 1 */
{
kolona =1; /* postavi prom. kolona na 1 pri ulasku u while petlju */
while ( kolona <= 5 ) /* sve dok je kolona manje i jednako 5... */
{
printf( "%c", (vrsta % 2) ? ('$'): ('#') ); /* Ispis na ekran */
kolona++; /* isto sto i kolona = kolona + 1 ili kolona += 1*/
} /* kraj unutrasnje while petlje */

vrsta--; /* isto sto i vrsta = vrsta 1 ili vrsta -= 1 */


printf( "\n" ); /* prelazak u novi red */
} /* kraj spoljsnje while petlje*/

return 0; /* povratna vrednost uspesnog zavrsetka programa */

} /* kraj funkcije main */

9
7. 5
. .

1 ( )

/* funkcija main, odavde pocinje izvrsavanje programa */


int main()
{
int brojac; /* Broj vrednosti koje treba uneti */
int vrednost; /* vrednost koja se unosi */
int zbir; /* suma unetih vrednosti */
int srednja_vred; /* srednja vrednost */

/* inicijalizacija */
zbir = 0; /* inicijalizacija promenljive zbir */
brojac = 1; /* inicijalizacija promenljive brojac */

/* faza obrade */
while ( brojac <= 5 ) /* sve dok je brojac manji ili jednak 5... */
{
printf( "Unesite vrednost: " ); /* Ispis poruke na ekran */
scanf( "%d", &vrednost ); /* ucitaj unetu vrednost */
zbir = zbir + vrednost ; /* dodaj unetu vrenost prom. zbir */
brojac = brojac + 1; /* inkrement promenljive brojac */
} /* kraj while petlje */

/* zavrsna faza */
srednja_vred = zbir / 5; /* celobrojno deljenje, odbacivanje decimalnog dela */

printf( "Srednja vrednost je %d\n", srednja_vred ); /* prikaz rezultata */

return 0; /* povratna vrednost uspesnog kraja programa */

} /* kraj funkcije main */

:
zbir srednja_vred ( int )
srednja_vred = zbir / 5 .

10
2 ( )

/* funkcija main, odavde pocinje izvrsavanje programa */


int main()
{
int brojac; /* Broj vrednosti koje treba uneti */
int vrednost; /* vrednost koja se unosi */
int zbir; /* suma unetih vrednosti */
float srednja_vred; /* srednja vrednost */

/* inicijalizacija */
zbir = 0; /* inicijalizacija promenljive zbir */
brojac = 1; /* inicijalizacija promenljive brojac */

/* faza obrade */
while ( brojac <= 5 ) /* sve dok je brojac manji ili jednak 10... */
{
printf( "Unesite vrednost: " ); /* Ispis poruke na ekran */
scanf( "%d", &vrednost ); /* ucitaj unetu vrednost */
zbir = zbir + vrednost ; /* dodaj unetu vrenost prom. zbir */
brojac = brojac + 1; /* inkrement promenljive brojac */
} /* kraj while petlje */

/* privremena promena tipa prom. zbir iz int u float, */


srednja_vred = (float)zbir / 5;

printf( "Srednja vrednost je %f\n", srednja_vred ); /* format %f */

return 0; /* povratna vrednost uspesnog kraja programa */

} /* kraj funkcije main */

:
zbir int srednja_vred float.
zbir/5 .
float double.
zbir int float (float)zbir.

11
3 ( srednja_vred )

/* funkcija main, odavde pocinje izvrsavanje programa */


int main()
{
int brojac; /* Broj vrednosti koje treba uneti */
int vrednost; /* vrednost koja se unosi */
int zbir; /* suma unetih vrednosti */

/* inicijalizacija */
zbir = 0; /* inicijalizacija promenljive zbir */
brojac = 1; /* inicijalizacija promenljive brojac */

/* faza obrade */
while ( brojac <= 5 ) /* sve dok je brojac manji ili jednak 10... */
{
printf( "Unesite vrednost: " ); /* Ispis poruke na ekran */
scanf( "%d", &vrednost ); /* ucitaj unetu vrednost */
zbir = zbir + vrednost ; /* dodaj unetu vrenost prom. zbir */
brojac = brojac + 1; /* inkrement promenljive brojac */
} /* kraj while petlje */

/* privremena promena tipa prom. zbir iz int u float, */


printf( "Srednja vrednost je %f\n", (float)zbir / 5 ); /* format %f */

return 0; /* povratna vrednost uspesnog kraja programa */

} /* kraj funkcije main */

12
8.
. -1.

#include <stdio.h>

/* funkcija main, odavde pocinje izvrsavanje programa */


int main()
{
int brojac; /* broj unetih vrednosti */
int vrednost; /* uneta vrednost */
int zbir; /* zbir unetih vrednosti */

float srednja_vred; /* srednja vrednost definisana kao realan broj */

/* inicijalizacija */
zbir = 0; /* inicijalizacija promenljive zbir */
brojac = 0; /* inicijalizacija promenljive brojac */

/* Obrada */
/* Procitaj prvu vrednost od korisnika */
printf( "Unesite vrednost, -1 za prekid: " ); /* Prikaz na ekran */
scanf( "%d", &vrednost ); /* Ucitaj unetu vrednost */

/* Kruzi u while petlji dok korisnik ne unese vrednost -1 */


while ( vrednost != -1 )
{
zbir = zbir + vrednost; /* dodaj unetu vrednost promenljivoj zbir */
brojac = brojac + 1; /* inkrement brojaca */

/* ucitaj sledecu vrednost od korisnika */


printf( "Unesite vrednost, -1 za prekid: " ); /* Prikaz na ekran */
scanf("%d", &vrednost); /* Ucitaj sledecu unetu vrednost */
} /* kraj while petlje */

/* zavrsna faza */
/* Ako je uneta bar jedna vrednost */
if ( brojac != 0 )
{
/* izracunaj srednju vrednost svih unetih vrednosti */
srednja_vred = ( float )zbir / brojac; /* privremena promena tipa */

/* prikazi srednju vrednost sa dve decimalne vrednosti */


printf( "Srednja vrednost je %.2f\n", srednja_vred );
} /* kraj if naredbe */
else /* Ako nije uneta ni jedna vrednost, ispis poruke */
{
printf( "Nije unesena ni jedna vrednost\n" );
} /* kraj else naredbe */

return 0; /* povratna vrednost uspesnog kraja programa */

} /* kraj funkcije main */

13
9.

#include <stdio.h>

/* funkcija main, pocetak izvrsavanja programa */


int main()
{
int a = 0x0003; /* a= 03h = 0000 0011b = 3d */
int b = 0x0022; /* b= 22h = 0010 0010b= 34d */
int c = 5;
int d;
int e;
int f = 0x0100; /* f=100h = 0001 0000 0000b = 256d */

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


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

printf("a bitsko AND b = %xh \n",a & b);


printf("a logicko AND b = %d \n",a && b);
printf("a bitsko OR b = %xh \n",a | b);
printf("a logicko OR b = %d \n",a || b);
printf("a bitsko EXOR b = %xh \n\n",a ^ b);

d = (a < b) && (b > c); /* logicko i (AND) */


printf("Vrednost logicke operacije (a < b) && (b > c) je %d \n\n",d);
e = a << 3; /* shift a za 3 u levo */
printf("Vrednost a je %x, vrednost a << 3 je %xh\n",a,e);
printf("Vrednost f je %d ili %xh\n",f,f);
f =f^(1 << 4); /* shift jedinice za 4 mesta u levo */
/* 1<<4= 0000 0001b << 4 = 0001 0000b = 10h = 16d */
/* f EXOR 16 = 100h EXOR 10h = 0001 0000 0000b EXOR 0000 0001
0000b */
printf("Vrednost f je 100h a f^(1 << 4) je %d ili %xh \n",f,f);

return 0; /* oznacava uspesan zavrsetak programa */


} /* kraj funkcije main */

14
10.
.
1,
2.
1 2

P 1

/* Upotreba do while petlje i if elseif else naredbe */


#include <stdio.h>

/* funkcija main, odavde pocinje izvrsavanje programa */


int main()
{
/* definisanje i inicijalizacija promenljivih */
int polozilo = 0; /* broj studenata koji su polozili ispit */
int palo = 0; /* broj studenata koji nisu polozili ispit */
int rezultat; /* uneta vrednost */
int izlaz=0;

do
{
printf( "Unesite rezultat ( 1=polozio, 2=pao ): " ); /* Ispis na ekran */
scanf( "%d", &rezultat );

/* Ako je rezultat 1, povecaj vrednost promenljive polozilo za 1 */


if ( rezultat == 1 )
{
polozilo = polozilo + 1;
} /* kraj if naredbe */
else if(rezultat==2)/* inace inkrementiraj vrednost promenljive palo */
{
palo = palo + 1;
} /* kraj else if*/
else
{
izlaz = 1;
}

} while ( izlaz == 0 ); /* kraj do while petlje */

/* zavrsna faza */
printf( "Broj studenata koji su polozili ispit %d\n", polozilo );
printf( "Broj studenata koji nisu polozili ispit %d\n", palo );

/* Ako je polozilo vise od 8 studenata ispisi Odlican uspeh" */


if ( polozilo > 8 )
{
printf( "Odlican uspeh\n" );
} /* kraj if */

return 0; /* povratna vrednost uspesnog zavrsetka programa */

} /* kraj funkcije main */

15
P 2

/* Upotreba do while petlje i if elseif else naredbe */


#include <stdio.h>

/* funkcija main, odavde pocinje izvrsavanje programa */


int main()
{
/* definisanje i inicijalizacija promenljivih */
int polozilo = 0; /* broj studenata koji su polozili ispit */
int palo = 0; /* broj studenata koji nisu polozili ispit */
int rezultat; /* uneta vrednost */

do
{
printf( "Unesite rezultat ( 1=polozio, 2=pao ): " ); /* Ispis na ekran */
scanf( "%d", &rezultat );

/* Ako je rezultat 1, povecaj vrednost promenljive polozilo za 1 */


if ( rezultat == 1 )
polozilo++;
else if(rezultat==2)/* inace inkrementiraj vrednost promenljive palo */
palo++;
else
break;

} while (1); /* kraj do while petlje, BESKONANA petlja */

/* zavrsna faza */
printf( "Broj studenata koji su polozili ispit %d\n", polozilo );
printf( "Broj studenata koji nisu polozili ispit %d\n", palo );

/* Ako je polozilo vise od 8 studenata ispisi Odlican uspeh" */


if ( polozilo > 8 )
printf( "Odlican uspeh\n" );

return 0; /* povratna vrednost uspesnog zavrsetka programa */

} /* kraj funkcije main */

:
do while ,
while(1). break.

16
11. for 1 10.

/* primena for petlje */


#include<stdio.h>

/* funkcija main, program pocinje da se izvrsava odavde */


int main(void)
{
int num;

printf("\tk\tk na treci stepen\n");


for(num=1; num <= 10 ;num++ )
{
printf("%5d %5d\n", num , num*num*num);
}

return 0; /* oznacava uspesan zavrsetak programa */


} /* kraj funkcije main */

12. for

/* primena for petlje, dekrement; if else if else grananje */


#include<stdio.h>

/* funkcija main, program pocinje da se izvrsava odavde */


int main(void)
{
int num;

printf("\nPreostalo je:\n");

for(num=10; num >= 1 ;num-- )


{
if( num >=5 )
printf("%2d sekundi\n", num);
else if(num > 1)
printf("%2d sekunde \n", num);
else
printf("%2d sekunda \n", num);
}
printf("\nVreme isteklo\n");
return 0; /* oznacava uspesan zavrsetak programa */
} /* kraj funkcije main */

17
13. for ++
#.

/* Upotreba for petlje */


#include <stdio.h>

/* funkcija main, program pocinje da se izvrsava odavde */


int main()
{
int x;
int y;
int i;
int j;

/* Prikaz na ekran */
printf( "Unesite dva cela broja: " );
scanf( "%d%d", &x, &y ); /* procitaj vrednosti za x i y */

for ( i = 1; i <= y; i++ ) /* broj od 1 do y */


{
for ( j = 1; j <= x; j++ ) /* broj od 1 do x */
{
printf( "#" ); /* ispisi # */
} /* kraj unutrasnje for petlje */

printf( "\n" ); /* predji u novu liniju */


} /* kraj spoljasnje for petlje */

return 0; /* oznacava uspesan zavrsetak programa */

} /* kraj funkcije main */

18
14. while 1 10

/* Upotreba while petlje */


#include <stdio.h>

/* funkcija main, pocetak izvrsavanja programa */


int main()
{
int brojac = 1; /* inicijalizacija */

while ( brojac <= 10 ) /* uslov ponavljanja */


{
printf ( "%d\n", brojac ); /* ispis vrednosti brojaca */
brojac++; /* povecaj vrednost brojaca za 1 */
} /* kraj while petlje */

return 0; /* oznacava uspesan kraj programa */

} /* kraj funkcije main */

15. fr 1 10

P 1
#include <stdio.h>

/* funkcija main, pocetak izvrsavanja programa */


int main()
{
int i;

for(i = 1; i < 11; i++) /* uslov ponavljanja */


{
printf ( "%d\n", i ); /* ispis vrednosti brojaca */
} /* kraj for petlje */

return 0; /* oznacava uspesan kraj programa */

} /* kraj funkcije main */

19
P 2

/* Upotreba for petlje */


#include <stdio.h>

/* funkcija main, pocetak izvrsavanja programa */


int main()
{
int i;

i = 1;
for( ; i < 11; i++) /* uslov ponavljanja */
{
printf ( "%d\n", i ); /* ispis vrednosti brojaca */
} /* kraj for petlje */

return 0; /* oznacava uspesan kraj programa */

} /* kraj funkcije main */

:
for (
). i (i=0) for .

P 3
/* Upotreba while petlje */
#include <stdio.h>

/* funkcija main, pocetak izvrsavanja programa */


int main()
{
int i;

i = 1;
for( ; i < 11; ) /* uslov ponavljanja */
{
printf ( "%d\n", i ); /* ispis vrednosti brojaca */
i++;
} /* kraj for petlje */

return 0; /* oznacava uspesan kraj programa */

} /* kraj funkcije main */

:
for (
). : i (i=0) for
i (i++) for .

20
4
/* Upotreba for petlje */
#include <stdio.h>

/* funkcija main, pocetak izvrsavanja programa */


int main()
{
int i;

i = 1;
for( ; ; ) /* uslov ponavljanja */
{
printf ( "%d\n", i ); /* ispis vrednosti brojaca */
i++;
if(i > 10)
break;
} /* kraj for petlje */

return 0; /* oznacava uspesan kraj programa */

} /* kraj funkcije main */

:
for (
). : i (i=0) for ,
for ( if(i > 10)break; )
i (i++) for .

16. fr 1 20.

#include <stdio.h>

/* funkcija main, pocetak izvrsavanja programa */


int main()
{
int broj; /* definisanje promenljive */

for ( broj = 2; broj < 21; broj += 2 )


{
printf("%2d\n", broj); /* ispis vrednosti */
} /* kraj for */

return 0; /* oznacava uspesan zavrsetak programa */

} /* kraj funkcije main */

21
17. fr 1 20.

#include <stdio.h>

/* funkcija main, pocetak izvrsavanja programa */


int main()
{
int broj; /* definisanje promenljive */

for ( broj = 1; broj < 21; broj += 2 )


{
printf("%2d\n", broj); /* ispis vrednosti */
} /* kraj for */

return 0; /* oznacava uspesan zavrsetak programa */


} /* kraj funkcije main */

18. fr 1 100.

/* Sumiranje sa for petljom 2+4+6+8+...+100 */


#include <stdio.h>

/* funkcija main, pocetak izvrsavanja programa */


int main()
{
int zbir= 0; /* inicijalizacija promenljive zbir */
int broj; /* broj koji se dodaje zbiru */

for ( broj = 2; broj <= 100; broj += 2 )


{
zbir += broj; /* dodaj broj zbiru */
} /* kraj for */

printf( "Suma je %d\n", zbir ); /* Ispisi zbir */

return 0; /* oznacava uspesan zavrsetak programa */

} /* kraj funkcije main */

22
19. break for

/* Upotreba naredbe break */


#include <stdio.h>

/* funkcija main, pocetak izvrsavanja programa */


int main()
{
int i; /* brojac */

/* 10 puta uradi sledece naredbe... */


for ( i = 1; i <= 10; i++ )
{
/* Ako je i jednako 5, napusti for petlju */
if ( i == 5 )
{
printf( "\nNapustam for petlju naredbom break\n");
break; /* prekid for petlje */
} /* kraj if */

printf( "%d ", i ); /* prikazi vrednost promenljive i x */


} /* kraj for */
printf( "\nNakon izlaska iz for petlje vrednost brojaca je: %d\n", i );

return 0; /* oznacava uspesan zavrsetak programa */

} /* kraj funkcije main */

20. break while


/* Upotreba naredbe break */
#include <stdio.h>

/* funkcija main, pocetak izvrsavanja programa */


int main()
{
int i=0; /* brojac */

/* 10 puta uradi sledece naredbe... */


while ( i <= 10)
{
i++;
/* Ako je i jednako 5, napusti for petlju */
if ( i == 5 )
{
printf( "\nNapustam while petlju naredbom break\n");
break; /* prekid for petlje */
} /* kraj if */

printf( "%d ", i ); /* prikazi vrednost promenljive i x */


} /* kraj for */
printf( "\nNakon izlaska iz while petlje vrednost brojaca je: %d\n", i );

return 0; /* oznacava uspesan zavrsetak programa */

} /* kraj funkcije main */

23
21. continue for

/* Upotreba naredbe continue */


#include <stdio.h>

/* funkcija main, pocetak izvrsavanja programa */


int main()
{
int i; /* brojac */

for ( i = 1; i <= 10; i++ ) /* 10 puta uradi sledece naredbe... */


{
/* Ako je i jednako 5, napusti preskoci naredbe do kraja for petlje */
if ( i == 5 )
{
printf( "\n\n Ne napustam for petlju, samo preskacem jednu vrednost\n\n");
continue; /* preskoci naredbe do kraja for petlje */
} /* kraj if */

printf( "%d\n", i ); /* prikazi vrednost promenljive i */


} /* kraj for */

return 0; /* oznacava uspesan zavrsetak programa */


} /* kraj funkcije main */

24
22. continue while

/* Upotreba naredbe continue */


#include <stdio.h>

/* funkcija main, pocetak izvrsavanja programa */


int main()
{
int i; /* brojac */

while( i <= 10) /* radi sve dok je ... */


{
/* Ako je i jednako 5, preskoci naredbe do kraja while petlje */
if ( i == 5 )
{
printf( "\n\n Ne napustam while petlju, preskacem jednu vrednost\n\n");
continue; /* preskoci naredbe do kraja while petlje */
} /* kraj if */

printf( "%d\n", i ); /* prikazi vrednost promenljive i */


} /* kraj while */

return 0; /* oznacava uspesan zavrsetak programa */


} /* kraj funkcije main */

25
C

1
isdigit, isalpha, isalnum, isxdigit

/* funkcije: isdigit, isalpha, isalnum, isxdigit */


#include <stdio.h>
#include <ctype.h>

int main()
{
printf( "%s\n%s%s\n%s%s\n\n", "Prema funkciji isdigit: ",
isdigit('8') ? ("8 je ") : ("8 nije "), "cifra",
isdigit('#') ? ("# je ") : ("# nije "), "cifra" );

printf( "%s\n%s%s\n%s%s\n%s%s\n%s%s\n\n", "Prema funkciji isalpha:",


isalpha( 'A' ) ? "A je " : "A nije ", "slovo",
isalpha( 'b' ) ? "b je " : "b nije ", "slovo",
isalpha( '&' ) ? "& je " : "& nije ", " slovo",
isalpha( '4' ) ? "4 je " : "4 nije ", "slovo" );

printf( "%s\n%s%s\n%s%s\n%s%s\n\n", "Prema funkciji isalnum:",


isalnum( 'A' ) ? "A je " : "A nije ", "cifra ili broj",
isalnum( '8' ) ? "8 je " : "8 nije ", "cifra ili broj",
isalnum( '#' ) ? "# je " : "# nije ", "cifra ili broj" );

printf( "%s\n%s%s\n%s%s\n%s%s\n%s%s\n%s%s\n", "Prema funkciji isxdigit:",


isxdigit( 'F' ) ? "F je " : "F nije ", "heksadecimalna cifra",
isxdigit( 'J' ) ? "J je " : "J nije ", "heksadecimalna cifra",
isxdigit( '7' ) ? "7 je " : "7 nije ", "heksadecimalna cifra",
isxdigit( '$' ) ? "$ je " : "$ nije ", "heksadecimalna cifra",
isxdigit( 'f' ) ? "f je " : "f nije ", "heksadecimalna cifra" );

return 0; /* uspesan zavrsetak programa */

} /* kraj funkcije main */

2
islower, isupper, tolower, toupper

#include <stdio.h>
#include <ctype.h>

int main()
{
printf( "%s\n%s%s\n%s%s\n%s%s\n%s%s\n\n", "Prema funkciji islower:",
islower( 'p' ) ? "p je " : "p nije ", "malo slovo",
islower( 'P' ) ? "P je " : "P nije ", "malo slovo",
islower( '5' ) ? "5 je " : "5 nije ", "malo slovo",
islower( '!' ) ? "! je " : "! nije ", "malo slovo" );

printf( "%s\n%s%s\n%s%s\n%s%s\n%s%s\n\n", "Prema fukciji isupper:",


isupper( 'D' ) ? "D je " : "D nije ", "veliko slovo",
isupper( 'd' ) ? "d je " : "d nije ", "veliko slovo",
isupper( '8' ) ? "8 je " : "8 nije ", "veliko slovo",
isupper( '$' ) ? "$ je " : "$ nije ", "veliko slovo" );

printf( "%s%c\n%s%c\n%s%c\n%s%c\n",
"m konvertovano u veliko slovo je ", toupper( 'm' ),
"7 konvertovano u veliko slovo je ", toupper( '7' ),
"$ konvertovano u veliko slovo je ", toupper( '$' ),
"K konvertovano u malo slovo je ", tolower( 'K' ) );

return 0; /* oznacava uspesan zavrsetak */

} /* kraj funkcije main */

3
isspace, isgraph

#include <stdio.h>
#include <ctype.h>

int main()
{
printf( "%s\n%s%s%s\n%s%s%s\n%s%s\n\n", "Prema funkciji isspace:",
"Novi red", isspace('\n') ? " je " : " nije ", "beli znak",
"Tab", isspace('\t') ? " je " : " nije ", "beli znak",
isspace( '%' ) ? "% je " : "% nije ", "beli znak" );

printf( "%s\n%s%s\n%s%s%s\n", "Prema funkciji isgraph:",


isgraph( 'Q' ) ? "Q je " : "Q nije ", "stampajuci znak ",
"Space", isgraph( ' ' ) ? " je " : " nije ", "stampajuci znak " );

return 0; /* uspesan zavrsetak programa */

} /* kraj funkcije main */

"99.50" double
double 3 .

#include <stdlib.h>

int main()
{
char str_a[]="99.50";
double nova; /* promenljiva koja cuva konvertovani string */

nova = atof(str_a);

printf("String \"%s\" konvertovan u double je %.2f\n", str_a, nova);


printf("Konvertovana vrednost podeljena sa 3 je %.2f\n",nova/3 );

return 0; /* uspesan zavrsetak programa */

} /* kraj funkcije main */

: printf
( printf("String \"%s\"...)

4
"3245" int int
245 .

#include <stdio.h>
#include <stdlib.h>

int main()
{
char str_a[]="3245";
int celo; /* promenljiva koja cuva konvertovani string */

celo = atoi(str_a);

printf("String \"%s\" konvertovan u integer je %d\n", str_a, celo);


printf("Konvertovana vrednost minus 245 je %d\n",celo -245 );

return 0; /* uspesan zavrsetak programa */


} /* kraj funkcije main */

1:

#include<stdio.h>
#include<string.h>

int main()
{
char linija_teksta[80]; /* definisanje niza od 80 elemenata */
char *ptr; /* pokazivac na char promenljivu */
int indeks_poklapanja;
int i;

printf( "Unesite jednu liniju teksta:\n" );

/* Primena funkcije gets da se u zadati niz ucita jedna linija teksta */


gets(linija_teksta);

/* Primena funkcije strchr da se u zadatom nizu pronadje pozicija (indeks) prvog


pojavljivanja zadatog karaktera, ovde trazimo kraj stringa ili karakter '\0' */
ptr=strchr(linija_teksta, '\0');

indeks_poklapanja=ptr - linija_teksta - 1;
/* moze i ovako: indeks_poklapanja=ptr-&linija_teksta[0] - 1; ili
indeks_poklapanja=ptr-&linija_teksta - 1; */

printf( "\nLinija odstampana unazad je:\n" );

for(i=indeks_poklapanja;i>=0;i--)
{
printf("%c", linija_teksta[i]);
}

printf("\n");
return 0; /* oznacava uspesan kraj programa */
} /* kraj funkcije main */

5
2:

#include<stdio.h>
#include<string.h>

int main()
{
char linija_teksta_a[80]; /* definisanje niza od 80 elemenata */
char linija_teksta_b[80]; /* definisanje niza od 80 elemenata */
char *ptr; /* pokazivac na char promenljivu */
int indeks_poklapanja;
int i;

printf( "Unesite jednu liniju teksta:\n" );

/* Primena funkcije gets da se u zadati niz ucita jedna linija teksta */


gets(linija_teksta_a);

/* trazimo kraj stringa ili ADRESU na kojoj se nalazi karakter '\0' */


ptr=strchr(linija_teksta_a, '\0');

/* indeks se dobija kao razlika adresa */


indeks_poklapanja=ptr - linija_teksta_a - 1;

printf( "\nLinija odstampana unazad je:\n" );

/* u niz linija_teksta_b upisi unazad sadrzaj niza linija teksta_a */


/* for petlja ima samo jednu naredbu, moze i bez { } */
for(i=0;i<=indeks_poklapanja;i++)
linija_teksta_b[i]=linija_teksta_a[indeks_poklapanja-i];

/* string mora da se zavrsi nul karakterom! */


linija_teksta_b[i]='\0';

/* Primenom funkcije puts ispisujemo sadrzaj stringa */


/* puts zamenjuje '\0' sa '\n' pa automatski imamo novi red! */
puts(linija_teksta_b);

return 0; /* oznacava uspesan kraj programa */

} /* kraj funkcije main */

6
.

/* Primena funkcija getchar i puts */


#include <stdio.h>

int main()
{
char znak; /* promen. u koju se upisuje znak koji unese korisnik */
char recenica[80]; /* niz od 80 elemenata */
int i = 0; /* brojac inicijalizovan na 0 */

/* Ispis poruke na monitor */


puts( "Unesite jednu liniju teksta:" );

/* Inicijalizacija promenljive znak */


znak=' ';

/* Primena funkcije getchar da se procita svaki uneti znak (character) */


while (znak != '\n') /* radi sve dok se ne pritisne ENTER */
{
znak = getchar(); /* ucitaj jedan znak */
recenica[i] = znak; /* upisi ucitani znak u niz*/
i++;
} /* kraj while petlje */

recenica[i] = '\0'; /* string se mora zavrsit ovim znakom */

/* funkcija puts ispisuje sadrzaj stringa na monitor */


puts( "\nUneli ste sledeci tekst:" );
puts(recenica);

return 0; /* oznacava uspesan zavrsetak programa */


} /* karaj funkcije main */

7
2
#include <stdio.h>

int main()
{
char znak; /* promen. u koju se upisuje znak koji unese korisnik */
char recenica[80]; /* niz od 80 elemenata */
int i = 0; /* brojac inicijalizovan na 0 */

/* Ispis poruke na monitor */


puts( "Unesite jednu liniju teksta:" );

/* Primena funkcije getchar da se procita svaki uneti znak (character) */


while ( ( znak = getchar() ) != '\n')
{
recenica[i++] = znak;
} /* kraj while petlje */

recenica[i] = '\0'; /* string se mora zavrsit ovim znakom */

/* funkcija puts ispisuje sadrzaj stringa na monitor */


puts( "\nUneli ste sledeci tekst:" );
puts(recenica);

return 0; /* oznacava uspesan zavrsetak programa */


} /* karaj funkcije main */

Happy Birthday to You x . : y z.


strcpy x y, 14 y
z. .

1
/* Primena funkcija strcpy i strncpy */
#include <stdio.h>
#include <string.h>

int main()
{
char x[] = "Happy Birthday to You"; /* inicijalizacija niza x */
char y[ 25 ]; /* definisanje niza y */
char z[ 15 ]; /* definisanje niza z */

printf( "%s %s\n", "Sadrzaj stringa x je:", x);

strcpy( y, x ); /* kopiraj sadrzaj stringa x u string y */

printf( "%s %s\n","Sadrzaj stringa y je:", y);

/* Kopiraj prvih 14 karaktera iz x u z. Ne kopira se null character! */


strncpy( z, x, 14 );

z[14] = '\0'; /* dodaj nul karakter stringu z */


printf( "String u nizu z je: %s\n", z );

return 0; /* oznacava uspesan zavrsetaka programa */


} /* kraj fukcije main */

8
2

#include <stdio.h>
#include <string.h>

int main()
{
char x[] = "Happy Birthday to You"; /* inicijalizacija niza x */
char y[ 25 ]; /* definisanje niza y */
char z[ 15 ]; /* definisanje niza z */

puts("Sadrzaj stringa x je:");


puts(x);

/* kopiraj sadrzaj stringa x u string y */


strcpy( y, x );

puts("\nSadrzaj stringa y je:");


puts(y);

/* Kopiraj prvih 14 karaktera iz x u z. Ne kopira se null character! */


strncpy( z, y, 14 );

z[14] = '\0'; /* dodaj nul karakter stringu z */


puts( "\nString u nizu z je:");
puts(z);

return 0; /* oznacava uspesan zavrsetaka programa */

} /* kraj fukcije main */

9
() s1 20 "Srecna ",
() s2 "Nova godina " s3
40 "". strcat s1 s2,
. 7 s1 s3
s3. s3 s1
s3.

/*strcat, strncat */
#include <stdio.h>
#include <string.h>

int main()
{
char s1[20] = "Srecna "; /* inicijalizacija niza s1 */
char s2[] = "Nova godina "; /* inicijalizacija niza s2 */
char s3[40] = ""; /* inicijalizacija niza s3 "prazn" niz */

/* Ispis sadrzaja stringova s1 i s2*/


printf( "s1 = %s \ns2 = %s \n", s1, s2 );

/* na sadrzaj stringa s1 dopisi sadrzaj stringa s2 */


strcat( s1, s2 );

/* ispisi sadrzaj stringa s1 */


printf( "Nakon naredbe strcat(s1, s2),\t sadrzaj stringa s1 je: %s\n", s1 );

/* dopisi prvih 7 karaktera stringa s1 u string s3.*/


strncat( s3, s1, 7);
printf( "Nakon naredbe strncat(s3,s1,7),\t sadrzaj stringa s3 je: %s\n",s3);

/* na sadrzaj stringa s3 dopisi sadrzaj stringa s1 */


strcat( s3, s1);
printf( "Nakon naredbe strcat(s3, s1),\t sadrzaj stringa s3 je: %s\n",s3);

return 0; /* Oynacava uspesan zavrsetak programa */

} /* kraj funkcije main */

10
() s1 "Happy New Year".
() s2 "Happy New Year". () s3
" Happy Holidays". strcmp
.

#include <stdio.h>
#include <string.h>

int main()
{
const char s1[] = "Happy New Year"; /* inicijalizacija stringa */
const char s2[] = "Happy New Year"; /* inicijalizacija stringa */
const char s3[] = "Happy Holidays"; /* inicijalizacija stringa */

printf("%s %s\n","Sadrzaj stringa s1 je:", s1);


printf("%s %s\n","Sadrzaj stringa s2 je:", s2);
printf("%s %s\n","Sadrzaj stringa s3 je:", s3);

printf("\nRezultat funkcije %s je: %2d","strcmp(s1, s2) = ", strcmp( s1, s2 ) );


printf("\nRezultat funkcije %s je: %2d","strcmp(s1, s3) = ", strcmp( s1, s3 ) );
printf("\nRezultat funkcije %s je: %2d\n","strcmp(s3, s1) = ", strcmp( s3, s1 ) );

return 0;

} /* kraj funkcije main */

strchr 'n' 'z' "Ovo je jedan test"

/* strchr */
#include <stdio.h>
#include <string.h>

int main()
{
const char niz_znakova[] = "Ovo je jedan test"; /* inicijalizacija niza */
char znak1 = 'n';
char znak2 = 'z';

/* Ako je znak1 (karakter) pronadjen u stringu... */


if ( strchr( niz_znakova, znak1 ) != NULL )
printf( "Znak \'%c\' je pronadjen u stringu \"%s\".\n", znak1, niz_znakova);
else /* ako znak1 nije pronadjen */
printf( "Znak \'%c\' nije pronadjen u stringu \"%s\".\n",znak1,niz_znakova);

/* Ako je znak2 (karakter) pronadjen u stringu... */


if ( strchr( niz_znakova, znak2 ) != NULL )
printf( "znak \'%c\' je pronadjen u stringu \"%s\".\n", znak2, niz_znakova);
else /* ako znak2 nije pronadjen */
printf( "Znak \'%c\' nije pronadjen u stringu \"%s\".\n",znak2,niz_znakova);

return 0;
} /* kraj funkcije main */

11
strstr "def"
"abcdefabcdef"

/* strstr */
#include <stdio.h>
#include <string.h>

int main()
{
char str1[] = "abcdefabcdef"; /* string koji se pretrazuje */
char str2[] = "def"; /* string koji se trazi */
char *pch;

printf( "%s \"%s\"\n", "string1 = ", str1);


printf( "%s \"%s\"\n", "string2 = ", str2);

pch=str1; /* pch=&str1[0] ili pch=&str1; ; */

do
{
pch=strstr(pch, str2);
if(pch != NULL)
{
printf("String \"%s\" se nalazi u stringu \"%s\" na poziciji %2d\n",
str2, str1, pch-str1+1);
pch++;
} /* kraj if naredbe */
}while(pch != NULL);

return 0;
} /* kraj funkcije main */

strlen : "abcdefghijklmnopqrstuvwxyz", "tri"


"Kikinda"

/* strlen */
#include <stdio.h>
#include <string.h>

int main()
{
/* initialize 3 char pointers */
const char str1[] = "abcdefghijklmnopqrstuvwxyz";
const char str2[] = "tri";
const char str3[] = "Kikinda";

printf("%s \"%s\" %s %d\n","Duzina stringa", str1, "je", strlen(str1));


printf("%s \"%s\" %s %d\n","Duzina stringa", str2, "je", strlen(str2));
printf("%s \"%s\" %s %d\n","Duzina stringa", str3, "je", strlen(str3));

return 0; /* oznacava uspesan zavrsetak */

} /* kraj funkcije main */

12
C


1. 1 10.
.

/* Kreiranje i primena funkcije */


#include <stdio.h>

int kvadrat( int y ); /* deklaracija ili prototip funkcije */

/* funkcija main, mesto pocetka izvrsavanja programa */


int main()
{
int x; /* brojac */

/* 10 pita izracunaj i ispisi kvadrat x */


for (x = 1; x <= 10; x++)
{
printf( "%d ", kvadrat(x) ); /* poziv funkcije */
} /* kraj for petlje */

printf( "\n" );

return 0; /* oznacava uspesan zavrsetak programa */

} /* kraj main */

/* funkcija kvadrat, definicija */


int kvadrat(int y) /* u y se kopira vrednost x */
{
return y*y; /* vraca kvadrat y kao int */
} /* kraj funkcije kvadrat */
2. .

/* Pronalazenje maksimuma od tri broja */

#include <stdio.h>

int maximum( int x, int y, int z ); /* prototip funkcije */

/* funkcija main, mesto pocetka izvrsavanja programa */


int main()
{
int number1; /* prvi broj */
int number2; /* drugi broj */
int number3; /* treci broj */

printf( "Unesite tri cela broja: " );


scanf( "%d%d%d", &number1, &number2, &number3 );

/* number1, number2 i number3 su argumenti pri pozivu funk. maximum */


printf( "Maksimalna vrednost je: %d\n", maximum( number1, number2, number3 ) );

return 0; /* oznacava uspesan zavrsetak programa */

} /* kraj funkcije main */

/* Funkcija maximum, definicija */


/* x, y z su formalni argumenti */
int maximum( int x, int y, int z )
{
int max = x; /* pretpostavimo da je x najveci broj */

if(y > max) /* ako je y veci onda je max jednak y */


{
max = y;
} /* kraj if */

if(z > max) /* ako je z vece od max, onda je max jednak z */


{
max = z;
} /* kraj if*/

return max; /* max je najveca vrednost */

} /* kraj funkcije maximum */


3. :

1
2 1
3 2 1
4 3 2 1
5 4 3 2 1
6 5 4 3 2 1
7 6 5 4 3 2 1
8 7 6 5 4 3 2 1
9 8 7 6 5 4 3 2 1
10 9 8 7 6 5 4 3 2 1
() broji_unazad( int x)
.

/* prenos argumenta po vrednosti*/


#include <stdio.h>

void broji_unazad(int x); /* prototip funkcije */

int main()
{
int br;

for (br=1; br <= 10; br++)


{
broji_unazad(br);
}

return 0;
} /* kraj funkcije main */

void broji_unazad(int x) /* definicija funkcije */


{
int i;

for (i = x; i > 0; i--)


{
printf("%d", x);
x--;
}

putchar('\n'); /* novi red */


} /* kraj funkcije broji_unazad */
4.

void zameni(int *a, int *b); /* prototip funkcije */

#include <stdio.h>

int main()
{
int x=6, y=10;

printf("Pre poziva funkcije, x = %d i y = %d\n\n", x, y);

zameni(&x, &y); /* Poziv funkcije i prosledjivanje promen. po adresi */

printf("Nakon povratka iz funkcije x = %d i y = %d\n\n", x, y);

return 0;
} /* kraj funkcije main */

/* definicija funkcije */
void zameni(int *a, int *b) /* funkcija nema povratnu vrednost, tip void */
{
/* u promenljivu a je preslikana adresa promen. x */
/* u promenljivu b je preslikana adresa promen. y */

int temp;

temp= *a; /* u promen. temp upisi vrednost na koju pokazuje pointer a, tj.
vrednost prom. x */
*a = *b; /* na adresu na koju ukazuje pointer a upisi vrednost sa adrese
na koju ukazuje pointer b */
*b = temp; /* na adresu na koju ukazuje pointer b upisi vrednost promen. temp*/
} /* kraj funkcije zameni */
5. 1 6.
( ). rand().

rand
.
()
int rand( void );
(Return)
0 RAND_MAX.
(32767), <stdlib.h>.
srand
rand.
:

#include <stdio.h>
#include <stdlib.h>

/* funkcija main, mesto pocetka izvrsavanja programa */


int main()
{
int i; /* brojac */

/* ponovi 20 puta */
for ( i = 1; i <= 20; i++ )
{
/* uzmi slucajan (random) broj izmedju 1 i 6 i ispisi ga */
printf( "%10d", 1 + ( rand() % 6 ) ); /* moduo po 6 daje vrednosti od 0 do 5 */

/* ako je brojac deljiv sa 5, predji u novi red */


if(i % 5 == 0)
{
printf( "\n" );
} /* kraj if */
} /* kraj for */

return 0; /* oznacava uspesan zavrsetak programa */

} /* kraj funkcije main */

. rand?

6. 1 6 rand() 6000
.
:

#include <stdio.h>
#include <stdlib.h>

/* funkcija main, mesto pocetka izvrsavanja programa */


int main()
{
int frekvencija1 = 0; /* brojac pojavljivanja broja 1 */
int frekvencija2 = 0; /* brojac pojavljivanja broja 2 */
int frekvencija3 = 0; /* brojac pojavljivanja broja 3 */
int frekvencija4 = 0; /* brojac pojavljivanja broja 4 */
int frekvencija5 = 0; /* brojac pojavljivanja broja 5 */
int frekvencija6 = 0; /* brojac pojavljivanja broja 6 */

int i;
int vrednost; /* dobijena vrednost od generatora pseudoslucajnih brojeva 6 */

/* ponovi 6000 puta i daj rezultat */


for (i = 1; i<=6000; i++ )
{
vrednost = 1 + rand() % 6; /* pseudosl. broj od 1 do 6 */
/* odredi vrednost i povecaj odgovarajuci brojac */
switch ( vrednost )
{
case 1: /* dobijena jedinica */
++frekvencija1;
break;
case 2: /* dobijena dvojka */
++frekvencija2;
break;
case 3: /* dobijena trojka */
++frekvencija3;
break;
case 4: /* dobijena cetvorka */
++frekvencija4;
break;
case 5: /* dobijena petica */
++frekvencija5;
break;
case 6: /* dobijena sestica */
++frekvencija6;
break;
} /* kraj switch */
} /* kraj for */

/* prikazi rezultat u tabelarnom formatu */


printf( "%s%13s\n", "Vrednost", "Frekvencija" );
printf( " 1%13d\n", frekvencija1 );
printf( " 2%13d\n", frekvencija2 );
printf( " 3%13d\n", frekvencija3 );
printf( " 4%13d\n", frekvencija4 );
printf( " 5%13d\n", frekvencija5 );
printf( " 6%13d\n", frekvencija6 );
return 0;/* oznacava uspesan zavrsetak programa */
} /* kraj funkcije main */
7. , ,
#include <stdio.h>
#include <stdlib.h>

/* funkcija main, mesto pocetka izvrsavanja programa */


int main()
{
int frekvencija[7] = {0,0,0,0,0,0,0}; /* brojac pojavljivanja brojva 1 do 6 */

int i;
int vrednost; /* dobijena vrednost od generatora pseudoslucajnih brojeva 6 */

/* ponovi 6000 puta i daj rezultat */


for (i = 1; i<=6000; i++ )
{
vrednost = 1 + rand() % 6; /* pseudosl. broj od 1 do 6 */
/* odredi dobijenu vrednost i povecaj odgovarajuci brojac */
++frekvencija[vrednost];
} /* kraj for */

/* prikazi rezultat u tabelarnom formatu */


printf( "%s%13s\n", " Vrednost", "Frekvencija" );

for(i=1;i<7;i++)
printf( "\t%d%13d\n", i,frekvencija[i] );

return 0;/* oznacava uspesan zavrsetak programa */


} /* kraj funkcije main */
8. .
rand .
(
) ( ), .
rand
srand(unsigned int), unsigned int
rand. srand(unsigned int)

#include <stdlib.h>
#include <stdio.h>

/* funkcija main, mesto pocetka izvrsavanja programa */


int main()
{
int i; /* brojac */
unsigned int seed; /* broj koji odredjuje mesto pocetka rada rand generatora */

printf( "Unesite vrednost parametra za rand generator: " );


scanf( "%u", &seed ); /* primetite %u za unsigned int */

srand( seed ); /* postavi pocetnu vrednost rand generatora */

/* petlja 10 puta */
for ( i = 1; i <= 10; i++ )
{
/* uzmi slucajnu vrednost od 1 do 6 i ispisi je */
printf( "%10d", 1 + ( rand() % 6 ) );

/* ako je brojac deljiv sa 5 predji u novi red */


if ( i % 5 == 0 )
{
printf( "\n" );
} /* kraj if */
} /* kraj for */

return 0; /* oznacava uspesan zavrsetak programa */


} /* kraj main */
9. .
rand .
srand .
time(NULL) .
( ) (00:00:00), 1. 1970. . A NULL
time .

#include <stdlib.h>
#include <stdio.h>
#include <time.h> /* sadrzi prototip funkcije time */

/* funkcija main, mesto pocetka izvrsavanja programa */


int main()
{
int i; /* brojac */

srand(time(NULL)); /* postavi pocetnu vrednost rand generatora svaki put kad se


pokrene program na drugu vrednost*/

/* petlja 10 puta */
for(i = 1; i <= 10; i++)
{
/* uzmi slucajnu vrednost od 1 do 6 i ispisi je */
printf( "%10d", 1 + ( rand() % 6 ) );

/* ako je brojac deljiv sa 5 predji u novi red */


if( i % 5 == 0 )
{
printf( "\n" );
} /* kraj if */
} /* kraj for */

return 0; /* oznacava uspesan zavrsetak programa */


} /* kraj main */
10.
. .
. n
n! :
n! =n*(n-1)*(n-2)*(n-3)*...*1
1! = 1
0! = 1
:
5! = 5*4*3*2*1= 120

broj for :

faktorijel = 1;
for(i=broj; i>=1; i--)
{
faktorijel *= i; /* faktorijel = faktorijel * i; */
}

:
:
5! = 5*4*3*2*1= 5*(4*3*2*1) = 5*(4!)
4!= 4*3*2*1=4*(3*2*1) = 4*(3!)
3! = 3*2*1=3*(2*1) = 3*(2!)
2! = 2*1=2*(1) = 2*(1!)
1! = 1
...
#include <stdio.h>

long faktorijel(long broj); /* prototip funkcije */

/* funkcija main, mesto pocetka izvrsavanja programa */


int main()
{
int i; /* brojac */

/* 11 puta ponovi naredbe, svaki put izracunaj faktorijel(i) i ispisi rezultat */


for ( i = 0; i <= 10; i++ )
{
printf("%2d! = %ld\n", i, faktorijel(i) ); /* poziv funkcije faktorijel i */
} /* kraj for */

return 0; /* oznacava uspesan zavrsetak programa */

} /* kraj funkcije main */

/* Definicija rekurzivne funkcije faktorijel */


long faktorijel(long broj)
{
/* ako je broj 0 ili 1, 0!=1 i 1!=1 */
if( broj <= 1 )
{
return 1; /* vrati 1 i zavrsi rada sa funkcijom */
} /* kraj if */
else /* jedan korak rekurzije */
{
return (broj * faktorijel(broj - 1) ); /* rekurzivni poziv funkcije */
} /* kraj else */

} /* kraj funkcije faktorijel */

faktorijel 0 10.
broj 1 0, 1
faktorijel.
(broj) 1 return(broj*faktorijel(broj-1));
faktorijel (broj-1)
11. .

Fibonacci- 0 1
, .
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...

fibonacci( i )

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

#include <stdio.h>

long fibonacci( long broj ); /* prototip funkcije */

/* funkcija main, mesto pocetka izvrsavanja programa */


int main()
{
long rezultat; /* fibonacci vrednost */
long indeks; /* broj koji unosi korisnik */

/* Uzmi broj od korisnika */


printf( "Unesite celi broj: " );
scanf( "%ld", &indeks );

/* Izracunaj fibonacci vrednost ya uneti broj */


rezultat = fibonacci(indeks);

/* prikazi rezltat */
printf( "Fibonacci( %ld ) = %ld\n", indeks, rezultat );

return 0; /* oznacava uspesan zavrsetak programa */

} /* kraj funkcije main */

/* definicija rekurzivne funkcije fibonacci */


long fibonacci(long broj)
{
long i;
long n_minus1=1, n_minus2=0, n;

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

for(i=1;i<broj;i++)
{
n=n_minus1+n_minus2;
n_minus2=n_minus1;
n_minus1=n;
}
return n;
} /* kraj funkcije fibonacci */
2

#include <stdio.h>

long fibonacci(long broj); /* prototip funkcije */

/* funkcija main, mesto pocetka izvrsavanja programa */


int main()
{
long rezultat; /* fibonacci vrednost */
long indeks; /* broj koji unosi korisnik */

/* Uzmi broj od korisnikao */


printf( "Unesite celi broj: " );
scanf( "%ld", &indeks );

/* Izracunaj fibonacci vrednost ya uneti broj */


rezultat = fibonacci( indeks );

/* prikazi rezltat */
printf( "Fibonacci( %ld ) = %ld\n", indeks, rezultat );

return 0; /* oznacava uspesan zavrsetak programa */


} /* kraj funkcije main */

/* definicija rekurzivne funkcije fibonacci */


long fibonacci(long n)
{
/* osnovni slucaj */
if(n == 0 || n == 1)
{
return n;
} /* kraj if */
else
{ /* rekurzija */
return fibonacci(n - 1) + fibonacci(n - 2);
} /* kraj else */
} /* kraj funkcije fibonacci */
12. .

#include <stdio.h>
#include <string.h> /* potrebno zbog funkcije strchr() */
#include<stdlib.h> /* potrebno zbog funkcije atoi() */
#include <ctype.h> /* potrebno zbog funkcije isdigit() */

int ucitaj_datum(int *d, int *m, int *g ); /* prototip funkcije*/


int proveri_datum( int xd, int ym, int yg ); /* prototip funkcije*/

int main()
{
int dan;
int mesec;
int godina;
int pom;

pom=ucitaj_datum(&dan, &mesec, &godina); /* poziv funkcije, unos podataka */

/* ako je po formatu korektno unet datum poroveri da li je moguc */


if(!pom) /* funkcija vraca vrednost u pom */
pom =proveri_datum(dan, mesec, godina); /* poziv funkcije, provera unosa */

switch(pom) /* i druga funkcija vraca vrednost u pom */


{
case 1:
printf("\n");
break;
case 2:
printf("Niste uneli odgovarajuci mesec\n\b");
break;
case 3:
printf("Niste uneli odgovarajuci dan u mesecu\n\b");
break;
default:
printf("Uneti datum je korektan!\n");
break;
}
return 0;
} /* kraj funkcije main*/
/* definicija funkcije ucitaj_datum */
int ucitaj_datum(int *d, int *m, int *g )
{
char niz[80];
char podniz[5];
int kontrola;
int duzina;
int i;
char *ptr;

kontrola=1;

do
{
printf("\nUnesite datum u formatu dd.mm.gggg ili dd.mm.gg, x za prekid\n" );
gets(niz); /* ucitaj unos korisnika */
duzina=strlen(niz); /* odredi broj unetih karaktera */

/* zahtev korisnika za prekid programa*/


if(niz[0]=='x' || niz[0]=='X')
return 1;

/* da li je broj unetih karaktera odgovarajuci? */


if(duzina != 10 )
printf("Broj unetih vrednosti nije odgovarajuci\n", duzina);
else
kontrola=0; /* ok */

/* Ako je broj unetih karaktera odgovarajuci... */


if(!kontrola)
{
/* da li je pozicija delimitera na pravom mestu (3. i 6.) */
ptr=strchr(niz, '.'); /* pozicija prvog delimitera */
if((ptr - niz+1) != 3)
{
printf("Pozicija delimitera ('.') nije odgovarajuca");
kontrola=1; /* greska u formatu */
}

if(!kontrola)
{
ptr=strchr(ptr+1, '.'); /* pozicija drugog delimitera */
if((ptr - niz+1) != 6)
{
printf("Pozicija delimitera ('.') nije odgovarajuca");
kontrola=1;
}
}
}
if(kontrola)
continue;

for(i=0; i<10;i++) /* da li su na svim pozicijama (sem 3 i 6) brojevi */


{
if(i==2 || i==5)
continue;

if( !( isdigit(niz[i]) ) )
{
printf("datum moze sadrzati samo brojeve\n");
kontrola =1;
break;
}
}

/* ako je format odgovarajuci, izdvoj podtke o danu mesecu i godini */


if(!kontrola)
{
strncpy( podniz, niz ,2);
podniz[2]='\0';
*d=atoi(podniz);
strncpy( podniz, niz+3 ,2);
podniz[2]='\0';
*m=atoi(podniz);
strncpy( podniz, niz+6 ,4);
podniz[4]='\0';
*g=atoi(podniz);

/* ukoliko je bar jedna od vrednosti 0 (uneto 00 ili slovo).. */


if( !(*d && *m && *g ) )
{
printf("Unete vrednosti moraju bit brojevi razliciti od 00 odnosno 0000\n");
kontrola =1;
}
}

}while(kontrola);

return 0;
}
int proveri_datum( int xd, int ym, int yg )
{

int max_dana;
int prestupna=0;

/* proveri da li je godnia prestupna */


if((yg % 4)==0)
prestupna =1;

/* utvrdi maks broj dana u mesecu */


if(ym>12)
return 2; /* mesec nije odgovarajuci*/

switch(ym)
{
case 4:
case 6:
case 9:
case 11:
max_dana = 30;
break;
case 2:
if (prestupna)
max_dana=29;
else
max_dana=28;
break;
default:
max_dana=31;
break;
}
if(xd>max_dana)
return 3; /* broj dana u mesecu nije odgovarajuci */

return 0;
}
C

1. 10 50 for ,
.

/* Inicijalizacija niza */
#include <stdio.h>

/* funkcija main, pocetak izvrsavanja programa */


int main()
{
int n[10]; /* n je niz od 10 celih brojeva */
int i; /* brojac */

/* inicijalizacija elementa niza na vrednost 50 */


for ( i = 0; i < 10; i++ )
{
n[ i ] = 50; /* dodeli vrednost e0 elementu niza sa indeksom i */
} /* kraj for petlje */

printf( "%s %11s \n\n", "Niz n", "Vrednost" ); /* %s je format za string */


printf("-----------------\n"); /* ispis crtica */

/* ispis vrednosti elemenata niza u obliku tabele */


for ( i = 0; i < 10; i++ )
{
printf( "n[%d] %6d\n", i, n[ i ] );
} /* kraj for */

return 0; /* oznacava uspesan zavrsetak programa */


} /* kraj funkcije main */

2. 2x5 1, 2, 3, 4, 5 2, 4, 6,
8, 10, .

#include <stdio.h>
int main()
{
/* Deklarisanje niza dimenzija 2 x 5 */
int x[2][5] = { {1, 2, 3, 4, 5},
{2, 4, 6, 8, 10} };

int red, kolona;

/* Prikaz elemenata niza po redovima */


for (red=0; red<2; red++)
{
/* Prikaz elemenata niza po kolonama */
for (kolona=0; kolona<5; kolona++)
{
printf("%2d\t", x[red][kolona]);
} /* kraj unutrasnje for petlje */
printf("\n"); /* putchar('\n');*/
} /* kraj spoljasnje for petlje */
return 0;
}/* kraj funkcije main */
3.

/* Inicijalizacija niza */
#include <stdio.h>

/* funkcija main, pocetak izvrsavanja programa */


int main()
{
int n[ 10 ] = { 32, 27, 64, 18, 95, 14, 90, 70, 60, 37 };
int i; /* brojac */

printf( "%s%13s\n\n", "Niz n", "Vrednost" );

/* ispis vrednosti elemenata niza u obliku tabele */


for ( i = 0; i < 10; i++ )
{
printf( "n[%d] %6d\n", i, n[ i ] );
} /* kraj for */

return 0; /* oznacava uspesan zavrsetak programa */


} /* kraj funkcije main */

4. 2 20

/* Inicijalizacija niza parnim brojevima od 2 do 20 */


#include <stdio.h>
#define SIZE 10

int main()/* funkcija main, pocetak izvrsavanja programa */


{
int s[ SIZE ];
int i; /* brojac */

for(i = 0; i < SIZE; i++) /* dodela pocetnih vrednosti */


{
s[i] = 2 + 2 * i;
} /* kraj for */

printf( "%s%13s\n\n", "Niz s", "Vrednost" );

/* ispis vrednosti elemenata niza u obliku tabele */


for(i = 0; i < 10; i++)
{
printf( "s[%d] %6d\n", i, s[ i ] );
} /* kraj for */

return 0; /* oznacava uspesan zavrsetak programa */


} /* kraj funkcije main */
5. . 12
.

/* Izracunavanje sume elemenata niza */


#include <stdio.h>
#define SIZE 12

/* funkcija main, pocetak izvrsavanja programa */


int main()
{
int a[ SIZE ] = { 1, 3, 5, 4, 7, 2, 99, 16, 45, 67, 89, 45 };
int i; /* brojac */
int suma = 0; /* zbir vrednosti elemenata niza */

for ( i = 0; i < SIZE; i++ ) /* dodela pocetnih vrednosti */


{
suma += a[ i ];
} /* kraj for */

printf( "Zbir svih vrednosti elemenata niza je %d\n", suma );

return 0; /* oznacava uspesan zavrsetak programa */


} /* kraj funkcije main */

6. 10 float, ,
.

/* Izdvajanje elementa niza koji ima najvecu vrednost*/


#include<stdio.h>

int main()
{
#define BR_ELEMENATA 10

double niz[BR_ELEMENATA] = {117.0, 129.95, 276.22, 201.10,106.31,


358.11, 31.85, 256.45, 269.09, 197.81};
double max;
int i;

max = niz[0];
for (i = 1; i < BR_ELEMENATA; i++)
{
if (niz[i] > max) max = niz[i];
/* Primetite da i pocinje od 1 */
}

printf("\nMaksimalna vrednost niza je %f\n", max);

return 0;
}
7. . 1 10.
() .
(. , ....)

#include <stdio.h>

#define BROJ_STUDENATA 40 /* definisi velicinu nizova */


#define FREKV_VELICINA 11 /* 10 ocena, 11 zbog zanemarivanja indeksa 0*/

/* funkcija main pocetak izvrsavanja programa */


int main()
{
int i; /* brojac koji kruzi od 1. do 40. odgovora */

/* inicijaliacija niza sa brojem dobijenih ocena na 0 */


int frekvOcena[FREKV_VELICINA] = { 0 };

/* inicijalizacija niza odgovor studenata, proizvoljno */


int odgovor[ BROJ_STUDENATA ] = { 1, 2, 6, 4, 8, 5, 9, 7, 8, 10,
1, 6, 3, 8, 6, 10, 3, 8, 2, 7, 6, 5, 7, 6, 8, 6, 7, 5, 6, 6,
5, 6, 7, 5, 6, 4, 8, 6, 8, 10 };

/* za svaki odgovor, odredite vrednost elementa niza odgovor


i uzmite tu vrednost kao indeks niza frekvOcena i da bi se
pozicionirali na taj element niza frekvOcena i povecajte ga za 1 */

for(i = 0; i < BROJ_STUDENATA; i++)


{
++frekvOcena[ odgovor[i] ];
} /* kraj for petlje */

/* prikazi rezultate */
printf( "Ocena Broj glasova\n" );

/* Prikaz u tabelarnom formatu */


for ( i = 1; i < FREKV_VELICINA; i++ )
{
printf("%5d%14d\n", i, frekvOcena[i]);
} /* kraj for */

return 0;
} /* kraj funkcije main */
8. 10 .
30. ,
, .

#include <stdio.h>

#define VELICINA 10 /* definisi velicinu niza */

int main()
{
/* inicializacija niza n */
int n[VELICINA] = { 19, 3, 15, 7, 11, 9, 13, 5, 17, 1 };
int i; /* brojac za elemente polja */
int j; /* brojac zvezdica */

printf("Element Vrednost Histogram\n" );

/* za svaki element polja ispisi index, vrednost i nacrtaj histogram */


for ( i = 0; i < VELICINA; i++ )
{
/* ispis indeksa i vrednosti*/
printf( "%7d%10d ", i, n[i]) ;

for ( j = 1; j <= n[i]; j++ )


{
printf( "%c", '*' ); /* ispisi jednu zvezdicu */
} /* kraj unutrasnje petlje */
printf( "\n" ); /* kraj ispisa histigrama za jedan element niza */
} /* kraj spoljasnje petlje */

return 0;
} /* kraj funkcije main */
9. bubble sort

#include <stdio.h>
#define DIMENZIJA 10

int main()
{
/* inicijalizacija niza a */
int a[DIMENZIJA] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 };
int prolaz; /* brojac prolaza */
int i; /* brojac poredjenjar */
int priv; /* privremeno cuvanje vrednosti */

printf( "Vrednosti niza u pocetnom redosledu\n" );

/* ispisi vrednosti u pocetnom redosledu */


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

/* bubble sort */
for ( prolaz = 1; prolaz < DIMENZIJA; prolaz++ )
{
for ( i = 0; i < DIMENZIJA - 1; i++ )
{
/* poredi vrednost susednih elemenata i yameni im mesta ako je
vrednost prvog elementa veca od drugog */
if ( a[i] > a[i + 1] )
{
priv = a[i];
a[i] = a[i + 1];
a[i + 1] =priv;
} /* kraj if */
} /* kraj unutrasnje for petlje */
} /* kraj spoljasnje for petlje */

printf( "\nVrednosti niza nakon sortiranja\n" );

/* Ispis vrednosti */
for ( i = 0; i < DIMENZIJA; i++ )
printf( "%4d", a[ i ] );

printf( "\n" );

return 0;
} /* kraj funkcije main */
C

1. .

#include <stdio.h>

int main()
{
int broj_a;
int *ptr_br;
float real1, real2;
float *ptr_re;

broj_a=4;
real1=3.2f;

ptr_br = &broj_a; /* pointer ukazuje na adresu prom. broj_a*/


broj_a = broj_a + *ptr_br + 1; /* *ptr_br je sadrzaj adrese na koju ukazuje
*/
printf("\n%d\n",broj_a);

ptr_re=&real1;
real2= *ptr_re;

printf("%f\n",real2);

return 0;
} /* kraj funkcije main */

ptr_br = &broj_a; ptr_br


broj_a. broj_a = broj_a + *ptr_br + 1;
broj_a 4+4+1 ...

2. .

#include <stdio.h>

int main()
{
int broj_a, broj_b, broj_c;
int *ptr_br;

broj_a=8;
broj_b=4;
ptr_br=& broj_c; /* pokazivac pokazuje na adresu promen. broj_c */
*ptr_br= broj_a + broj_b; /* isto sto i broj_c = broj_a + broj_b */

printf("\n%d\n",broj_c);

ptr_br=& broj_a; /* pokazivac pokazuje na adresu promen. broj_a */


broj_a = broj_b * broj_c; /* mnozenje */
printf("\n%d\n",*ptr_br);

ptr_br=& broj_b; /* pokazivac pokazuje na adresu promen. broj_b */


printf("\n%d\n",*ptr_br);

return 0;
} /* kraj funkcije main */
3. 5. 7.
. 10 . , , 5.
6 7. . .

#include <stdio.h>

int main()
{
int niz[10]={10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
int broj_a;
int *ptr_br;

/* pointer ukazuje na 0ti indeks niza */


ptr_br=niz; /* isto sto i ptr =niz[0] ili ptr=&niz[0] */

broj_a= *(ptr_br+4); /* *(ptr+4) citaj kao sadrzaj 5 elementa niza (indeks


4) */
printf("\n%d\n",broj_a);

ptr_br=&niz[6]; /* isto sto i ptr =niz[6] */


printf("\n%d\n",*ptr_br);

*(ptr_br-1)=*ptr_br + *(ptr_br +1);


/* ptr pokazuje na niz[6], *(ptr_br-1) je sadrzaj niz[5], *ptr_br je sadrzaj
niz[6]
*(ptr_br +1); je sadrzaj niz[6], pa je ovo ekvival. niz[5]=niz[6]+ niz[7]
*/

printf("\n%d\n",*(ptr_br-1));
printf("\n%d\n",niz[5]);

return 0;
} /* kraj funkcije main */
4. : 10
.

1
#include <stdio.h>

int main()
{
int niz[10];
int i;
int *pok;

i=1;
for(pok=niz; pok <= &niz[9]; pok++)
{
printf("upisite %d. element niza\n",i);
scanf("%d", pok);
i++;
}

i=2;
for(pok=&niz[1];pok <= &niz[9]; pok = pok+2)
{
printf("%d. element je: %d\n",i, *pok);
i+=2;
}
return 0;
}

2
#include <stdio.h>

int main()
{
int niz[10];
int i;
int *pok;

for(pok=niz, i=1; pok <= &niz[9]; pok++, i++)


{
printf("upisite %d. element niza\n",i);
scanf("%d", pok);
}

for(pok=&niz[1], i=2; pok <= &niz[9]; pok = pok+2, i+=2)


printf("%d. element je: %d\n",i, *pok);

return 0;
}
: (,) - (;).
5.

#include <stdio.h>
main()
{
int a[8] = {1,23,17,4,-5,100,55,44};
int *pa, *pb;
int x, y;

pa=&a[4]; /* pa ukazuje na a[4] tj na vrednost -5 */


printf("Vrednost *pa nakon naredbe pa=&a[4] je: %d\n", *pa);
x=*(pa+3); /* x=a[7]=44 */
printf("Vrednost x nakon naredbe x=*(pa+3) je: %d\n", x);
y=*pa+3; /* y=a[4]+3=-2*/
printf("Vrednost y nakon naredbe y=*pa+3; je: %d\n", y);
*pa++; /* povecava se sadrzaj pokazivaca, isto sto i *(pa++)
ili pa=&a[5] */
printf("Vrednost *pa nakon naredbe *pa++ je: %d\n", *pa);
(*pa)++; /* povecava se pokazani podatak a[5]=a[5]+1=101 */
printf("Vrednost *pa nakon naredbe (*pa++) je: %d\n", *pa);
pb=&a[2];
}

6. malloc

#include <stdio.h>
#include <stdlib.h> /* potrebno zbog malloc i free funkcije */

main()
{
int number;
int *ptr;
int i;

printf("Koliko int vrednosti zelite da sacuvate? ");


scanf("%d", &number);

ptr = malloc(number*sizeof(int)); /* zahtev za dodelu memorije */


/* ptr = (int *)malloc(number*sizeof(int)); */ /* moze i ovako */

if(ptr!=NULL)
{
for(i=0 ; i<number ; i++)
{
*(ptr+i) = i;
}
for(i=number ; i>0 ; i--)
{
printf("%d\n", *(ptr+(i-1))); /* prikazi u suprotnom redosledu */
}

free(ptr); /* oslobodi dodeljenu memoriju */


}
else
printf("\nDodela memorije nije izvrsena - nema dovoljno
memorije.\n");
}
7. calloc

#include <stdio.h>
#include <stdlib.h> /* potrebno zbog malloc i free funkcije */

main()
{
float *ptr_c1, *ptr_c2, *ptr_m1, *ptr_m2;
int i;

ptr_c1 = calloc(3, sizeof(float)); /* moze se zahtevati konverzija */


ptr_c2 = calloc(3, sizeof(float));
ptr_m1 = malloc(3 * sizeof(float));
ptr_m2 = malloc(3 * sizeof(float));

if(ptr_c1!=NULL && ptr_c2!=NULL && ptr_m1!=NULL && ptr_m2!=NULL)


{
printf("adresa ptr_c1 je %05.5p,\n", ptr_c1);
printf("adresa ptr_c2 je %05.5p,\n", ptr_c2);
printf("adresa ptr_m1 je %05.5p,\n", ptr_m1);
printf("adresa ptr_m2 je %05.5p,\n\n", ptr_m2);

for(i=0 ; i<3 ; i++)


{
printf("*ptr_c1[%d] ima vrednost %05.5f,\n", i, *(ptr_c1+i));
printf("*ptr_c2[%d] ima vrednost %05.5f,\n", i, *(ptr_c1+i));
printf("*ptr_m1[%d] ima vrednost %05.5f\n", i, *(ptr_m1+i));
printf("*ptr_m2[%d] ima vrednost %05.5f,\n\n", i, *(ptr_c1+i));
}

free(ptr_c1);
free(ptr_c2);
free(ptr_m1);
free(ptr_m2);
}
else
printf("Nema dovoljno memorije\n");
}
8. realloc

#include<stdio.h>
#include <stdlib.h>

int main()
{
int *ptr;
int i;

ptr = calloc(5, sizeof(int)); /*dinamicki niz od 5 elemenata indeks 0-4


*/

if(ptr!=NULL) /* ako je dodeljena memorija...*/


{
*ptr = 1; /* isto sto i ptr[0]=1 ili *ptr=1 */
*(ptr+1) = 2; /* isto sto i ptr[1]=2 */
*(ptr+2) = 4;
*(ptr+3) = 8;
*(ptr+4) = 16;

printf("\nNakon naredbe calloc(5, sizeof(int)) i dodele


vrednosti...\n");
for(i=0 ; i<5 ; i++)
printf("*(ptr+%d) ukazuje na vrednost %d\n", i, *(ptr+i));

ptr = realloc(ptr, 7*sizeof(int)); /* dodaj jos 2 int (bilo je vec 5)*/

if(ptr!=NULL)
{
printf("\n Nakon naredbe ptr = realloc(ptr, 7*sizeof(int));... \n");
for(i=0 ; i<7 ; i++)
printf("*(ptr+%d) ukazuje na vrednost %d\n", i, *(ptr+i));

*(ptr+5) = 32;
*(ptr+6) = 64;

printf("\n Nakon naredbe dodele vrednosti 6. i 7. elementu... \n");


for(i=0 ; i<7 ; i++)
printf("*(ptr+%d) ukazuje na vrednost %d\n", i, *(ptr+i));

realloc(ptr,0); /* isto sto i free(ptr); */


}
else
printf("Nema dovoljno memorije - realloc neuspesan.\n");
}
else
printf("Nema dovoljno memorije - calloc neuspesan.\n");
}
C

1
1. (klijenti.dat) ,
. , Ctrl+Z.

/* Upis podataka u fajl */


#include <stdio.h>

int main()
{
int broj_racuna; /* broj racuna korisnika */
char ime[ 30 ]; /* ime korisnika */
double stanje; /* stanje na racunu */

FILE *prt_na_fajl; /* prt_na_fajl = fajl pointer */

/* fopen otvara fajl, w za upisivanje. */


/* Ukoliko ne uspe pointer je jednak 0, izadji iz programa */
if ( ( prt_na_fajl = fopen( "klijenti.dat", "w" ) ) == NULL )
{
printf( "Fajl se ne moze otvoriti\n" );
} /* kraj if */
else
{
printf( "Unesite broj racuna, ime korisnika i stanje.\n" );
printf( "Unesite Ctrl+Z za kraj rada.\n" );
printf( "? " );
scanf( "%d%s%lf", &broj_racuna, ime, &stanje );

/* Upisite broj racuna, ime i stanje u fajl nredbom fprintf */


while ( !feof( stdin ) )
{
fprintf( prt_na_fajl, "%d %s %.2f\n", broj_racuna, ime, stanje );
printf( "? " );
scanf( "%d%s%lf", &broj_racuna, ime, &stanje );
} /* kraj while */

fclose( prt_na_fajl ); /* fclose zatvara fajl */


} /* kraj else */

return 0; /* oznacava uspesan zavrsetaka */

} /* kraj main */

feof( stdin ) end-of-file .


(stdin),
. (Ctrl+Z) za (end-of-file), feof
1.

0
( )

? 100 Petric 324.22


? 121 Markovic 0.00
? 111 Simic 32.33
? 246 vac -34.56
? 343 Jack -200
? 654 Jon 9567.34
? ^Z

2
2. ( ), .

:
/* citanje podataka iz fajla*/
#include<stdio.h>
int main()
{
int broj_racuna; /* broj racuna korisnika */
char ime[ 30 ]; /* ime korisnika */
double stanje; /* stanje na racunu */

FILE *prt_na_fajl; /* prt_na_fajl = fajl pointer */

/* fopen otvara fajl, r (read) za citanje. */


/* Ukoliko ne uspe pointer je jednak 0, izadji iz programa */
if ( ( prt_na_fajl = fopen( "klijenti.dat", "r" ) ) == NULL )
{
printf( "Fajl se ne moze otvoriti\n" );
} /* kraj if */
else
{
printf( "%-14s%-16s%s\n", "Broj racuna","Ime","Stanje" );
fscanf( prt_na_fajl,"%d%s%lf", &broj_racuna, ime, &stanje );

/* Citanje podataka iz fajla naredbom fscanf */


while ( !feof( prt_na_fajl ) )
{
printf( "%-14d%-16s%7.2f\n", broj_racuna,ime, stanje );
fscanf( prt_na_fajl,"%d%s%lf", &broj_racuna, ime, &stanje );
} /* kraj while */

fclose( prt_na_fajl ); /* fclose zatvara fajl */


} /* kraj else */

return 0; /* oznacava uspesan zavrsetaka */

} /* kraj main */

3
3.
:
. 0
.
.
.

#include<stdio.h>
int main()
{
int zahtev;
int broj_racuna; /* broj racuna korisnika */
char ime[ 30 ]; /* ime korisnika */
double stanje; /* stanje na racunu */
FILE *prt_na_fajl; /* prt_na_fajl = fajl pointer */

/* fopen otvara fajl, r (read) za citanje. */


/* Ukoliko ne uspe pointer je jednak 0, izadji iz programa */
if ( ( prt_na_fajl = fopen( "klijenti.dat", "r" ) ) == NULL )
printf( "Fajl se ne moze otvoriti\n" );
else
{
/* prikazi zahtevane opcije */
printf( "Unesite zahtev\n"
" 1 - Izlistaj racune sa stanjem NULA\n"
" 2 - Izlistaj racune sa stanjem u MINUSu\n"
" 3 - Izlistaj racune sa POZITIVNIM stanjem\n"
" 4 - Kraj\n? " );
scanf( "%d", &zahtev );

while(zahtev !=4)
{
fscanf( prt_na_fajl,"%d%s%lf", &broj_racuna, ime, &stanje );
switch(zahtev)
{
case 1:
printf( "\nRacuni sa stanjem NULA:\n" );
/* citaj sadrzaj fajla do kraja (sve do eof) */
while ( !feof( prt_na_fajl ) )
{
if ( stanje == 0 )
printf( "%-14d%-16s%7.2f\n", broj_racuna, ime, stanje );
/* procitaj broj racuna, ime i stanje iz fajla */
fscanf( prt_na_fajl, "%d%s%lf", &broj_racuna, ime, &stanje );
} /* kraj while */
break;

4
case 2:
printf( "\nRacuni sa stanjem u MINUSu:\n" );
/* citaj sadrzaj fajla do kraja (sve do eof) */
while ( !feof( prt_na_fajl ) )
{
if ( stanje < 0 )
printf( "%-14d%-16s%7.2f\n", broj_racuna, ime, stanje );
/* procitaj broj racuna, ime i stanje iz fajla */
fscanf( prt_na_fajl, "%d%s%lf", &broj_racuna, ime, &stanje );
} /* kraj while */
break;
case 3:
printf( "\nRacuni sa POZITIVNIM stanjem:\n" );
/* citaj sadrzaj fajla do kraja (sve do eof) */
while ( !feof( prt_na_fajl ) )
{
if ( stanje > 0 )
printf( "%-14d%-16s%7.2f\n", broj_racuna, ime, stanje );
/* procitaj broj racuna, ime i stanje iz fajla */
fscanf( prt_na_fajl, "%d%s%lf", &broj_racuna, ime, &stanje );
} /* kraj while */
break;
}/* kraj switch */

fseek(prt_na_fajl, 0, SEEK_SET); /* pozicioniraj se na pocetak fajla*/


/*potpuno je isto sto i rewind( ptr_na_fajl); */
printf( "\n? " );
scanf( "%d", &zahtev );

} /* kraj while(zahtev !=4 ) */

printf("Kraj rada\n");
fclose( prt_na_fajl ); /* fclose zatvara fajl */
} /* kraj else */

return 0; /* oznacava uspesan zavrsetak */


} /* kraj main */

5
4. 100 . : ,
, . 0
, 0 . 100
fwrite

/* Rad sa binarnim fajlovima */


#include <stdio.h>

/* Definicija strukture podaci_klijenta */


struct podaci_klijenta
{
int broj_racuna; /* broj_racuna klijenta */
char prezime[ 15 ]; /* prezime klijenta */
char ime[ 10 ]; /* ime klijenta */
double stanje; /* stanje na racunu */
}; /* kraj definicije strukture */

int main()
{
int i; /* brojac racuna od 1 do 100 */

/* kreiraj promen. novi_klijent tipa strukture podaci_klijenta i inicijalizuj */


struct podaci_klijenta novi_klijent = { 0, "", "", 0.0 };

FILE *ptr_fajl; /* fajl pointer */

/* fopen otvara fajl, izlaz iz programa ukoliko ne uspe */


if ( ( ptr_fajl = fopen( "kredit.dat", "wb" ) ) == NULL )
printf( "Fajl se ne moze otvoriti.\n" );
else
{
/* upisi 100 "praznih" zapisa (struktura) u fajl */
for ( i = 1; i <= 100; i++ )
fwrite( &novi_klijent, sizeof( struct podaci_klijenta ), 1, ptr_fajl );

fclose ( ptr_fajl ); /* fclose zatvara fajl */


} /* kraj else */

return 0; /* indicates successful termination */


} /* end main */

6
5. .
1 100 ( ).

/* Rad sa binarnim fajlovima */


#include <stdio.h>

/* Definicija strukture podaci_klijenta */


struct podaci_klijenta
{
int broj_racuna; /* broj_racuna klijenta */
char prezime[ 15 ]; /* prezime klijenta */
char ime[ 10 ]; /* ime klijenta */
double stanje; /* stanje na racunu */
}; /* kraj definicije strukture */

int main()
{
struct podaci_klijenta klijent = { 0, "", "", 0.0 };
FILE *ptr_fajl; /* fajl pointer */

/* fopen otvara fajl, izlaz iz programa ukoliko ne uspe */


if ( ( ptr_fajl = fopen( "kredit.dat", "rb+" ) ) == NULL )
printf( "Fajl se ne moze otvoriti.\n" );
else
{
/* traziti od korisnika da unese broj racuna */
printf("Unesite broj racuna (1-100):");
scanf("%d", &klijent.broj_racuna);
/* Korisnik treba da unese podatke za klijenta */
while(klijent.broj_racuna>0 && klijent.broj_racuna<101)
{
/* Unos prezimena, imena i stanja */
printf( "Unesite prezime, ime i stanje\n? " );
/* vrednosti */
fscanf( stdin, "%s%s%lf", &klijent.prezime, &klijent.ime, &klijent.stanje );

/* Pozicioniraj se na poziciju racuna (zadao je korisnik) */


fseek( ptr_fajl, ( klijent.broj_racuna - 1 ) *
sizeof( struct podaci_klijenta), SEEK_SET );

/* upisi unete vrednosti u fajl */


fwrite( &klijent, sizeof( struct podaci_klijenta), 1, ptr_fajl);

/* Omogui korisniku da unese podatke za druge racune */


printf( "Unesite broj racuna\n? " );
scanf( "%d", &klijent.broj_racuna );
} /* kraj while*/

fclose( ptr_fajl ); /* fclose zatvara fajl */


} /* kraj else */

return 0; /* oznacava uspesan zavrsetak */


} /* kraj main */

7
6. () .

/* Rad sa binarnim fajlovima */


#include <stdio.h>

/* Definicija strukture podaci_klijenta */


struct podaci_klijenta
{
int broj_racuna; /* broj_racuna klijenta */
char prezime[ 15 ]; /* prezime klijenta */
char ime[ 10 ]; /* ime klijenta */
double stanje; /* stanje na racunu */
}; /* kraj definicije strukture */

int main()
{
struct podaci_klijenta klijent = { 0, "", "", 0.0 };

FILE *ptr_fajl; /* fajl pointer */

/* fopen otvara fajl, izlaz iz programa ukoliko ne uspe */


if ( ( ptr_fajl = fopen( "kredit.dat", "rb" ) ) == NULL )
printf( "Fajl se ne moze otvoriti.\n" );
else
{
printf( "%-6s%-16s%-11s%10s\n", "Racun", "Prezime","Ime", "Stanje" );
/* Procitaj sve racune do kraja fajla */
while(!feof(ptr_fajl))
{
fread( &klijent, sizeof( struct podaci_klijenta ), 1, ptr_fajl );
/* prikazi podatke racuna */
if ( klijent.broj_racuna != 0 )
printf( "%-6d%-16s%-11s%10.2f\n",klijent.broj_racuna, klijent.prezime,
klijent.ime,klijent.stanje );
} /* kraj while */

fclose( ptr_fajl ); /* fclose zatvara fajl */


} /* kraj else */

return 0; /* oznacava uspesan zavrsetak */


} /* kraj main */

8
OSNOVE C JEZIKA

1./*Napisati program koji na ekranu ispisuje poruku Zdravo svete!*/

#include<stdio.h>
void main()
{
printf("Zdravo svete!\n");
}

Funkcija void main() je glavna funkcija i postoji samo jedna ova funkcija u C programu.
()oznaava da main nema argumenata. printf je funkcija za tampanje poruke Zdravo svete!.
Karakter \n predstavlja oznaku za novu liniju. Svaki iskaz se mora zavriti karakterom ;, koji
ima ulogu terminatora iskaza. Karakteri { i } objedinjuju vie pojedinanih iskaza u jednu
programsku celinu i oni su obavezni jer se tu izvrava neka obrada.
scanf je funkcija slina printf. Razlika je to se argumenti funkcije printf prenose sa
vrednou, dok se kod scanf prenose svojom adresom, jer se uitana vrednost mora vratiti u
pozivajui program. To se postie navoenjem karaktera & (operator adresiranja) ispred
argumenta u listi argumenata. Npr.

scanf(%d,&x); - %d - broj koji se unosi je celobrojni.


- %8.2f ostavljanje mesta za zapis realnog broja

Escape karakteri Konverzioni karakteri funkcije printf


\b povratnik \nnn vrednost karaktera Konverz. kar. Konverzija izlaznog niza
\f from feed \\ - obrnuta kosa crta c Karakter (char)
\n nova linija \ dvostuka navodnica d ceo broj (int)
\r carriage return \ jednostruke navodnice f realan broj (float)
\t horizontalni tab \ - nastavak linije s niz karaktera (string)
\v vertikalni tab e realan br. u naunoj notaciji
le double

1.2.2 Variables - Promenljive


Promenljiva je objekt jezika koji ima ime i kome se mogu dodeljivati razliite vrednosti u toku
izvravanja programa.

Imena promenljivih se grade od velikih i malih slova, cifara od 1 do 9 i karaktera (donja crta _ ).
Ime ne sme poinjati cifrom, niti sme sadrati rezervisane rei. Nedozvoljeni znaci su i
matematiki operatori (+, -, *, /, %).

Variable names are case sensitive imena promenljivih su osetljiva na mala i velika slova..

Ime promenljive (indentifikator):


skola
y
Ab63c
auto_skola

1
Osnovni tipovi podataka
Osnovni tipovi podataka su int, float, double i char.
Podaci tipa int su celobrojne vrednosti. Tu spadaju celobrojne konstante, promenljive,
izrazi i funkcije. Opseg celobrojnig vrednosti je razliit i moe se menjati primenom
kvalifikatora long, short i unsigned. Kvalifikator long poveava opseg vrednosti celobrojnih
promenljivih. Kvalifikator short ispred int smanjuje opseg celobrojnih promenljivih. Kvalifikator
unsigned ispred int deklarie promenljivu tako da moe memorisati samo pozitivne vrednosti.
Promenlljive tipa float ili double memoriu vrednosti realnih brojeva, odnosno, vrednosti
sa decimalnim (pokretnim) zarezom. Promenljive daklarisane kao double mogu memorisati oko
dva puta vie decimalnih cifara od promenljivih tipa float.
Promenljive i konstante tipa char memoriu karaktere. Konstante tipa char dobijaju se
stavljanjem karaktera izmeu jednostrukih navodnica, npr. A, 1, itd. A treba razlikovati od
A, jer A predstavlja konstantni niz karaktera koji u C jeziku ima posebnu predstavu i
tretman.

Primeri:
int bob=32;
Creates variable "bob" and initializes it to the value 32. (Kreirana promenljivba "bob" i izvrena
inicijalizacija na 32.)
boolean yes=1;
Creates variable "yes" as type "char" and sets its value to 1.

Aritmetiki izrazi i operatori

Aritmetiki operatori C jezika su +, -, *, / i % koji odgovaraju matematikim operacijama


sabiranja, oduzimanja, mnoenja, deljenja i deljenja po modulu, respektivno. Ovi operatori su
binarni, jer zahtevaju dva operanda, sa izuzetkom operatora -, koji moe biti i unaran. Operator
deljenja po modulu (%) daje ostatak posle celobrojnog deljenja.

2
Tablica operatora.

Operator Namena Primer Rezultat


+ Sabiranje 5+6 11
- Oduzimanje 7 - 3 4
* Mnoenje 4*4 16
/ Deljenje 12 / 6 2
% Deljenje sa ostatkom 5%2 1
% operator se naziva jo i modulus operator .

Aritmetiki operatori jednako dobro rade sa negativnim brojevima kao i sa pozitivnim, sa


izuzetkom modulus operatora, rade sa celim brojevima jednako dobro kao i sa realnim.

Konstante (nepromenjive)

- Varijable su promenjive dok su konstante izrazi sa fiksnim, nepromenjivim vrednostima.


- Kostante su objekti koji dobijaju vrednost pre nego to pone izvravanje programa i u toku
rada programa se ne mogu menjati.

Primer definisanja konstanti:


#define PI 3.141592 #define PI 3.141592 #define POREZ 20
#define POREZ 20 main(){
.....
Obim=2*r*PI;
...
}

#define IME VLADE DIVAC


#define BROJ 52
main()
{
printf(Kosarkas %s ima br. Cip.%f,IME, BROJ);
}

Odnosni operatori

Odnosni operatori se npr. koriste ako elite napraviti program koji e iz baze podataka odrediti
osobe sa vie od 30 godina i slino.

Odnosni operatori: if ((a>b)&&(b>c)) || (b>d)

Operator Znaenje Primer


&& logiko I (i>1)&&(j<6)
|| logiko ILI x=10||20;
! logika negacija if(!b) brojac=0;

3
Odnosne naredbe naredbe uslova

Kao i aritmetiki operatori, odnosni operatori su binarni tj. usporeuju dva operanda. Naredba sa
dva operanda i odnosnim operatorom zove se odnosna naredba (eng. relational expression.)
Rezultat odnosne naredbe je Boolean vrednost odnosno istinu ili la (true ili false). S ovom
tablicom moete videti kako to funkcionie.

U ovoj tablici se koriste konkretne ( literal ) vrednosti koje ne mogu biti promenjene. 4 je
konkretna vrednost (konstanta), i ona se ne moe menjati (moglo bi se menjati da se umesto
konstanta koriste promenljive).

Operator inkrementiranja i dekrementiranja

Operator inkrementiranja ++ i dekrementiranja -- su unarni operatori i javljaju se u


prefiksnom i postfiksnom obliku. Operator inkrementiranja ++ promenljivoj p dodaje vrednost 1,
dok operator dekrementiranja -- promeljivoj p oduzima vrednost 1, pa vai:

p++ je ekvivalentno p=p+1 p-- je ekvivalentno p=p-1 (postfiksni oblik)


++p je ekvivalentno p=p+1 --p je ekvivalentno p=p-1 (prefiksni oblik)

Ako se koristi oblik ++x to znai da se x prvo uveava pa tek onda koristi u izrazu. Oblik x++
znai da se x prvo koristi u izrazu pa tek onda uveava. Anaklogno vai za operaciju --.
x+=2 je x=x+2
x/2 je x=x/2
x*=2 je x=x*2
x%=2 je x=x%2

Rezervisane rei - Keywords

The following keywords are reserved and may not be used as an identifier for any other purpose.

auto double int long


break else long switch
case enum register typedef
char extern return union
const float short unsigned
continue for signed void
default goto sizeof volatile
do if static while

4
Elementarne algoritamske strukture
Algoritamske strukture se dele u tri osnovne grupe:

Linijska (sekvencija)
Razgranata (selekcija)
Ciklina (iteracija)

Linijska struktura:
Karakteristika linijske strukture je da se svi elementi izvravaju samo jednom i koraci se odvijaju u nizu
jedan za drugim bez ponavljanja ili "skretanja".
Primjer u BASIC-u Primjer u C-u
INPUT a, b #include <stdio.h>
zbir = a + b
PRINT zbir void main () {
END int a, b, zbir;

printf("a,b? ");
scanf("%d%d", &a, &b);
zbir = a + b;
printf("a + b = %d\n", zbir);
}

Razgranata struktura:
Razgranata struktura e se pojaviti kod algoritma koji ima blok odluivanja kao to su IF i CASE, pri emu
se vri testiranje odreenog uslova a prema rezultatu (obino TRUE ili FALSE) algoritam se grana i
nastavlja tok jednom od grana- opcija. Primjer na slici je tipian gdje se otklanja blokiranje programa
provjerom da li je djelilac jednak nuli. Ako je djelilac razliit od nule, dae rezultat dijeljenja, u suprotnom
e dati samo poruku da dijeljenje nulom nema smisla i nastaviti dalje prema sledeoj proceduri ili kraju
programa.
Primjer u BASIC-u Primjer u C-u
INPUT a,b #include<stdio.h>
IF b <> 0 THEN
PRINT a/b void main () {
ELSE float a, b;
PRINT "Ne mogu
deliti nulom" scanf("%f%f", &a, &b);
END if (b == 0) {
printf("Ne mogu deliti
nulom\n");
} else {
printf("a : b = %f\n", a /
b);
}
}

Ciklina struktura
Ciklini algoritam e se pojaviti kada treba isti posao uraditi vie puta. Postoji vie varijanti ove srtukture,
a dve osnovne poele su:

5
Broj iteracija (ponavljanja) je unapred poznat. Primer ove petlje je na slici i tu se obino koristi
petlja FOR.
Iteracija se vri dok se ne zadovolji odreen uslov. Koriste se petlje tipa WHILE...DO.

Kod Iteracije sa proverom istinitosti uslova (da li je uslov zadovoljen) postoje varijante s proverom uslova
na ulazu u petlju, odnosno na kraju petlje. Razlika izmeu ove dvije varijante je to kod provere istinitosti
uslova na kraju petlje program mora proi bar jednom kroz petlju.
Primjer u BASIC-u Primjer u C-u
zbir = 0 #include <stdio.h>
INPUT b
FOR a = 1 TO b void main() {
zbir = zbir + a int a, b, zbir = 0;
NEXT a
PRINT zbir scanf("%d", &b);
END for (a = 1; a <= b; a++) {
zbir += a;
}

printf("%d\n", zbir);
}

Primer algoritma kada nije poznat konaan broj iteracija sa provjerom na poetku petlje

Primjer u BASIC-u Primjer u C-u


Kod provere istinitosti na ulazu u petlju zbir = 0 #include <stdio.h>
postoji mogunost da se ne izvri ni WHILE zbir < 200
jedno ponavljanje. Razlog je INPUT a void main() {
zbir = zbir + a int a, zbir = 0;
jednostavan, ako uslov nije ispunjen
WEND
odmah se "preskae" na sledeu liniju while (zbir < 200) {
izvan petlje. Za ovu vrstu petlje u veini PRINT zbir scanf("%d", &a);
programa se koristi kljuna re END zbir += a;
"WHILE" prilagoena sintaksi }
programskog jezika.
printf("%d\n", zbir);
}

Primer algoritma kada nije poznat konaan broj iteracija sa proverom na kraju petlje

Primjer u BASIC-u Primjer u C-u


Kod provere istinitosti na kraju petlje, zbir = 0 #include <stdio.h>
ne postoji mogunost da se ne izvri DO
ni jedno ponavljanje. Razlog je INPUT a void main() {
zbir = zbir + a int a, zbir = 0;
jednostavan, provera se vri u
WHILE (zbir < 200)
posednjem redu bloka kda, pe se PRINT zbir do {
mora proi barem jedanput kroz itav END scanf("%d", &a);
blok. Za ovu vrstu petlje u veini zbir += a;
programa se koristi kljuna re } while (zbir < 200);
"DO..WHILE" prilagoena sintaksi
programskog jezika. printf("%d\n", zbir);
}

6
2. /*Primer za operatore inkrementiranja i dekrementiranja*/

#include<stdio.h>
void main()
{
int a=0,b=0,c=0;
printf("\na=%d b=%d c=%d\n",a,b,c);
a=++b + ++c;
printf("a=%d b=%d c=%d\n",a,b,c);
a=b++ + c++;
printf("\na=%d b=%d c=%d\n",a,b,c);
a=++b + c++;
printf("\na=%d b=%d c=%d\n",a,b,c);
a=++c + c;
printf("\na=%d b=%d c=%d\n",a,b,c);
}
3. /*Napisati program kojim se obraunavaju trokovi putovanja ako je udaljenost S
kilometara, potronja automobila na 100 km L litara, a cena litra goriva C dinara.*/

#include<stdio.h>
void main()
{
float s,l,c,t;
printf("Rastojanje u kilometrima\n");
scanf("%f",&s);
printf("Potrosnja u litrima na 100 km\n");
scanf("%f",&l);
printf("Cena goriva u dinarima\n");
scanf("%f",&c);
t=2*s/100*l*c;
printf("Troskovi putovanja su %0.2f dinara\n",t);
}
4./*Napisati program koji datom prirodnom etvorocifrenom broju:
a) izraunava proizvod cifara;
b) izraunava razliku sume krajnjih i srednjih cifara broja;
c) izraunava sumu kvadrata cifara;
d) odreuje broj koji se dobija ispisom cifara u obrnutom porektu.*/
a)
#include<stdio.h>
void main()
{
int n,a,b,c,d,proizvod;
printf("Uneti cetvorocifren broj\n");
scanf("%d",&n);
a=n%10;
b=((n%100)/10);
c=((n/100)%10);
d=n/1000;
proizvod=a*b*c*d;
printf("Proizvod cifara broja %d je: %d\n",n,proizvod);
}

7
b)
#include<stdio.h>
void main()
{
int n,a,b,c,d,razlika;
printf("Uneti cetvorocifren broj\n");
scanf("%d",&n);
a=n%10;
b=((n%100)/10);
c=((n/100)%10);
d=n/1000;
razlika=(a+d)-(b+c);
printf("Razlika sume krajnjih i srednjih cifara broja %d je: %d\n",n,razlika);
}
c)
#include<stdio.h>
void main()
{
int n,a,b,c,d,suma;
printf("Uneti cetvorocifren broj\n");
scanf("%d",&n);
a=n%10;
b=((n%100)/10);
c=((n/100)%10);
d=n/1000;
suma=a*a+b*b+c*c+d*d;
printf("Suma kvadrata cifara broja %d je: %d\n",n,suma);
}
d)
#include<stdio.h>
void main()
{
int n,a,b,c,d,suma;
printf("Uneti cetvorocifren broj\n");
scanf("%d",&n);
a=n%10;
b=((n%100)/10);
c=((n/100)%10);
d=n/1000;
suma=1000*a+100*b+10*c+d;
printf("Broj %d u obrnutom redosledu je: %d\n",n,suma);
}
5./*Napisati program u kome se unose vrednost ASCII koda (npr. 66) i tampa znak tog
koda.*/

#include <stdio.h>
void main()
{
int ascii;
printf("Uneti ASCII ko nekog znaka: ");
scanf("%d", &ascii);
printf("%d je ASCII kod za %c.\n", ascii, ascii);
}

8
If iskaz

if je kontrolna struktura za ostvarivanje programskih granjanja. Prosta forma ovog iskaza je:

if (izraz)
iskaz;
sledeci_iskaz;

Meutim, ako postoji viestruko granjanje koristi se:

if(izraz1)
iskaz1;
else if(izraz2)
iskaz2;
.....
else
iskazn;

If statements
if ( statement is TRUE )
Execute this line of code

Else
if ( TRUE ) {
/* Execute these statements if TRUE */
}
else {
/* Execute these statements if FALSE */
}

*) Primer:

#include <stdio.h>

int main() /*Most important part of the program!*/


{
int age; /* Need a variable... */

printf( "Please enter your age" ); /* Asks for age */


scanf( "%d", &age ); /* The input is put in age */
if ( age < 100 ) { /*If the age is less than 100*/
printf ("You are pretty young!\n" ); /*Just to show you it works.*/
}
else if ( age == 100 ) { /*I use else just to show an example*/
printf( "You are old\n" );
}
else {
printf( "You are really old\n" ); /*Executed if no other statement is*/
}
return 0;
}

9
Osnovne bibliotene funkcije <math.h>

sin(x) - sin(x)
cos(x) - cos(x)
tan(x) - tg(x)
exp(x) - ex
log(x) - log e (x), x>0
log10(x) - log 10 (x), x>0
pow(x,y) - x y
sqrt(x) - x , x>=0
fabs(x) - |x| apsolutna vrednost od x
ceil(x) vrednost funkcije je najmanja celobrojna vrednost koja nije manja od x (zaokruuje navie).
floor(x) - vrednost funkcije je najvea celobrojna vrednost koja nije vea od x (zaokruuje na najblii
manji ceo broj).

Examples
Sample value Floor [ ] Ceiling [ ] Fractional part { }
2.7 3 2 0.3
2 2 2 0
12/5 = 2.4 2 3 2/5 = 0.4
2.7 2 3 0.7

6. /*Napisati program za izraunavanje apsolutne vrednosti celog broja*/

#include<stdio.h>
void main()
{
int broj,a_vred;
printf("Ukucajte ceo broj?");
scanf("%d",&broj);
a_vred=broj;
if(a_vred<0) a_vred=-a_vred;
printf("Apsolutna vrednost broja %d je %d\n", broj, a_vred);
}

7. /*Napisati program koji ispituje da li je karakter malo


ili veliko slovo, cifra ili specijalni karakter - if else iskaz*/

#include<stdio.h>
void main()
{
char c;
printf("Ukucajte karakter?");
scanf("%c",&c);
if(c>='a'&&c<='z')
printf("Karakter %c je malo slovo\n",c);

10
else if(c>='A'&&c<='Z')
printf("Karakter %c je veliko slovo\n",c);
else if(c>='0'&&c<='9')
printf("Karakter %c je cifra\n",c);
else
printf("Karakter %c je specijalni karakter\n",c);
}

8./*Izraunati povrinu trougla zadatog stranicama x, y i z po formuli za povrinu


p=sqrt(s*(s-x)*(s-y)*(s-z)), gde je s=(x+y+z)/2. */
#include<stdio.h>
#include<math.h>
void main()
{
double x,y,z,p,s;
printf("Unesite stranice\n");
scanf("%lf%lf%lf",&x,&y,&z);
if((x+y>z)&&(x+z>y)&&(y+z>x))
{
s=(x+y+z)/2;
p=sqrt(s*(s-x)*(s-y)*(s-z));
printf("Povrsina trougla je=%0.2f\n",p);
}
else printf("Ne moze se konstruisati trougao\n");
}

9. /*Napisati program koji za dati trocifreni prirodan broj n proverava da li je


Armstrongov. Broj je Armstrongov ako je jednak zbiru kubova svojih cifara.*/

#include<stdio.h>
void main()
{
int c1,c2,c3,n;
printf("Uneti trocifren broj\n");
scanf("%d",&n);
c1=n%10;
c2=n/10%10;
c3=n/100;
if(c1*c1*c1+c2*c2*c2+c3*c3*c3==n)
printf("Broj %d je Armstrongov\n",n);
else
printf("Broj %d nije Armstrongov\n",n);
}

10. /*Napisati program koji za dato x izraunava y po formuli.*/


2 x,........ 2 x 2
3x 1,........5 x 7
y
1 / x,........za..ostale...slucajeve

#include<stdio.h>
11
void main()
{
double x,y;
printf("Uneti vrednost za x\n");
scanf("%d",&x);
if (x<=-2)
y=1/x;
else
if (x<2)
y=2*x;
else
if (x<5)
y=1/x;
else
if (x<=7)
y=3*x-1;
else
y=1/x;
printf("y=%f ",y);

11. Napiite program koji uitava dva cela broja i, ako su oba parna ispisuje njihovu sumu;
inae treba ispisati proizvod.

#include <stdio.h>
main ( ) {
int prvibroj , drugibroj ;

printf("Unesite prvi broj:") ;


scanf("%d", &prvibroj ) ;
printf("Unesite drugi broj :" ) ;
scanf("%d" , &drugibroj ) ;

if ( ( prvibroj % 2 == 0) && ( drugibroj % 2 == 0 ) )


printf ("%d\n" , prvibroj + drugibroj ) ;
else
printf("%d\n" , prvibroj * drugibroj ) ;

return 0 ;
}

12. Napisati program koji broji razmake, tabulatore i nove redove.

#include <stdio.h>
main () {
int c,nb,nt,nl;

nb=0;
nt=0;
nl=0;
while ((c = getchar()) != EOF){
if(c ==' ')
12
++nb;
if (c =='\t')
++nt;
if (c =='\n')
++nl;
}
printf("%d%d%d\n" , nb, nt, nl ) ;
}

13. Napisati program koji za uneti prirodan broj n ispituje da li je deljiv sa 5 i tampa
odgovarajue obavetenje.

#include <stdio.h>
main ( ) {
int n;
printf("Unetite prirodan broj:");
scanf("%d",&n);
if (n%5==0){
printf("Broj je deljiv sa 5\n");
}
else{
printf("Broj nije deljiv sa 5\n");
}
return 0;
}

Operator viestrukog izbora SWITCH

Omoguava grananje u programu izborom jednog izmeu vie operatora


switch (izraz)
{
case konstanta1: operator1
......
break;
case konstanta2: operator2
.........
break;
.....
default : operatorn
break;
}

Naredba switch

- Izraz u naredbi switch mora imati celobrojnu vrednost (char, int).


- Nakon kljune rei case pojavljuju se celobrojne konstante ili konstantni izrazi.
- Na poetku izvravanja naredbe switch prvo se testira izraz. Ako je vrednost izraza jednaka
konstanta_i onda se izvrava naredba_i i sve naredbe koje dolaze nakon nje, sve do prve

13
break naredbe ili kraja switch naredbe. Nakon toga program se nastavlja prvom naredbom
iza switch naredbe.
- Ako izraz nije jednak ni jednoj konstanti, onda se izvrava naredba koja dolazi posle kljune
rei default (ako postoji) i sve naredbe iza nje, sve do kraja switch naredbe.
- Sluaj default ne mora biti nuno prisutan u switch naredbi. Ako nije, i ako nema
podudaranja vrednosti izraza i navedenih konstanti, program se nastavlja prvom naredbom
iza switch naredbe.

Primer:

switch(operator) {
case'z':
printf("%g\n",a+b);
break;
case'o':
printf("%g\n",a-b);
break;
case'm':
printf("%g\n",a*b);
break;
default:
printf("Nedopustena operacija!");
}

14./*Napisati program koji e zamentiti u unetom tekstu . sa ! i slovo a sa A.*/

#include <stdio.h>
void main()
{
char ch;
int ct1 = 0;
int ct2 = 0;
while ((ch = getchar()) != '#')
{
switch(ch)
{
case '.' : putchar('!'); ++ct1; break;
case 'a' : putchar('A'); ++ct2; break;
default : putchar(ch);
}
}
printf("\n");
printf("Zamenjeno je %d . sa !\n", ct1);
printf("Zamenjeno je %d slova a with A\n", ct2);
}

14
15./*Napisati program koji za uneti broj meseca (na primer, 1=Januar, 2=Februar, itd.)
ispisuje njegov broj dana. U sluaju unete vrednosti 2 pitati korisnika da li je godina
prestupna.*/
#include<stdio.h>
void main()
{
int mesec;
char ch;
printf("Uneti redni broj meseca\n");
scanf("%d",&mesec);
switch(mesec)
{
case 1:case 3:case 5:case 7:case 8:case 10: case 12: printf("31 dan\n"); break;
case 4: case 6: case 9: case 11: printf("30 dana\n"); break;
case 2: printf("Da li je godina prestupna (d/n)?\n"); scanf("%c%c",&ch,&ch);
if((ch=='d')||(ch=='D'))
printf("29 dana\n");
else
printf("28 dana\n");
break;
default: printf("Nekorektan broj meseca\n");
}
}

16. Napisati program koji na ulazu ima prirodan broj a i realan broj x. Program treba da
izrauna vrednost funkcije y i da je odtampa i to na sledei nain:
- ako je a = 1 tada je y = 3x-2
- ako je a = 2 tada je y = sin(2x)-3x+1
- ako je a = 3 tada je y = x 3 - x+1
- a ako je a bilo ta drugo onda je y = x.

#include <stdio.h>
#include <math.h>
main ( ) {
int a;
double x, y;

printf("Unetite ceo broj a i realan broj x:");


scanf("%d%lf",&a, &x);

switch (a){
case 1: y=3*x-2; break;
case 2: y=sin(2*x)-3*x+1; break;
case 3: y=pow(x,3)-x+1; break;
default: y=x; break;
}
printf("rezultujuca funkcija je:%.4lf\n", y);
}

15
- ako je a = 1 tada je y = |x| + |x-5|....................................................y = fabs(x)+fabs(x-5)
- ako je a = 2 tada je y najvei ceo broj koji nije vei od x..............y = floor(x)
- ako je a = 3 tada je y = sin(x+5)-e x ...............................................y = sin(x+5)+exp(x)
- ako je a = 4 tada je y najmanji ceo broj ne manji od x...................y = ceil(x)

While petlja

while(uslov_petlje)
while_iskaz;
sledeci_iskaz;

While iskaz se izvrava sve dok je uslov_petlje istinit (razliit od nule), a kad je neistinit
onda se prelazi na sledeci_iskaz;. While_iskaz se izvrava jednom ili vie puta, zavisno od
uslova_petlje.

17./*Program za izraunavanje sume prvih n=10 celih brojeva, pri emu se koriste razliite
petlje*/

#include <stdio.h>
void main()
{
int i,n=10,S=0;
i=1;
while (i <= n)
{
S+=i;
i++;
}
printf("\n Suma je %d\n", S);
}

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


while (i <= n) do {
{ { S+=i;
S+=i; S+=i; }
i++; i++;
} } while (i <= n);

16
18./*Program za tampanje tabele koja pretvara Fahrenheitove stepene u Celzijuse. Za
Fahrenheitove stepene koristiti redom brojeve od 0, 20, ..., 300. celsius=5*(fahr-32)/9*/

#include <stdio.h> /* stampanje Fahrenheit-Celsius tabele za fahr = 0, 20, ..., 300 */


void main()
{
int fahr, celsius;
int lower, upper, step;
lower = 0;
upper = 300;
step = 20;
fahr = lower;
while (fahr <= upper)
{
celsius = 5 * (fahr-32) / 9;
printf("%d\t%d\n", fahr, celsius);
fahr = fahr + step;
}
}

19. /*Program za odreivanje srednje vrednosti n celih pozitivnih brojeva*/

#include<stdio.h>
void main()
{
int n, brojac=0;
float suma=0, x;
printf("Ukupno brojeva?\n");
scanf("%d",&n);
while(brojac<n)
{
printf("Ukucajte %d. broj?", brojac+1);
scanf("%f",&x);
suma+=x;
brojac+=1;
}
printf("Srednja vrednost ovih borjeva je %6.2f\n",suma/n);
}

17
Do-while petlja
do
do_iskaz;
while(uslov_petlje)
sledeci_iskaz;

U do-while iskazu prvo se izvrava do-iskaz. Zatim se izvrava uslov_petlje. Ako je


istinit, petlja se nastavlja, inae se petlja zavrava i kontrola prenosi na sledeci_iskaz. Do-while
iskaz se koristi za sluaj da je petlju neophodno izvriti najmanje jedanput.

20. /*Program za permutovanje cifara celog broja*/

#include<stdio.h>
void main()
{
int broj;
printf("Ukucajte ceo broj?\n");
scanf("%d",&broj);
printf("Permutovan broj je\n");
do
{
printf("%d",broj%10);
broj/=10;
}
while(broj);
printf("\n");
}

For petlja

for(pocetni_izraz; uslov_petlje; izraz_petlje)


programski_iskaz;
sledeci_iskaz;

pocetni_izraz, postavlja poetne parametre petlje (moe ih biti vie, pri emu se
razdvajaju zarezom). uslov_petlje predstavlja uslov koji je potreban da bi se petlja nastavila, a
ako je uslov_petlje jednak 0 (neistinit) telo petlje se ne izvrava i kontrola se prenosti na
sledeci_iskaz.

- Beskonana petlja koja ne radi nita:


for(;;);

21. /*Program za izraunavanje faktorijela*/


#include<stdio.h>
void main()
{
int i,n;
long fak=1;
printf("Izracunavanje n!\nUkucajte broj (<33)?");
scanf("%d",&n);
for(i=1;i<=n;i++)
fak*=i;
printf("%d!=%ld\n",n,fak);
}
18
22. /*Program za odredjivanje srednje vrednosti n celih pozitivnih brojeva-for iskaz*/

#include<stdio.h>
void main()
{
int n, brojac=1;
float suma=0, x;
printf("Ukupno brojeva?\n");
scanf("%d",&n);
for(;brojac<=n;++brojac,suma+=x) /*for(;...) - brojac je na pocetku postavljen na 1*/
{
printf("Ukucajte %d. broj?", brojac);
scanf("%f",&x);
}
printf("Srednja vrednost ovih brojeva je %6.2f\n",suma/n);
}

FUNKCIJE
Funkcija je programska celina koja uzima neke ulazne podatke, izvrava odreen niz naredbi i
vraa rezultat svog izvravanja.

Definicija funkcije ima oblik:


tip_p ime_funkcije(tip_1 arg_1, ... ,tip_n arg_n)
{
telo funkcije
}

gde je tip_p tip podatka koji e funkcija vratiti kao rezultat svog izvravanja. Unutar zagrada
nalazi se deklaracija formalnih argumenata funkcije. Prvi argument, arg_1, je promenljiva tipa
tip_1 itd. Deklaracije pojedinih argumenata meusobno se odvajaju zarezima. Unutar vitiastih
zagrada pojavljuje se telo funkcije koje se sastoji od deklaracija promenljivih i izvrnih naredbi.

poruka()
{ /*Zaglavlje funkcije*/
printf(Zdravo!\n); /*Telo funkcije su svi iskazi izmedju { i }*/
}

Primer :

#include <stdio.h>
Sledea funkcija pretvara mala slova (engleske abecede) u velika.

char malo_u_veliko(char z) {
char c;
c= (z >= 'a' && z <= 'z') ? ('A' + z - 'a') : z;
return c;
}

19
Poziv funkcije:

int main(void) {
char malo, veliko;
printf("Unesite malo slovo: ");
scanf("%c", &malo);
veliko = malo_u_veliko(malo);
printf("\nUneseno slovo = %c\n",veliko);
return 0;
}

char malo_u_veliko(char z)
{
if(z >= 'a' && z <= 'z')
return('A' + z - 'a');
else
return z;
}

if naredba i uslovni operator

Sedee dve naredbe su ekvivalentne:

1) max = a>b ? a : b

2) if(a>b) max=a;
else max=b;

Funkcija tipa void:


Kada funkcija ne vraa nikakvu vrednost onda se za tip vraene vrednosti koristi kljuna re
void:

Primer:
#include <stdio.h>

void maximum(int x, int y)


{
int z;
z=(x>=y) ? x : y;
printf("\nMaksimalna vrednost =%d\n",z);
return;
}

int main(void)
{
int x,y;
printf("Unesite dva cela broja: ");
scanf("%d %d", &x,&y);
maximum(x,y);
return 0;
}

20
void maximum(int x, int y)
{
int z;
if(x>y) z=x;
else z=y;
printf("\nMaksimalna vrednost =%d\n",z);
return;
}

23. /*Napisati program za izraunavanje sume kvadrata celih brojeva od 1 do n*/

#include<stdio.h>
suma_kvadrata(int n)
{
int i;
long suma=0;
for(i=1; i<=n; suma+=(long)i*i,++i);
printf("Suma kvadrata od 1 do %d je %ld\n",n,suma);
}
main()
{
suma_kvadrata(10);
suma_kvadrata(15);
suma_kvadrata(20);
}

Funkcija suma_kvadrata(n) je deklaracija funkcije, koja definie ime funkcije (identifikator


suma_kvadrata), broj argumenata funkcije i njihova imena, i predstavljaju formalne argumente.
Ovde je definisan samo jedan argument n koji predstavlja formalni argument jer se koristi samo
u definiciji funkcije. Na kraju funkcije se nalazi return promenljiva; gde se kao rezultat funkcije
vraa vrednost promenljive. Funkcija se poziva tako to se u glavnom programu napie ime
funkcije sa odgovarajuim argumentima funkcije. Kada se pozove funkcije, u zagradi stoje
stvarni argumenti

24./*Napisati program u kome se definie funkcija prost() koja ispituje da li je broj prost i
funkcija main() koja njenim korienjem tampa sve proste brojeve do datog prirodnog
broja n.*/
#include<stdio.h>
#include<math.h>
int prost(int n)
{
int i;
for (i=2;i<=sqrt(n);i=i+1)
if(n%i==0)
return 0;
return i;
}
void main()
{
int i,n;
printf("Uneti broj\n");
scanf("%d",&n);
printf("Prosti brojevi su\n");
for(i=2;i<=n;i=i+1)

21
if(prost(i)) printf("%d\n",i);
}

25./*Napisati program kojim se ispisuju parovi prijateljskih brojeva do n. Za dva broja


kaemo da su prijateljski, ako je jedan broj jednak sumi delioca drugog broja. U sumu
delioca ne ulazi sam taj broj. Sumu delioca raunati korienjem funkcije Npr. prijateljski
brojevi su:
220=1+2+4+71+142
284=1+2+4+5+10+11+20+22+44+55+110*/

#include<stdio.h>
#include<math.h>
int sumadelioca(int n)
{
int s=1,i;
for (i=2;i<=sqrt(n);i++)
if(n%i==0) s+=i+(n/i)*(i!=n/i); //uslov (i!=n/i) izost. duplir. faktora npr. za 36
return s;
}
void main()
{
int s,i,n;
printf("Uneti broj n\n");
scanf("%d",&n);
printf("Trazeno svojstvo do %d imaju:\n",n);
for(i=2;i<=n;i=i+1)
{
s=sumadelioca(i);
if(s<=i&&sumadelioca(s)==i) printf("%5d%5d\n",i,s);
}
}

26./*Napisati program za izraunavanje faktorijela zadatog broja n korienjem funkcije


fakt().*/
#include<stdio.h>
int fakt(int n)
{
int p=1,i;
for(i=2;i<=n;i++)
p*=i;
return p;
}
void main()
{
int n;
long broj;
printf("Uneti broj ciji faktorijel trazimo\n");
scanf("%d",&n);
broj=fakt(n);
printf("Faktorijel broja %d je: %ld\n",n,broj);
}

22
21./*Napisati program kojim se tampaju svi trocifreni brojevi (ako ih ima) koji su jednaki
sumi faktorijela svojih cifara.*/
#include<stdio.h>
int fakt(int n)
{
int p=1,i;
for(i=2;i<=n;i++)
p*=i;
return p;
}
void main()
{
int n,a,b,c;
printf("Trocifreni brojevi jednaki sumi faktorijela svojih cifara su:\n");
for(n=100;n<1000;n++)
{
a=n%10;
b=n/10%10;
c=n/100;
if(n==fakt(a)+fakt(b)+fakt(c)) printf("%d\n",n);
}
}

Funkcije getchar i putchar: (<stdio.h>)

int getchar(void);
int putchar(int);

Funkcija getchar ita jedan znak sa standardnog ulaza (tastature). Funkcija nema argumenata pa je
sintaksa poziva:
c_var=getchar();
Funkcija putchar alje jedan znak na standardni izlaz (ekran). Ona uzima jedan argument (znak koji
treba ispisati) i vraa celobrojnu vrednost. Najee poziv funkcije ima oblik
putchar(c_var);
pri emu se vraena vrednost ignorie.

D O D A T A K

Naredba break

Naredba break slui za zaustavljanje petlje i izlazak iz switch naredbe. Moe se koristiti sa for,
while i do-while petljom. Pri nailasku na naredbu break kontrola programa se prenosi na prvu
naredbu iza petlje ili switch naredbe unutar koje se break nalazi.

Primer:
int i;
while(1){
scanf("%d",&i);
if (i<0) break;
.........
}

23
while(1) je beskonana petlja. Iz nje se izlazi ukoliko se uita negativan broj.

Naredba goto

goto naredba prekida sekvencijalno izvravanje programa i nastavlja izvravanje s naredbom


koja je oznaena labelom koja se pojavljuje u goto. Oblik joj je
goto labela;
gdje je label identifkator koji slui za oznaavanje naredbe kojom se nastavlja program. Sintaksa
je
labela: naredba;
Labela na koju se vri skok mora biti unutar iste funkcije kao i goto naredba (pomou goto se ne
moe izai iz funkcije).

Naredba continue

Naredba continue koristi se unutar for, while i do-while petlje. Nakon nailaska na continue
preostali deo tela petlje se preskae i program nastavlja sa sledeim prolazom kroz petlju.

int i;
while{1){
scanf("%d",&i);
if (i<0) continue;
.........
}
Sada nam u delu koda koji obrauje pozitivne brojeve treba neki drugi nain izlaza iz petlje.

Primer:

scanf("%d",&i);
while{i<=100){
.......
if (i<0) goto error;
.........
scanf("%d",&i);
}
.......
/* detekcija greske */
error: {
printf("Greska : negativna vrednost!\n");
exit(-1);
}

Naredbe break i continue mogu se izvesti pomou goto naredbe. Na primer, kod

for(...) {
.......

24
if (...) continue;
........
}

je ekvivalentan s

for(...) {
.......
if (...) goto cont;
.......
cont: ;
}

Slino vredi i za continue unutar while i do-while petlje.

22./* Napisati program za rekurzivnu funkciju za izraunavanje n-tog stepena realnog


broja x0, ako je n ceo broj.*/
1, n0
n 1
x x x , n 0
n

1 / x n , n 0

moe se izvriti sledea rekurzivna formula:
1, n0

stepen x, n x stepen x, n 1, n 0
1 / stepen x,n , n 0

na osnovu ovoga se formira sledea rekurzivna funkcija:

#include<stdio.h>
double stepen(double x, int n)
{
if (n==0) return 1;
if(n>0) return x*stepen(x,n-1);
if(n<0) return 1/stepen(x,-n);
}
void main()
{
int n;
double x;
printf("Uneti vrednosti realnog broja\n");
scanf("%lf",&x);
printf("Uneti vrednosti stepena\n");
scanf("%d",&n);
printf("Vrednost %d stepena broja %lf je %lf\n",n,x,stepen(x,n));

JEDNODIMENZIONALNI I VIEDIMENZIONALNI NIZOVI


Nizovi predstavljaju skup homogenih podataka. Nizove treba razlikovati od struktura
koje predstavljaju skup heterogenih podataka. Elementi niza su istog tipa, dok su elementi
struktura razliitih tipova. Niz se obeleava:

25
int a[20];
gde int deklarie tip svih elemenata niza, kojih ima 20 (broj izmeu uglastih zagrada). Da bi se
dodelila poetna vrednost elementima niza na ovaj nain, mora se staviti kljuna re static pre
deklaracije. Npr.:
static int ocena[5]={6,7,8,9,10};
deklarie celobrojni niz ije su poetne vrednosti 6, 7, 8, 9, 10. Ili slino imamo:
static char slova[5]={a,e,i,o,u};

Primer: int broj[100];

Ovim se uvodi niz broj koji se sastoji iz 100 celobrojnih promenljivih sa imenima broj[0],
broj[2], broj[3],...., broj[99] . Prema tome indeksiranje elemenata niza je od 0, a ne od 1.

12 broj[0] (sadri prvi broj, na primer 12)


4 broj[1] (sadri prvi broj, na primer 4)
10 broj[2] (sadri prvi broj, na primer 10)
....
....
7 broj[99] (sadri prvi broj, na primer 7)

29. /*Napiite funkciju koja kao argumente uzima niz realnih brojeva i ceo broj n (koji
oznaava duinu niza). Funkcija treba uzlazno da sortira niz. Napiite i kako se funkcija
poziva (pretpostavite da imate uitani niz sa n elemenata)*/

#include <stdio.h>

void sort(double x[] , int n) {


int i,j;
for ( i = 0 ; i <n-1 ; i++)
for ( j = i+1 ; j<n ; j++)
if ( x[i] >= x[j] ) {
double temp = x[i];
x[i] = x[j];
x[j] = temp;
}
}

int main(void){
double a[50];int n;
...
sort(a, n);
}

int main(void){
double a[50];int n;
...
sort(a, n);
}

26
este greke:
sort(a[], n);
sort(a[n], n);
sort(a[0], n);

30. /*Napisati program za unos i stampanje 10 ocena ucenika*/


#include<stdio.h>
void main()
{
int i,ocena[10];
printf("Uneti ocene ucenika\n");
for(i=0;i<10;i++)
scanf("%d",&ocena[i]);
printf("Unete ocene ucenika su:\n");
for(i=0;i<10;++i)
printf("%c ocena[%2d]=%2d",(i%5==0)?'\n':' ',i,ocena[i]);
printf("\n");
}

31. /*Program za sortiranje jednodimenzionalnih nizova realnih brojeva od najmanjeg do


najveceg*/
#include<stdio.h>
void main()
{
int n,i,j;
float priv, x[100];
do
{
printf("Koliko brojeva za sortiranje?[<100]:");
scanf("%d",&n);
}
while(n>=100||n<=0);
printf("\n");
/*Ucitavanje n brojeva*/
for(i=0;i<n;++i)
{
printf("? x[%2d]=",i);
scanf("%f",&x[i]);
}
/*Sortiranje*/
for(j=0;j<n-1;++j)
for(i=j+1;i<n;++i)
if(x[i]<x[j])
{
priv=x[j];
x[j]=x[i];
x[i]=priv;
}
/*Stampanje sortiranih brojeva*/
printf("\nSortiranji brojevi:\n");
for(i=0;i<n;++i)
printf("x[%2d]=%15.6e\n",i,x[i]);
}

32./*Napisati program za odreivanje broja maksimalnih elemenata niza. U reavanju koristiti funkciju za
unos lanova niza.*/

27
#include <stdio.h>
void citaj(float a[],int n)
{
int i;
printf("Uneti niz \n");
for(i=0;i<n;i++)
{
printf("a[%d]=",i);
scanf("%f",&a[i]);
}
}

int BrojMax(float a[],int n)


{
float max;
int i,k;
max=a[0]; k=1;
for(i=1;i<n;i++)
if(a[i]>max)
{
max=a[i];
k=1;
}
else if(a[i]==max)
k++;
return k;
}
void main()
{
float a[100];
int n;
printf("Uneti broj elemenata niza\n");
scanf("%d",&n);
citaj(a,n);
printf("U nizu ima %d maksimalnih clanova\n", BrojMax(a,n));
}

33. /*Dat je niz realnih brojeva. Napisati funkciju koja:


a) izraunava sumu elemenata niza koji prethode prvoj nuli u nizu;
b) odreuje broj elemenata koji prethode prvom negativnom elementu u nizu;
c) izraunava proizvod elemenata izmeu prve i druge nule u nizu (niz ima bar dve nule);*/
#include <stdio.h>
void citaj(float a[],int n)
{
int i;
printf("Uneti niz \n");
for(i=0;i<n;i++)
scanf("%f",&a[i]);
}
float suma(float a[],int n)
{
int i=0;
float s=0;
while(i<n&&a[i])
s+=a[i++];
return s;
}

28
int BrojPoz(float a[],int n)
{
int k=0,i;
for(i=0;i<n&&a[i]>=0;i++)
k++;
return k;
}
proizvod(float a[],int n)
{
int i,k=0;
float p=1;
for(i=0;i<n&&k<2;i++)
{
if(a[i]==0)k++;
if(k==1&&a[i]!=0)
p*=a[i];
}
return p;
}
void main()
{
float a[100];
int n;
printf("Uneti broj elemenata niza\n");
scanf("%d",&n);
citaj(a,n);
printf("Suma elemenata niza koji prethode prvoj nuli u nizu je %f\n", suma(a,n));
printf("Broj elemenata koji prethode prvom negativnom elementu je %d\n",BrojPoz(a,n));
printf("Proizvod elemenata niza izmedju prve i druge nule je %f\n",proizvod(a,n));

}
34./*Dat je niz realnih brojeva. Napisati program koji saima niz uklanjanjem elemenata ija je
vrednost jednaka zadatom broju X.*/
#include <stdio.h>
void citaj(float a[],int n)
{
int i;
printf("Uneti niz \n");
for(i=0;i<n;i++)
scanf("%f",&a[i]);
}
void pisi(float a[],int n)
{
int i;
for(i=0;i<n;i++)
printf("%f\t",a[i]);
}

void main()
{
float a[100],x;
int k=-1,i,n;
printf("Uneti broj elemenata niza\n");
scanf("%d",&n);
printf("Uneti x\n");
scanf("%f",&x);
citaj(a,n);

29
for(i=0;i<n;i++)
if(a[i]!=x)
a[++k]=a[i];
n=k+1;
printf("Novi niz je\n");
pisi(a,n);
prinf("\n");
}
35. /*Dat je niz realnih brojeva. Napisati funkciju koja:
d) ispisuje sve elemente niza koji se u nizu pojavljuju tano jedanput;
e) proverava da li u nizu postoji par jednakih elemenata;
#include <stdio.h>
void citaj(float a[],int n)
{
int i;
printf("Uneti niz \n");
for(i=0;i<n;i++)
scanf("%f",&a[i]);
}
void tacnojednom(float a[],int n)
{
int k,i,j;
for(i=0;i<n;i++)
{
k=0;
for(j=0;j<n;j++)
if(a[i]==a[j])
k++;
if(k==1)
printf("%f\n",a[i]);
}
}
void parjednakih(float a[],int n)
{
int k,i,j;
for(i=0;i<n-1;i++)
{
k=0;
for(j=i+1;j<n;j++)
if(a[i]==a[j])
k++;
if(k==1)printf("%f\n",a[i]);
}

}
void main()
{
float a[100];
int n;
printf("Uneti broj elemenata niza\n");
scanf("%d",&n);
citaj(a,n);
printf("Elementi koji se pojavljuju tacno jedanput su:\n");
tacnojednom(a,n);
printf("Par jednakih je \n");
parjednakih(a,n);
}

30
36./*Napisati program koji za uneti niz a od n elemenata, prebacuje negativne elemente na kraj niza bez
obzira na njihov poredak*/
#include <stdio.h>
void citaj(float a[],int n)
{
int i;
printf("Uneti niz \n");
for(i=0;i<n;i++)
{
printf("a[%d]=",i);
scanf("%f",&a[i]);
}
}
void uredi(float a[],int n)
{
float pom;
int i,j;
i=0; j=n-1;
while(i<j)
if(a[i]>0) i++;
else
{
if(a[j]>0)
{
pom=a[i];
a[i]=a[j];
a[j]=pom;
j--;
}
}
}
void pisi(float a[],int n)
{
int i;
printf("Formirani niz\n");
for(i=0;i<n;i++)
printf("a[%d]=%5.2f\n",i,a[i]);
}
void main()
{
float a[100];
int n;
printf("Uneti broj elemenata niza\n");
scanf("%d",&n);
citaj(a,n);
uredi(a,n);
pisi(a,n);
}

37. /*Dat je niz celih brojeva A dimenzija n. Napisati funkciju na programskom jeziku C koja
vraca zbir poslednjih 8 clanova niza A.*/

Uradjen ceo program.

31
#include<stdio.h>

#define DIM 100

void main(){
int A[DIM];
int i, n;
int zbir=0;

printf("Unesite broj elemenata niza:\n");


scanf("%d", &n);

printf("Unesite elemenateniza:\n");
for(i=0; i<n; i++)
scanf("%d", &A[i]);

for(i=n-1; i>n-9; i--)


zbir+=A[i];

printf("Zbir zadnjih osam elemenata niza je: %d\n", zbir);


}

ili kao funkcija:

int zbirZadnjihOsam(int niz[], int n)


{
int i;
int zbir=0;
for(i=n-1; i>n-9; i--)
zbir+=niz[i];

return zbir;
}

VIEDIMENZIONALNI NIZOVI

Oznaavanje matrice M od i vrste i j kolona M[i][j], ili viedimenzionalnog vektora Z[i][j][k] itd.
Dvodimenzionalni vektori se inicijalizuju na slian nain kao jednodimenzionalni. Inicijalizacioni
elementi se navode po vrstama. Vitiaste zagrade se mogu koristi za izdvajanje inicijalizacionih
elemenata jedne vrste od druge. Inicijalizacija matrice M je:

static int M[4][3]={


{13,-18,21},
{36,101,0},
{-5,0,-9},
{3,1,9}
};

Npr:
int x[10];
int y[10][20];
int z[15][25][35];
...

32
printf("%d", y[7][13]);
scanf("%d", &y[2][0]);
scanf("%d", &z[6][24][10]);

Kod prosleivanja viedimenzionalnih polja u funkciju, u zaglavlju funkcije se moraju navesti dimenzije
polja osim prvog.

void funkcija(int z[][25][35]);

38. /*Program za skalarno mnoenje matrica*/

#include<stdio.h>
void main()
{
int vrsta,kol;
float scalar;
static float matrica[3][5]={
{7.0,16.83,55.131,13.1,12.91},
{15.0,10.9,42.99,0.0,7.7},
{-2.2,1.1,2.2,4.4,9.9}
};
printf("Originalna matrica:\n");
for(vrsta=0;vrsta<3;++vrsta)
{
for(kol=0;kol<5;++kol)
printf("%10f",matrica[vrsta][kol]);
printf("\n");
}
printf("\n Scalar?\n");
scanf("%f",&scalar);
for(vrsta=0;vrsta<3;++vrsta)
for(kol=0;kol<5;++kol)
matrica[vrsta][kol]*=scalar;
printf("\n Matrica posle skalarnog mnozenja:\n");
for(vrsta=0;vrsta<3;++vrsta)
{
for(kol=0;kol<5;++kol)
printf("%10f\t", matrica[vrsta][kol]);
printf("\n");
}
}

39. /*Napisati program za sabiranje matrica a i b dimenzije n i tampanje rezultujue matrice c*/

#include <stdio.h>
void citaj(int a[][10],int n)
{
int i,j;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
scanf("%d",&a[i][j]);
}
void zbir(int a[][10],int b[][10],int c[][10],int n)
{
int i,j;
for(i=0;i<n;i++)
{

33
for(j=0;j<n;j++)
{
c[i][j]=a[i][j]+b[i][j];
printf("%d\t",c[i][j]);
}
printf("\n");
}
}
void main()
{
int a[10][10],b[10][10],c[10][10];
int n;
printf("Uneti broj vrsta i kolona matrice a i b\n");
scanf("%d",&n);
printf("Uneti elemente matrice a\n");
citaj(a,n);
printf("Uneti elemente matrice b\n");
citaj(b,n);
printf("Zbir matrica a i b je:\n");
zbir(a,b,c,n);
}

40./*Program za mnoenje dve zadate matrice*/

#include<stdio.h>
void citaj(float m[][10],int n)
{
int i,j;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
scanf("%f",&m[i][j]);
}
void mnozenje(float m1[][10], float m2[][10],float m3[][10],int n)
{
int i,j,k;
for(i=0;i<n;++i)
for(j=0;j<n;++j)
for(m3[i][j]=0,k=0;k<n;++k)
m3[i][j]+=m1[i][k]*m2[k][j];
}
void pisi(float m[][10],int n)
{
int i,j;
for(i=0;i<n;++i)
{
for(j=0;j<n;++j)
printf("%5.2f\t",m[i][j]);
printf("\n");
}
}
void main()
{
float m1[10][10],m2[10][10],m3[10][10];
int n;
printf("Uneti dimenziju matrica \n");
scanf("%d",&n);
printf("Uneti elemente matrice m1\n");

34
citaj(m1,n);
printf("Uneti elemente matrice m2\n");
citaj(m2,n);
printf("\n\nProizvod matrica m1*m2\n");
printf("...................................\n");
mnozenje(m1,m2,m3,n);
pisi(m3,n);
}

41./*Program za transponovanje matrice a dimenzije n*/

#include <stdio.h>
void citaj(int a[][10],int n)
{
int i,j;
printf("Uneti elemente matrice \n");
for(i=0;i<n;i++)
for(j=0;j<n;j++)
scanf("%d",&a[i][j]);
}
void transponovana(int a[][100],int n)
{
int i,j,p;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
p=a[i][j];
a[i][j]=a[j][i];
a[j][i]=p;
}
}
void pisi(int a[][10],int n)
{
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
printf("%\t",a[i][j]);
printf("\n");
}
}
void main()
{
int a[100][100];
int n;
printf("Uneti broj vrsta i kolona matrice\n");
scanf("%d",&n);
citaj(a,n);
transponovana(a,n);
pisi(a,n);
}

42./*Napisati program koji u matrici realnih brojeva a odreuje:


a) maksimalni element;
b) sumu elemenata ispod glavne dijagonale;
c) sumu elemenata iznad sporedne dijagonale.*/

35
#include <stdio.h>
void citaj(float a[][10],int n)
{
int i,j;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
scanf(%f,&a[i][j]);
}
float maksimalni(float a[][10],int n)
{
int i,j;
float max=a[0][0];
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(max<a[i][j]) max=a[i][j];
return max;
}
float sumaispodgd(float a[][10],int n)
{
float s=0;
int i,j;
for(i=1;i<n;i++)
for(j=0;j<i;j++)
s+=a[i][j];
return s;
}
float sumaiznadsd(float a[][10],int n)
{
float s=0;
int i,j;
for(i=0;i<n-1;i++)
for(j=0;j<n-1-i;j++)
s+=a[i][j];
return s;
}
void main()
{
float a[10][10];
int n;
printf(Uneti broj vrsta i kolona matrice a \n);
scanf(%d,&n);
printf(Uneti elemente matrice a\n);
citaj(a,n);
printf(Maksimalni element matrice a je: %f\n\n,maksimalni(a,n));
printf(Suma elemenata ispod glavne dijagonale je: %f\n\n,sumaispodgd(a,n));
printf(Suma elemenata iznad sporedne dijagonale je: %f\n\n,sumaiznadsd(a,n));
}

II nain

#include <stdio.h>
void citaj(float a[][10],int n)
{
int i,j;
for(i=0;i<n;i++)

36
for(j=0;j<n;j++)
scanf("%f",&a[i][j]);
}
float maksimalni(float a[][10],int n)
{
int i,j;
float max=a[0][0];
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(max<a[i][j]) max=a[i][j];
return max;
}
float sumaispodgd(float a[][10],int n)
{
float s=0;
int i,j;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(i>j)
s+=a[i][j];
return s;
}
float sumaiznadsd(float a[][10],int n)
{
float s=0;
int i,j;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(i+j<n-1)
s+=a[i][j];
return s;
}
void main()
{
float a[10][10];
int n;
printf("Uneti broj vrsta i kolona matrice a \n");
scanf("%d",&n);
printf("Uneti elemente matrice a\n");
citaj(a,n);
printf("Maksimalni element matrice a je: %f\n\n",maksimalni(a,n));
printf("Suma elemenata ispod glavne dijagonale je: %f\n\n",sumaispodgd(a,n));
printf("Suma elemenata iznad sporedne dijagonale je: %f\n\n",sumaiznadsd(a,n));
}

43. Data je matrica celih brojeva x dimenzije nxn. Napisati program za sortiranje matrice po
vrstama u rastuem poretku.

#include<stdio.h>
void citaj(int x[][10],int n)
{
int i,j;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
printf("x[%d,%d]=",i,j);
scanf("%d",&x[i][j]);

37
}
}
void pisi(int x[][10],int n)
{
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
printf("%3d",x[i][j]);
printf("\n");
}
}
void razmeni(int*a,int*b)
{
int pom;
pom=*a;*a=*b;*b=pom;
}
void sort(int a[][10],int n)
{
int i,j,k;
for(i=0;i<n;i++)
for(j=0;j<n-1;j++)
for(k=j+1;k<n;k++)
if(a[i][j]>a[i][k])
razmeni(&a[i][j],&a[i][k]);
}

main()
{
int n;
int x[10][10];
printf("\nUneti broj vrsta matrice:");
scanf("%d",&n);
printf("\nUnesi elemente matrice po vrstama :\n");
citaj(x,n);
sort(x,n);
printf("matrica posle sortiranja je:\n");
pisi(x,n);
}

44. Napisati funkciju za soritranje matrice a dimenzije nxn po kolonama u rastuem redosledu.
void sort(int a[][10],int n)
{
int i,j,k;
for(j=0;j<n;j++)
for(i=0;i<n-1;i++)
for(k=i+1;k<n;k++)
if(a[i][j]>a[k][j])
razmeni(&a[i][j],&a[k][j]);
}

45. Napisati funkciju za soritranje elemenata na glavnoj dijagonali matrice a dimenzije nxn u
rastuem redosledu.
void sort(int a[][10],int n)
{
int i,j;
for(i=0;i<n-1;i++)

38
for(j=i+1;j<n;j++)
if(a[i][i]>a[j][j])
razmeni(&a[i][i],&a[j][j]);
}

46. Napisati funkciju za soritranje elemenata spredne dijagonale matrice a dimenzije nxn u
rastuem redosledu.
void sort(int a[][10],int n)
{
int i,j;
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
if(a[i][n-i-1]>a[j][n-j-1])
razmeni(&a[i][n-i-1],&a[j][n-j-1]);
}

47. Data je matrica M dimenzije nxn. Formirati niza A dimenzije n od maksimalnih elemenata
matrice po vrstama.
#include<stdio.h>
void citaj(int x[][10],int n)
{
int i,j;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
printf("x[%d,%d]=",i,j);
scanf("%d",&x[i][j]);
}
}
void pisi(int x[],int n)
{
int i;
for(i=0;i<n;i++)
printf("%d\n",x[i]);
}
void niza(int n, int M[][10], int A[])
{
int i, j;
for(i=0; i<n; i++)
{
A[i]=M[i][0];
for(j=1; j<n; j++)
if(A[i]<M[i][j])
A[i]=M[i][j];
}
}

main()
{
int n, j, i;
int M[10][10], A[10];
printf("\nUneti broj vrsta matrice:");
scanf("%d",&n);
printf("\nUnesi elemente matrice po vrstama :\n");
citaj(M,n);
niza(n,M,A);
printf("Dobijeni niz je:\n");

39
pisi(A,n);
}

48. Data je matrica x dimenzije nxn. Napisati program koji koristi funkciju za sortiranje v vrste
matrice x.
#include<stdio.h>
void citaj(int x[][10],int n)
{
int i,j;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
printf("x[%d,%d]=",i,j);
scanf("%d",&x[i][j]);
}
}
void pisi(int x[][10],int n)
{
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
printf("%3d",x[i][j]);
printf("\n");
}
}

void razmeni(int*a,int*b)
{
int pom;
pom=*a;*a=*b;*b=pom;
}
void sort(int a[][10],int n, int v)
{
int i,j;
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
if(a[v][i]>a[v][j])
razmeni(&a[v][i],&a[v][j]);
}

main()
{
int n, v;
int x[10][10];
printf("\nUneti broj vrsta matrice:");
scanf("%d",&n);
printf("\nUnesi elemente matrice po vrstama :\n");
citaj(x,n);
printf("\nUneti indeks vrste koja se sortira:");
scanf("%d",&v);
sort(x, n, v);
printf("Matrica posle sortiranja je:\n");
pisi(x,n);
}

40
49. Uitati kvadratnu matricu M sa tastature i formirati matricu realnih brojeva C na ijoj glavnoj
dijagonali se dobijaju prosene vrednosti pojedinih vrsta matrice M, a svi ostali elementi su
jedinice.

#include<stdio.h>
#define DIM 100

void main(){
int M[DIM][DIM];
float C[DIM][DIM];
static float sumaRedova[DIM];//Poetne vrednosti su nule
int i, j, n;

printf("Uneti dimenzije matrice: ");


scanf("%d", &n);

printf("Uneti elemente matrice:\n");


for(i=0; i<n; i++)
for(j=0; j<n; j++)
scanf("%d", &M[i][j]);
/*Sumiranje elemenata matrice M po redovima i smestanje vrednosti u niz sumaRedova*/
for(i=0; i<n; i++)
for(j=0; j<n; j++)
sumaRedova[i]+=M[i][j];

/*Formiranje matrice C od prosecnih vrednosti vrsta matrice na glavnoj dijagonali, a ostali


elementi su jedinice (van glavne dijagonale)*/
for(i=0; i<n; i++)
for(j=0; j<n; j++)
if(i==j)
C[i][j]=sumaRedova[i]/n;
else
C[i][j]=1.;

/*Stampanje matrice C na standardnom izlazu*/


printf("\n\nNovodobijena matrica C je:\n\n");

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


printf("\n");
for(j=0; j<n; j++){
printf(" %4.2f ", C[i][j]);
}
}

printf("\n\n");
}

POKAZIVAI (POINTERI)

Pokazivaka promenljiva je promenljiva koja pokazuje na drugu promenljivu, odnosno sadri


adresu memorijske lokacije u kojoj se uva ta promenljiva.
Deklarie se tako to se u specifikaciji zada tip promenljive na koju ukazuje pokazivaka promenljiva.

Ispred imena promenljive pie se *

int *pi /*pokaziva na celobrojnu promenljivu */


41
char *pc /*pokaziva na znakovnu promenljivu */
float *a, *b /*pokaziva na float promenljive */
x = *pi dodeljuje promenljivoj x celobrojnu vrednost koja se nalazi na adresi sadranoj u promenljivoj
pi.

Primer (pokazivai) :

#include<stdio.h>
void kvadrat(int*x,int*y)
{
*y=*x**x;
printf("Unutar funkcije: x=%d, y=%d.\n",*x,*y);
}

main()
{
int x=3,y=5;
printf("Prije poziva: x=%d, y=%d.\n",x,y);
kvadrat(&x,&y);
printf("Nakon poziva: x=%d, y=%d.\n",x,y);
return 0;
}

Prenos adrese argumenata

int a; /* promenljiva tipa int */


int *pok; /* pokaziva na int tip */
a = 10; /* inicijalizacija promenljive a na 10 */
pok = &a; /* inicijalizacija pokaziva tako da pokazuje na promenljivu a */
*pok = 100; /* promena sadraja promenljive a na 100 preko pokazivaa */
a = 100;

Pokazivai omoguavaju formiranje sloenih dinamikih struktura podataka (liste, magacini,


stabla, redovi i dr.) i s tim u vezi dinamiko dodeljivanje memorije, prenos argumenata funkcije
referisanjem, efikasniji rad sa vektorima i prenos funkcija kao argumenata u druge funkcije. Proizvoljna
programska promenljiva memorisana je u odreenom memorijskom bloku, na odreenoj programskoj
lokaciji ili adresi. Pokazivai omoguavaju indirektni nain za pristupanje programskim promenljivim,
korienjem i manipulacijom adresama promenljivih. U C jeziku moemo deklarisati promenljivu, prom:
int *prom;
koja omoguava da se indirektno pristupi vrednosti promenljive prom. Karakter zvezdica * deklarie
promenljivu kao pokaziva, a tip int da je promenljiiva prom pokaziva na celobrojnu promenljivu, to

42
znai, ovo predstavlja indirektan pristup celobrojnim promenljivim. Adresni operator & se koristi u
funkciji scanf za prenos uitane vrednosti u pozivajuu funkciju main().
Operator indirekcije * omoguava indirektno pristupanje promenljivoj koristei pokaziva na tu
promenljivu. Ako je x deklarisana kao int, tada se iskazom
x=*prom;
promenljivoj x dodeljuje vrednost promenljive na koju pokazivaj prom ukazuje. Operatori * i & su
inverzni.
U C jeziku postoji specijalni operator za indirektnu selekciju lanova strukture. To je operator ->.
Operator -> je operator selekcije lanova strukture sa pokazivaem na strukturu.

Dinamike strukture podataka

Dinamike strukture zahtevaju eksplicitno rezervisanje i oslobaanje memorije. U sistemskoj biblioteci


svakog C prevodioca postoje funkcije malloc, calloc, realloc i free, kojima se rezervie i oslobaa
mimorijski blok. Za kreiranje dinamikih objekata koriste se funkcije malloc() i calloc(), a za njihovo
unitavanje funkcija free(). Pri korienju ovih funkcija treba prikljuiti zaglavlje <alloc.h>.Definicija
ovih funkcija je sledea:
1. char *malloc(size). Rezervie memorijski blok veliine size bajtova, koji se inicijalizuje na 0.
Argument size je unsigned. U sluaju uspene rezervacije malloc vraa pokaziva na rezervisani
memorijski blok. U protivnom, vraa 0.

char *malloc(unsigned n)
int *pint;
pint=(int*)malloc(200); /* izdvaja 200 bajtova. Vrednost f-je je pokaziva na char
koji se kast operatorom konvertuje u pokaziva na int tip.*/

2. char *calloc(n, size). Rezervie memorijski blok dovoljan za memorisanje n elemenata svaki
veliine size bajtova, znai n*size. Rezervisan memorijski blok je inicijalizovan na 0. U sluaju
uspene rezervacije calloc vraa pokaziva na char, koji pokazuje na rezervisan memorijski blok.
U protivnom, vraa 0.

char *calloc(unsigned n, unsigned vel) /*n je br. elemenata za koje treba izdvojiti memoriju,
a vel memorijski prostor koji zauzima svaki
element.*/

3. void free(pokaz). Oslobaa memorijski blok, koji je rezervisan funkcijama calloc i malloc.
Argument pokaz je pokaziva na char, koji pokazuje na memorijski blok za oslobaanje. Funkcija
free ne vraa nikakvu vrednost.
4. char *realloc(pokaz, size). Oslobaa rezervisani memorijski blok i rezervie novi veliine size
bajtova. Argument pokaz je pokazatelj na char i defimnie memorijski blok, koji se realocira.
Argument size je unsigned i odreuje veliinu realociranog memorijskog bloka. Ako je
realociranje uspoeno realloc vraa pokaziva na char, koji pokazuje na memorijski blok. U
protivnom, realloc vraa 0.

50./*Izraunati zbir i razliku dva broja koristei pokazivae na funkciju*/


#include<stdio.h>
int zbir(int *a,int *b)
{
return *a+*b;
}
int razlika(int *a,int *b)
{
return *a-*b;
}

43
void main(void)
{
int a=10, b=5, r_zbir, r_razlika;
int (*pointer[2])(int *,int *);
pointer[0]=zbir;
pointer[1]=razlika;
r_zbir=(*pointer[0])(&a,&b);
r_razlika=(*pointer[1])(&a,&b);
printf("zbir =%d razlika=%d\n",r_zbir,r_razlika);
}

51./*Stranice a i b pravougaonika su prirodni brojevi. Odrediti, na koliko se kvadrata maksimalne


povrine moe isei dati pravougaonik. Ispisati dimenzije kvadrata. Na primer za a=12 i b=7 se
ispisuje:
1 kvadrata stranice: 7
1 kvadrata stranice: 5
2 kvadrata stranice: 2
2 kvadrata stranice: 1
#include<stdio.h>
void razmeni(int *a, int *b)
{
int t;
t=*a;
*a=*b;
*b=t;
}
void main()
{
int a,b;
printf("Uneti stranice pravougaonika\n");
scanf("%d%d",&a,&b);
if(a==b)
printf("Jedan kvadrat stranice %d\n",a);
else
while(a)
{
if(a<b) razmeni(&a,&b);
printf("%d kvadrata stranice: %d\n",a/b,b);
a=a%b;
}
}
52. /*Nizovi i pokazivaci*/
#include<stdio.h>
void main()
{
float a,b,c,fniz[5]={0.01,0.1,0.5,1.0,10.0};
float *p_fniz;
char tekst[]={"Ovo je znakovni niz\n"};
char *p_tekst;
int i;
p_fniz=fniz;
a=*p_fniz;
b=*(p_fniz+2);
p_fniz=&fniz[2];
c=*(p_fniz+2);
printf("a=%f b=%f c=%f\n",a,b,c);
for(i=0;tekst[i]!='\0';++i)putchar(tekst[i]);

44
for(p_tekst=tekst;*p_tekst!='\0';++p_tekst)putchar(*p_tekst);
}

53. /*Program za odredjivanje duzine stringa*/


#include<stdio.h>
int duzina(char *p_string);
void main(int argc,char *argv[])
{
char *p_text={"ovo je znakovni niz\n"};
int i;
for(i=1;i<argc;i++)
printf("argument%d%s\n",i,argv[i]);
i=duzina(p_text);
printf("duzina stringa je %d\n",i);
}
int duzina(char *p_string)
{
int l=0;
char*p;
p=p_string;
while(*p!='\0')
{
++l;
++p;
}
return l;
}

54./*Data je kvadratna matrica celih brojeva a dimenzije n i prirodan broj k<n. Napisati program
koristei funkciju koja realizje simetrino preslikavanje u odnosu na sporednu dijagonalu, trougla
odreenog pozicijama (0,0), (0,k-1) i (k-1,0) u odgovarajui trougao i obrnuto.*/
#include <stdio.h>
void citaj(int a[][10],int n)
{
int i,j;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
scanf("%d",&a[i][j]);
}

void razmeni (int *x,int *y)


{
int p;
p=*x; *x=*y; *y=p;
}

void f(int a[][10],int n, int k)


{
int i,j;
for(i=0;i<k;i++)
for(j=0;j<k-i;j++)
razmeni(&a[i][j],&a[n-1-j][n-1-i]);
}
void pisi(int a[][10],int n)
{
int i,j;
for(i=0;i<n;i++)

45
{
for(j=0;j<n;j++)
printf("%d\t",a[i][j]);
printf("\n");
}
}
void main()
{
int a[10][10];
int n,k;
printf("Uneti broj vrsta i kolona matrice a \n");
scanf("%d",&n);
printf("Uneti elemente matrice a\n");
citaj(a,n);
printf("Uneti k \n");
scanf("%d",&k);
printf("Dobijena matrica je:\n");
f(a,n,k);
pisi(a,n);
}

55./*Program za izraunavanje zbira kubova i kvadrata.*/

#include <stdio.h>
main()
{
int m,n,k,l,p,q,r;
void kavdrat_kub(); /*deklaracija f-je*/
kavdrat_kub(2,4,&p,&q); /*poziv f-je*/
printf("p=%d q=%d\n",p,q);
scanf("%d%d%d%d",&m,&n,&k,&l);
kavdrat_kub(m,n,&p,&q); /*poziv f-je*/
printf("p=%d q=%d\n",p,q);
kavdrat_kub(m-k,n+l,&p,&r); /*poziv f-je*/
printf("p=%d q=%d\n",p,r);
}
void kvadrat_kub(int m, int n, int *kv, int *kub) /*definicija f-je*/
{
int i;
*kv=*kub=0;
for(i=m;i<=n;i++)
{
*kv+=i*i;
*kub+=i*i*i;
}
}

56. /*Napisati program koji unosi jedan po jedan elemenat celobrojnog niza (vektora) B[9]. Kada je
unoenje zavreno odreuje se koji je najvei broj u ovom nizu i na kojoj poziciji se nalazi i tampa
se ovaj element, njegov indeks, i niz B.*/

#include <stdio.h>
main()
{

46
int B[9], max, ind_max, i;

for(i=0;i<9;i++){
printf("Uneti sledeci element niza:\n");
scanf("%d",&B[i]);
}
max=B[0];
ind_max=0;

for(i=0;i<9;i++){
if(B[i]>max){
max=B[i];
ind_max=i;
}
}
printf("\n");

printf("Najveci element niza je %d, a njegov indeks %d \n", max, ind_max);

printf("Izgled vektora (niza) B:\n");


for(i=0;i<9;i++){
printf("%d ",B[i]);
}
printf("\n");
return 0;
}

Dodatak Nizovi i pokazivai

int x[4], *p;


p=x;

p p+1 p+2 p+3


x[0] x[1] x[2] x[3]
56006 56007 56008 56009 56010 56011 56012 56013

x+2=&x[2]
*(x+2)=x[2]

*(x+i)=x[i]

1. Napisati program kojim se odredjuje koliko je ucesnika takmicenja iz programiranja imalo


natprosecne rezultate.

Problem se moze razloziti na sledece module:

1. Ucitavanje vrednosti elemenata niza.


2. Izracunavanje prosecnog rezultata:
3. Prebrojavanje natprosecnog rezultata.
4. Ispisivanje izvestaja (izlazni podaci)

#include<stdio.h>
void main()
{
int n,i,broj, ocena[50];

47
float prosek(); /*deklaracija f-je prosek*/

printf("Uneti broj takmicara\n");


scanf("%d",&n);

/*Ucitavanje elemenata niza*/


for(i=0;i<n;++i)
{
printf("ocena[%d]=",i);
scanf("%d",&ocena[i]);
}
/*Prebrojavanje natprosecnih rezultata*/
broj=0;
for(i=0;i<n;++i)
if (ocena[i]>prosek(ocena,n))
broj++;
printf("Prosecan rezultat je: %f.\n", prosek(ocena,n));
printf("Natprosecne rezultate je imalo: %d takmicara.\n",broj);
}

float prosek(int x[], int n) /*definicija f-je prosek*/


{
int i, suma;
suma=0;
for(i=0; i<n; suma+=x[i], i++);
return((float)suma/n);
}

II nain: (Operatori - int x[] i int *x su ekvivalentni, jer oba deklariu primenljivu x kao pokaziva
na niz celih brojeva )

x[4] je isto to i *(x+4)


x[i] je isto to i *(x+i)

float prosek(int *x, int n)


{
int pom, i;
suma=0;
for(i=0; i<n; suma+=*(x+i), i++);
return((float)suma/n);
}

2. Napisati funkciju kojom se realizuje ciklino premetanje vrednosti elemenata niza a[0],
a[1],...a[n-1] za jedno mesto u levo.

Traeno premetanje se realizuje tako to vrednost a[0]sklanjamo u pomonu promenljivu pom, a zatim u
n-1 koraka vrednost premetamo ulevo kroz dodele: a[0]=a[1], a[1]=a[2], ..., a[n-2]=a[n-1], i dodelom
a[n-1]=pom sauvanu vrednost od a[0] kopiramo u a[n-1].

void levo_za_1(int a[], int n)


{
int pom, i;
pom=a[0];
for(i=1; i<n; a[i-1]=a[i], i++);
a[n-1]=pom;

48
}

II nain: Ako bi umesto deklaracije int a[]; stavili int *a; { a[i] je isto to i *(a+i) }

void levo_za_1(int *a, int n)


{
int pom, i;
pom=*a;
for(i=1; i<n; *(a+i-1)=*(a+i), i++);
*(a+n-1)=pom;
}

STRINGOVI

String je niz znakova koji zavrava nul znakom '\0' (ASCII kod 0)
<string.h> sadri skup funkcija za manipulaciju stringovima, npr:
strlen, strcpy, strcat, strcmp
Stringovne konstante se navode unutar dvostrukih navodnika:
"Pero Peric", "A", "" (prazni niz), "23"
String duine 10 (npr. "Pero Peric") zauzima 11 byteova u memoriji.
Primeri deklaracije:
char niz [velicina];
char *niz; (uz obvezni malloc kasnije)
Ispis stringa : koristi se format %s, npr. printf("%s", niz)
Primeri uitavanja stringa:
gets(niz);
scanf("%s", niz);
scanf("%[^\n]", niz);

Standardni fajlovi zaglavlja

Prototipovi bibliotecnih funkcija su dati u nekoliko standardnih fajlova zaglavlja. Npr. standardni fajlovi
su:
- stdio.h-sadrzi definisane funkcije printf , scanf , putchar i getchar
- assert.h-assertions
- ctype.h-definisane su funikcije za ispitivanje karaktera
- float.h-ogranienja sistema za realne tipove podataka
- limits.h-ogranienja sistema za celobrojne tipove podataka
- math.h - matematicke funkcije
- setjmp.h-nelokalni skokovi
- signal.h-javljanje greaka i signala
- stdarg.h-lista parametara promenljive duine
- stdlib.h-utility functions; number conversions, memory allocation, exit and system, Quick Sort
- string.h-funkcije stringova
- time.h-vremenske i datumske funkcije

Nizovi karaktera su jednodimenzionalni vektori tipa char.

U standardnom zaglavlju stdio.h definisane su sledee funkcije:


- getchar() - ita sledei znak, ukljuujui i bele znakove, preko tastature. Vrednost funkcije je kod
proitanog znaka ili simbolika konstanta EOF (end of file) ukoliko je proitan signal za kraj datoteke
kao i u sluaju greke u toku itanja.

49
- putchar(c) - funkcija za ispisivanje znaka c na ekranu.
- gets(s) - funkcija za itanje jednog reda teksta
- puts(s)-funkcija za ispisivanja jednog reda teksta
- getc(c)-unos jednog karaktere
- putc(c)-tampanje jednog karaktera
- stdin-standardni ulazni tok
- stdout-standardni izlazni tok
- stderr-standardne greke
- EOF-end of file
- printf(format, arg1,...)-tampanje formatiranih podataka
- sprintf(s,format, arg1,...)-tampanje u string s
- scanf(format, &ime1,...)-unos formatiranih podataka
- sscanf(s,format, &ime1,...)-unos iz stringa s
- FILE *fp-deklaracija pokazivaa na fajl
- fopen(ime,mod-reim)-pokaziva na ime fajla (mod: r-itanje(read), w-upis(write), a-dodavanje
(append))
- fprintf(fp,format,arg1,...)-upis u fajl
- fscanf(fp,format,arg1,...)-itanje iz fajla
- fclose(fp)-zatvaranje fajla
- ferror(fp)-nenulta vrednost ukoliko je greka
- feof(fp)-nenulta vrednost ukoliko je kraj datoteke
- fgets(s,max,fp)-ita liniju u string s (< max karaktera) iz datoteke fp
- fputs(s,fp)-ispisuje string s u datoteku fp

U standardnom zaglavlju string.h definisane su sledee funkcije:


- strlen(cs)-vraa duzinu stringa cs.
- strcmp(cs,ct)-uporeuje niz cs sa nizom ct; vraa <0 ako je cs<ct, 0 ako je cs=st ili >0 ako je cs>ct.
- strcpy(s, c)-kopira niz c u niz s.
- strcpy(s, c,n)-kopira niz c u niz s prvih n karaktera.
- srtcat(s, c)-povezuje niz karaktera c iza niza s
- srtcat(s, c,n)-povezuje niz karaktera c iza niza s poevi od n-tog karaktera
- srtcmp(s, c)-uporeuje niz karaktera s sa nizom c
- srtcmp(s, c,n)-uporeuje prvih n karaktera niza s sa nizom c
- strchr(s, c)-pokaziva na prvi karakter niza c u nizu s
- strrchr(s, c)-pokaziva na poslednji karakter niza c u nizu s
- memcpy(s, c, n)-kopira n karaktera iz niza c u niz s
- memmove(s, c, n)-kopira n karaktera iz niza c u niz s sa mogunou preklapanja
- memchr(s, c, n)-pozakizva na prvi c u privih n karaktera u nizu s
- memset(s, c, n)-smeta c u prvih na karaktera niza s

U standardnom zaglavlju ctype.h definisane su sledee funkcije:


- isalnum(c)-ispituje da li je c alfanumeriki karakter (slovo ili broj)
- isalpha(c)-ispituje da li je c alfabetski karakter (slovo)
- iscntrl(c)-ispituje da li je c kontrolni karakter
- isdigit(c)-ispituje da li je c cifra
- isgraph(c)-ispituje da li je c tampani karakter (ne ukljuuje prazninu)
- islower(c)-ispituje da li je c malo slovo
- isprint(c)-ispituje da li je c karakter (samo da nije praznina)
- ispunct (c)- ispituje da li je c znak izuzimajui praznine, slovo ili broj
- isspace(c)-ispituje da li je c praznina, formfeed, nova linija, vertikalni, horizontalni karaker
- isupper(c)-ispituje da li je c veliko slovo
- isxdigit(c)-ispituje da li je c heksadecimalni broj
- tolower(c)-pretvara c u malo slovo
- toupper(c)-pretvara c u veliko slovo
- isblank(c)- ispituje da li je c razmak ili '\t' (TAB)?

50
57. Napiite program koji uitava jednu re maksimalne duine 17 znakova i ispisuje:
a) tu re
b) tu re bez prvog znaka
c) tree slovo te rei (pretpostavite da je re dovoljno dugaka)

#include <stdio.h>

int main(void) {
char rec[18];

printf("Upisite rec: "); scanf("%s", rec);

printf("a) rec: %s\n", rec);


printf("b) rec bez prvog znaka: %s\n", &rec[1]);
printf("c) treci znak: %c\n", rec[2]);

return 0;
}

58. /*Prikazivanje tablice ASCII kodova*/


#include<stdio.h>
void main()
{
char c; int i;
printf("\t\t Tablica ASCII kodova\n\n");
for(c=' ';c<' '+19;++c){
for(i=0;i<95;i+=19)
printf("%3d %c ",c+i,c+i);
putchar('\n');
}
}

59/*Napisati program kojim se ucitavaju znaci sve dok se ne unese # i onda daje izvestaj o broju
ucitanih praznina, novih linija i broju svih ostalih ucitanih karaktera.*/
#include <stdio.h>
void main()
{
char ch;
int praznina = 0, nl = 0,ostalo = 0;
while ((ch = getchar()) != '#')
{
if (ch == ' ')
praznina++;
else if (ch == '\n')
nl++;
else
ostalo++;
}
printf(" Broj praznina: %d\n Novih linija: %d\n Ostali karakteri: %d\n", praznina, nl, ostalo);
}

60. /*Program za odredjivanje duzine nizova karaktera*/


#include<stdio.h>
unsigned strlen(s)
char *s;

51
{
unsigned i;
for(i=0;*s!='\0';++s,++i);
return(i);
}
main()
{
char demo[]="Uvod u C jezik";
printf("Duzina niza demo je %d\n",strlen(demo));
}

61. /*Primer koji radi sa stringovima korienjem <string.h> zaglavlja*/

#include<stdio.h>
#include<string.h>

void main(){
char buffer[80];
int brojSlova;
char lozinka[80];
int provera;
char novi [ ]= "Student ";

printf("Uneti recenicu:\n");

/*scanf("%s", buffer);*/
/*Bolje je koristiti gets jer scanf uzima string sa tastature samo do prvog razmaka u recenici*/
gets(buffer);

/*Provera unetog stringa*/


printf("Uneta je recenica: %s\n", buffer);

/*Funkcija strlen daje duzinu stringa, odnosno broj karaktera u stringu*/


brojSlova=strlen(buffer);
printf("Broj slova u recenici je: %d\n", brojSlova);

/*Funkcija strlwr menja sva slova u zadatom stringu u mala slova*/


strlwr(buffer);
printf("Uneta je recenica: %s\n", buffer);

/*Funkcija strupr menja sva slova u zadatom stringu u velika slova*/


strupr(buffer);
printf("Uneta je recenica: %s\n", buffer);

/*Funkcija strcmp poredi dva stringa (drugi sa prvim argumentom)*/


printf("Uneti lozinku: ");
gets(lozinka);
provera=strcmp(buffer, lozinka);

if (provera==0) /*ili if(!provera)*/


printf("tacno uneta lozinka\n");
else
printf("pogresno uneta lozinka\n");

printf("Uneta je recenica: %s\n", buffer);

52
/*Funkcija strcat spaja dva stringa u jedan i pamti rezultat u prvom argumentu*/
strcat(novi, buffer);
printf("Dobijen je novi string: %s\n", novi);
}

62. /*Zadatak pokazuje vezu pointera i nizova karaktera (stringova) . Pokaziva sa inicijalizuje
adresom poetka niza (njegovim imenom), a zatim se pomeranjem za jedan u pokazivau pamti
ostatak niza, sve dok se ne doe do zadnjeg elementa u nizu karaktera.*/

#include<stdio.h>
#include<string.h>

void main(){
char niz[ ]= "Marko Markovic";
int i;

char *pniz;
pniz=niz;

printf("String je:\n");
for(i=0; i<(int)strlen(pniz); i++)
printf("%s\n", pniz+i);
}

63. /*Program za ilustraciju brojanja reci u nizu karaktera*/


#include<stdio.h>
unsigned wc(s)
char *s;
{
unsigned n=0;
while(*s)
{
while(*s==' '||*s=='\n'||*s=='\t')
++s;
if(*s)
{
++n;
while(*s!=' '&&s!='\n'&&*s!='\t'&&*s!='\0')
++s;
}
}
return(n);
}
main()
{
static char string[]="Ilustracija procesiranja nizova\t karaktera\n\t\n";
printf("Broj reci je %u\n",wc(string));
}

return l;
}

64./*Napisati program za odredjivanje broja velikih i malih slova u unetom tekstu.*/


#include <stdio.h>
void main()
{
int ch;

53
int uct = 0,lct = 0;
while ((ch = getchar()) != EOF)
if (isupper(ch))
uct++;
else if (islower(ch))
lct++;
printf("\n");
printf("velikih slova: %d\n", uct);
printf("malih slova: %d\n", lct);

65./*Napisati program za odredjivanje ukupnog broja karaktera u unetom tekstu.*/


#include <stdio.h>
int main(void)
{
int ch;
int ct = 0;

while ((ch = getchar()) != EOF)


ct++;
printf("\n");
printf("Uneto je %d karaktera\n", ct);
}

66./*Napisati program kojim se iz stringa s brie svaki znak koji odgovara bilo kom znaku stringa t.*/
#include <stdio.h>
#include <string.h>
void main()
{
char s[50], t[50];
int i,j;
gets(s);
gets(t);
for(i=j=0;s[i];i++)
if(!strchr(t,s[i]))
s[j++]=s[i];
s[j]='\0';
puts(s);
}

67./*Napisati program koji iz datog stringa s izbacuje sve komentare oblika /*...*/, s tim to u komentaru
nema komentara*/
#include <stdio.h>
#include <string.h>
void main()
{
char s[100], *p,*q;
gets(s);
while(p=strstr(s,"/*"))
{
q=strstr(s,"*/");
strcpy(p,q+2);
}
puts(s);
}

54
68./*Napisati program koji iz datog stringa s odreuje prosean broj slova u reima parne duine*/
#include <stdio.h>
void main()
{
char s[100];
int i,k=0,br=0;
float q=0;
gets(s);
for(i=0;s[i];i++)
if(s[i]!=' ') k++;
else
if(k>0)
{
if(k%2==0)
{
br++; q+=k;
}
k=0;
}
if(k>0)
if(k%2==0)
{
br++;
q+=k;
}
printf("Prosecan broj simbola u recima parne duzine je %f\n",q/br);
}

69. /*Napisti program za ucitavanje neuredjenog spiska imena prekog glavnog ulaza, po jedno ime iz
svakog reda, sve dok umesto prezimena i imena ne procita dve tacke sa znakom razmaka izmedju. Po
zavrsetku citanja imena treba urediti i potom ispisati na glavnom izlazu, po jedno ime u svakom redu*/

#include<stdio.h>
#include<string.h>
#define N 100
#define D 40
void main()
{
char ljudi[N][D+1];
int i, n=0;
/*Citanje neuredjenog niza imena*/
printf("Neuredjen niz prezimena i imena?\n\n");
do
gets(ljudi[n]);
while(strcmp(ljudi[n++],". .")!=0);
n--;
/*Uredjivanje niza imena*/
for(i=0; i<n-1;i++){
int j,m=i;
for(j=i+1;j<n;j++)
if(strcmp(ljudi[j],ljudi[m])<0)m=j;
if(m!=i){
char osoba[D+1];

55
strcpy(osoba , ljudi [i]);
strcpy(ljudi[i],ljudi[m]);
strcpy(ljudi[m],osoba );
}
}
/*Ispisivanje uredjenog niza imena*/
printf("\nUredjeni niz imena:\n\n");
for(i=0;i<n;puts(ljudi[i++]));
}

70. /*Program za konverziju niza ASCII cifara u celobrojnu vrednost*/


#include<stdio.h>
int isspace(c)
char c;
{
return(c==' '||c=='\t'||c=='\n');
}
int isdigit(c)
char c;
{
return(c>='0'&&c<='9');
}
int atoi(s)
char *s;
{
int value=0,sign=1;
char c;
if(*s=='-')
{
++s;
sign=-1;
}
else if(*s=='+')
++s;
while(isspace(*s))
++s;
while(isdigit(c=*s++))
value=10*value+c-'0';
return(sign*value);
}
void main()
{
char niz[81];
printf("Ukucajte broj:\n");
scanf("%s",niz);
printf("\"%s\"=%d\n",niz,atoi(niz));
}

71. /* Napiite funkciju koja kao argument prima jedan string i iz njega brie svako tree slovo.
Napiite i program koji pokazuje kako se funkcija upotrebljava.*/

#include <stdio.h>
#include <ctype.h>

void izbaci(char *s){


int i,j,br=0;
for(i=0, j=0 ; s[i] != '\0' ; i++){

56
if (! (isalpha(s[i]) && ++br % 3 == 0) )
s[j++] = s[i];
}
s[j] = '\0';
}

int main ( void) {


char s[] = "Ovo je niz iz kojeg treba izbaciti svako 3. slovo.";
izbaci(s);
printf("%s\n", s);
return 0;
}

72. /*Napiite funkciju koja kao argument prima jedan string i iz njega brie svako tree slovo.
Napiite i program koji pokazuje kako se funkcija upotrebljava.*/

Reenje 2: umesto indeksa i i j koristimo pomoni pokaziva

void izbaci(char *s){


char *p; int br=0;
p = s;
for(; *s ; s++){
if (! (isalpha(*s) && ++br % 3 == 0) ){
*p = *s;
p++;
}
}
*p = '\0';
}
73. /*Program koji ucitava 7 imena i prezimena studenata. Imena nisu duza od 15 karaktera, a
prez. 25. Zatim formira novi tekst koji je oblika: Ime Prezime: za svakog studenta. Potom
odredjuje koji od ovako novoformiranih tekstova je najduzi i stampa ga.*/

#include<stdio.h>
#include<string.h>
#define BR_ST 7
#define D_IME 15
#define D_PRZ 25
main(){
char ime[BR_ST][D_IME];
char prezime[BR_ST][D_PRZ];
char rez[BR_ST][D_IME+D_PRZ+2];
char Najduzi[D_IME+D_PRZ+2];

int i, Max;
int D[BR_ST];

for(i=0; i<BR_ST; i++){


printf("Uneti ime sledeceg studenta: ");
gets(ime[i]);
printf("Uneti prezime sledeceg studenta: ");
gets(prezime[i]);
strcpy(rez[i], ime[i]);
strcat(rez[i], " ");
strcat(rez[i], prezime[i]);
strcat(rez[i],":");
D[i]=strlen(rez[i]);

57
}
Max=0;
for(i=0;i<BR_ST;i++){
if(Max<D[i]){
Max=D[i];
strcpy(Najduzi, rez[i]);
}
}
printf("\nNajduzi tekst - kombinacija imena i prezimena je:%s\n ", Najduzi);
return 0;
}

74. /* Napiite funkciju int palindrom(char *s) koja vraa 1 ako je string s palindrom; inae treba vratiti
0. Funkcija treba biti case-insensitive (tj. ne sme praviti razliku izmeu velikih i malih slova) i mora
ignorisati sve znakove koji nisu slovo. Pri tome ne sme menjati string s. Npr. string Ana voli:
Milovana! treba prepoznati kao palindrom.*/

int palindrom(char *s){


int i=0,j;
for(j=0 ; s[j]!='\0'; j++);
while(i < j){
if (!isalpha(s[i])){
i++; continue;
}
if (!isalpha(s[j])){
j--; continue;
}
if (tolower(s[i]) != tolower(s[j]))
return 0;
else{
i++;j--;
}
}
return 1;
}

Dinamiki alocirani stringovi

char *string;
int len;
printf("Duzina stringa: ");
scanf("%d", &len);
string = (char*)malloc((len+1)*sizeof(char));
scanf("%s", string);

Ukoliko je string definisan kao pokaziva pre njegovog koritenja (scanf, printf) obavezno treba
alocirati memoriju za njega

Napomena:
char string[20] -> sizeof(string) je 20
char *string -> sizeof(string) je 4

75. Napiite funkciju koja kao argument uzima string, i iz njega brie sve samoglasnike. Dodatno,
napiite i program koji pokazuje kako se funkcija upotrebljava.

58
void brisi_samoglasnike(char s[]) {
int i, j = 0;
for (i = 0; s[i] != '\0'; i++) {
char c = tolower(s[i]);
if (!(c == 'a' || c == 'e' ||
c == 'i' ||
c == 'o' || c == 'u'))
s[j++] = s[i];
}
s[j] = '\0';
}

int main (void) {


char s[17];
printf("Upisite string: ");
scanf("%[^\n]", s);
brisi_samoglasnike(s);
printf("Rez: \"%s\"\n", s);

return 0;
}

59
STRUKTURE PODATAKA

Strukture su skupovi heterogenih elemenata (jedan elemenat je char, drugi je int itd.). U C jeziku
postoji mogunost grupisanja logiki povezanih promenljivih razliitog tipa u jednu celinu, strukturu.
Koristei kljunu re struct moemo definisati strukturu datum sa tri celobrojne komponente, koje
predstavljaju dan, mesec i godinu. Ovo se deklarie:

struct datum {
int dan;
int mesec;
int godina;
};
Struktura datum sadri tri elementa tipa int: dan, mesec i godina, koji se nazivaju lanovima
strukture. Kljuna re struct definie strukturu tako da promenljive mogu biti deklarisane kao tip struct
datum. Za selekciju lanova strukture koristi se operator .(taka), tako to se specificira ime promenljive,
operator taka i ime lana. Operator . ima najvii prioritet meu operatorima C jezika i istog je prioriteta
sa operatorom selekcije elementa vektora (uglaste zagrade). Selekcija lana strukture ima optu formu

ime_promenljive.ime_clana

Inicijalizacija strukture je slina inicijalizaciji vektora. Inicijalizacione vrednosti se navode


izmeu vitiasti zagrada razdvojene zarezom.

76. /*Program koji za za zadato tekue vreme odreuje naredno vreme.*/


#include<stdio.h>
void main()
{
struct vreme{
int sat;
int minut;
int sekund;
}tekuce_vreme,naredno_vreme;
printf("Unesite tekuce vreme?[cc:mm:ss]");
scanf("%d:%d:%d",&tekuce_vreme.sat,
&tekuce_vreme.minut,
&tekuce_vreme.sekund);
naredno_vreme=tekuce_vreme;
if(++naredno_vreme.sekund==60)
{
naredno_vreme.sekund=0;
if(++naredno_vreme.minut==60)
{
naredno_vreme.minut=0;
if(++naredno_vreme.sat==24)
naredno_vreme.sat=0;
}
}
printf("Naredno vreme je %02d:%02d:%02d\n", naredno_vreme.sat,
naredno_vreme.minut, naredno_vreme.sekund);
}

77. /*Napisati program za formiranje strukture student sa karakteristikama Ime, Prezime, broj
indeksa, srednja ocena. Za uneti broj studenata n, sortirati studente prema srednjoj oceni i ispisati
na ekranu*/
#include<stdio.h>
typedef struct student{
char Ime[20],Prezime[20];
int broj_indeksa;
60
float srednja_ocena;
};
void razmeni(struct student *a, struct student *b)
{
struct student pom;
pom=*a;
*a=*b;
*b=pom;
}
void sort(struct student STF[], int n)
{
int i, j;
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
if(STF[i].srednja_ocena<STF[j].srednja_ocena)
razmeni(&STF[i],&STF[j]);
}

void main()
{
int n;
int i;
struct student STF[100];
printf("Unesite broj studenata: \n");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("Unesi ime: \n");
scanf("%s",STF[i].Ime);
printf("Unesi prezime: \n");
scanf("%s",STF[i].Prezime);
printf("Unesi broj indeksa: \n");
scanf("%d",&STF[i].broj_indeksa);
printf("Unesi srednju ocenu: \n");
scanf("%f",&STF[i].srednja_ocena);
}
sort(STF,n);
for(i=0;i<n;i++)
{
printf("student broj %d\n",i+1);
printf("Ime:%s\n",STF[i].Ime);
printf("Prezime:%s\n",STF[i].Prezime);
printf("Broj indeksa: %d\n",STF[i].broj_indeksa);
printf("Srednja ocena: %5.2f\n\n\n",STF[i].srednja_ocena);
}
}

78. /*Program za prevodjenje srpskih reci na engleske (srpsko-engleski recnik)*/


#include<stdio.h>
struct element {
char srpski[20];
char engleski[50];
};
int strcmp(char*s1,char*s2)
{
while(*s1==*s2)
{
if(!*s1)
61
return(0);
++s1;
++s2;
}
return(*s1-*s2);
}
int bin_search(struct element recnik[],char*ukaz_niz,unsigned n)
{
int low=0;
int mid,high=n-1;
int result;
while(low<=high)
{
mid=(low+high)/2;
result=strcmp(ukaz_niz,recnik[mid].srpski);
if(result<0)
high=mid-1;
else if(result>0)
low=mid+1;
else
return(mid+1);
}
return(0);
}
void main(){
static struct element recnik[100]=
{{"baba","old woman,grandmother"},
{"babica","widwife"},
{"badem","almond"},
{"bager","dredge"},
{"bajka","fairytale"},
{"bakalin","grocer"}};
unsigned j;
int n=10;
char rec[20];
printf("Ukucajte rec:\n");
scanf("%s",rec);
j=bin_search(recnik,rec,6);
if(!j)
printf("Zalim, rec %s nije u recniku\n",rec);
else
printf("%s\n",recnik[j-1].engleski);
}
79./* Napisati program koji pravi rang listu studenata koji su polagali prijemni ispit. Sa
standardnog ulaza se unose sledeci podaci: ime studenta, cetiri ocene iz prethodnog skolovanja i
broj bodova na prijemnom ispitu.*/

#include<stdio.h>
#define DIM 10
typedef struct student{
char ime[20];
int brBodova;/*Ukupna suma bodova svakog studenta: ocene + prijemni*/
};
void razmeni(struct student *a, struct student *b){
struct student tmp;
tmp=*a;
*a=*b;
*b=tmp;
62
}
void sort(struct student niz[], int n){
int i, j;
for(i=0; i<n-1; i++)
for(j=i; j<n; j++)
if(niz[i].brBodova<niz[j].brBodova)
razmeni(&niz[i], &niz[j]);
}
void main(){
struct student nizStudenata[DIM];
int n, i, j;
static int ocene[5];
int bodovi;
static int sumaOcena[DIM];/*Suma ocena iz prethodnog skolovanja*/
printf("Uneti broj studenta koji je polagao prijemni: ");
scanf("%d", &n);
for(i=0; i<n; i++){
printf("Uneti ime studenta: ");
scanf("%s", &nizStudenata[i].ime);
printf("Uneti cetiri ocene iz prethodnog skolovanja: ");
for(j=0; j<4; j++){
scanf("%d", &ocene[j]);
sumaOcena[i]+=ocene[j];
//printf("Suma ocena je: %d\n", sumaOcena[i]);
}
printf("Uneti broj bodova sa prijemnog: ");
scanf("%d", &bodovi);

nizStudenata[i].brBodova=sumaOcena[i]+bodovi;
printf("Ukupna suma bodova svakog studenta: ocene + prijemni je: %d\n",
nizStudenata[i].brBodova);
}
sort(nizStudenata, n);
printf("Rang lista studenata je:\n\n");
for(i=0; i<n; i++)
printf("%s\t%d\n", nizStudenata[i].ime, nizStudenata[i].brBodova);

80. /*Definisati strukturu GRAD sa podacima clanovima: ime, broj_stanovnika,


prosecan_dohodak_radnika. Napisati program kojim se unose podaci o gradovima u Srbiji i
stampati na standardnom izlazu ime grada sa najvecim brojem stanovnika. Izracunati ukupan
dohodak svih unetih gradova.*/

#include<stdio.h>
#define DIM 10
typedef struct grad{
char ime[20];
int brStan;
float dohodak;
};
void main(){
struct grad nizGradova[DIM];
int i, n;
float ukupanDohodak=0.0;
int najveci;
int indeksNajvecegGrada;
printf("Uneti koliko gradova ima: ");
63
scanf("%d", &n);
for(i=0; i<n; i++){
printf("Uneti ime grada: ");
scanf("%s", &nizGradova[i].ime);
printf("Uneti broj stnovnika: ");
scanf("%d", &nizGradova[i].brStan);
printf("Uneti dohodak: ");
scanf("%f", &nizGradova[i].dohodak);
ukupanDohodak+=nizGradova[i].dohodak;
}
printf("Ukupan dohodak svih gradova je: %6.2f\n", ukupanDohodak);
najveci=nizGradova[0].brStan;
indeksNajvecegGrada=0;
for(i=0; i<n; i++){
if(nizGradova[i].brStan>najveci){
najveci=nizGradova[i].brStan;
indeksNajvecegGrada=i;
}
}
printf("Grad sa najvise stanovnika je %s\n", nizGradova[indeksNajvecegGrada].ime);
}

81. /*Napisati program za formiranje strukture podataka telefonski_imenik sa poljima: prezime,


broj i adresa. Napisati program za sortiranje imenika prema prezimenu pretplatnika.*/
#include<stdio.h>
#define DIM 10
typedef struct telefonski_imenik{
char prezime[20];
char broj[10];
char adresa[20];
};
void razmeni(struct telefonski_imenik *a, struct telefonski_imenik *b){
struct telefonski_imenik tmp;
tmp=*a;
*a=*b;
*b=tmp;
}
void sort(struct telefonski_imenik niz[], int n){
int i, j;
for(i=0; i<n-1; i++)
for(j=i; j<n; j++)
if(niz[i].prezime<niz[j].prezime)
razmeni(&niz[i], &niz[j]);
}
void main(){
struct telefonski_imenik nizImenik[DIM];
int n, i;
printf("Uneti broj telefonskih pretplatnika: ");
scanf("%d", &n);
for(i=0; i<n; i++){
printf("Uneti prezime pretplatnika: ");
scanf("%s", &nizImenik[i].prezime);
printf("Uneti broj telefona pretplatnika: ");
scanf("%s", &nizImenik[i].broj);
printf("Uneti adresu pretplatnika: ");
scanf("%s", &nizImenik[i].adresa);;
}
sort(nizImenik, n);
64
printf("\nTelefonski imenik sortiran po prezimenu pretplatnika je:\n\n");
for(i=0; i<n; i++)
printf("%s\t%s\t%s\n", nizImenik[i].prezime, nizImenik[i].broj, nizImenik[i].adresa);

RAD SA DATOTEKAMA

Datotekama se pristupa korienjem pokazatelja na strukturu FILE, koja je definisana u


include datoteci stdio.h. Datoteka stdio.h se ukljuuje u program iskazom #include. U stdio.h
definisane su i konstante EOF i NULL. Konstanta EOF oznaava kraj datoteka i najee ima
vrednost -1. Konstanta NULL ima vrednost 0, i vraa se kao rezultat nekih funkcija za
upravljanje datotekama u sluaju neuspenog izvravanja funkcija.
fopen vraa pokazatelj na strukturu FILE, koji se dodeljuje promenljivoj in_file istog
tipa. U sluaju neuspenog otvaranja fopen, vraa vrednost NULL. Iz tog razloga neophodno je
ispitati vraenu vrednost, odnosno, dodati iskaz

if(in_file==NULL)
printf(Datoteka file1 ne moze biti otvorena\n);
Da bi se izvrila neka operacija datoteka mora biti otvorena, pozivanjem odgovarajue
funkcije i specificiranjem imena datoteke. Prilikom otvaranja datoteke, mora se specificirati tip
eljene ulalzno/izlazne operacije. Npr. ako se eli proitati sadraj datoteke, specificira se reim
itanja "r"(eng. read mode); ako se neki sadraj upisuje u datoteku, specificira se reim upisa "w"
(eng. write mode); ako se eli dodati neki sadraj, specificira se reim dodavanja "a" (eng.
append mode). Da bi se aurirao sadraj datoteke (naizmenino itanje i pisanje), prethodnim
oznakama se dodaje znak +, nezavisno koji je osnovni reim rada. Pri radu sa binarnim
datotekama prethodnim oznakama se dodaje i slovo b.
Iza svakog od ovih formata moe se dodati ili b (za binarne datoteke) ili t za tekstualne
datoteke. Ako se ne navede nita, podrazumijeva se da se radi o tekstualnim datotekama.

Zatvaranje datoteke vri se funkcijom fclose ija je deklaracija:


int fclose(FILE *dat);

dat je pokaziva datoteke koji je pridruen datoteci koja se zatvara. Vrednost funkcije je nula u
sluaju uspeha, a smibolika konstanta EOF u sluaju otkrivanja greke.
Funkcija koja ita iz datoteke dat najvie br podataka veliine vel bajtova u memoriju
poev od adrese niz:
int fread(void *niz, int vel, int br, FILE *dat);

Primer za itanje niza od najvie n_max celobrojnih podataka iz datoteke podaci:


n=fread(vektor, sizeof(int), n_max, podaci);
int fwrite(const void *niz, int vel, int br, FILE *dat);
Funkcije za tampanje i unos podataka:
fprintf-za tampanje podataka u datoteci (fajlu)
sprintf-za tampanje znakovnog niza
fscanf-za unos podataka u datoteku
sscanf-za unos znakovnog niza.
Funkcija getc() uitava jedan karakter iz specificirane datoteke. Ova funkcija je vrlo
slina ve opisanoj funkciji getchar, s tom razlikom to se uitavanje ne obavlja sa terminala
nego iz datoteke. getc vraa vrednost EOF, ako je dosegnut kraj datoteke.
Funkcija putc upusuje karakter u specificiranu datoteku. Zaglavlje funkcije je
int putc(c,file_pointer)
char c;

65
FILE*file_pointer;
Na pr. pozivom putc(z,in_file); u datoteku in_file upisujemo karakter z.
Pozicioniranje na mesto u datoteci dat ija je udaljenost pomeraj bajtova od oznaene
reperne take data je funkcijom:
int fseek(FILE*dat, long pomeraj, int reper);
Mogue reperne take obeleavaju se sibmolikim konstantama SEEK_SET (poetak datoteke),
SEEK_CUR (trenutna pozicija u datoteci) ili SEEK_END (kraj datoteke). Sledee itanje ili
pisanje vrie se poevi od ovako odabrane pozicije u datoteci. Funkcija za pozicioniranje na
poetak datoteke dat je:
void rewind(FILE *dat);

82. /*Odrediti broj linija u tekstualnom fajlu sa imenom knjiga.txt.*/

#include<stdio.h>
void main()
{
int k=0;
FILE *fp;
char s[256];
if((fp=fopen("knjiga.txt","r"))==NULL)
{
perror("Greska");
return;
}
while(fgets(s,256,fp)!=NULL)k++;
printf("Fajl ima %d linija\n",k);
fclose(fp);
}
83. /*Napisati program kojim se sadraj fajla test.dat formiran od velikih slova alfabeta ifriran alje u fajl sifra.dat. Znak se ifrira tako to se
zamenjuje sledeim ASCII znakom, a znak Z zamenjuje sa A.*/

#include<stdio.h>
void main()
{
int c;
FILE *inf,*outf;
inf=fopen("test.dat","r");
outf=fopen("sifra.dat","w");
while((c=fgetc(inf))!=EOF)
{
if('A'<=c&&c<'Z')
c++;
else c='A';
putc(c,outf);
}
fclose(inf);
fclose(outf);
}

84. /*U tekstualnom fajlu odrediti najduu liniju. Ako ima vie linija najvee duine odrediti prvu meu njima.*/

#include<stdio.h>
#include<string.h>
void main()
{
66
unsigned k=0,maxl;
char s[256],maxs[256];
FILE *fp;
if((fp=fopen("test.txt","r"))==NULL)
{
printf("Greska\n ");
return;
}
maxl=0;
while(fgets(s,256,fp)!=NULL)
if(strlen(s)>maxl)
{
maxl=strlen(s);
strcpy(maxs,s);
}
printf("Najduza linija\n%s\n ima duzinu %d\n",maxs,maxl);
fclose(fp);
}

85. /*Napisati program koji poredi dva fajla i ispisuje prvu liniju u kojoj se razlikuju.*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAXLINE 100
void main()
{
FILE *fp1;
FILE *fp2;
void filecomp(FILE *fp1, FILE *fp2);
if((fp1=fopen("prvi.txt","r"))==NULL)
{
perror("Ne moze se otvoriti prvi.txt");
return;
}
if((fp2=fopen("drugi.txt","r"))==NULL)
{
perror("Ne moze se otvoriti drugi.txt");
return;
}
filecomp(fp1,fp2);
fclose(fp1);
fclose(fp2);
}
void filecomp(FILE *fp1,FILE *fp2)
{
char line1[MAXLINE], line2[MAXLINE];
char *lp1,*lp2;
do
{
lp1=fgets(line1, MAXLINE, fp1);
lp2=fgets(line2, MAXLINE, fp2);
if(lp1==line1&&lp2==line2)
{
67
if(strcmp(line1,line2)!=0)
{
printf("Prva razlika je u liniji\n%s\n",line1);
lp1=lp2=NULL;
}
}
else
if(lp1!=line1&&lp2==line2)
printf("Kraj prvog fajla u liniji \n%s\n",line2);
else
if(lp1==line1&&lp2!=line2)
printf("Kraj drugog fajla u liniji \n%s\n",line1);
}
while(lp1==line1&&lp2==line2);
}

86./*Napisati program za uitavanje datoteke pod imenom ulaz.dat i formiranje datoteke sa nazivom izlaz.dat koja sadri samo one redove ulazne
datoteke ulaz.dat u kojima se nalazi re fakultet.*/

#include<stdio.h>
#include<string.h>
void main()
{
FILE *ulaz;
FILE *izlaz;
char buffer[80];
char trazenaRec[]="fakultet";
if((ulaz=fopen("ulaz.dat","r"))==NULL)
printf("Datoteka ulaz.dat nije otvorena.");
if((izlaz=fopen("izlaz.dat","w"))==NULL)
printf("Datoteka izlaz.dat nije otvorena.");
while(!feof(ulaz)){
fgets(buffer,80,ulaz);
if(strstr(buffer,trazenaRec)!=NULL){
printf("%s",buffer); /*stamanje na ekranu*/
fprintf(izlaz,"%s",buffer);
}
}
fclose(ulaz);
fclose(izlaz);
}

87. /*Napisati program koji cita podatke iz datoteke ULAZ.TXT (ime studenta, broj bodova na
prijemnom ispitu), broji sve studente koji imaju broj bodova veci od proseka i upisuje podatke o
takvim studentima u datoteku IZLAZ.TXT.*/

#include<stdio.h>
#define DIM 10
typedef struct student{
char ime[20];
int brBodova;
};
int main(){
struct student nizStudenata[DIM];
int i;

68
int brojStudenata=0;
int suma=0;
float prosek;
FILE *ulaz;
FILE *izlaz;
ulaz=fopen("ulaz.txt", "r");
if(ulaz==NULL){
printf("Ulazna datoteka nije otvorena!\n");
return 1;
}
izlaz=fopen("izlaz.txt", "w");
if(izlaz==NULL){
printf("Izlazna datoteka nije kreirana!\n");
return 1;
}
while(!feof(ulaz)){
fscanf(ulaz, "%s%d", &nizStudenata[brojStudenata].ime,
&nizStudenata[brojStudenata].brBodova);
suma+=nizStudenata[brojStudenata].brBodova;
brojStudenata++;
}
prosek=(float)suma/brojStudenata;
for(i=0; i<brojStudenata; i++)
if(nizStudenata[i].brBodova>prosek)
fprintf(izlaz, "%s\t%d\n", nizStudenata[i].ime, nizStudenata[i].brBodova);
fclose(ulaz);
fclose(izlaz);
return 0;
}

88. /*Napisati program za nalazenje i stampanje na ekranu zbira ASCII kodova svih znakova
zadate datoteke pod imenom ULAZ.TXT*/

#include<stdio.h>
#include<string.h>
int main(){
FILE *in;
int ascii;
int suma=0;
in=fopen("ulaz.txt", "r");
if(in==NULL){
printf("Ulazni fajl nije otvoren!");
return 1;
}
while(!feof(in)){
ascii=fgetc(in);
suma+=ascii;
printf("%c=\t%d\n",ascii, ascii);
//putc(fgetc(in), stdout);
}
printf("Suma svih znakova je: %d\n",suma);
fclose(in);
return 0;
}
89. /*U datoteci IMENIK.TXT nalaze se sledeci podaci: ime, prezime i broj telefona telefonskog
pretplatnika. Napisati program koji vrsi sortiranje imenika prema prezimenu pretplatnika i za
zadato prezime prikazuje telefonski broj pretplatnika na standardnom izlazu.*/

69
#include<stdio.h>
#include<string.h>
#define DIM 10
typedef struct telefonski_imenik{
char ime[10];
char prezime[20];
char broj[10];
};
void razmeni(struct telefonski_imenik *a, struct telefonski_imenik *b){
struct telefonski_imenik tmp;
tmp=*a;
*a=*b;
*b=tmp;
}
void sort(struct telefonski_imenik niz[], int n){
int i, j;
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(niz[i].prezime<niz[j].prezime)
razmeni(&niz[i], &niz[j]);
}
int main(){
struct telefonski_imenik nizImenik[DIM];
int n, i;
FILE *in;
char trazi[20];
in=fopen("imenik.txt", "r");
if(in==NULL){
printf("Ulazni fajl nije otvoren!");
return 1;
}
i=0;
while(!feof(in)){
fscanf(in, "%s%s%s", &nizImenik[i].ime, &nizImenik[i].prezime, &nizImenik[i].broj);
i++;
}
fflush(in);
n=i+1;
sort(nizImenik, n);
printf("\nTelefonski imenik sortiran po prezimenu pretplatnika je:\n\n");
for(i=0; i<n; i++)
printf("%s\t%s\t%s\n", nizImenik[i].prezime, nizImenik[i].ime, nizImenik[i].broj);
printf("Ukupan broj telefonskih pretplatnika je: %d\n",n);
printf("Zadati prezime pretplatnika: ");
scanf("%s", &trazi);
for(i=0; i<n; i++){
if(strcmp(nizImenik[i].prezime,trazi)==0){
printf("Broj telefoma trazenog pretplatnika je:\n");
printf("%s\t%s\t%s\n", nizImenik[i].prezime, nizImenik[i].ime,
nizImenik[i].broj);
}
}
fclose(in);
return 0;
}

90. /*Datoteka sadrzi proizvoljan broj tacaka u ravni predstavljenih (x, y) koordinatama. Napisati
program koji za ucitanu tacku odredjuje minimalno rastojanje od tacaka u navedenoj datoteci.*/
70
#include<stdio.h>
#include<math.h>
int main(){
FILE *in;
double rastojanje;
int x0, y0, x, y;
int brojacTacaka=0;
double minimalnoRastojanje;
int i;
double nizRastojanja[100];
in=fopen("tacke.txt", "r");
if(!in){
printf("Ulazna datoteka ne postoji!\n");
return 1;
}
printf("Uneti x i y koordinatu referentne tacke: ");
scanf("%d%d", &x0, &y0);
while(!feof(in)){
fscanf(in, "%d%d", &x, &y);
if(x0<x && y0<y)
rastojanje=sqrt(pow(x-x0, 2) + pow(y-y0, 2));
else if(x0>x && y0>y)
rastojanje=sqrt(pow(x0-x, 2) + pow(y0-y, 2));
else if(x0<x && y0>y)
rastojanje=sqrt(pow(x-x0, 2) + pow(y0-y, 2));
else if(x0>x && y0<y)
rastojanje=sqrt(pow(x0-x, 2) + pow(y-y0, 2));

nizRastojanja[brojacTacaka]=rastojanje;/*Rastojanje svake tacke od referentne pamtimo


u nizu*/
printf("Rastojanje od %d tacke je: %8.4le\n", brojacTacaka+1,
nizRastojanja[brojacTacaka]);
brojacTacaka++;
}
minimalnoRastojanje=nizRastojanja[0];/*Pretpostavimo da je minimalno rastojanje izmedju prve
tacke*/
for(i=0; i<brojacTacaka; i++){
if(nizRastojanja[i]<minimalnoRastojanje)
minimalnoRastojanje=nizRastojanja[i];
}
printf("Rastojanje najblize tacke od referentne je: %8.4le\n", minimalnoRastojanje);
fclose(in);
return 0;
}
91. /*Dodavanje novih zapisa u datoteku o stedisama*/ stednovi.c
#include<stdio.h>
typedef struct{char prezime[16], licno_ime[16];} Ime_i_prezime;
typedef struct{Ime_i_prezime ime; double stanje;} Stedisa;
void main(){
FILE *stednja;
Stedisa stedisa;
Stedisa prazno={0};
unsigned int sifra;
unsigned int veldat;
/*Otvaranje datoteka o stedisama*/

71
if ((stednja=fopen("stedise.dat","r+b"))==NULL)
/*Datoteka postoji, citanje broja zapisa u datoteci*/
fread(&veldat, sizeof veldat, 1, stednja);
else{
/*Datoteka ne postoji, stvaranje prezne datoteke*/
stednja=fopen("stedise.dat","w+b"); veldat=0;
fwrite(&veldat, sizeof veldat, 1, stednja);
}
/*Dodavanje zapisa o novim stedisama*/
while(1){
/*Citanje podataka o stedisi*/
printf("\nSifra stedise? "); scanf("%d",&sifra);
if(sifra==0) break; /*Zavrsetak programa*/
printf("Prezime stedise? ");
scanf("%s", stedisa.ime.prezime);
printf("Licno ime stedise? ");
scanf("%s", stedisa.ime.licno_ime);
stedisa.stanje=0;
/*Priprema za upisivanje podataka u datoteku*/
if(sifra>veldat){
/*Novi zapis je iza kraja datoteka, promena velicine datoteke*/
fseek(stednja, 0L, SEEK_END);
while(++veldat<sifra) fwrite(&prazno, sizeof prazno, 1, stednja);
veldat=sifra;
}else
/*Novi zapis je pre kraja datoteke, nalazenje njegovog mesta*/
fseek(stednja, (sizeof veldat)+(long) (sifra-1)*(sizeof stedisa),
SEEK_SET);
/*Upisivanje podataka u datoteku*/
fwrite(&stedisa, sizeof stedisa, 1, stednja);
rewind(stednja); fwrite(&veldat, sizeof veldat, 1, stednja);
}
}
92. /*Ispisivanje sadrzaja datoteke o stedisama*/ stedpisi.c

#include<stdio.h>
#include"stedisa.h"
typedef struct{char prezime[16], licno_ime[16];} Ime_i_prezime;
typedef struct{Ime_i_prezime ime; double stanje;} Stedisa;
void main(){
FILE*stednja;
Stedisa stedisa;
unsigned int sifra;
unsigned int veldat;
unsigned int i, k;
/*Otvaranje datoteke o stedisama*/
if((stednja=fopen("stedise.dat","r+b"))==NULL) exit(1);
fread(&veldat, sizeof veldat, 1, stednja);
/*Ispisivanje podataka o pojedinim stedisama*/
for(sifra=1;sifra<=veldat;sifra++){
/*Citanje sledeceg zapisa iz datoteke*/
printf("%3d", sifra);
fread(&stedisa, sizeof stedisa, 1, stednja);
72
if(stedisa.ime.prezime[0]!='\0'){
/*Prikaz podataka o postojecem stedisi*/
k=printf("%s%s", stedisa.ime.prezime, stedisa.ime.licno_ime);
for(i=k; i<34; i++) putchar(' ');
printf("%8.2f\n",stedisa.stanje);
}else
/*Prazan zapis, stedisa ne postoji*/
printf("***Ne postoji stedisa sa ovom sifrom***\n");
}
}
93. /*Azuriranje zapisa u datoteci o stedisama*/ stedazur.c

#include<stdio.h>
typedef struct{char prezime[16], licno_ime[16];} Ime_i_prezime;
typedef struct{Ime_i_prezime ime; double stanje;} Stedisa;
void main(){
FILE*stednja;
Stedisa stedisa;
unsigned int sifra;
unsigned int veldat;
double promena;
/*Otvaranje datoteke o stedisama*/
if((stednja=fopen ("stedise.dat", "r+b"))==NULL) exit(1);
fread(&veldat, sizeof veldat, 1, stednja);
/*Azuriranje stanja uloga pojedinih stedisa*/
while(1){
/*Citanje sifre sledeceg stedise za obradu*/
printf("\nSifra stedise?", " ");
scanf("%d",&sifra);
if(sifra==0)break;
if(sifra<=veldat){
/*Citanje zatecenih podataka o stedisi iz datoteke*/
fseek(stednja, (sizeof veldat)+(long)(sifra-1)*(sizeof stedisa),
SEEK_SET);
fread(&stedisa, sizeof stedisa, 1, stednja);
if(stedisa.ime.prezime[0]){
/*Prikazivanje zatecenih podataka o stedisi*/
printf("Stedisa=%s %s\n",stedisa.ime.prezime,
stedisa.ime.licno_ime);
printf("Staro stanje=%8.2f\n", stedisa.stanje);
/*Citanje promene stanja uloga*/
printf("Promena stanja? ");
scanf("%lf",&promena);
stedisa.stanje+=promena;
/*Upisivanje novog sadrzaja zapisa o stedisi u datoteku*/
fseek(stednja, -(long) (sizeof stedisa), SEEK_CUR);
fwrite(&stedisa, sizeof stedisa, 1, stednja);
}else
printf("***Ne postoji stedisa sa tom sifrom***\n");
}else
printf("***Ne postoji stedisa sa tom sifrom***\n");
}
}
73
74
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

VEBA 1 - Okruenje Microsoft Visual Studio 2013

Microsoft Visual Studio 2013 predstavlja integrisano okruenje za razvoj softvera. Sastoji se od sledeih
celina:
Visual C++,
Visual Basic,
Visual C#
MSDN Library.
Druge
Visual studio C++ je okruenje koje omoguava razvoj i pisanje programa u programskom jeziku C++,
a samim tim i u programskom jeziku C.

Pokretanje Visual Studio 2013 okruenja


Okruenje Visual Studio 2013 se moe otvoriti klikom na taster Start i izborom stavke Microsoft Visual
Studio 2013 iz liste programa. Nakon startovanja otvorie se osnovi prozor okruenja Visual Studio
2013 koji je prikazan na slici 1.

Slika 1. Izgled osnovnog prozora po otvaranju Visual C++-a

Kreiranje projekta za konzolnu aplikaciju


Da bi se napisao, kompilirao, izvrio i eventualno debagirao C program, u Visual Studiju je
potrebno kreirati projekat koji sadri odgovarajue datoteke sa izvornim kodom programa. Za
potrebe pisanja programa u C-u bie korien najjednostavniji tip projekta koji obezbeuje
pravljenje konzolnih aplikacija. Konzolne aplikacije su programi koji se izvravaju u komandnom
(DOS) prozoru i koriste standardni ulaz i izlaz.
1
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I
Kreiranje projekta se vri startovanjem stavke iz menija File/New, izborom kartice Project i stavke
Visual C++ i zatim Win32 Console Application (slika 2).

Slika 2. Izgled prozora za kreiranje novog projekta

Pri kreiranju projekta potrebno je uneti naziv projekta u polje Project name, i eventualno promeniti
direktorijum na disku gde e projekat biti kreiran (polje Location). Po unosu naziva projekta aktivirae
se taster OK. Klikom na ovaj taster pojavie se prozor za izbor tipa konzolnog projekata koji se eli
kreirati (slika 4). U ovom sluaju ne treba nita menjati jer je ve odabrana opcija za kreiranje praznog
projekta (An empty project). Da bi se kreirao projekat potrebno je kliknuti na taster Finish. Ukoliko
elite moete klikunit i na dugme next. U tom sluaju e Vam biti prikazan sledei prozor sa
dodatnim popcijama.

Slika 3. Izgled prozora za izbor tipa konzolnog projekta koji e biti kreiran

Kreiranje i dodavanje datoteka za izvorni kod programa


Nakon kreiranja praznog projekta za konzolnu aplikaciju potrebno je kreirati i dodati u projekat
datoteke koje e se koristiti za unos izvornog koda programa. U Vs2013 obino je za Vas ve
kreiran fajl koji se zove isto kao va projekat. Ukoliko nije potrebno je kreirati i dodati datoteku na
sledei nain. Pozivate stavku iz menija File/New File i stavke Visual C++. Zatim moete izabrati

2
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I
izmeu C++ File ili Header File (slika 4). Potrebno je uneti eljeni naziv datoteke u polje File
name i kliknuti na taster OK.

Slika 4. Izgled prozora za kreiranje i dodavanje datoteka za izvorni kod programa

Po kreiranju i dodavanju nove datoteke u projekat potrebno je uneti odgovarajui sadraj (ukucati
program). Za to se koristi centralni deo glavnog prozora (slika 5). Visual Studio poseduje neke napredne
opcije za prikaz izvornog koda programa kao to su bojenje kljunih rei i komentara.

Slika 5. Deo za unos i prikaz sadraja datoteka sa izvornim kodom

Prikaz i otvaranje datoteka i funkcija koje projekat sadri


Za prikaz datoteka koje su ukljuene u projekat koristi se panel sa leve strane osnovnog prozora
Visual C++-a. Ovaj panel sadri dva kartice ClassView i Solution Explorer. Kartica Solution
Explorer omoguava pregled i otvaranje datoteka koje su dodate u projekat. Datoteke se grupisane
po tipu koji je odreen eksenzijama (Source Files - *.cpp datoteke, Header Files - *.h datoteke).
Duplim klikom na naziv datoteke, sadraj odgovarajue datoteke e biti prikazan u centralnom delu
prozora Visual C++-a. Naziv datoteke koja je trenutno otvorena prikazan je u naslovnoj liniji
glavnog prozora.

3
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I
Kartica ClassView je izvorno namenjena za prikaz informacija o klasama definisanim u C++
programu. Kako programski jezik C ne podrava rad sa klasama u prikazu vezanom za ovu karticu
pobrojane su samo funkcije definisane u datotekama koje projekat sadri. Duplim klikom na naziv
funkcije otvara se odgovarajua datoteka i postavlja se na poetak odgovarajue funkcije. Na slici 6
ilustrovani su FileView i ClassView prikazi.

Slika 6. Prikaz datoteka i funkcija koje projekat sadri

Kompiliranje programa i izvetaj o grekama


Nakon unosa koda programa u odgovarajue datoteke mogue je izvriti kompiliranje, povezivanje
i izvravanje programa. U ovu svrhu se koriste stavke iz menija Build ili iz odgovarajue preice sa
alatima (vidi sliku 7).

Slika 7. Alati za kompiliranje programa


Najjednostavniji nain za iniciranje procesa kompiliranja svih datoteka sa izvornim kodom,
kreiranje izvrne (EXE) datoteke programa i njeno startovanje je korienjem stavke
Build/Execute..., kombinacije tastera Ctrl+F5 sa tastature ili odgovarajue preice (ikonica "").
Ukoliko program nije prethodno preveden ili je izmenjen od vremena kada je poslednji put
preveden, pojavie se prozor sa pitanjem da li treba izvriti prevoenje (kompajliranje) programa. U
oba sluaja potrebno je kliknuti na dugme Yes nakon ega e uslediti kompiliranje i povezivanje
(linkovanje) izvrnog programa. Ukoliko je program uspeno preveden automatski e se izvriti
njegovo startovanje, u suprotnom u donjem delu osnovnog prozora e biti prikazan izvetaj o
otkrivenim grekama (slika 8). Za svaku otkrivenu greku ili upozorenje pored koda i opisa,
navedena je datoteka i linija koda u kojoj je greka naena. na liniju sa opisom greke u ovom
izvetaju automatski se otvara odgovarajua datoteka i vri pozicioniranje kursora na problematinu
liniju.

4
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

Slika 8. Prikaz izvetaja o grekama i upozorenjima


Nakon ispravljanja greki potrebno je ponovo izvriti startovanje procesa prevoenja i izvrenja
programa. Na slici 9 prikazan je prozor u kome se izvrava program. Nakon zavretka izvrenja
programa bie ispisan tekst "Press any key to continue". Pritiskom na neki taster prozor u kome se
program izvravao e biti zatvoren.

Slika 9. Izgled prozora u kome se izvrava program

Prekompajlirani hederi
Prekompajlirani hederi predstavljaju C i C++ heder fajlove koji se pre kompajliranja pripreme i
prebace u intermediate formu koju kompajler moe bre da kompajliura. Ova forma se naziva jo i
prekompajlirani heder.Korienje ovakvih hedera moe skratiti vreme kompajliranja, naroito kada
se primeni na velike heder fajlove. Problem kompajliranja velikog broja ukljuenih fajlova postoji i
kod drugih programskih jezika i svaki od njih ga reava na neki svoj nain. Demonstrirajmo
primerom kako se to reava u C++ jeziku. Uzmimo za primer dprojekat koji ima dodata dva fajla
heder fajl header.h i sors fajl source.cpp:
//header.hpp
...

//source.cpp
#include "header.hpp"
...
U sluaju da je opcija za prekompajlirane hedere ukljuena, kompajler e generisati prekompajlirani
heder fajl header.pch. Kada sledei put budete kompajlirali fajlove, ukoliko se vreme zadnje
promene fajla header.h nije promenilo, raunar e preskoiti kompajliranje i iskoristiti ve postojei
header.pch fajl. U suprotnom novi fajl heaader.pch e biti kreiran, a stari obrisan.

Prilikom korienja visual studia 2013 postoji fajl stdafx.h koji predstavlja prekompajlirani heder za sve one
biblioteke koje elite da ukljuite u va program, a koje se retko menjaju. To znai da sve include direktive
treba pisati u vom fajlu.

5
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I
Debagiranje programa
Pored sintaksnih greaka koje se otkrivaju u toku prevoenja, program moe da sadri i logike
greke koje spreavaju da se izvrava na nain koji je programer predvideo. Ovakve greke se
nazivaju bug-ovi, a proces njihovog uklanjanja debugging. Proces debagiranja podrazumeva
postavljanje prekidnih taaka u kojima e se izvrenje programa privremeno prekinuti u cilju
oitavanja vrednosti pojedinih promenljivih i sl. Postavljanje (ili uklanjanje) prekidnih taaka vri
se pozicioniranjem kursora na odgovarajuu liniju i klikom na dugme u obliku ake (vidi sliku 11).
Druga varijanta za dodavanje (ili uklanjanje) prekidne take je desni klik na odgovarajuu
programsku liniju i izbor stavke Insert/Remove Brakepoint iz padajueg menija. Za startovanje
izvrenja programa u ovom modu koristi se stavka iz menija Build/Start Debug/Go, taster F5 ili
odgovarajua preica iz linije sa alatima (vidi sliku 10).

Slika 10. Alati za debagiranje programa


Pri debagiranju, program e se izvravati normalno sve dok se ne doe do neke od zadatih
prekidnih taaka. U tom trenutku se zaustavlja izvrenje i postaje aktivno okruenje Visual C++-a
prekonfigurisano za debagiranje. Na slici 11 prikazan je izgled okruenja u modu za debagiranje.

Slika 11. Okruenje za debagiranje programa

Za kontrolu izvrenja koriste se komande menija Debug. Znaenja pojedinih komandi su sledea:
Go (taster F5) nastavlja izvrenje do naredne prekidne take.
Restart (kombinacija tastera Ctrl+Shift+F5) resetuje izvrenje programa u modu za
6
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I
debagiranje.
Stop Debugging (kombinacija tastera Shift+F5) prekida debagiranje programa.
Step Into (taster F11) ulazi u funkciju koja eka na izvrenje. Ukoliko je u pitanju neka
druga naredba izvrava je i prelazi na narednu liniju u kodu.
Step Over (taster F10) izvrava funkciju ili naredbu i prelazi na narednu liniju u kodu.
Step Out (kombinacija tastera Shift+F11) izvrava tekuu funkciju do kraja i izlazi na nivo iz
koga je pozvana.
Run to Cursor (kombinacija tastera Ctrl+F10) izvrava program do linije koda na koju
ukazuje poloaj kursora.
Po zaustavljanju izvrenja mogue je oitati vrednosti pojedinih promenljivih i prikaz konteksta
(funkcija) iz kojeg se dolo do prekidne take. Oitavanje vrednosti promenljivih se moe izvriti
na nekoliko naina:
1. Zadrati pokaziva mia iznad naziva promenljive negde u kodu, to e rezultovati ispisivanjem
vrednosti pored pokazivaa.
2. Dodavanjem naziva promenljive ije se praenje eli u panelu Watch (desno ispod koda).
3. Direktno, ukoliko je promenljiva automatski izlistana u spisku promenljivih koje se trenutno
koriste (panel levo ispod koda).

7
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I
Zadatak 1: Napisati i pokrenuti program.
void main()
{
printf("Moj prvi program u C jeziku\n");
}

Zadatak 2: Napisati i pokrenuti program.


void main()
{
int razlika;
razlika = 100 -90;
printf("Razlika 100 -90= %d\ n", razlika);
}

Zadatak 3:Napisati i izvriti program. Probajte da debagirate program.


void main()
{
int zbir = 0;
int i;
for (i=0; i<10; i++)
{
zbir = zbir + i;
printf("i=%d zbir=%d\n", i, zbir);
}
printf("\nzbir=%d\n", zbir);
}

Zadatak 4:Nacrtati algoritam za sledee zadatke:


A. Sastaviti dijagram toka i napisati program kojim se izraunava vrednost funkcije:
x, x2

y 2, 2 x 3 .
x 1, x 3

B. Nacrtati algoritam koji tampa vae ime 1000 puta.
C. Nacrtati algoritam koji rauna N5
D. Nacrtati algoritam koji rauna Nx

8
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

VEBA 2 Tipovi Podataka, naredba scanf, printf, operatori


Osnovne definicije
Promenljiva (Variable) ime ili referenca na zapmenu vrednost (obino u memoriji)
Tip podatka (Data type) odreuje veliinu promenljive u memoriji, koje vrednosti ona moe da uzme, i koje
operacije su za ovu promnljivu dozvoljene
Operator (Operator) operacija koja se obavlja sa jednom do tri promenljive
Izraz (Expression) kombinacija litralnih vrednosti i promenljivih sa operacijma ili funkcijama
Opseg vaenja (Scope) deo programa u kome je ime nekog entiteta (promenljive ili funkcije) validno i moe
se iskorititi za pristup tom entitetu

Osnovni tipovi podataka i deklaracija podataka

Osnovni opsezi i veliina podataka razlikuju se od raunara do raunara i uglavnom zavise od arhitekture procesora.

1
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I
Konverzioni znaci za razliite tipove podataka
\Konverzacioni znak Opis
%c Jedan karakter znakovnog tipa
%d Oznaeni ceo broj
%e Broj u pokretnom zarezu, e -notacija
%E Broj u pokretnom zarezu, E -notacija
%f Broj u pokretnom zarezu, decimalna not.
%i Oznaeni ceo broj
%X Neoznaeni heksadecimalni broj (A do F)
%x Neoznaeni heksadecimalni broj (a do f)
%s Karakterni niz

ESCAPE KARAKTERI
Escape karakteri se koriste za definisanje nekih specijalnih znakova koje inae nije mogue napisati u string konstantama.
Ovo je lista specijalnih znakova:
Escape sequence Description Representation
\' single quote byte 0x27
\" double quote byte 0x22
\? question mark byte 0x3f
\\ backslash byte 0x5c
\0 null character byte 0x00
\a audible bell byte 0x07
\b backspace byte 0x08
\f form feed - new page byte 0x0c
\n line feed - new line byte 0x0a
\r carriage return byte 0x0d
\t horizontal tab byte 0x09
\v vertical tab byte 0x0b

OPERATORI
U programskom jeziku C direktno je mogua primena osnovnih matematikih operatora +, -, *, / i operatora koji ne
postoje u drugim programskim jezicima: inkrement i dekrement. Ostale matematike operatore moemo ukljuiti iz skupa
datoteka zaglavlja koji sadri datoteku <math.h> i koja se po potrebi u procesu strukturnog programiranja ukljuuje u
izvorni program naredbom #include .
Aritmetiki operatori u C jeziku Komentar
Dodela vrednosti (=)
Aritmetiki operatori (+, -, *, /, % )
Inkrement (++) Efekti primene izraza su razliiti
Dekrement (--) Efekti primene izraza su razliiti
+=, -=, *=, /=, %=, >>=, <<=, &=, ^=, |=
Relacioni operatori ( ==, !=, >, <, >=, <= ) Koristimo ih kod logikih izraza (npr. IF naredbe)
Logiki operatori ( !, &&, || ) Za povezivanje vie logikih izraza
Uslovni operator (uslov ? iz1; iz2) a>b ? a : b
Operatori nad bitovima ( &, |, ^, ~, <<, >> )
sizeof(data_type) x = sizeof (char);
cast operator int i; float f = 3.14; i = (int) f;
Direktiva #include <stdio.h> u zaglavlju programa - ukljuuje stdio.h biblioteku koja je deo paketa C kompajlera i sadri
informacije o ulazno/izlaznim funkcijama za raunar. Naziv potie od STanDard Imput/Output.

2
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I
Prioritet Operatora
U sledeoj tabeli moete nai operatore u C jeziku od najveeg ka najmanjem prioritetu:
Level Precedence group Operator Description Grouping
1 Scope :: scope qualifier Left-to-right
++ -- postfix increment / decrement
() functional forms
2 Postfix (unary) Left-to-right
[] subscript
. -> member access
++ -- prefix increment / decrement
~! bitwise NOT / logical NOT
+- unary prefix
3 Prefix (unary) &* reference / dereference Right-to-left
new delete allocation / deallocation
sizeof parameter pack
(type) C-style type-casting
4 Pointer-to-member .* ->* access pointer Left-to-right
5 Arithmetic: scaling */% multiply, divide, modulo Left-to-right
6 Arithmetic: addition +- addition, subtraction Left-to-right
7 Bitwise shift << >> shift left, shift right Left-to-right
8 Relational < > <= >= comparison operators Left-to-right
9 Equality == != equality / inequality Left-to-right
10 And & bitwise AND Left-to-right
11 Exclusive or ^ bitwise XOR Left-to-right
12 Inclusive or | bitwise OR Left-to-right
13 Conjunction && logical AND Left-to-right
14 Disjunction || logical OR Left-to-right
= *= /= %= += -=
assignment / compound assignment
15 Assignment-level expressions >>= <<= &= ^= |= Right-to-left
?: conditional operator
16 Sequencing , comma separator Left-to-right

Zadatak 1. Sastaviti program na programskom jeziku C za upotrebu specifikatora konverzije u odnosu na


oekivane vrednosti celobrojnih promenljivih.
#include <stdio.h>
void main()
{
unsigned neoznacen = -39000;
printf ("neoznacen = %u, i nije %d\n", neoznacen,neoznacen);
printf ("Characters: %c %c \n", 'a', 65);
printf ("Decimals: %d %ld\n", 1977, 650000L);
printf ("Preceding with blanks: %10d \n", 1977);
printf ("Preceding with zeros: %010d \n", 1977);
printf ("Some different radices: %d %x %o %#x %#o \n", 100, 100, 100, 100,
100);
printf ("floats: %4.2f %+.0e %E \n", 3.1416, 3.1416, 3.1416);
printf ("Width trick: %*d \n", 5, 10);
printf ("%s \n", "A string");
}
Napisati izlaz iz programa i prokomentarisati rezultat tamo gde je potrebno:

3
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I
Zadatak 2. Sastaviti program na programskom jeziku C za formatiranje ulaza u pokretnom zarezu.
void main()
{
/* deklaracija podataka */
float f_pro;
double d_pro;
/*dodela vrednosti*/
f_pro = 106,11;
d_pro = -0,0000654;
/*tampanje vrednosti promenljivih */
printf ("Promenljiva f_pro=%2f\n", f_pro);
printf ("Promenljiva d_pro=%.11f\n", d_pro);
printf ("Promenljiva f_pro=%e\n", f_pro);
printf ("Promenljiva d_pro=%G\n", d_pro) ;
}

Izlaz iz programa je:

Zadatak 3. Sastaviti program na programskom jeziku C za unos proizvoljnog karaktera i za tampanje ASCII
koda tog karaktera.
#include<stdio.h>
void main()
{
char ch;
printf("Unesite proizvoljan karakter.\n");
scanf("%c",&ch); /*naredba za unos podataka*/
printf("ASCII kod unetog karaktera %c je %d\n",ch,ch);
}
Prepiite izlaz iz programa:

Zadatak 4. Napisati program na C jeziku za tampanje dva cela broja x i y u kao i njihovog inkrementa i
dekrementa koristei prefiksni i postfiksni operator.
Napomena: Operator inkrementa se koristi da bi se poveala vrednost promenljive za jedan. Operator dekrementa se
koristi da bi se smanjila vrednost promenljive za jedan. Pravila po kojima se primenjuje postfiksni i prefiksni zapis
operatora dekrementa na celobrojne promenljive i izraze su potpuno analogna pravilima upotrebe operatora inkrementa i
mogu se sagledati iz navedenog primera.
void main()
{
int x,y;
x=10; y=10;
printf("Vrednost izraza ++x je %d\n",++x);
printf("Vrednost izraza y++ je %d\n",y++);
printf("Nakon inkrementiranja vrednost za x je %d\n",x);
printf("Nakon inkrementiranja vrednost za y je %d\n",y);
printf("Vrednost izraza --x je %d\n",--x);
printf("Vrednost izraza y-- je %d\n",y--);
printf("Nakon dekrementiranja vrednost za x je %d\n",x);
printf("Nakon dekrementiranja vrednost za y je %d\n",y);
}

4
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I
Upisati rezultate rada programa i objasniti razliku izmeu prefiksnog i postfiksnog operatora:

Zadatak 5. ta oznaavaju vitiaste zagrade u jeziku C? Zato koristimo ove zagrade pri definiciji main (ili bilo
koje druge ) funkcije

Zadarak 6. Opiite razliku izmeu 7,7,7?

Zadatak 7. Napiite vrednosti sledeih izraza na osnovu tablice prioriteta operatora:


1. ( (5 == 5) && (3 > 6) )
2. ( (5 == 5) || (3 > 6) )
3. a=2; b=7; c = (a>b) ? a : b; Koliko je c?
4. a=2, b=7, a += 3 + b, b=1; Koliko je a i b?
5. a=2, b=7, a += 3 + b, b=1; Koliko je a i b?
1.
2.
3.
4.

5
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

VEBA 3 If naredba, predprocesorske direkltive, scanf

Predprocesorske direktive
Preprocessor directives are lines included in the code of programs preceded by a hash sign (#). These lines are not program
statements but directives for the preprocessor. The preprocessor examines the code before actual compilation of code
begins and resolves all these directives before any code is actually generated by regular statements.

These preprocessor directives extend only across a single line of code. As soon as a newline character is found, the
preprocessor directive is ends. No semicolon (;) is expected at the end of a preprocessor directive. The only way a
preprocessor directive can extend through more than one line is by preceding the newline character at the end of the line
by a backslash (\).
#define TABLE_SIZE 100

Zadatak 1: Napiite logiki izraz kojim moete da proverite da li je uneti karakter c:


Malo slovo (Answer: c>=a&& c<=z )
Veliko slovo (Answer: c>=A&& c<=Z )
cifra (Answer: c>=0&& c<=9 )
beli znak (ukljuujui blanko, tab I novi red) (Answer: c==\n|| c==\t|| c== )

Zadatak 2: Sastaviti program na programskom jeziku C za upotrebu funkcije rand() kojom se ukljuuje generator
sluajnih brojeva i tampa celobrojni sluajni broj i njegova dvostruka vrednost. tampati i sluajan borj izmeu 0 i
9. tmpati sluajan broj izmeu 10 i 19.

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
void main()
{
int slucajan, dvostruki, x, y;
srand (time(NULL)); /* initialize random seed: */

slucajan = rand();
dvostruki = slucajan*2;
x = rand() % 10; /*slucajan izmedju 0 i 9*/
y = rand() % 10 + 10; /*slucajan izmedju 10 i 19*/
printf("Slucajan broj je %d\n", slucajan);
printf("Dvostruki slucajan broj je %d\n", dvostruki);
printf("Jos neki slucajni brojevi %d, \t %d \n", x, y);
}
Prepiite izlaz iz programa. Funkcija rand() je deo koje biblioteke?

Zadatak 3: Proveriti upravljaku strukturu if naredbe:

#include <stdio.h>
void main()

1
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

{
int x, y, z; x = 10; y= 3; z = ( x / y ) * y;
if (x == z)
{ printf ( "Vrednosti x-a i z-a su jednake\n");
printf ( "Vrednost x-a je %d\n", x );
printf ( "Vrednost z-a je %d\n", z );
}
if ( x <= z)
{ printf ("Vrednost x-a je < ili = od vredriosti z-a\n");
printf( "Vrednost x-a je %d\n", x );
printf( "Vrednost z-a je %d\n", z );
}
if ( x >= z)
{ printf ( "Vrednost x-a je > ili = od vredriosti z-a\n" );
printf ( "Vrednost x-a je %d\n", x );
printf ( "Vrednost z-a je %d\n", z );
}
}

Prepisati rezultat:

Zadatak 4: Napisati program na C jeziku za reavanje kvadratne jednaine x2 + x - 2 = 0 korienjem


obrasca:
b b 2 4ac
x1, 2
2a
i tampanje vrednosti za x1 i x2.

#include<stdio.h>
#include<math.h>
void main()
{
double a,b,c;
double x1,x2,pom;
a = 1; b = 1; c = -2;
pom = sqrt(b*b-4*a*c);
x1 = ( (-b) + pom ) / 2 * a;
x2 = ( (-b) - pom ) / 2 * a;
printf("Vrednost prvog korena x1 = %f\n",x1);
printf("Vrednost drugog korena x2 = %f\n",x2);
}

Opisati rezultate rada programa :

2
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

Zadatak 5: Napisati isti program ali u optem obliku kada se veliine a, b i c uitavaju sa tastature.
Napisati izvorni kod programa:

Zadatak 6: Napisati program na C jeziku za izraunavanje ukamaene vrednosti ako je poznata mesena
kamatna stopa, period oroavanja u mesecima i iznos glavnice. tampati dobijene rezultate i proveriti
matematiku postavku programa.

Napomena: Koristiti pow funkciju iz biblioteke math.h koja izraunava x na y. Kamata se rauna kao glavnica *
(1+kamata/100)period.
#include <stdio.h>
#include <math.h>
void main( )
{
double stopa, period, glavnica;
printf( "Unesite mesecnu kamatnu stopu: " ) ;
scanf( "%lf", &stopa ) ; /* ulaz u pokretnom zarezu */
/* konverzija u procente */
stopa = stopa / 100.0;
printf( "Unesite glavnicu: " );
scanf( "%lf", &glavnica );
printf( "Unesite vreme orocavanja u mesecima: " );
scanf( "%lf", &period ) ;
printf( "Ukamacena vrednost je = %.2f\n",
glavnica * pow( (1.0+stopa), period));
}
Proveriti izlaz iz programa za sledee vrednosti: Kamatna stopa: 1, glvnica: 100, oroavnje: 3 meseca. Koliko e
iznositi krajnja vrednost?

Zadatak 7: Objasnite zato su ovi izrazi netani:


a) #include <stdio.h>;

b) int main(int arg1){ return arg1-1 }

c) int 2nd value=10;

d) #define MESSAGE = "Happy new year!"


printf("%s",MESSAGE);

3
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

VEBA 4 for petlja, while petlja, makroi

For petlja

ulaz

izraz 1

izraz 3

T
izraz 2 naredba

N
izlaz

Upravljake informacije kod for petlje, za razliku od while petlje, su smetene na jednom mestu i to na vrhu iteracije.
Petlja for je definisana, to znai da unapred znamo koliko puta e petlja da se izvri, a njena osnovna konstrukcija je:
Inicijalizacija inicijalizacije vrednosti brojaa. i = 0
Uslov na primer uporeenje brojaa sa graninom vrednou. i < 10
Inkrementirnje auriranje brojaa pri svakoj iteraciji. i ++
Prema tome, opti oblik naredbe for je: for ( izraz1, izraz2, izraz3 )
naredba
uz napomenu da neki od izraza u for petlji moe ostati prazan i tada se za taj izraz smatra da ima vrednost true..

Zadatak 1 Napisati program na C jeziku za prikaz neparnih brojeva manjih ili jednakih 20 korienjem for petlje.

1
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

While petlja
Ulaz

T
izraz naredba

Izlaz

Upravljaku strukturu while karakteriu etiri osobine:


petlja se ponavlja sve dok izraz koji se testira ne postane netaan ( logika 0 );
petlja je sa ulaznim uslovom : odluka o jo jednom prolasku kroz telo petlje se donosi pre izvrenja naredbi petlje;
while petlja mora sadr`avati promenu vrednosti izraza tako da postane la`an posle odre|enog broja iteracija, kako
petlja ne bi postala beskonana;
jedna naredba se posmatra kao deo upravljake strukture while petlje, bilo ona prosta ili sloena.

Zadatak 2. Napisati program na C jeziku za izraunavanje zbira celih brojeva upotrebom while petlje.
Izraunavanje se prekida kada se unese 0;
void main()
{
long sum = 0L;
int num;
printf("Unesite broj za sumiranje Ili 0 za izlaz\n");
scanf("%ld", &num);
while (num != 0)
{
sum = sum+num;
printf("Unesite naredni broj za sabiranj ili 0 za quite :::::::: %d \n ", num);
scanf("%ld", &num);
}
printf("Zbir unetih brojeva je %ld.\n", sum);
}

Upisati rezultate rada programa :

2
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I
Zadatak 3. Napisati program u C jeziku za permutovanje cifara celog broja - while iskaz: (npr. 54321 u 12345 )
Postupak: celi broj 54321 delimo po modulu 10 - rezultat je 1
celi broj 54321 delimo sa 10 - rezultat je 5432
celi broj 5432 delimo po modulu 10 - rezultat je 2
celi broj 5432 delimo sa 10 - rezultat je 543
celi broj 543 delimo po modulu 10 - rezultat je 3
celi broj 543 delimo sa 10 - rezultat je 54
celi broj 54 delimo po modulu 10 - rezultat je 4
celi broj 54 delimo sa 10 - rezultat je 5
celi broj 5 delimo po modulu 10 - rezultat je 5
Petlja se prekida jer broj postaje nula !!!

#include <stdio.h>
void main()
{
int broj;
printf("Ukucajte ceo broj ? ");
scanf("%d", &broj );
printf("Permutovani broj je ");
while ( broj )
{
printf("%d", broj % 10);
broj = broj/10;
}
printf("\n");
}

Rezultat za uneti broj 8612 je:

Zadatak 4. Napisati program na C jeziku za odreivanje srednje vrednosti n celih pozitivnih brojeva pomou
while petlje. Testirati program za vrednosti n=4, brojevi su redom 34.345, 234.2876, 45.98, 453.32. Koliki je
rezultat?

Zadatak 5. Razmotrite izraz : double ans = 18.0/squared(2+1). Izraunati vrednost izraza ako je funkcija makro
squared() definisana kao:
A. #define squared(x) x*x

B. #define squared(x) (x*x)

C. #define squared(x) (x)*(x)

D. #define squared(x) ((x)*(x))

3
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I
Zadatak 6. Napisati algoritam na programskom jeziku C koji vrednosti 3 promenljive rotira za k mesta u levo.
Vrednosti promenljivih i vrednost promenljive k zadaje korisnik. Prikazati vrednost promenljivih nakon rotacije.

Zadatak 7 ta je mrtva petlja?Napisati primer mrtve petlje za for i while naredbe i objasniti.

4
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

VEBA 5 do while petlja, switch case

Petlja sa ulaznim uslovom do while


U sluaju do while petlje obavezno izvravanje bar jedne iteracije se postie tako to je upravljaki
izraz petlje na samom dnu petlje. Tako se uslov petlje proverava nakon izvrenih naredbi tela petlje.
Strukturni dijagram toka moe se prikazati kao:

ulaz

naredba

T
izraz

izlaz

Zadatak 1. Napisati program za izraunavanje n! primenom do while structure:

Reenje:
#include <stdio.h>
void main() /* Program za izracunavanje faktorijela */
{
int i, fak;
long n ;
i = 1; n = 1;
printf("lzracunavanje n!\nUkucajte broj ? ");
scanf("%d", &fak);
do{
n *= i;
i++;
} while (i <= fak);
printf("%d! = %ld\n", fak,n);
}

Koliko puta se izvri naredba n *= i. Napisati isti program koristei samo for petlju:

1
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

Bezuslovno grananje : naredbe break i continue


Prekid izvrenja naredbi tela petlje se moe realizovati i pre nego to uslovni izraz dobije logiku netanu
vrednost. Naredba kojom je mogue realizovati iskakanje iz upravljake strukture se realizuje korienjem kljune rei
break. Ova naredba inicira sledea dva procesa:
Prekid izvrenja naredbi tela petlje u upravljakim strukturama while, for i do while iskakanjem iz tela petlje.
Programski tok se nastavlja neposredno na prvoj naredbi iza naredbe upravljake strukture.
Preskakanje preostalih naredbi unutar viestrukog grananja, koje se ostvaruju naredbom switch,

Prekid izvrenja trenutnog ciklusa petlja, preskakanja svih ostalih naredbi i prelazak na sledeu iteraciju sa
obavlja naredbom continue.

Naredba viestrukog grananja Switch Case


Naredba viestrukog grananja je ekvivlentna upotrei naredbe if then else if. Koristi se kada vrednost nekog izraza moe
imati vie od dve vrednosti. Sintaksa narede je:
switch (promenljiva)
{
case literarna vrednost: naredba; break;
case literarna vrednost: naredba; break;
case literarna vrednost: naredba; break;
default nardba; break;
}

Zadatak 2. Primer programa u kome se koristi naredba break u kombinaciji sa naredbom switch za
izraunavanje broja samoglasnika u delu proizvoljnog teksta:

void main()
{
char ch;
int a_ct,e_ct,i_ct,o_ct,u_ct;
a_ct=e_ct=i_ct=o_ct=u_ct=0;
printf("Unesi priozvoljan tekst; Unesi # za izlaz.\n");
while((ch=getchar())!= '#')
{
switch (ch)
{
case 'a' : a_ct++; break;
case 'A' : a_ct++; break;
case 'e' : e_ct++; break;
case 'E' : e_ct++; break;
case 'i' : i_ct++; break;
case 'I' : i_ct++; break;
case 'o' : o_ct++; break;
case 'O' : o_ct++; break;
case 'u' : u_ct++; break;
case 'U' : u_ct++; break;
default: break;
} /* kraj switch */
} /* dok petlji nije kraj */
printf("Broj samoglasnika: A E I O U\n");
printf("%4d %4d %4d %4d %4d\n", a_ct,e_ct,i_ct,o_ct,u_ct);
}

Izlaz iz programa je:

2
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

Zadatak 3. Sastaviti program na C jeziku za reavanje sistema linearnih jednaina primenom Kramerovog
pravila:
1
x1 , x2 2 , x3 3 , , xn n

i praktino reiti sistem jednaina:
x1 + x2 + 2x3 = 9
4x1 - x2 + 3x3 = 11
-2x1 + 2x2 + x3 = 5
1 1 2 9 1 2 1 9 2 1 1 9
gde je : 4 1 3 , 1 11 1 3 , 2 4 11 3 , 3 4 1 11
2 2 1 5 2 1 2 5 1 2 2 5
void main()
{
int x1, x2, x3; int a1, a2, a3; int b1, b2, b3;
int c1, c2, c3; int r1, r2, r3;

scanf("%d %d %d %d", &a1, &b1, &c1, &r1);


scanf("%d %d %d %d", &a2, &b2, &c2, &r2);
scanf("%d %d %d %d", &a3, &b3, &c3, &r3);

int d = a1*b2*c3 + a2*b3*c1 + a3*b1*c2 - c1*b2*a3 - c2*b3*a1 - c3*b1*a2;


int d1 = r1*b2*c3 + r2*b3*c1 + r3*b1*c2 - c1*b2*r3 - c2*b3*r1 - c3*b1*r2;
int d2 = a1*r2*c3 + a2*r3*c1 + a3*r1*c2 - c1*r2*a3 - c2*r3*a1 - c3*r1*a2;
int d3 = a1*b2*r3 + a2*b3*r1 + a3*b1*r2 - r1*b2*a3 - r2*b3*a1 - r3*b1*a2;

x1 = d1/d; x2 = d2/d; x3 = d3/d;

printf ("determinante: %d %d %d %d", d, d1, d2, d3);


printf ("\npromenljive: %d %d %d\n", x1, x2, x3);
}
Proveriti reenja ovog sistema linearnih jednaina. Reenje treba da bude: x1=1, x2=2 i x3=3.

Zadatak 4. For petlja i do while petlja se mogu transformisati u while petlju. Transformiite sledee primere
a) Primer 1: Prevesti dati izraz koristei while petlju:
int i , ret = 1;
for ( i = 2; i <= n; i++)
ret = i ;

b) Primer 2: Prevesti dati izraz koristei for petlju


int i=1; int z = 0;
do {
z = z + i;
i++;
}
while (i <= 10 );

3
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

c) Primer 3: Prevesti dati izraz koristei while petlju


int i=1;
int z = 0;
do
{
z = z + i;
i++;
while (i <= 10 );
}
return n;
}

Zadatak 5. Napisati program sa menijem:


1- Program matematika
2- Program finansija
3- Program zabave
4- Exit
upotrebom naredbe switch i case. Korisnik unosi broj od 1 do 4. Nakon unosa program tampa ime
odabrane opcije i nudi mogunost za novi izbor sve dok se ne izabere opcija 4 (Exit).

4
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

VEBA 6 Funkcije
1. Potprogrami i struktura programa

Potprogrami predstavljaju mehanizam koji direktno podrava funkcionalnu dekompoziciju kao jednu od
osnovnih metoda strukturnog programiranja. Oni su samostalni segmenti programskog koda koji se pozivaju radi
obavljanja konkretno specificiranog zadatka. Potprogram moe biti neogranieno puta pozivan iz istog ili u okviru
razliitih programa. Programski jezik C sadri module (biblioteke) u kojima se nalaze grupe deklaracija promenljivih i
deklaracija potprograma kao jedinice fizike dekompozicije. Ovakav pristup za direktnu posledicu ima stvaranje optih
programskih reenja i mogunost viestrukog korienja istog programskog koda u razliitim softverskim proizvodima.
Svaki podprogram se sastoji od:
Deklaracije kojom se definie interfejs potprograma prema programu, koja ukljuuje ime potprograma, listu
parametara koja ne mora biti neprazna i opciono tip vraene vrednosti
Tela potprograma koje se sastoji od deklaracija i naredbi.

Postoje dva tipa potprograma:


FUNKCIJA: je segment programskog koda koji na osnovu nijednog, jednog ili vie argumenata, uvek daje
kao rezultat jednu tano odreenu vrednost koja se naziva vrednost funkcije.

PROCEDURA:je tip potprograma koji takoe moe prihvatiti nijednu, jednu ili vie vrednosti u obliku
argumenata. Na osnovu prihvaene vrednosti rezultat procedure moe biti nijedna ili vie vrednosti.
Programski jezik c ne podrava kreiranje procedura.

Rezervisana re void se koristi kao oznaka za povratnu vrednost kada funkcija ne vraa nita.

Definicija funkcije u optem sluaju ima sledei oblik:


povratni_tip ime_funkcije ( lista_argumenata )
{
naredba
naredba

return ime_promenljive
}

Izvravanje se moe prekinuti naredbama return ili exit.

1
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

Zadatrak 1 Poziv funkcija bez argumenata


#include <stdio.h>
#define IME "Visa tehnicka skola"
#define ADRESA "Beogradska 20"
#define MESTO "18000 Nis"
#define LIMIT 65
void zvezde(); /* deklaracija funkcije bez argumenata */

void main()
{
zvezde(); /* poziv korisnicke funkcije */
printf("%s \n",IME); /*poziv funkcije iz standardne biblioteke*/
printf("%s \n",ADRESA);
printf("%s \n",MESTO);
zvezde();
}

/*definicija korisnickih funkcija*/


void zvezde() /*potprogramska funkcija nema argumenata*/
{
int brojac;
for ( brojac=1; brojac <= LIMIT; brojac++)
printf("%c",'*');
printf("\n");
}

1.1 Sagledati tok glavnog programa i potprograma i utvrditi u kojoj programskoj liniji nastaju "take prekida"
glavnog program i kada se kontrola prebacuje na izvravanje potprograma.

1.2 ta oznaava kljuna re void?

1.3 Zato je neophodno prvo deklarisati funkciju zvezde()? ta bi se desilo da nismo deklarisali funkciju? Da li je
mogue napisati funkciju tako da se deklaracija i definicija funkcije obave zajedno? Kako?

1.4 Koristei isti program umesto konstanti IME, ADRESA i MESTO uneti vase podatke. Kompajlirati,
linkovati i izvriti ovako modifikovan program.

2
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

Zadatak 2. Poziv funkcija sa 2 argumenata: Sastaviti program na C jeziku za izraunavanje minimuma dva cela
broja. U glavnom programu obezbediti tampanje oba broja i njihovog minimum. Potprogramu treba kao
parameter da primi dva broja i da vrati manji od njih.
#include<stdio.h>
int imin ( int n, int m); // Deklaracija funkcije

void main() /* glavni program */


{
int broj1, broj2, vrati, rez;
printf("Unesite 2 proizvoljna broja: \n");
vrati=scanf("%d %d",&broj1,&broj2);
rez = imin(broj1,broj2);
if (vrati == 2)
{
printf("Manji od %d i %d je %d\n",broj1,broj2, imin(broj1,broj2));
printf("Manji od %d i %d je %d\n",broj1,broj2, rez);
}
}

int imin( int n, int m ) /* potprogram definicija funkcije */


{
int min;
if (n<m)
min=n;
else
min=m;
return min;
}

2.1 ta vraa funkcija scanf?

2.2 Obajsnite sledeu naredbu: printf("Manji od %d i %d je %d\n",broj1,broj2, imin(broj1,broj2));

Zadatak 3. Sastaviti program korienjem struktura IF...THEN....ELSE IF za izraunavanje funkcije y. U


glavnom programu obezbediti tampanje rezultata, a u potprogramu definisati vrednosti funkcije po datim
uslovima. Brojevi su integer tipa.
x1+x2, x1<x2
y= x1*x2, x1=x2
x1-x2, x1>x2
Napisati program:

3
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

Zadatak 4. Napisati program za izraunavanje hipotenuze pravouglog trougla. U glavnom program izvriti unos
vrednosti prve i druge katete i tampati vrednost hipotenuze. U potprogramu izraunati vrednost hipotenuze.

Zadatak 5. Sastaviti program za prenos argumenata pozivom po vrednosti.


#include <stdio.h>
void promeni(int u, int v)
{ int temp;
printf("U funkciji originalne vrednosti su: u = %d a v= %d.\n", u, v);
temp=u;
u=v;
v=temp;
printf("U funkciji nakon promene vrednosti su: u = %d a v= %d.\n", u, v);
}

void main ( )
{ int x = 5, y = 10;
printf("U programu oriqinalne vrednosti: x = %d a y = %d.\n", x, y);
promeni(x,y);
printf("U programu nakon poziva funkcije je: x = %d a y = %d.\n", x, y);
}
4
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

5.1 Napisati reaultate rada programa. Zato promenljive x i y nisu zamenile vrednosti u glavnom program, a
jesu unutar funkcije? Izmeniti i napisati kod programa funkcije promeni tako da promenljive x i y zamene mesta
i u glvnom programu. Problem moete reiti pomou pokazivaa ili referenci.

5
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

VEBA 7 Nizovi

1. Izvedeni tipovi podataka - nizovi


Niz je homogena struktura u kojoj su svi objekti istog tipa. Objekti u nizu se nazivaju elementi niza. Tip niza
predstavlja implicitnu konsekvencu tipa svojih elemenata. Korienjem indeksa u nizu se veoma lako pretrauju
homogeni tipovi podataka, vri se njihovo sortiranje ili prestruktuiranje elemenata na neki drugi nain. Nizovi mogu biti:
nizovi celih, nizovi realnih brojeva, nizovi pokazivaa, nizovi karaktera, nizovi objekata itd.
Opti oblik deklaracije niza je: tip_podatka ime_niza [veliina]

2. Pokazivai
Pokaziva je promenljiva koja sadri adresu objekta ili funkcije. Rad sa pokazivakim promenljivama je veoma
teko razumeti bez razumevanja koncepta indirekcije, odnosno koncepta posrednog pristupa. Objekti programskog
reenja se uvek memoriu u odreenom programskom bloku, i to na tano odreenoj memorijskoj lokaciji. Pokazivai

omoguuju indirektni pristup vrednostima programskih promenljivih korienjem njihovih memorijskih adresa. U
neposrednoj vezi sa pokazivaima su dva specijalna operatora programskog jezika.operator adresa-od u oznaci & je
operator koji daje memorijsku adresu objekta na koga je primenjen; posredni operator * je operator kojim se upravlja
memorijskim lokacijama u pokazivakim promenljivama.
Adresni operator & je unarni operator vrlo visokog prioriteta, to je sluaj i sa ostalim unarnim operatorima.
Ovaj operator predstavlja nain da se sazna memorijska lokacija gde je taj objekat smeten u memoriji raunara.
Asocijativnost ovog unarnog operatora je s desna na levo, a opseg vrednosti koji moe da ima je skup nenegativnih celih
brojeva (unsigned int). Operator indirekcije * omoguava deklarisanje pokazivake promenljive i indirektni pristup do
vrednosti za koje su koriene pokazivake promenljive. U razvoju programskih reenja se vrlo esto informacija o
memorijskoj adresi promenljive ili funkcije uva i kasnije koristi. Za implementaciju ovog koncepta je neophodno
obezbediti mesto u memoriji gde se smeta informacija o adresi programskog objekta, koju dobijamo deklarisanjem
pokazivake promenljive. Paradigma pokazivakih promenljivih u C jeziku bi izgledala:

Pokazivai se esto koriste u sprezi sa nizovima kako bi se lake dolazilo do odreenog lana niza to predstavlja
adekvatnu upotrebu aritmetikih operacija nad pokazivaima. Dozvoljene operacije su sabiranje i oduzimanje celobrojnih
podataka, dodela vrednosti jednog pokazivaa drugom, poreenje dva pokazivaa, poreenje pokazivaa i nule kao
celobrojne vrednosti, oduzimanje vrednosti pokazivaa istog tipa.

1
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

Deklaracija Niza
Svaki niz mora biti deklarisan pre nego to se moe koristiti:
type variable_name[lengthofarray];

Ilustrujmo to primerima:
double height[10]; float width[20]; int min[9]; char name[20];

U C jeziku elemnti niza poinju od pozicije (indeksa) 0. Elementi niza se nalaze ne susednim memoriskim lokacijama.
Samo ime niza ustvari predstavlja pokaziva na memorisku lokaciju prvog elemnta niza. Zato je mogue pristupiti bilo
kom elementu niza navoenjem odgovarajueg indeksa tog elementa:
m=height[0];

U prethonom primeru promenljiva m e dobiti vrednost prvog elementa niza height.

Inicijalizacija Niza
Inicijalizacija niza predstavlja dodelu inicijalne vrednosti svim njegovim lanovima. Sledei kod ilustruje deklaraciju i
inicijalizaciju niza:
int myArray[5] = {1, 2, 3, 4, 5}; //istovremena deklaracija i inicijalizacija
int studentAge[4]; studentAge[0]=14; studentAge[1]=13;
studentAge[2]=15; studentAge[3]=16;

Dinamika deklaracija niza


Nizove je mogue deklarisati:
statiki u statikom delu memorije ili steku
dinamiki u dinamikom delu memorije ili heap-u
O dinamikom alociranju memorije emo dettljnije uiti na kursu programski jezici II.

2
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

1. Zadatak 1. Napisati program za unos i izraunavanje zbira lanova niza sa 5 elemenata.


void main(void)
{
float broj[5]; //deklaracija niza
double rez = 0; int i; //pomocne promenljive

for(i=0; i < 5; i++) //uzmi podatke i smesti ih u broj


{
printf("Unesite broj %d : ", i+1);
scanf("%f", &broj[i] );
}

for(i = 4; i+1 ; i--) //saberi


rez += broj[i];

printf("Zbir unesenih brojeva je %lf \n", rez); //prikazi rezultat


}

1.1 Testirajte program. Navedite uneene vrednosti za niz i rezultat:

1.2 Deklarisati niz od 4 elemenata tipa char i inicijalizovati sve lanove niza na vrednost a. Ilustrovati oba na;ina
inicijalizacije:

1.3 Dodeliti vednost m drugom i cetvrtom elemntu niza.

1.4 ta e se desiti ukoliko pokuamo da petom elemntu ovog niza dodelimo vrednost m

Zadatak 2. Napisati program kojim se odreuje redni broj maksimalnog elementa u celobrojnom nizu X od N
elemenata.
Reenje:
start

N, (X(I), I=1,N)

IMAX=1

I=2,N

X(IMAX)<X(I) ne
da
IMAX=I

(X(I),I=1,N)

IMAX,X(IMAX)

kraj

3
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

Zadatak 3. Primer prenosa argumenata funkcije pokazivakim promenljivim za realizaciju sabiranja lanova
niza.
#include <stdio.h>
#define VELIC 10
long sump(int *pok, int vel);

void main()
{
static int niz[VELIC] = {20,10,5,39,4,16,19,26,31,20};
long odgovor;
odgovor = sump(niz, VELIC);
printf("Suma niza je: %ld.\n", odgovor);
}

long sump(int *ar, int n) /* koristi pokazivacku aritmetiku */


{
int i ;
long ukupno = 0;
for(i = 0; i < n; i++) {
ukupno += *ar; /* dodaje vrednost na ukupno */
ar++; /* pomera pokazivac na sledeci elemenat */
}
return ukupno;
}
Rezultat ovog programa je:

Zadatak 4. Napisati program za tampanje niza i mnoenje elemenata niza konstantnom vrednou.
#include <stdio.h>
#define VELICINA 5

void main()
{
double dip[VELICINA] = {20.0, 17.66, 8.2, 15.3, 22.22};
int i;
for(i = 0; i < VELICINA; i++)
dip[i] *= mnozi;

printf("\n");
for(i = 0; i < n; i++)
printf("%8.3f ", dip[i]);
printf ("\n");
}

Napisati rezultate rada programa:

4
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

Zadatak 4.1. Izmeniti kod iz prethodnog zadatka tako da se svaki element niza uvea (umesto pomnoi) za neku
konstantnu vrednost koja se unosi sa tastature.

Zadatak 4.2 Izmeniti kod iz prethodnog zadatka tako da se tampanje niza i mnoenje niza obavi u potprogramu.

5
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

Zadatak 5. Razmotriti rad programa pisanog u C programskom jeziku, koji sortira dati vektor ar =
{7,3,9,2,11,20,17,19,6,4} korienjem metode "bubble sort" algoritma. Program se najpre sastoji u pisanju
funkcije "swap" koja vri zamenu vrednosti dve promenljive i smeta ih u dve memorijske lokacije. Zatim tu
funkciju koristimo da bi izvrili sortiranje datog vektora. "Bubble sort" ispituje svake dve elije vektora i ako nisu
sortirane - svapuje ih. Ako se obezbedi uporeenje i svapovanje n-1 put nad svim elijama vektora, on e biti
kompletno sortiran.

#include <stdio.h>
void swap (int *a, int *b);

void main()
{
int ar[10] = {7, 3, 9, 2, 11, 20, 17, 19, 6, 4};
int i,j,n;

printf("Vektor pre sortiranja:\n");


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

n=10; /*broj clanova u vektoru koji se sortira*/


for(i=0;i<n-1;i++)
for(j=0;j<n-1;j++)
{
if(ar[j]>ar[j+1])
swap(&ar[j],&ar[j+1]);
}

printf("\nVektor posle sortiranja:\n");


for(i=0;i<10;i++)
printf("ar[%d]=%d\n",i,ar[i]);
}

void swap ( int *a,int *b)


{
int temp;
temp=*a;
*a=*b;
*b=temp;
}

Prepisati rezultate rada programa:

6
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

Zadatak 6: Napisati program u programskom jeziku C koji odreuje broj elemenata niza koji se javljaju samo
jednom.

Zadatak 7: Napisati program u programskom jeziku C koji za dva uneta niza A i B proverava da li ovi nizovi
imaju zajednikih elemenata. Ukoliko zajedniki elementi postoje, od njih se formira novi niz C i na kraju
zadataka tampa na standardni izlaz.

Primer A = { 1, 2, 3 ,4 ,5}; B = {2, 7, 4, 9, 8};


U ovom sluaju C e biti {2, 4};

7
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

VEBA 8 Znakovni nizovi


Zadatak 1. Sastaviti program na programskom jeziku C za ispisivanje tablice ASCII kodova za sve tampajue
znake.
ASCII kod sa brojem 32 je blanko simbol ili razmak. Prvih 32 ASCII kodova i svi ASCII kodovi vei ili
jednaki 127 predstavljaju specijalne simbole koji se koriste u razliite svrhe i najee nemaju neko jasno slovno
znaenje. Koristili su se za iscrtavanje DOS prozora, i na taj nain simulirali grafiku u tekstualnom reimu rada.
Konkretno prozori razvojnog okruenja Turbo C su napravljeni na ovaj nain. ASCII kodovi izmeu 33 i 126 su
tampajui znaci.
Znaci se prikazuju po kolonama. U jednoj koloni se prikazuje po 19 znakova, a u jednom redu se prikazuje po
5 znakova (5x19=95). Prikazaemo sve ASCII kodove od 32 do 126.

#include <stdio.h>
void main()
{
char c=' ';
int i;

printf ("\t\tTablica ASCII kodova \n \n");


for (i=0; i<95; i++)
printf("%3d %c ",c+i,c+i);
if (i%19 == 0)
printf("\n");
}
1.1 Koji je kod za karaktere a, A, #?

Zadatak 2 Poreati sledei niz naredbi u odgovarajui redosled tako da program odtampa jednostavnu poruku
Ja s am student prve godine
1. return 0;
2. const char msg[] = MSG1;
3. }
4. #define MSG1 "All your base are belong to us!"
5. int main(void){
6. #include <stdio.h>
7. puts(msg);

Zadatak 3. Unos i tampanje karaktera


Program uitava i broji karaktere sa ulaza sve dok se ne otkuca znak za kraj unosa EOF. EOF se moe generisati
kucanjem Control + Z, a zatim enter.
#include <stdio.h>
void main()
{
int ch, i = 0;
while((ch = getchar()) != EOF)
i ++;
printf("%d\n", i);
}
3.1 ta je EOF? U kom fajlu (biblioteci) je ona definisana? Pronadjite kolika je njena celorojna vrednost:

1
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I
Zadatak 4. Sastaviti program koji iz skupa unetih karaktera (na primer: Ja sam rodjen 1990. god u 12. mesecu,
i u petak!) izraunava broj unetih slova, brojeva i ostalih karaktera. Tekst se unosi sa tastature, a program se
prekida pritiskom na ctrl+Z, a zatim enter.

Zadatak 5. Napisati program konvertuje velika u mala slova. Recenica se unosi sa tastature a program se prekid
unoenjem karaktera %.

5.1 Koju celobronu vredsnot imaju znakovi a, A i #?

Zadatak 6 Napisati program na programskom jeziku C koji uitava dva znakovna niza, ije se duine unose kao
podatak sa tastature, izvri nadovezivanje drugog na prvi, okrene naopako dobijeni niz i ispie ga na
standardnom izlaznom ureaju. Znakovni nizovi su maksimalne duine 200 karaktera.

6.1 Da li je mogue deklariati niz sledeim izrazom int niz[n], gde je n neka promenljiva. Zato?

6.2 Napisati primer unetih vrednosta za niz i dobijeni rezultat.

6.3 Napisati koje jo naredbe znate za rad sa nizovima i kratko objanisiti ta rade:

2
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I
6.4 Da li je mogue promeniti veliinu ve deklarisnaog niza. Zato?

Zadatak 7. Sastaviti program na jeziku C za uitavanje imena gradova uz njihovo ureivanje po abecednom
redosledu i ispisivanje rezultata. U svakom redu se uitava po jedno ime sve dok se ne uita prazan red.
Program:

3
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

VEBA 9 Matrice

Multidimenzijalni nizovi
U C jeziku mogu postojati i viedimenzijalni nizovi. Probajmo da to ilustrujemo primerom jedne matrice dimenzija 4 x
5:

Column numbers (j)


0 1 2 3 4
Row
0 11 3 5 -9 -6
number
1 5 6 -8 7 24
(i)
2 -8 9 2 12 45
3 10 13 -10 4 5

Neka je ime nae matrice X. Za pristup elemntu matrice mramo da koristimo dva indeksa, jedan za red a drugi za vrstu
matrice. Izraz bi u ovom sluaju izgledao X [i] [j], gde je i indeks reda, a j indeks kolone. To znai da bi X [0] [0]
referencirao vrednost 10, X [2] [1] referencira vrednost 9. Ukratko, multidimenzijalni nizovi se definiu na isiti nain
kao i obini nizovi samo to korite vei broj indeksa za pristup svojim elementima. Mi emo za sada raditi samo sa
dvodimenzijalnim nizovima. Deklarisanje ovakvog niza se moe uraditi ovako:
float table [50] [50];
char line [24] [40];

Prvi primer definie matricu (dvodimenzionalni niz) float vednosti koja ima 50 vrsta i 50 kolona. To znai da e ukupan
broj elementata biti 50x50=2500. Drugi primer deklarie matricu char elemenat sa 24 vrsta i 40 kolona. Ukupan broj
elemenata je 24 x 40 = 1920 elemenata.

Pokaimo jo jedan primer matrice 3 x 4 sa vrednostima {1, 2, 3, 4, 5, 6, 7, 8, 9, 10. 11, 12, };


Values [0] [0] = 1 Values [0] [1] = 2 Values [0] [2] = 3 Values [0] [3] = 4
Values [1] [0] = 5 Values [1] [1] = 6 Values [1] [2] = 7 Values [1] [3] = 8
Values [2] [0] = 9 Values [2] [1] = 10 Values [2] [2] = 11 Values [2] [3] = 12

Prvi indeks oznaava vrstu a drugi kolonu. Prvi indeks moe uzeti vrednosti od 0 do 2 to ukupno ini 3 vrst. Drugi
indeks moe uzeti vrednosti od 0 do 3 to ukupno ini 4 kolone. Ova matrica se moe deklarisati i inicijalizovti i na
sledei nain:
int values [3] [4] = {
{ 1, 2, 3, 4 }
{ 5, 6, 7, 8 }
{ 9, 10, 11, 12 }
};

1
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I
Zadatak 1. Sastaviti program na programskom jeziku C koji tampa sadraj kvadratne matrice 5 * 5 vrstu po
vrstu, a potom sporednu dijagonalu, sleva-udesno. Matricu formirati generatorom sluajnih brojeva RAND()
#include <stdio.h>
void main()
{
int a[5][5], n, i, j;
for (i=0; i<5; i++)
{
/*alocira memoriju za n elemenata vrste koji su tipa int*/
for (j=0; j<5; j++)
a[i][j] = rand()%10;
}

for (i=0; i<5; printf("\n"), i++)


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

for (i=4; i>=0; i--)


printf(" %d", *(*(a+i)+5-1-i));
printf("\n");
}

Prepisati rezultate rada programa. Napisati na drugi nain izraz printf(" %d", *(*(a+i)+5-1-i)).

Zadatak 2. Neka je data kvadratna matrica u formatu:


1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
lanove matrice uneti u program kao konstantne celobrojne veliine, a kao izlaz iz programa predvideti
tampanje ove matrice u pokazanom formatu kao polazne matrice i tampanje nove matrice u istom obliku ali
sada unazad od lana a44,a43,a42a41,......,a11.
void main()
{
int mat[4][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
int i,j;
printf("\nPolazna matrica je\n");
for(i=0;i<4; i++)
{
for(j=0;j<4; j++)
printf("%2d ",mat[i][j]);
printf("\n");
}

printf("\nNova matrica je\n");


for(i=3;i>=0; i--)
{
for(j=3;j>=0; j--)
printf("%2d ",mat[i][j]);
printf("\n");
}
}

2
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I
Napisati rezultate rada programa:
ulazni nizovi: obrnuti izlazni niz

Zadatak 3. Napisati program na C++ jeziku koji izraunava sumu svih elemenata u svakom redu pojedinano,
pravougaone matrice [4x4].
1 2 3 4
5 6 7 8
A=
9 10 11 12
13 14 15 16
void main()
{
int mat[4][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
int i,j,s=0;

printf("\nPolazna matrica je\n");


for(i=0;i<4; i++)
{
for(j=0;j<4; j++)
printf("%2d ",mat[i][j]);
printf("\n");
}

for(i=0;i<4; i++)
{
printf("\nSuma %d reda je:",i+1);
for(j=0;j<4; j++)
s=s+mat[i][j];
printf("%2d\n",s);
s=0;
}
}
Napisati rezultat rada programa:

Zadatak 4. Napisati program na C jeziku koji e izraunati sumu elemenata na glavnoj dijgonali proizvoljne
marice dimenzija 5x5.

3
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I

VEBA 10 Rad sa fajlovima

Upis i itanje iz fajla


U drugoj laboratoriskoj vebi smo uili kako da izvrimo upis sa standardnog ulaza, odnosno ispis na standardni izlaz u
programskom jeziku C. U ovoj vebi emo nauiti kako da creiramo, otvorimo, upiemo, proitamo i zatvorimo
tekstualni ili binanrni fajl.

Otvaranje fajla
Za otvaranje fajlova se koristi funkcija fopen. Svaki fajl se mora otvoriti pre korienja i zatvoriti nakon korienja
kako bi sve promene na fajlu bile zapamene. Ukoliko fajl ne postoji ova funkcija e ga kreirati, otvoriti, inicijalizovati
objekat tipa FILE, koji sadri sve informacije neophodne za kontrolu toka (stream) podataka. Pogledaj mo deklaraciju
ove funkcije:
FILE *fopen( const char * filename, const char * mode );
U ovom primeru filename je string literal i predstavlja putanju i ime fajla. Mode predstavlja pristupni mod i moe imati
sledee vrednosti:

Mod Opis

r Otvara trenutni tekstualni fajl kako bi se izvrilo itanje.

Otvara tekstualni fajl kako bi se izvrio upis. Ako fajl ne postoji , novi fajl e biti kreiran i program
w
e izvriti upis na poetak fajla.

Otvara tekstualni fajl za upis. Ako fajl ne postoji novi fajl e biti kreiran. Upis e izvriti dodavanje
a
sadraja na ve postojei sadraj fajla.

r+ Otvara tekstualni fajl za itanje i pisanje.

Otvara tekstualni fajl za itanje i pisanje. Sav sadraj fajla se brie. Ukoliko fajl ne postoji kreira
w+
se novi fajl.

Otvara teksualni fajl za itanje i pisanje. Kreira fajl ukoliko ne postoji. itanje e poeti na
a+
poetku fajla, ali pisanje e izvriti dodavanje sadraja na kraju fajla.
Ukoliko elite da koristite binarne fajlove onda morate koristiti sledee modove:
"rb", "wb", "ab", "rb+", "r+b", "wb+", "w+b", "ab+", "a+b"

Zatvaranje fajla
Za zatvaranje fajla koristite funkciju fclose(). Deklaracija ove funkcije je:
int fclose( FILE *fp );
Ova funkcija vraa nulu ukoliko je poziv uspean ili EOF ukoliko postoji greka pri zatvaranju fajla. Ova funkcija
ustvari prazni bafer koji se koristi za rad sa fajlom, zatvara fajl i oslobaa memoriju koja se koristila za fajl. EOF je
konstanta definisana u zaglavlju stdio.h fajla i najee ima vrednost -1.

Upis u fajl
Najjednostavnija funkcija za upis jednog karaktera u fajl je:
int fputc( int c, FILE *fp );
Ova funkcija vri upis jednog karaktera koji ima vreedsnot c na tok podataka referenciran sa fp. U naem primeru fp e
referencirati neki fajl. Funkcija e prilikom upisa izvriti internu konverziju karaktera u tip unsigned char. Funkcija
vraa karakter koji je upisan u sluaju da je funkcija uspeno izvrena, u suprotnom vraa EOF.

Sledea funkcija se moe koristiti za upis null-termineted stringa:


int fputs( const char *s, FILE *fp );
Ova funkcija vri upis stringa s u tok podataka referenciran sa fp. Ukoliko je funkcija upeno izvrena vraa se neka
nenegativna vrednost. U sluaju greke vraa se EOF. Moete koristiti i funkciju int fprintf(FILE *fp,const char
*format, ...) za upis jednog stringa u fajl.Ilustrujmo to primerom:

1
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I
Zadatak 1: Primer upisa u fajl.
#include <stdio.h>
void main()
{
FILE *fp;

fp = fopen("test.txt", "w+");
fprintf(fp, "This is testing for fprintf...\n");
fputs("This is testing for fputs...\n", fp);
fclose(fp);
}
1.1 ta e se desiti ukoliko fajl "test.txt" ne posotji?

1.2 Gde e se ovaj fajl kreirati? Zato?

1.3 ta bi se desilo da je pristupni mod bio a+?

1.4 Kojoj biblioteci (fajlu) pripadaju funkcije

itanje fajla
Sledea funkcija vri itanje jednog karaktera u fajl:
int fgetc( FILE * fp );
Funkcija fgets() vri itanje jednog karaktera iz toka podataka referenciranog sa fp. Povratna vrednost funkcije je
proitani karakter ukoliko je ona uspena. Ukoliko je dolo do greke funkcija e vratiti EOF.

Sledea funkcija omoguava itanje stringa iz ulaznog toka podataka:


char *fgets( char *buf, int n, FILE *fp );
Funkcija fgets() ita do n-1 karaktera sa ulaznog toka podataka referenciranog sa fp. Ona kopira proitani string u bafer
buf i dodaje null karkater kako bi zavrila string. Ako ova funkcija proita karakter za novi red '\n' ili karakter za kraj
fajla EOF pre nego to je proitala svih n-1 karaktera ona e prekinuti dalje itanje podataka. Zadnji karakter koji e
vratiti e biti znak za novi red.

Za itanje stringa se moe koristiti i funkcija int fscanf(FILE *fp, const char *format, ...). Ona e prekinuti itanje
nakon prvog blanko znaka. Ukoiko je uspena funkcija e vratiti broj argumenata koji su proitani. Na primer funkcija
fscanf(fp, "%s %s", ime, prezime); e vratiti vrednost 2 ukoliko je uspena ili EOF ako je neuspena.
Ilustrujmo ovo primerom:

Zadatak 2: Primer itanja iz fajla:


void main()
{
FILE *fp;
char buff[255];
fp = fopen("test.txt", "r");
fscanf(fp, "%s", buff);
printf("1 : %s\n", buff );

fgets(buff, 255, (FILE*)fp);


printf("2: %s\n", buff );

fgets(buff, 255, (FILE*)fp);


printf("3: %s\n", buff );
fclose(fp);
}
2.1 ta radi prethofni zadatak i ta e on ispisati na ekranu:

2
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I
Zadatak 3: Fajlovi zad4.txt sadri podatke o poenima koje su studenti osvojili na ispitu iz predmeta programski
jezici 1. Za svakog studenta je zapamen broj poena koje je student dobio na ispitu. Odtampati imena svih
studenata koji su poloili ispit. Ispit su poloili svi studenti koji imaju vie od 50 poena. Listu odtampati na
standardni ulaz i u fajl rezultati.txt. Primer fajla zad4.txt je:
Pera Peric 30
Ivana Stojicic 65
Marko Knezevic 45
Milutin Milankovic 80
void main()
{
FILE *fp, *fpr;
char ime[20], prezime[20];
int i=1, rez=0, r1=0, r3=0;
fp = fopen("zad3.txt", "r");
fpr = fopen("rez.txt", "w");
while (fscanf(fp, "%s", ime) != EOF)
{
r1 = fscanf(fp, "%s", prezime);
r3 = fscanf(fp, "%d", &rez);

if (rez >= 50)


{
printf("%d: %s %s %d \n", i, ime, prezime, rez);
fprintf(fpr, "%d: %s %s %d \n", i, ime, prezime, rez);
// printf("%d: %d %d \n", i, r1, r3 );
i++;
}
}
fclose(fp);
}

3.1 Gde se nalazi datoteka rez.txt i koji je njen sadraj nakon izvrenja programa?

3.2 Zato se u naredbi fscanf(fp, "%s", prezime); promenljiva prezime koristi bez operatora referenciranja &, a
promenljiva rez u naredbi fscanf(fp, "%d", &rez) se koristi sa ovim operatorom?

3.3 Da li moete da napiete program tako da se sve tri promenljive ime, prezime i rez itaju odjednom?
Dovoljno je napisati samo deo koda koji se razlikuje od trenutnog reenja. Koliku e vrednost u tom sluaju
vratiti funkcija fscanf?

3
Visoka tehnika kola strukovnih studija u Niu
Laboratorijske vebe iz Programskih jezika I
Zadatak 4: Fajl zad4.txt sadri odlomak jednog naeg poznatog romana. Tokom kucanja odlomka grekom je
umesto slova lj kucano slovo q i umesto slova nj, slovo w . Izvriti ispravku greaka pri kucanju ovog
odlomka i unete ispravke upisati u fajl rez4.txt. Izbrojati koliko je izmena ukupno bilo. Primer sadraja fajla
zad4.txt je: Vesti o qubicastom cvetu qiqanu mozete naci na wegovm blogu. Napisati program, ta tampa program na
standardni izlaz i sadraj fajla rez4.txt nakon izvrenja programa.

4
PRIMERI PROGRAMA ZA PRIPREMU PRVOG
KOLOKVIJUMA
/* abs funkcija za PRIMER APSOLUTNE VREDNOSTI CELOG BROJA */

#include <stdio.h>
#include <math.h>

int main(void)
{
int number = -1234;

printf("broj: %d ima apsolutnu vrednost: %d\n", number, abs(number));


return 0;
}

/* exp funkcija za IZRAUNAVANJE BROJA e NA REALNI STEPEN */

#include <stdio.h>
#include <math.h>

int main(void)
{
double result;
double x = 4.0;

result = exp(x);
printf("'e' dignuto na stepen %lf (e ^ %lf) = %lf\n",
x, x, result);

return 0;
}
/* log funkcija za PRIMER LOGARITMA REALNOG BROJA */

#include <math.h>
#include <stdio.h>

int main(void)
{
double result;
double x = 8.6872;

result = log(x);
printf("Prirodni logaritam %lf je %lf\n", x, result);

return 0;
}

/* sin funkcija za PRIMER IZRAUNAVANJA SINUSA REALNOG BROJA */

#include <stdio.h>
#include <math.h>

int main(void)
{
double result, x = 0.5;

result = sin(x);
printf("Sinus od %lf je %lf\n", x, result);
return 0;
}

/* poly funkcija za PRIMER IZRAUNAVANJA VREDNOSTI POLINOMA */

#include <stdio.h>
#include <math.h>
/*program za resavanje vrednosyi polinoma*/
/* polynomial: x**3 - 2x**2 + 5x - 1 */

int main(void)
{
double array[] = { -1.0, 5.0, -2.0, 1.0};
double result;
result = poly(2.0, 3, array);
printf("Polinom: x**3 - 2.0x**2 + 5x - 1 na 2.0 je %lf\n", result);
return 0;
}

/* pow funkcija za PRIMER IZRAUNAVANJA REALNOG BROJA NA STEPEN */

#include <math.h>
#include <stdio.h>

int main(void)
{
double x = 2.0, y = 3.0;

printf("%lf na stepen %lf je %lf\n", x, y, pow(x, y));


return 0;
}

/* pow funkcija za PRIMER IZRAUNAVANJA n-tog KORENA REALNOG BROJA */

#include <math.h>
#include <stdio.h>

float main(void)
{int n=5;
double x = 32.0,rezultat;
rezultat=pow(x,1./n);
printf("%d_ti koren broja %lf je: %lf\n",n, x,rezultat);
return 0;
}

NAPOMENA: u optem sluaju rezultat = n x m = pow ( x , m . / n)

/* sqrt funkcija kao PRIMER IZRACUNAVANJA KVADRATNOG KORENA REALNOG BROJA */

#include <math.h>
#include <stdio.h>

int main(void)
{
double x = 4.0, resultat;
resultat = sqrt(x);
printf("KVADRATNI KOREN %lf JE %lf\n", x, resultat);
return 0;
}

/* log10 funkcija za PRIMER LOGARITMA ZA OSNOVU 10 REALNOG BROJA */

#include <math.h>
#include <stdio.h>

int main(void)
{
double result;
double x = 800.6872;

result = log10(x);
printf("LOGARITAM BROJA %lf JE %lf\n", x, result);

return 0;
}

/* rand funkcija za PRIMER GENERISANJA SLUCAJNIH BROJEVA */

#include <stdlib.h>
#include <stdio.h>

int main(void)
{
int i;
printf("Deset slucajnih brojeva od 0 do 99 su:\n\n");
for(i=0; i<10; i++)
printf("%d\n", rand() % 100);
return 0;
}
Napisati program za generisanje sluajnog broja, izraunati njegovu dvostruku vrednost i prikazati sledei
sluajni broj.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void main()
{
int slucajan, dvostruki;
slucajan = rand();
dvostruki = slucajan*2;
printf("Slucajan broj je %d\n", slucajan);
printf("Dvostruki slucajan broj je %d\n", dvostruki);
printf("Naredni slucajan broj je %d\n", rand());
}

/* Rad sa specijalnim karakterima */


#include <stdio.h>
int main(void)
{printf("Alert: zvucni ili vizuelni signal \a\n");
printf("Alert: NESTO SE CUJE \n");
printf("Alert: PONOVO zvucni ili vizuelni signal \a\n");
printf("Po\bvratnik ili b\backspace: sakrij me\b \n");
printf("Form feed. \f\n");
printf ("Horizontalni\ttab\n");
return 0;}
vezba 1-2
/*Stampanje vrednosti stepena Farenhajta i Celzijusa pocev od 0 do 300 sa korakom 20 */
#include <stdio.h>
int main(void)
{
float fahr, celsius; /*vrednosti stepena Celzijusa, Farenhajta*/
int lower, upper, step; /* donja vrednost skale - lower, gornja vrednost skale -upper, korak skaliranja */
/*inicijalizacije*/
lower = 0;
upper = 300;
step = 20;
/*stampanje zaglavlja "tabele" */
printf("F C\n\n");
/*stampanje vrednosti stepena pocev
od 0 do 300 sa korakom 20 */
fahr = lower;
while(fahr <= upper)
{
celsius = (5.0 / 9.0) * (fahr - 32.0);
printf("%3.0f %6.1f\n", fahr, celsius);
fahr = fahr + step;
}
return 0;
}
vezba 1-3
obrnuto

#include <stdio.h>

/* print Fahrenheit-Celsius table */


int
main()
{
int fahr;

for (fahr = 300; fahr >= 0; fahr = fahr - 20)


printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32));

return 0;
}
Primer za tampanje rezultata mnoenja (od 1*1 do 9*9 u redovima po 9 ).

#include<stdio.h>
void main()
{
int i,j;
for(i=1;i<10;i++)
{
for(j=1;j<10;j++)
printf("%3d",i*j);
printf("\n");
}
}

Odreivanje znaka unetog broja

#include<stdio.h>
void main()
{
int n;
printf("Unesi ceo broj: ");
scanf("%d",&n);
if(n>=0)
printf("Broj je pozitivan !\n");
if(n<0)
printf("Broj je negativan !\n");
}

Drugi nain sa if alse strukturom :

#include<stdio.h>
void main()
{
int n;
printf("Unesi ceo broj: ");
scanf("%d",&n);
if(n>=0)
printf("Broj je pozitivan !\n");
else
printf("Broj je negativan !\n");
}

Napisati program za reavanje kvadratne jednaine ax2+bx+c=0.

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
void main()
{
float delta,a,b,c,x1,x2;
printf("Unesite a : ");
scanf("%f",&a);
printf("Unesite b : ");
scanf("%f",&b);
printf("Unesite c : ");
scanf("%f",&c);
delta=b*b-(4*a*c);
printf("Podkorena velicina delta je:%f",delta);
if(delta<0)
{
printf("Jednacina nema resenja !\n");
exit(0);
}
if(delta==0)
{
x1=-b/(2*a);
printf("E Jednacina ima dva ista resenja !\n");
printf("x1=x2=%f",x1);
exit (0);
}

x1=(-b+sqrt(delta))/(2*a);
x2=(-b-sqrt(delta))/(2*a);

printf("\nResenja jednacine su:");


printf("\nX1=%f",x1);
printf("\nX2=%f\n",x2);
}
Napisati program sa menijem:

1- Program matematika
2- Program finansija
3- Program zabave
4- Exit

upotrebom while naredbe i if, else if strukture za startovanje svih stavki iz menija.

#include<stdio.h>
#include<stdlib.h>
void main()
{
int choice;

while(1)
{
printf("\n\nMeni:\n");
printf("1- Program matematika\n2- Program finansija\n");
printf("3- Program zabave\n4- Exit");
printf("\n\nVas izbor -> ");
scanf("%d",&choice);

if(choice==1)
printf("\nProgram matematika Runs. !");
else if(choice==2)
printf("\nProgram finansija Runs. !");
else if(choice==3)
printf("\nProgram zabave Runs. !");
else if(choice==4)
{
printf("\nKraj programa!.\n");
exit(0);
}
else
printf("\nPogresan izbor");
}
}
Isti zadatak samo upotrebom naredbe switch i case.

#include<stdio.h>
#include<stdlib.h>
void main()
{
int choice;

while(1)
{
printf("\n\nMeni:\n");
printf("1- Program matematika\n2- Program finansija\n");
printf("3- Program zabave\n4- Exit");
printf("\n\nVas izbor -> ");
scanf("%d",&choice);

switch(choice)
{ case 1 :
printf("\nProgram matematika Runs. !");
break;
case 2 :
printf("\nProgram finansija Runs. !");
break;
case 3 :
printf("\nProgram zabave Runs. !");
break;
case 4 :
{
printf("\nKraj programa!.\n");
exit(0);
}
default:
printf("\nPogresan izbor");
}
}}

x 2 sin( x ) 1
Napisati program za izraunavanje funkcije y = 3
.
x
#include <stdio.h>
#include <math.h>
void main()
{
double x,y,pom;
printf("Unesite broj\n");
scanf("%lf",&x);
pom=pow(x,1./3.);
y=(x*x*sin(x)-1)/pom;
printf("Vrednost izraza je %lf a vrednost korena %lf\n",y,pom);
}
//Operator inkrementa
#include <stdio.h>
void main()
{
int x, y;
x = 10;
y =10;
printf("Vrednost izraza ++x je %d\n", ++x);
printf("Vrednost izraza y++ je %d\n", y++);
printf{"Nakon inkrementiranja vrednost x-a je %d\n",x);
printf{"Nakon inkrementiranja vrednost y-a je %d\n", y);
}

//Operator dekrementa
#include <stdio.h>
void main()
{
int x, y;
x = 10;
y = 10;
printf( "Vrednost izraza --x je %d\n", --x);
printf( "Vrednost izraza y-- je %d\n", y--) ;
printf( "Nakon dekrementiranja vrednost x-a je %d\n",x);
printf( "Nakon dekrementiranja vrednost y-a je %d\n", y);
}
//Operator dodeljivanja
#include <stdio.h>
void main()
{
int x, y;
x = 6;
y = 6;
if ( x = 7)
{
printf( " Prvi <if> je zadovoljen\n" );
}
else
{
printf( " Prvi <if> nije zadovoljen\n" );
}
if ( y == 7 )
{
printf( " Drugi <if> je zadovoljen\n" );
}
else
printf( " Drugi <if> nije zadovoljen\n" );
}

//Relacioni izrazi i logicki operatori


#include <stdio.h>
void main()
{
int minimum,maximum;
int prl, pr2;
minimum=10;
maximum = 1000;
prl = 110;
pr2 = 1123;
if( (prl < maximum && prl > minimum) || (pr2 < maximum && pr2 > minimum) )
printf( "Najmanje jedna vrednost je u opsegu\n" );
if( (prl < maximum && prl > minimum) && (pr2 < maximum && pr2 > minimum) )
{
printf( "Obe vrednosti su u opsegu\n" ) ;
}
}
//Poziv funkcije stdio.h i primena kod izlaznog tipa promenljive.
#include <stdio.h>
void main()
{
float n1=3.0;
double n2=3.0;
long n3=2000000000;
long n4=1234567890;
printf("%.le, %.le, %ld, %ld\n", n1,n2,n3,n4);
printf("%ld, %ld\n", n3, n4);
printf("%f, %f, %ld, %ld\n", n1,n2,n3,n4);
}

//Obracun kamata u pokretnom zarezu


#include <stdio.h>
#include <math.h>
void main( )
{
double stopa, period, glavnica;
printf( "Unesite kamatnu stopu: " ) ;
scanf( "%lf", &stopa ) ; /* ulaz u pokretnom zarezu */
/* konverzija u procente */
stopa = stopa / 100.0;
/* kamata se izracunava mesecno */
stopa= stopa / 12.0;
printf( "Unesite glavnicu: " );
scanf( "%lf", &glavnica );
printf( "Unesite vreme orocavanja: " );
scanf( "%lf", &period ) ;

/*Stopa je konvertovana na mesecnu osnovicu*/


period = period * 12.0;
printf( "Ukamacena vrednost je = %.2f\n",
glavnica * pow( (1.0+stopa), period));
}
//Zaokruzivanje vrednosti
#include <stdio.h>
void main()
{
float fvr_pz;
double dvr_pz;
fvr_pz= 123.45;
printf("l. Vrednost u pokretnom zarezu je %f\n", fvr_pz);
fvr_pz /= 3.30;
fvr_pz *= 3.30;
printf("2. Vrednost u pokretnom zarezu je %f\n", fvr_pz);
dvr_pz = 123.45;
printf("l. Vrednost u dvostrukoj preciznosti je %f\n", dvr_pz);
dvr_pz /= 3.30;
dvr_pz *= 3.30;
printf("2. Vrednost u dvostrukoj preciznosti je %f\n", dvr_pz);
}

//Formatiranje ulaza u pokretnom zarezu


#include <stdio.h>
void main()
{
/* deklaracija podataka */
float f_pro;
double d_pro;
/*dodela vrednosti*/
f_pro=106.11;
d_pro=-0.0000654;
/*stampanje vrednosti promenljivih */
printf ("Promenljiva f_pro=%2f\n", f_pro);
printf ("Promenljiva d_pro=%.11f\n", d_pro);
printf ("Promenljiva f_pro=%e\n", f_pro);
printf ("Promenljiva d_pro=%G\n", d_pro) ;
}
//Upravljacka struktura if
#include <stdio.h>
void main()
{
int x, y, z;
x = 10;
y= 3;
z = ( x / y ) * y;
if (x == z)
{
printf ( "Vrednosti x-a i z-a su jednake\n");
printf ( "Vrednost x-a je %d\n", x );
printf ( "Vrednost z-a je %d\n", z );
}
if ( x <= z)
{
printf ("Vrednost x-a je < ili = od vredriosti z-a\n");
printf( "Vrednost x-a je %d\n", x );
printf( "Vrednost z-a je %d\n", z );
}
if ( x >=z)
{
printf ( "Vrednost x-a je > ili = od vredriosti z-a\n" );
printf ( "Vrednost x-a je %d\n", x );
printf ( "Vrednost z-a je %d\n", z );
}
}

//Formiranje zbira celih brojeva while petljom

#include <stdio.h>
void main()
{
long num, sum = 0L;
int status;
printf("Unesite broj za sumiranje\n");
printf("Ili q za izlaz\n");
status = scanf("%ld", &num);
while (status==1)
{
sum = sum+num;

printf("Unesite naredni broj za sabiranje\n");


printf("Unesite q za quit!\n");
status=scanf("%ld", &num);
}
printf("Zbir unetih brojeva je %ld.\n", sum);
}
//Neparni brojevi sa for petljom

#include <stdio.h>
void main()
{
int broj;
for (broj=1;broj<=20;broj=broj+2)
printf("\n%d",broj);
}

//Naredba break sa naredbom switch


#include <stdio.h>
void main()
{
char ch;
int a_ct,e_ct,i_ct,o_ct,u_ct;
a_ct=e_ct=i_ct=o_ct=u_ct=0;
printf("Unesi priozvoljan tekst; Unesi # za izlaz.\n");
while((ch=getchar())!= '#')
{
switch (ch)
{
case 'a' :
case 'A' : a_ct++;
break;
case 'e' :
case 'E' : e_ct++;
break;
case 'i' :
case 'I' : i_ct++;
break;
case 'o' :
case 'O' : o_ct++;
break;
case 'u' :
case 'U' : u_ct++;
break;
default:
break;
} /* kraj switch */
} /* dok petlji nije kraj */
printf("Broj samoglasnika: A E I O U\n");
printf(" %d %d %d %d %d\n", a_ct,e_ct,i_ct,o_ct,u_ct);
}

//Ispisivanje brojeva Morzeovom azbukom


#include <stdio.h>
int main()
{ int broj;
printf("Unesi jedan broj izmedju 0 i 9:");
scanf("%d",&broj);
if((broj<0)||(broj>9))
{ printf("Broj nije u opsegu izmedju 0 i 9\n");}
else
{ printf("Broj %d prikazan Morzeovom azbukom je:",broj);}
if(broj==0) printf(-----);
if(broj==1) printf(.----);
if(broj==2) printf(..---);
if(broj==3) printf(...--);
if(broj==4) printf(....-);
if(broj==5) printf(.....);
if(broj==6) printf(-....);
if(broj==7) printf(--...);
if(broj==8) printf(---..);
if(broj==9) printf(----.);
return 0;
}
Program za izraunavanje sume prvih 20 prirodnih brojeva.
#include <stdio.h>
int main(void) /* suma prvih 20 prirodnih brojeva */
{
int brojac,suma; /* deklaracijska naredba */
brojac=1; /* naredba pridruzivanja */
suma =0; /* isto */
while(brojac++ < 21) /* while */
suma += brojac; /* naredba */
printf("suma = %d\n",suma); /* funkcijska naredba */
return 0;
}

Postavimo sada sledei zadatak: za zadani prirodan broja treba ispisati sve njegove delitelje.

#include <stdio.h>
int main(void)
{
long num; // broj koji proveravamo
long div; // potencijalni delitelj
unsigned flag = 0; // prim broj?
printf("Unesite celi broj ili q za izlaz: ");
while(scanf("%ld",&num) == 1)
{
for(div=2; (div*div) <= num; ++div)
{
if(num % div == 0)
{
if(div * div != num)
printf("%d je deljiv sa %d i %d\n", num, div,
num/div);
else
printf("%d je deljiv s %d.\n", num, div);
flag=1;
}
}
if(flag == 0) printf("%ld je prom broj.\n",num);
printf("Unesite celi broj ili q za izlaz: ");
}
return 0;
}
U sledeem primeru uitavaju se dva broja i jedan znak koji predstavlja izbor raunske operacije. U
zavisnosti od uitanog znaka izvrava se jedna od etiri raunske operacije.

#include <stdio.h>
int main(void)
{
float a,b;
char operacija;
printf("Upisati prvi broj: ");
scanf(" %f",&a);
printf("Upisati drugi broj: ");
scanf(" %f",&b);
printf("Upisati operaciju: zbir(z), oduzimanje(o),\n");
printf(" mnozenje(m),deljenje(d) :");
scanf(" %c",&operacija);
if(operacija=='z')
printf("%f\n",a+b);
else if(operacija=='o')
printf("%f\n",a-b);
else if(operacija=='m')
printf("%f\n",a*b);
else if(operacija=='d')
printf("%f\n",a/b);
else
printf("Nedopustena operacija!\n");
return 0;
}
U sledeem primeru uitavaju se dva broja i jedan znak koji predstavlja izbor njihovog odnosa (< manje, >
vee, = jednako ). U zavisnosti od uitanog znaka ispituje se jedan od tri odnosa za poreenje ova dva
broja.Ako je odnos taan tampati poruku "Izabrali smo pravi odnos brojeva a i b", a ako nije "Izabrali
smo pogresan odnos brojeva a i b". U sluaju da se unese pogrean znak za poreenje tampati poruku
"Nedopusteni znak za odnos brojeva!" .

#include<stdio.h>
#include <stdio.h>
int main(void)
{
float a,b;
char znak;
printf("Upisati prvi broj: ");
scanf(" %f",&a);
printf("Upisati drugi broj: ");
scanf(" %f",&b);
printf("Upisati znak poredjenja: manje <, vece >,\n");
printf(" jednako = :");
scanf(" %c",&znak);
if(znak=='<')
{if(a<b) printf("Izabrali smo pravi odnos brojeva a i b\n");
else printf("Izabrali smo pogresan odnos brojeva a i b\n");}
else if(znak=='>')
{if(a>b) printf("Izabrali smo pravi odnos brojeva a i b\n");
else printf("Izabrali smo pogresan odnos brojeva a i b\n");}
else if(znak=='=')
{if(a==b) printf("Izabrali smo pravi odnos brojeva a i b\n");
else printf("Izabrali smo pogresan odnos brojeva a i b\n");}
else
{printf("Nedopusteni znak za odnos brojeva!\n");}
return 0;
}

Program za izraunavanje srednje vrednostin upisanih brojeva.

#include <stdio.h>
/* Srednja vrednost upisanih brojeva (razlicitih od 0). */
int main(void)
{
int i=0;
double sum=0.0,x[];
printf(" Upisite niz brojeva !=0, ili nulu za kraj.\n");
printf(" x[0]= "); scanf("%lf",&x);
while (x!=0.0){
sum+=x;
printf(" x[%d]= ",++i);
scanf("%lf",&x);
}
sum/=i;
printf(" Srednja vrednost = %f\n",sum);
return 0;
}

/* Program za nalazenje najveceg zajednickog delioca dva nenegativna cela broja */


#include<stdio.h>
void main()
{
int prvi, drugi, pomocni;
printf("Ukucajte dva nenegativna cela broja ?\n");
scanf("%d%d", &prvi, &drugi );
while (drugi==0)
{
pomocni = prvi % drugi;
prvi = drugi;
drugi = pomocni;
}
printf("Najveci zajednicki delilac ovih brojeva je %d\n", prvi);
}

/* Program za permutovanje cifara celog broja - while iskaz */


#include<stdio.h>
void main()
{
int broj;

printf("Ukucajte ceo broj ? ");


scanf("%d", &broj );
printf("Permutovani broj je ");
while ( broj )
{
printf("%d", broj % 10);
broj = broj/10;
}
printf("\n");
}

/* Program za odredjivanje srednje vrednosti n celih pozitivnih brojeva -while iskaz */


#include<stdio.h>
void main()
{
int n, brojac = 0;
float suma = 0, x;
printf("Ukupno brojeva ? ");
scanf("%d", &n);
while (brojac < n)
{
printf("Ukucajte %d. broj ? ", brojac+1);
scanf("%f", &x );
suma += x ;
brojac += 1;
}
printf("Srednja vrednost ovih brojeva je %f\n", suma/n);
}

/* Program za izracunavanje faktorijela */


#include <stdio.h>
#include <math.h>
void main()
{
int i, n;
long fak = 1;
printf("lzracunavanje n!\nUkucajte broj ? ");
scanf("%d", &n);
for ( i=1; i<=n; ++i)
fak *= i;
printf("%d! = %ld\n", n, fak);
}

/* Program za odredjivanje srednje vrednosti n celih pozitivnih brojeva -for iskaz */


#include<stdio.h>
void main()
{
int n, brojac =1;
float suma =0, x ;
printf("Ukupno brojeva ? ");
scanf("%d", &n);
for ( ; brojac<=n; ++brojac, suma+=x )
{
printf("Ukucajte %d broj ?",brojac);
scanf("%f",&x);
}
printf("Srednja vrednost ovih brojeva je %f\n", suma/n);
}

Reiti funkciju primenom operatora uslovnog izraza:

1 broj < 0

s= 0 broj = 0
1 broj > 0

#include<stdio.h>
void main()
{
int s, broj;
printf("Unesite broj za odredjivanje uslova:");
scanf("%d",&broj);
s=(broj < 0) ? -1 : ((broj==0) ? 0 : 1);
printf("Vrednost izraza za uneti broj %d je s=%d\n",broj,s);
}
RAD SA NIZOVIMA KARAKTERA
//PROGRAM 1.

#include <stdio.h>
int main()
{
printf("Alert: zvucni ili vizuelni signal \a\n");
printf("Po\bvratnik ili b\backspace: sakrij me\b \n");
printf("Upravljacki znak carriage return, \r, pomera aktivnu poziciju do inicijalne pozicije
tekuce linije.\n");
printf("Form feed. \f\n");
printf ("Horizontalni\ttab\n");
printf("Vertikalni tab \v je trikovit, jer mu je ponasanje nije specificirano pod izvesnim
uslovima\n");
return 0;
}

/* Posle unosa sa tastature se za uneti EOF (uglavnom control-D ili control-Z karakter, ali ne
obavezno), stampa 0. Inace, stampa se 1. Akoje Vas input stream baferovan (a verovatno jeste),
onda morate pritisnuti ENTER taster pre nego dobijete izlaznu poruku */

//PROGRAM 2.

#include <stdio.h>
int main()
{
printf("Na mom sistemu vrednost za EOF je %d\n\n", EOF);
return 0;
}

1
//PROGRAM 3.

//Unos i tampanje karaktera


#include<stdio.h>//PRIMER 1.
int main()
{
char recenica[80];
printf("Unesite niz karaktera: ");
scanf("%s",&recenica);
printf("Prikaz unetog sadrzaja: %s\n",recenica);
return 0;
}

//PROGRAM 4.

//Unos i tampanje karaktera

#include<stdio.h>
void main( ) {
char c;
printf("Unesite jedan proizvoljni karakter:");
c = getchar( );
putchar('\n');//Prelazak u novi red
printf("Uneli ste karakter:");
putchar(c);//Stampanje unetog karaktera
putchar('\n');//Prelazak u novi red
}

2
//PROGRAM 5.
//Unos i tampanje karaktera

#include<stdio.h>
void main( ) {
char c[30];
printf("Unesite niz proizvoljnih karaktera:");
gets(c);
printf("\n");//Prelazak u novi red
printf("Uneli ste karakter:");
puts(c);//Stampanje unetog karaktera
printf("\n");//Prelazak u novi red
}

//PROGRAM 6.
//Unos i tampanje karaktera

#include <stdio.h>
main()
{ int vrednost;
vrednost='A';
printf("%s\nkarakter=%3c\nvrednost=%3d\n","Veliko slovo",vrednost,vrednost);
vrednost='a';
printf("%s\nkarakter=%3c\nvrednost=%3d\n","Malo slovo",vrednost,vrednost); }

//PROGRAM 7.
//Unos i tampanje karaktera

#include <stdio.h>
void main()
{
int c1, c2;
c1 = getchar();
printf("------------\n");
c2 = getchar();

3
printf("c1 = %d, c2 = %d\n",c1, c2);
printf("c1 = %c, c2 = %c\n",c1, c2);
putchar(c1); /* isto je kao i printf("%c",c1); */
putchar(c2); /* isto je kao i printf("%c",c2); */
putchar('\n');
/* Za ispisivanje karaktera a */
putchar('a');
/* dozvoljeno je : printf("abc"); printf("a"); */
/* nedozvoljeno je : printf('a'); putchar('abc'); putchar("abc"); */
}

//PROGRAM 8.
//Program ita jedan karakter i ispisuje ga.
#include <stdio.h>
void main()
{
int c; /* Karakter - obratiti paznju na int */
printf("Unesite jedan proizvoljni karakter:");
c = getchar(); /* cita karakter sa standardnog ulaza */
printf("\nUneli ste karakter:");
putchar(c); /* pise karakter zapamen u promenljivoj c na standardni izlaz */
putchar('\n'); /* prelazak u novi red */
printf("Ispisuje malo a:");
putchar('a'); /* ispisuje malo a */
printf("\nIspisuje ASCI 97:");
putchar(97); /* ekvivalentno prethodnom */
putchar('\n');/* prelazak u novi red */
}

4
//PROGRAM 9.
//Program ita ceo izraz i ispisuje ga.

#include <stdio.h>
int main()
{
char my_string[50];
printf("Otkucaj nesto!\n");
gets(my_string);
printf("Otkucao si:%s\n", my_string);
return 0;
}

//PROGRAM 10.
//Program ita ceo izraz i ispisuje ga pomou funkcija gets i puts.

#include <stdio.h>

int main()
{
char my_string[500];
printf("Otkucaj nesto!\n");
gets(my_string);
printf("Otkucao si:\n");
puts(my_string);
return 0;
}

5
//PROGRAM 11.
//Unos i tampanje karaktera
Program uitava broj karaktera sa ulaza sve dok se ne otkuca znak za kraj unosa EOF. EOF
se moe generisati kucanjem Control /Z.

#include <stdio.h>
main()
{ int ch, i = 0;

while((ch = getchar()) != EOF)


i ++;
printf("%d\n", i);
}

//PROGRAM 12.
//Unos i tampanje niza karaktera
/*Program koristi getchar da uita liniju sa standardnog ulaza
stdin, postabvlja takav ulaz u buffer, onda zavrava string pre
tampanja linije na ekranu. */

#include <stdio.h>
void main( void )
{
char buffer[81];
int i, ch;
printf( "Enter a line: " );
/* Read in single line from "stdin": */
for( i = 0; (i < 80) && ((ch = getchar()) != EOF)
&& (ch != '\n'); i++ )
buffer[i] = (char)ch;
/* Terminate string with null character: */
buffer[i] = '\0';
printf( "%s\n", buffer );
}

6
//PROGRAM 13.
//Unos i tampanje karaktera
Program konvertuje ulazne karaktere u velika slova. Da bi ovo uinili moramo dodati
funkciju toupper iz biblioteke za konverziju karaktera ctype.h

#include <ctype.h> /* For definition of toupper */


#include <stdio.h> /* For definition of getchar, putchar, EOF */

void main()
{ int ch;
while((ch = getchar()) != EOF)
putchar(toupper(ch));
}

//PROGRAM 14.

//Unos i tampanje karaktera

Program koji koristi gets i puts to double space typed input.

#include <stdio.h>

void main()
{ char line[256]; /* Definie string duine 256 karaktera koji se pamti kao ulazna linija */

while(gets(line) != NULL) /* itanje linije */


{ puts(line); /* Print linije */
printf("\n"); /* Print prazne linije */
}
}

7
//PROGRAM 15.
//Unos i tampanje karaktera

//Proghram stanpa broj karaktera pre ispisivanja linije:


#include<stdio.h>
void main( ) {
int n;
char line[100];
n = 0;
while( (line[n++]=getchar( )) != '\n' );
line[n] = '\0';
printf("%d:\t%s", n, line);
}

//PROGRAM 15.
//Unos i tampanje karaktera

#include <stdio.h>
#include <string.h>
main()
{char linija_teksta[81];
while( fgets(linija_teksta,81, stdin)!= NULL)
/* Unos u liniju teksta se prekida i petlja sa kontrolnim karakterom Ctrl/z */
{continue;}
printf("Linija je : %s\n",linija_teksta);}

8
//PROGRAM 17.

//Unos i tampanje karaktera

/*(Funkcije getchar(), putchar() ) NCP koji sadraj standardnog ulaza tampa znak po znak
na standardni izlaz sve do markera kraja ulaza.*/

#include <stdio.h>
main()
{ int znak;
znak=getchar(); /*promenljivoj znak se dodeljuje znak sa ulaza */
while( znak !=EOF) //End of file Ctrl/Z
{ putchar(znak); /*dodeljeni znak se kopira na izlaz */
znak=getchar(); } }

//PROGRAM 18.

//Unos i tampanje karaktera


/*. NCP koji e ispisati na standardni izlaz ukupan broj karaktera standardnog ulaza do
markera kraja, kao i broj prelazaka u novi red. Pretpostaviti da je za ukupan broj karaktera
(zajedno sa enter i blanko) i ukupan broj prelazaka u novi red dovoljan opseg long
promenljivih. */

#include <stdio.h>
void main()
{
int znak; /*prihvata znak sa ulaza */
long linije=0 ; /*brojac linija */
long br_znak=0; /*brojac znakova na ulazu */
while ( (znak=getchar() ) != EOF)
{ br_znak++;
if (znak=='\n') linije ++;
}
printf("Prelazaka u novi red: %ld, karaktera: %ld \n",linije,br_znak);
}

9
//PROGRAM 19.

//Unos i tampanje karaktera

//Testira duzinu i jednakost dva stringa


#include <stdio.h>
#include <string.h>
void main()
{
char a[3], b[3],ch[3];
int i=0;
printf("Unesi priozvoljan tekst; Unesi # za izlaz!\n");
ch[i]=getchar();
while(ch[i]!='#')//izlazak iz petlje kada je uneto #
{putchar(ch[i]);i=i+1;//ispisuje trenutno uneti karakter direktno na izlaz
ch[i]=getchar();}
printf("\nNiz ch je: %s, kojih ima ukupno %d\n",ch,i) ;
strcpy(a, "abc");//kopiranje niza karaktera u vektor a
strcpy(b, "abc");//kopiranje niza karaktera u vektor b
printf("Ovako izgleda a niz:%s\n",a) ;
printf("Ovako izgleda b niz:%s\n",b) ;
printf("Ovako izgleda clan a[0] niza:%c\n", a[0]);
printf("Ovako izgleda clan a[1] niza:%c\n", a[1]);
printf("\nDuzina izraza a po broju karaktera je:%d\n",strlen(a)) ;//izracunavanje duzine
niza
printf("\nDuzina izraza b po broju karaktera je:%d\n",strlen(b)) ;//izracunavanje duzine
niza
if (strcmp(a,b) == 0) //komparacija-uporedjivanje dva niza
{ printf("Ovo su jednaki NIZOVI!\n") ;}
else
printf("Ovo nisu jednaki NIZOVI!\n");
}

10
//PROGRAM 20.
//Unos i tampanje karaktera

//Program za prikazivanje tablice ASCII kodova:

#include <stdio.h>
main()
{
char c=' ';
int i;
printf ("\t\tTablica ASCII kodova \n \n");
linija:
i=0;
znak:
printf("%3d %c ",c+i,c+i);
i=i+19;
if (i<95) goto znak;
printf("\n");
c=c+1;
if (c<' '+19) goto linija;
}

//PROGRAM 21.

//NCP koji pronalazi najduzu liniju sa ulaza. Nije poznat ukupan broj linija, ali svaka linija
nema vise od 80 karaktera ( izlaz CTRL/Z).

#include <stdio.h>
#include <string.h>
#define MAX_DUZINA_LINIJE 81

main()

11
{
char linija[MAX_DUZINA_LINIJE];
char najduza_linija[MAX_DUZINA_LINIJE];
int duzina_linije = 0;
int duzina_najduze_linije = 0;
najduza_linija[0] = '\0';
while( fgets(linija, MAX_DUZINA_LINIJE, stdin) != NULL)
{
duzina_linije=strlen(linija);
if (duzina_linije>duzina_najduze_linije)
{strcpy(najduza_linija, linija);
duzina_najduze_linije = duzina_linije;}
}
printf("Najduza linija je : %s\n",najduza_linija);
}

//PROGRAM 22.

// NCP koji stampa liniju sa ulaza pod uslovom da linija nema vise od 80 karaktera.

#include <stdio.h>
void main( void )
{
char buffer[81];
int i, ch;

printf( "Unesi liniju teksta: " );

/* Citanje linije karaktera sa standardnog "stdin": */


for( i = 0; (i < 80) && ((ch = getchar()) != EOF)
&& (ch != '\n'); i++ )
buffer[i] = (char)ch;

/* String se terminira sa NULL karakterom: */


buffer[i] = '\0';
printf( "%s\n", buffer );
}

12
//PROGRAM 23.

//NCP koji stampa liniju konstantnog niza karaktera.


#include <stdio.h>
void main( void )
{
char buffer[81];
int i, ch;
printf( " Unesi liniju teksta: " );

/* Citanje linije karaktera sa standardnog "stdin": */


for( i = 0; (i < 80) && ((ch = getchar()) != EOF)
&& (ch != '\n'); i++ )
buffer[i] = (char)ch;
/* String se terminira sa NULL karakterom: */
buffer[i] = '\0';
printf( "%s\n", buffer );
}

//PROGRAM 24.

/*Uraditi program za unos niza karaktera Moram da poloim drugi kolokvijum iz Programskih
jezika 1 u vektor Niz1. Odtampati ovaj niz karaktera u potpunoj formi, i izraunati duinu ovog
unetog niza. Iskopirati sadraj vektora Niz1 u vektror Niz2 i utvrditi dali su to isti nizovi.
Prebrojati koliko praznina (blanko karaktera) ima u nizu Niz1.*/

#include <stdio.h>
#include <string.h>
void main()
{ int brojznak=0,i=0;
char Niz1[81],Niz2[81];
printf("Unesi clanove niza Niz1, za kraj Ctrl/z/");
while( fgets(Niz1,81, stdin)!= NULL)
/* Unos u liniju teksta se prekida i petlja sa kontrolnim karakterom Ctrl/z */
{continue;}
printf("Linija niza Niz1 je : %s\n",Niz1);
printf("\nDuzina niza po broju karaktera je:%d\n",(strlen(Niz1)-1));
strcpy(Niz2,Niz1);
printf("Linija niza Niz2 je : %s\n",Niz2);

13
if (strcmp(Niz1,Niz2)==0)//Komparacija-uporedjivanje dva niza
{ printf("Ovo su jednaki NIZOVI!\n");}
else
printf("Ovo nisu jednaki NIZOVI!\n");
while (Niz1[i]!='\n')
{ if(Niz1[i]==' ')brojznak++;i=i+1;}
printf("Broj blanko znakova u nizu Niz1 je:%ld \n",brojznak); }

//PROGRAM 25.

/*Sastaviti program koji iz skupa unetih karaktera ( naPRIMER: reenice Ja sam rodjen
1990. god u 12. mesecu, i u petak!!izraunava broj unetih slova, brojeva i ostalih
karaktera.*/

#include<stdio.h>
#include<conio.h>
main( )
{
int slovo, broj, ostalo, c;
slovo = broj = ostalo = 0;
while( (c=getchar( )) != EOF )
if( ('A'<=c && c<='Z') || ('a'<=c && c<='z') )
++ slovo;
else if( '0'<=c && c<='9' ) ++broj;
else ++ostalo;
printf("Uneli ste:%d slova, %d brojeva,%d ostalih\n", slovo, broj, ostalo);
}

//PROGRAM 26.
//Formatiranje izlaza

14
#include <stdio.h>
#define IME "Srbija"
#define ADRESA "Ul. Beogradska 20."
#define MESTO "18000 Nis"
#define LIMIT 65
void main()
{void zvezde(void);/*deklaracija funkcije bez argumenata*/
zvezde(); /*poziv korisnicke funkcije */
printf("%s \n ",IME) ; /*poziv funkcije iz standardne biblioteke*/
printf("%s\n", ADRESA);
printf("%s\n", MESTO) ;
zvezde ( ) ;} /*definicija korisnicke funkcije */
void zvezde() /*funkcija nema argumenata*/
{ int brojac;
for(brojac=l;brojac<=LIMIT;brojac++)
putchar ( '*' );
putchar ( '\n' ) ; }

//PROGRAM 27.

//Program koji kopira ulaz svakog karaktera direktno na izlaz. `%' oznaava kraj ulaza.

#include <stdio.h>
void main( ) {
char c;
while( (c=getchar( )) != '%' )
putchar(c);
}

15
//PROGRAM 28.
//Program konvertuje velika u mala slova
#include <stdio.h>
void main( ) {
char c;
while( (c=getchar( )) != '%' )
if( 'A'<=c && c<='Z' )
putchar(c+'a'-'A');
else
putchar(c);
}

//PROGRAM 29.
//Program broji karaktere, brojeve i praznine u tekstu. Zavrava se unosom %.
#include <stdio.h>
void main( ) {
int let, dig, other, c;
let = dig = other = 0;
while( (c=getchar( )) != '%' )
if( ('A'<=c && c<='Z') || ('a'<=c && c<='z') )
++let;
else if( '0'<=c && c<='9' ) ++dig;
else ++other;
printf("%d slova, %d broja, %d ostalih karaktera\n", let, dig, other);

16
//PROGRAM 30.
//Izraunavanje duine zapisanog stringa, IZLAZ ENTER.

#include <stdio.h>
void main( ) {
int n, c;
char line[100];
n = 0;
while( (c=getchar( )) != '\n' ) {
if( n < 100 )
line[n] = c;
n++;
}
printf("duzina stringe je: = %d\n", n);
}

//PROGRAM 31.
//Duina stringa sa izlazom ENTER

void main( ) {
int n;
char line[100];
n = 0;
while( (line[n++]=getchar( )) != '\n' );// Karakter \n kao ENTER za kraj
line[n] = '\0';
printf("Duzine stringa je %d:\t%s", n, line);
}

17
OPTI ZADACI

/* 2.1 MINIMUM TRI CELA BROJA */

#include<stdio.h>
#include<math.h>
void main()
{int a,b,c,m;
printf("\nUnesite vrednosti za a , b i c\n");
scanf("%d%d%d",&a,&b,&c);
m=a;
if(b<m) m=b;
if(c<m) m=c;
printf("Minimum brojeva a=%d b=%d i c=%d je broj %d\n",a,b,c,m);}

/* 2.2 Program za odredjivanje da li je godina prestupna ili nije*/


#include<stdio.h>
#include<math.h>
void main()
{
int godina,ost_4,ost_100,ost_400;
printf("Ukucajte godinu ? ");
scanf("%d", &godina);
ost_4=godina%4;
ost_100=godina%100;
ost_400=godina%400;
if (ost_4 ==0 && ost_100 != 0 || ost_400== 0)
printf("Godina %d je prestupna\n", godina);
else
printf("Godina %d nije prestupna\n", godina);
}

18
/2.3* Program za permutovanje cifara
nenegativriog celog broja - do-while iskaz */

#include<stdio.h>
#include<math.h>
void main()
{int broj;
printf("Ukucajte ceo broj ? ");
scanf("%d", &broj );
printf("Permutovani broj je ");
do
{printf("%d", broj%10);
broj =broj/10;}
while (broj);
printf("\n"); }

/2.4* Program za odredjivanje srednje vrednosti n celih pozitivnih brojeva -for iskaz */
#include<stdio.h>
#include<math.h>
void main()
{
int n,brojac;
float suma =0, x ;
printf("Ukupno brojeva ? ");
scanf("%d", &n);
for (brojac=1 ; brojac<=n; ++brojac, suma+=x )
{
printf("Ukucajte %d broj ?",brojac);
scanf("%f",&x);
}
printf("Srednja vrednost ovih brojeva je %f\n", suma/n);
}

19
/2.5* Program za izracunavanje faktorijela */

#include <stdio.h>
#include <math.h>
void main()
{
int i, n;
long fak = 1;
printf("lzracunavanje n!\nUkucajte broj ? ");
scanf("%d", &n);
for ( i=1; i<=n; ++i)
fak *= i;
printf("%d! = %ld\n", n, fak);
}

/2.6* Program za izracunavanje prostih aritmetickih izraza


u formi operand1 operator operand2 */

#include <stdio.h>
#include <math.h>
void main()
{
float operand1, operand2;
char op;
printf("Ukucajle lzraz ? \n");
scanf("%f%c%f", &operand1, &op, &operand2);
switch (op)
{
case '+':
printf("%f\n", operand1+operand2);
break;
case '-':
printf("%f\n", operand1-operand2 );

20
break;
case '*':
printf("%f\n", operand1*operand2 );
break;
case '/':
printf("%f\n", operand1/operand2);
break;
default:
printf("Nepoznat operator\n");
}}

Odredjivanje u ulaznom tekstu broja praznih karaktera, kao i broja


/2.7
znakova: tacka, zarez, dvotacka i tacka-zarez (naredbe switch i break)
- za izlaz CTRL/Z/

#include <stdio.h>
void main( )
{ int c, prazno=0, interp=0;
while((c=getchar())!=EOF)
switch(c)
{ case ' ':
prazno++;
break;
case '.':
case ',':
case ':':
case ';':
interp++;
break;
default:
break; }
printf("\nBroj praznina: %d", prazno);
printf("\nBroj znakova tacka, zarez, dvotacka i tacka-zarez: %d\n", interp); }

//2.8 tampanje elemenata matrice

21
#include<stdio.h>
#include<math.h>
void main()
{
static int mat[2][3]={{0,1,2},{3,4,5}};
int i,j;
for(i=1;i<=2;++i)
{
printf("Elementi %d.reda su:\n",i);
for(j=1;j<=3;++j)
printf("kolona%d:%d\n",j,mat[i-1][j-1]);
}
printf("\n");
}

2.9 Neka je data kvadratna matrica u formatu:

1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
lanove matrice uneti u program kao konstantne celobrojne veliine, a kao izlaz iz
programa predvideti tampanje ove matrice u pokazanom formatu kao polazne matrice i
tampanje nove matrice u istom obliku ali iji su svi lanovi sada pomnoeni skalarom 2.

/* 1 STAMPANJE CLANOVA MATRICE I CLANOVA MATRICE POMNOZENE


SKALAROM*/
#include<stdio.h>
#include<math.h>
void main()
{int mat[4][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
int i,j;
printf("\nPolazna matrica je\n");
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{printf("%2d ",mat[i][j]);}printf("\n");}
printf("\nNova matrica je\n");
for(i=0;i<4;i++)

22
{
for(j=0;j<4;j++)
{printf("%2d ",2*mat[i][j]);}printf("\n");}}

2.10 Neka je data kvadratna matrica u formatu:

1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
lanove matrice uneti u program kao konstantne celobrojne veliine, a kao izlaz iz
programa predvideti tampanje ove matrice u pokazanom formatu kao polazne matrice i
tampanje nove matrice u istom obliku ali sada unazad od lana a44,a43,a42a41,......,a11.

/* 2 STAMPANJE CLANOVA MATRICE I CLANOVA MATRICE UNAZAD*/


#include<stdio.h>
#include<math.h>
void main()
{int mat[4][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
int i,j;
printf("\nPolazna matrica je\n");
for(i=0;i<4; i++)
{
for(j=0;j<4; j++)
{printf("%2d ",mat[i][j]);}printf("\n");}
printf("\nNova matrica je\n");
for(i=3;i>=0; i--)
{
for(j=3;j>=0; j--)
{printf("%2d ",mat[i][j]);}printf("\n");}}

23
2.11 Napisati program na C++ jeziku koji izraunava sumu svih elemenata u svakom redu
pojedinano, pravougaone matrice [4x4].

1 2 3 4
5 6 7 8
A=
9 10 11 12
13 14 15 16

#include<stdio.h>
#include<math.h>
void main()
{int mat[4][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
int i,j,s=0;
printf("\nPolazna matrica je\n");
for(i=0;i<4; i++)
{
for(j=0;j<4; j++)
{printf("%2d ",mat[i][j]);}printf("\n");}

for(i=0;i<4; i++)
{printf("\nSuma %d reda je:",i+1);
for(j=0;j<4; j++)

{s=s+mat[i][j];}
printf("%2d\n",s);s=0;}
return 0;}

24
2.12 NCP koji sa standardnog ulaza uitava 3x3 matricu i ispisuje je na standardni izlaz tako
da centralno polje a[1][1] bude jednako sumi gornjeg levog (a[0][0]) i donjeg desnog polja
(a[2][2]). Pre ucitavanja popuniti matricu proizvoljnim vrednostima.

#include <stdio.h>
void main()
{
int a[3][3] = {{0, 1, 2}, {10, 11, 12}, {20, 21, 22}}; /* deklaracija i inicijalizacija matrice a, moe
se uraditi za konkretan primer date matrice*/
int i, j; /*brojaci u ciklusu */
/* unos elemenata matrice */
for(i=0; i<3; i++)
for(j=0; j<3; j++)
{
printf("\na[%d][%d] = ", i, j);
scanf("%d", &a[i][j]);
}
printf("\n*******************\n");
a[1][1] = a[0][0] + a[2][2]; /* 0 + 22 = 22 */
/*ispis matrice */
for(i=0; i<3; i++)
{
for(j=0; j<3; j++) printf("%d\t", a[i][j]);
printf("\n");
}
}

25
2.13 Neka je data kvadratna matrica u formatu:
a11 a12 a13
a 21 a 22 a 23
a31 a32 a33
Uneti lanove matrice u program kao celobrojne veliine, a kao izlaz iz programa
predvideti tampanje takve matrice u pokazanom formatu kao i tampanje izraunate
vrednosti njene determinante uraene preko funkcije.

#include<stdio.h>
#include<math.h>
#include<iomanip.h>
main()
{static int mat[4][4];
int i,j;
float delta;
printf("Unesite proizvoljne elemente pravougle matrice:\n");
for(i=0;i<4;++i)
for(j=0;j<4;++j)
{printf("a[%d][%d]=",i,j);
scanf("%d",&mat[i][j]);printf("\n");}
printf("\nPolazna matrica je\n");
for(i=0;i<4;++i)
{for(j=0;j<4;++j)
printf("%3d ",mat[i][j]);printf("\n");}
printf("\nDeterminanta sistema je:\n");
delta=mat[0][0]*((mat[1][1]*mat[2][2]*mat[3][3]

26
+mat[1][2]*mat[2][3]*mat[3][1]
+mat[2][1]*mat[3][2]*mat[1][3])
-(mat[1][3]*mat[2][2]*mat[3][1]
+mat[1][1]*mat[2][3]*mat[3][2]
+mat[1][2]*mat[2][1]*mat[3][3]))-
mat[0][1]*((mat[1][0]*mat[2][2]*mat[3][3]
+mat[1][2]*mat[2][3]*mat[3][0]
+mat[2][0]*mat[3][2]*mat[1][3])
-(mat[1][3]*mat[2][2]*mat[3][0]
+mat[1][0]*mat[2][3]*mat[3][2]
+mat[1][2]*mat[2][0]*mat[3][3]))+
mat[0][2]*((mat[1][0]*mat[2][1]*mat[3][3]
+mat[1][3]*mat[2][0]*mat[3][1]
+mat[2][0]*mat[3][1]*mat[1][3])
-(mat[1][3]*mat[2][1]*mat[3][0]
+mat[3][1]*mat[2][3]*mat[1][0]
+mat[1][1]*mat[2][0]*mat[3][3]))-
mat[0][3]*((mat[1][0]*mat[2][1]*mat[3][2]
+mat[1][1]*mat[2][2]*mat[3][0]
+mat[2][0]*mat[3][1]*mat[1][2])
-(mat[1][2]*mat[2][1]*mat[3][0]
+mat[3][1]*mat[2][2]*mat[1][0]
+mat[1][1]*mat[2][0]*mat[3][2]));
printf("Vrednost determinante je :%f",delta);
return 0;}

2.14 Sastaviti program za izraunavanje sume:


n
S= i!
i =1

27
Napomena: radi se o integer veliinama ali voditi rauna da ne doe do preoptereenja
memorije!

#include<stdio.h>
#include<math.h>
main()
{int i,n;
float F=1,S=1;
printf("Unesite verdnost za n\n n=");
scanf("%d",&n);
for(i=2;i<=n;i++)
{F=F*i;
S=S*F;};
printf("\nRezultat proizvoda i! je S=%lf\n",S);
return 0;}

2.15 Napisati program za nalaenje proizvoda prva 3 sluajna broja.

#include <stdlib.h>
#include <stdio.h>

int main(void)
{
int i,R;
long int P=1;
printf("Tri slucajna broja od 0 do 99 su:\n\n");
for(i=0; i<3; i++)
{R= rand()% 100;
printf("%d\n",R );
P=R*P;}
printf("Proizvod prva 3 slucajna broja je: %d\n", P);
return 0;
}

28
2.16 U sledeem primeru uitavaju se dva broja i jedan znak koji predstavlja izbor njihovog
odnosa (< manje, > vee, = jednako ). U zavisnosti od uitanog znaka ispituje se jedan
od tri odnosa za poreenje ova dva broja. Ako je odnos taan tampati poruku "Izabrali smo
pravi odnos brojeva a i b", a ako nije "Izabrali smo pogresan odnos brojeva a i b". U
sluaju da se unese pogrean znak za poreenje tampati poruku "Nedopusteni znak za odnos
brojeva!" .
#include <stdio.h>
int main(void)
{
float a,b;
char operacija;
printf("Upisati prvi broj: ");
scanf(" %f",&a);
printf("Upisati drugi broj: ");
scanf(" %f",&b);
printf("Upisati operaciju: zbir(z), oduzimanje(o),\n");
printf(" mnozenje(m),deljenje(d) :");
scanf(" %c",&operacija);
if(operacija=='z')
printf("%f\n",a+b);
else if(operacija=='o')
printf("%f\n",a-b);
else if(operacija=='m')
printf("%f\n",a*b);
else if(operacija=='d')
printf("%f\n",a/b);
else
printf("Nedopustena operacija!\n");
return 0;
}

2.17 Sastaviti program na C jeziku za izraunavanje povrine trougla po obrascu


a+b+c
PTROUGLA = p ( p a )( p b)( p c) gde je p =
2

#include<stdio.h>
#include <stdio.h>
#include <math.h>

float main(void)
{
float a,b,c,p,PTROUGLA;

29
printf("Upisati broj a: ");
scanf(" %f",&a);
printf("Upisati broj b: ");
scanf(" %f",&b);
printf("Upisati broj c: ");
scanf(" %f",&c);
p=(a+b+c)/2.;
printf("Vrednost prolazne promenljive je:%f\n",p);
PTROUGLA=sqrt(p*(p-a)*(p-b)*(p-c));
printf("Povrsina trougla izracunata datim obrascem je:%f\n",PTROUGLA);
return 0;
}

2.18 U sledeem primeru uitavaju se dva broja i jedan znak koji predstavlja izbor njihovog
odnosa (< manje, > vee, = jednako ). U zavisnosti od uitanog znaka ispituje se jedan
od tri odnosa za poreenje ova dva broja. Ako je odnos taan tampati poruku "Izabrali smo
pravi odnos brojeva a i b", a ako nije "Izabrali smo pogresan odnos brojeva a i b". U
sluaju da se unese pogrean znak za poreenje tampati poruku "Nedopusteni znak za odnos
brojeva!" .
#include<stdio.h>
#include <stdio.h>
int main(void)
{
float a,b;
char znak;
printf("Upisati prvi broj: ");
scanf(" %f",&a);
printf("Upisati drugi broj: ");
scanf(" %f",&b);
printf("Upisati znak poredjenja: manje <, vece >,\n");
printf(" jednako = :");
scanf(" %c",&znak);
if(znak=='<')
{if(a<b) printf("Izabrali smo pravi odnos brojeva a i b\n");
else printf("Izabrali smo pogresan odnos brojeva a i b\n");}
else if(znak=='>')
{if(a>b) printf("Izabrali smo pravi odnos brojeva a i b\n");
else printf("Izabrali smo pogresan odnos brojeva a i b\n");}
else if(znak=='=')
{if(a==b) printf("Izabrali smo pravi odnos brojeva a i b\n");

30
else printf("Izabrali smo pogresan odnos brojeva a i b\n");}
else
{printf("Nedopusteni znak za odnos brojeva!\n");}
return 0;
}

FUNKCIJE
1. Pokazati kako funkcionie prototip funkcije.

#include<stdio.h>
myfunc();/*inicijalizacija funkcije bez argumenata*/
void main()
{
myfunc();/*pozivanje funkcije bez argumenata*/
}
myfunc()/*definisanje funkcije bez argumenata*/
{
printf("ZDRAVO, ovo je test\n");
return 0;}

2. Korienje prototipa funkcije sa argumentom.

31
#include<stdio.h>
napisi(int count);
void main()
{napisi(4);}
napisi(int count)
{
int c;
for(c=0;c<count;c++)
printf("\nZDRAVO");
return 0;}

3. Test funkcije

#include<stdio.h>
test();
void main()
{
printf("Ulazimo unutar test funkcije\n");
test();
printf("\nVracamo se iz test funkcije\n");
}
test()
{
int a,b;a=100;
b=a+100;
printf("a je %d i b je %d",a,b);
return 0;}

4. Nai minimum od dva cela broja. U glavnom programu obezbediti tampanje, a u funkciji
njihovo poreenje.

#include<stdio.h>
int imin(int n,int m);
void main()/* glavni program */
{ int broj1,broj2,vrati;
printf("Unesite dva cela broja\n");

32
vrati=scanf("%d %d",&broj1,&broj2);
if(vrati==2)
printf("Manji od %d i %d je %d\n",broj1,broj2,imin(broj1,broj2));}

int imin(int n,int m)/* potprogram */


{
int min;
if (n<m)
min=n;
else
min=m;
return min;
}

5. Isti kao 4. samo na drugi nain.

#include<stdio.h>
int min(int a, int b);
main()
{
int m;
m=min(3,6);
printf("Minimum je %d\n",m);
return 0;
}

int min(int a, int b)


{
if(a<b)
return a;
else
return b;
}

33
6. Formiranje zbira preko funkcije

#include <iostream.h>

int Add (int x, int y);


int main()
{
cout << "Ja sam u main()!\n";
int a, b, c;
cout << "Unesite dva broja: ";
cin >> a;
cin >> b;
cout << "\nPozivam Add()\n";
c=Add(a,b);
cout << "\nNazad u main().\n";
cout << "c ima vrednost " << c;
cout << "\nIzlazim....\n\n";
return 0;
}

int Add (int x, int y)


{
cout << "U Add(), preuzimam " << x << " i " << y << "\n";
return (x+y); }

7.Uraditi meni sa izborom operacija za sabiranje, oduzimanje i mnoenje dva cela realna
broja. U funkciji izvesti opisane raunske radnje.

#include<stdio.h>
#include<stdlib.h>
add();
subtract();
multiply();
void main()
{
int choice;
while(1)
{
printf("\n\nMenu:\n");

34
printf("1- Add\n2- Subtract\n");
printf("3- Multiply\n4- Exit");
printf("\n\nYour choice -> ");
scanf("%d",&choice);
switch(choice)
{ case 1 : add();
break;
case 2 : subtract();
break;
case 3 : multiply();
break;
case 4 : printf("\nProgram Ends. !");
exit(0);
default:
printf("\nInvalid choice");

}
}
}

add()
{
float a,b;
printf("\nEnter a:");
scanf("%f",&a);
printf("\nEnter b:");
scanf("%f",&b);
printf("a+b=%f",a+b);
return 0;}

subtract()
{
float a,b;
printf("\nEnter a:");
scanf("%f",&a);
printf("\nEnter b:");
scanf("%f",&b);
printf("a-b=%f",a-b);
return 0;}

multiply()
{
float a,b;
printf("\nEnter a:");
scanf("%f",&a);
printf("\nEnter b:");
scanf("%f",&b);
printf("a*b=%f",a*b);
return 0;}

35
8. Pozivanje funkcije po vrednosti

/*Pozivanje po vrednosti*/
#include<stdio.h>
void test(int a);
main()
{
int m;
m=2;
printf("\nM je %d",m);
test(m);
printf("\nM je %d",m);
return 0;
}

void test(int a)
{
a=5;}

9.MNOZENJE I SABIRANJE DVA REALNA BROJA PREKO FUNKCIJE

#include<stdio.h>
#include<math.h>
mno();
sab();

36
void main()
{ mno();
sab();}

mno()
{float a,b;
printf("\nUnesite vrednosti za a i b\n");
scanf("%f%f",&a,&b);
printf("a*b=%f",a*b);
return 0;}

sab()
{float a,b;
printf("\nUnesite vrednosti za a i b\n");
scanf("%f%f",&a,&b);
printf("a+b=%f",a+b);
return 0;}

10. MINIMUM TRI CELA BROJA PREKO FUNKCIJE

#include<stdio.h>
#include<math.h>
min();
void main()
{ min();}

min()
{int a,b,c,m;
printf("\nUnesite vrednosti za a , b i c\n");
scanf("%d%d%d",&a,&b,&c);
m=a;
if(b<m) m=b;
if(c<m) m=c;
printf("Minimum brojeva a=%d b=%d i c=%d je broj %d\n",a,b,c,m);
return 0;}

37
11.Poziv funkcije salje vrednost promenljive m funkciji a ne salje promenljivu samu sebi:
m=2, M=2

/*Pozivanje po referenci*/
#include<stdio.h>
void test(int *ptr);
main()
{
int m;
m=2;
printf("\nM je %d",m);
test(&m);
printf("\nM je %d",m);
return 0;
}

void test(int *ptr)


{
*ptr=5;
}
/*Poziv funkcije salje vrednost promenljive m po referenci: m=2, M=5*/

12. Suma kvadrata celih brojeva od 1 do N preko funkcije

/*Program za izracunavanje sume


kvadrata celih brojeva od 1 do n*/
#include <stdio.h>
#include <math.h>
suma_kvadrata(int n);

void main( )
{

38
suma_kvadrata(10);
suma_kvadrata(15);
suma_kvadrata(20);
}

suma_kvadrata(int n) /*f ja za izracunavanje*/


/*sume kvadrata*/
{
int i;
long suma=0;
for (i=1; i<=n; suma+=(long)i*i, ++i);
printf("Suma kvadrata od 1 do %d je %ld\n", n, suma);
return 0;}

13. Napisati program za reavanje kvadratne j-ne ax2+bx+c=0.

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
void main()
{
float delta,a,b,c,x1,x2;

printf("Enter a : ");
scanf("%f",&a);
printf("Enter b : ");
scanf("%f",&b);
printf("Enter c : ");
scanf("%f",&c);
delta=b*b-(4*a*c);
if(delta<0)
{
printf("Jednacina NEMA resenja !\n");
exit(0);//Potrebna hederska funkcija stdlib
}
if(delta==0)
{
x1=-b/(2*a);
printf("Jednacina IMA dva ista resenja !\n");
printf("x1=x2=%f",x1);
exit(0);
}

39
x1=(-b+sqrt(delta))/(2*a);
x2=(-b-sqrt(delta))/(2*a);
printf("\nX1=%f",x1);
printf("\nX2=%f\n",x2);
}

14. F-ja ne vraca nikakvu vrednost


#include<stdio.h>
void ispis(int i1, int i2, int i3); /* F-ja ne vraca nikakvu vrednost*/
main()
{
int a,b,c;
a=b=c=1;
ispis(a,b,c);
a=b=c=2;
ispis(a,b,c);
return 0;}

void ispis(int i1, int i2, int i3)


{
printf("Vrednost promenljive param1 je %d.\n",i1);
printf("Vrednost promenljive param2 je %d.\n",i2);
printf("Vrednost promenljive param3 je %d.\n",i3);
}

15. Poziv funkcije bez argumenta

#include <stdio.h>
#define IME "VTS"
#define ADRESA "Ul. Generala Medvedeva 20."
#define MESTO "18000 Nis"
#define LIMIT 65

40
void zvezde();
void main()
{ void zvezde(); /*deklaracija funkcije bez argumenata*/
zvezde(); /*poziv korisnicke funkcije */
printf("%s \n ", IME) ; /*poziv funkcije iz standardne biblioteke*/
printf("%s\n", ADRESA);
printf("%s\n", MESTO) ;
zvezde ( ) ; }
/*definicija korisnicke funkcije */
void zvezde() /*funkcija nema argumenata*/
{ int brojac;
for(brojac=1;brojac<=LIMIT;brojac++)
putchar ( '*' );
putchar ( '\n' ) ; }

16. Primer kada program poziva dve funkcije


#include<stdio.h>
#include<math.h>
void Hipotenuza(void);// funkcijski prototipovi
void Ucitaj(void); //funkcijski prototipovi
double a,b,c;/* deklaracija globalne promenljive, pre pocetka programa*/
void main()
{ Ucitaj();
Hipotenuza();
printf("nHipotenuza je %f.",c);}

void Hipotenuza(void)
{c=sqrt(a*a+b*b);}

void Ucitaj(void)
{printf("Prva kateta:");
scanf("%lf",&a);
printf("Druga kateta:");
scanf("%lf",&b);}

41
17. Primer za izracunavanje y=sin2(x)+cos2(x)
#include<stdio.h>
#include<math.h>
double Funkcija(double x);
void main()
{double x,y;/* deklaracija lokalnih promenljivih, posle pocetka programa*/
printf("Unesite vrednost za x:");
scanf("%lf",&x);
y=Funkcija(x);
printf("Vrednost funkcije je %f.",y);}
double Funkcija(double x)
{double y;
y=sin(x)*sin(x)+cos(x)*cos(x);
return y;}

18. Izracunavanje povrsine trougla sa dve funkcije


#include<stdio.h>
#include<math.h>
void Povrsina(void);
void Ucitaj(void);
double a,b,c,p,pt;/* deklaracija globalne promenljive, pre pocetka programa*/
void main()
{Ucitaj();
Povrsina();
printf("/nPovrsina trougla je %f.",pt);}
void Povrsina(void)
{p=(a+b+c)/2;
pt=sqrt(p*(p-a)*(p-b)*(p-c));}
void Ucitaj(void)
{printf("Prva kateta:");
scanf("%lf",&a);
printf("Druga kateta:");
scanf("%lf",&b);
printf("Treca kateta:");
scanf("%lf",&c);}

42
19. Neka je data kvadratna matrica u formatu:

a11 a12 a13 a14


a 21 a 22 a 23 a 24
a31 a32 a 33 a34
a 41 a 42 a 43 a 44
Uneti lanove matrice u program kao celobrojne veliine, a kao izlaz iz programa
predvideti tampanje takve matrice u pokazanom formatu kao i tampanje izraunate
vrednosti njene dijagonale a11*a22*a33*a44 uraene preko funkcije.
#include<stdio.h>
#include<math.h>
#include<iomanip.h>
main()
{static int mat[4][4];
int i,j;
float dijagonala;
printf("Unesite proizvoljne elemente pravougle matrice:\n");
for(i=0;i<4;++i)
for(j=0;j<4;++j)
{printf("a[%d][%d]=",i,j);
scanf("%d",&mat[i][j]);printf("\n");}
printf("\nPolazna matrica je\n");
for(i=0;i<4;++i)
{for(j=0;j<4;++j)
printf("%3d ",mat[i][j]);printf("\n");}
dijagonala=mat[0][0]*mat[1][1]*mat[2][2]*mat[3][3];
printf("Vrednost dijagonale je :%f", dijagonala);
return 0;}

43
20.etiri raunske radnje preko funkcije choice i switch naredbi.
#include<stdio.h>
#include<stdlib.h>
void add(void);
void subtract(void);
void multiply(void);
void divide(void);
float a,b,rezultat;
void main()
{int choice;

while(1)
{
printf("\n\nMenu:\n");
printf("1- Add\n2- Subtract\n");
printf("3- Multiply\n4- Divide\n5-Exit");
printf("\n\nYour choice -> ");
scanf("%d",&choice);
switch(choice)
{ case 1 : add();printf("Rezultat operacije je:%f\n",rezultat);
break;
case 2 : subtract();printf("Rezultat operacije je:%f\n",rezultat);
break;
case 3 : multiply();printf("Rezultat operacije je:%f\n",rezultat);
break;
case 4 : divide();printf("Rezultat operacije je:%f\n",rezultat);
break;
case 5 : printf("\nProgram Ends. !");
exit(0);
default:
printf("\nInvalid choice");}
}}
void add(void)
{printf("\nEnter a:");
44
scanf("%f",&a);
printf("\nEnter b:");
scanf("%f",&b);
rezultat=(a+b);}
void subtract(void)
{printf("\nEnter a:");
scanf("%f",&a);
printf("\nEnter b:");
scanf("%f",&b);
rezultat=(a-b);}

void multiply(void)
{printf("\nEnter a:");
scanf("%f",&a);
printf("\nEnter b:");
scanf("%f",&b);
rezultat=(a*b);}

void divide(void)
{printf("\nEnter a:");
scanf("%f",&a);
printf("\nEnter b:");
scanf("%f",&b);
rezultat=(a/b);}

45
PRIMERI PROGRAMA ZA PRIPREMU PRVOG
KOLOKVIJUMA

1. ULAZ - IZLAZ ..................................................................................................................................... 2


2. OPERATORI ...................................................................................................................................... 4
3. IF NAREDBA...................................................................................................................................... 5
4. POMONE FUNKCIJE ........................................................................................................................ 9
5. SWITCH CASE NAREDBA ...............................................................................................................12
6. FOR PETLJA .....................................................................................................................................13
7. WHILE i DO WHILE PETLJE ...............................................................................................................16

1
1. ULAZ - IZLAZ

Zadatak 1: Primer rada sa specijalnim karakterima.


int main(void)
{
printf("Alert: zvucni ili vizuelni signal \a\n");
printf("Alert: NESTO SE CUJE \n");
printf("Alert: PONOVO zvucni ili vizuelni signal \a\n");
printf("Povratnik ili backspace: sakrij me\b \n");
printf("Form feed. \f\n");
printf ("Horizontalni\ttab\n");
return 0;
}

Zadatak 2: Primer poziva funkcije printf:


#include <stdio.h>
void main()
{
float n1=3.0;
double n2=3.0;
long n3=2000000000;
long n4=1234567890;
printf("%.le, %.le, %ld, %ld\n", n1,n2,n3,n4);
printf("%ld, %ld\n", n3, n4);
printf("%f, %f, %ld, %ld\n", n1,n2,n3,n4);
}

Zadatak 3: Zaokruzivanje vrednosti.


#include <stdio.h>
void main()
{
float fvr_pz;
double dvr_pz;
fvr_pz= 123.45;
printf("l. Vrednost u pokretnom zarezu je %f\n", fvr_pz);
fvr_pz /= 3.30;
fvr_pz *= 3.30;
printf("2. Vrednost u pokretnom zarezu je %f\n", fvr_pz);
dvr_pz = 123.45;
printf("l. Vrednost u dvostrukoj preciznosti je %f\n", dvr_pz);
dvr_pz /= 3.30;
dvr_pz *= 3.30;
printf ("2. Vrednost u dvostrukoj preciznosti je %f\n", dvr_pz);
}

2
Zadatak 4: Formatiranje ulaza u pokretnom zarezu
void main()
{
/* deklaracija podataka */
float f_pro;
double d_pro;
/*dodela vrednosti*/
f_pro=106.11;
d_pro=-0.0000654;
/*stampanje vrednosti promenljivih */
printf ("Promenljiva f_pro=%2f\n", f_pro);
printf ("Promenljiva d_pro=%.11f\n", d_pro);
printf ("Promenljiva f_pro=%e\n", f_pro);
printf ("Promenljiva d_pro=%G\n", d_pro) ;
}

Zadatak 5: Obraun kamata u pokretnom zarezu. Kamata se rauna kao glavnica *


(1+kamata/100)period.
#include <stdio.h>
#include <math.h>
void main( )
{
double stopa, period, glavnica;
printf( "Unesite mesecnu kamatnu stopu: " ) ;
scanf( "%lf", &stopa ) ; /* ulaz u pokretnom zarezu */
/* konverzija u procente */
stopa = stopa / 100.0;
printf( "Unesite glavnicu: " );
scanf( "%lf", &glavnica );
printf( "Unesite vreme orocavanja u mesecima: " );
scanf( "%lf", &period ) ;
printf( "Ukamacena vrednost je = %.2f\n",
glavnica * pow( (1.0+stopa), period));
}

3
2. OPERATORI

Zadatak 6: Primer za operatore inkrementa i dekrementa:


void main()
{
int x, y;
x = 10; y =10;
printf("Vrednost izraza ++x je %d\n", ++x);
printf("Vrednost izraza y++ je %d\n", y++);
printf("Nakon inkrementiranja vrednost x je %d\n",x);
printf("Nakon inkrementiranja vrednost y je %d\n\n\n", y);

x = 10; y =10;
printf( "Vrednost izraza --x je %d\n", --x);
printf( "Vrednost izraza y-- je %d\n", y--) ;
printf( "Nakon dekrementiranja vrednost x je %d\n",x);
printf( "Nakon dekrementiranja vrednost y je %d\n", y);
}

Zadatak 7: Primer za relacione izraze i logicke operatore:


void main()
{
int minimum,maximum;
int prl, pr2;
minimum=10;
maximum = 1000;
prl = 110;
pr2 = 1123;
if( (prl < maximum && prl > minimum) || (pr2 < maximum && pr2 > minimum) )
printf( "Najmanje jedna vrednost je u opsegu\n" );
if( (prl < maximum && prl > minimum) && (pr2 < maximum && pr2 > minimum) )
{
printf( "Obe vrednosti su u opsegu\n" ) ;
}
}

Zadatak 8: 43. Reiti funkciju primenom operatora uslovnog izraza:

#include<stdio.h>
void main()
{
int s, broj;
printf("Unesite broj za odredjivanje uslova:");
scanf("%d",&broj);
s=(broj < 0) ? -1 : ((broj==0) ? 0 : 1);
printf("Vrednost izraza za uneti broj %d je s = %d\n",broj,s);
}

4
3. IF NAREDBA

Zadatak 9: Primer IF naredbe:


void main()
{
int x, y;
x = 6;
y = 6;
if ( x = 7)
printf( " Prvi <if> je zadovoljen\n" );
else
printf( " Prvi <if> nije zadovoljen\n" );
if ( y == 7 )
printf( " Drugi <if> je zadovoljen\n" );
else
printf( " Drugi <if> nije zadovoljen\n" );
}

Zadatak 10: Za uneti broj odrediti da li je pozitivan ili negativan.


void main()
{
int n;
printf("Unesi ceo broj: ");
scanf("%d",&n);
if(n>=0)
printf("Broj je pozitivan !\n");
if(n<0)
printf("Broj je negativan !\n");
}
Drugi nain sa if else strukturom :
void main()
{
int n;
printf("Unesi ceo broj: ");
scanf("%d",&n);
if(n>=0)
printf("Broj je pozitivan !\n");
else
printf("Broj je negativan !\n");
}

Zadatak 11: Napisati program sa menijem:


1- Program matematika
2- Program finansija
3- Program zabave
4- Exit
upotrebom if, else if strukture za startovanje svih stavki iz menija. Ukoliko se izabere stavka
u meniju koja ne postoji tampati poruku Pogrean izbor.
#include<stdio.h>
#include<stdlib.h>
void main()
{
int choice;
printf("\n\nMeni:\n");
printf("1- Program matematika\n2- Program finansija\n");
printf("3- Program zabave\n4- Exit");
printf("\n\nVas izbor -> ");
scanf("%d",&choice);
if(choice==1)
printf("\nProgram matematika Runs. !");

5
else if(choice==2)
printf("\nProgram finansija Runs. !");
else if(choice==3)
printf("\nProgram zabave Runs. !");
else if(choice==4)
{
printf("\nKraj programa!.\n");
exit(0);
}
else
printf("\nPogresan izbor");
}
Napisati program koji de unetu cifru ispisiati Morzeovom azbukom. Sldeda tablica prikazuje izgled cifre
prevedene na Morzeovu azbuku:
0 "-----"
1 (".----"
2 "..---"
3 "...--"
4 "....-"
5 "....."
6 "-...."
7 "--..."
8 "---.."
9 "----.")

int main()
{
int broj;
printf("Unesi jedan broj izmedju 0 i 9:");
scanf("%d",&broj);
if((broj<0)||(broj>9))
printf("Broj nije u opsegu izmedju 0 i 9\n");
else
{
printf("Broj %d prikazan Morzeovom azbukom je:",broj);
if(broj==0) printf("-----");
if(broj==1) printf(".----");
if(broj==2) printf("..---");
if(broj==3) printf("...--");
if(broj==4) printf("....-");
if(broj==5) printf(".....");
if(broj==6) printf("-....");
if(broj==7) printf("--...");
if(broj==8) printf("---..");
if(broj==9) printf("----.");
}
printf("\n\n");
}

Zadatak 12: U sledeem primeru uitavaju se dva broja i jedan znak koji predstavlja izbor
njihovog odnosa (< manje, > vee, = jednako ). U zavisnosti od uitanog znaka ispituje se
jedan od tri odnosa za poreenje ova dva broja. Ako je odnos taan tampati poruku
"Izabrali smo pravi odnos brojeva a i b", a ako nije "Izabrali smo pogresan odnos brojeva a i
b". U sluaju da se unese pogrean znak za poreenje tampati poruku "Nedopusteni znak za
odnos brojeva!" .
int main(void)
{
float a,b;
char znak;
printf("Upisati prvi broj: ");

6
scanf(" %f",&a);
printf("Upisati drugi broj: ");
scanf(" %f",&b);
printf("Upisati znak poredjenja: manje <, vece >,\n");
printf(" jednako = :");
scanf(" %c",&znak);
if(znak=='<')
{
if(a<b) printf("Izabrali smo pravi odnos brojeva a i b\n");
else printf("Izabrali smo pogresan odnos brojeva a i b\n");
}
else if(znak=='>')
{
if(a>b) printf("Izabrali smo pravi odnos brojeva a i b\n");
else printf("Izabrali smo pogresan odnos brojeva a i b\n");
}
else if(znak=='=')
{
if(a==b) printf("Izabrali smo pravi odnos brojeva a i b\n");
else printf("Izabrali smo pogresan odnos brojeva a i b\n");
}
else
printf("Nedopusteni znak za odnos brojeva!\n");
return 0;
}

Zadatak 13: U sledeem primeru uitavaju se dva broja i jedan znak koji predstavlja izbor
raunske operacije (s za sabiranje, o za oduzimanje, m za mnoenje i d za deljenje). U
zavisnosti od uitanog znaka izvrava se jedna od etiri raunske operacije i tampanje
rezultata.
int main(void)
{
float a,b;
char operacija;
printf("Upisati prvi broj: ");
scanf(" %f",&a);
printf("Upisati drugi broj: ");
scanf(" %f",&b);
printf("Upisati operaciju: zbir(z), oduzimanje(o),\n");
printf(" mnozenje(m),deljenje(d) :");
scanf(" %c",&operacija);
if(operacija=='z')
printf("%f\n",a+b);
else if(operacija=='o')
printf("%f\n",a-b);
else if(operacija=='m')
printf("%f\n",a*b);
else if(operacija=='d')
printf("%f\n",a/b);
else
printf("Nedopustena operacija!\n");
return 0;
}

7
Zadatak 14: Izraunavanje vrednosti funkcije
Sastaviti dijagram toka i napisati program kojim se izraunava vrednost funkcije:
x, x2

y 2, 2 x 3 .
x 1, x 3

Za 10 razliitih vrednosti argumenta x tampati vrednosti argumenta i vrednosti funkcije.


#include<stdio.h>
#include<stdlib.h>
void main()
{
int x, y;
printf("Unesi x\n");
scanf("%d",&x);

if (x < 2)
y = x;
else if(x>=2 && x<3)
y = 2;
else
y = x-1;

printf("Rezultat funkcije je %d\n", y);


}

8
4. POMONE FUNKCIJE

Zadatak 15: Primeri korienja funkcija abs, exp, log, sin. sqrt
#include <math.h>
#include <stdio.h>

void main(void)
{
int number = -1234;
double x = 4.0, y = 8.6872, result, z = 0.5;

printf("broj: %d ima apsolutnu vrednost: %d\n\n", number, abs(number));


result = exp(x);
printf("'e' dignuto na stepen %lf (e ^ %lf) = %lf\n\n", x, x, result);
result = log(y);
printf("Prirodni logaritam %lf je %lf\n\n", y, result);
result = sin(z);
printf("Sinus od %lf je %lf\n\n", z, result);
result = sqrt(x);
printf("KVADRATNI KOREN %lf JE %lf\n\n", x, result);
}

Zadatak 16: pow funkcija za PRIMER IZRAUNAVANJA REALNOG BROJA NA


STEPEN
#include <math.h>
#include <stdio.h>

int main(void)
{
double x = 2.0, y = 3.0;
printf("%lf na stepen %lf je %lf\n", x, y, pow(x, y));
return 0;
}

Zadatak 17: pow funkcija za PRIMER IZRAUNAVANJA n-tog KORENA REALNOG


BROJA
#include <math.h>
#include <stdio.h>
float main(void)
{
int n=5;
double x = 32.0,rezultat;
rezultat=pow(x,1./n);
printf("%d_ti koren broja %lf je: %lf\n",n, x,rezultat);
return 0;
}

Zadatak 18: 9. log10 funkcija za PRIMER LOGARITMA ZA OSNOVU 10 REALNOG


BROJA
#include <math.h>
#include <stdio.h>

int main(void)
{
double result;
double x = 100;
result = log10(x);
printf("LOGARITAM BROJA %lf JE %lf\n", x, result);
return 0;
}

9
Zadatak 19: rand funkcija za PRIMER GENERISANJA SLUCAJNIH BROJEVA
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main(void)
{
int i;
/* initialize random seed: */
srand (time(NULL));

printf("Deset slucajnih brojeva od 1 do 100 su:\n\n");


for(i=0; i<10; i++)
printf("%d\n", rand() % 100 + 1);
return 0;
}

Zadatak 20: Sastaviti program na programskom jeziku C za upotrebu funkcije rand()


kojom se ukljuuje generator sluajnih brojeva i tampa celobrojni sluajni broj i njegova
dvostruka vrednost. tampati i sluajan borj izmeu 0 i 9. tmpati sluajan broj izmeu 10 i
19.
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
void main()
{
int slucajan, dvostruki, x, y;
srand (time(NULL)); /* initialize random seed: */

slucajan = rand();
dvostruki = slucajan*2;
x = rand() % 10; /*slucajan izmedju 0 i 9*/
y = rand() % 10 + 10; /*slucajan izmedju 10 i 19*/
printf("Slucajan broj je %d\n", slucajan);
printf("Dvostruki slucajan broj je %d\n", dvostruki);
printf("Jos neki slucajni brojevi %d, \t %d \n", x, y);
}

Zadatak 21: Napisati program za izraunavanje funkcije:


( )
.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void main()
{
double x,y,pom;
printf("Unesite broj\n");
scanf("%lf",&x);
pom=pow(x,1./3.);
y=(x*x*sin(x)-1)/pom;
printf("Vrednost izraza je %lf a vrednost korena %lf\n",y,pom);
}

Zadatak 22: Napisati program za reavanje kvadratne jednaine ax2+bx+c=0.


void main()
{
double a,b,c;
double x1,x2,pom;
// a = 1; b = 1; c = -2;

10
scanf("%lf%lf%lf", &a, &b, &c);
pom = sqrt(b*b-4*a*c);
x1 = ( (-b) + pom ) / 2 * a;
x2 = ( (-b) - pom ) / 2 * a;
printf("Vrednost prvog korena x1 = %f\n",x1);
printf("Vrednost drugog korena x2 = %f\n",x2);
}

Zadatak 23: Sastaviti program na C jeziku za izraunavanje povrine trougla po obrascu


abc
PTROUGLA p( p a)( p b)( p c) gde je p
2
#include<stdio.h>
#include <stdio.h>
#include <math.h>

float main(void)
{
float a,b,c,p,PTROUGLA;
printf("Upisati broj a: ");
scanf(" %f",&a);
printf("Upisati broj b: ");
scanf(" %f",&b);
printf("Upisati broj c: ");
scanf(" %f",&c);
p=(a+b+c)/2.;
printf("Vrednost prolazne promenljive je:%f\n",p);
PTROUGLA=sqrt(p*(p-a)*(p-b)*(p-c));
printf("Povrsina trougla izracunata datim obrascem je:%f\n",PTROUGLA);
return 0;
}

11
5. SWITCH CASE NAREDBA

Zadatak 24: Naredba break sa naredbom switch. Uneti neki tekst. Unos teksta prekinuti
unoenjem znaka #. Izbrojati koliko kojih samoglasnika ima u unetom tekstu.
#include <stdio.h>
void main()
{
char ch;
int a_ct,e_ct,i_ct,o_ct,u_ct; a_ct=e_ct=i_ct=o_ct=u_ct=0;
printf("Unesi priozvoljan tekst; Unesi # za izlaz.\n");
while((ch=getchar())!= '#')
{
switch (ch)
{
case 'a' :
case 'A' : a_ct++;
break;
case 'e' :
case 'E' : e_ct++;
break;
case 'i' :
case 'I' : i_ct++;
break;
case 'o' :
case 'O' : o_ct++;
break;
case 'u' :
case 'U' : u_ct++;
break;
default: break;
} /* kraj switch */
} /* dok petlji nije kraj */
printf("Broj samoglasnika: \n A %d\n E %d\n I %d\n O %d\n U %d\n\n",
a_ct,e_ct,i_ct,o_ct,u_ct);
}

Zadatak 25: Napisati program sa menijem:


1- Program matematika
2- Program finansija
3- Program zabave
4- Exit
upotrebom naredbe switch i case.
void main()
{
int choice;
while(1)
{
printf("\n\nMeni:\n");
printf("1- Program matematika\n2- Program finansija\n");
printf("3- Program zabave\n4- Exit");
printf("\n\nVas izbor -> ");
scanf("%d",&choice);
switch(choice)
{
case 1 : printf("\nProgram matematika Runs. !"); break;
case 2 : printf("\nProgram finansija Runs. !"); break;
case 3 : printf("\nProgram zabave Runs. !"); break;
case 4 : printf("\nKraj programa!.\n"); exit(0);
default: printf("\nPogresan izbor");
}
}
}

12
6. FOR PETLJA

Zadatak 26: Napisati program koji rauna proizvod 5 sluajno izabranih jednocifrenih
brojeva.
#include <stdlib.h>
#include <time.h>
#include <stdio.h>

int main(void)
{
int i,R;
long int P=1;
srand(time(NULL));
printf("Pet slucajnih brojeva izmedju 0 i 9 su: \n\n\n");
for(i=0; i<5; i++)
{
R= rand() % 10;
printf("%d\n",R );
P=R*P;
}
printf("Proizvod 5 slucajnih brojeva je: %d\n\n\n", P);
return 0;
}

Zadatak 27: Odtampati sve neparne brojeve manje od 200 koristei for petlju:
#include <stdio.h>
void main()
{
int broj;
for (broj=1; broj<=200; broj=broj+2)
printf("\n%d",broj);
}

Zadatak 28:
1. Napisati program koji tampa tablicu mnoenja (od 1*1 do 9*9 tako da kao rezultat
dobijete tablicu koja ima 9 redova i 9 kolona).
#include<stdio.h>
void main()
{
int i,j;
for(i=1;i<10;i++)
{
for(j=1;j<10;j++)
printf("%3d",i*j);
printf("\n");
}
}

13
Zadatak 29: Napisati program koji rauna faktorijel unetog broja (N! = 1*2*3*...* (N-1) *N)
void main()
{
int i, n;
long fak = 1;
printf("lzracunavanje n!\nUkucajte broj ? ");
scanf("%d", &n);
for ( i=1; i<=n; ++i)
fak *= i;
printf("%4d! = %ld\n", n, fak);
}

Zadatak 30: Napisati program koji rauna aritmetiku sredinu za n proizvoljno unetih
realnih brojeva.
void main()
{
int n, brojac;
float suma = 0, x;
printf("Ukupno brojeva ?");
scanf("%d", &n);
for ( brojac=1; brojac<=n; ++brojac)
{
printf("Ukucajte %d broj ?", brojac);
scanf("%f",&x);
suma+=x;
}
printf("Srednja vrednost ovih brojeva je %4.2f\n", suma/n);
}

Zadatak 31: Sastaviti program za izraunavanje sume:


n
S i!
i 1
ukoliko je n celobrojna vrdnost. (Za n=5 proizvod S=34560)
float main()
{
int i,n;
float F=1,S=1;
printf("Unesite verdnost za n\n n=");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
F=F*i;
S=S*F;
}
printf("\nRezultat proizvoda je S=%lf\n",S);
return 1;
}

14
Zadatak 32: tampanje vrednosti stepena Farenhajta i Celzijusa pocev od 0 do 300 sa
korakom 20
#include <stdio.h>
int main()
{
int fahr;
for (fahr = 300; fahr >= 0; fahr = fahr - 20)
printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
return 0;
}

15
7. WHILE i DO WHILE PETLJE

Zadatak 33: Izraunajte zbira n proizvoljno unetih celih brojeva korienjem while petlje.
#include <stdio.h>
void main()
{
long sum = 0L;
int num;
printf("Unesite broj za sumiranje Ili 0 za izlaz\n");
scanf("%ld", &num);
while (num != 0)
{
sum = sum+num;
printf("Unesite naredni broj za sabiranj ili 0 za quite :::::::: %d
\n ", num);
scanf("%ld", &num);
}
printf("Zbir unetih brojeva je %ld.\n", sum);
}

Zadatak 34: Npisati program za izraunavanje sume prvih 20 prirodnih brojeva


korienjem while petlje.
#include <stdio.h>
int main(void)
{
int brojac,suma; /* deklaracija promenljive */
brojac = 1; /* inicijalizacija promenljive */
suma = 0; /* isto */
while(brojac++ < 21) /* while */
suma += brojac; /* naredba */
printf("suma = %d\n",suma); /* funkcijska naredba */
return 0;
}

Zadatak 35: Napisati program koji rauna srednju vrednosti n realnih brojeva pomou
while petlje.
void main()
{
int n, brojac = 0;
float suma = 0, x;
printf("Ukupno brojeva? ");
scanf("%d", &n);
while (brojac < n)
{
printf("Ukucajte %d. broj ? ", brojac+1);
scanf("%f", &x );
suma += x ;
brojac += 1;
}
printf("Srednja vrednost ovih brojeva je %f\n", suma/n);
}

Zadatak 36: Program za permutovanje cifara celog broja - while iskaz (npr. 54321 u 12345 )
Postupak: celi broj 54321 delimo po modulu 10 - rezultat je 1
celi broj 54321 delimo sa 10 - rezultat je 5432
celi broj 5432 delimo po modulu 10 - rezultat je 2
celi broj 5432 delimo sa 10 - rezultat je 543
celi broj 543 delimo po modulu 10 - rezultat je 3

16
celi broj 543 delimo sa 10 - rezultat je 54
celi broj 54 delimo po modulu 10 - rezultat je 4
celi broj 54 delimo sa 10 - rezultat je 5
celi broj 5 delimo po modulu 10 - rezultat je 5
Petlja se prekida jer broj postaje nula !!!
#include <stdio.h>
void main()
{
int broj;
printf("Ukucajte ceo broj ? ");
scanf("%d", &broj );
printf("Permutovani broj je ");
while ( broj )
{
printf("%d", broj % 10);
broj = broj/10;
}
printf("\n");
}

Zadatak 37: Napisati program na jeziku C koji za zadani prirodan broja treba da izrauna i
ispie sve njegove delitelje.
int main(void)
{
long num; // broj koji proveravamo
long div; // potencijalni delitelj
unsigned flag = 1; // prost broj?
printf("Unesite celi broj: ");
scanf("%ld",&num);
printf("%d je deljiv sa 1 i %d\n", num, num);
for (div=2; div<=num/2; div++)
if(num % div == 0)
{
printf("%d je deljiv sa %d i %d\n", num, div, num/div);
flag = 0;
}

if(flag == 1) printf("%ld je prost broj.\n",num);


return 0;
}

Zadatak 38: Napisati program na jeziku C koji proverava da li je uneti broj prost?
int main(void)
{
long num; // broj koji proveravamo
long div; // potencijalni delitelj
unsigned flag = 1; // prost broj?
printf("Unesite celi broj: ");
scanf("%ld",&num);
for (div=2; div<=num/2; div++)
if(num % div == 0)
flag = 0;

if(flag == 1)
printf("%ld je prost broj.\n",num);
else
printf("%ld je slozen.\n",num);
return 0;
}

Zadatak 39: Napisati program za izraunavanje n! primenom do while structure:

17
#include <stdio.h>
void main() /* Program za izracunavanje faktorijela */
{
int i, fak;
long n ;
i = 1; n = 1;
printf("lzracunavanje n!\nUkucajte broj ? ");
scanf("%d", &fak);
do{
n *= i;
i++;
} while (i <= fak);
printf("%d! = %ld\n", fak,n);
}

Zadatak 40: Napisati program na jeziku C koji rauna najveeg zajednikog delioca dva
nenegativna cela broja. Za izraunavanje koristiti Euklidovu metodu koja se sastoji iz
sledeih koraka:
Neka su a i b dva broj za koje vai da je a >= b
Izraunaj c = a MOD b
Ako je c = 0, b je najvedi zajedniki delilac
Ako je c != 0, onda de a da uzme vrdnost b, a b de uzeti vrednost c.
Ponoviti postupak sve dok c ne bude jednako 0
#include<stdio.h>
void main()
{
int prvi, drugi, pomocni;
printf("Ukucajte dva nenegativna cela broja ?\n");
scanf("%d%d", &prvi, &drugi );
if (prvi < drugi)
{
pomocni = prvi;
prvi = drugi;
drugi = pomocni;
}

while (drugi != 0)
{
pomocni = prvi % drugi;
prvi = drugi;
drugi = pomocni;
}
printf("Najveci zajednicki delilac ovih brojeva je %d\n", prvi);
}

Zadatak 41: Napisati program za permutovanje cifara nenegativnog celog broja koristei
do-while iskaz.
#include<math.h>
void main()
{
int broj;
printf("Ukucajte ceo broj ? ");
scanf("%d", &broj );
printf("Permutovani broj je ");
do
{
printf("%d", broj%10);
broj =broj/10;
}
while (broj);
printf("\n");

18
}

19
Zadaci za pripremu II kolokvijum iz predmeta
programski jezici I

Sadraj
Zadaci za pripremu II kolokvijum iz predmeta programski jezici I .................................................... 1
Nizovi ................................................................................................................................................... 2
Funkcije i procedure............................................................................................................................. 4
Rad sa nizovima karaktera ................................................................................................................. 14
Matrice ............................................................................................................................................... 21
Opti zadaci ........................................................................................................................................ 26

1
Nizovi
Zadatak 1: Napisati program za unos i izraunavanje zbira lanova niza sa 5 elemenata.
void main(void)
{
float broj[5]; //deklaracija niza
double rez = 0; int i; //pomocne promenljive

for(i=0; i < 5; i++) //uzmi podatke i smesti ih u broj


{
printf("Unesite broj %d : ", i+1);
scanf("%f", &broj[i] );
}

for(i = 4; i+1 ; i--) //saberi


rez += broj[i];

printf("Zbir unesenih brojeva je %lf \n", rez); //prikazi rezultat


}

Zadatak 2: Napisati program za tampanje niza i mnoenje elemenata niza konstantnom


vrednou.
#include <stdio.h>
#define VELICINA 5

void main()
{
double dip[VELICINA] = {20.0, 17.66, 8.2, 15.3, 22.22};
int i;
for(i = 0; i < VELICINA; i++)
dip[i] *= mnozi;

printf("\n");
for(i = 0; i < n; i++)
printf("%8.3f ", dip[i]);
printf ("\n");
}

Zadatak 3: Razmotriti rad programa pisanog u C programskom jeziku, koji sortira dati
vektor ar = {7,3,9,2,11,20,17,19,6,4} korienjem metode "bubble sort" algoritma.
Program se najpre sastoji u pisanju funkcije "swap" koja vri zamenu vrednosti dve
promenljive i smeta ih u dve memorijske lokacije. Zatim tu funkciju koristimo da bi
izvrili sortiranje datog vektora. "Bubble sort" ispituje svake dve elije vektora i ako nisu
sortirane - svapuje ih. Ako se obezbedi uporeenje i svapovanje n-1 put nad svim elijama
vektora, on e biti kompletno sortiran.
#include <stdio.h>
void swap (int *a, int *b);

void main()
{
int ar[10] = {7, 3, 9, 2, 11, 20, 17, 19, 6, 4};
int i,j,n;

printf("Vektor pre sortiranja:\n");


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

n=10; /*broj clanova u vektoru koji se sortira*/


for(i=0;i<n-1;i++)
for(j=0;j<n-1;j++)
2
{
if(ar[j]>ar[j+1])
swap(&ar[j],&ar[j+1]);
}

printf("\nVektor posle sortiranja:\n");


for(i=0;i<10;i++)
printf("ar[%d]=%d\n",i,ar[i]);
}

void swap ( int *a,int *b)


{
int temp;
temp=*a;
*a=*b;
*b=temp;
}

3
Funkcije i procedure
Zadatak 4: Pokazati kako funkcionie prototip funkcije.
void myfunc();/*inicijalizacija funkcije bez argumenata*/
void main()
{
myfunc();/*pozivanje funkcije bez argumenata*/
}

void myfunc()/*definisanje funkcije bez argumenata*/


{
printf("ZDRAVO, ovo je test\n");
}

Zadatak 5: Korienje prototipa funkcije sa argumentom.


void napisi(int count);
void main()
{
napisi(4);
}

void napisi(int count)


{
int c;
for(c=0;c<count;c++)
printf("\nZDRAVO");
}

Zadatak 6: Nai minimum od dva cela broja. U glavnom programu obezbediti tampanje, a
u funkciji njihovo poreenje.
int imin(int n,int m);
void main()/* glavni program */
{
int broj1,broj2,vrati;
printf("Unesite dva cela broja\n");
vrati=scanf("%d %d",&broj1,&broj2);
if(vrati == 2)
printf("Manji od %d i %d je %d\n",broj1,broj2,imin(broj1,broj2));
}

int imin(int n,int m)/* potprogram */

4
{
int min;
if (n<m)
min=n;
else
min=m;
return min;
}

Zadatak 7: Uraditi meni sa izborom operacija za sabiranje, oduzimanje i mnoenje dva


cela realna broja. U funkciji izvesti opisane raunske radnje.
void add();
void subtract();
void multiply();

void main()
{
int choice;
while(1)
{
printf("\n\nMenu:\n");
printf("1- Add\n2- Subtract\n");
printf("3- Multiply\n4- Exit");
printf("\n\nYour choice -> ");
scanf("%d",&choice);
switch(choice)
{ case 1 : add();
break;
case 2 : subtract();
break;
case 3 : multiply();
break;
case 4 : printf("\nProgram Ends. !");
exit(0);
default:
printf("\nInvalid choice");

}
}
}

void add()
{
float a,b;
printf("\nEnter a:");
scanf("%f",&a);
printf("\nEnter b:");
scanf("%f",&b);
printf("a+b=%f",a+b);
}

void subtract()
{

5
float a,b;
printf("\nEnter a:");
scanf("%f",&a);
printf("\nEnter b:");
scanf("%f",&b);
printf("a-b=%f",a-b);
}

void multiply()
{
float a,b;
printf("\nEnter a:");
scanf("%f",&a);
printf("\nEnter b:");
scanf("%f",&b);
printf("a*b=%f",a*b);
}

Zadatak 8: Prenoenje parametara funkcije po vrednosti i po referenci


void test1(int a)
{
a=5;
}

void test2(int &a)


{
a=5;
}

void test3(int* a)
{
*a = 5;
}

int main()
{
int m;
m=2;
printf("\nM je %d",m);
test1(m);
printf("\nM je i dalje %d iako je vrednost promenjna u funkciji",m);
6
printf("\n\n\nM je %d",m);
test2(m);
printf("\nM je promenila vrednost i sada je %d\n",m);

printf("\n\n\nM je %d",m);
test3(&m);
printf("\nM je promenila vrednost i sada je %d\n",m);
return 0;
}

Zadatak 9: MNOZENJE I SABIRANJE DVA REALNA BROJA PREKO FUNKCIJE


int mno(int x, int y);
int sab(int x, int y);
void main()
{
int a,b;
printf("\nUnesite vrednosti za a i b\n");
scanf("%d%d",&a,&b);
printf ("\nproizvod je %d\n", mno(a,b));
printf ("\nZbir je %d\n", sab(a,b));
}

int mno(int x, int y)


{
return x*y;
}

int sab(int x, int y)


{
return x+y;
}

Zadatak 10: MINIMUM TRI CELA BROJA PREKO FUNKCIJE


#include<math.h>
void min();
void main()
{
min();
}

void min()
{
int a,b,c,m;
printf("\nUnesite vrednosti za a , b i c\n");
scanf("%d%d%d",&a,&b,&c);
m=a;
if(b<m) m=b;
if(c<m) m=c;
printf("Minimum brojeva a=%d b=%d i c=%d je broj %d\n",a,b,c,m);
}

7
Zadatak 11: Suma kvadrata celih brojeva od 1 do N preko funkcije
#include <stdio.h>
#include <math.h>
suma_kvadrata(int n);

void main( )
{
suma_kvadrata(10);
suma_kvadrata(15);
suma_kvadrata(20);
}

suma_kvadrata(int n) /*f ja za izracunavanje*/


/*sume kvadrata*/
{
int i;
long suma=0;
for (i=1; i<=n; suma+=(long)i*i, ++i);
printf("Suma kvadrata od 1 do %d je %ld\n", n, suma);
return 0;}

Zadatak 12: Primer funkcije bez povratnih vrednosti


void ispis(int i1, int i2, int i3); /* F-ja ne vraca nikakvu vrednost*/
void main()
{
int a,b,c;
a=b=c=1;
ispis(a,b,c);
a=b=c=2;
ispis(a,b,c);
}

void ispis(int i1, int i2, int i3)


{
printf("\nVrednost promenljive param1 je %d.\n",i1);
printf("Vrednost promenljive param2 je %d.\n",i2);
printf("Vrednost promenljive param3 je %d.\n",i3);
}

8
Zadatak 13: Poziv funkcije bez argumenta
void main()
{
void zvezde(); /*deklaracija funkcije bez argumenata*/
zvezde(); /*poziv korisnicke funkcije */
printf("%s \n ", IME) ; /*poziv funkcije iz standardne biblioteke*/
printf("%s\n", ADRESA);
printf("%s\n", MESTO) ;
zvezde ( ) ;
}
/*definicija korisnicke funkcije */
void zvezde() /*funkcija nema argumenata*/
{
int brojac;
for(brojac=1; brojac <= LIMIT; brojac++)
putchar ( '*' );
putchar ( '\n' ) ;
}

Zadatak 14: Napisati program za izraunavanje hipotenuze pravouglog trougla. U glavnom


program izvriti unos vrednosti prve i druge katete i tampati vrednost hipotenuze. U
potprogramu izraunati vrednost hipotenuze.
#include<stdio.h>
float hipotenuza( float n, float m); // Deklaracija funkcije

void main() /* glavni program */


{
float kat1, kat2, hip;
printf("Unesite 2 proizvoljna broja: \n");
scanf("%f %f",&kat1,&kat2);
hip = hipotenuza(kat1,kat2);
printf("Hipotenuza je %4.2f\n",hip);
}

float hipotenuza( float n, float m ) /* potprogram definicija


funkcije */
{
float rez = sqrt(n*n + m*m);
return rez;
}

Zadatak 15: Napisati program za izraunavanje hipotenuze pravouglog trougla. U glavnom


programu tampati vrednost hipotenuze. U potprogramu izraunati vrednost hipotenuze.
U drugom potpotprogramu izvriti unos vrednosti kateta.

#include<stdio.h>
float hipotenuza( float n, float m); // Deklaracija funkcije
void unos( float &n, float &m);

void main() /* glavni program */


{
9
float kat1, kat2, hip;
unos(kat1, kat2);
hip = hipotenuza(kat1,kat2);
printf("Hipotenuza je %4.2f\n",hip);
}

float hipotenuza( float n, float m ) /* potprogram definicija


funkcije */
{
float rez = sqrt(n*n + m*m);
return rez;
}

void unos( float &n, float &m)


{
printf("Unesite 2 proizvoljna broja: \n");
scanf("%f %f",&n,&m);
}

Zadatak 16: Primer za izracunavanje y=sin2(x)+cos2(x)


double Funkcija(double x)
{
double y;
y=sin(x)*sin(x)+cos(x)*cos(x);
return y;
}
void main()
{
double x,y;/* deklaracija lokalnih promenljivih, posle pocetka programa*/
printf("Unesite vrednost za x:");
scanf("%lf",&x);
y=Funkcija(x);
printf("Vrednost funkcije je %f.",y);
}

Zadatak 17: Izracunavanje povrsine trougla sa dve funkcije


#include<stdio.h>
#include<math.h>
float Povrsina(int &a, int &b, int &c);
void Ucitaj(int &a, int &b, int &c);
void main()
{
int a, b,c;
Ucitaj(a, b, c);

10
float pt = Povrsina(a, b, c);
printf("\nPovrsina trougla je %f.",pt);
}

float Povrsina(int &a, int &b, int &c)


{
float p = (a+b+c)/2;
p = sqrt(p*(p-a)*(p-b)*(p-c));
return p;
}

void Ucitaj(int &a, int &b, int &c)


{
printf("Prva kateta:");
scanf("%d",&a);
printf("Druga kateta:");
scanf("%d",&b);
printf("Treca kateta:");
scanf("%d",&c);
}

Zadatak 18: etiri raunske radnje preko funkcije choice i switch naredbi.
#include<stdio.h>
#include<stdlib.h>
float add(float aa, float bb);
float subtract(float aa, float bb);
float multiply(float aa, float bb);
float divide(float aa, float bb);

void main()
{
int choice;
float a, b, rezultat;
while(1)
{
printf("\n\nMenu:\n");
printf("1- Add\n2- Subtract\n");
printf("3- Multiply\n4- Divide\n5-Exit");
printf("\n\nYour choice -> ");
scanf("%d",&choice);
if (choice != 5)
{
printf("\nEnter a:");
scanf("%f",&a);
printf("\nEnter b:");
scanf("%f",&b);
}
switch(choice)
{
case 1: rezultat = add(a,b);
printf("Rezultat operacije je:%f\n",rezultat);
break;
case 2: rezultat = subtract(a,b);
printf("Rezultat operacije je:%f\n",rezultat);

11
break;
case 3: rezultat = multiply(a,b);
printf("Rezultat operacije je:%f\n",rezultat);
break;
case 4: rezultat = divide(a,b);
printf("Rezultat operacije je:%f\n",rezultat);
break;
case 5: printf("\nProgram Ends. !");
exit(0);
default: printf("\nInvalid choice");}
}
}

float add(float aa, float bb)


{
return (aa+bb);
}

float subtract(float aa, float bb)


{
return (aa-bb);
}

float multiply(float aa, float bb)


{
return (aa*bb);
}

float divide(float aa, float bb)


{
return (aa/bb);
}

Zadatak 19: Primer prenosa niza kao parametra funkcije za realizaciju sabiranja lanova
niza.
#include <stdio.h>
#define VELIC 10
long sump(int *pok, int vel);

void main()
{
12
static int niz[VELIC] = {20,10,5,39,4,16,19,26,31,20};
long odgovor;
odgovor = sump(niz, VELIC);
printf("Suma niza je: %ld.\n", odgovor);
}

long sump(int *ar, int n) /* koristi pokazivacku aritmetiku */


{
int i ;
long ukupno = 0;
for(i = 0; i < n; i++) {
ukupno += *ar; /* dodaje vrednost na ukupno */
ar++; /* pomera pokazivac na sledeci elemenat */
}
return ukupno;
}

Zadatak 20: Napisati program za tampanje niza i mnoenje elemenata niza konstantnom
vrednou. Mnoenje i tmpanje niza impelemntirati pomou potprograma.
void prikaz_niza(double niz[], int n);
void uvecaj_niz(double broj, double *pok, int vel);

void main()
{
static double dip[VELICINA] = {20.0, 17.66, 8.2, 15.3, 22.22};
prikaz_niza(dip, VELICINA);
uvecaj_niz(2.5, dip, VELICINA) ;
prikaz_niza(dip, VELICINA);
}

void prikaz_niza(double *ar, int n) //*ar je ekvivalentno sa ar[] !!!//


{
int i;
printf("\n") ;
for(i = 0; i < n; i++)
printf("%8.3f ", ar[i]);
printf ("\n");
}

void uvecaj_niz(double mnozi, double *ar)


{
int i;
for(i = 0; i < VELICINA; i++)
ar[i] *= mnozi;
}

13
Rad sa nizovima karaktera
Zadatak 21: Primer rada sa funkcijama za rad sa stringovima (nizovima karaktera).
#include <cstring>
#include <stdio.h>

void main()
{
char rec1[20] = "lep";
char rec2[20] = "dan";
char rec3[20];

printf("%d\n", strlen(rec1));
printf("%d\n", strlen(rec2));
printf("%s\n", strcat(rec1, rec2));
printf("%d\n", strlen(rec1));

strcpy(rec3, rec1);

printf("%s \n %s\n %s\n", rec1, rec2, rec3);


// printf ("%d", i);

printf("%d\n", strcmp(rec1, rec2));


printf("%d\n", strcmp(rec1, rec3));
}

Zadatak 22: Primer za vrednost EOF


#include <cstdio>
int main()
{
printf("Na mom sistemu vrednost za EOF je %d\n\n", EOF);
return 0;
}

Zadatak 23: Razliciti primeri za unosenje i tampanje niza karaktera sa standardnog ulaza:
void main()
{
char recenica[80];
printf("Unesite niz proizvoljnih karaktera:");
gets(recenica);
printf("\nUneli ste niz karaktera:");
puts(recenica); //Stampanje unetih karaktera
printf("\n"); //Prelazak u novi red

printf("Unesite niz karaktera: ");


scanf("%s",&recenica); //scanf cita samo do prvog belog znaka
printf("Prikaz unetog sadrzaja: %s\n",recenica);
}

14
Zadatak 24: Unos i tampanje jednog karaktera
#include<stdio.h>
void main( ) {
char c;
printf("Unesite jedan proizvoljni karakter:");
c = getchar( );
putchar('\n');//Prelazak u novi red
printf("Uneli ste karakter:");
putchar(c);//Stampanje unetog karaktera
putchar('\n');//Prelazak u novi red
}

Zadatak 25: Unos i tampanje karaktera


#include <stdio.h>
void main()
{
int vrednost;
vrednost='A';
printf("%s \nkarakter=%3c \nvrednost=%3d \n","Veliko slovo",
vrednost, vrednost);
vrednost='a';
printf("%s\nkarakter=%3c\nvrednost=%3d\n","Malo slovo",
vrednost, vrednost);
}

15
Zadatak 26: - Program ita jedan karakter i ispisuje ga.
#include <stdio.h>
void main()
{
int c; /* Karakter - obratiti paznju na int */
printf("Unesite jedan proizvoljni karakter:");
c = getchar(); /* cita karakter sa standardnog ulaza */
printf("\nUneli ste karakter:");
putchar(c); /* pise karakter zapamen u promenljivoj c na standardni izlaz */
putchar('\n'); /* prelazak u novi red */
printf("Ispisuje malo a:");
putchar('a'); /* ispisuje malo a */
printf("\nIspisuje ASCI 97:");
putchar(97); /* ekvivalentno prethodnom */
putchar('\n');/* prelazak u novi red */
}

Zadatak 27: Program uitava i broji karaktera sa ulaza sve dok se ne otkuca znak za kraj
unosa EOF. EOF se moe generisati kucanjem Control /Z.
#include <stdio.h>
void main()
{
int ch, i = 0;
while((ch = getchar()) != EOF)
i ++;
printf("%d\n", i);
}

Zadatak 28: Program koristi getchar da uita liniju sa standardnog ulaza stdin, postavlja
takav ulaz u buffer, onda zavrava string terminacionim karakterom i zatim tampa
string na ekranu.
#include <stdio.h>
void main( void )
{
char buffer[81];
int i, ch;
printf( "Enter a line: " );
/* Read in single line from "stdin": */
for( i = 0; (i < 80) && ((ch = getchar()) != EOF)
&& (ch != '\n'); i++ )
buffer[i] = (char)ch;
/* Terminate string with null character: */
buffer[i] = '\0';
printf( "%s\n", buffer );

16
}

Zadatak 29: Program konvertuje ulazne karaktere u velika slova. Da bi ovo uinili moramo
dodati funkciju toupper iz biblioteke za konverziju karaktera ctype.h
#include <ctype.h> /* For definition of toupper */
#include <stdio.h> /* For definition of getchar, putchar, EOF */

void main()
{
int ch;
while((ch = getchar()) != EOF)
putchar(toupper(ch));
}

Zadatak 30: NCP koji e ispisati na standardni izlaz ukupan broj karaktera standardnog
ulaza do markera kraja, kao i broj prelazaka u novi red. Pretpostaviti da je za ukupan
broj karaktera (zajedno sa enter i blanko) i ukupan broj prelazaka u novi red dovoljan
opseg long promenljivih.
#include <stdio.h>
void main()
{
int znak; /*prihvata znak sa ulaza */
long linije=0 ; /*brojac linija */
long br_znak=0; /*brojac znakova na ulazu */
while ( (znak=getchar() ) != EOF)
{
br_znak++;
if (znak=='\n')
linije ++;
}
printf("Prelazaka u novi red: %ld, karaktera: %ld \n",linije,br_znak);
}

Zadatak 31: Program za prikazivanje tablice ASCII kodova:


#include <stdio.h>
void main()
17
{
char c=' ';
int i;

printf ("\t\tTablica ASCII kodova \n \n");


for (i=0; i<95; i++)
printf("%3d %c ",c+i,c+i);
if (i%19 == 0)
printf("\n");
}

Zadatak 32: Napisati program koji nalazi najduzu unetu liniju sa standardnog ulaza. Nije
poznat ukupan broj linija, ali svaka linija nema vise od 80 karaktera a unos se prekida
unosom karaktera CTRL/Z.
#define MAX_DUZINA_LINIJE 80
void main()
{
char linija[MAX_DUZINA_LINIJE];
char najduza_linija[MAX_DUZINA_LINIJE];
int duzina_linije = 0;
int duzina_najduze_linije = 0;
najduza_linija[0] = '\0';
while( gets(linija) != NULL){
duzina_linije=strlen(linija);
if (duzina_linije > duzina_najduze_linije){
strcpy(najduza_linija, linija);
duzina_najduze_linije = duzina_linije;
}
}
printf("Najduza linija je : %s\n i ona ima %d karaktera
\n\n",najduza_linija, duzina_najduze_linije);
}

18
Zadatak 33: Uraditi program za unos niza karaktera Moram da poloim drugi kolokvijum
iz Programskih jezika 1 u vektor Niz1. Odtampati ovaj niz karaktera u potpunoj formi,
i izraunati duinu unetog niza. Iskopirati sadraj vektora Niz1 u vektror Niz2 i utvrditi
dali su to isti nizovi. Prebrojati koliko praznina (blanko karaktera) ima u nizu Niz1.
void main()
{
int brojznak=0,i=0;
char Niz1[81],Niz2[81];
printf("Unesi clanove niza Niz1, za kraj Ctrl/z/");
while( gets(Niz1)!= NULL) /* Unos se prekida sa Ctrl/z */
continue;

printf("Linija niza Niz1 je : %s\n",Niz1);


printf("\nDuzina niza po broju karaktera je:%d\n",(strlen(Niz1)-1));
strcpy(Niz2,Niz1);
printf("Linija niza Niz2 je : %s\n",Niz2);

if (strcmp(Niz1,Niz2)==0)//Komparacija-uporedjivanje dva niza


printf("Ovo su jednaki NIZOVI!\n");
else printf("Ovo nisu jednaki NIZOVI!\n");

while (Niz1[i]!='\n')
{
if(Niz1[i] == ' ')
brojznak++;
i=i+1;
}
printf("Broj blanko znakova u nizu Niz1 je:%ld \n",brojznak);
}

Zadatak 34: Sastaviti program koji iz skupa unetih karaktera (na primer: Ja sam rodjen
1990. god u 12. mesecu, u petak!) izraunava broj unetih slova, brojeva i ostalih
karaktera. Tekst se unosi sa tastature, a program se prekida pritiskom na ctrl+Z
#include<conio.h>
void main( ){
int slovo, broj, ostalo, c;
slovo = broj = ostalo = 0;
while( (c=getchar( )) != EOF )
if( ('A'<=c && c<='Z') || ('a'<=c && c<='z') )
++ slovo;
else if( '0'<=c && c<='9' ) ++broj;
else ++ostalo;
printf("Uneli ste:%d slova, %d brojeva,%d ostalih\n\n", slovo, broj,
ostalo);
}

19
Zadatak 35: Napisati program konvertuje velika u mala slova. Recenica se unosi sa tastature
a program se prekid unoenjem karaktera %.
void main( ) {
char c;
while( (c=getchar( )) != '%' )
if( 'A'<=c && c<='Z' )
putchar(c+'a'-'A');
else
putchar(c);
}

Zadatak 36: Program broji karaktere, brojeve i praznine u tekstu. Zavrava se unosom %.
void main( )
{
int let, dig, other, c;
let = dig = other = 0;
while( (c=getchar( )) != '%' )
if( ('A'<=c && c<='Z') || ('a'<=c && c<='z') )
++let;
else if( '0'<=c && c<='9' ) ++dig;
else ++other;
printf("%d slova, %d broja, %d ostalih karaktera\n", let, dig,
other);
}

20
Matrice
Zadatak 37: tampanje elemenata matrice
#include<stdio.h>
#include<math.h>
void main()
{
static int mat[3][3]={{0,1,2},{3,4,5},{6,7,8}};
int i,j;
for(i=0; i<3; ++i)
{
printf("\n");
for(j=0; j<3; ++j)
printf("%d\t",j,mat[i][j]);
}
printf("\n");
}

Zadatak 38: Neka je data kvadratna matrica u formatu:


1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
lanove matrice uneti u program kao konstantne celobrojne veliine, a kao izlaz iz programa
predvideti tampanje ove matrice u pokazanom formatu kao polazne matrice i tampanje
nove matrice u istom obliku ali iji su svi lanovi sada pomnoeni skalarom 2.
#include<stdio.h>
#include<math.h>
void main()
{
int mat[4][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
int i,j;
printf("\nPolazna matrica je\n");
for(i=0;i<4; i++)
{
for(j=0;j<4; j++)
printf("%2d ",mat[i][j]);
printf("\n");
}

printf("\nNova matrica je\n");


for(i=0;i<4; i++)
{
for(j=0;j<4; j++)
printf("%2d ",2*mat[i][j]);
printf("\n");
}
}

21
Zadatak 39: Neka je data kvadratna matrica u formatu:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
lanove matrice uneti u program kao konstantne celobrojne veliine, a kao izlaz iz programa
predvideti tampanje ove matrice u pokazanom formatu kao polazne matrice i tampanje
nove matrice u istom obliku ali sada unazad od lana a44,a43,a42a41,......,a11.
void main()
{
int mat[4][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
int i,j;
printf("\nPolazna matrica je\n");
for(i=0;i<4; i++)
{
for(j=0;j<4; j++)
printf("%2d ",mat[i][j]);
printf("\n");
}

printf("\nNova matrica je\n");


for(i=3;i>=0; i--)
{
for(j=3;j>=0; j--)
printf("%2d ",mat[i][j]);
printf("\n");
}
}

Zadatak 40: Napisati program na C++ jeziku koji izraunava sumu svih elemenata u
svakom redu pojedinano, pravougaone matrice [4x4].
22
1 2 3 4
5 6 7 8
A=
9 10 11 12
13 14 15 16
void main()
{
int mat[4][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
int i,j,s=0;

printf("\nPolazna matrica je\n");


for(i=0;i<4; i++)
{
for(j=0;j<4; j++)
printf("%2d ",mat[i][j]);
printf("\n");
}

for(i=0;i<4; i++)
{
printf("\nSuma %d reda je:",i+1);
for(j=0;j<4; j++)
s=s+mat[i][j];
printf("%2d\n",s);
s=0;
}
}

Zadatak 41: NCP koji sa standardnog ulaza uitava 3x3 matricu i ispisuje je na standardni
izlaz tako da centralno polje a[1][1] bude jednako sumi gornjeg levog (a[0][0]) i donjeg
desnog polja (a[2][2]). Pre uitavanja popuniti matricu proizvoljnim vrednostima.
#include <stdio.h>
void main()
{
int a[3][3]; /* deklaracija i inicijalizacija matrice a, moe se uraditi
za konkretan primer date matrice*/
int i, j; /*brojaci u ciklusu */

for(i=0; i<3; i++)


for(j=0; j<3; j++)
{
printf("\na[%d][%d] = ", i, j);
scanf("%d", &a[i][j]);
}
printf("\n*******************\n");
23
a[1][1] = a[0][0] + a[2][2]; /* 0 + 22 = 22 */

/*ispis matrice */
for(i=0; i<3; i++)
{
for(j=0; j<3; j++) printf("%d\t", a[i][j]);
printf("\n");
}
}

Zadatak 42: Neka je data kvadratna matrica u formatu:


a11 a12 a13 a14
a 21 a 22 a 23 a 24
a31 a32 a33 a34
a 41 a 42 a 43 a 44
Uneti lanove matrice u program kao celobrojne veliine, a kao izlaz iz programa predvideti
tampanje takve matrice u pokazanom formatu kao i tampanje izraunate vrednosti njene
dijagonale a11*a22*a33*a44 uraene preko funkcije.
int d(int mat[4][4])
{
int i,j, rez=0;
for(i=0;i<4;++i)
for(j=0;j<4;++j)
if (i == j)
rez = rez + mat[i][j];
return rez;
}

void main()
{
int mat[4][4];
int i,j;
float dijagonala;
printf("Unesite proizvoljne elemente pravougle matrice:\n");
for(i=0;i<4;++i)
for(j=0;j<4;++j)
24
{
printf("a[%d][%d]=",i,j);
scanf("%d",&mat[i][j]);
printf("\n");
}
printf("\nPolazna matrica je\n");
for(i=0;i<4;++i)
{
for(j=0;j<4;++j)
printf("%3d ",mat[i][j]);
printf("\n");
}

printf ("Vrednost zbira elemenata na glavnoj dijagonali je: %d\n",


d(mat));
}

25
Opti zadaci
Zadatak 43: Program za odredjivanje da li je godina prestupna ili nije
#include<stdio.h>
#include<math.h>
void main()
{
int godina,ost_4,ost_100,ost_400;
printf("Ukucajte godinu ? ");
scanf("%d", &godina);
ost_4=godina%4;
ost_100=godina%100;
ost_400=godina%400;
if (ost_4 ==0 && ost_100 != 0 || ost_400== 0)
printf("Godina %d je prestupna\n", godina);
else
printf("Godina %d nije prestupna\n", godina);
}

Zadatak 44: Program za odredjivanje srednje vrednosti n celih pozitivnih brojeva -for iskaz
#include<stdio.h>
#include<math.h>
void main()
{
int n,brojac;
float suma =0, x ;
printf("Ukupno brojeva? ");
scanf("%d", &n);
for (brojac=1 ; brojac<=n; ++brojac, suma+=x )
{
printf("Ukucajte %d broj? ",brojac);
scanf("%f",&x);
}
printf("Srednja vrednost ovih brojeva je %f\n", suma/n);
}

Zadatak 45: Program za izracunavanje faktorijela


#include <stdio.h>
#include <math.h>
void main()
{
int i, n;
long fak = 1;
printf("lzracunavanje n!\nUkucajte broj ? ");
scanf("%d", &n);
26
for ( i=1; i<=n; ++i)
fak *= i;
printf("%d! = %ld\n", n, fak);
}

Zadatak 46: Program za izracunavanje prostih aritmetickih izraza u formi operand1


operator operand2
#include <stdio.h>
#include <math.h>
void main()
{
float operand1, operand2;
char op;
printf("Ukucajle lzraz ? \n");
scanf("%f%c%f", &operand1, &op, &operand2);
switch (op)
{
case '+':
printf("%f\n", operand1+operand2);
break;
case '-':
printf("%f\n", operand1-operand2 );
break;
case '*':
printf("%f\n", operand1*operand2 );
break;
case '/':
printf("%f\n", operand1/operand2);
break;
default:
printf("Nepoznat operator\n");
}
}

Zadatak 47: Odredjivanje u ulaznom tekstu broja praznih karaktera, kao i broja znakova:
tacka, zarez, dvotacka i tacka-zarez (naredbe switch i break) za izlaz CTRL/Z.
#include <math.h>
#include <stdio.h>
void main( )
{
int c, prazno=0, interp=0;
while((c=getchar())!=EOF)
switch(c)
{
27
case ' ':
prazno++;
break;
case '.':
case ',':
case ':':
case ';':
interp++;
break;
default:
break;
}
printf("\nBroj praznina: %d", prazno);
printf("\nBroj znakova tacka, zarez, dvotacka i tacka-zarez: %d\n",
interp);
}

28

You might also like