Exceptions (try/catch)

recess

Mitglied
Hallo zusammen, ich habe hier eine Methode geschrieben, die Lottozahlen zwischen 1 und 49 einlesen soll.
Dabei möchte ich zumindest eine Exception machen, dass ein Fehler auftaucht wenn ein Buchstabe eingegeben wird statt einer Zahl und am liebsten noch wenn die Eingabe außerhalb von 1 und 49 ist.
Mein jetziger stand ist:

Java:
public void tippabgabe(){

		boolean getippt;
		int[] tipp = new int[6];
		try {
			for (int i=0; i<6; i++){
				System.out.print("Geben Sie nun die "+(i+1)+". Zahl ein!: ");
				do {
					getippt = false;
					tipp[i] = eingabe.nextInt();

					for (int j = 0; j < i; j++) {
						if (tipp[j] == tipp[i]){
							getippt = true;
							System.out.print("Diese Zahl wurde bereits getippt, wählen Sie bitte eine neue Zahl!:");
						}
					}
				} while (getippt);
			}
		}catch (InputMismatchException e){	
			System.out.print("Die Eingabe ist ungültig. Bitte geben Sie nun eine Zahl in:");
			eingabe = new Scanner(System.in); 	
		}// end of catch

		java.util.Arrays.sort( tipp );
		objektTippSpeicher.speichere(new Tipp(tipp));
	}

Allerdings kommt dann bei mir wenn ich dann einen Buchstaben eingebe, die Fehlermeldung (Du hast keine zahl eingegeben(oder so ähnlich)" und danach kommt direkt bitte treffen Sie eine Auswahl , springt also raus.
Ich steh auf dem Schlauch, ich muss warsch nur die Klammern anders setzen, aber bin der meinung alles ausprobiert zu haben,.
Kann mir vll jemand nen Tipp geben?
 
Zuletzt bearbeitet:
H

hüteüberhüte

Gast
Ich hätts so gemacht:
Java:
    private static int[] lottozahlenEinlesen() throws IOException {
        int[] result = new int[6];
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        for (int i = 0; i < result.length;) {
            try {
                System.out.print(i + 1 + ". Zahl eingeben: ");
                int input = Integer.parseInt(reader.readLine());
                if (input < 1 || input > 49) {
                    throw new NumberFormatException();
                }
                for (int j = 0; j < i; j++) {
                    if (result[j] == input) {
                        throw new NumberFormatException();
                    }
                }
                result[i++] = input;
            } catch (NumberFormatException nfe) {
                System.out.println("Bitte Zahl zwischen 1 und 49 eingeben.");
            }
        }
        Arrays.sort(result);
        return result;
    }

    public static void main(String[] args) throws IOException {
        System.out.println(Arrays.toString(lottozahlenEinlesen()));
    }

Wenn keine Zahl eingegeben wird, kleiner 1 oder größer 49, oder bereits vorhanden ist, wird eine NFE geworfen/ausgelöst und behandelt.

Hth!
 

KuhTee

Aktives Mitglied
Hm... hüteüberhüte... irgendjemand sollte die IOException schon behandeln...
Statt dem Array würde sich ein Set anbieten, dann sparst du dir das drüber Iterieren zum Prüfen.

Und ehrlich gesagt würde ich das Verwenden einer Exception in diesem Fall eher als schlechten (und vor allem unnötig umständlichen) Code ansehen. Ist mir schon klar, dass soll zur Übung sein. Aber eher unschönen Code üben? Ich weiss nicht... Missbrauchen von Exceptions sollte man eher nicht üben, finde ich.
 

TKausL

Top Contributor
Hm... hüteüberhüte... irgendjemand sollte die IOException schon behandeln...
Statt dem Array würde sich ein Set anbieten, dann sparst du dir das drüber Iterieren zum Prüfen.

Und ehrlich gesagt würde ich das Verwenden einer Exception in diesem Fall eher als schlechten (und vor allem unnötig umständlichen) Code ansehen. Ist mir schon klar, dass soll zur Übung sein. Aber eher unschönen Code üben? Ich weiss nicht... Missbrauchen von Exceptions sollte man eher nicht üben, finde ich.

1. Das Set tut intern genau das selbe, drüberiterieren...
2. Warum sollte diese Exception "Missbraucht" worden sein? Sie tut genau das was sie soll: Einen Fehler melden. Nur weil die Exception in der selben Methode behandelt wird ist sie noch lange nicht "Missbraucht".
 
H

hüteüberhüte

Gast
Hm... hüteüberhüte... irgendjemand sollte die IOException schon behandeln...

Unsinn, wenn eine IOE auftritt, soll das Programm beendet werden. So einfach ist das.

Statt dem Array würde sich ein Set anbieten, dann sparst du dir das drüber Iterieren zum Prüfen.

Ich denke, mit einem Set & einer Hashfunktion kann jemand, der gerade bei einem int[] ist, noch nicht so viel anfangen. Wenn schon, dann wäre ein zusätzliches boolean[] jedenfalls schneller.

Und ehrlich gesagt würde ich das Verwenden einer Exception in diesem Fall eher als schlechten (und vor allem unnötig umständlichen) Code ansehen. Ist mir schon klar, dass soll zur Übung sein. Aber eher unschönen Code üben? Ich weiss nicht... Missbrauchen von Exceptions sollte man eher nicht üben, finde ich.

Du würdest also nie
Code:
throw new SomeException
schreiben, oder wie darf ich das verstehen? Meine Methode ist einwandfrei, du darfst Deinen Neid gerne behalten.
 

tfa

Top Contributor
Ich denke, hier ist der Missbrauch der NumberFormatException zum Kontrollfluss gemeint (Zeile 9 und 13). Und das ist ziemlich daneben. Zumal im catch-Block einfach nur eine Meldung ausgegeben wird. Das kann man auch in eine Methode auslagern.
 

KuhTee

Aktives Mitglied
1. Das Set tut intern genau das selbe, drüberiterieren...
Und warum dann das nicht nutzen statt selbst zu schreiben? :)

2. Warum sollte diese Exception "Missbraucht" worden sein? Sie tut genau das was sie soll: Einen Fehler melden. Nur weil die Exception in der selben Methode behandelt wird ist sie noch lange nicht "Missbraucht".
Weil die Exception in dem Fall zur Programmflusssteuerung verwendet wird, was unnötig ist (siehe unten). Ein Grund, weshalb Java als so geschwätzig gilt, ist der exzessive und oftmals unnötige Einsatz von Exceptions. Dass die Art und Weise der Implementierung und Verwendung von Exceptions in Java nicht gerade optimal ist, sehen ja auch erfahrene Javaentwickler so. Und ich finde einfach, dass man Neulingen das durchaus frühzeitig so erklären sollte. Hab schon genug Kollegen, wo man vor try-catch den wichtigen Code nicht mehr sieht.

Unsinn, wenn eine IOE auftritt, soll das Programm beendet werden. So einfach ist das.
Ok, sagen wir: Ansichtssache. Sowie: war nur ein Vorschlag.

Du würdest also nie
Code:
throw new SomeException
schreiben, oder wie darf ich das verstehen? Meine Methode ist einwandfrei, du darfst Deinen Neid gerne behalten.
Doch, natürlich würde ich das. Aber bei einer "Ausnahme" eben. Nur in dem Code oben würde ich eben keine Exception verwenden, weil mMn "Missbrauch" von Exceptions. Eher so (ohne Garantie auf Kompilerbarkeit) :
Java:
private static int[] lottozahlenEinlesen() throws IOException {    
    Set<Integer> result = new HashSet<>();        
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    while (result.size() < 6) {
        System.out.print((result.size() + 1) + ". Zahl eingeben: ");
        int input = Integer.parseInt(reader.readLine());
        if (input < 1 || input > 49 || result.contains(input)) {
            System.out.println("Bitte Zahl zwischen 1 und 49 eingeben.");
        }
        else {
            result.add(input);
        }
    }
    return Arrays.sort(result.toArray());
}
 
public static void main(String[] args) throws IOException {
    System.out.println(Arrays.toString(lottozahlenEinlesen()));
}
Ist mMn lesbarer, vor allem da deine Exception ja nichts weiter darstellt als ein "if (...) goto ...".

@tfa: Exakt. Leider wird das häufig sogar genau so gelehrt.
 

KuhTee

Aktives Mitglied
Wenn man wie du ein HashSet benutzt, itiert es natürlich nicht über alle Einträge. Das ist ja gerade der Witz eines Sets.
Es geht dabei ja nur darum, eine Zahl nicht mehrfach einzulesen. Und dafür eben das (Hash)Set. Drüber"iterieren" tut da in dem Fall nix, ja, aber es geht ja nur darum, sich das manuelle Iterieren zu sparen. Was es fürn Set ist, ist in dem Fall ja sowieso eher unwichtig.
 
