Vejitve

Programi v realnem svetu tipično niso linearni in se jih kot take ponavadi v večini primerov ne da izraziti kot navadno sekvenco stavkov. Pogosto namreč v njih nastopajo odločitve in posledično različno izvajanje kot npr.:

Take in podobne rešitve v programskih jezikih rešujejo posebni stavki, ki jim pravimo vejitve.

V Javi nastopata dve stavčni obliki vejitev:

pogojno pa med vejitve lahko uvrstimo tudi pogojni operator :

Vsako izmed naštetih oblik si bomo ogledali v naslednjih razdelkih.


Stavek if

Predstavlja najsplošnejšo obliko vejitve. Tok programa je zmožen glede na pogoj razcepiti v dve ločeni izvajalni poti.

Sam stavek lahko nastopa v dveh oblikah :

krajši:

if (logični_pogoj) Stavek;
oz.
if (logični_pogoj) {
   Stavek1;
   Stavek2;

   ..
   StavekN;
}

 

   

Z diagramo lahko spodnji stavek predstavimo kot :

V prvem primeru se ob izpolnjenem logičnem pogoju izvrši stavek Stavek, v drugem pa blok stavkov od stavka Stavek1 do stavka StavekN.

Na mestu logičnega pogaja vedno nastopa logična vrednost; ali podatek, ki je logičnega ali pa izraz, katerega rezultat je logična vrednost ali pa funkcija(metoda), ki vrača vrednost logičnega tipa.

Dva kratka primerčka :

if (ocena==1)
    System.out.println("Pricni se uciti !");
if (ocena==1 && letnik==4){
   System.out.println("Pricni se uciti !");
   System.out.println("Matura je pred vrati  !");
} 

razširjeni:

if (logični_pogoj) {
   stavekd_1;
   stavekd_2;


..

   stavekd_N;
}  else {
     stavekn_1;

     ..

     stavekn_N;
}

V primeru izpolnjenega pogoja se izvrši blok stavkov stavekd_1 do stavekd_N, v nasprotnem primeru pa blok stavkov stavekn_1 do stavekn_N. Strukturo stavka ponazarja slika :

 

Programska primera:

 

/* program z ukazne vrstice prevzame tri številske argumente in preveri, 
   če lahko daljice s takimi dolžinami sestavijo trikotnik */   

class If_003{  
   public static void main(String[] arg){  

      int a = Integer.valueOf(arg[0]);  
      int b = Integer.valueOf(arg[1]);  
      int c = Integer.valueOf(arg[2]); 

       if (a+b>c) 
         if (a+c>b) 
            if (b+c>a) 
               System.out.println("Daljice z dolzinami "+a+" "+b+" "+c+  
                                  " lahko sestavijo trikotnik");  
   }  
}  

 

 

/ * Program, ki preveri, če sta dve naključno generirani števili enaki . * /   
class Preveri2Stevili {   
   public static void main(String[] arg){  
        int x= (int)(Math.random()*6+1);  
        int y= (int)(Math.random()*6+1);   

        if ( x == y)  
           System.out.print ( " Vrednosti sta enaki. " ); 
         else 
           System.out.print ( " Vrednosti sta različni. " );  
   }  
}  

 


'switch' stavek

Switch stavek omogoča vejitev na več kot dve izvajalni poti in je v svojem bistvu okrajšava zapisa v primeru, da tako vejitev želimo izvesti s serijo gnezdenih if stavkov. Poglejmo si primer :

 
if (x == 0) 
      stavek0; 
else 
    if (x == 1) 
          stavek1; 
   else 
        if (x == 2) 
               stavek2; 
       else 
            if (x == 3) 
                  stavek3; 
          else 
                if (x == 4) 
                      stavek4; 
              else 
                    stavekD;

Zaporedje stavkov je enakovredno desnemu diagramu poteka izvajanja.

Krajše lahko enako v Javi zapišemo z uporabo stavka switch-case, kot je nakazano spodaj:

 

switch (x) {                   
     case 0: stavek0;  break;  
     case 1: stavek1;  break;  
     case 2: stavek2;  break;  
     case 3: stavek3;  break;  
     case 4: stavek4;  break;  
  default:                     
     stavekD;                  
}                              

