Tečaj C - Poglavje 4

Dodeljevanje vrednosti in logične primerjave

Skozi to celotno poglavje so  podana različna območja vrednosti spremenljivk. Ta se nanašajo na območje vrednosti, ki jih je možno dodeliti neki spremenljivki. Vaš prevajalnik lahko za nekatere od teh spremenljivk uporablja drugačna območja, saj ANSI-C standard ne definira specifičnih mej za vsak tip spremenljivk. Oglejte si dokumentacijo vašega prevajalnika za točna območja vrednosti za vsakega od tipov spremenljivk.

STAVKI ZA DODELJEVANJE VREDNOSTI CELOŠTEVILSKIM SPREMENLJIVKAM

Primer programa ------> INTASIGN.C

Naložite program INTASIGN.C in si ga oglejte kot primer dodeljevalnih stavkov. Na začetku definiramo tri spremenljivke za uporabo v programu, ostalo pa so serije ilustracij različnih vrst dodeljevalnih stavkov. Vse tri
spremenljivke so definirane v eni vrstici in imajo na začetku v njih shranjene neznane vrednosti.

Prvi dve vrstici dodeljevalnih stavkov, vrstici 8 in 10, dodelijo numerične vrednosti spremenljivkam a in b, naslednjih pet pa prikaže pet osnovnih aritmetičnih funkcij in njihovo uporabo. Peta se imenuje modulo operator in
nam daje ostanek pri deljenju dveh spremenljivk. Lahko ga uporabimo le na celoštevilskih spremenljivkah, kar bomo podrobneje definirali kasneje. Vrstici 15 in 16 ilustrirata, kako lahko združujemo nekaj spremenljivk
v relativno kompleksne matematične izraze.Vsi zgornji primeri naj ne bi potrebovali dodatnih komentarjev, treba je povedati le še to, da nobena izmed enačb ni posebno uporabna, razen kot ilustracija.

Prioriteta operatorjev je zelo pomembna tema, katero bomo morali pozneje bolj podrobno predelati, sedaj pa bomo potrebovali le nekaj pravil. Ko imate mešane aritmetične izraze, se množenje in deljenje izvedeta pred seštevanjem in odštevanjem, če so vse operacije na istem logičnem nivoju. Za izraz a * b + c / d torej velja, da se najprej izvedeta množenje in deljenje, nato pa sledi še seštevanje. V primeru a * (b + c / d) pa seštevanje sledi deljenju, vendar pa nastopi pred množenjem, ker so operacije na dveh različnih logičnih nivojih, kot je to definirano z oklepaji.

Izrazi v vrsticah 17 in 18 so veljavni takšni kot so, vendar pa bomo pozneje v tem poglavju videli, da obstaja način zapisati te izraze tako, da dobimo veliko bolj kompaktno kodo.
 

KODA, KI IZGLEDA PRECEJ ČUDNO

To nas pripelje do vrstic 20 in 21, ki se vam bodo morda zdele zelo nenavadne. C-jevski prevajalnik pregleduje dodelitvene stavke od desne proti levi (kar se morda zdi nekoliko nenavadno, saj mi ne beremo na ta način),
kar se izkaže v zelo uporabnem konstruktu, ki ga lahko vidite tukaj. Prevajalnik najde vrednost 20, jo dodeli c-ju, nato pa nadaljuje proti levi, kjer ugotovi, da se mora zadnja vrednost dodelitit b-ju. Ker smatra, da je bil rezultat zadnjega izracuna 20, dodeli to vrednost tudi b-ju, in nadaljuje z iskanjem proti levi in tako dodeli vrednost 20 tudi a-ju. To je zelo uporaben konstrukt, ko želite inicializirati skupino spremenljivk. Stavek v vrstici 21 prikaže, da lahko naredimo nekaj izračunov in tako pridemo do vrednosti, ki se bo dodelila vsem trem spremenljivkam. Vrednosti, ki so jih imeli a, b in c pred zaćetkom stavka v vrstici 21, se uporabijo za izračun vrednosti, katera se potem dodeli vsem trem spremenljivkam.

Kot pomoč pri razumevanju, je vrstica 23 podana z oklepaji, da združimo pogoje na razumljiv način. Vrstici 20 in 23 sta identična stavka.

Program nima nobenega izpisa, zato bo prevajanje in poganjanje tega programa zelo nezanimivo. Ker ste se že naucili, kako izpisati celoštevilčne razultate s pomočjo printf( ) funkcije, bi bilo v vaše dobro, da bi dodali
nekaj izhodnih stavkov in tako ugotovili, če posamezni stavki počnejo to, kar ste od njih pričakovali. Morali pa boste dodati stavek #include <stdio.h> na začetek programa, da bi lahko uporabljali printf( ) stavke.

Prav tako lahko dodajate svoje dodeljevalne stavke in si tako pridobite nekaj izkušenj za delo z njimi.
 

NAJPREJ DEFINICIJE, ŠELE NATO PA IZVRŠEVALNI STAVKI