H

hüteüberhüte

Gast
Eher so (ohne Garantie auf Kompilerbarkeit) :

Das kompiliert nicht, weil du eine mögliche NFE weder behandelst noch weitergibst. Und sobald du dich darum kümmern würdest, wäre dein Code mindesten genauso verschachtelt wie meiner: Ergo, unübersichtlicher.
 
Zuletzt bearbeitet von einem Moderator:

KuhTee

Aktives Mitglied
Mea culpa, hast recht. Das kommt davon, wenn man in Qt denkt und dann Java schreibt :D
Es ging mir bei meiner Kritik aber um
Code:
throw new NumberFormatException();
, wo ich bei meiner Aussage bleibe: Missbrauch von Exceptions.
 

tfa

Top Contributor
In dieser Methode geht es nicht um Schnelligkeit. Osi layer 8 ist sowieso der langsamste Part. Einen Missbrauch kann ich nicht erkennen.

Du müsstest um Zeile 6-12 einen Try-catch-Block schreiben, damit dein Programm funktioniert.

Es bleibt dabei: ein eklatanter Missbrauch von Exceptions zu Kontrollflusszwecken! Wer über das Anfängerstadium hinaus ist, sollte sowas nicht mehr machen.

Das Gewurschtel in diesem Beispiel könnte man vermeiden, in dem man einfach mehr und kleinere Methoden macht: eine zum Einlesen einer (gültigen Zahl), eine zum Testen des Bereichs, zum Testen auf Doppelte etc. Nur so wird es übersichtlich.
 
H

hüteüberhüte

Gast
Das Gewurschtel in diesem Beispiel könnte man vermeiden, in dem man einfach mehr und kleinere Methoden macht: eine zum Einlesen einer (gültigen Zahl), eine zum Testen des Bereichs, zum Testen auf Doppelte etc. Nur so wird es übersichtlich.

Naja, dann mach das doch, anstatt hier andere zu kritisieren. Ich möchte gerne mal sehen, inwieweit das dann übersichtlicher wäre. :lol:
 

KuhTee

Aktives Mitglied
In dieser Methode geht es nicht um Schnelligkeit.
Schnelligkeit war nun wirklich das Letzte, was mir dabei in den Sinn kam.

Einen Missbrauch kann ich nicht erkennen.
Wurde doch schon genannt: du verwendest Exceptions zur Programmflusssteuerung, was in diesem Fall keinen Sinn macht und was man so Neulingen auch gar nicht erst beibringen sollte.

Du müsstest um Zeile 6-12 einen Try-catch-Block schreiben, damit dein Programm funktioniert.
Ja (also eigentlich nur um das parseInt()). Mach ich jetzt aber nicht, ok? :)
Bzw., in einem "echten" Programm würde ich natürlich eine parseInteger Methode verwenden, die keine (in vielen Fällen sowieso unnütze) Exception wirft. Das meinte ich weiter oben mit "in Qt gedacht", da liefert die entsprechende Methode bei einer Nicht-Zahl nämlich schlichtweg 0 (die Info über einen Fehler ist optional). Das geht jetzt aber schon langsam in Richtung einer Diskussion über Sinn und Unsinn von Exceptions, was wohl hier eh fehl am Platze ist. Ich wollte nur darauf hinweisen, dass das Werfen einer Exception in diesem Fall als eher schlechter Code zu verstehen ist und vermieden werden sollte, besonders in größeren Programmen.
 

KuhTee

Aktives Mitglied
Ich möchte gerne mal sehen, inwieweit das dann übersichtlicher wäre. :lol:
Hm, wieso sollte es nicht? Das Aufteilen einer Methode in mehrere kleinere, die exakt eine einzige Aufgabe haben (in etwa genau die, die tfa genannt hat) ist doch der absolut übliche Weg, um die Übersichtlichkeit in einem Programm zu verbessern. Mal abgesehen davon, dass man die Methoden mehrfach verwenden kann, was sich ja gerade beim Exception-freien Parsen eines String anbietet.
 
H

hüteüberhüte

Gast
Ja (also eigentlich nur um das parseInt()). Mach ich jetzt aber nicht, ok? :)

Ich hab mir mal erlaubt, deine Methode zu verbessern:
Java:
    private static int[] lottozahlenEinlesen() throws IOException {
        Set<Integer> result = new HashSet<Integer>();
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while (result.size() < 6) {
            System.out.print(result.size() + 1 + ". Zahl eingeben: ");
            try {
                int input = Integer.parseInt(reader.readLine());
                if (input < 1 || input > 49 || result.contains(input)) {
                    System.out.println("Bitte Zahl zwischen 1 und 49 eingeben.");
                } else {
                    result.add(input);
                }
            } catch (NumberFormatException nfe) {
                System.out.println("Bitte Zahl zwischen 1 und 49 eingeben.");
            }
        }
        int[] a = new int[result.size()];
        Iterator<Integer> iter = result.iterator();
        int i = 0;
        while (iter.hasNext()) {
            a[i++] = iter.next();
        }
        Arrays.sort(a);
        return a;
    }

Sieht wahnsinnig übersichtlich aus in Vergleich zu meiner Methode... [/IRONIE] Das Thema ist für mich erledigt. Schönen Abend noch
 

recess

Mitglied
Hey ich wollte jetzt eig kein so großes fass aufmachen :lol:

Es ging mir darum, wie ich die Exception handle. DIe bisherigen Lösungen von euch sehen alle vor, dass ich unten drunter eine Main.Methode habe. Die habe ich aber schon:/
Kann man das nich einfach (es muss nich sauber programmiert sein), innerhalb der Methode , nur mit Exception wie IOException und try catch irg wie abfangen ? Muss man die unbedingt werfen? WEnn es eine möglichkeit gibt das ohne throw zu machen, wie geht diese?




Ich hab mir mal erlaubt, deine Methode zu verbessern:
Java:
    private static int[] lottozahlenEinlesen() throws IOException {
        Set<Integer> result = new HashSet<Integer>();
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while (result.size() < 6) {
            System.out.print(result.size() + 1 + ". Zahl eingeben: ");
            try {
                int input = Integer.parseInt(reader.readLine());
                if (input < 1 || input > 49 || result.contains(input)) {
                    System.out.println("Bitte Zahl zwischen 1 und 49 eingeben.");
                } else {
                    result.add(input);
                }
            } catch (NumberFormatException nfe) {
                System.out.println("Bitte Zahl zwischen 1 und 49 eingeben.");
            }
        }
        int[] a = new int[result.size()];
        Iterator<Integer> iter = result.iterator();
        int i = 0;
        while (iter.hasNext()) {
            a[i++] = iter.next();
        }
        Arrays.sort(a);
        return a;
    }

Sieht wahnsinnig übersichtlich aus in Vergleich zu meiner Methode... [/IRONIE] Das Thema ist für mich erledigt. Schönen Abend noch
 
S

Spacerat

Gast
Hey ich wollte jetzt eig kein so großes fass aufmachen :lol:
Dann bleib' halt bei den halben Litern. :lol:
Java:
import java.util.Arrays;
import java.util.Scanner;

public class Lotto {
	private static final int[] BALLS;

	static {
		BALLS = new int[49];
		for(int n = 0; n < BALLS.length; n++) {
			BALLS[n] = n + 1;
		}
	}

	public static void main(String[] args) {
		int[] balls = BALLS.clone();
		int[] tipp = new int[6];
		Scanner sc = new Scanner(System.in);
		int zahl = 0;
		for(int n = 0; n < 6; n++) {
			try {
				zahl = sc.nextInt();
			} catch (InputMismatchException e) {
				sc.next();
				System.out.println("ZAHLEN! Keine Buchstaben! Nochmal");
				n--;
				continue;
			}
			if(!pruefeZahl(zahl, balls)) {
				System.out.println("Zahl ungueltig oder schon getippt. Nochmal");
				n--;
			} else {
				tipp[n] = zahl;
			}
		}
		sc.close();
		System.err.print("Ihr Tipp: " + Arrays.toString(tipp));
	}

	private static boolean pruefeZahl(int zahl, int[] balls) {
		Arrays.sort(balls);
		int index = Arrays.binarySearch(balls, zahl);
		if(zahl < 0 || index < 0) {
			return false;
		}
		balls[index] = -1;
		return true;
	}
}
Ich denke mal, Methodenname und Rückgabewert bekommst du noch selber hin. ;)
 
Zuletzt bearbeitet von einem Moderator:

recess

Mitglied
Aber du hast doch jetzt auch alles wieder in die Main Methode gepackt?! Kann ich die dann einfach umbennnen und neuen Rückgabewert bilden?
 

recess

Mitglied
Hier ist meine komplette Klasse:

Vielleicht hilft das mich besser zu verstehen :)

Java:
package Lottozahlen;

import java.util.Scanner;

