Ako već nisu čuli za C++, za C su čuli svi oni koji su se makar u tragovima susretali s programiranjem. Programski jezik C ima korijene u davnoj prošlosti, početkom sedamdesetih godina prošloga stoljeća je već bio definiran kao novi programski jezik. Zbog toga, C i njegove kasnije inačice uvukle su se u sve pore softverske industrije te je C dobio status klasičnoga programskoga jezika s kojim se najčešće sve počinje pri početku učenja programiranja.

C je programski jezik relativno niske razine što znači da programer ima prilično dobar uvid u pozadinske radnje koje se odvijaju prilikom programiranja. Tako npr., u usporedbi s Pythonom, u C-u je potrebno definirati tip svake varijable, adresa varijable (pointer, pokazivač) se mora dohvaćati eksplicitno te ukratko, programer mora paziti na puno više stvari prilikom programiranja u C-u u odnosu na Python.

Zbog toga, učenje C-a ili njegove naprednije varijante C++-a predstavlja savršenu priliku za bolje razumijevanje načina rada programskog jezika te izvršavanja programa.

U tekstu se bavimo programskim jezikom C++. Ta je varijanta nastala izravno iz programskoga jezika C dok je iz C++-a izvedena varijanta C# (C sharp). Za početnika, razlika između C-a i C++-a je minimalna. Sintaksa je jednaka, no C++ uvodi mogućnost objektno orijentiranog pristupa što je praktički i jedini nedostatak C-a u odnosu na C++, Python ili Javu. Učenjem C++a ćete automatski naučiti i C zbog minornih razlika. Osim dodane mogućnosti objektno orijentiranoga pristupa, razlike se očituju u sitnicama pri pripremi datoteke koja će sadržavati kôd koji se upisuje te načinu na koji se vrši ispis podataka na ekran.

C++: Hello World!


Programiranje u C++ jeziku, kao i za svaki drugi jezik, najbolje je početi klasičnim primjerom: ispis poruke “Hello World!”. Za početak, uputit ćemo vas što je potrebno imati na računalu za programiranje u C++-u. Ako ste linuksaš, preporučujemo program Geany koji možete skinuti preko ugrađenoga Software Centera. Unutar Geanya možete i pisati i pokretati vaše programe.

Ukoliko se dogodi da nemate instaliran kompajler za C++, instalirate ga upisom u Terminal [sudo apt-get install build-essential]. Time dobivate kompajlere za C i C++. Programe možete pokretati i iz Terminala, tako što ih prvo kompajlirate pomoću [g++ datoteka_s_kôdom -o ime_programa] u mapi u kojoj se nalazi vaš kôd pri čemu je rezultat te linije u Terminalu program u istoj toj mapi imena “ime_programa”. Nakon toga ga jednostavno pokrećete pomoću [./ime_programa].

 

c-hello-world

Za Windows okruženje preporučamo program Dev-C++, koji je malen, lagan za korištenje te što je najvažnije besplatan. Unutar njega također imate mogućnosti i pokretati program nakon kompajliranja. U članku ćemo odabrati pristup na Ubuntu operativnom sustavu. Ako ste linuksaš, predlažemo pisanje kôda u Geanyu, a kompajliranje i izvršavanje u Terminalu jer tako ćete bolje uvještiti i rad u Terminalu, a ispisi su točno onakvi kakvi će biti i korištenjem programa bez Geanya (što i je cilj programiranja: napraviti aplikaciju koju pokrećete iz Terminala). Inače, sintaksa i način pisanja programa je jednak bez obzira na operativni sustav tako da odabir platforme nije od ključnoga značaja. U okviru sa strane je prvi primjer programa u jeziku C++.

Program jednostavno ispisuje poruku “Hello World” te završava s radom. Napomenimo da će sve linije osim šeste biti zajedničke svim programima koje ćemo obraditi u ovom članku. Jedino šesta linija kôda zapravo ispisuje poruku na ekran dok su ostale zapravo podrška kako bi se uopće moglo išta izvršiti. Neke od tih linija su obavezne, neke nisu, no svakako preporučujemo da i te neobavezne uvijek koristite te da vam uđu u naviku. Prva linija kôda je obavezna ukoliko program radi upis ili ispis podataka.

