Endlosschleife bei User Input mit try Scanner

javapingu

Mitglied
Liebe Community,

ich habe seit 4 Stunden einen Bug (wahrscheinlich Logikfehler), bin aber leider nicht in der Lage diesen selbstständig zu finden - trotz aller größter Bemühungen 🙁 .
Da ich nun mittlerweile tatsächlich nicht mehr weiter weiß würde ich euch gerne um etwas Hilfe bitten.

Ich möchte den Tag und den Monat vom User einlesen und die Kombination validieren - dabei jedoch nur eine Methode nutzen um es möglichst Redundanzfrei zu halten.
Der Fehler steckt meiner Meinung nach in Zeile 31-36.
Erwartetes Verhalten:
Nach der erfolgreichen Eingabe des Tages, wird mit dem Monat gleich verfahren - es wird geprüft ob der Monat im Bereich 1-12 liegt und eine Zahl ist, solange bis eine gültige Eingabe erfolgt.

Erhaltenes Verhalten:
Eine Endlosschleife mit folgendem Output: [CODE lang="java" title="output"]Monat (1-12): Bitte eine ganze Zahl eingeben.[/CODE]
Anschließend die Fehlermeldung:
[CODE lang="java" title="error_msg"]Exception in thread "main" java.util.regex.PatternSyntaxException: Stack overflow during pattern compilation near index 138
(([-+]?(((((?i)[0123456789\[...] at java.base/java.util.regex.Pattern.error(Pattern.java:2027)[/CODE]

Mein Code lautet wie folgt:

[CODE lang="java" title="Der problematische Code"]import java.util.Scanner;

/**
*
* @author pingu
*/

/**
* Eine Klasse die vom User die Nutzereingaben einliesst, zu einem String
* konkateniert und diesen am Ende der Eingaben ausgibt
*/
public class Jahreszeit {

public static void main(String[] args) {
Jahreszeit jahreszeit = new Jahreszeit();
int tag = jahreszeit.userInput(true, true, 1, 31);
System.out.println(tag);
int monat = jahreszeit.userInput(true, true, 1, 12);
System.out.println(monat);
}

/**
* Eine Methode die eine Loop hat. Dabei ist die Haeufigkeit des durchlaufens
* vom UserInput abhaengig
*/
public int userInput(boolean inputInt, boolean valide, int min, int max) {
int dateValue;
errorNaN(inputInt, valide); // Nur wenn !int || ungültig - error_msg
try (Scanner userInput = new Scanner(System.in)) { // nur wenn valider Tag return, sonst repeat
System.out.print(max > 12 ? "Tag (1-31): " : "Monat (1-12): ");
return ((inputInt = userInput.hasNextInt())
&& (valide = validator(dateValue = userInput.nextInt(), min, max)) ? dateValue
: userInput(inputInt, valide, min, max));
} // Scanner close mit try
}

/** Eine Methode die den UserInput (Monat, Tag) validiert */
public boolean validator(int dateValue, int min, int max) {
return (dateValue >= min && dateValue <= max) ? true : false;
}

/** Eine Methode die User darauf hinweisst einen validen int einzugeben */
public static void errorNaN(boolean inputInt, boolean valide) {
System.out.print(!inputInt ? "Bitte eine ganze Zahl eingeben.\n" : "");
System.out.print(inputInt && !valide ? "Nicht im geforderten Bereich.\n" : "");
}

}[/CODE]

Ich verstehe leider nicht, weshalb eine Endlosschleife entsteht, denn bei der Übergabe des Parameters für den monat sind ja beide booleans inputInt und valide true...da ich meinen Fehler nicht selbstständig finden konnte, kann ich das Problem leider auch nicht sauber lösen 🙁
Über eine Hilfe mit Erklärung, weshalb der Fehler entsteht (womöglich weiß ich etwas noch nicht oder bin blind) und Hinweise die mich in die richtige Richtung zur Fehlerbehebung "schubsen" wäre ich unendlich dankbar...

Vielen, vielen Dank im voraus und einen schönen & stressfreien Abend
 
Kannst du den ganzen Stacktrace der Fehlermeldung posten?

(der sieht interessant aus, Fehler hast du in deinem Code aber noch andere, aber dazu später mehr 🙂 )
 
Kannst du den ganzen Stacktrace der Fehlermeldung posten?
Selbstverständlich, das wäre:

[CODE lang="java" title="gesamte Fehlermeldung"]Monat (1-12): Bitte eine ganze Zahl eingeben.
Monat (1-12): Bitte eine ganze Zahl eingeben.
Monat (1-12): Bitte eine ganze Zahl eingeben.
Monat (1-12): Bitte eine ganze Zahl eingeben.
Monat (1-12): Exception in thread "main" java.util.regex.PatternSyntaxException: Stack overflow during pattern compilation near index 155
(([-+]?(((((?i)[0123456789\p{javaDigit}])++)|([\p{javaDigit}&&[^0]]((?i)[0123456789\p{javaDigit}])?((?i)[0123456789\p{javaDigit}])?(\x{2e}((?i)[0123456789\p{javaDigit}])((?i)[0123456789\p{javaDigit}])((?i)[0123456789\p{javaDigit}]))+)))))|(((((?i)[0123456789\p{javaDigit}])++)|([\p{javaDigit}&&[^0]]((?i)[0123456789\p{javaDigit}])?((?i)[0123456789\p{javaDigit}])?(\x{2e}((?i)[0123456789\p{javaDigit}])((?i)[0123456789\p{javaDigit}])((?i)[0123456789\p{javaDigit}]))+)))|(\Q-\E((((?i)[0123456789\p{javaDigit}])++)|([\p{javaDigit}&&[^0]]((?i)[0123456789\p{javaDigit}])?((?i)[0123456789\p{javaDigit}])?(\x{2e}((?i)[0123456789\p{javaDigit}])((?i)[0123456789\p{javaDigit}])((?i)[0123456789\p{javaDigit}]))+)))
^
at java.base/java.util.regex.Pattern.error(Pattern.java:2027)
at java.base/java.util.regex.Pattern.<init>(Pattern.java:1430)
at java.base/java.util.regex.Pattern.compile(Pattern.java:1068)
at java.base/java.util.Scanner$PatternLRUCache.forName(Scanner.java:3047)
at java.base/java.util.Scanner.integerPattern(Scanner.java:446)
at java.base/java.util.Scanner.hasNextInt(Scanner.java:2158)
at java.base/java.util.Scanner.hasNextInt(Scanner.java:2138)
at Jahreszeit.userInput(Jahreszeit.java:33)
at Jahreszeit.userInput(Jahreszeit.java:35)
at Jahreszeit.userInput(Jahreszeit.java:35)
at Jahreszeit.userInput(Jahreszeit.java:35)
at Jahreszeit.userInput(Jahreszeit.java:35)
at Jahreszeit.userInput(Jahreszeit.java:35)
at Jahreszeit.userInput(Jahreszeit.java:35)
at Jahreszeit.userInput(Jahreszeit.java:35)
at Jahreszeit.userInput(Jahreszeit.java:35)
at Jahreszeit.userInput(Jahreszeit.java:35)[/CODE]

Vielen Dank 🙂
 
da ich meinen Fehler nicht selbstständig finden konnte, kann ich das Problem leider auch nicht sauber lösen
Du solltest erst mal versuchen etwas übersichtlicher zu programmieren.

Sowas wie
Java:
return ((inputInt = userInput.hasNextInt())
                    && (valide = validator(dateValue = userInput.nextInt(), min, max)) ? dateValue
                            : userInput(inputInt, valide, min, max));
ist nicht sehr gut zu lesen und der Rest ist nicht viel besser.
 
Ahh. Das Hauptproblem dürfte sein, dass man den Scanner nicht schließen darf und nur eine einzige Instanz öffnen sollte. Wenn man den Scanner schließt, schließt man auch System.in, und das kann man nie wieder öffnen. Außerdem puffert Scanner intern die Eingabe, wenn man mehrere hat "klauen" diese sich die Eingabe.
 
Dieses lässt sich vereinfachen:
Java:
    /** Eine Methode die den UserInput (Monat, Tag) validiert */
    public boolean validator(int dateValue, int min, int max) {
        return (dateValue >= min && dateValue <= max) ? true : false;
    }
zu
Java:
    /** Eine Methode die den UserInput (Monat, Tag) validiert */
    public boolean validator(int dateValue, int min, int max) {
        return (dateValue >= min && dateValue <= max);
    }
Das ist aber nebensächlich.
 
Du solltest erst mal versuchen etwas übersichtlicher zu programmieren.

Sowas wie
Java:
return ((inputInt = userInput.hasNextInt())
                    && (valide = validator(dateValue = userInput.nextInt(), min, max)) ? dateValue
                            : userInput(inputInt, valide, min, max));
ist nicht sehr gut zu lesen und der Rest ist nicht viel besser.
Dankeschön, ja es ist dieses mal tatsächlich unübersichtlich geworden, das tut mir wirklich leid - ich hatte versucht es so kurz wie möglich zu fassen mit ternären Operatoren und habe mich wohl in dem Versuch verlaufen.
Ich werde versuchen in Zukunft die übersichtlichere Variante vorzuziehen (und diese Variante wahrscheinlich nochmal übersichtlicher zu überarbeiten) :| Und dankeschön für den Kürzungstipp 🙂
 
Ahh. Das Hauptproblem dürfte sein, dass man den Scanner nicht schließen darf und nur eine einzige Instanz öffnen sollte. Wenn man den Scanner schließt, schließt man auch System.in, und das kann man nie wieder öffnen. Außerdem puffert Scanner intern die Eingabe, wenn man mehrere hat "klauen" diese sich die Eingabe.
Vielen, vielen Dank für den Tipp - ich versuche dies zu beheben =)
 

Zurück
Oben