public class LottoMain {
	//Anlegen vom Scanner und von Objekten des Types verschiedener Klassen (für Methoden aufruf oder ähnliches)
	private static Scanner eingabe = new Scanner (System.in);
	ZiehungsSpeicher objektZiehungsSpeicher = new ZiehungsSpeicher();
	Lottotrommel objektLottotrommel = new Lottotrommel();
	TippsSpeicher objektTippSpeicher = new TippsSpeicher();
	Tipptrommel objektTipptrommel = new Tipptrommel();

	//Main-Methode. Ausgabe der einzelnen Menüpunkte auf die Console.
	//Außerdem wird mit Hilfe des Lottomain-Objektes die Methode auswahl() aufgerufen.
	public static void main(String[] args) {
		//Erstellen eines Objektes der Klasse Lottomain
		LottoMain objektLottoMain = new LottoMain ();

		System.out.println("Willkommen in Ihrem Lottoprogramm");
		System.out.println("--------------------");
		System.out.println("(1) Ich will n-Ziehungen automatisch (per Zufall) generieren lassen, dabei n selber vorgeben!");
		System.out.println("(2) Ich will 1000 Ziehungen generieren und abspeichern lassen!");
		System.out.println("(3) Ich will alle Ziehungen (Lottozahlen) ausgeben!");
		System.out.println("(4) Ich möchte einen Tipp abgeben!");
		System.out.println("(5) Ich will n-Tipps automatisch (per Zufall) generieren lassen, dabei n selber vorgeben!");
		System.out.println("(6) Ich möchte alle Tipps ausgeben!");
		System.out.println("(7) Ich will das Programm beenden!");
		System.out.println();
		//Aufruf der Methode auswahl()
		objektLottoMain.auswahl();
	}	


	//Methode, die das Menü wiederspiegelt. Der Benutzer wird aufgefordert 
	//sich zu entscheiden, welchen Menü-Punkt er auswählen möchte.
	//Die unterschiedlichen Methoden werden mit Hilfe von switch-case realisiert.
	//Wenn der Benutzer den Menüpunkt 7 wählt, wird der "else"-Teil aufgerufen
	//und die do Schleife abgebrochen.
	
	public void auswahl (){
		int auswahl;
		do{
			System.out.print("Treffen Sie nun eine Auswahl: ");
			auswahl= eingabe.nextInt();

			if (auswahl !=7){
				switch (auswahl){
				case 1: nZiehungen();
				break;
				case 2: tausendZiehung();
				break;	
				case 3: System.out.println(objektZiehungsSpeicher);
				break;
				case 4: tippabgabe();
				break;
				case 5: nTipps();
				break;
				case 6:  System.out.println(objektTippSpeicher);
				break;
				default: System.out.println("Falsche Eingabe");
				}
				System.out.println();
			}
			else{		 
				System.out.println();
				System.out.println("~~~~~~~~~~~~~~~~~");
				System.out.println("Auf Wiedersehen, ich hoffe Sie sind jetzt reich!");
			}
		}while (auswahl !=7);
	}


	//Methode zur automatischen Generierung von 1000 Lottozahlen.
	//Die Lottozahlen werden durch den Teil "objektLottotrommel.trommeldrehen()"
	//gezogen und durch den ersten Teil "objektZiehungsSpeicher.speichere()" über 
	//die Methode speichere() abgespeichert. trommeldrehen() ist eine Methode vom Typ Ziehung
	// und die Methode speichere() verlangt den Typ Ziehung.
	private void tausendZiehung (){
		for (int i = 0; i <1000 ; i++) {
			objektZiehungsSpeicher.speichere(objektLottotrommel.trommeldrehen());
		}
	}


	//Methode zur automatischen Generierung von n Lottozahlen. "n" soll durch den 
	//Benutzer selbst entschieden werden.
	//Die Lottozahlen werden durch den Teil "objektLottotrommel.trommeldrehen()"
	//gezogen und durch den ersten Teil "objektZiehungsSpeicher.speichere()" über 
	//die Methode speichere() abgespeichert. trommeldrehen() ist eine Methode vom Typ Ziehung
	// und die Methode speichere() verlangt den Typ Ziehung.
	private void nZiehungen(){
		System.out.print("Wie viele Lottozahlen wollen Sie generieren? ");
		int durchläufe=eingabe.nextInt();
		for (int i = 0; i <durchläufe ; i++) {
			objektZiehungsSpeicher.speichere(objektLottotrommel.trommeldrehen());
		}
	}

	//Methode zur automatischen Generierung von n Tipps. "n" soll durch den 
	//Benutzer selbst entschieden werden.
	//Die Tipps werden durch den Teil "objektTipptrommel.tipptrommeldrehen()"
	//gezogen und durch den ersten Teil "objektTippSpeicher.speichere()" über 
	//die Methode speichere() abgespeichert. tipptrommeldrehen() ist eine Methode vom Typ Tipp
	//und die Methode speichere() verlangt den Typ Tipp.
	
	private void nTipps(){
		System.out.print("Wie viele Tipps wollen Sie generieren? ");
		int durchläufe=eingabe.nextInt();
		for (int i = 0; i <durchläufe ; i++) {
			objektTippSpeicher.speichere(objektTipptrommel.tipptrommeldrehen());
		}
	}


	public void tippabgabe(){

		boolean getippt;
		int[] tipp = new int[6];

		for (int i=0; i<6; i++){
			System.out.print("Geben Sie nun die "+(i+1)+". Zahl ein!: ");
			do {
				getippt = false;
				tipp[i] = eingabe.nextInt();
				if (tipp[i] < 1 || tipp[i] > 49) {
					getippt =true ;
					System.out.print("Die Zahl befindet sich außerhalb von 1 und 49! Geben Sie eine neue Zahl ein: ");
				}

				for (int j = 0; j < i; j++) {
					if (tipp[j] == tipp[i]){
						getippt = true;
						System.out.print("Diese Zahl wurde bereits getippt, wählen Sie bitte eine neue Zahl!:");
					}
				}
			}while (getippt);

		}
		java.util.Arrays.sort( tipp );
		objektTippSpeicher.speichere(new Tipp(tipp));
	}

}
 
H

hüteüberhüte

Gast
Zuguterletzt:
Java:
    private static int[] lottozahlenEinlesen() throws IOException {
        int[] result = new int[6];
        boolean[] contai = new boolean[50];
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        for (int i = 0; i < result.length;) {
            System.out.print(i + 1 + ". Zahl eingeben: ");
            try {
                int input = Integer.parseInt(reader.readLine());
                if (input < 1 || input > 49 || contai[input]) {
                    System.out.println("Bitte Zahl zwischen 1 und 49 eingeben.");
                } else {
                    contai[input] = true;
                    result[i++] = input;
                }
            } catch (NumberFormatException nfe) {
                System.out.println("Bitte Zahl zwischen 1 und 49 eingeben.");
            }
        }
        Arrays.sort(result);
        return result;
    }

Finde ich nur nicht so schön. Die NFE steuert eben doch den Programmfluss und ist ohne Scanner auch nicht vermeidbar.

@Spacerat: Scanner schließen? :autsch:
 
S

Spacerat

Gast
@Spacerat: Scanner schließen? :autsch:
Du sprichst mir aus der Seele, aber ich mag halt keine Warnings.
@TO: Methodenname und Rückgabewert ändern ist doch 'n Klacks.
Java:
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.Scanner;

public class Lotto {
	private static final int[] BALLS;

	static {
		BALLS = new int[49];
		for(int n = 0; n < BALLS.length; n++) {
			BALLS[n] = n + 1;
		}
	}

	public static int[] lottoTipp() {
		int[] balls = BALLS.clone();
		int[] tipp = new int[6];
		Scanner sc = new Scanner(System.in);
		int zahl = 0;
		for(int n = 0; n < 6; n++) {
			try {
				zahl = sc.nextInt();
			} catch (InputMismatchException e) {
				sc.next();
				System.out.println("ZAHLEN! Keine Buchstaben! Nochmal");
				n--;
				continue;
			}
			if(!pruefeZahl(zahl, balls)) {
				System.out.println("Zahl ungueltig oder schon getippt. Nochmal");
				n--;
			} else {
				tipp[n] = zahl;
			}
		}
		sc.close();
		return tipp;
	}

	private static boolean pruefeZahl(int zahl, int[] balls) {
		Arrays.sort(balls);
		int index = Arrays.binarySearch(balls, zahl);
		if(zahl < 0 || index < 0) {
			return false;
		}
		balls[index] = -1;
		return true;
	}
}
 

recess

Mitglied
Super, es funktioniert vielen Dank :)

Allerdings Blicke ich durch die obere und untere Methoden nicht durch.
ALso

Java:
private static final int[] BALLS;

	static {
		BALLS = new int[49];
		for(int n = 0; n < BALLS.length; n++) {
			BALLS[n] = n + 1;
		}
	}

