9
Dr. Ţeljko Jurić: Tehnike programiranja /kroz programski jezik C++/ Predavanje 1_a Radna skripta za kurs “Tehnike programiranja” na Elektrotehničkom fakultetu u Sarajevu Akademska godina 2014/15 1 Predavanje 1_a Ovi materijali namijenjeni su onima koji su odslušali kurs Osnove računarstva” na Elektrotehničkom fakultetu u Sarajevu po novom nastavnom programu, kao i svima onima koji već poznaju osnove programiranja u programskom jeziku C, a ţele da preĎu na programski jezik C++. S obzirom da je programski jezik C++ isprva bio zamišljen kao nadgradnja jezika C, gotovo svi programi pisani u jeziku C ujedno predstavljaju ispravne C++ programe. Ipak, kompatibilnost izmeĎu C-a i C++-a nije stoprocentna, tako da postoje neke konstrukcije koje su ispravne u jeziku C, a nisu u jeziku C++. Takvi primjeri će biti posebno istaknuti. S druge strane, bitno je napomenuti da mnoge konstrukcije iz jezika C, mada rade u jeziku C++, treba izrazito izbjegavati u jeziku C++, s obzirom da u jeziku C++ postoje mnogo bolji, efikasniji i sigurniji načini da se ostvari isti efekat. Treba shvatiti da je C++ danas ipak posve novi programski jezik, bitno drugačiji od C-a, mada u principu visoko kompatibilan sa njim. Rješenja koja su dobra (a ponekad i jedina moguća) u C-u, u C++-u mogu biti veoma loša. Stoga biti vrlo dobar programer u C-u najčešće ne znači biti dobar C++ programer. Vrijedi čak obrnuto: ispočetka su nabolji C programeri obično katastrofalno loši C++ programeri, sve dok se ne naviknu na filozofiju novog jezika i na novi način razmišljanja. Stoga će uvodna poglavlja uglavnom biti posvećena onim aspektima jezika C koje nije preporučljivo koristiti u C++-u, dok će specifičnosti načina razmišljanja u C++-u doći kasnije. Verzija (standard) jezika C++ koja će se koristiti u ovim materijalima poznata je kao ISO C++ 2011 ili skraćeno kao C++11, koja je objavljena krajem 2011. godine (prije oficijelnog objavljivanja, dugo vremena koristio se radni naziv C++0x, s obzirom da se očekivalo da će ova verzija biti objavljena najkasnije do 2009. godine, ali se rad na ovoj verziji neplanirao otegnuo). Posljedica ove činjenice da će se neki primjeri iz ovih materijala moći uspješno kompajlirati i izvršiti samo sa najnovijim kompajlerima, koji podrţavaju C++11 standard (nije na odmet napomenuti da je u pripremi i standard C++14, koji predviĎa uglavnom neka minorna poboljšanja standarda C++11). U nekim kompajlerima, podrška za C++11 standard je još uvijek u eksperimentalnoj fazi, tako da je podršku za C++11 potrebno posebno aktivirati podešavajući opcije kompajlera (recimo, u CodeBlocks razvojnom okruţenju, potrebno je aktivirati odgovarajuću opciju na kartici “Compiler” u meniju “Settings”). Bitno je naglasiti da je u standardu C++11 uvedeno toliko mnogo inovacija u odnosu na prethodni standard C++03 (iz 2003. godine, koji se sasvim minorno razlikuje od standarda C++98 godine, koji je bio prije njega), da programi koji koriste mnogo svojstava standarda C++11 neupućenima djeluju kao da su pisani u potpuno novom programskom jeziku, a ne u C++-u. Zapravo, standard C++11 je jezik C++ učinio gotovo dvostruko obimnijim u odnosu na prethodni standard C++03 (što je zaista mnogo, jer je već i standard C++03 bio izuzetno obiman). U ovom kursu, radi nedostatka prostora, neće se koristiti mnogo inovacija standarda C++11 (zapravo, najbitnije inovacije kao što su podrška višenitnom programiranju uopće se neće ni spomenuti), nego će se uglavnom koristiti inovacije koje su lako objašnjive, a koje omogućavaju znatno elegantnije izvoĎenje nekih programskih konstrukcija nego što je to bilo moguće u C++03 odnosno C++98. Počnimo od prvog C programa iz većine udţbenika o C-u tzv. “Hello world” / “Vozdra raja” programa: #include <stdio.h> main() { /* NEISPRAVNO OD C++98 NADALJE! */ printf("Vozdra raja!\n"); return 0; } Čak ni ovaj posve jednostavan C program nije ispravan u C++-u počev od standarda C++98 nadalje (inače, u ovim materijalima, svi neispravni kodovi prikazivaće se crveno, a ispravni plavo). Naime, u ovom primjeru, funkcija “main” nema povratni tip. U C-u se tada podrazumijeva da je povratni tip “int”, dok se u C++-u povratni tip uvijek mora navoditi. Dakle, u C++-u bi ispravna bila sljedeća varijanta: #include <stdio.h> int main() { printf("Vozdra raja!\n"); return 0; } Ovo je, bar za sada, ispravno C++ rješenje. MeĎutim, već pojavom sljedećeg C++ standarda, postoji velika mogućnost da se ni ovo rješenje neće smatrati ispravnim. Naime, standardna biblioteka funkcija prilagoĎena jeziku C, kojoj izmeĎu ostalog pripada i zaglavlje “stdio.h”, ne uklapa se dobro u neke moderne koncepte

