Képernyőről beolvasni, tömbök, debug

Magas szintű programozási nyelvek 2 (INBPM0315-21) · 2. labor gyakorlat · Frissítve: 2026-09-16

Tematika

Kontextus

A múlt órán a programjaink egyetlen módon kaptak adatot kívülről: parancssori argumentumként, még a program elindítása előtt megadva. Ma megnézzük, hogyan tudunk adatot bekérni futás közben — miközben a program már fut, megvárja, amíg begépeltek valamit.

Utána ezt kombináljuk a tömbökkel: nem csak egy, hanem több értéket is be tudunk kérni és eltárolni. Végül, ahelyett hogy System.out.println-ekkel próbálnánk kitalálni, mi történik a programunkban, megtanuljuk, hogyan lehet egy futó Java programot lépésről lépésre megfigyelni IntelliJ-ben — ez lesz a mai óra legnagyobb, gyakorlat-központú része.

Hirdetés

Képernyőről beolvasni — Scanner

Scanner: A Scanner egy beépített Java osztály, amellyel a program a szabványos bemenetről (jellemzően a billentyűzetről) tud adatot beolvasni, amíg fut.

import java.util.Scanner;

public class GreetInput {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.print("Mi a neved? ");
        String name = scanner.nextLine();

        System.out.println("Szia, " + name + "!");
    }
}

Amit tisztázni kell:

Ez a múlt héthez képest: a múlt órán a Greet program a nevet parancssori argumentumként kapta (java Greet Anna), és a program elindulása előtt már rendelkezésre állt. Most a program fut, megáll, megvárja, amíg begépelünk valamit, és csak utána folytatja a futást.

Számok beolvasása

Scanner scanner = new Scanner(System.in);

System.out.print("Hány éves vagy? ");
int age = scanner.nextInt();
System.out.println("Kor: " + age);

System.out.print("Mennyi a tanulmányi átlagod? ");
double average = scanner.nextDouble();
System.out.println("Átlag: " + average);

Gyakori hiba (a "newline" csapda): ha nextInt() vagy nextDouble() után egy nextLine() következik, a nextLine() sokszor egy üres sort fog visszaadni. Ennek az az oka, hogy a nextInt() csak a számot olvassa be, a utána lévő sortörés-karaktert a bemenetben hagyja — és a következő nextLine() pont ezt az otthagyott sortörést olvassa be, nem az újabb begépelt szöveget. Megoldás: szám beolvasása után, ha utána nextLine()-t is hívunk, iktassunk be egy plusz scanner.nextLine(); hívást, ami "felemészti" az otthagyott sortörést.

Tömbök

Tegyük fel, hogy nem csak egy jegyet, hanem egy egész hallgatói csoport jegyeit be szeretnénk kérni és tárolni. Egyesével elnevezett változókkal (grade1, grade2, grade3, ...) ez kezelhetetlen — pont erre valók a tömbök.

Tömb (array): A tömb azonos típusú elemek rögzített méretű, sorszámozott (indexelt) gyűjteménye.

Deklaráció és inicializálás

int[] grades = new int[5];   // 5 elemű, egész számokat tároló tömb, kezdetben mind 0

int[] literalGrades = {5, 4, 5, 3, 4};   // közvetlenül megadott értékekkel létrehozott tömb

Indexelés

grades[0] = 5;          // az első elem beállítása
System.out.println(grades[0]);   // az első elem kiolvasása

int size = grades.length;   // a tömb mérete (nem metódus, hanem mező: nincs zárójel!)

Fontos: grades.length — nincsenek zárójelek, mert ez egy mező, nem egy metódushívás (szemben pl. a String length() metódusával, ahol van zárójel).

Bejárás

for (int i = 0; i < grades.length; i++) {
    System.out.println("grades[" + i + "] = " + grades[i]);
}

for (int grade : grades) {
    System.out.println(grade);
}
Hirdetés

Példa: jegyek beolvasása és átlaga

import java.util.Scanner;

public class Grades {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.print("Hány jegyet adsz meg? ");
        int count = scanner.nextInt();

        int[] grades = new int[count];

        for (int i = 0; i < grades.length; ++i) {
            System.out.print((i + 1) + ". jegy: ");
            grades[i] = scanner.nextInt();
        }

        int sum = 0;
        for (int grade : grades) {
            sum += grade;
        }

        double average = (double) sum / grades.length;
        System.out.println("Átlag: " + average);
    }
}

Ezt a Grades programot fogjuk a következő részben debugolni.

Debug IntelliJ-ben

Eddig, ha egy programunk rosszul viselkedett, System.out.println-eket szórtunk bele, hogy lássuk, mi történik. Ez működik, de lassú, és utólag ki kell törölni ezeket a sorokat. A debugger ennek a szisztematikus, beépített változata: meg tudjuk állítani a programot egy adott ponton, és élőben megnézhetjük, mi van a változókban.

Egy hiba beültetése

Rontsuk el szándékosan a Grades programot — cseréljük ki a ciklus feltételét egy hibás verzióra:

for (int i = 0; i <= grades.length; ++i) {   // hiba: <= a < helyett
    System.out.print((i + 1) + ". jegy: ");
    grades[i] = scanner.nextInt();
}

