Gyakorlati alapok
Signore Fibonacci feltételes bekérései
Ebben a fejezetben a már ismertetett Fibonacci-sorozatot generáljuk le, de feltételes adatbekéréssel: merészen megkérdezzük a felhasználótól, hogy hány elemű sorozatot óhajt.
A felhasználóval történő interakció pillanatától ügyelnünk kell arra, hogy a program a felhasználótól korrekt, a program számára értelmezhető bemeneti adatokat kapjon. Ezért a felhasználó által megadott adatokat mindig ellenőrizni kell!
Ezt a fontos alapelvet tanulmányozhatjuk az alábbi kódban. Ebben a konkrét esetben az ellenőrzés során nem szabad megengednünk, hogy bemeneti adatként:
-
negatív számot,
-
túl nagy számot,
-
értelmezhetetlen számot (itt például 3.14),
-
egyéb, értelmezhetetlen karaktert vagy ezek kombinációit kapjunk.
Kezdjük egy egyszerűbb Java-kóddal, amelyik csak a számellenőrzést végzi el: egy elöltesztelő ciklus segítségével csakis pozitív, 1 és 30 közötti számot fogadunk el, ez lesz a sorozat elemszáma (int elemszam):
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner (System.in);
System.out.println ("Hány elemű Fibonacci-sorozatot óhajt (1
és 30 között)?");
String elem = scanner.nextLine();
int elemszam = Integer.parseInt(elem);
while (elemszam <= 0 || elemszam > 30) {
System.out.println ("Kérem, hogy csak
pozitív számot adjon meg 1 és 30 között!");
elem = scanner.nextLine();
elemszam = Integer.parseInt(elem);
}
int [] tomb = new int [elemszam+2];
tomb[0] = 0;
tomb[1] = 1;
for (int i = 0; i < elemszam; i++){
tomb[i+2] = tomb[i] + tomb[i+1];
System.out.print (tomb[i] + " ");
}
}
}
Végeredmény:
Hány elemű Fibonacci-sorozatot óhajt (1 és 30 között)?
31
Kérem, hogy pozitív számot adjon meg 1 és 30 között!
10
0 1 1 2 3 5 8 13 21 34
Érdemes a felhasználót -mintegy észrevétlenül-, kissé irányítani. Az 1. kérdésben ("Hány elemű Fibonacci-sorozatot óhajt (1 és 30 között)?") például diszkréten meg is adjuk a lehetséges számtartományt, és azon tényt, miszerint kizárólag számokat várunk, ezáltal nem hagyjuk meg neki, hogy saját maga kezdjen el találgatni. Esetleges hibás adatbevitel után a lehetőségeket tovább szűkíthetjük ("Kérem, hogy csak pozitív számot adjon meg 1 és 30 között!"). Persze lehetünk szigorúbbak is: ekkor már az 1. kérdésben felsoroljuk az összes választási opciót. Mi most legyünk engedékenyebbek, feltételezvén, hogy a felhasználó tudja: a Fibonacci-sorozat nem kezdődik negatív számmal (de a felhasználóban soha ne bízzunk meg ennyire).
A tesztelés egy elöltesztelő ciklus feltételében történik (while (elemszam <= 0 || elemszam > 30)), és ez egészen addig fog ismétlődni, amíg a bevitt adat a feltétel szerint korrekt nem lesz. A Fibonacci-sorozatot generáló algoritmus csak ezután aktiválódik.
Most nehezítsük meg az adatbekérés kiértékelését, amely egyébiránt kutyakötelességünk is, hiszen ha például szám helyett betűkaraktert gépelünk be, akkor tisztességes mennyiségű hibaüzenetet kapunk:
Exception in thread "main"
java.lang.NumberFormatException: For input string: "w"
at
java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:492)
at java.lang.Integer.parseInt(Integer.java:527)
at Main.main(Main.java:8)
A rendszer nyilvánvalóan nem képes a w karaktert int típusú számmá alakítani a parseInt() függvénnyel.
Az adatbekérés korrekt lekezeléséhez érdemes mindig abból kiindulni, amit be KELL kérnünk és nem abból, amit NEM. Ez kissé érthetetlen, ezért nézzük meg rögtön ebben a konkrét esetben!
Számokat várunk 1 és 30 között, ezért 2 digitű számot várunk, valamint 1. és a 2. digitén csakis az 1 2 3 4 5 6 7 8 9 számkarakterek állhatnak, minden más tiltott (ez nem teljesen igaz, hiszen jobbról a 2. digitén nem állhat 3-nál nagyobb szám, de kiértékelés szempontjából ez nem lényeges, majd alább látjuk, hogy miért.
Tehát nem vizsgáljuk, hogy a bevitt rossz karakter milyen jellegű: azt vizsgáljuk meg, amit be kell kérnünk és nem azt, amit nem.
Az adatbekérés ellenőrzése a következők szerint módosul:
A for ciklus azt ellenőrzi, hogy a szám 2 digitjébe nem kerül-e NEM számkarakter. A kiértékelés még a String-ből kihasított char típuson történik, ráadásul villámgyorsan, ezért nem lényeges, hogy a szám jobbról a 2. digitén nem állhat 3-nál nagyobb szám. Ha talál, a kiértékelés a rosszAdat flag-et true értékre állítja és a break utasítással megszakad.
for(int i = 0; i < elem.length(); i++){
char karakter = elem.charAt(i);
if(karakter != '0'
&& karakter
!= '1'
&& karakter
!= '2'
&& karakter
!= '3'
&& karakter
!= '4'
&& karakter
!= '5'
&& karakter
!= '6'
&& karakter
!= '7'
&& karakter
!= '8'
&& karakter
!= '9'){
rosszAdat = true;
break;
}
}
A következő if elágazás nagyon lényeges:
if(rosszAdat == true){
System.out.println("Kérem, hogy csak pozitív számot adjon meg
1 és 30 között!");
continue;
}
Ha ugyanis az előző kiértékelés rossz karaktert talált, akkor a continue utasítás a ciklusfutást megszakítja és az egész kezdődik a do-while ciklus elejéről, ezáltal megakadályozva, hogy ne számkarakter kerüljön be a parseInt() függvénybe (amely garantált hibaüzenet).
A következő kiértékelés...
if(elemSzam <= 0 || elemSzam > 30){
rosszAdat = true;
...már konkrét számformátumon történik és behatárolja a számtartomány alsó és felső határát.
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner (System.in);
int elemSzam = 0;
boolean rosszAdat = false;
String elem = "";
System.out.println ("Hány elemű Fibonacci-sorozatot óhajt (1
és 30 között)?");
do{
rosszAdat = false;
elem = scanner.nextLine();
for(int i = 0; i < elem.length();
i++){
char karakter
= elem.charAt(i);
if(karakter != '0'
&& karakter != '1'
&& karakter != '2'
&& karakter != '3'
&& karakter != '4'
&& karakter != '5'
&& karakter != '6'
&& karakter != '7'
&& karakter != '8'
&& karakter != '9'){
rosszAdat = true;
break;
}
}
if(rosszAdat == true){
System.out.println("Kérem, hogy csak pozitív számot adjon meg 1 és 30
között!");
continue;
}
elemSzam = Integer.parseInt(elem);
if(elemSzam <= 0 || elemSzam > 30){
rosszAdat =
true;
}
if(rosszAdat == true){
System.out.println("Kérem, hogy csak pozitív számot adjon meg 1 és 30
között!");
}
}while(rosszAdat == true);
int [] tomb = new int [elemSzam+2];
tomb[0] = 0;
tomb[1] = 1;
for (int i = 0; i < elemSzam; i++){
tomb[i+2] = tomb[i] + tomb[i+1];
System.out.print (tomb[i] + " ");
}
}
}
Végeredmény (például):
Hány elemű Fibonacci-sorozatot óhajt (1 és 30 között)?
qwertz
Kérem, hogy csak pozitív számot adjon meg 1 és 30 között!
34
Kérem, hogy csak pozitív számot adjon meg 1 és 30 között!
10
0 1 1 2 3 5 8 13 21 34