Java:
private static boolean pruefeZahl(int zahl, int[] balls) {
		Arrays.sort(balls);
		int index = Arrays.binarySearch(balls, zahl);
		if(zahl < 0 || index < 0) {
			return false;
		}
		balls[index] = -1;
		return true;
	}
#
Vielleicht kannst du mir kurz erklären was die Methoden machen genau? Was macht die Methode binary Search??

Wieso einfach nur "static{...}", Ist das eine Methode oder wie?
 
S

Spacerat

Gast
Das static ist ein Klasseninitializer (eine Methode, ja). Dieser wird einmalig beim initialisieren der Klasse aufgerufen. In diesem Initializer definiere ich einen Satz Lottokugeln (BTW.: Ein Array eignet sich für soetwas normalerweise weniger, diese Idee also gleich vergessen ;)), der Klassenweit verfügbar ist, also in jeder Instanz dieser Klasse der selbe (Bemerkung: Arrayinhalte könnten von jeder Instanz beliebig verändert werden).

Der erste Schritt beim Lottotipp ist, den Klassenweiten Kugel-Satz zu kopieren, damit er verändert werden kann ("BALLS.clone()"). Schon getippte Zahlen werden mit einem negativen Wert (-1) invalidiert und so von der Binärsuche nicht mehr erfasst (besser, man hätte "zahl < 1" ausgewertet und die getippte Zahl mit 0 invalidiert, aber das ist nur ein gewohnheitsbedingter Schönheitsfehler).
Die Binärsuche prüft, ob die getippte Zahl noch in dem aktuellen Satz Kugeln vorhanden ist. Das geht aber nur, wenn bereits getippte Zahlen in diesem Satz einen invaliden Wert bekommen.
 
Zuletzt bearbeitet von einem Moderator:

KuhTee

Aktives Mitglied
Sieht wahnsinnig übersichtlich aus in Vergleich zu meiner Methode... [/IRONIE] Das Thema ist für mich erledigt. Schönen Abend noch
Es sieht so wahnsinnig übersichtlich aus, weil der Code wahnsinnig schlecht ist ;)
Naja, Scherz. Aber wieder eben unnötig umständlich (schon wieder Iterieren, warum bist du so geil auf Iterieren?) und die Ratschläge von tfa (sinnvolles Aufteilen auf Methoden) hast du auch nicht berücksichtigt.

[EDIT]
Wie wärs denn beispielsweise so? Man kann natürlich das Prüfen der Zahl auch noch in eine Methode auslagern:
Java:
private static int parseInt(String s)
{
	try {
		return Integer.parseInt(s);
	}
	catch (NumberFormatException e) {} //In dem Fall ist die Exception eher nutzlos -> 0
	return 0;
}

private static int[] lottozahlenEinlesen() throws IOException {    
    Set<Integer> result = new HashSet<>();        
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    while (result.size() < 6) {
        System.out.print((result.size() + 1) + ". Zahl eingeben: ");
        int input = parseInt(reader.readLine());		
        if (input < 1 || input > 49) {
            System.out.println("Bitte Zahl zwischen 1 und 49 eingeben.");
        } else if (result.contains(input)) {
            System.out.println("Zahl schon verwendet.");
        } else {
            result.add(input);
        }
    }
    return Arrays.sort(result.toArray());
}
 
public static void main(String[] args) throws IOException {
    System.out.println(Arrays.toString(lottozahlenEinlesen()));
}
Keine wilden Programmsprünge, Code ist von oben nach unten durchgehbar und verständlich. Klar kann man noch weitere Methoden nutzen zB eine eigene Methode die sich nur ums Einlesen kümmert und eine nur fürs Validieren, aber dann wirds wirklich langsam "Kanonen auf Spatzen". Und schau mal: obwohl der Code genauere Fehlermeldungen zeigt als deiner, ist er nicht länger. Cool, wa? :)

[/EDIT]

Allerdings Blicke ich durch die obere und untere Methoden nicht durch.
Mit dem oberen Codeblock wirds "BALLS" mit 1 bis 49 automatisch initialisiert, der untere Codeblock "löscht" eine Kugel aus BALLS. Also unglaublich umständliches Vorgehen für ein triviales Problem, aber scheinbar scheinen beide auf sowas zu stehen...
 
Zuletzt bearbeitet:

recess

Mitglied
Sorry , aber ich verstehe immernoch bahnhof.
Die Methode lottoTipp ist klar, Das ist kein Problem.
Aber vielleicht kannst du nochmal auf 2 Fragen eingehen:

1.) Was GENAU wird in static gemacht, wieso wählst du diese Form einfach nur static zu schreiben?!?!
Gibts da vielliecht Literatur zu, ich habe das noch nie gesehn und finde auch nichts.

2.) WIeso is das private static final int[] BALLS;
privat, statisch und final???

3.)
Java:
private static boolean pruefeZahl(int zahl, int[] balls) {
        Arrays.sort(balls);
        int index = Arrays.binarySearch(balls, zahl);
        if(zahl < 0 || index < 0) {
            return false;
        }
        balls[index] = -1;
        return true;
    }
Also wieso jetzt true und false returnt wird ist klar.
Aber wieso sind in der Methode int zahl und int [] balls als Paramter angegeben??
Wieso werden die Arrays vorher sortiert.
Was ist der Sinn von Binary Search und wieso

if(zahl < 0 || index < 0) ???

Sorry aber vielleicht haste ja kurz Zeit mir zu erklren was du damit meintest
 

recess

Mitglied
Zitat: hüteüberhüte

Beitrag anzeigen



Sieht wahnsinnig übersichtlich aus in Vergleich zu meiner Methode... [/IRONIE] Das Thema ist für mich erledigt. Schönen Abend noch


Es sieht so wahnsinnig übersichtlich aus, weil der Code wahnsinnig schlecht ist
Naja, Scherz. Aber wieder eben unnötig umständlich (schon wieder Iterieren, warum bist du so geil auf Iterieren?) und die Ratschläge von tfa (sinnvolles Aufteilen auf Methoden) hast du auch nicht berücksichtigt.

Edit:

Wie wärs denn beispielsweise so? Man kann natürlich das Prüfen der Zahl auch noch in eine Methode auslagern:
Java Code: Quelltext in neuem Fenster öffnen

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29



private static int parseInt(String s)
{
try {
return Integer.parseInt(s);
}
catch (NumberFormatException e) {} //In dem Fall ist die Exception eher nutzlos -> 0
return 0;
}

private static int[] lottozahlenEinlesen() throws IOException {
Set<Integer> result = new HashSet<>();
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (result.size() < 6) {
System.out.print((result.size() + 1) + ". Zahl eingeben: ");
int input = parseInt(reader.readLine());
if (input < 1 || input > 49) {
System.out.println("Bitte Zahl zwischen 1 und 49 eingeben.");
} else if (result.contains(input)) {
System.out.println("Zahl schon verwendet.");
} else {
result.add(input);
}
}
return Arrays.sort(result.toArray());
}

public static void main(String[] args) throws IOException {
System.out.println(Arrays.toString(lottozahlenEinlesen()));
}

Keine wilden Programmsprünge, Code ist von oben nach unten durchgehbar und verständlich. Klar kann man noch weitere Methoden nutzen zB eine eigene Methode die sich nur ums Einlesen kümmert und eine nur fürs Validieren, aber dann wirds wirklich langsam "Kanonen auf Spatzen". Und schau mal: obwohl der Code genauere Fehlermeldungen zeigt als deiner, ist er nicht länger. Cool, wa?

Der letzte Teil schmeckt mir irg wie nicht :D
WIeso muss die Main throw IOE.....???

In meiner Main steht so viel zeug drin, wie und wo und warum soll ich

System.out.println(Arrays.toString(lottozahlenEinlesen()));

noch mit einbinden?


Außerdem find ich deinen Vorschlag mit hashset und Set noch verwirrender, weil ich davon noch nie etwas gehört habe :lol: ABer der Code sieht ansonstne einfacher aus das stimmt :toll:
 
Zuletzt bearbeitet:

KuhTee

Aktives Mitglied
Sorry , aber ich verstehe immernoch bahnhof.
Das ist nicht schlimm bei diesem Code ;)
Wenn ich jetzt gehässig wäre, würde ich sagen: vergiss diesen Code und machs bloß nicht so. Bei einer Firma mit Codereview würde dieser Code wegen unnötiger Umständlichkeit durchfallen.

WIeso muss die Main throw IOE.....???
Weil hüteüberhüte der Meinung ist, dass die Anwendung bei einer IOException beendet werden sollte.

In meiner Main steht so viel zeug drin, wie und wo und warum soll ich

System.out.println(Arrays.toString(lottozahlenEinlesen()));

noch mit einbinden?
Das ist ja nur zur Ausgabe, um die endgültigen Zahlen zu sehen. Ersetz es durch Code, den du brauchst.

