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.

 

www.informatika-programozas.hu - Ezt most meg kell tanulni!

 

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:

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):

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

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.

 

www.informatika-programozas.hu - Ezt most meg kell tanulni!

 

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.

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

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