Svaki vaš program će sigurno obavljati upis, ispis ili oboje, svejedno jesu li u pitanju ekran i tipkovnica ili datoteka jer nema smisla da program odradi posao koji ni na koji način neće biti zabilježen. Općenito, linije koje počinju znakom “#” su direktive kompajleru. Ukratko ćemo objasniti kako uopće funkcionira kompajler, kako bi bilo jasnije što uopće predstavljaju direktive. Kôd koji upisujete je za računalo tekstualna datoteka, baš kao i ona napisana u Notepadu, Wordu ili bilo kojem drugom tekst editoru.

Pri kompajliranju, datoteka se analizira red po red te se iz tih dijelova kôda stvara izvršna datoteka koju računalo može pokrenuti kao program. Svaka linija kôda se na neki način izravno pretvara u strojni kôd, kojeg je procesor u stanju pokrenuti, a koji obavlja tu radnju koja je zamišljena tom linijom kôda. Izuzetak su upravo direktive, koje se ne kompajliraju, nego na neki način mijenjaju ponašanje kompajlera ili izgled upisanog kôda.

Tako, naredba “#include” učitava tzv. header koji je datoteka smještena na računalu i sadrži definicije određenih funkcija. U našem slučaju, linija kôda [#include ] učitava modul potreban za baratanje s takozvanim Input/Output STREAMovima odnosno tokovima podataka za upis i ispis. Pri kompajliranju, umjesto ove linije doslovno se učituje ogroman broj linija kôda koji je potreban da bismo koristili upise i/ili ispise.

c++ #include

 

To se odvija u pozadini i postupak je za programera nevidljiv, no poznavanje svrhe headera je nužno. Dogodit će se recimo da upotrijebite nekakvu funkciju te kompajler izbaci grešku da funkcija nije definirana. U tom slučaju, ako ste sigurni da ta funkcija zaista postoji, jednostavno ćete pomoću include-a učitati modul koji sadrži definiciju te funkcije. Treća linija kôda je obavezna, a predstavlja namespace koji se koristi.

Nema potrebe detaljno se upuštati u objašnjenje ove linije kôda, no ipak se običnim rječnikom može reći sljedeće: definiramo korištenje (using) standardnog (std) namespace-a. Primjetite znak točka-zarez na kraju retka – taj znak je obavezan na kraju svakog naredbenog retka unutar kôda odnosno nakon svake naredbe (poziv funkcije, matematički izraz) stavlja se točka-zarez.

Iza blokova se ne stavlja točka-zarez. U petoj liniji kôda počinje glavni program, dakle pri pokretanju programa u principu računalo kreće upravo ovdje – sve što se upisuje prije main-a su direktive i nekakve naredbe koje su potrebne za pravilan rad programa te eventualno definicije ručno definiranih funkcija (o ovome će biti riječi u kasnijim tekstovima). Main je zapravo funkcija koju program prvu pokreće pa je i napisana kao definicija funkcije te ćete ih kasnije, kad budete znali definirati vlastite funkcije, na sličan način stvarati kao i main funkciju. Format [int main(void)] možete slijepo zapamtiti kao takvog i uvijek ga upisivati na jednaki način, bez potrebe za dubljom analizom.

Ipak, napomenut ćemo što koja riječ znači u toj liniji kôda: int govori da funkcija main vraća kao rezultat cijeli broj, dok void u zagradi govori da funkcija main ne prima nikakve argumente. Otvorena vitičasta zagrada započinje tzv. tijelo funkcije; sve što je između te otvorene vitičaste zagrade i zatvorene vitičaste zagrade u osmoj liniji kôda pripada glavnoj funkciji main te će biti izvršeno kao glavni dio programa. Zatvaranjem vitičaste zagrade u zadnjoj liniji program završava s radom ukoliko nije ranije završio. Šesta linija kôda izvršava željeni zadatak: ispisuje poruku “Hello World!” na ekran.

