Mala skola C-a
2. dio

Hello world

E vo nas već do drugog nastavka. Pošto znam da jedva čekate da pokrenete vaše kompajlere u ovom nastavku će te se upoznati sa najneophodnijim stvarima te tako moći da napišete svoje prve C programe. Ne gubimo više ni trena!!!

     Obično, kada se uči neki programski jezik prvi program koji se napiše je "Hello world". U C-u bi on izgledao ovako:

 #include <stdio.h>
 main()
 {
         printf("Hello world\n");
 }

Napišite program u text editoru, snimite ga u vaš poddirektorij, recimo pod imenom "primjer.c". Običaj je da se C source-ovi snimaju sa ".c" ekstenzijom, pa se ubuduće i vi toga pridržavajte. Sad se prebacite u CLI, pozicionirajte u vas poddirektorij i kompajlirajte program sa:

sc primjer.c

Poslije ovoga (ako niste napravili grešku u pisanju) u vašem direktoriju će se naći izvrsni fajl pod nazivom "primjer". Pretpostavljam da ste u scopts podesili da se programi odmah i linkuju. Sad program možete startati upisivanjem njegovog imena "primjer" iz CLI-ja. Program će ispisati:

Hello, world, prebaciti kursor u novi red i vratiti kontrolu OS-u.

A sad objašnjenja:

#include <stdio.h>

Ovaj red se u toku kompajliranja zamjeni datotekom "stdio.h", da bi se uključile deklaracije potrebnih funkcija (objašnjeno niže). Mi konkretno koristimo "printf" funkciju.

Bilo bi potpuno isto da smo umjesto "#include " ubacili cijeli "stdio.h" fajl, samo što taj posao sada, umjesto nas, radi kompajler. Pored "include" direktive postoji i direktiva "define" koja se koristi za definiciju konstanti. Recimo da ispod "#include" dodamo nešto kao:

#define BROJ 20

Ovim smo kompajleru prijavili konstantu BROJ (konstante se obično pišu velikim slovima) koja ima vrijednost 20. Kompajler će sada kad god naiđe na tekst "BROJ" u vašem listingu zamijeniti ga tekstom "20". Ovom naredbom možete definirati ne samo brojevne konstante, već i tekstualne, recimo da smo na početku stavili i:

#define piši printf

Mogli bi da, umjesto "printf", koristimo "piši" u daljnjem listingu. Međutim, na ovaj način listing postaje manje čitljiv svima sem vama i dovodi do zabune.

Zato izbjegavajte da preimenujete već postojeće riječi (funkcije i sl.), a trudite se da što česće definirate brojevne konstante i na taj način izbjegnete postojanje "magičnih" brojeva u vašim listinzima.
Tako će te vrlo brzo moći da mijenjate vrijednosti tih konstanti (dovoljno je da izmenite samo jednu liniju na početku listinga), a i sam listing će biti jasniji.

main()

Ovaj red predstavlja definiciju funkcije. Funkcija se zove "main". Program uvijek počinje da se izvršava od funkcije "main" (glavna). Ostale funkcije koje pravite možete nazvati (skoro) kako hoćete, ali u vašem programu mora postojati funkcija "main" da bi se znalo odakle program počinje sa izvršavanjem.

     Funkcija može, ali i ne mora, da vraća neku vrijednost. Tip funkcije (odnosno vrijednosti koju funkcija vraća) naznačava se ispred imena funkcije. Kada, tip nije naznačen podrazumeva se da je "int" ("integer", cijelobrojni - biti će objašnjen kasnije). Mogli smo znači staviti i:

int main()

Ako želimo da funkcija ne vraća ništa ispred imena stavljamo "void". Ako se poziv funkcije nalazi ispred definicije funkcije potrebno je funkciju deklarirati da bi kompajler znao koje parametre funkcija prima, a koje vraća. Deklaracija je potpuno ista definiciji, samo što se na kraju dodaje ";". Recimo:

int kvadrat (int);

Ovim smo deklarirali funkciju "kvadrat", koja je int tip (vraća integer). ";" se inače stavlja poslije svake naredbe (poziva funkcije i sl.), ali se ne stavlja poslije naredbi za kontrolu toka (petlje i sl.)

Posije imena funkcije slijede u zagradi tipovi i imena parametara koje funkcija prima. Recimo:

 int kvadrat( int n)
 {
   /*
   tijelo funkcije
   */
        return(ret);
 }