Sedaj bi bil dober trenutek za predhodno definicijo pravila, ki se ga morate držati v C-ju. Definicije spremenljvk so vedno podane pred izvrševalnimi stavki v vsakem programskem bloku.Zato so spremenljivke definirane na začetku sklopa v tem  in tudi v vsakem drugem C-jevskem programu. Če boste novo spremenljvko poskušali definirati
po nekaj izvajalnih stavkih, vam bo prevajalnik javil napako. Programski sklop je enota enega ali več stavkov, ki so omejeni z zavitim oklepajem. Sklop je lahko tudi prazen, vendar za to ni prave potrebe, razen kot rezerviranje prostora v zgodnji fazi programskega razvoja. Več o sklopih bomo povedali kasneje.
 

DODATNI TIPI PODATKOV

Primer programa ------> MORTYPES.C

Nalaganje in editiranje programa MORTYPES.C bo ilustriralo, kako lahko uporabite še druge vrste podatkovnih tipov. Še enkrat smo definirali nekaj celoštevilskih spremenljivk, katere vam bi morale biti jasne, dodali pa smo
še dva nova tipa, char in float.

Tip podatkov char je zelo podoben integerjem, le da lahko zavzame numerične vrednosti med -128 in 127 na večino implementacij C-ja na mikroračunalnikih, saj je ponavadi shranjen v enem bytu pomnilnika. Nekatere implementacije C-ja uporabljajo za hranjenje char spremenljivk večje elemente pomnilnika, in zato dobi večje območje vrednosti. Tip podatkov char se ponavadi uporablja za ASCII podatki, ki so bolj znani pod imenom besedilo. Besedilo, ki ga trenutno berete, je bilo napisano na računalniku z urejevalnikom besedila, ki je shranjeval tekst v računalnik tako, da je vsak znak shranil v en byte pomnilnika. Na drugi strani pa tip podatka int skoraj vsi mikroračunalniki shranjujejo v dva byta pomnilnika, nekateri pa tudi v več, saj je večina novejših računalnikov 32 bitnih in shranjujejo int spremenljivke v štiri byte pomnilnika.

Zapomnite si, da čeprav je bil tip char namenjen temu, da hrani predstavitev ASCII znaka,  ga lahko učinkovito uporabimo za hranjenje manjših vrednosti, če to želimo. Več o tem bomo povedali v sedmem poglavju, ko bomo obdelali nize.

MEŠANJE TIPOV PODATKOV

Sedaj bi se izplacalo razložiti način, s katerim C obravnava tipa char in int. Večina operacij v C-ju, ki je zasnovana za delovanje z int tipom, bo enako dobro delovala s char tipom, saj sta oba celoštevilska, kar pomeni, da nimata decimalnega dela. Te operacije, kadar se bodo izvajale na  spremenljivkah char, bodo namreč pretvorjene v tip int. Zato je mogoče char in int tip med seboj mešati na skoraj vse mogoče načine. Prevajalnik se ne bo zmedel, mogoče pa je, da se boste vi. Dobro je, da se na to ne zanašate preveč, pač pa uporabljate pravilne tipe tam, kjer morajo biti uporabljeni.

Drugi novi tip podatkov je tip float, ki se mu pravi tudi podatek s plavajočo vejico. To je tip podatka, ki ima ponavadi zelo veliko območje vrednosti, precej veliko število pomembnih mest, potrebno pa je veliko število racunalniških besed za njegovo hranjenje. S float tipom podatka je povezana decimalna vejica in za hranjenje posamezne spremenljivke tipa float je potrebno nekaj bytov pomnilnika .

KAKO UPORABITI NOVE TIPE PODATKOV

Prve tri vrstice programa dodelijo vrednosti vsem devetim definiranim spremenljivkam, tako, da imamo podatke, katere lahko izmenjujemo med različnimi tipi.

Ker je, kot smo že omenili, tip podatka char pravzaprav celoštevilski tip, ki se avtomatsko pretvori v tip int, ko je to potrebno, ni potrebno upoštevati ničesar posebnega, kadar pretvarjamo tip char v int, prav tako pa lahko podatkovno polje tipa char dodelimo int spremenljivki. Če pa spreminjamo v drugo smer, lahko int spremenljivko dodelimo spremenljivki tipa char, kar se bo prevedlo pravilno, če je vrednost v območju vrednosti tipa char, ponavadi od -128 do 127. Če pa je vrednost izven območja tipa char, prevajalnik zavrže najbolj pomembne bite in uporabi najmanj pomembne.

Vrstica 16 prikaže enostavnost pretvarjanja int v float. Spremenljivki float preprosto dodelimo novo vrednost, pravilno pretvorbo pa bo naredil sam sistem. Kadar pa float pretvarjamo v int, pa se pojavi težava. Ker ima število s plavajočo vejico decimalni del, se mora sistem odločiti, kaj bo z njim naredil. Ponavadi se ta del odreže in tako dobimo celo število.

Ta program ne generira nikakršnega izpisa, pa tudi nismo še povedali, kako
izpisujemo char in float spremenljivke, zato se ne morete poglobiti program
in se poigrati z rezultati. To bomo obdelali v naslednjem programu.