Upravo u ispisu je jedna od najuočljivijih razlika između C-a i C++-a, iako, C++ podržava i funkciju printf() koja se koristi u C-u. Kako ovaj ispis funkcionira? Nas neki način, riječ cout predstavlja rezerviranu varijablu u C++-u. Ta “varijabla” pak predstavlja ispis na ekran i sve što je “stavljeno” u nju prikazuje se na ekranu. Pomoću operatora << varijable, sastavnice, rezultati funkcija itd. se slažu, jedni za drugim, istim redoslijedom kojim su upisani u liniju. U našem slučaju, slažu se string “Hello world!” i iza njega rezervirana riječ endl te se nakon toga ukupan string upisuje u cout, odnosno ispisuje na ekran.

Riječ endl predstavlja prelazak u novi red i pražnjenje buffera. Pražnjenjem buffera se ne morate opterećivati – dovoljno je zapamtiti da endl obavlja prelazak u novi red. Zadnja naredba funkcije main je poziv funkcije return(). Pomoću returna funkcija završava s radom. U našem slučaju, [return(0);] znači da funkcija main završava s radom i kao rezultat vraća broj 0.

Jednak će koncept rada biti i kod ručno definiranih funkcija, no kao što smo već napomenuli, o tome će biti riječi u slijedećim tekstovima. Valja napomenuti da će taj program raditi i bez returna, no ipak return doprinosi nekakvoj standardnosti pisanja kôda. Kada bismo uklonili return, program završava s radom na zatvorenoj vitičastoj zagradi jer je to kraj funkcije main.

Pokušajte premjestiti return prije ispisa poruke te kompajlirati i pokrenuti program. Tada se poruka neće ispisati, jer će return završiti rad funkcije main prije naredbe za ispis. Upoznavanje rada programskog jezika možete vrlo lako isprobati na pomalo neobičan način. Jednostavno iz kôda obrišete neku liniju i probate kompajlirati. Ukoliko dođe do pogreške, kompajler će ispisati poruku o pogrešci, a iz nje možete vidjeti zašto je ta linija kôda potrebna.

Uvod vam se mogao učiniti predetaljan i preopširan, no vjerujte da nije. Ukoliko pratite našu školu Pythona, primijetili ste da se manje išlo u dubinu pozadine rada programskog jezika. Razlog je jednostavan: u Pythonu programer nema mogućnost ići u dubinu dok u C++-u ima. Zbog toga, poznavanje pozadine rada je nužno, ako ne sada u počecima, ali zasigurno će biti od velike pomoći kada budete definirali vlastite funkcije, objekte i metode. C++ pruža neograničene mogućnosti programeru, no uz uvjet da programer poznaje principe rada programskog jezika “u pozadini”.

C++: Varijable

Varijable su osnova svakog programskog jezika – poznavanje istih je nužno za bilo kakvu obradu podataka. Postoji nekoliko tipova varijabli u C++-u koji su osnovni i koriste se u gotovo svakom programu. U drugom primjeru su korišteni svi osnovni tipovi podataka. Postoje dva pojma vezana za varijable koja je dobro poznavati, a to su deklaracija i inicijalizacija.

Varijabla nastaje upravo deklaracijom, dakle, to bi na neki način predstavljalo stvaranje varijable i dodjeljivanje nekakvog imena istoj. Inicijalizacija je postavljanje inicijalne, početne vrijednosti varijabli. Postoji nekoliko pravila u vezi s ta dva pojma, tako svaka varijabla mora biti prvo deklarirana kako bi se uopće mogla koristiti. Varijabla postoji tek nakon deklaracije te je tako omogućena manipulacija istom.

 

c++ varijable

Pri deklaraciji određuje se i tip varijable, tako da nije moguće stvoriti varijablu bez definiranja što ona točno predstavlja: cijeli broj, string, niz brojeva itd. Varijabla se može inicijalizirati tek nakon deklaracije ili pri deklaraciji, nikako prije. Ako se varijabla ne inicijalizira, program neće prijaviti pogrešku, ali će varijabla sadržavati neočekivanu vrijednost.