Predavanje 1 A

  • Upload
    amer

  • View
    6

  • Download
    2

Embed Size (px)

DESCRIPTION

c++

Citation preview

  • Dr. eljko Juri: Tehnike programiranja /kroz programski jezik C++/ Predavanje 1_a Radna skripta za kurs Tehnike programiranja na Elektrotehnikom fakultetu u Sarajevu Akademska godina 2014/15

    1

    Predavanje 1_a

    Ovi materijali namijenjeni su onima koji su odsluali kurs Osnove raunarstva na Elektrotehnikom fakultetu u Sarajevu po novom nastavnom programu, kao i svima onima koji ve poznaju osnove programiranja u programskom jeziku C, a ele da preu na programski jezik C++. S obzirom da je programski jezik C++ isprva bio zamiljen kao nadgradnja jezika C, gotovo svi programi pisani u jeziku C ujedno predstavljaju ispravne C++ programe. Ipak, kompatibilnost izmeu C-a i C++-a nije stoprocentna, tako da postoje neke konstrukcije koje su ispravne u jeziku C, a nisu u jeziku C++. Takvi primjeri e biti posebno istaknuti. S druge strane, bitno je napomenuti da mnoge konstrukcije iz jezika C, mada rade u jeziku C++, treba izrazito izbjegavati u jeziku C++, s obzirom da u jeziku C++ postoje mnogo bolji, efikasniji i sigurniji naini da se ostvari isti efekat. Treba shvatiti da je C++ danas ipak posve novi programski jezik, bitno drugaiji od C-a, mada u principu visoko kompatibilan sa njim. Rjeenja koja su dobra (a ponekad i jedina mogua) u C-u, u C++-u mogu biti veoma loa. Stoga biti vrlo dobar programer u C-u najee ne znai biti dobar C++ programer. Vrijedi ak obrnuto: ispoetka su nabolji C programeri obino katastrofalno loi C++ programeri, sve dok se ne naviknu na filozofiju novog jezika i na novi nain razmiljanja. Stoga e uvodna poglavlja uglavnom biti posveena onim aspektima jezika C koje nije preporuljivo koristiti u C++-u, dok e specifinosti naina razmiljanja u C++-u doi kasnije.

    Verzija (standard) jezika C++ koja e se koristiti u ovim materijalima poznata je kao ISO C++ 2011 ili skraeno kao C++11, koja je objavljena krajem 2011. godine (prije oficijelnog objavljivanja, dugo vremena koristio se radni naziv C++0x, s obzirom da se oekivalo da e ova verzija biti objavljena najkasnije do 2009. godine, ali se rad na ovoj verziji neplanirao otegnuo). Posljedica ove injenice da e se neki primjeri iz ovih materijala moi uspjeno kompajlirati i izvriti samo sa najnovijim kompajlerima, koji podravaju C++11 standard (nije na odmet napomenuti da je u pripremi i standard C++14, koji predvia uglavnom neka minorna poboljanja standarda C++11). U nekim kompajlerima, podrka za C++11 standard je jo uvijek u eksperimentalnoj fazi, tako da je podrku za C++11 potrebno posebno aktivirati podeavajui opcije kompajlera (recimo, u CodeBlocks razvojnom okruenju, potrebno je aktivirati odgovarajuu opciju na kartici Compiler u meniju Settings).

    Bitno je naglasiti da je u standardu C++11 uvedeno toliko mnogo inovacija u odnosu na prethodni standard C++03 (iz 2003. godine, koji se sasvim minorno razlikuje od standarda C++98 godine, koji je bio prije njega), da programi koji koriste mnogo svojstava standarda C++11 neupuenima djeluju kao da su pisani u potpuno novom programskom jeziku, a ne u C++-u. Zapravo, standard C++11 je jezik C++ uinio gotovo dvostruko obimnijim u odnosu na prethodni standard C++03 (to je zaista mnogo, jer je ve i standard C++03 bio izuzetno obiman). U ovom kursu, radi nedostatka prostora, nee se koristiti mnogo inovacija standarda C++11 (zapravo, najbitnije inovacije kao to su podrka vienitnom programiranju uope se nee ni spomenuti), nego e se uglavnom koristiti inovacije koje su lako objanjive, a koje omoguavaju znatno elegantnije izvoenje nekih programskih konstrukcija nego to je to bilo mogue u C++03 odnosno C++98.

    Ponimo od prvog C programa iz veine udbenika o C-u tzv. Hello world / Vozdra raja programa:

    #include

    main() { /* NEISPRAVNO OD C++98 NADALJE! */

    printf("Vozdra raja!\n");

    return 0;

    }

    ak ni ovaj posve jednostavan C program nije ispravan u C++-u poev od standarda C++98 nadalje (inae, u ovim materijalima, svi neispravni kodovi prikazivae se crveno, a ispravni plavo). Naime, u ovom primjeru, funkcija main nema povratni tip. U C-u se tada podrazumijeva da je povratni tip int, dok se u C++-u povratni tip uvijek mora navoditi. Dakle, u C++-u bi ispravna bila sljedea varijanta:

    #include

    int main() {

    printf("Vozdra raja!\n");

    return 0;

    }

    Ovo je, bar za sada, ispravno C++ rjeenje. Meutim, ve pojavom sljedeeg C++ standarda, postoji velika mogunost da se ni ovo rjeenje nee smatrati ispravnim. Naime, standardna biblioteka funkcija prilagoena jeziku C, kojoj izmeu ostalog pripada i zaglavlje stdio.h, ne uklapa se dobro u neke moderne koncepte

  • Dr. eljko Juri: Tehnike programiranja /kroz programski jezik C++/ Predavanje 1_a Radna skripta za kurs Tehnike programiranja na Elektrotehnikom fakultetu u Sarajevu Akademska godina 2014/15

    2

    jezika C++. Stoga e veina kompajlera na gornji program dati upozorenje da je upotreba zaglavlja stdio.h pokuena odnosno izrazito nepreporuljiva (engl. deprecated) u jeziku C++ i da vjerovatno u budunosti nee biti podrana (pokuene osobine jezika su one osobine za koje je ustanovljeno da se ne uklapaju dobro u filozofiju jezika i za koje nema garancije da e ih budui standardi jezika i dalje podravati, tako da ih treba prestati koristiti). Umjesto toga, poev od C++98 standardu, napravljene su nove verzije zaglavlja standardne biblioteke za one elemente jezika C++ koji su naslijeeni iz jezika C, a koje su napravljene tako da se bolje uklapaju u koncepte jezika C. Stoga, ukoliko je pqr.h naziv nekog zaglavlja standardne biblioteke jezika C, u C++-u umjesto njega treba koristiti zaglavlje imena cpqr, dakle, bez sufiksa .h i sa prefiksom c (npr. cstdio umjesto stdio.h, cmath umjesto math.h, cctype umjesto ctype.h, itd.). Stoga, potpuno ispravna verzija gornjeg programa u C++-u (poev od standarda C++98 nadalje) glasi ovako:

    #include

    int main() {

    std::printf("Vozdra raja!\n");

    return 0;

    }

    Ovdje vidimo jo jednu novinu: specifikator std:: ispred imena funkcije printf. Ovo je jedna od novina zbog koje su uope i uvedena nova zaglavlja tzv. imenici (engl. namespaces). Imenici su osobina jezika C++ koja je uvedena tek u standardu C++98 (tj. relativno skoro). Naime, pojavom velikog broja nestandardnih biblioteka razliitih proizvoaa bilo je nemogue sprijeiti konflikte u imenima koje mogu nastati kada dvije razliite biblioteke upotrijebe isto ime za dva razliita objekta ili dvije razliite funkcije. Na primjer, biblioteka za rad sa bazama podataka moe imati funkciju nazvanu update (za auriranje podataka u bazi), dok neki autor biblioteke za rad sa grafikom moe odabrati isto ime update za auriranje grafikog prikaza na ekranu. Tada mogu nastati problemi ukoliko isti program koristi obje biblioteke poziv funkcije update postaje nejasan, jer se ne zna na koju se funkciju update misli. Zbog toga je odlueno da se imena (identifikatori) svih objekata i funkcija mogu po potrebi razvrstavati u imenike (kao to se datoteke mogu razvrstavati po folderima). Dva razliita objekta ili funkcije mogu imati isto ime, pod uvjetom da su definirani u razliitim imenicima. Identifikatoru ime koji se nalazi u imeniku imenik pristupa se pomou konstrukcije imenik :: ime. Dalje, standard propisuje da se svi identifikatori koji spadaju u standardnu biblioteku jezika C++ moraju nalaziti u imeniku std. Odatle potie specifikacija std::printf. Slinu specifikaciju bismo morali dodati ispred svih drugih objekata i funkcija iz standardne biblioteke (npr. std::sqrt za funkciju sqrt iz zaglavlja cmath, koja rauna kvadratni korijen).

    Stalno navoenje imena imenika moe biti naporno, stoga je mogue pomou kljune rijei using navesti da e se podrazumijevati da se neki identifikator uzima iz navedenog imenika, ukoliko se ime imenika izostavi. Sljedei primjer pokazuje takav pristup:

    #include

    using std::printf;

    int main() {

    printf("Vozdra raja!\n");

    return 0;

    }

    Ovim smo naveli da se podrazumijeva da identifikator printf uzimamo iz imenika std, ako se drugaije ne kae eksplicitnim navoenjem imenika ispred identifikatora. Moemo takoer rei da se neki imenik (u naem primjeru std) podrazumijeva ispred bilo kojeg identifikatora ispred kojeg nije eksplicitno naveden neki drugi imenik, na nain kao u sljedeem primjeru:

    #include

    using namespace std;

    int main() {

    printf("Vozdra raja!\n");

    return 0;

    }

    Mada je u kratkim programima ovakvo rjeenje vjerovatno najjednostavnije, ono se ipak ne preporuuje, jer na taj nain u program uvozimo cijeli imenik, ime naruavamo osnovni razlog zbog kojeg su imenici uope uvedeni. Imenik std je zaista veoma bogat i uvoenjem cijelog ovog imenika postaje sasvim mogue da e se neko ime koje postoji u ovom imeniku poklopiti sa imenom neke promjenljive, objekta ili

  • Dr. eljko Juri: Tehnike programiranja /kroz programski jezik C++/ Predavanje 1_a Radna skripta za kurs Tehnike programiranja na Elektrotehnikom fakultetu u Sarajevu Akademska godina 2014/15

    3

    funkcije koju programer definira u svom programu (pogotovo ako se kao identifikatori koriste engleska imena), to moe uzrokovati konflikte koji se teko otkrivaju. Zbog toga emo u nastavku ovih materijala uvijek eksplicitno navoditi prefiks std:: ispred svih identifikatora koji pripadaju standardnoj biblioteci. Ovo ima dodatnu prednost to e se itaoci na taj nain podsvjesno pamtiti koji identifikatori pripadaju standardnoj biblioteci. One koje nervira stalno navoenje std:: prefiksa mogu, na sopstveni rizik, koristiti naredbu using, ali mi je u nastavku neemo koristiti.

    Mada su prethodni primjeri dotjerani tako da budu u potpunosti po standardu jezika C++, oni jo uvijek nisu u duhu jezika C++, zbog koritenja biblioteke cstdio i njene funkcije printf, koje su isuvie niskog nivoa sa aspekta jezika C++, koji je konceptualno jezik vieg nivoa nego C (zapravo, C++ je hibridni jezik, u kojem se moe programirati na niskom nivou, na visokom nivou, u proceduralnom, neobjektnom stilu, kao i u objektno-orijentiranom stilu, pa ak i u nekim apstraktnim stilovima kao to su generiki i funkcionalni stil programiranja, za razliku od jezika kao to je Java, koji forsira iskljuivo objektno-orijentirani stil, i kad treba, i kad ne treba). Slijedi primjer koji radi isto to i svi prethodni primjeri, samo to je pisan u duhu jezika C++:

    #include

    int main() {

    std::cout

  • Dr. eljko Juri: Tehnike programiranja /kroz programski jezik C++/ Predavanje 1_a Radna skripta za kurs Tehnike programiranja na Elektrotehnikom fakultetu u Sarajevu Akademska godina 2014/15

    4

    objekat cout, kojem se alje znak za novi red. Krajnji rezultat je ponovo objekat cout, ali tu injenicu moemo ignorirati, s obzirom da jezik C++, slino jeziku C, dozvoljava da se krajnji rezultat ma kakvog izraza ignorira (recimo, i funkcija printf daje kao svoj rezultat broj ispisanih znakova, ali se taj rezultat gotovo uvijek ignorira). U duhu jezika C, prethodna naredba napisala bi se ovako: std::printf("2 + 3 = %d\n", 2 + 3);

    U zaglavlju iostream je definiran i objekat za prelazak u novi red endl. Logiki gledano, on ima slinu ulogu kao i string "\n", mada u izvedbenom smislu postoje znaajne razlike (u efektivnom smislu, razlika je to upotreba objekta endl uvijek dovodi do pranjenja spremnika izlaznog toka, to moe biti znaajno kod tokova vezanih za datoteke). Stoga smo mogli pisati i:

    std::cout

  • Dr. eljko Juri: Tehnike programiranja /kroz programski jezik C++/ Predavanje 1_a Radna skripta za kurs Tehnike programiranja na Elektrotehnikom fakultetu u Sarajevu Akademska godina 2014/15

    5

    Isti program, napisan u duhu C-a, mogao bi izgledati recimo ovako: #include

    int main() { int broj_1, broj_2;

    std::printf("Unesite prvi broj: ");

    std::scanf("%d", &broj_1); std::printf("Unesite drugi broj: ");

    std::scanf("%d", &broj_2);

    std::printf("Zbir brojeva %d i %d glasi %d\n", broj_1, broj_2, broj_1 + broj_2);

    return 0;

    }

    Primijetimo da nas objekat ulaznog toka takoer oslobaa potrebe da vodimo rauna o tipu podataka koje unosimo, i da eksplicitno prenosimo adresu odredine promjenljive pomou operatora &, to moramo raditi pri upotrebi funkcije scanf. Za razliku od operatora umetanja, desni operand kod operatora izdvajanja ne moe biti proizvoljan izraz, ve samo promjenljiva, ili neki objekat iza kojeg postoji rezervirani prostor u memoriji, kao to je npr. element niza, dereferencirani pokaziva, itd. (takvi objekti nazivaju se l-vrijednosti, engl. l-values).

    Promjenljive se u jeziku C++ deklariraju na isti nain kao u jeziku C, i za njihova imenovanja vrijede ista pravila kao u jeziku C, uz iznimku da C++ posjeduje vie kljunih rijei od jezika C, tako da postoji vei broj rijei koje ne smiju biti imena promjenljivih (tako, npr. friend i this ne mogu biti imena promjenljivih u C++-u, a mogu u C-u, jer si u C++-u friend i this kljune rijei). Prema standardu C++11, kljune rijei u jeziku C++ su sljedee:

    alignas alignof and and_eq

    asm auto bitand bitor

    bool break case catch

    char char16_t char32_t class

    compl const constexpr const_cast

    continue decltype default delete

    do double dynamic_cast else

    enum explicit export extern

    false float for friend

    goto if inline int long mutable namespace new

    noexcept not not_eq nullptr

    operator or or_eq private

    protected public register reinterpret_cast

    return short signed sizeof

    static static_assert static_cast struct

    switch template this thread_local

    throw true try typedef

    typeid typename union unsigned

    using virtual void volatile

    wchar_t while xor xor_eq

    Radi lakeg uoavanja, rezervirane rijei se u programima obino prikazuju podebljano, to je uinjeno i u dosadanjim primjerima, i to e biti ubudue primjenjivano u svim primjerima koji slijede.

    Slino kao kod operatora umetanja, rezultat operatora izdvajanja primijenjen nad objektom ulaznog toka daje kao rezultat ponovo sam objekat ulaznog toka, to omoguava ulanavanje i ovog operatora. Recimo, konstrukcija poput

    std::cin >> a >> b >> c;

    ima isto dejstvo kao da smo napisali

    std::cin >> a;

    std::cin >> b;

    std::cin >> c;

    Ovo je iskoriteno u sljedeem primjeru, u kojem se sa tastature uitavaju tri cijela broja, a zatim ispisuju na ekran, svaki u novom redu:

  • Dr. eljko Juri: Tehnike programiranja /kroz programski jezik C++/ Predavanje 1_a Radna skripta za kurs Tehnike programiranja na Elektrotehnikom fakultetu u Sarajevu Akademska godina 2014/15

    6

    #include

    int main() {

    int a, b, c;

    std::cin >> a >> b >> c;

    std::cout = 0. Meutim, kako su ova dva izraza meusobno povezana zarezom, oni se tretiraju kao jedan sloeni izraz. U ovom sluaju, zarez nema ulogu razdvojnika (separatora) nego poveznika koji dva ili vie izraza povezuje u jedan sloeni izraz (zarez upotrijebljen na ovaj nain naziva se zarez-operator, ili engl. comma operator). Dakle, nailaskom na while petlju, izvravaju se oba podizraza sloenog izraza koji se nalazi u zagradi. Prvo e se izvriti podizraz std::cin >> x koji e izvriti unos cijelog broja sa tastature u promjenljivu x, a nakon toga e se izvriti podizraz x >= 0 koji testira da li je unesena vrijednost vea ili jednaka od nule. Meutim, kao rezultat tog sloenog izraza uzima se samo rezultat posljednjeg izraza (tj. rezultat obavljenog testiranja), tako da e se na osnovu tog testiranja odluiti da li emo uope ui u tijelo petlje ili ne (tijelo petlje se ovdje sastoji samo od naredbe koja ispisuje kvadrat unesenog broja). Nakon eventualno obavljenog ispisa, vraamo se ponovo na uvjet petlje, u kojem se ponovo vre dvije akcije: unos novog broja i njegovo testiranje na nenegativnost. Ovakve konstrukcije na prvi pogled nisu posve oigledne, ali se prilino esto koriste, kako u C-u, tako i u C++-u.

    Pogledajmo sada kako se u kontekstu ovoga to smo upravo objasnili interpretira izraz

    std::cin >> a, b, c; /* OVO NE RADI DOBRO!!! */

    Osnovni problem kod ovako formiranog izraza to se on zapravo interpretira kao objedinjenje tri izraza std::cin >> a, b i c u jednu cjelinu. Mada e se sva tri izraza izvriti, samo prvi od njih zaista obavlja unos sa tastature (drugi i trei izraz, odnosno izrazi b i c nee proizvesti nikakvu akciju). Posljedica e biti da e samo vrijednost promjenljive a biti unesena sa tastature, dok e promjenljive b i c ostati kakve su bile i ranije. Jo jednom treba napomenuti da je injenica da zarez u nekim sluajevima slui kao separator (tj. kao razdvaja vie stavki u nekom popisu, kao recimo prilikom deklaracije promjenljivih), dok u nekim sluajevima slui kao poveznik, i da treba tano znati kad je u pitanju jedna a kad druga uloga, dovodi do estih zabuna u C i C++ programima (teta je to za funkciju povezivanja u ovim jezicima nije upotrijebljen neki drugi znak a ne ba zarez zabune bi tada bile mnogo rjee).

  • Dr. eljko Juri: Tehnike programiranja /kroz programski jezik C++/ Predavanje 1_a Radna skripta za kurs Tehnike programiranja na Elektrotehnikom fakultetu u Sarajevu Akademska godina 2014/15

    7

    Razmotrimo sada malo detaljnije ta se tano deava prilikom upotrebe ulaznog toka. Svi znakovi koje korisnik unese sve do pritiska na taster ENTER uvaju se u spremniku (baferu) ulaznog toka. Meutim, operator izdvajanja vri izdvajanje iz ulaznog toka samo do prvog razmaka ili do prvog znaka koji ne odgovara tipu podataka koji se izdvaja (npr. do prvog znaka koji nije cifra u sluaju kada izdvajamo cjelobrojni podatak). Preostali znakovi i dalje su pohranjeni u spremniku ulaznog toka. Sljedea upotreba operatora izdvajanja e nastaviti izdvajanje iz niza znakova zapamenog u spremniku. Tek kada se ulazni tok isprazni, odnosno kada se istroe svi znakovi pohranjeni u spremniku bie zatraen novi unos sa ulaznog ureaja. Sljedea slika prikazuje nekoliko moguih scenarija prilikom izvravanja programa prikazanog u dnu stranice 6. (kurzivom su prikazani podaci koje unosi korisnik nakon to se program pokrene):

    Ovakvo ponaanje je u nekim sluajevima povoljno, ali u nekim nije. Nekada elimo da smo uvijek sigurni da e operator izdvajanja proitati svjee unesene podatke, a ne neke podatke koji su od ranije preostali u spremniku ulaznog toka. Zbog toga je mogue pozivom funkcije ignore nad objektom ulaznog toka cin isprazniti ulazni tok (u jeziku C++ postoje funkcije koje se ne pozivaju samostalno, nego uvijek nad nekim objektom, pri emu je sintaksa takvog poziva objekat. funkcija(argumenti), o emu emo kasnije detaljno priati. Ova funkcija ima dva argumenta, od kojih je prvi cjelobrojnog tipa, a drugi znakovnog tipa (tipa char). Ona uklanja znakove iz ulaznog toka, pri emu se uklanjanje obustavlja ili kada se ukloni onoliko znakova koliko je zadano prvim argumentom, ili dok se ne ukloni znak zadan drugim argumentom. Na primjer, naredba

    std::cin.ignore(50, '.');

    uklanja znakove iz ulaznog toka dok se ne ukloni 50 znakova, ili dok se ne ukloni znak '.'. Ova naredba se najee koristi da kompletno isprazni ulazni tok. Za tu svrhu, treba zadati naredbu poput

    std::cin.ignore(10000, '\n');

    Ova naredba e uklanjati znakove iz ulaznog toka ili dok se ne ukloni 10000 znakova, ili dok se ne ukloni oznaka kraja reda '\n' (nakon ega je zapravo ulazni tok prazan). Naravno, kao prvi parametar smo umjesto 10000 mogli staviti neki drugi veliki broj (na je cilj zapravo samo da uklonimo sve znakove dok ne uklonimo oznaku kraja reda, ali moramo neto zadati i kao prvi parametar). Opisana tehnika je iskoritena u sljedeoj sekvenci naredbi:

    int broj_1, broj_2; std::cout > broj_1;

    std::cin.ignore(10000, '\n');

    std::cout > broj_2;

    Izvrenjem ovih naredbi emo biti sigurni da e se na zahtjev Unesi drugi broj: zaista traiti unos broja sa tastature, ak i ukoliko je korisnik prilikom zahtjeva Unesi prvi broj: unio odmah dva broja.

    U sluaju unosa pogrenih podataka (npr. ukoliko se oekuje broj, a ve prvi uneseni znak nije cifra), ulazni tok e dospjeti u tzv. neispravno stanje. Da je tok u neispravnom stanju, moemo provjeriti primjenom operatora negacije ! nad objektom toka. Rezultat je taan ako i samo ako je tok u neispravnom stanju, to moemo iskoristiti kao uvjet unutar naredbe if, while ili for. Ovo ilustrira sljedei fragment:

    int broj;

    std::cout > broj;

    if(!std::cin) std::cout

  • Dr. eljko Juri: Tehnike programiranja /kroz programski jezik C++/ Predavanje 1_a Radna skripta za kurs Tehnike programiranja na Elektrotehnikom fakultetu u Sarajevu Akademska godina 2014/15

    8

    Kao uvjet unutar naredbi if, while i for, moe se iskoristiti i sam objekat toka, koji se tada interpretira kao taan ako i samo ako je u ispravnom stanju. Tako se prethodni isjeak mogao napisati i ovako:

    int broj;

    std::cout > broj;

    if(std::cin) std::cout broj;

    }

    std::cout > broj) koji e oitati vrijednost promjenljive broj iz ulaznog toka a zatim testirati stanje toka. Rezultat ovog izraza bie taan ili netaan u zavisnosti od stanja toka, odnosno on predstavlja sasvim ispravan uvjet, koji se moe iskoristiti za kontrolu while petlje! Kada uzmemo sve ovo u obzir, nije teko shvatiti kako radi sljedei programski isjeak: int broj;

    std::cout > broj)) {

    std::cout

  • Dr. eljko Juri: Tehnike programiranja /kroz programski jezik C++/ Predavanje 1_a Radna skripta za kurs Tehnike programiranja na Elektrotehnikom fakultetu u Sarajevu Akademska godina 2014/15

    9

    std::cin.clear();

    std::cin.ignore(10000, '\n');

    }

    std::cout