Außerdem find ich deinen Vorschlag mit hashset und Set noch verwirrender, weil ich davon noch nie etwas gehört habe :lol:
Ein Set ist schlichtweg eine Collection, welche jeden Wert nur ein einziges Mal aufnehmen kann. Bietet sich also für sowas wie Lottozahlen an.

ABer der Code sieht ansonstne einfacher aus das stimmt :toll:
Das ist die jahrelange Erfahrung mit Lotto :toll:
 
Zuletzt bearbeitet:
H

hüteüberhüte

Gast
@KuhTee: Meine erste Lösung hatte 23 Zeilen. Deine umfasst schon 25 Zeilen. Was soll daran also kürzer sein?

Für mich ist immer noch die Erste am Besten geeignet. Wenn du das anders siehst, ist dies deine Meinung, die ich respektiere, und nicht weiter darauf eingehen möchte.

Hier ist auch nochmal eine andere Variante:
Java:
    private static int[] lottozahlenEinlesen() throws IOException {
        int[] result = new int[6];
        boolean[] contai = new boolean[50];
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        for (int i = 0; i < result.length;) {
            System.out.print(i + 1 + ". Zahl eingeben: ");
            int input = pruefeLine(reader.readLine(), contai);
            if (input == -1) {
                System.out.println("Bitte Zahl zwischen 1 und 49 eingeben.");
            } else {
                result[i++] = input;
            }
        }
        Arrays.sort(result);
        return result;
    }

    private static int pruefeLine(String s, boolean[] a) {
        int result;
        try {
            result = Integer.parseInt(s);
        } catch (NumberFormatException numberFormatException) {
            return -1;
        }
        if (result < 1 || result > 49 || a[result]) {
            return -1;
        }
        a[result] = true;
        return result;
    }

@recess: Nimm irgendeine der hier vorgeschlagenen Lösungen und (btw) drücke nebenbei noch auf Danke. :D
 

recess

Mitglied
ok super, aber vielleicht möchtest du mir auch noch auf meine Fragen antworten? Also bisher funktionieren ehrlich gesagt nur deine beiden vorschläge hüte :p

Will damit aber KuhTee nicht schlecht machen, es klappt nur irg wie bei mir nicht..

@hütte: Vielleicht möchtest du mir noch auf meine fragen antworten, damit ich falls ich deinen ersten Vorschlag nehme auch weiß was ich da gemacht habe :p
 
S

Spacerat

Gast
@recess: Vllt. hilft zum Thema static ja dieses hier schon weiter.

http://www.java-forum.org/stichwort-static/1353-bedeutet-static.html
Galileo Computing :: Java ist auch eine Insel – 5.6 Klassen- und Objektinitialisierung *

Das [c]if(zahl < 0 || index < 0)[/c] sollte eigentlich [c]if(zahl < 1 || index < 0)[/c] heissen.
"Arrays.binarySearch()" sucht in einem Array einen übergebenen Wert und gibt entweder dessen Index (wenn der Wert gefunden wurde) oder negative Werte (wenn der Wert nicht gefunden wurde) zurück. Das Array muss für eine Binärsuche zuvor sortiert werden.
Im vorliegenden Fall kann der höchste Wert, der gefunden werden kann nur 49 und der kleinste nur 1 sein, so wird das anfangs durch den klassenweiten Kugelsatz festgelegt. Das Array, welches aber an "pruefeZahl()" übergeben wird, ist jedoch nicht der klassenweite Kugelsatz, sondern die für den aktuellen Tipp verwendete Kopie davon. Aus dieser Kopie dürfen getippte Kugeln entnommen werden, das geschieht mit [c]balls[index] = -1[/c]. Da "-1" unterhalb des gültigen Zahlenbereichs 1 - 49 liegt, können diese durch "Arrays.binarySearch()" nicht mehr gefunden werden.

privat static final ist der Kugelsatz, weil er so in jeder Instanz der Klasse verfügbar, aber nicht nach aussen (in anderen Klassen) sichtbar ist.

[EDIT]...und für jene, die es evtl. doch mal vernünftig mit Sets probieren wollen, oder jenen den Arrays.binarySearch nicht liegt:
Java:
import java.util.Collections;
import java.util.InputMismatchException;
import java.util.Scanner;
import java.util.SortedSet;
import java.util.TreeSet;

public class Lotto {
	private static final SortedSet<Integer> BALL_SET;

	static {
		SortedSet<Integer> ballSet = new TreeSet<>();
		for(int n = 0; n < 49; n++) {
			ballSet.add(n + 1);
		}
		BALL_SET = Collections.unmodifiableSortedSet(ballSet);
	}

	public int[] tipp() {
		SortedSet<Integer> balls = new TreeSet<>(BALL_SET);
		int[] tipp = new int[6];
		Scanner sc = new Scanner(System.in);
		int zahl = 0;
		for(int n = 0; n < 6; n++) {
			try {
				zahl = sc.nextInt();
			} catch (InputMismatchException e) {
				sc.next();
				System.out.println("ZAHLEN! Keine Buchstaben! Nochmal");
				n--;
				continue;
			}
			if(!pruefeZahl(zahl, balls)) {
				System.out.println("Zahl ungueltig oder schon getippt. Nochmal");
				n--;
			} else {
				tipp[n] = zahl;
			}
		}
		sc.close(); // Also dieses close hier ist echt eklig!
		return tipp;
	}

	private static boolean pruefeZahl(int zahl, SortedSet<Integer> balls) {
		if(balls.contains(zahl)) {
			balls.remove(zahl);
			return true;
		}
		return false;
	}
}
[/EDIT]
 
Zuletzt bearbeitet von einem Moderator:

KuhTee

Aktives Mitglied
Allerdings meckert der Compiler bei

" return Arrays.sort(result.toArray());"
Stimmt. Sort funktioniert ja so auch nicht :) So etwa sollte es gehen:
Java:
Integer[] bla = result.toArray();
Arrays.sort(bla);
usw...

...und für jene, die es evtl. doch mal vernünftig mit Sets probieren wollen, oder jenen den Arrays.binarySearch nicht liegt:
Wofür ich das Set verwenden würde, hast du noch nicht so ganz verstanden, oder? :) Deine ganze "BALLS" Geschichte ist unnütz. Pack die "tipps" doch einfach ins Set. So schwer ist das doch nicht. Egal...

Aber wenn wir schon dabei sind... Hierfür:
Java:
n--;
continue;
sollte dich irgendjemand ganz dolle schlagen.
 

recess

Mitglied
Java:
private  int [] lottozahlenEinlesen() throws IOException {
        int[] tippabgabe = new int[6];
        boolean[] prüfen = new boolean[50];
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        for (int i = 0; i < tippabgabe.length;) {
            System.out.print(i + 1 + ". Zahl eingeben: ");
            int einlese = pruefeLine(reader.readLine(), prüfen);
            if (einlese == -1) {
                System.out.println("Bitte Zahl zwischen 1 und 49 eingeben.");
            } else {
                tippabgabe[i++] = einlese;
            }
        }
        Arrays.sort(tippabgabe);
        objektTippSpeicher.speichere(new Tipp(tippabgabe));
		return tippabgabe;
    }
 
    private static int pruefeLine(String s, boolean[] pruefen) {
        int tippabgabe;
        try {
            tippabgabe = Integer.parseInt(s);
        } catch (NumberFormatException numberFormatException) {
            return -1;
        }
        if (tippabgabe < 1 || tippabgabe > 49 || pruefen[tippabgabe]) {
            return -1;
        }
        pruefen[tippabgabe] = true;
        return tippabgabe;
    }[code=Java]



eine Frage noch hierzu, wo wird denn pruefen überprüft?? In der untern Methode wird pruefen ja auf true gesetzt, wofür??
Also es funktioniert, ich sehe aber nirgendwo das auf diese bedingung überprüft wird??!!
 
H

hüteüberhüte

Gast
pruefeLine prüft, ob sich der übergebene String in ein int umwandeln lässt Und zwischen 1 und 49 liegt Und nicht bereits in dem boolean-Array vorhanden ist. Ist dies der Fall, wird der entsprechende Eintrag des boolean[] auf true gesetzt und die Zahl (int) zurückgegeben. Andernfalls wird -1 zurückgegeben.

In lottozahlenEinlesen wird dann geprüft, ob die eingelesene Zeile valide ist (Wert zwischen 1 und 49) oder nicht (-1). Wenn ja, wird sie als nächstes Element tippabgabe hinzugefügt.

Eine IOException kann natürlich auftreten, wenn der Benutzer z.B. die Eingabe schließt. Deshalb muss diese auch behandelt werden. In diesem Fall wird sie einfach an die aufrufende Methode weitergegeben.

Welche Zeilen sind für dich noch unklar?

