Beruflich Dokumente
Kultur Dokumente
1. UVOD U PROGRAMIRANJE
1.1. O računarima
Upravljanje
(procesor)
Često je nezgodno koristiti samo Bit kao jedinicu za količinu informacije, te zato
postoje i izvedene jedinice:
Byte – informacija koja se sastoji od 8 Bita, dakle od osam vrijednosti jedinica ili nula
Kilobyte (KB) – je količina informacija od 1024 Byta (ne 1000 kao što neki misle, već
zato što je 210=1024)
Megabyte (MB) – je isto što i 1024 KB odnosno 1048576 Byta
Gigabyte (GB) – sadrži 1024 MB informacija
Terabyte (TB) – je još uvijek rijetko korištena jedinica i sadrži 1024 GB informacija
Brzina računara se ne mjeri u MHz, već u broju operacija u sekundi. Obično se koristi
jedinica FLOPS (Floating point Operations Per Second) i govori koliko operacija sa
pomičnim zarezom računar napravi u sekundi. Ova jedinica je obično premala, pa se
koristi MFLOPS=1000000FLOPS.
Računarski program je skup naredbi koji govori računaru na koji način da obavi
određeni zadatak. Tekst programa koji je čitljiv programeru i korisniku zove se izvorni
kod programa, dok je izvršna verzija programa binarna, i može je čitati i izvoditi samo
računar.
Jezici prve generacije temelje se na strojnom jeziku, tj. kodovima naredbi koje izvodi
direktno sam procesor. Programi su napisani u binarnim kodovima, i vrlo su nečitljivi.
Kasnije su dodani simbolični nazivi naredbama, no skokovi su bili izvedeni prema
hardverskim adresama koje su zadane brojem.
Zanimljivo je što se i danas svaki program na kraju svodi na ovu razinu, jer to je jedini
oblik programa koji računar razumije. Za prevođenje jezika viših razina u jezike niže
razine koriste se programi zvani prevodioci ili compileri.
Jezici pete generacije su uglavnom usko specijalizirani jezici koji često kreiraju cijele
aplikacije potpuno automatski putem raznih Wizarda i slično. Razvoj ovakvih jezika je
u početnoj fazi.
Ova paradigma temelj je programskih jezika čija glavna namjena je obrada nekih
događaja koji se dešavaju u izvođenju koda. Ova arhitektura je u potpunosti
drugačija od proceduralne, zato jer ne postoji neki glavni kod koji se izvršava, već se
čeka na neki događaj (zahtjev operativnog sistema, unos podataka od korisnika itd.) i
tek kada se on desi, započinje se poziv proceduralnog niza koji ga obrađuje. Na ovoj
arhitekturi temelji se VB 6.0
¾ Analiza problema
¾ Postavljanje modela
¾ Izrada algoritma
¾ Izrada dijagrama toka
¾ Kodiranje programa
¾ Prevođenje programa
¾ Testiranje programa
¾ Dokumentiranje programa
¾ Eksploatacija programa
model rješenja:
• Model podataka sadrži definiciju podataka (nazive, vrste, dimenzije,
ograničenja
• vrijednosti...) te strukture podataka (nizovi, skupovi, datoteke, tablice...)
• Model procesa može biti prikazan različitim tehnikama (dijagram toka,
dijagram strukture procesa, dijagrami akcija....), ali svi oni, na svoj
način, prikazuju slijed odvijanja procesa.
• Model resursa sadrži definiciju računalnih resursa i njihovih svojstva
(operacijski sistem, vrsta programskog prevodioca, svojstva jedinica
računara...) koje su potrebne da bi program uredno radio.
Model
procesa
Model
Model
podataka
podataka
3. ALGORITMI
Definicija 1.
Algoritam je tačan opšte razumljiv propis koji definiše proces transformacije početnih
podataka u traženi rezultat.
Definicija 2.
Algoritam je tačan propis o tome koje operacije nad kojim brojevima i u kom
redosljedu treba izvršiti da bi se rješili svi zadaci nekog zadatog tipa.
Definicija 3.
Algoritam je konačni skup pravila koja daju redosljed operacija za rješavanje
specifičnog problema.
SMJER U KOME SE
ODVIJA ALGORITAM IZLAZ JE
MONITOR
IZLAZNI UREĐAJ
ULAZ PODATAKA JE PRINTER
ULAZ/IZLAZ
PODATAKA ODLUKA
ULAZ JE SA
BUŠENIH KARTICA KONEKTOR
Primjer algoritma
Bilo koji problem se može riješiti izvršavanjem serije akcija u određenom Redosljedu.
Akcije koje će se izvršiti i redosljed u kojem će se to odvijati nazivamo algoritam.
Iskustvo pokazuje da je najteži dio riješavanja programerskog problema na računalu
upravo razvijanje algoritma za riješenje. Jednom kad je određen ispravan algoritam,
razvoj programa za sam alorgitam je poprilično jednostavan.
3.2. PSEUDOKOD
Skica programa, napisana u formi na način da se lako može pretovriti u pravi kod. Na
primjer pseudokod za bubble sort
Dijagram toka
Slijedovna struktura
Slijedovna struktura je ugrađena u Visual Basic. Ukoliko nije drugačije određeno,
računar izvršava naredbe Visual Basica jednu nakon druge slijedom kojim su i
napisane.
• If / Then
• If / Then / Else
• Select Case
Sintaksa
If/Then/Else struktura može biti smještena unutar druge If/Then/Else strukture te u
tom slučaju kažemo da je ugnježdena.
Visual Basic osigurava funkciju Switch koja može zamijeniti logiku višestrukih
If/Then/Else struktura.
Ako postoji više vrijednosti u jednoj listi, te vrijednosti su razdvojene zarezima. Visual
Basic izvršava izraze u bloku Case Else (koji je neobavezan) ako ni jedna od
vrijednosti u listama izraza ne odgovara tekstualnom izrazu.
• Do While / Loop
• Do / Loop While
• Do Until / Loop
• Do / Loop Until
For / Next ponavljačka struktura se koristi za ponavljanje izraza unutar petlje točno
određeni broj puta. Za razliku od petlji tipa Do/Loop, petlja ovog tipa koristi varijablu
nazvanu counter (brojač) kojoj se vrijednost povečava ili smanjuje kod svakog
ponavljanja petlje.
Ako postoji više vrijednosti u jednoj listi, te vrijednosti su razdvojene zarezima. Visual
Basic izvršava izraze u bloku Case Else (koji je neobavezan) ako ni jedna od
vrijednosti u listama izraza ne odgovara tekstualnom izrazu.
Sintaksa
Argument indeks sadrži vrijednost od 1 do broja zadnjeg izbora Argument izbor vraća
vrijednost iz liste nabrojenih izbora a prema vrijednosti argumenta indeks.
Print Choose(x,”Crveno”,”Žuto”,”Zeleno”)
Ako je x=1 prikazano je Crveno, za x=2 Žuto a za x=3 Zeleno.
Pisanje programa u asemblerskom jeziku daje programeru potpunu kontrolu nad svim
komponentama ra_cunala. Programer stoga mora poznavati arhitekturu ra_cunala za
koje pi_se program te kontrolirati sve operacije koje ra_cunalo izvr_sava.
Programiranje i najjednostavnijih zada_ca rezultira velikim i slo_zenim programima pa
se programiranje u asembleru koristi se samo za speci__cne zada_ce vezane uz
manipulacije s hardwareom. Izvorni program napisan u asembleru nije prenosiv
izmedu ra_cunala razli_cite arhitekture. Zbog svih tih razloga za ve_cinu
programerskih zada_ca koriste se vi_si programski jezici.
Ćelija . . . varijabla koju promatramo kao zasebnu cjelinu.To je relativan pojam (nešto
se u jednom trenutku može smatrati ćelijom, a kasnije se može gledati unutrašnja
građa iste cjeline). Svaka ćelija ima svoj tip i adresu.
#include <stdio.h>
int main(void)
Funkcija mo_ze uzimati jedan ili vi_se argumenata i obi_cno vra_ca neku vrijednost.
Deklaracijom se uvodi ime funkcije, broj i tip argumenata koje uzima i tip povratne
vrijednosti. U na_sem primjeru ime funkcije je main i ona ne uzima niti jedan
argument. To je deklarirano tako _sto je u oble zagrade stavljena klju_cna rije_c void
(eng. void=prazan). Povratna vrijednost je tipa int, _sto je oznaka za cijeli broj.1
Iza oblih zagrada dolaze viti_caste zagrade koje omeduju tijelo funkcije. Tijelo
funkcije je sastavljeno od deklaracija varijabli i izvr_snih naredbi. Sve deklaracije
varijabli dolaze prije prve izvr_sne naredbe. U na_sem primjeru nemamo deklaracija
varijabli. Tijelo sadr_zi samo dvije naredbe: poziv funkcije printf i return naredbu:
#include <iostream>
using namespace std;
int main()
{
cout << “Hello, world!” << endl;
system("PAUSE");
return 0;
}
Nakon što se sačuva ovaj kod, treba ga kompajlirati, tj. proizvesti izvršnu mašinsku datoteku.
Ovo se izvodi korištenjem kombinacije tipki Ctrl+F9 na tastaturi, ili izborom opcije Compile u
meniju Execute, ili pritiskom na ikonu u nizu alata.
Nakon startanja procesa kompajliranja, pojavljuje se prozor sa porukama koje
prate process kompajliranja. Dev-C++ daje poruku u slučaju da nađe bilo kakvu grešku u
programu. U slučaju da nema grešaka, stvara se izvršna datoteka koja se naziva hello.exe.
1 #include <iostream>
2 using namespace std;
3 int main()
4 {
5 cout << “Hello, world!” << endl;
6 system("PAUSE");
7 return 0;
8 }
ime datoteke. Nađi tu datoteku i odmah je pročitaj. Uglaste zagrade (<>) daju naredbu
predprocesoru da nađe zadatu datoteku koja je dio standardne biblioteke (u datom primjeru to
je datoteka koja sadrži definicije za ispis i upis). U slučaju kada bismo htjeli uvrstiti neku
svoju datoteku, umjesto zagrada bismo koristili znake navoda. Dakle, ova linija kaže
predprocesoru da nađe datoteku koja se zove iostream i da je odmah pročita. Naravno,
sadržaj tražene datoteke bismo mogli upisati u izvornu datoteku bez korištenja direktive
#include.
Linija 2 omogučuje pristup standardnom entitetu (namespace) koji se naziva std. Bez ove
linije, linija 5 bi se morala izvršiti na drugačiji način (std::cout << ....)
Linijom 3 počinje stvarni program sa funkcijom koja se naziva main(). Svaki C++ program
sadrži ovu funkciju. Funkcija predstavlja dio koda koji odrađuje određenu radnju. Inače,
program može da ima proizvoljan broj funkcija, pri čemu je funkcija main() specijalna. Kada
god se program starta, ona se automatski poziva. Sve funkcije počinju zagradom { i
završavaju zagradom }, a sve između ovih zagrada predstavlja dio funkcije.
Glavni dio programa je linija 5, koja predstavlja neku naredbu, tj. računarski korak koji daje
neku vrijednost. Kraj naredbe uvijek zavrčava tačka-zarezom. Naredba u datom primjeru šalje
string "Hello world \n" na tok cout (output stream). String je svaki niz karaktera koji se
nalazi između znaka navoda. Posljednji karakter u datom stringu (\n) je karakter koji
označava novi red. Stream je objekat koji izvršava ulazne i izlazne naredbe. cout je
standardni izlazni stream u C++ (standardni izlazni stream je obično ekran). Simbol << je
izlazni operator (usmjerivač toka) kojem je lijevi operand izlazni stream, a desni izraz, i koji
uzrokuje da se ovaj posljednji posalje na prvopomenuti. Dakle, u ovom slučaju string "Hello
Slika 4.1 ilustruje prethodno navedene korake i za C++ prevodilac i za C++ prirodni
kompajler. U praksi su sve ove komande obično izvršene jednom komandom (npr. CC), a
korisnik ni ne vidi datoteke koje su se napravile u međufazama.
Kada se varijabla definiše, njena vrijednost je nedefinisana sve dok joj se ne pridruži
neka.Pridruživanje vrijednosti nekoj varijabli po prvi put naziva se inicijalizacija. Neophodno
je obezbijediti da se svaka varijabla inicijalizira prije nego se koristi. Također je moguče da se
varijabla definiše i inicializira u isto vrijeme, što je vrlo praktično. Naredni primjer pokazuje
različite načine definisanja i inicijaliziranja varijabli.
#include <iostream>
using namespace std;
main()
{
int a,b,c;
float x = 4.32;
int e,f,g;
char ime;
e = 4;
f = g = 12;
ime = 'C'
}
4.7 Memorija
Za pohranjivanje izvršnog koda kao i podataka sa kojima progam manipuliše, kompjuter ima
na raspolaganju RAM memoriju (Read Access Memory). Memorija se može zamisliti kao
neprekidan
niz bita, od kojih svaki može da pohrani binarni broj (0 ili 1). Obično je memorija podijeljena
na grupe od 8 uzastopnih bita (ovo predstavlja bajt, byte). Bajtovi su uzastopno adresirani,
tako da je svaki bajt jedinstveno predstavljen svojom adresom (Slika 4.2).
#include <iostream>
using namespace std;
int main (void)
{
int radniDani = 22;
float radniSati = 7.5;
float satnica, plata;
cout << "Kolika je satnica? ";
cin >> satnica;
plata = radniDani * radniSati * satnica;
cout << "Plata = ";
cout << plata;
cout << '\n';
}
Linija 9 čita ulaznu vrijednost, koju unosi korisnik i kopira je u satnica. Ulazni operator >>
uzima ulazni stream kao lijevi operand (cin je standardni C++ ulazni stream koji odgovara
podacima unesenim pomoču tastature), a varijablu (na koju se kopira ulazni podatak) kao
desni operand.
4.9 Komentari
Komentar je dio opisnog teksta koji objašnjava neke aspekte programa. Kompajler u
potpunosti ignoriše komentare u programu, tako da je jedina svrha koju komentar ima, da
pomognu onome koji če čitati program. C++ daje dvije mogučnosti pisanja komentara:
#include <iostream>
using namespace std;
/* Ovaj program racuna ukupnu platu radnika, koja se zasniva na ukupnom broju
radnih sati I satnici. */
int main (void)
{
int radniDani = 22; // Broj radnih dana u mjesecu
float radniSati = 7.5; // Broj radnih sati u danu
float satnica = 33.50; // Satnica
float plata; // Ukupna mjesecna plata
plata = radniDani * radniSati * satnica;
cout << “Plata = “ << plata << ‘\n’;
}
Jasno da je da se prvi primjer može koristiti za komentar jedne I samo jedne linije (ili dijela
jedne linije), dok se posljednjim može komentarisati tekts upisan u više linija.
4.10 Imena
Programski jezici koriste imena kako bi se označile različite cjeline koje čine program. Osim
imena varijabli, ovdje spadaju i imena funkcija, tipova, te makroa. C++ postavlja sljedeča
pravila za pravilno kreiranje imena (ili identifikatora). Ime traba da se sastoji od jednog ili više
karaktera, od kojih bilo koji može biti slovo (tj, slova engleske abecede a-z i A-Z), broj (0-9)
i znak "_", pri čemu na prvom mjestu ne može da bude broj. Uz to, velika i mala slova se
razlikuju, tako da se, na primjer, varijable zarada i Zarada razlikuju.
C++ ne postavlja nikakvo ograničenje na broj karaktera u nekom identifikatoru. Međutim,
večina implementacija ima ovo ograničenje, ali je ono toliko veliko da ne predstavlja nikakav
problem (npr. i do 255 karaktera). Treba imati na umu da postoje odrežene riječi u C++ koje
su rezervisane, tako da identifikatori ne mogu uzimati njihova imena. Te riječi se nazivaju
rezervisane ili ključne riječi i date su u tabeli
4.13 Karakteri
Varijabla karakter se definiše tipom char. Ona obuhvata jedan jedini bajt koji sadrži kod
datog karaktera. Ovaj broj je numerička vrijednost i zavisi od sistema kodiranja karaktera koji
se koristi (to je zavisno od mašine). Najčešči sistem je ACSII (Amercan Standard Code for
Information Interchange). Na primjer, karakter A ima ASCII kod 65, a karakter a 97.
Kao i interger i karakter može da bude signed i unsigned. Tako, signed karakter može da
sadrži numeričke vrijednosti između -128 i 127, a unsigned 0 do 255. Karakteri koji imaju
posebnu namjenu (ne predstavljaju karaktere koji se ispisuju) predstavljaju se
pomoču escape sekvenci, kao npr:
‘\n’ – novi red
‘\t’ – novi tabulator
‘\v’ – novi vertikalni tabulator
‘\b’ – backspace
‘\’’ – znak navoda (apostrof)
‘\”’ – dvostruki znak navoda
‘\\’ – backslash (/)
‘\a’ – zvučni signal
4.14 Stringovi
String je uzastopni niz karaktera koji se završavaju nultim karakterom. Tako je, barem, bilo u
jeziku C. Ipak, u C++ uveden je novi tip podataka koji se naziva C++ string klasa, pa je
moguče na mnogo prirodniji način manipulisati varijablama sa više karaktera. Sljedeči primjer
pokazuje njenu upotrebu.
#include <iostream>
using namespace std;
main()
{
char ch;
do {
cout << "Pritisnite K ili k za kraj, a bilo koju tipku za
nastavak \n";
cin >> ch;
Ovaj primjer dobro funkcioniše jer završava program ako se unese "k" ili "K", odnosno
program se nastavlja ako se unese bilo koji drugi karakter. Problem nastaje ako korisnik
programa pritisne samo tipku ENTER. U tom slučaju objekat "cin" očekuje da se unese neka
vrijednost, pa tek onda pritisne ENTER.
4.15 Operatori
Ovo poglavlje obrađuje ugrađene C++ operatore koji se koriste za stvaranje izraza, pri čemu
izraz predstavlja bilo kakav proračun koji daje neku vrijednost. C++ nudi operatore za
izvršavanje aritmetičkih, ralacijskih, logičkih, bitwise i uslovnih izraza. Također nudi veoma
korisne “popratne efekte” (side-effect) kao što su pridruživanje, inkrement i dekrement.
Osim ostatka pri djeljenju (%) svi aritmetički operatori prihvataju miješanje cijelih i realnih
brojeva. Opčenito, ako su oba operanda cijeli brojevi, i rezultat je cijeli broj. Međutim, ako je
jedan od operanada realan, onda je i rezulat realan (tipa double).
Kada su oba operanda pri dijeljenju cijeli brojevi, rezultat je također cijeli broj (tzv.
Cjelobrojno dijeljenje). U tom slučaju rezultat se zaokružuje na donju vrijednost, tj.
9 / 2 // daje 4, a ne 4.5!
Operator % daje ostatak pri dijeljenju dva cijela broja (oba operanda moraju biti cijeli brojevi),
npr. 13%3 daje 1
Treba zapamtiti da se operatori <= i >= mogu korisiti samo u tom obliku, a da =< i => ne
znače ništa u ovom kontekstu.
Operandi nekog relacijskog operatora moraju biti brojevi. No, i karakteri su ispravni operandi
pošto predstavljaju brojnu vrijednost (sjetimo se ASCII tabele).
Relacijski operaotri se ne smiju korisiti ze poređenje stringova, pošto se u tom slučaju porede
njihove adrese, a ne sadržaj. U tom slučaju, rezlutat je neodređen. Ipak, postoje funkcije koje
mogu porediti i leksikografsku razliku dva stringa.
Logička negacija je unarni opearator, tj. ima samo jedan operand kojem daje negativnu
vrijednost.
Kao što se vidi, oba operatora se mogu korisiti u prefiksnom ili postfiksnom obliku. Razlika je
velika, jer kada se operator koristi u prefiksnom obliku prvo se primijenjuje operator, a onda
se u izrazu koristi rezultat. Kada se koristi u postfiksnom obliku, prvo se računa izraz, a onda
se primijenjuje operator.
Oba operatora se mogu primijeniti kako na cjelobrojne, tako i na realne brojeve, iako se ova
karakteristika veoma rijetko koristi na realnim brojevima.
Kako operator pridruživanja sam po sebi predstavlja izraz čija se vrijednost pohranjuje u lijevi
operand, on se može korisititi kao desni operand za narednu operaciju pridruživanja, odnosno
može se napisati:
int m, n, p;
ili
m = 100;
int m = 1, n = 2;
Postoji još nekoliko vrsta operatora (npr. zarez operator, sizeof operator), ali o njema neče biti
riječi u ovom kursu.
4.16. Naredbe
Ovo poglavlje opisuje razne oblike C++ naredbi koje služe za pisanje programa. Kao i večina
ostalih programskih jezika, C++ nudi različite vrste naredbi koje se koriste u različite svrhe.
Tako se deklaracione naredbe koriste za definisanje varijabli, naredbe pridruživanja za
jednostavne proračune, itd. U narednom teksu biče objašnjene neke od njih.
Posljednji primjer pokazuje beskorisnu naredbu, jer nema nikakvih popratnih efekata.
Najjednostavniji oblik naredbe je linija koja sadrži samo tačka-zarez, tzv. null-aredba. No, i
ovakva naredba ponekad ima smisla, što če se pokazati u kasnijem tekstu.
Mnogostruke naredbe se mogu kombinovati u složene naredbe kada se grupišu između velikih
zagrada ({}), kao na primjer
4.2 Naredba if
Ponekad je poželjno da se izvrši određena naredba koja zavisi od ispunjenja nekog uslova.
Upravo tu mogučnost pruža if naredba, čiji je opšti oblik:
Prvo se izvršava izraz, i ako je rezultat različit od nule izvršava se naredba. U suprotnom,
ništa se ne dešava.
Na primjer, ako bismo željeli provjeriti da li je pri djeljenju djelilac različit od nule, imali
bismo:
if (djelilac != 0)
Kolicnik=djelitelj/djelilac;
Da bismo izvršili više naredbi koje ovisi o nekom istom uslovu, koristimo složenu naredbu, tj.
sve naredbe stavljamo između zagrada.
Varijanta if naredbe koja omogučuje da se specificiraju dvije alternativne naredbe, jedna
koja se izvršava kada je uslov ispunjen i druga kada nije, se naziva if-else naredba i ima
oblik:
if (izraz)
naredba;
if (izraz)
naredba1;
else
naredba2;
Ovdje se najprije izvršava izraz, i ako je rezultat različit od nule, izvršava se naredba1. U
suprotnom, izvršava se naredba2, što pokazuje i sljedeči primjer:
#include <iostream>
using namespace std;
main()
{
int x;
cout << "Unesite neki broj";
cin >> x;
if (x % 2 == 0)
cout << "Broj je paran" << endl;
else
cout << "Broj je neparan" << endl;
}
Pored prethodno navedenih varijanti, postoji i ugniježdena if naredba, u kojoj se javljaju više
od dvije alternative. Primjer takve varijente je:
if (callHour > 6) {
if (duzinaPoziva <= 5)
cijena = duzinaPoziva * tarifa1;
else
switch (izraz) {
case konstanta_1:
naredbe;
...
case konstanta_n:
naredbe;
default:
naredbe;
}
#include <iostream>
using namespace std;
main()
{
int ocj;
cout << "Unesite ocjenu: ";
cin >> ocj;
switch (ocj)
{
case 5:
cout << "Imate 90 – 100 bodova" << endl;
break;
case 4:
cout << "Imate 80 – 89 bodova" << endl;
break;
case 3:
cout << "Imate 70 – 79 bodova" << endl;
break;
case 2:
cout << "Imate 60 – 69 bodova" << endl;
break;
default:
cout << "Imate ispod 60 bodova" << endl;
}
}
Prvo se izračunava izraz (naziva se i uslov petlje). Ako je rezultat različit on nule tada se
izvršava naredba (naziva se i tijelo petlje) i cijeli proces se ponavlja. U suprotnom, proces se
zaustavlja.
Na primjer, ako bismo željeli izračunati zbir svih brojeva od 1 do n, upotreba while naredbe
bi izgledala kao:
i = 1;
sum = 0;
while (i <= n)
sum += i++;
Interesantno je da nije neuobičajeno za while naredbu da ima prazno tijelo petlje, tj. null-
naredbu. Takav primjer je problem nalaženja največeg neparnog faktora nekog broja
while (n % 2 == 0 && n /= 2)
;
Ovdje uslov petlje izvršava sve neophodne kalkulacije, tako da nema potrebe za tijelom.
4.5 Naredba do
Naredba do (naziva se i do petlja) je slična naredbi while, osim što se prvo izvršava tijelo
petlje, a zatim se provjerava uslov. Opšti oblik naredbe je:
while (izraz)
naredba;
Prvo se izvršava naredba, a zatim provjerava izraz. Ako je izraz različit od nule cijeli
proces se ponavlja. U suprotnom, petlja se zaustavlja. do petlja se manje koristi nego while
petlja. Obično se koristi kada se tijelo petlje mora izvrčiti najmanje jedanput bez obzira na
ispunjenje uslova. Takav primjer je ponovljeno unošenje nekog broja i izračunavanje
njegovog kvadrata dok se ne unese 0:
do {
cin >> n;
cout << n * n << '\n';
} while (n != 0);
Za razliku od while petlje, do petlja se nikada ne koristi sa praznim tijelom prvenstveno
zbog jasnoće.
sum = 0;
for (i = 1; i <= n; ++i)
sum += i;
Bilo koja od komponenti u petlji može biti prazna. Na primjer, ako se uklone prvi i treči izraz,
onda
Pošto petlje predstavljaju naredbe, mogu se pojaviti unutar drugih petlji (tzv. ugniježdene
petlje).
Na primjer:
5 Funkcije
Tijelo funkcije sadrži računske korake (naredbe) koji čine neku funkciju.
Korištenje funkcije se izvodi njenim pozivanjem. Poziv funkcije se sastoji od imena funkcije,
pračenim zagradama za pozivanje (). Unutar ovih zagrada se pojavljuje nula ili više
argumenata koji se odvajaju zarezom. Broj argumenata bi trebao odgovarati broju parametara
funkcije. Svaki argument je izraz čiji tip bi trebao odgovarati tipu odgovarajučeg parametra u
interfejsu funkcije.
Kada se izvršava poziv funkcije, prvo se računaju argumenti i njihove rezultujuče vrijednosti
se pridružuju odgovarajučim parametrima. Nakon toga se izvršava tijelo funkcije. Na kraju,
funkcija vrača vrijednost (ako ista postoji) pozivu.
Sljedeči primjer ilustrativno pokazuje definiciju jednostavne funkcije koja izračunava
vrijednost stepen cijelog broja na neki cijeli broj.
Linija 1 definiše interfejs funkcije. Ona počinje tipom funkcije koji se vrača (u ovom slučaju
int).
Nakon toga je dato ime funkcije (Stepen), a zatim njena lista parametara. Funkcija Stepen
ima dva parametra (baza i eksponent) koji su tipa int. Sintaksa parametara je slična sintaksi
definisanja varijabli, tj. nakon tipa daje se ime parametra. Međutim, nije moguče nakon tipa
dati niz parametara odvojenih zarezom, kao u
int Stepen (int baza, eksponent) // Ovo je pogrešno!
Zagrada { u liniji 2 predstavlja početak tijela funkcije.
Linija 3 definiše lokalnu varijablu.
Linije 4 i 5 računaju stepen varijable baza na varijablu eksponent pomoču for petlje.
Rezultat se pohranjuje u varijablu rezultat.
#include <iostream>
using namespace std;
main (void)
{
cout << "2 ^ 8 = " << Stepen(2,8) << '\n';
}
Kada se program pokrene daje sljedeči izlaz:
2 ^ 8 = 256
Opčenito, funkcija se treba definisati prije nego se koristi. To se može uraditi na više načina,
kao što je pokazano u narednim primjerima.
Primjer 1.
#include <iostream>
using namespace std;
double Stepen (int baza, int eksponent)
{
double rezultat = 1;
for (int i = 0; i < eksponent; ++i)
rezultat *= baza;
return rezultat;
}
main ()
{
int a,b;
cout << "Unesi bazu:";
cin >> a;
cout << "\nUnesi eksponent:";
cin >> b;
cout << a<<"^" <<b<<" = " << Stepen(a,b) << '\n';
system("PAUSE");
}
Primjer 2.
Treba napomenuti da se deklaracija funkcije sastoji od njenog prototipa, tako da je za
deklarisanje dovoljno ispisati samo njen prototip. Na taj način, kompletna definicija funkcije
se može dati kasnije, kao što je pokazano u narednom primjeru. Također je moguče izostaviti
nazive parametara
u deklaraciji, ali to nije preporučljivo.
#include <iostream>
using namespace std;
double Stepen (int baza, int eksponent); // deklarisanje funkcije
/* moguce je funkciju daklarisati i na sljedeci nacin
double Stepen (int, int);
#include <iostream>
#include “StepenInt.h”
using namespace std;
main ()
{
int a,b;
cout << "Unesi bazu:";
cin >> a;
cout << "\nUnesi eksponent:";
cin >> b;
cout << a<<"^" <<b<<" = " << Stepen(a,b) << '\n';
system("PAUSE");
}
Ovdje treba paziti gdje se datoteka StepenInt.h nalazi. U primjeru koji je dat, ona se nalazi
u istom direktoriju kao i izvršna datoteka. U suprotnom, treba dati tačan (relativni ili
apsolutni) položaj (path) iste.
Pošto lokalni scope poništava globalni, to lokalne varijable sa istim imenom kao globalne
varijable onemogučavaju pristup globalnim varijablama unutar lokalnog scope-a.
Na primjer, u int greska;
void Greska (int greska)
{
//...
}
globalna varijabla greska je nepristupačna unutar funkcije Greska, pošto je poništena
lokalnim parametrom greska.
Ovaj problem se može prevaziči korištenjem unarnog operatora :: (unary scope operator),
koji globalni entitet uzima kao argument, kao u primjeru
int greska;
void Greska (int greska)
{
//...
if (::greska != 0) // odnosi se na globalnu varijablu error
//...
}
Posljednji dio definicije jasno pokazuje da je faktorijel definisan u odnosu na samog sebe, te
se stoga može predstaviti rekurzivnom funkcijom, npr.
int Faktorijel (unsigned int n)
#include <iostream>
#include <cmath>
using namespace std;
int Stepen (int baza, int eksponent)
{
int rezultat = 1;
for (int i = 0; i < eksponent; ++i)
rezultat *= baza;
return rezultat;
}
double Stepen (double baza, double eksponent) // funkcija Stepen sa
realnim parametrima
{
return exp(eksponent*log(baza));
}
double Stepen (double eksponent) // funkcija Stepen sa jednim
parametrom za izračunavanje stepena broja 2
{
return Stepen(2.0,eksponent);
}
main (void)
{
double a,b;
cout << "Unesi bazu:";
cin >> a;
cout << "\nUnesi eksponent:";
6. Polja
Ovo poglavlje objašnjava polja i ilustruje njihovu upotrebu pri definisanju varijabli. Polje se
sastoji od niza objekata (nazivaju se i elementi niza), koji su istog tipa i zauzimaju neprekidan
memorijski prostor. Opčenito, samo polje ima simboličko ime, a ne njegovi elementi. Svaki
elemenat je identificiran njegovim indeksom, koji pokazuje položaj nekog elementa u nizu.
Broj elemenata u nizu naziva se dimenzija polja. Dimenzija polja je fiksirana i prethodno
određena, i ne može se promijeniti u toku izvršenja programa.
Polja su pogodna za predstavljanje podataka koji se sastoje od mnogo sličnih, individualnih
objekata. Primjeri za to su lista imena, tabela gradova i njihovih sezonskih temperatura.
int visina[10];
Pristup individualnim elementima nekog niza vrši se indeksiranjem niza. Prvi elemenat niza
uvijek ima indeks 0. Na taj način, visina[0] i visina[9] označavaju prvi i posljednji
elemenat niza
visina, respektivno. Svaki elemenat niza se može tretirati kao varijabla tipa cijeli broj. Tako,
na primjer, da bi smo trečem elementu ovog niza pridružili vrijednost 177, pisali bismo:
visina[2] = 177;
Pokušaj pristupa nepostoječem elementu nekog niza (na primjer visina[-1] ili visina[10])
može uzrokovati ozbiljnu grešku (tzv. runtime greška, ili greška 'indeks izvan granica’).
Procesiranje bilo kojeg niza obično uključuje korištenje petlje, koja ide kroz niz od elementa
do elementa. Sljedeči primjer pokazuje funkciju koja računa srednju vrijednost nekog niza:
Kao i kod ostalih varijabli, vrijednosti elemenata niza se mogu inicijalizirati. U tu svrhu
koriste se zagrade{}, između kojih se specificira lista početnih vrijednosti elemenata niza koje
su odvojene zarezom. Na primjer, nt broj[3] = {5, 10, 15};
#include <iostream>
using namespace std;
Interesantno je napomenuti da je i C++ string niz karaktera. Tako char str[] = "HELLO";
definiše varijablu str kao niz šest (6) karaktera: pet slova i prazan karakter (null-character).
Završni prazan karakter postavlja kompajler. Za razliku od toga, char str[] = {'H', 'E', 'L', 'L', 'O'};
definiše varijablu str kao niz od 5 elemenata.
Kao i kod jednodimezionalnih nizova, elementima nizova se pristupa preko indeksa. No,
neophodan
je dodatni indeks za svaku dimenziju. Na primjer, srednja temperatura u Sidneju u toku ljeta,
data je
elementom godDobTemp[0][1].
int godDobTemp[3][4] = {
Prolječe Ljeto Jesen Zima
Sidnej 26 34 22 17
Melburn 24 32 19 13
Brizbejn 28 38 25 20
... 32 19 13 28 26 34 22 17 24 38 25 20 ...
First row Second row Third row
Prvi red Drugi red Treči red
26, 34, 22, 17, 24, 32, 19, 13, 28, 38, 25, 20
};
#include <iostream>
using namespace std;
const int redovi = 3;
const int kolone = 4;
int godDobTemp[redovi][kolone] = {
{26, 34, 22, 17},
{24, 32, 19, 13},
{28, 38, 25, 20}
};
int najvecaTemp (int temp[redovi][kolone])
{
int najveca = 0;
for (int i = 0; i < redovi; ++i)
for (int j = 0; j < kolone; ++j)
if (temp[i][j] > najveca)
najveca = temp[i][j];
return najveca;
}
main ()
{
cout << najvecaTemp(godDobTemp) << "\n";
system("PAUSE");
}
7. Datoteke
Ovo poglavlje pokazuje kako se podaci dobiveni pokretanjem nekog programa mogu sačuvati
njihovim pohranjivanjem na neku datoteku. S obzirom da čuvanje podataka nema svrhu ako
tim podacima ne možemo da pristupamo, biče objašnjeno i kako pročitati podatke sa neke
datoteke.
Datoteka, pri tome, predstavlja skup podataka koji su snimljeni na neku formu trajne memorije
(hard disk, CD-ROM, floppy disk, ...). Datoteci se pristupa preko njenog imena (filename), u
čijem sastavu se obično nalazi ekstenzija (dio imena iza tačke), koja označava tip podataka u
datoteci (npr. .doc za Microsoft Word, .xls Microsoft Excel, .cpp za C++ izvršnu datoteku,
itd.).
U osnovi, postoje dvije vrste datoteka: tekstualne i binarne. Tekstualne datoteke sadrže tekst,
dok binarne mogu sadržavati i kompleksnije vrste podataka, kao što su slike, izvršni programi,
baze podataka, itd. Tekstualnim datotekama je nešto jednostavnije pristupiti, pisati podatke u
njih, te čitati sa njih. Upravo to je i razlog zbog čega če se primjeri u ovom poglavlju odnositi
samo na njih.
#include <fstream>
Datoteka fstream definiše tri nova tipa podataka:
ifstream. Ovaj tip podataka predstavlja stream za ulazne datoteke (i se odnosi na input).
Pravac ulaza je sa datoteke prema programu. Ovaj tip podataka se koristi za čitanje
informacija sa datoteka. Ne može se koristiti za kreiranje datoteka i pisanje na njih.
fstream. Ovaj tip podataka predstavlja opčenito stream za datoteke, ima karateristike I
ofstream i ifstream. On može kreirati datoteke, pisati na njih i čitati sa njih.
Datoteka prvo mora da se otvori. Ovo otvara put u komunikaciji između datoteke i stream
objekta u programu (fstream, ifstream, ofstream), koji se koristi u pristupu datoteci.
Nakon otvaranja program čita sa datoteke, piše na nju, ili čini oboje.
Na kraju, program zatvara datoteku. Ovo je bitan korak, pošto održavanje komunikacije
između datoteke i stream objekta zahtijeva resurse, tako da zatvaranje datoteke oslobađa ove
resurse kada više nisu potrebni. Uz to, postoji mogučnost da se kasnije u programu ne može
pristupiti datoteci ako nije zatvorena prije prethodnog pristupa.
ofstream izlaz;
izlaz.open("studenti.txt");
Za razliku od relativnog puta, apsolutni put predstavlja lokaciju koja započinje slovom drajva,
sadržeči sve direktorije i poddirektorije dok se ne dođe do datoteke. Na primjer, ako je
datoteka studenti.txt u direktoriju Pedagoski, a ovaj je podirektorij direktorija UNZE, a sve se
nalazi na tvrdom disku sa slovom C, onda bi se datoteka otvorila na sljedeči način:
ofstream izlaz;
izlaz.open("C:\\MFZE\\Pedagoski\\studenti.txt");
Vidimo da se u tom slučaju koriste po dva znaka \\, jer samo jedan između navodnika
predstavlja escape-sekvencu (poglavlje II.2.10).
Bez obzira da li koristimo relativni ili apsolutni put, argument za funkciju open ne mora da
bude neko ime (riječ), nego i (string) varijabla, kao što je to u sljedečem primjeru:
ofstream izlaz;
char imeDatoteke[80];
cout << "Unesite ime datoteke: ";
cin >> imeDatoteke;
izlaz.open(imeDatoteke);
Važno je zapamtiti da je korištenje relativnog puta bolja opcija, jer se može desiti da neki
direktorij u apsolutnom putu ne postoji, naročito ako se program koristi na nekom drugom
računaru (sa drugačijim direktorijima).
Korištenje drugog argumenta u funkciji open definiše modul u kojem se datoteka treba
otvoriti.
Neke od opcija (tzv. file mode flag), koje se mogu koristiti date su u Tabeli II.7.1.
Tabela II.7.1
Opcija (file mode flag) Opis
ios::app Postoječi sadržaj datoteke je očuvan i sav izlaz se ispisuje na
kraj datoteke.
ios::binary Informacija se na datoteku piše u binarnom obliku.
ios::in Infomacija če se čitati sa datoteke. Datoteka se ne kreira ako ne
postoji.
ios::out Informacija če se zapisati u datoteku. Postoječi sadržaj datoteke
je poništen.
Ako za otvaranje datoteke koristimo ofstream objekat, onda ne moramo koristiti dodatne
ofstream izlaz;
izlaz.open("studenti.txt", ios::app);
Međutim, ako se za otvaranje datoteke za pisanje koristi fstream objekat, treba se dodati još
jedan argument, tj. opcija za pisanje (ios::in). U ovom slučaju bi bilo:
fstream izaz;
izlaz.open("studenti.txt", ios::out);
Jedina razlika je što se, uz korištenje objekta fstream, umjesto objekta ofstream koristi
iostream objekat. Uz to, datoteka sa koje se čita mora postojati, jer se pokretanjem jednog
od prethodnih objekata ne kreira datoteka.
Stoga, otvaranje datoteke za čitanje se može otvoriti na jedan od sljedečih načina:
ifstream ulaz;
ulaz.open("studenti.txt");
fstream ulaz;
ulaz.open("studenti.txt", ios::in); //obavezno dodati argument ios::in
ifstream ulaz("studenti.txt");
fstream ulaz("studenti.txt", ios::in);
fstream izlazUlaz;
izlazUlaz.open("studenti.txt", ios::in | ios::out);
ili pomoču konstruktora: fstream izlazUlaz ("studenti.txt", ios::in | ios::out);
U oba primjera korišten je tzv. bitwise operator (|), koji ima isto značenje kao logički operator
(ili).
Provjera da li je datoteka otvorena. Prije nego počnemo čitati podatke sa neke datoteke,
korisno je znati da li ona uopšte postoji. Provjera se može izvršiti na dva načina. Ako se
datoteka ne može otvoriti za čitanje, onda je: (i)
vrijednost ifstream objekta jednaka NULL (nula), (ii) vrijednost funkcije fail objekta
ifstream je true(1). Sljedeči primjer ilustruje korištenje oba načina.
#include <fstream>
#include <iostream>
using namespace std;
int main (){
ifstream ulaz;
ulaz.open("studenti.txt");
cout << "(ulaz) = " << ulaz << endl;
cout << "(ulaz.fail()) = " << ulaz.fail() << endl;
return 0;
}
Pri čemu 0x22fed4 predstavlja memorijsku lokaciju (adresu) ifstream varijable ulaz.
Za razliku od ifstream objekta, ofstream objekat koji pokušava otvoriti datoteku koja ne
još postoji nije NULL, a njegova fail funkcija ima vrijednost false(0). To je zbog toga što
operativni sistem kreira datoteku, ako ona ne postoji. Ipak, i u ovom slučaju je korisno
provjeriti da li datoteka postoji. Naime, ako datoteka postoji, ali ima osobinu read-only,
dobičemo negativan odgovor o njenom postojanju (vrijednost iostream objekta je NULL, a
funkcije fail je true, tj. 1).
Upotrebom drugog argumenta pri otvaranju datoteke za pisanje (ios::app) možemo dodavati
sadržaj na postoječu datoteku kao što to pokazuje sljedeči primjer. U ovom primjeru
zapisivanje se prekida nakon unosa znakova ***.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main ()
{
string x;
ofstream izlaz;
izlaz.open("podaci.txt", ios::app);
while (x != "***")
{
cout << "Unesite neki tekst (za kraj unesite ***):" << endl;
cin >> x;
izlaz << x << endl;
}
izlaz.close();
}
#include <fstream>
#include <iostream>
using namespace std;
int main (){
string podaci;
ofstream izlaz;
izlaz.open("studenti.txt");
cout << "Upisivanje u datoteku" << endl;
cout << "=====================" << endl;
cout << "Unesite razred: ";
getline(cin,podaci);
izlaz << podaci << endl;
cout << "Unesite broj studenata: ";
cin >> podaci;
cin.ignore();
izlaz << podaci << endl;
izlaz.close();
ifstream ulaz;
cout << "Citanje sa datoteke" << endl;
cout << "===================" << endl;
ulaz.open("studenti.txt");
getline(ulaz,podaci);
cout << podaci << endl;
getline(ulaz,podaci);
cout << podaci << endl;
ulaz.close();
return 0;
}
Međutim, vidimo da je u ovom slučaju korištena C++ string klasa umjesto varijable podaci
tipa
char.
Na taj način se pomoču funkcije getline može ispisati ime razreda koje ima više od jedne
riječi.
Prethodni primjer se može napisati i na programerski adekvatniji način upotrebom funkcija za
čitanje i pisanje na datoteku.
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
bool upisiDatoteku (ofstream&, char*);
bool citajDatoteku (ifstream&, char*);
int main (){
string podaci;
bool status;
ofstream izlaz;
8. Urađeni primjeri
Primjer 8.1
Primjer 8.2
#include <cstdlib>
#include <iostream>
#include <fstream>
ifstream unos;
unos.open("matrica.txt");
for(i=0;i<m;i++)
for(j=0;j<n;j++)
{
cout<<" A["<<i<<"]["<<j<<"] = "; unos>>A[i][j]; cout<<" "<<A[i][j];
B[i][j]=0.;
}
cout<<endl<<endl;
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
cout<<A[i][j]<<"\t";
}
cout<<endl;
}
cout<<"\n\n----------------------------\n";
for(i=0;i<n;i++)
for(j=0;j<n;j++)
for(int k=0;k<n;k++)
{
B[i][j]+=A[i][k]*A[k][j];
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
cout<<B[i][j]<<"\t";
}
cout<<endl;
}
cout<<"\n\n----------------------------\n";
system("PAUSE");
return EXIT_SUCCESS;
}
#include <iostream>
#include <math.h>
using namespace std;
void meni()
{
cout<<"\t::MENI::\n";
cout<<"1. Sabiranje"<< endl;
cout<<"2. Oduzimanje"<< endl;
cout<<"3. Mnozenje"<< endl;
cout<<"4. Djeljenje"<< endl;
cout<<"5. Provjera"<< endl;
cout<<"6. Korijen"<<endl;
cout<<"7. Suma uzastponih brojeva"<<endl;
cout<<"8. EXIT"<< endl;
}
int main(void)
{
float a, b, c;
int izbor, x, y;
do {
meni();
case 2:
{
cout <<"Unesite a i b"<< endl;
cin >> a >> b;
c= a-b;
cout <<"Razlika je: "<< c << endl;
system("pause");
system("cls");
}break;
case 3:
{
cout <<"Unesite a i b"<< endl;
cin >> a >> b;
c= a*b;
cout <<"Proizvod je: "<< c << endl;
system("pause");
system("cls");
}break;
case 4:
{
cout <<"Unesite a i b"<< endl;
cin >> a >> b;
c= a/b;
cout <<"Kolicnik je: "<< c << endl;
system("pause");
system("cls");
}break;
case 5:
{
cout <<"Unesite x i y"<< endl;
}
}while(izbor>0 && izbor<8);
#include <stdio.h>
/* Funkcija binom() racuna binomni koeficijent. */
long binom(int n, int k)
{
long rezult=1;
int i;
if(n == k) return 1;
if(k == 0) return 1;
for(i=n;i>n-k;i--)
rezult=rezult*i;
for(i=1;i<=k;++i)
rezult=rezult/i;
return rezult;
}
int main(void)
{
long bnm;
int n, k;
for(n=0;n<10;n++){
for(k=0;k<=n;k++){
bnm=binom(n,k);
printf("%ld ",bnm);
}
printf("\n");
}
Primjer 8.12.
#include <stdio.h>
#include <math.h>
double epsilon=1.0E-10;
double kosinus_kuta(double x[], double y[]);
int main(void)
{
double a[3], b[3];
double cos_phi;
int i;
printf("Unesite vektor a.\n");
for(i=0;i<3;++i){
printf("a[%d]= ",i+1);
scanf(" %lf",&a[i]);
}
printf("Unesite vektor b.\n");
for(i=0;i<3;++i){
printf("b[%d]= ",i+1);
scanf(" %lf",&b[i]);
}
cos_phi= kosinus_kuta(a, b);
if(fabs(cos_phi) < epsilon){
printf("Vektori su okomiti.\n");