Prevedite in poženite  program, ko ste se prepričali, da veste, kako deluje. Morda vam bo prevajalnik javil opozorila glede pretvarjanja tipov. Ta lahko ignorirate zaradi majhnih vrednosti, ki jih uporabljamo za ilustracijo posameznih tipov podatkov.

NEKATERE TIPIČNE VELIKOSTI

Ta seznam prikazuje nekatere tipične vrednosti za različne tipe, ki so dosegljivi v C-ju. Vaš prevajalnik  lahko ponuja različne meje in velikosti, saj so med posameznimi prevajalniki lahko razlike. Te vrednosti veljajo za Microsoft Visual C++ verzijo 1.5 (16 bits) in Visual C++ verzijo 2.0 (32 bits).

Ime Tipa         Biti      Območje
  ------------- 16 bit system -------------
char              1       -128 to 127
signed char       1       -128 to 127
unsigned char     1       0 to 255
short             2       -32,768 to 32,767
unsigned short    2       0 to 65,535
int               2       -32,768 to 32,767
unsigned int      2       0 to 65,535
long              4       -2,147,483,648 to 2,147,483,647
unsigned long     4       0 to 4,294,967,295
float             4       3.4E+/-38 (7 digits)
double            8       1.7E+/-308 (15 digits)
long double      10       1.2E+/-4932 (19 digits)

  ------------- 32 bit system -------------
char              1       -128 to 127
signed char       1       -128 to 127
unsigned char     1       0 to 255
short             2       -32,768 to 32,767
unsigned short    2       0 to 65,535
int               4       -2,147,483,648 to 2,147,483,647
unsigned int      4       0 to 4,294,967,295
long              4       -2,147,483,648 to 2,147,483,647
unsigned long     4       0 to 4,294,967,295
float             4       3.4E+/-38 (7 digits)
double            8       1.7E+/-308 (15 digits)
long double      10       1.2E+/-4932 (19 digits)
Marljiv študent bo opazil, da je edina razlika med tema dvema seznamoma v velikosti in mejah spremenljivk tipa int, tako predznačenih kot nepredznačenih. ANSI-C standard namreč pravi, da ima int "naravno velikost, ki je pogojena s sistemom, kjer se program izvaja", tako, da se območja v zgornjem seznamu popolnoma skladajo s tem standardom.

Poudariti pa je treba še eno stvar glede zgornje tabele. Ali je tip char predznačen ali ne, je čisto v rokah pisca prevajalnika. Pisci Microsoftovega prevajalnika so se, kot večina drugih piscev prevajalnikov, odločili, da definirajo tip char kot signed char, vseeno pa imate sami možnost to spremeniti, saj večina prevajalnikov ponuja možnost preklopa na izbiro, da je char v resnici unsigned char.

Za ugotavljanje meja območij vrednosti je na voljo nekaj koristnih konstant. Kot primer sta imeni INT_MIN in INT_MAX na voljo v datoteki "limits.h" kot konstanti, ki ju lahko uporabite v svoji kodi. INT_MAX je največje možno število, ki ga lahko shranite v tip spremenljivke int z danim prevajalnikom. Ko boste zamenjali prevajalnik, kar boste nekega dne gotovo storili, se bo INT_MAX nanašal na največjo vrednost int za tisti prevajalnik. Četudi boste nekoč delali na operacijskem sistemu s 64 ali celo 128-bitno strukturo, se bo INT_MAX še zmeraj nanašal na največji int na tistem računalniku. Datoteka "limits.h" vsebuje veliko število takih meja, vse pa so vam dosegljive tako, da to datoteko vključite v svoj program. Je tekstovna datoteka, ki jo lahko odprete v vsakem urejevalniku besedila in preučite, kar bi za vas tudi bila dobra vaja v tem trenutku.
 

VELIKO TIPOV SPREMENLJIVK

Primer programa------> LOTTYPES.C

Naložite program LOTTYPES.C in si ga oglejte. Ta datoteka vsebuje večino standardnih enostavnih tipov podatkov, ki so na voljo v programskem jeziku C. Preglejte dokumentacijo vašega prevajalnika za celoten seznam tipov, ki so na voljo v njem. Obstajajo še drugi tipi, vendar so to sestavljeni tipi (na primer-polja in strukture), ki pa jih bomo obdelali pozneje.

Oglejte si program. Najprej definiramo enostaven int, nato pa še long int. Nato sledi short int, ki ima območje vrednosti, ki je lahko enaki tisti, ki jo ima int. Naslednji tip je unsigned, ki ima enako območje kot int, le da nima predznaka. Treba je poudariti, da ko deklariramo tipe long, short, ali unsigned, besedica int ni nujno potrebna, in jo večina izkušenih programerjev izpušča. Vaš prevajalnik ima lahko za spremenljivke zelo različna območja, zato preglejte njegovo dokumentacijo  za natančna območja teh tipov.