int-Array wird deklariert und initialisiert...
boolean-Array wird deklariert und initialisiert...
BufferedReader wird deklariert und initialisiert (dem Konstruktor wird eine neues InputStreamReader-Objekt mitgegeben usw.)...
for-Schleife mit Initialisierung, Überprüfung und (leerer) Inkrementierungs-Anweisung (sie läuft von 0 bis (einschließlich) 6)...
Ausgabe auf der Konsole (der Ausdruck innerhalb des Methodenaufrufs wird von links nach rechts ausgewertet: zuerst int-Addition, dann String-Konkatenation)...
Deklaration und Zuweisung des Ergebnis des Aufrufs von pruefeLine an input...
Fallunterscheidung (bedingte Anweisung), wie oben bereits erwähnt...
usw.

Der Rest müsste verständlich sein!

Hth!
 
S

Spacerat

Gast
Eine IOException kann natürlich auftreten, wenn der Benutzer z.B. die Eingabe schließt. Deshalb muss diese auch behandelt werden.
Schreib' ruhig "D**p", denn was anderes fällt mir für meinen "Fauxpas" auch nicht ein... obwohl, ist ja nicht mein Fehler, wenn Oracle oder Eclipse der Meinung ist, da müsste was geschlossen werden... dann bin ich halt der "D**p", der das auch noch macht. Das Schlimme daran... "System.in" wird tatsächlich auch noch geschlossen... Das kann von denen, die da plötzlich eine offen gelassene Ressource anprangern kaum so gewollt sein. Wie man's ohne Warnungen und Exceptions dennoch hinbekommt (anonymer InputStream delegiert alles bis auf "close()" an System.in), sprengt allerdings das Thema dieses Threads und ist Umstand hoch drei.
 
Zuletzt bearbeitet von einem Moderator:
G

Guest2

Gast
Moin,

sowohl der Reader als auch der Scanner werfen zwangsweise eine Exception, sofern die Eingabe ungültig ist. Imho ist es legitim sich dort mit einer weiteren Exception dran zu hängen, um die Eingabe auf ein gültiges Intervall einzugrenzen. Die Exceptions zu fangen und durch ein "Magic-Value" (-1, 0, 1337) zu ersetzen halte ich hingegen für ungünstig.

Auch finde ich es relativ unerheblich ob die Methode 23 oder 25 Zeilen lang ist. Lieber mehrere kurze knackige Methoden als eine lange, auch wenn es insgesamt mehr Zeilen sind. (In dem Beispiel unten sogar wesentlich mehr ;))

Spontan würde ich das etwa so implementieren:

lottery.BallValue:
Java:
package lottery;


public final class BallValue implements Comparable<BallValue> {

    private static final int LOWEST_VALUE  = 1;
    private static final int HIGHEST_VALUE = 49;


    private final int        value;


    public BallValue(final int value) {

        if (value < LOWEST_VALUE || value > HIGHEST_VALUE)
            throw new IllegalArgumentException();

        this.value = value;

    }


    public int getValue() {

        return value;

    }


    @Override
    public int compareTo(final BallValue o) {

        if (value < o.value)
            return -1;

        else if (value == o.value)
            return 0;

        else
            return 1;

    }


    @Override
    public String toString() {

        return String.valueOf(value);

    }


}

lottery.Lotto:
Java:
package lottery;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Set;
import java.util.TreeSet;


public final class Lotto {

    private static final int     NUMBER_OF_PICKS     = 6;

    private final BufferedReader readerForUserInput  = new BufferedReader(new InputStreamReader(System.in));
    private final Set<BallValue> pickedBallsFromUser = new TreeSet<>();


    public void printPickedBalls() {

        System.out.print("Folgende Zahlen wurden gewählt: " + pickedBallsFromUser);

    }


    public void letUserPickAllBallValues() {

        while (pickedBallsFromUser.size() < NUMBER_OF_PICKS)
            letUserPickOneSingeBallValue();

    }


    private void letUserPickOneSingeBallValue() {

        System.out.print((pickedBallsFromUser.size() + 1) + ". Zahl eingeben: ");

        try {

            final BallValue ballValue = readBallValueFromUser();

            if (pickedBallsFromUser.contains(ballValue))
                System.out.println("Zahl bereits gewählt!");

            else
                pickedBallsFromUser.add(ballValue);

        } catch (IllegalArgumentException | IOException e) {

            System.out.println("Eingegebene Zahl war ungültig!");

        }

    }


    private BallValue readBallValueFromUser() throws IOException {

        final String input = readerForUserInput.readLine();
        final int integer = Integer.parseInt(input);
        final BallValue ballValue = new BallValue(integer);

        return ballValue;

    }


    public static void main(final String[] args) {

        final Lotto lotto = new Lotto();

        lotto.letUserPickAllBallValues();
        lotto.printPickedBalls();

    }

}

Viele Grüße,
Fancy
 
H

hüteüberhüte

Gast
Die Exceptions zu fangen und durch ein "Magic-Value" (-1, 0, 1337) zu ersetzen halte ich hingegen für ungünstig.

Kennst du eig. die Methode indexOf (oder zahlreiche andere Methoden)?

Jetzt extra Klassen einzuführen, und damit den Code unnötig aufzublähen, halte ich hingegen für die schlechteste Lösung. 6, setzen, bitte... (Auch wenn viele andere aus welchen Gründen auch immer deine Beiträge sehr zu schätzen wissen...)
 
G

Guest2

Gast
Kennst du eig. die Methode indexOf (oder zahlreiche andere Methoden)?

Natürlich. Allerdings ist zu erwarten, dass -1 niemals ein gültiger Index innerhalb eines Strings sein wird. Für eine Methode die eine Zahl vom Nutzer einliest, kann -1 aber durchaus mal ein gültiger Wert sein.


Jetzt extra Klassen einzuführen, und damit den Code unnötig aufzublähen, halte ich hingegen für die schlechteste Lösung. 6, setzen, bitte...

Bei meinem Ansatz gibt es exakt eine Klasse, in der das gültige Intervall festgelegt wird. In allen anderen Klassen ist das Intervall dann vollkommen unerheblich. Auch ist mein Ansatz nicht aufgebläht, sondern die SLOC/Methode sind sogar deutlich reduziert. Es gibt hier im Forum einige die 3 - 5 SLOC pro Methode als geeignet ansehen.

Aber ich habe mit Deiner Reaktion gerechnet. :)

Viele Grüße,
Fancy
 
H

hüteüberhüte

Gast
Rechne mit was du willst.

Bin mal gespannt drauf, ob ihr Oberschlaumeier folgendes kürzer _und_ übersichtlicher hinbekommen würdet:
Java:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

/**
 * @author hüte
 */
public class Lotto {

    private static final BufferedReader reader =
            new BufferedReader(new InputStreamReader(System.in));
    private static final Random random =
            new Random();
    private static final List<int[]> ziehungen =
            new ArrayList<int[]>(1000);
    private static final List<int[]> tipps =
            new ArrayList<int[]>();

    public static void main(String[] args) throws IOException {
        a:
        for (;;) {
            System.out.println("Willkommen in Ihrem Lottoprogramm");
            System.out.println("---------------------------------");
            System.out.println("(1) Ich will n-Ziehungen automatisch (per Zufall) generieren lassen, dabei n selber vorgeben!");
            System.out.println("(2) Ich will 1000 Ziehungen generieren und abspeichern lassen!");
            System.out.println("(3) Ich will alle Ziehungen (Lottozahlen) ausgeben!");
            System.out.println("(4) Ich möchte einen Tipp abgeben!");
            System.out.println("(5) Ich will n-Tipps automatisch (per Zufall) generieren lassen, dabei n selber vorgeben!");
            System.out.println("(6) Ich möchte alle Tipps ausgeben!");
            System.out.println("(7) Ich will das Programm beenden!");
            switch (readInt(1, 7)) {
                case 1:
                    one();
                    break;
                case 2:
                    two();
                    break;
                case 3:
                    three();
                    break;
                case 4:
                    four();
                    break;
                case 5:
                    five();
                    break;
                case 6:
                    six();
                    break;
                case 7:
                    break a;
            }
        }
    }

    private static void one() throws IOException {
        System.out.println("n eingeben!");
        int n = readInt(1, Integer.MAX_VALUE);
        for (int i = 0; i < n; i++) {
            ziehungen.add(generiereZiehung());
        }
    }

    private static void two() {
        for (int i = 0; i < 1000; i++) {
            ziehungen.add(generiereZiehung());
        }
    }

    private static void three() {
        for (int i = 0; i < ziehungen.size(); i++) {
            System.out.println(i + 1
                    + ". Ziehung: "
                    + Arrays.toString(ziehungen.get(i)));
        }
    }