Ovo znači da funkcija "kvadrat" prima parametar tipa integer (n), a da vraća vrijednost ("ret") koja je također tipa integer. Poslije definicije slijedi otvorena vitičasta zagrada koja označava odakle počinje tijelo funkcije. Funkcija traje sve do zatvorene vitičaste zagrade. To važi ne samo za tijelo funkcije, već za bilo koji blok naredbi (recimo tijelo petlje i sl.). Ako se tijelo sastoji od samo jedne naredbe, onda nije neophodno stavljati vitičaste zagrade.

"return" označava koju vrijednost funkcija vraća ("ret" konkretno).

"/*" označava početak komentara, a "*/" kraj komentara, tako da kompajler jednostavno preskoči dio programa između tih znakova. U SAS C-u je moguće koristiti i znak "//". Od tog znaka, sve do kraja reda nalazi se komentar i kompajler taj dio listinga preskače.

a=a+4; // Početak Komentara

Inače, ovaj način komentiranja je preuzet iz C++ jezika.

printf("Hello, world\n");

Ovo je poziv funkcije "printf". Kao što vidimo, u zagradi se nalaze parametri koji se prosljeđuju funkciji. Trenutno se funkciji proslijeđuje samo string "Hello world\n". Rad sa stringovima je malčice kompliciraniji nego što izgleda, ali otom potom. U stringu se nalazi znak "\n". Iako su to dva karaktera tumače se kao jedan i označavaju prelazak u novi red. Pored "\n" imamo još i "\a" - zvučni signal, "\t" - tab, "\b" - povratnik...Na kraju ide obavezno ";".

     Potrebno je objasniti nekoliko puta spominjan tip podataka "int". To je cijelobrojni tip koji obično zauzima 4 bajta (može da se podesi i na 2). Opseg je otprilike +/- 2 milijarde, znači sasvim dovoljno za normalnu upotrebu (dok je sa 2 bajta oko +/- 32000). Inače, rad sa integer-ima je najbrži, pošto CPU najbrže pristupa LONG-u (4 bajta), pa onda WORD-u (2 bajta) i na kraju BYTE-u (bajtu, 8 bita). Prije upotrebe varijabli potrebno ih je najaviti, da bi kompajler rezervirao potrebnu memoriju za njihovo korištenje. Npr. :

int zbroj;

Ovim smo dobili varijablu "zbroj" "int" tipa (obavezno ";" na kraju). Moguće je odmah i dodijeliti neku vrijednost varijabli, npr. :

int a=10, b=20, c=30, d;

Kao što vidite moguće je odjednom najaviti više varijabli. Međutim ako u programu imamo ovako nešto:

int a,b; b=a+5;

kompajler će nas na to upozoriti, pošto varijabli "a" nije dodijeljena vrijednost i ishod računanja "b" je nepredvidiv.

     Varijable mogu biti lokalne ili globalne. Ako se definiraju unutar funkcije onda pripadaju samo toj funkciji i za druge funkcije one ne postoje. Znači slobodno možete u različitim funkcijama koristiti varijable sa istim imenima. Ako se pak varijable definiraju van funkcija one se mogu koristiti u svim funkcijama u tom listingu. Ako želimo da koristimo i globalne varijable iz nekog drugog fajla potrebno je varijablu najaviti ključnom reci "extern". Npr.:

extern int x;

     Lokalne varijable (tzv. automatske) gube vrijednost pri prestanku izvršenja funkcije, pa zato moraju biti definirane prije upotrebe unutar funkcije. Ako je potrebno da lokalne varijable ipak zadrže vrednosti između dva poziva koristi se tip "static":

static int i;

Ovako definirana funkcija će zadržati vrijednost po prestanku izvršenja funkcije i imati tu istu vrijednost kada se funkcija ponovo pozove.

     Pored ispisa potrebno je moći dodijeliti vrijednost varijablama. To nam omogućuje funkcija "scanf", koja je slična BASIC naredbi INPUT. Ona je također dio standardne C biblioteke i prima podatke sa standardnog ulaza, koji je, ako se ne preusmjeri, tastatura. Npr. poslie izvršenja reda:

scanf("%d",&i);

program ce sačekati da unesete cijeli broj i tu vrijednost će smjestiti u varijablu "i". "scanf" je ime funkcije, parametri su u zagradi, ";" na kraju - to je jasno, ali šta je sa parametrima? Prvi parametar je tzv. format string. Stringovi se pišu pod znacima navoda, a konkretno "%d" znači da unijetu vrijednost treba smjestiti u varijablu tipa integer. Isti format string se koristi i kod "prinf" funkcije kada želimo ispisati vrijednost neke varijable. Evo primjera:

i=10;
printf("i=%d\n",i);

Poslije izvršenja ova dva reda u varijablu "i" (koja mora biti int tipa) smjestiti ce se vrijednost 10 i ispisati će se na ekranu (ako izlaz nije preusmjeren):