U praksi se stoga nikad varijabla ne koristi ako joj se ne postavi nekakva početna vrijednost; iznimka su napredniji objekti koji su automatski prazni ili namješteni na neku predefiniranu vrijednost. Jedan od tih objekata je i string, koji ako nije inicijaliziran, jednostavno je prazan, ne sadrži ni jedan znak. U našem drugom primjeru imamo četiri deklarirane varijable i sve su inicijalizirane. Dvije su varijable inicijalizirane pri samoj deklaraciji dok druge dvije nisu. Krenimo redom. Prva linija glavnog dijela programa je [int broj1;].

U njoj se stvara varijabla imena “broj1”, tipa int. Riječ int je jedna od rezerviranih ključnih riječi programskog jezika C++,te se kao i svaka druga rezervirana riječ ne smije koristiti u nijednom drugom kontekstu osim u kontekstu kojega definira sintaksa jezika. Dakako, bilo koja riječ, bila ona rezervirana ili ne, smije biti sadržaj variajble, ali ne smije biti ime varijable ili funkcije. Kratica int dolazi od engleske riječi “integer” koja predstavlja cijeli broj pa tako ta varijabla smije sadržavati isključivo cijeli broj, nikako decimalni broj s točkom, tekst ili bilo koji drugi tip podatka.

To ograničenje vrijedi za svaki tip podataka u C++-u. Ipak, postoje načini pretvorbe među tipovima podataka, no oni se najčešće obavljaju eksplicitno. U drugoj liniji main-a imamo deklaraciju i istovremenu inicijalizaciju varijable imena “broj2”, tipa “float” i sadržaja 3.14. Ključna riječ float definira tzv. broj s pomičnim zarezom odnosno laički rečeno, decimalni broj koji nije nužno cijeli broj. Prilično je jasno kako se inicijalizira vrijednost tek deklarirane varijable. Trećom linijom deklariramo varijablu tipa string i imena “tekst”. String ne pripada osnovnim tipovima podataka jer je zapravo objekt, no o tome nije potrebno zasad voditi brigu.

U C-u ne postoji taj tip podatka, nego se stringovi tvore kao nizovi znakova, no u C++-u valja iskoristiti taj, puno moćniji način manipulacije tekstom. Rijetko kada će uopće biti potrebno spremati tekst kao niz znakova. Glavna prednost objekta string je što nije potrebno unaprijed odrediti koliko će znakova sadržavati kao što je to slučaj kod niza znakova.

Pri radu s nizovima, uvijek je potrebno rezervirati točno određen dio memorije, a problem nastaje ako se nekim slučajem dogodi da je potrebno spremiti više podataka nego što ima mjesta u varijabli. Ta “nedefiniranost” veličine stringa je zaslužna i za uštedu memorije jer se rezervira točno onoliki prostor koliki je potreban – ni više ni manje. kod niza znakova pak, ako rezerviramo prostor za 50 znakova, a upišemo u varijablu jedan znak, varijabla će i dalje zauzimati 50 znakova s obzirom da je za nju rezerviran toliki prostor. Objekt string će zauzimati mjesto potrebno za spremanje jednog znaka, a i dalje će se moći po potrebi širiti i smanjivati.

Kaže se da su stringovi pa i objekti općenito, dinamički tipovi podataka jer dinamički barataju memorijom na štedljiv i efikasan način. Zasad, u toj liniji kôda, taj objekt zauzima memoriju potrebnu samo za njegovu deklaraciju, sadržaj je prazan. Nadalje, imamo deklariranu i inicijaliziranu varijablu imena “var”, tipa bool i sadržaja true. Tip bool može poprimiti samo dvije vrijednosti: true (istina) i false (neistina). Istina i neistina se mogu predočavati i drukčijim podacima kao npr. brojevima 1 i 0.