Tip double je za število s plavajočo vejico, vendar pokriva večje območje kot tip float in ima več pomembnih mest za bolj natančno računanje. Zahteva pa tudi več pomnilnika za hranjenje kot enostavni float. Long double pokriva mnogo večje območje vrednosti in hrani več pomembnih mest, vendar pa tudi računanje z njim traja dalj časa zaradi večje velikosti podatkov, ki jih uporabljamo.

Na tej točki je potrebna še ena opomba. Vaš prevajalnik najbrž nima možnosti računanja s števili s plavajočo vejico, lahko pa računa z double števili s plavajočo vejico. Float števila bo zato spremenil v double in nato računal z njimi, tako, da bomo potrebovali le eno matematično knjižnico. Za vas je to seveda nevidno, zato vam o tem ni potrebno preveč razmišljati. Zaradi tega boste morda pomislili, da bi bilo najbolje vsako spremenljivko s plavajočo vejico definirati kot double, saj se vse te spremenljivke pretvorijo v tip double, vendar pa to ni vedno dobra ideja. Spremenljivka float bo zasedla štiri byte pomnilnika, double pa osem, in če imate za hranjenje veliko podatkov s plavajočo vejico, vam bo tip double zahteval veliko več pomnilnika. Če ne rabite dodatnega območja vrednosti ali dodatnih pomembnih mest, raje kot double uporabite float. Prevajalnik naredi vse podatke s plavajočo vejico, kot je to vrednost 3.14159 v vrstici 19, konstante double že sam po sebi. Nekateri prevajalniki bodo morda sporočili opozorilo zaradi vrstice 19, kjer prirejamo spremenljivki double spremenljivko tipa float. Zaenkrat lahko to opozorilo mirno ignorirate.

Ko definiramo podatkovne tipe, podamo numerično vrednost vsaki od spremenljivk, da bi lahko prikazali načine, kako vsako od njih izpisujemo na zaslon.
 

NEKATERI POZNI DODATKI

Ko se programski jezik razvija, se mu dodajajo dodatni konstrukti, da bi zadovoljili neke prej spregledane potrebe. Dve novi rezervirani besedi sta bili dodani C-ju, zaradi   izdaje ANSI-C standarda. Le-ti nista prikazani v primerih programov, bosta pa obravnavani v tem tečaju. To sta besedi const in volatile in se uporabljata za sporočanje prevajalniku, da so to spremenljivke, ki zahtevajo posebno pozornost. Konstanto deklariramo z rezervirano besedo const, označuje pa vrednost, katere programsko ne moremo spreminjati. Če boste pomotoma skušali spremeniti vrednost, ki je definirano kot konstanta, vam bo prevajalnik javil napako.  Deklarirati zadevo kot const pomeni olajšati delo optimizatorju in omogočiti, da bo program tekel nekoliko hitreje. Ker konstantam ne moremo vrednosti določati v izvajalnih stavkih, jih moramo vedno inicializirati. Če je uporabljena beseda volatile, deklarira vrednost, ki jo lahko spreminja program, lahko pa jo tudi spremeni nek zunanji vpliv, kot je recimo računalniška ura, ki bi recimo povečala vrednost shranjene spremenljivke. To prepreci optimizatorju, da bi optimiziral stvari, za katere misli, da se ne bodo spreminjale, vendar pa se z njimi to lahko zgodi.

Tu so podani primeri uporabe obeh tipov konstant;

     const int index1 = 2;
     const index2 = 6;
     const float big_value = 126.4;
     volatile const int index3 = 12;
     volatile int index4;


ZNAKI ZA PRETVORBO

Sledeča tabela je seznam nekaterih pretvorniških  znakov in način, kako jih uporabimo v printf( ) stavkih. Kompleten seznam teh znakov bi moral biti priložen dokumentaciji danega prevajalnika. Ni še potrebno, da razumete vse, morali pa bi vedeti, da je pri teh stavkih prisotna velika prilagodljivost, ko se jo boste naučili uporabljati..

      d    desetiška notacija
      i    desetiška notacija (razširitev novega standarda ANSI)
      o    osmiška notacija
      x    šestnajstiška notacija
      u    nepredznačena notacija
      c    znak (character)
      s    niz (string)
      f    notacija s plavajočo vejico
Pred vsakega izmed teh znakov moramo postaviti znak za procent (%), da nakažemo, katerega tipa  izpis želimo. Naslednja polja pa lahko postavimo med ta dva znaka.
     -     leva poravnava v polju
     (n)   število, ki določa najmanjšo širino polja
     .     ločilo med n in m
     (m)   število pomembnih decimalnih mest za števila s plavajočo vejico
     l     da nakažemo long
Vsi ti znaki so že uporabljeni v programu LOTTYPES.C, z izjemo notacije niza, katero bomo obdelali pozneje. Vrstice od 33 do 35 prikazujejo, kako lahko določimo poljubno širino polja, v katerega se izpiše spremenljivka,
vrstici 39 in 40 pa prikažeta, kako določimo širino polja s pomočjo programske kontrole. Širina polja za izpis tip float v vrsticah od 43 do 47 bi morala biti jasna sama po sebi. Prevedite in poženite program ter ugotovite, kakšen vpliv imajo posamezna polja na izpis.