Pri tem mora biti x (parameter stavka switch) ali spremenljivka ali pa izraz (formula,...), ki lahko vrne vrednost. Vrednost spremenljivke ali izračunanega izraza mora biti enega izmed naslednjih tipov : int, byte, short ali char (katerega koli tipa, ki ga lahko pretvorimo v tip int brez izgube natančnosti).

Pri izvajanju danega delčka kode se x zaporedno primerja z vrednostjo vsakega izmed case stavkov, dokler ujemanje ni uspešno. Dani primer primerja x s konstantami. Namesto konstant bi lahko uporabili spremenljivke ali izraze, dokler bi bila njena vrednost enega izmed tipov int, byte, short ali char.

V primeru, da je ujemanje v enem izmed case stavkov uspešno , se izvedejo vsi nadaljni stavki do konca switch stavka, ki sledijo temu ujemanju. Ker tega ponavadi ne želimo, ob koncu vsakega stavka dodamo stavek break, ki dejansko prekine nadaljevanje izvajanja switch stavka.

Če pri izvajanju ne pride do ujemanja, se izvede stavek stavekD za besedico default (privzeti stavek).

Uporaba privzetega stavka ni obvezna; torej lahko nastopi switch stavek brez bloka default :

switch (x) {
			case 0: stavek0; break;
			case 1: stavek1; break;
			case 2: stavek2; break;
			case 3: stavek3; break;
			case 4: stavek4; break;
}  

Če ujemanje ne nastopi (x ni enak 0 ali 1 ali 2 ali 3 ali 4) se pač ne izvede noben stavek.

 

Pomembno si je zapomniti, da switch statevek sam ne preneha z izvajanjem ko je eno izmed primerjanj uspešno in se ob tem izvede ustrezen stavek. Za analizo obnašanja si oglejmo naslednji primer in predpostavimo, daje vrednost x enaka 2. Pomagajmo si z desnim diagramom :

 

switch (x) {
   case 0: stavek0;
   case 1: stavek1;
   case 2: stavek2;
   case 3: stavek3;
   case 4: stavek4;
 default:
   stavekD; 
}
 
 
ujemanje dosežemo v vstici:
case 2 : stavek 2;  


zato se zaporedno izvedejo vsi naslednji stavki :
 
stavek2,
stavek3,
stavek4,
stavekD

 

 
  

Pogojni operator ? :

Vrednost spremenljivke je pogosto odvisna od nekega logičnega izraza. Primer določanja večje izmed dveh vrednosti je podan kaže naslednja koda:

if (a > b) {
  max = a;
}
else {
  max = b;
}

Določanje ene izmed dveh vrednosti eni sami spremenljivki pri programiranju pogosto rešujemo s sekvenco stavkovif-then-else . Tak problem lahko rešimo tudi z uporabo pogojnega operatorja ?: . Če zgornji primer na novo prepišemo, dobimo naslednje :

max = (a > b) ? a : b;

(a > b) ? a : b; je izraz, ki vrača eno izmed dveh vrednosti, a ali b. Pogoj(a > b) se pri izvajanju testira . Če je resničen stavek vrne prvo vrednost za simbolom ?, v nasprotnem primeru pa drugo vrednost, ki je podana za simbolom : . Pogoj a > b mora pri tem biti logičnega tipa, lahko je sprememnljivka, konstanta ali pa izraz, ki vrača logično vrednost.

Pogojni operator deluje le za prirejanje vrednosti spremenljivki ! Poglejmo si naslednji primer :

if (a>b) {
  System.out.println("A je večji");
}
else {
  System.out.println("A NI večji'");
}

Gornjega ne moremo prepisati kot :

(a>b) 
 ? System.out.println("A je večji") 
 : System.out.println("A NI večji");

Najprej sta drugi in tretji argument operatorja ?: taka, da ne vračata nobene vrednosti (void). Nato, nobena prireditev v stavku ni prisotna, ki bi določala, kakšnega tipa je vrednost, ki jo pričakujemo, da jo bosta vrnila drugi in tretji argument (navkljub temu, da vemo, da ne moreta biti tipa void).

Prvi argument pogojnega operatorja mora vrniti logično vrednost, drugi in tretji argument pa morata vračati vrednost, ki je združljiva s tipom, ki ga vrača celoten izraz.

Nikoli za drugi in tretji argument ne smemo uporabiti nekaj, kar ne vrne nobene vrednosti (oziroma je tipa void).


 

 

Vejitve - vaje za utrjevanje

 