    private static void four() throws IOException {
        int[] tipp = new int[6];
        for (int i = 0; i < tipp.length;) {
            System.out.println(i + 1 + ". Zahl eingeben!");
            int t = readInt(1, 49);
            if (t != -1 && Arrays.binarySearch(tipp, t) < 0) {
                tipp[0] = t;
                Arrays.sort(tipp);
                i++;
            }
        }
        tipps.add(tipp);
    }

    private static void five() throws IOException {
        System.out.println("n eingeben!");
        int n = readInt(1, Integer.MAX_VALUE);
        for (int i = 0; i < n; i++) {
            tipps.add(generiereZiehung());
        }
    }

    private static void six() {
        for (int i = 0; i < tipps.size(); i++) {
            System.out.println(i + 1
                    + ". Tipp: "
                    + Arrays.toString(tipps.get(i)));
        }
    }

    private static int readInt(int from, int to) throws IOException {
        try {
            int i = Integer.parseInt(reader.readLine());
            if (i >= from && i <= to) {
                return i;
            }
        } catch (NumberFormatException numberFormatException) {
        }
        return -1;
    }

    private static int[] generiereZiehung() {
        int[] result = new int[6];
        boolean[] contains = new boolean[50];
        for (int i = 0; i < result.length;) {
            int r = random.nextInt(49) + 1; // 1..49
            if (!contains[r]) {
                contains[r] = true;
                result[i++] = r;
            }
        }
        Arrays.sort(result);
        return result;
    }
}

136 Zeilen...

Hth!

PS: Über ein Dank würd ich mich sehr freuen. :)
 
Zuletzt bearbeitet von einem Moderator:
S

Spacerat

Gast
@hüte:
1. Kein Mensch würde so Programmieren, Übersicht geht anders, wenn auch zu Lasten der Zeilenanzahl, auf die es aber nicht ankommt. Bin mir fast sicher, du weist nicht mal, was SLOCs sind. Kleiner Tipp, man trägt sie keineswegs an den Füßen.
2. Leute, die sich selbst als Nonplusultra der Entwicklergilde betrachten, gehören eigentlich auf die Ignorierliste. Ist ja keineswegs so, dass sie nicht auch mal Hilfe benötigen, wofür sie sich ebenso wenig bedanken würden, sogar dezente Tipps schlagen sie aus und verlangen stattdessen, dass man sich für ihre permanente Überheblichkeit auch noch bei ihnen bedankt. Dabei vergessen sie stets, dass immer einer besser kann.
3. Bist du ADHS-Patient? (ADHS -> Aufmerksamkeitsdefizit-/Hyperaktivitätsstörung) In dem Falle nehm' ich sogar Rücksicht.
 
Zuletzt bearbeitet von einem Moderator:
H

hüteüberhüte

Gast
Beitrag gemeldet. Eine kleine Sperre würde dir (und vor allem uns) glaube ich mal ganz gut tun.
 
Zuletzt bearbeitet von einem Moderator:
G

Gast2

Gast
Hrm... selber austeilen und sich dann beschweren... *kopschüttel*

Ich kann da nur zustimmen, du bist uneinsichtig und völlig beratungsresistent - auch wenn die Tips von erfahrenen Entwicklern kommen und wirklich sinnvolle Denkanstöße bieten.
 
H

hüteüberhüte

Gast
Naja, Erfahrung heißt eben nicht alles, solange nur Vorschläge kommen, die eher zu einer Verschlechterung als Verbesserung führen (z.B. bei der Lesbarkeit oder Performance, siehe Spacerat s letzten Versuch). Ich bleib dabei, solange jemand nichts besseres vorweisen kann, betrachte ich seine Beiträge als Spam oder Trolling. Mir ist es auch wurscht, wie beliebt oder hoch angesehen Fancy hier bei einigen anscheinend ist.

@Spacerat: 1. Du würdest vielleicht nicht so programmieren, weil du es nicht besser kannst. 2. Wenn man gezeigt bekommt, wies richtig gemacht wird, denke ich, sollte ein dezentes Danke schon drin sein. Wie wär's, wenn du auch mal über deinen eigenen Schatten springen würdest und dich bedankst? :D
3. Wie gesagt, bereits gemeldet.
 
Zuletzt bearbeitet von einem Moderator:

Jango

Gesperrter Benutzer
Macht weiter, ich amüsiere mich köstlich!

Der TO hat schon längst das Interesse an dem Thread verloren, aber es wird geflamt ohne Ende.
Und wer ist nicht nur wieder mittendrin, sondern auch der Hauptflamer? hüteüberhüte... :lol:
 

KuhTee

Aktives Mitglied
sowohl der Reader als auch der Scanner werfen zwangsweise eine Exception, sofern die Eingabe ungültig ist. Imho ist es legitim sich dort mit einer weiteren Exception dran zu hängen, um die Eingabe auf ein gültiges Intervall einzugrenzen.
Damit vermengt man aber kritische Fehlerbehandlung mit Programmlogik. Finde ich nicht so prickelnd.

Die Exceptions zu fangen und durch ein "Magic-Value" (-1, 0, 1337) zu ersetzen halte ich hingegen für ungünstig.
Doch, das ist sogar ziemlich günstig und praktisch in den meisten Fällen. Ich zB verwende ich ca 80% meiner Projekte eine Methode "toInt(String s, int onError)". In den meisten Fällen ist es so, dass das Programm nicht einfach mit einer Fehlermeldung abschmieren darf, sondern weiterlaufen muss, und zwar mit einem Default Wert. Und das ist dann auch kein "Magic value", sondern ein ganz Problembezogener Wert. So wie auch in diesem Fall. Daher interpretiert man bei den Lottozahlen eine Nichtzahl einfach als 0.

Dein Code ist übersichtlich und lesbar, aber verwendest auch wieder Exceptions zur Programmflusssteuerung. Die Dinger heissen "Ausnahmen". Unter einer Ausnahme sollte man eher etwas verstehen wie Division durch 0, Zugriff auf nicht existierenden Arrayindex etc. Aber reine Programmlogik? Neeee... Aber das können wir ja anderswo diskutieren :)
 

KSG9|sebastian

Top Contributor
Also huette, vielleicht solltest du die Füße ein wenig still halten. Deine Codeneispiele entsprechen eher dem Paradigma "Masse statt Klasse", vielleicht solltest du akzeptieren was die erfahrenen Leute hier posten!
Die Anzahl an Zeilen hat mal nix mit Performance zu tun, Code der von oben nach unten durchläuft ist nicht lesbar sondern eher Spaghetticode, daher lass es mal gut sein.

Auch wenn der Artikel vielleicht zu viel des Guten ist beschreibt er soziemlich jeden "Bock" in deinem Code:
One Jar To Rule Them All: Avoiding FORs - Anti-If Campaign

Für jede Zahl ne eigene Methode zu machen..sorry.. epic fail!

** Edith sagt **
Bei ner IOException das Programm beenden? Nicht dein Ernst? Wie kommst du auf solche "Patterns"?
 
Zuletzt bearbeitet:
G

Guest2

Gast
Doch, das ist sogar ziemlich günstig und praktisch in den meisten Fällen. Ich zB verwende ich ca 80% meiner Projekte eine Methode "toInt(String s, int onError)". In den meisten Fällen ist es so, dass das Programm nicht einfach mit einer Fehlermeldung abschmieren darf, sondern weiterlaufen muss, und zwar mit einem Default Wert.

Weiterlaufen mit einem Default-Wert wäre für mich im Allgemeinen in Ordnung. Hier ist dies jedoch nicht so, das Verhalten der anderen Methoden unterscheidet sich zwischen -1 und anderen Werten. Die -1 ist nach meinem Empfinden also klar ein Magic-Value.

Das Verhalten der Java API Klassen/Methoden ist öffentlich dokumentiert und bekannt. Kapselt man eine dieser Methoden und verändert ihr Verhalten, also z.B. das Fangen einer Exception und umwandeln in ein Magic-Value, dann verändert man ein standardkonformes Verhalten in ein nicht standardkonformes Verhalten.

Unter C verwende ich diese Art der Rückgabe ebenfalls. Jedoch ist dies dort Usus. Hier in Java werfen die entsprechenden Methoden der API Exceptions und die Aufgabe des Entwicklers ist es imho, sinnvoll darauf zu reagieren. Das Umwandeln in ein Magic-Value ist für mich keine sinnvolle Reaktion.

Möchte man z.B unbedingt das Verhalten von Integer.parseInt() anpassen und die NumberFormatException kapseln, würde ich ehr etwas in dieser Art vorschlagen:

Java:
public final class CustomUserInput {

    private final BufferedReader reader;

    private Integer              lastValidValue;


    public CustomUserInput(final BufferedReader reader) {

        this.reader = reader;

    }


    public boolean readNextInt() throws IOException {

        try {

            final String input = reader.readLine();
            final int integer = Integer.parseInt(input);
            lastValidValue = integer;

            return true;

        } catch (final NumberFormatException e) {

            return false;

        }

    }