Programski jezik u pozadini obavi potrebne pretvorbe pa će linija [bool var = 1;] imati jednako značenje kao i linija upotrijebljena u primjeru. Taj tip podataka dobro dođe kada je potrebno izvesti nekakvu zastavicu (engl. flag) kojom će se pamtiti nekakvo stanje, npr. je li neki podzadatak programa obavljen i slično. U sljedećoj liniji je jednostavno varijabli broj1 pridjeljena vrijednost 26.

Probajte obaviti ispis te varijable prije dodjele vrijednosti, ona će biti neočekivana, nepouzdana. Nakon toga, inicijalizirana je varijabla tekst. Vrijednost objekta tipa string uvijek se stavlja u navodnike. Objekt je “proširen”, zauzeo je točno količinu memorije koja je potrebna za spremanje teksta “Hello again!” te mu je vrijednost upravo taj tekst. U narednim se trima redcima vrši ispis svih varijabli s dodanim opisnim tekstom. Razlika u odnosu na prethodni primjer je jedino što je nanizano više “stvari” koje se ispisuju te su dodane i varijable. Jednostavno se navede ime varijable, a prilikom izvršavanja provodi se zamjena u vidu da se ime varijable zamjenjuje njenom vrijednosti predstavljenom kao tekst. Možete vidjeti i to da je vrijednost true varijable var ispisana kao broj 1.

C++: Upis podataka i osnove obrade

Prije nego što pređemo na nešto napredniju obradu podataka pomoću ugrađenih funkcija, valja obraditi upis i osnove obrade u vidu osnovnih matematičkih operacija. Ispis smo već u principu obradili – zasad je bitno da možemo vidjeti rezultat obrade na bilo koji način. Međutim, bez upisa je nemoguća bilo kakva interakcija korisnika s programom. U trećem primjeru pokrivene su osnove upisa podataka i osnovne matematičke operacije nad unesenim podacima.

Prva uočljiva razlika u odnosu na prošli primjer je deklaracija triju varijabli u jednom retku. Ako imamo više varijabli istog tipa, jednostavno ih odvajamo zarezima, kao što je to ovdje učinjeno. Također, smije se neke od njih ili sve odmah i inicijalizirati, npr. [int a = 5, b = 7, c; ] će stvoriti tri varijable, od kojih su dvije odmah i inicijalizirane.

Savjetujemo da ne imenujete varijable predugim imenima, općenito, valja težiti što je moguće kraćim imenima, ali do te mjere da je intuitivno jasno što varijabla predstavlja. Tako je ovdje jasno da kratica “br” predstavlja broj, a “rez” nekakav rezultat. Nakon prvog ispisa poruke imamo upis podataka preko rezervirane riječi “cin”. Lako je pamtljivo da cout barata tokom podataka prema van (out), a cin prema unutra (in). I operator >> je logičan – vizualno djeluje kao strelica usmjerena sa cin-a prema varijablama.

Upravo se se i događa: sa standardnog ulaza čitaju se podaci, jedan po jedan i spremaju u varijable navedene na desnoj strani, a odvojene operatorima >>. Program prepoznaje kada treba preći na sljedeću varijablu čitanjem razmaka, tab-a ili prelaskom u novi red. U tome primjeru, brojeve možete odvojiti razmakom pa pritisnuti Enter ili nakon svakog broja pritisnuti Enter, svejedno je. U sljedećem retku imamo prvi matematički izraz. Računa se podizraz s desne strane jednakosti, u tom slučaju umnožak varijabli br1 i br2 te se rezultat podizraza, pomoću znaka jednakosti, sprema u varijablu rez.

Svaka matematička operacija će se obavljati na jednak način – računa s desna strana i dodjeljuje lijevoj. Slijede ispisi umnoška i zbroja dva unesena broja. Umnožak se ispisuje ispisom sadržaja varijable rez, dok smo zbroj izračunali “u hodu”. Dakle, ovdje pri ispisu, smije se direktno napisati matematički izraz kojeg će program pri izvršavanju izračunati te rezultat pretvoriti u tekst kojeg ispisuje na ekran.