Vprašanje 1
Kateri izmed naštetih konstruktov omogočajo vejitve (in ne tudi ponavljanja) ?
 
if stavek
while stavek
for stavek
switch stavek (switch-case)
do-while stavek
   
Vprašanje 2
Operator ?: lahko uporabimo namesto if stavka
zgolj v primeru, da izraz po odločitvi vrača vrednost
da
ne
   
Vprašanje 3
Kolikšna je vrednost spremenljivke x po izvedbi naslednjega zaporedja stavkov?

 

int a = 3, b = 9;
int x = ( (b%a)>1) ? a : b;

0
1/3 (ena tretina)
3
9
   
Vprašanje 4
Kdaj bi bilo smiselno uporabiti switch stavek namesto if stavka ?
 
stavek switch v nobenem primeru ne more nadomestiti if stavka
v vsakem primeru, saj niti zapis switch stavka ni daljši od zapisa if stavka
v primeru, da imamo na neki točki programa vejitev postopka v več kot dve izključujoči se izvajalni poti
v primeru, da imamo na neki točki programa vejitev postopka v veź kot dve neizključujoči se (odvisni) izvajalni poti
   
Vprašanje 5
Kakšna je vrednost spremenljivke b po izvedbi stavkov ?

 

boolean a=false;
int b = (a) ? 3 : 6;

3
6
   
Vprašanje 6
Koliko je b po naslednji izvršeni sekvenci ?

 

int a = 3, b=0;
switch (a) {
  case 2 : b=b+1; break;
  case 3 : b=b+2; break;
  case 4 : b=b+3;
}

0
2
3
4
5
   
Vprašanje 7
Kaj je rezultat naslednjega zaporedja stavkov ?

 

int a = 3, b=0;
switch (b) {
  case 2 : b=b+1;
  case 3 : b=b+2;
  case 4 : b=b+3;
}

b=0;
b=2;
b=3;
b=4
b=5
 

Rešite naslednje programske probleme

Naloga 1

Napišite program, ki bo izvedel prekodiranje zaporedne številke dneva v tednu v ime dneva. Pri tem predpostavite, da ima teden natanko 7 dni, ter da je prvi dan v tednu vedno ponedeljek. Realizacija naj vključuje dva ločena programa, prvi naj zahtevano izvede s pomočjo stavkov if, drugi s pomočjo stavka switch. Zaporedno številko dneva v tednu pridobite preko parametra glavne funkcije. V primeru, da je vneseno število tako, da ne more predstavljati dneva v tednu, naj program izpiše informacijo o nepravilnem vnosu in se konča.

 


Naloga 2

Dan je naslednji javanski program:

 

 /* 
 Simulacija meta kocke 
 */ 
 class SimKocka{ 
    public static void main(String[] arg){ 
      int izbrana = (int)(Math.random()*6+1); 
      if (izbrana==6) { 
         System.out.println(" ----- "); 
         System.out.println("| * * |"); 
         System.out.println("| * * |"); 
         System.out.println("| * * |"); 
         System.out.println(" ----- "); 
      } 
    } 
 } 

 

Program je trenutno zmožen detektirati le met številke 6. Popravite dani program tako, da bo odziv programa ustrezna ‘grafična’ predstavitev meta kocke za vsako izmed možnih generiranih števil.

 

 

Naloga 3

Pri določenih igrah s kocko potrebujemo za legalen met dve kocki (npr. Jamb). Vaša naloga je : ‘popravite’ program, da bo namesto ene ‘vrgel’ dve kocki. Pri tem bi želeli, da se kocki za isti met izrišete ena poleg druge. Npr. pri metu 3,5 bi želeli izris oblike :

  -----   -----
 | *   | | * * |
 |  *  | |  *  |
 |   * | | * * |
  -----   ----- 

V primeru, da se vam zdi problem pretežak, ga lahko poenostavite v tej meri, da se kocki izrišeta ena pod drugo.

Naloga 4

Programsko realizirajte matematično funkcijo 'signum' . Pri tem vrednost neodvisne spremenljivke prebere preko parametra ukazne vrstice programa, program naj glede na vrednost parametra izpiše odgovarjajočo vrednost. Podajte dve realizaciji programa: realizacijo s pomočjo if stavka in realizacijo s pomočjo pogojnega operatorja ?:.

( mimogrede : signum(negativna_vrednost) vrne -1, signum(0) vrne 0, signum(pozitivna_vrednost) vrne 1 )