Interaktivnost v javanskih programih

( enostaven vnos podatkov med izvajanjem programa in več)

Naši dosedanji programi so bili slabo interaktivni. Preprosto smo se izogibali postopkov, ki med delovanjem programa zahtevajo vnos nekih vrednosti s strani uporabnika. Včasih pa se kljub temu pojavi potreba po takem vnosu in tu se prično komplikacije.

Tipično se vnosi oz. branje podatkov vrši preko mehanizma tokov (Streams) in postopek uporabe zahteva poznavanje zahtevnejših dodatnih mehanizmov, da se branje izvrši pravilno in brez napak. Nekatere od teh postopkov bomo spoznali v nadaljevanju.

Poenostavitev postopka vnosa podatkov v javanski program med njegovim izvajanjem predstavlja razred Scanner (java.util.Scanner), ki je bil uveden z Java 2 platformo verzije 1.5.0:

 

Scanner

Scanner je preprost bralnik (scanner), ki je sposoben iz podanega besedila izluščiti podatke primitivnih tipov pa tudi nize znakov. Vhodno besedilo razbije na posamezne dele, ki so med seboj ločeni z zahtevanim ločilnim znakom (privzeto je to presledek) in posamezne dele skuša pretvoriti v podatek zahtevanega tipa.

Realizacij branja je poenostavljena:

Primer branja celoštevilskega podatka s standardnega vhoda :

Scanner sc = new Scanner(System.in);
int i = sc.nextInt();

 

Prvi stavek pove, da bo Scanner deloval nad standardnim vhodom, z drugim zahtevamo branje celoštevilske vrednosti. Namesto System.in bi lahko nastopala poljubna vhodna naprava, niz znakov ali datoteka (poljuben vhodni tok podatkov).

Primer niz znakov razbije na posamezne besede in vsako izmed njih izpiše v lastni vrstici:

     String input = "ena dva tri stiri";
     Scanner s = new Scanner(input);
     System.out.println(s.next());
     System.out.println(s.next());
     System.out.println(s.next());
     System.out.println(s.next());
     s.close(); 

izpis:

ena
dva
tri
stiri

V zgornjem primeru je ločilec med podatki presledek, po potrebi pa lahko določimo lastnega. Recimo, da podatke med seboj ločuje pika (.) :

     String input = "1.fish.2.fish.red.fish.blue.fish";
     Scanner s = new Scanner(input);
     s.useDelimiter("\\.");   // nov ločilec med podatki naj bo pika
     System.out.println(s.next());
     System.out.println(s.next());
     System.out.println(s.next());
     System.out.println(s.next());
     s.close(); 

izpis:

1
fish
2
fish

Ločilci med podatki morajo biti v obliki podani v skladu z regularnimi izrazi (regular expressions oz. regex; definirani z istoimenskim javanskim razredom).

 

Primer :

Sesteje vse (zgolj celoštevilske) vrednosti, ki jih naštejemo in izpiše njihovo vsoto :

import java.util.*;   // za Scanner


class SestejVrednosti{


  public static void main(String[] ar){


      String input = "1 2 3 4 5 6 7 8 9 10";

      Scanner vhod = new Scanner(input);


      int vsota = 0; 

      while (vhod.hasNextInt()) {
          int celo = vhod.nextInt();
          vsota+=celo;
      }
      System.out.println(vsota);
  }
}

 

Opozorilo :

Scanner lahko 'blokira' izvajanje javanskega programa v primeru, da čaka na uporabnikov vnos podatkov !

Poglejmo si rahlo spremenjen predhodni primer :

import java.util.*;   // za Scanner


class SestejVrednostiVhoda{


  public static void main(String[] ar){


      
      Scanner vhod = new Scanner(System.in);


      int vsota = 0; 

      while (vhod.hasNextInt()) {
          int celo = vhod.nextInt();
          vsota+=celo;
      }
      System.out.println(vsota);
  }
}

Od predhodnega se razlikuje le v tem, da vhodni tok podatkov predstavlja standardni vhod.

Poskusite analizirati delovanje zgornjega programa in ugotoviti, kje smo storili 'napako'. (včasih med izvajanjem 'pomaga' tudi kakšen pritisk na kombinacijo tipk CTRL+c).


Na hitro : 

Inicializacija Scanner-ja z določitvijo ustreznega vhodnega toka :

Scanner ime = new Scanner(vhodni_tok); 

Ali je v vhodnem toku pripravljen podatek, ki ga lahko preberemo:

ime.hasNext();

Branje naslednjega podatka

ime.next(); // niz znakov
ime.nextChar(); //en znak
ime.nextInt(); // int
ime.nextLong(); // long
ime.nextFloat(); // float
....

Zaustavitev Scannerja

ime.close();

Določanje ločilca med posameznimi podatki

ime.useDelimiter(regEx);  

 


Napake pri vnosu:

v primeru, da Scanner podatka ne more pretvoriti v pravilen (zahtevan) primitiven tip, generira izjemo tipa

InputMismatchException (java.util.InputMismatchException)


Programske naloge

Naloga 1

Napišite preprost javanski program, ki med delovanjem zahteva vnos celoštevilske vrednosti, nato na zaslon izpiše prebrano vrednost, kvadrat in kub te prebrane vrednosti.

 

Naloga 2

Napišite javanski program, v katerem si program ‘izmisli’ neko vrednost iz intervala od 0 do 30, uporabnik pa jo mora uganiti v največ petih poskusih. Program na vsako ponujeno rešitev odgovarja z {vrednost premajhna, vrednost prevelika, uganil si}.

 

Naloga 3

Napišite javanski program, ki bo zamenjal vlogi programa in uporabnika v programu iz naloge št. 2. Pri tem naj bodo podatki, ki jih uporabnik poda programu spodnja iz zgornja meja intervala celih števil ugibane vrednosti. Program naj ugiba število ‚inteligentno’ (binarno iskanje oz. bisekcija). Uporabnik med izvajanjem (pravilno) odgovarja oz. usmerja izvajanje programa z {premajhna, prevelika, pravilna}. Omejite delovanje programa na največ 5 poskusov. Po zadnjem poskusu izpišite število poskusov, ki jih je program potreboval, da je ugotovil pravo število/ ali ga ni uspel ugotoviti.

 

Naloga 4

Tabelirajte funkcijo f(x) = 2*x^1.25-2.55 na intervalu [-5,+5] v korakih po 0.1. Rezultat programa naj bo tabela z dvema stolpcem; prvi stolpec naj podaja vrednosti neodvisne spremenljivke, drugi pa vrednost funkcije. Vsa števila naj bodo podana na 4 decimalna mesta natančno, števila naj bodo poravnana glede na mesto decimalne pike (decimalna poravnava).