Dakako, umnožak se mogao na isti način ispisati – ispisali smo ga pomoću varijable rez čisto da se vide različiti pristupi rješavanju istog problema. Naime, umnožak je spremljen u varijablu te ga je moguće kasnije koristiti dok zbroj nigdje nije spremljen. Kada bismo htjeli nakon tog ispisa opet koristiti zbroj, morali bismo ga ponovno računati. Na koji način će se problem riješiti, to isključivo ovisi o potrebama i planovima pri programiranju.

C++: Unos stringova

Četvrti primjer pokriva problem s unosom stringova. Naime, “naredba” cin automatski prelama unose kada naiđe na razmak, tab ili prelazak u novi red. Problem se očituje pri korisnikovom unosu teksta koji sadrži razmake. U screenshotu možete vidjeti ponašanje toga primjera pri unosu teksta s razmacima te ćemo na tom pokrenutom primjeru i pojasniti zašto dolazi do toga, pomalo neočekivanoga ponašanja koje je u biti logično (kao i sve što se tiče programiranja).

c-unos-stringova

 

Prvom upotrebom cin-a čitamo tekst s tipkovnice u prvu varijablu. Nakon njega imamo prvu upotrijebljenu funkciju uopće, a to je getline(). Ona prima dva argumenta, u našem slučaju, prvi argument je cin, a drugi varijabla unos2, odnosno unos3. Funkcija čita liniju iz toka koji je predan kao prvi argument što je kod nas tok podataka s tipkovnice odnosno cin. Tu se dakle uvijek upisuje riječ “cin”, ako je cilj čitanje linije unesene tipkovnicom. Drugi argument govori gdje će se pročitana linija spremiti, u našem slučaju, to je varijabla unos2 i u sljedećem retku unos3.

Ostatak kôda bi vam trebao biti jasan, iako smo namjerno stavili u predzadnjem ispisu rezerviranu riječ “endl” na početak ispisa, čisto da se vidi da ga je moguće staviti bilo gdje, baš kao i varijablu, izraz ili sastavnicu. Što se događa u primjeru pokretanja? Naime, cin čita sve do pojave prvog prekida, u našem slučaju, to je razmak. Stoga, u varijablu unos1 spremljena je string “Ocekujemo”.

Pošto je taj dio linije pročitan, funkcija getline() nastavlja s čitanjem na istom mjestu gdje je prošlo čitanje završilo i čita sve do pojave prelaska u novi red. Ostatak rečenice, uključujući vodeći razmak koji je ostao nepročitan, sprema se u varijablu unos2. Na kraju, cijela drugounesena linija sprema se u varijablu unos3. Time ste vidjeli kako valja paziti na unos stringova, ukoliko se oni očekuju, i unosi teksta koji sadrži razmake.

Najbolje je unositi stringove jednostavno funkcijom getline() te formirati poruke tako da korisnik pritisne Enter nakon unosa stringa. Općenito, treba izbjegavati unos stringa i broja u jednoj liniji jer se tada javlja bespotreban rizik da će se npr. i string i broj učitati u istu varijablu tipa string što opet povlači za sobom zahtjev za upisom broja koji je u biti već učitan itd.

Opisom problema pri unosu stringova završavamo s ovim, uvodnim dijelom škole programiranja u C++-u. Iako djeluje kao da smo se previše fokusirali na nekakve teorijske podloge koje vam ne trebaju, to nije tako.

Zaista, programirati se može i napamet, bez poznavanja osnovnih principa vezanih za sve ono što programer ne vidi, a to su: headeri, principi rada tokova za upis i ispis podataka, problemi s memorijom i tipovima podataka itd.

Ipak, kvalitetan uvod i duboko razumijevanje procesa koji se odvijaju u pozadini su odlična osnova za daljnje učenje programiranja na visokoj razini. Potreba za dodatnim vanjskim informacijama svesti će se na minimum, a programiranje će vam postati intuitivno i lako.

Piše: B.B.

Komentiraj

Please enter your comment!
Please enter your name here