i=10

"\n" će obezbijediti prelazak kursora u novi red. Dakle, prvi parametar je string koji se ispisuje kakav jeste, osim specijalnih kontrol i format znakova umjesto kojih se vrši neka radnja (npr. prebaci se kursor u novi red) ili se umjesto njih ispisuje slijedeći parametri respektivno. Evo još jednog primjera:

i=5;
a=i+6;
printf(" i=%5d, podatak broj %d\n a=%d\n",i,1,a);

Dobiti će se na izlazu:

i=    5,  podatak broj 1
a=11

Jasno? "%5d" znači da treba ispisati parametar int tipa, ali tako da zauzima 5 polja (mjesta). Za detaljnija uputstva pogledajte SAS C help (ili koji već koristite ili bilo koju knjigu o C-u), mada će vam ovo biti sasvim dovoljno za početak.

Ostala je nerazjašnjena svrha znaka "&" ispred varijable kod scanf funkcije. U C-u funkcija prima samo kopije varijabli sa kojima je pozvana, a ne prave varijable, tako da je nemoguće iz funkcije promijeniti vrijednost varijable kojom je funkcija pozvana. printf funkciji je dovoljno proslijediti i kopiju varijable, jer mi u glavnom programu ne očekujemo da nam printf vrati bilo kakve vrijednosti. Ali kako scanf mora da vrati vrijednost sa ulaza, nije dovoljno proslijediti kopiju varijable, već se zato prosljeđuje adresa varijable u koju je potrebno smestiti broj sa ulaza. Znači znak "&" označava da se ne prosljeđuje vrijednost varijable, već adresa u memoriji na kojoj se ta varijabla drži, a scanf će na tu adresu smijestiti dobijenu vrijednost i po vraćanju u glavni program varijabla će imati tu novu vrijednost. Znači i "scanf" i "printf" rade u ovom primjeru sa varijablama "int" tipa, ali kod "prinf" "%d" znači da se očekuje vrijednost parametra, a kod "scanf" "%d" znači da se očekuje adresa parametra, koji je "int" tipa.
Probajte da napišete nešto ovako:

 #include
 main()
 {
        int i;
        printf("Unesi vrijednost varijable i:");
        scanf("%d",&i);
        printf("i=%d\n i je smješteno na adresi:%d\n",i,&i);
 }

i saznati će te na kojoj adresi je smještena varijabla "i".

     Mislim da je za ovaj put bilo dosta (možda i previše). Za kraj evo još jednog primjera (3.), ne bi li još bolje shvatili kako se koriste funkcije. Vi slobodno eksperimentirajte, isprobavajte sve što vam padne na pamet. To je jedini način da se nauči bilo koji jezik, pa i C.

 #include

 int kvadrat(int n);               /* Deklaracije funkcija */
 int kub(int);               /* Ocekuju integer i vracaju integer */
 int formula(int);               /* Bitno da se poklopi tip, a ime varijabli nije vazno, pa ga ne moramo staviti. Posto su sve funkcije definirane poslije (ispod) poziva moraju se deklarirati */

 int ex;               /* Globalna varijabla, vidljiva u svim funkcijama */

 main()
 {
     int i=5;               /* Lokalna varijabla main-a */

     printf("Unesi vrijednost ex varijable:");               /* Isps teksta */
     scanf("%d",&ex);               /* smještanje ulaza u ex */
     printf ("\n Ok. ex=%d i=%d\n",ex,i);

     printf("%d^2=%d\n",i,kvadrat(i));
     printf("%d^3=%d\n",i,kub(i));

     printf("n^3+6*n^2+4*n=%d\n",formula(i));

     printf("ex je sada %d\n",ex);
 }

 int kvadrat (int n)               /* Definicija - ide bez ";" !! */
 {
     int i;               /* Lokalna varijabla i - nema veze sa onom iz main-a */

     i=n*n;               /* i=n^2 */
     return(i);               /* vrijednost koju funkcija vraća */
 }

 int kub (int n)

 {
     return (n*n*n);               /* Može i ovako*/
 }

 int formula (int n)               /* n^3+6n^2+4n */

 {
     int tmp;               /* Privremena varijabla */

     tmp=kub(n)+6*kvadrat(n)+4*n;               /* Formula. Iz jedne funkcije se mogu pozivati druge. Cak je dozvoljeno da funkcija pozove samu sebe (rekurzija) */

     ex=ex+5;               /* ex je glob. varijabla, pa je svuda mozemo koristiti i mijenjati */

     return(tmp);

 }

Milan Golubovic



Mala škola C-a (1.dio, 2.dio) | Najavljene igre | Otkazane igre