Ez ArrayIndexOutOfBoundsException-t fog dobni, mert a ciklus megpróbál a tömb méreténél eggyel nagyobb indexre is írni.

Breakpoint elhelyezése

Breakpoint (töréspont): Egy jelölés egy kódsoron, amely jelzi az IntelliJ-nek, hogy futás közben itt álljon meg a program, mielőtt az adott sor lefutna.

  1. Kattintsatok a sorszám melletti szürke sávra a grades[i] = scanner.nextInt(); sor mellett — megjelenik egy piros pötty.
  2. A main metódus melletti zöld ▶ ikon helyett most a bogár ikonra kattintsatok (vagy jobb klikk a fájlon → Debug 'Grades.main()').
  3. A program elindul, és megáll a breakpointnál, mielőtt az adott sor lefutna.

Lépegetés

Az IntelliJ ablak alján megjelenik a Debug panel, benne lépegető gombokkal:

Változók megfigyelése

A Debug panel Variables fülén élőben látjátok:

Lépegessetek végig a ciklus néhány iterációján a Step Over gombbal, és figyeljétek meg, ahogy i nő, és hogyan íródnak be az értékek a grades tömbbe — amikor i eléri a grades.length értékét, a következő lépésnél lássátok meg élőben, ahogy a hibás index miatt kivétel keletkezik.

Javítás

Cseréljétek vissza a feltételt i < grades.length-re, futtassátok újra (most már Run-nal, nem Debug-gal), és ellenőrizzétek, hogy a program helyesen fut.

Gyakorlat

  1. Írjátok meg a GreetInput programot, és próbáljátok ki a nextInt() + nextLine() csapdát szándékosan — figyeljétek meg, mi történik, majd javítsátok ki egy extra nextLine() hívással.
  2. Írjátok meg a Grades programot (helyesen), és futtassátok néhány bemenettel.
  3. Ültessetek bele szándékosan egy hibát (pl. rossz kezdőérték, vagy <= a < helyett), tegyetek rá breakpointot, és debuggerrel derítsétek ki, hol romlik el.
  4. Bővítsétek a Grades programot: írja ki a legnagyobb jegyet is a tömbből (ciklussal, Math.max vagy manuális összehasonlítással) — nem kell hozzá rendezés, csak egy futó "eddigi maximum" változó.

Puffer (~30 perc)

Kérdések, esetleges környezet-/telepítési problémák megoldása, illetve további gyakorlási idő azoknak, akik lassabban haladnak — különösen a debugger használatának begyakorlására érdemes időt hagyni, mert ez sokaknak új eszköz.

Házi feladat

Ezek a feladatok a 2. órán tanultak (Scanner, tömbök, IntelliJ debugger) önálló, otthoni elmélyítésére szolgálnak.

1. feladat (Könnyű) — Három szám átlaga

Írjatok egy ThreeNumbersAverage nevű programot, amely Scanner-rel egyesével bekér három egész számot a felhasználótól, majd kiírja az összegüket és az átlagukat.

2. feladat (Közepes) — Szavak visszafelé

Írjatok egy ReverseWords nevű programot, amely:

  1. bekéri Scanner-rel, hány szót fog megadni a felhasználó (N),
  2. beolvassa a szavakat egy String[N] tömbbe,
  3. kiírja a szavakat fordított sorrendben (az utolsóként megadott szó legyen az első a kiírásban).

Segítség: ehhez egy olyan for ciklus kell, amely a tömb végétől indulva, csökkenő indexekkel halad.

3. feladat (Közepes/Haladó) — Legkisebb és legnagyobb hőmérséklet

Írjatok egy Temperatures nevű programot, amely:

  1. bekéri Scanner-rel, hány hőmérsékletadatot fog megadni a felhasználó (N),
  2. beolvassa az értékeket egy double[N] tömbbe,
  3. kiírja a legkisebb és a legnagyobb beolvasott hőmérsékletet is.

4. feladat (Haladó) — Saját hibavadászat

Az alábbi program hibás — egy tömb elemeinek összegét próbálja kiszámolni, de valamit elrontottunk benne:

import java.util.Scanner;

public class BuggySum {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.print("Hány számot adsz meg? ");
        int count = scanner.nextInt();

        int[] numbers = new int[count];
        for (int i = 0; i <= count; i++) {
            System.out.print((i + 1) + ". szám: ");
            numbers[i] = scanner.nextInt();
        }

        int sum = 0;
        for (int i = 1; i < numbers.length; i++) {
            sum += numbers[i];
        }

        System.out.println("Összeg: " + sum);
    }
}

Másoljátok be a kódot IntelliJ-be, tegyetek rá legalább egy breakpointot, és debug módban lépegetve derítsétek ki, mi a két külön hiba a programban. Javítsátok ki mindkettőt, és ellenőrizzétek, hogy helyes összeget ad néhány teszteléssel.

Hirdetés

Hasznosnak találtad ezt a jegyzetet?

Ezek a jegyzetek minden hallgató számára ingyenesek. Ha időt spóroltál vele, fontold meg egy borravaló hagyását.

☕ Hívj meg egy kávéra