Sedaj imate zmožnost izpisa kakršnegakoli podatkovnega polja in dobro bi bilo, če bi pogledali prejšnje programe in ugotovili, če lahko polja prikažete na nacin, ki si ga sami želite.
 

ZDRUŽEVANJE RAZLIČNIH TIPOV

Primer programa ------> COMBINE.C

Oglejte si datoteko COMBINE.C, kjer so primeri kombiniranja spremenljivk različnih tipov v programu. Velikokrat moramo množiti spremenljivko tipa int s spremenljivko tipa float in C nam to dovoljuje z uvedbo skupine strogih pravil, ki se jih drži pri relizaciji takih kombinacij.

V programu deklariramo pet spremenljivk treh različnih tipov v vrsticah 4 do 6, tri od njih pa tudi inicializiramo, tako, da imamo nekaj podatkov, s katerimi lahko delamo. Vrstica 8 nam pokaže primer ko int spremenljivko prištejemo float spremenljivki, rezultat pa dodelimo spremenljivki tipa char. Za kontrolo tipa, ki ga prištevamo, uporabimo t.i. kasto, ki ji nakažemo z definicijo tipa, v katerega želimo pretvarjati, ki ga zapišemo v oklepaj pred spremenljivko. To prisili oba tipa, da se pretvorita v tip char pred seštevanjem. V nekaterih primerih uporabe kaste, se mora bitna struktura spremeniti od znotraj, da bi lahko dobili tip, ki ga želimo. Vrstice od 9 do 11 izvedejo enako seštevanje z uporabo različnih kast, da bi dobili končni rezultat. To pomeni, da je seštevanje v vseh treh primerih različno, ker seštevamo različne tipe, lahko bi se celo zgodilo, da dobimo različne rezultate.

Vrstice od 13 do 15 nam ilustrirajo uporabo kaste pri množenju dveh
float spremenljivk. V dveh primerih se vmesni rezultat pretvori v tip int,
končni rezultat pa se s pomočjo kaste zopet pretvori nazaj v tip float.
Marljiv študent bo opazil, da rezultat teh treh vrstic ne bo nujno enak.

Prevedite in poženite ta program. Ko ga boste prevedli, se lahko zgodi, da boste dobili veliko opozoril zaradi pretvarjanja tipov, katere pa lahko zaenkrat še ignorirate. V tem programu demonstriramo stvari, katere lahko naredite, niso pa nujno dobre v pravih programih. Lahko pa se znebimo vseh opozoril tako, da v program pri pretvarjanju tipov vključujemo kaste.

LOGIČNE PRIMERJAVE

Primer programa ------> COMPARES.C

Naložite in si oglejte program, ki vsebuje veliko primerov primerjalnih stavkov v C-ju. Začnemo z deklaracijo in inicializacijo devetih spremenljivk za uporabo v programu.

Prva skupina primerjalnih stavkov predstavlja najenostavnejšo vrsto primerjav, saj med seboj enostavno primerjamo dve spremenljivki. Katerokoli od spremenljivk bi lahko zamenjali s konstanto, pa bi primerjava še zmeraj bila legalna, vendar pa je primerjava dveh spremenljivk bolj splošna. Prva primerjava preverja, če je vrednost x-a enaka vrednosti y-a in uporablja dvojni enačaj za primerjavo. Ker sta x in y enaka, dobi z vrednost -13. Tu bi lahko uporabili enojni enačaj, kar pa bi imelo drugačen pomen, kot bomo to videli kasneje. Druga primerjava preverja, če je trenutna vrednost x-a večja od trenutne vrednosti y-a.

Tretja primerjava vpelje nov operator, negacijo, ki je predstavljena s klicajem (!), ki se lahko uporabi za invertiranje rezultata logične primerjave. Četrta preverja, če je vrednost b-ja manjša ali enaka vrednosti c-ja, zadnja pa preveri, če vrednost r-a ni enaka vrednosti s-a. Kot smo se  naučili že v prejšnjem poglavju, če je rezultat primerjave resničen, se bo izvedel stavek, ki sledi if stavku, rezultati pa so dani v komentarju.

Možne so tudi primerjave "manjše od" in "večje ali enako", vendar jih v tem primeru nismo omenili.

Dobro bi bilo, če bi omenili drugačen format if stavka v tem primeru. Prehod v novo vrsto kot ločitev stavkov ni potreben, če pa postavimo pogojni stavek v isto vrsto kot if stavek, izboljšamo čitljivost celotnega programa.
 

ŠE VEČ PRIMERJAV

Primerjave v drugi skupini so že nekoliko bolj zapletene. Če začnemo s prvo primerjavo, najdemo v oklepaju nenavadno skupino pogojev. Da bi jih razumeli, moramo razumeti, kaj v C-ju pravzaprav pomeni resnično in neresnično. Neresnično je definirano kot vrednost nič, resnično pa je katerakoli druga, od nič različna vrednost. Vsaka celoštevilska ali znakovna spremenljivka se lahko uporablja kot rezultat testa resnično/neresnično, tudi rezultat lahko priredimo int ali char spremeniljivki.

