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 vejicoPred 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 longVsi 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,
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?
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.