    public Integer getLastValidValue() {

        return lastValidValue;

    }

}

(Das geht dann in die Richtung von Scanner.hasNextInt() / nextInt())

Viele Grüße,
Fancy
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
B JUnit / Exceptions/ try-catch Java Basics - Anfänger-Themen 6
F Mehrere Exceptions in einem Catch-Block abfangen Java Basics - Anfänger-Themen 12
J Frage zum Thema Exceptions (Try/Catch) Java Basics - Anfänger-Themen 3
Z Catch & Exceptions Java Basics - Anfänger-Themen 4
Daniel_L Verwendung von try und catch bei exceptions Java Basics - Anfänger-Themen 7
C Exceptions, try, catch --> Frage Java Basics - Anfänger-Themen 7
Silver-Blue fragen zu Swing und catch Exceptions Java Basics - Anfänger-Themen 2
M Exception->mehrere Exceptions in einem Catch Block behand Java Basics - Anfänger-Themen 4
M Test auf Exceptions schreiben Java Basics - Anfänger-Themen 11
berserkerdq2 Habe zwei exceptions, welche ist ein Kommunikationsfehler und welche ein Ausgabefehler? Java Basics - Anfänger-Themen 4
julian112 Input/Output .gz bzw. .txt Datei Einlesen und Umgang mit Exceptions Java Basics - Anfänger-Themen 1
C Exceptions identifizieren Java Basics - Anfänger-Themen 5
A Exceptions mit objektreferenzen Java Basics - Anfänger-Themen 4
A Exceptions und methods Java Basics - Anfänger-Themen 2
A Cannot find symbol bei exceptions Java Basics - Anfänger-Themen 2
A Exceptions und Packages Java Basics - Anfänger-Themen 6
X Exceptions Benutzereingaben Java Basics - Anfänger-Themen 4
F Exceptions in Interfaces Java Basics - Anfänger-Themen 4
L Exceptions und Konten Java Basics - Anfänger-Themen 21
D Frage zu Exceptions Java Basics - Anfänger-Themen 8
I Wie programmiert man Exceptions? Java Basics - Anfänger-Themen 4
N Unterschied zwischen Checked und Unchecked Exceptions Java Basics - Anfänger-Themen 12
C Erste Schritte Exceptions nicht verstanden Java Basics - Anfänger-Themen 2
J Fragen zu Exceptions Java Basics - Anfänger-Themen 24
T Exceptions - ausgeführte Zeilen Java Basics - Anfänger-Themen 4
J Exceptions Java Basics - Anfänger-Themen 69
C Exceptions Java Basics - Anfänger-Themen 8
C Exceptions Java Basics - Anfänger-Themen 6
A ArrayQueue mit Exceptions und Vererbung Java Basics - Anfänger-Themen 3
F Exceptions Java Basics - Anfänger-Themen 6
M "Exceptions abfragen" Java Basics - Anfänger-Themen 6
Farbenfroh Exceptions Anfänger - Finde Fehler nicht Java Basics - Anfänger-Themen 7
N Compiler-Fehler Drei Exceptions in GUIHack für Dreiecke auf MoveButtons Java Basics - Anfänger-Themen 36
V Welche Exceptions müssen importiert werden? Java Basics - Anfänger-Themen 3
S Exceptions Java Basics - Anfänger-Themen 7
M Vererbung Problem Vererbung/Exceptions Java Basics - Anfänger-Themen 9
S Verschachtelte Exceptions - Übersicht verbessern Java Basics - Anfänger-Themen 2
J Eclipse Exceptions Java Basics - Anfänger-Themen 2
K Schleifen und Exceptions Java Basics - Anfänger-Themen 8
K Exceptions auslagern Java Basics - Anfänger-Themen 15
R NullPointer Exceptions Java Basics - Anfänger-Themen 3
F Erste Schritte Übung zu Exceptions Java Basics - Anfänger-Themen 24
H Int Exceptions Java Basics - Anfänger-Themen 12
M Exceptions per throws oder try Java Basics - Anfänger-Themen 4
M Compiler-Fehler Queue als ArrayList mit Exceptions Java Basics - Anfänger-Themen 3
T Exceptions in einer Klasse Java Basics - Anfänger-Themen 3
B Eigene Exceptions entwerfen Java Basics - Anfänger-Themen 3
H Methoden Überflüssige Exceptions Java Basics - Anfänger-Themen 20
C Exceptions Java Basics - Anfänger-Themen 14
1 While Schleife Exceptions Java Basics - Anfänger-Themen 6
I Erste Schritte Eigene Fehlermeldungen bei Exceptions Java Basics - Anfänger-Themen 19
D Frage zu Exceptions Java Basics - Anfänger-Themen 12
M Compiler-Fehler Exceptions lieber throwen oder direkt catchen? Java Basics - Anfänger-Themen 8
T Exceptions Java Basics - Anfänger-Themen 19
B Wie finde ich Exceptions? Java Basics - Anfänger-Themen 19
Dit_ Input/Output Alle Exceptions protokollieren Java Basics - Anfänger-Themen 9
T Exceptions Java Basics - Anfänger-Themen 12
J Standard Exceptions abfangen Java Basics - Anfänger-Themen 5
F Exceptions werfen oder catchen?? Java Basics - Anfänger-Themen 14
D Exceptions - Ausnahmebehandlung Java Basics - Anfänger-Themen 19
D Frage zu Exceptions und der import Anweisung Java Basics - Anfänger-Themen 12
J Paar Fragen zu Exceptions Java Basics - Anfänger-Themen 16
G Verständnisproblem: Exceptions Java Basics - Anfänger-Themen 17
S Exceptions bei push/pop in Stack Java Basics - Anfänger-Themen 8
C Exceptions beim Beenden Java Basics - Anfänger-Themen 2
C TimerTask und Exceptions Java Basics - Anfänger-Themen 5
E Klasse öffnen, mehrere Exceptions Java Basics - Anfänger-Themen 9
C Exceptions Java Basics - Anfänger-Themen 7
G 2 Exceptions in einer Methode Java Basics - Anfänger-Themen 3
firefexx Exceptions werfen Java Basics - Anfänger-Themen 5
0 Exceptions mehrfach fangbar? Java Basics - Anfänger-Themen 4
O Exceptions Java Basics - Anfänger-Themen 3
K Sinn eigener Exceptions Java Basics - Anfänger-Themen 11
H Diverse Exceptions - Troubleshooting Java Basics - Anfänger-Themen 3
J exceptions Java Basics - Anfänger-Themen 8
sc0p InterruptedExceptions und Exceptions - in Einem! Java Basics - Anfänger-Themen 5
M Frage zu Exceptions Java Basics - Anfänger-Themen 19
M Fragen zu Exceptions Java Basics - Anfänger-Themen 3
A Exception Verständnisfrage: Exceptions während, einer Statischenzuweisung abfangen Java Basics - Anfänger-Themen 10
D Exceptions werfen + beenden Java Basics - Anfänger-Themen 12
M Exceptions aus interface-Methoden Java Basics - Anfänger-Themen 2
S File.renameTo und Exceptions / Fehlermeldung Java Basics - Anfänger-Themen 2
B Exceptions in Liste sammeln? Java Basics - Anfänger-Themen 5
O Eigene Exceptions Java Basics - Anfänger-Themen 11
O "restliche" Exceptions fangen Java Basics - Anfänger-Themen 8
H [Stil] Exceptions in der Klasse behandeln oder throwen? Java Basics - Anfänger-Themen 62
T Problem beim Werfen und Fangen von Exceptions Java Basics - Anfänger-Themen 2
V Aktivitätsdiagramm / Exceptions Java Basics - Anfänger-Themen 5
V Exceptions Java Basics - Anfänger-Themen 6
K Frage zu Exceptions -> Logging Java Basics - Anfänger-Themen 6
M Eigene Fehlermeldung bei Exceptions? Java Basics - Anfänger-Themen 12
R JDom Exceptions Java Basics - Anfänger-Themen 4
R Datei einlesen mit Exceptions Java Basics - Anfänger-Themen 2
C Reflection Exceptions behandeln Java Basics - Anfänger-Themen 6
G Exceptions - spiegeln wir da nicht einen Spiegel im Spiegel? Java Basics - Anfänger-Themen 10
G Verschiedene Exceptions zu gleichem Block Java Basics - Anfänger-Themen 6
U Frage zu Exceptions Java Basics - Anfänger-Themen 5
mwildam Philosophiefrage zu Exceptions und Rückgabewerten Java Basics - Anfänger-Themen 6
D Static, final Objekte mit Exceptions im Konstruktor Java Basics - Anfänger-Themen 2
G Exceptions Java Basics - Anfänger-Themen 4

Ähnliche Java Themen

Neue Themen


Oben