Poglejte si prvo primerjavo v drugi skupini primerjalnih stavkov. Pogojni stavek "r != s" bo ocenjen kot resničen, saj smo r-u v vrstici 13 dodelili vrednost 0.0, torej bo rezultat primerjave neničelno število. Pri vseh dobrih prevajalnikih za C bo postavljena na 1. Pravilo dobrega programiranja bi bilo, da tako dobljene enke ne uporabljamo v izračunih, pač pa le za logično kontrolo. Čeprav sta obe primerjani spremenljivki tipa float, bo logični rezultat tipa int, Nazadnje rezultat dodelimo celoštevilski spremenljivki x. Če bi tu uporabili dvojni enačaj, bi se fantomska vrednost, to je ena, primerjala z x-om, ker pa smo uporabili enojni enačaj, se vrednost 1 priredi x-u, kot da stavek ne bi bil v oklepaju. Ker je bil rezultat primerjave v oklepaju neničelen, je bil celoten izraz ocenjen kot resničen, smo x-u dodelili novo vrednost, z-ju pa smo dodelili vrednost 1000. V tem stavku smo predelali kar nekaj snovi, zato si ga, preden nadaljujete, oglejte še enkrat. Stvari, ki si jih velja zapomniti, so vrednosti, ki jih zavzameta izraza resnično in neresnično ter to, da lahko v primerjalnemu stavku priredimo več stvari. Vrednost, prirejena x-u, je bila verjetno 1, toda edina zahteva je to, da je bilo to neničelno število. ANSI-C standard pravi, da mora biti rezultat primerjalnih operacij ( >, >=, <, or <=) enak 1 ali 0, ne definira pa rezultata operacije enačenja. Če boste predvideli, da bo ta vrednost 1 ali 0, in jo boste uporabili le za kontrolo, ne boste imeli težav.

Primer v vrstici 20 bi vam nekaj od zgornjih trditev pomagal razjasniti. V tem primeru x-u priredimo vrednost y-a, in ker je rezultat 11, je pogoj neničelen, kar pomeni, da je resničen, z dodelimo vrednost 222.

Tretji primer v drugi skupini v vrstici 21, primerja vrednost x-a z ničlo. Če je rezultat resničen, torej x ni nič, potem z-ju priredimo vrednost 333, kar se bo tudi zgodilo. Zadnji primer v tej skupini predstavlja isti koncept, saj bo rezultat resničen, če je x različen od nič. Primerjava z ničlo v vrstici 21 pravzaprav sploh ni potrebna in rezultat primerjave je resničen. Tretji in četrti primer v tej skupini so tako logično enaki. Seveda pa z-ju vsakič priredimo drugo vrednost.
 

DODATNI PRIMERJALNI KONCEPTI

Tretja skupina primerjav nam bo predstavila neka dodatne koncepte, to sta logična "in" ter "ali" operatorja. Vrednost 77 priredimo vsem trem spremenljivkam preprosto zato, da imamo neke podatke, s katerimi lahko operiramo. Prva primerjava v tej skupini nam predstavi nov operator &&, ki je logični "in", ki je resničen,  če sta resnicni obe strani. Celoten izraz se tako prebere : če je x enak y in če je x enak 77, potem je rezultat resničen. Ker to velja, z-ju dodelimo vrednost 33. Operator "in" lahko uporabljamo le s celoštevilskimi spremenljivkami, torej tipa float in double tu ne prideta v poštev.

Naslednja primerjava v tej skupini uvede operator ||, to je logični "ali", ki je resničen, če je vsaj ena izmed strani resnična. Stavek se prebere kot: če je x večji od y ali če je z večji od 12, potem je rezultat resničen. Ker je z večji od 12, ni pomembno, če je x večji od y, saj mora biti le eden od pogojev resničen, pa je tudi rezultat resničen. Tak tu tudi je, zato z-ju priredimo vrednost 22. Podobno kot v prejšnjem primeru, tudi tu ne moremo uporabljati tipov float in double.
 

LOGIČNO VREDNOTENJE (SHORT CIRCUIT)

Kadar vrednotimo sestavljen stavek, vrednotenje poteka z leve proti desni, in ko je izid zagotovljen, se vrednotenje ustavi. Tako se v primeru "and" stavka, ko je eden od pogojev neresničen, vrednotenje ustavi, saj tudi dodatni resnični pogoji ne morejo povzročiti, da bi bil tudi celoten rezultat resničen. V primeru "or" stavka pa se vrednotenje ustavi, ko je eden od pogojev resničen, saj je kljub kakršnimkoli naslednjim pogojem nemogoče, da bi bil rezultat neresničen. Temu pravimo tudi "short circuit evaluation", saj se ostali pogoji ne vrednotijo.

Če gremo na naslednji primer v tretji skupini, najdemo tri enostavne spremenljivke, uporabljene v pogojnem delu primerjave. Ker so vse tri različne od nič, so vse tri resnične, torej je tudi "and" stavek resničen, zato z-ju priredimo vrednost 11. Bodite pozorni, da spremenljivk r, s in t ne bi mogli uporabiti na tak način, saj so tipa float.

Če nadaljujemo na vrstici 30, najdemo tri prireditvene stavke v primerjalnem delu if stavka. Če ste razumeli zgornjo diskusijo, Vam ne bo težko razumeti, da vsem trem spremenljivkam po vrsti priredimo njihove nove vrednosti, rezultat od vseh treh je različen od nič, kar pomeni, da je rezultat resničen.
 

TO JE TRIK, BODITE PAZLJIVI

Zadnji primer v tretji skupini vsebuje nekakšen trik, ker pa smo ga že obdelali zgoraj, ne zvemo  nič novega. Opazili boste, da je prvi del primerjave neresničen, saj x trenutno ni enak 2. Ostali deli primerjave se ne vrednotijo, saj je to logični "and", in je v vsakem primeru neresničen. Če bi bil program odvisen od dodelitve vrednosti 3 y-u, ne bi deloval, saj se vrednotenje konca po prvem pogoju, ki je neresničen. Podobno, spremenljivki z ne dodelimo vrednosti 4, prav tako pa ne spremenimo r-a. To je zato, ker C, kot smo že povedali, uporablja "short circuit evaluation".
 

POTENCIALNA  PROBLEMATICNA  OBMOČJA

Zadnja skupina prikazuje tri možnosti, kjer lahko zaidete v težave. Vse tri imajo podoben rezultat, to je nepravilno ravnanje z z-jem, vendar pa se to dogaja iz različnih razlogov. V vrstici 37 se primerjava ovrednoti kot resnična, vendar pa podpičje, ki sledi drugemu oklepaju, zaključi if stavek, zato se prireditveni stavek, ki vsebuje z, vedno izvede kot naslednji stavek. If stavek torej nima nobenega vpliva zaradi napačno postavljenega podpičja. V resnici je to ničti stavek, ki je sicer veljaven  v C-ju, vendar pa programer verjetno ni hotel zapisati dodatnega podpičja.

Stavek v vrstici 38 je bolj jasen, saj bo spremenljivka x vedno enaka sama sebi, neenačaj ne bo nikoli izpolnjen, torej celoten stavek ne bo nikoli izveden, pač pa je le izgubljen trud. Stavek v vrstici 39 bo x-u vedno priredil vrednost 0, primerjava bo vedno neresnična, pogojni del if stavka se torej nikoli ne bo izvedel.

Pogojni stavek je izredno pomemben in ga morate podrobno razumeti, da boste lahko pisali učinkovite C-jevske programe. Če se vam katerikoli del snovi zdi nerazumljiv, ga preučite še enkrat, dokler ne boste prepričani, da ga razumete. Lahko se zgodi, da boste dobili veliko opozoril zaradi konverzije tipov, ki jih lahko ignorirate ali pa v program zapišete kaste. Dodajte nekaj izpisa, da boste videli rezultate nekaterih operacij.
 

NEJASNI DEL C-JA

Primer programa ------> CRYPTIC.C

V C-ju obstajajo trije konstrukti, ki se  ne bodo zdeli smiselni, ko jih boste prvič videli, saj jih je težko razumeti intuitivno, vendar pa lahko izboljšajo učinkovitost prevedene kode in jih izkušeni programerji s pridom uporabljajo. Ravno zato jih morate videti in se jih nauciti, saj se bodo pojavljali v večini, če ne kar v vseh programih, ki jih boste srečali v publikacijah. Naložite in si oglejte program CRYPTIC.C za primer teh treh novih konstruktov.

V tem programu je nekaj spremenljivk definiranih in inicializiranih za poznejšo uporabo. Stavek v vrstici 8 enostavno doda 1 vrednosti x, kar vas ne bi smelo presenetiti. Tudi naslednja dva stavka dodata 1 x-u, vendar pa to ni takoj razvidno. To je res, ker je tako definirano. Torej, po definiciji C-ja, dvojni plus pred ali po spremenljivki poveča to spremenljivko za 1. Dodatno, če sta plusa pred spremenljivko, se ta poveča pred uporabo, če pa sta za njo, pa se poveča po uporabo. V vrstici 11, vrednost y-a dodelimo z-ju, nato pa y povečamo, saj sta plusa za spremenljivko. V zadnjem stavku te skupine, vrstica 12, vrednost y-a najprej povečamo, nato pa njegovo vrednost dodelimo spremenljivki z. Pravilna izraza za ta dva konstrukta sta predekrement in postdekrement.

Naslednja skupina stavkov prikazuje zmanjšanje spremenljivke za eno. Definicija je enaka za dekrement kot za inkrement. Če sta minusa pred spremenljivko, se ta najprej zmanjša in nato uporabi, če pa sta minusa za spremenljivko, pa jo najprej uporabimo in nato zmanjšamo. Pravilna izraza pa sta predekrement in postdekrement.

Ta konstrukt boste v svojih programih veliko uporabljali.
 

NEJASNI ARITMETIČNI OPERATOR

Še en uporaben, vendar nejasen operator je aritmetični operator. Ta operator uporabljamo za spreminjanje neke spremenljivke za konstantno vrednost. Stavek v vrstici 23 prišteje 12 vrednosti spremenljivke a. Stavek v vrstici 24 naredi isto, vendar pa to zopet ni intuitivno jasno. Katerokoli izmed štirih aritmeticih funkcij +,-,*,/ lahko uporabljamo na ta način tako, da postavimo želeno operacijo pred enačaj in izpustimo drugo sklicevanje na spremenljivko. treba je poudariti, da je lahko izraz na desni strani aritmetičnega operatorja katerikoli veljaven izraz v C-ju, primeri so enostavni za lažje razumevanje tega novega operatorja.

Kot velja za inkrement in dekrement, tudi aritmetični operator izkušeni programerji veliko uporabljajo, zato bi se vam izplačalo, da ga dobro razumete.
 

POGOJNI IZRAZI

Pogojni izrazi so tako nejasni kot zadnja dva konstrukta, vendar se  jih zopet splača razumeti, saj so zelo uporabni. Sestavljajo jih trije izrazi, ločeni z vprašajem ter dvopičjem. Najprej se ovrednoti izraz pred vprašajem, da se ugotovi ali je resničen ali neresničen. Če je resničen, se ovrednoti izraz med vprašajem in dvopičjem, če pa izraz ni resničen, pa se ovrednoti izraz za dvopičjem. Rezultat enega od vrednotenj se uporabi za prireditev, kot je to prikazano v vrstici 30. Končni rezultat je enak tistemu, ki ga dobimo s pomočjo if-else stavka. To je prikazano v vrsticah od 32 do 35 v tej skupini stavkov. Pogojni izrazi imajo to prednost, da je z njimi koda bolj kompaktna, ter da se prevede na manj strojnih ukazov v končnem programu.

Vrstice 37 in 38 tega primera so podane, da prikažejo, kako spremenljivki c dodeliti večjo od vrednosti a in b, in kako dodeliti manjšo od teh dveh vrednosti c-ju. Bodite pozorni, kako učinkovita je koda v tem primeru.
 

PISATI JASNO ALI NEJASNO

Nekaj študentov je izjavilo, da jim ti trije nekoliko nejasni konstrukti niso všeč in da jih enostavno ne bodo uporabljali. To bi bilo v redu, če jim ne bi bilo treba brati programov, ki so jih napisali drugi ljudje ali pa te programe celo uporabljati v svojih. Našli boste veliko funkcij, ki jih boste lahko uporabili v svojih programih, rabili pa bodo malenkostne spremembe, za katere pa bo potrebno razumevanje izposojene funkcije. Zato bo v vašo korist, da se teh konstruktov naučite in jih tudi uporabljate. Uporabljeni bodo tudi v nadaljevanju tega tečaja, tako, da se boste prisiljeni z njimi spopasti.

To je bilo dolgo poglavje, vendar pa je vsebovalo pomembne snovi, ki Vam bodo v veliko pomoč, da boste zaceli programirati v C-ju. V naslednjem poglavju se bomo posvetili gradbenim enotam programov, funkcijam. Takrat boste že imeli dovolj osnovnega znanja za pisanje smiselnih programov.
 

STILSKI NASVETI

Po tem poglavju nimamo kakšnih posebnih stilskih nasvetov, razen stilskih metod, predstavljenih v primerih programov. Večina teh programov je netipičnih za C, saj na primer skoraj nikoli nimamo potrebe v program napisati seznam vseh možnih primerjav. Te programe lahko uporabljate kot vodnike do dobrega stila programiranja, čeprav niso pravi programi.
 

KAJ JE l-vrednost IN KAJ r-vrednost?
 

Figure 4-1
Včasih boste kje zasledili pojma l-value ali r-value v gradivu o C-ju ali v dokumentaciji za vaš prevajalnik. Vsaka spremenljivka ima r-vrednost, ki je definirana kot dejanska vrednost shranjena v spremenljivki, ima pa tudi l-vrednost, ki je definirana kot ime spremenljivke. Tako bi imela spremenljivka, predstavljena grafično na sliki 4-1 l-vrednost index in r-vrednost 137, saj je to dejanska vrednost shranjena v spremenljivki.

Definicija te spremenljivke bi se torej glasila :

int index = 137;
 

PROGRAMERSKE NALOGE

  1. Napišite program, ki bo štel od 1 do 12, izpisoval šteta števila in
     njihove kvadrate, za vsako število posebej.
  2. Napišite program, ki šteje od 1 do 12 in izpisuje števne vrednosti in
     njihova inverzna števila na pet decimalk natančno. Za to bo potrebno
     število s plavajočo vejico.
  3. Napišite program, ki bo štel od 1 do 100, izpisal pa le števila med 32
     in 39, vsakega v svojo vrsto. Za ta program uporabite operator
     inkrement.

Povratek na kazalo

Prehod na poglavje 5


Copyright  1988-1997 Coronado Enterprises - Last update, March 15, 1997
Prevedel: Sašo Kuntarič