Scanner Bug (Tried Everything)

So I ask users through input through these two methods:
public static String whileLoopInputString (Predicate<String> checkCase, String inputMessage, String errorMessage, Scanner scanner) {
String input = "";

while (!checkCase.test(input)) {
System.out.println(inputMessage);
input = scanner.nextLine();
if (!checkCase.test(input)) {
System.out.println(errorMessage);
}
}

return input;
}


public static byte whileLoopInputByte (Predicate<Byte> checkCase, String inputMessage, String errorMessage, Scanner scanner) {
byte input = -1;

while (!checkCase.test(input)) {
try {
System.out.println(inputMessage);
input = scanner.nextByte();
scanner.nextLine();
if (!checkCase.test(input)) {
System.out.println(errorMessage);
}
} catch (InputMismatchException e) {
System.out.println(errorMessage);
scanner.nextLine();
}
}

return input;
}
public static String whileLoopInputString (Predicate<String> checkCase, String inputMessage, String errorMessage, Scanner scanner) {
String input = "";

while (!checkCase.test(input)) {
System.out.println(inputMessage);
input = scanner.nextLine();
if (!checkCase.test(input)) {
System.out.println(errorMessage);
}
}

return input;
}


public static byte whileLoopInputByte (Predicate<Byte> checkCase, String inputMessage, String errorMessage, Scanner scanner) {
byte input = -1;

while (!checkCase.test(input)) {
try {
System.out.println(inputMessage);
input = scanner.nextByte();
scanner.nextLine();
if (!checkCase.test(input)) {
System.out.println(errorMessage);
}
} catch (InputMismatchException e) {
System.out.println(errorMessage);
scanner.nextLine();
}
}

return input;
}
The error occurs in the switch statement below, I think it happens when I ask for a byte, then a string, or vice versa (I forget):
switch (bytInput) {
case 1:
System.out.println("Rules");
break;
case 2:
strCreatedPlayerName = Logic.whileLoopInputString(
conditions);
break;

case 3:
strUsernameToLoadIn = Logic.whileLoopInputString(conditions);

case 4:
method();
break;
case 5:
bolIsInProgram = false;
break;

}
switch (bytInput) {
case 1:
System.out.println("Rules");
break;
case 2:
strCreatedPlayerName = Logic.whileLoopInputString(
conditions);
break;

case 3:
strUsernameToLoadIn = Logic.whileLoopInputString(conditions);

case 4:
method();
break;
case 5:
bolIsInProgram = false;
break;

}
bytInput also used a method switch is in a loop, if you need code more pls ask
6 Replies
JavaBot
JavaBot6d ago
This post has been reserved for your question.
Hey @austrianpainter! Please use /close or the Close Post button above when your problem is solved. Please remember to follow the help guidelines. This post will be automatically marked as dormant after 300 minutes of inactivity.
TIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here.
dan1st
dan1st6d ago
Can you elaborate on what happens?
nikcho-kouhai
nikcho-kouhai6d ago
It's probably because of the scanner.next stuff. Generally speaking that can cause issues because the non-parsed data stays in the input stream and it has to be discarded via a call to nextLine. You can confirm this by running this piece of code:
Scanner scan = new Scanner(System.in);
try {
scan.nextByte();
}catch (InputMismatchException e){

}
System.out.println(scan.nextLine());
Scanner scan = new Scanner(System.in);
try {
scan.nextByte();
}catch (InputMismatchException e){

}
System.out.println(scan.nextLine());
I believe the best way to avoid this is to just use nextLine() on your scanner and then parsing to the appropriate type as that advances the scanner past the line no matter what.
Scanner scan = new Scanner(System.in);
try{
String in = scan.nextLine();
byte b = Byte.parseByte(in);
}catch (NumberFormatException e){

}
//this hangs, because there is nothing in the input stream.
System.out.println(scan.nextLine());
Scanner scan = new Scanner(System.in);
try{
String in = scan.nextLine();
byte b = Byte.parseByte(in);
}catch (NumberFormatException e){

}
//this hangs, because there is nothing in the input stream.
System.out.println(scan.nextLine());
For this you can make a utility function that looks something like this and should work for all number types:
public static <T> T getInput(Function<String,T> c,String inputMessage,String errorMessage,Scanner scanner){
while (true){
try{
System.out.println(inputMessage);
return c.apply(scanner.nextLine());
}catch (NumberFormatException e){
System.out.println(errorMessage);
}
}
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
byte i = getInput(Byte::parseByte,"Some input message","Some error message",scan);
}
public static <T> T getInput(Function<String,T> c,String inputMessage,String errorMessage,Scanner scanner){
while (true){
try{
System.out.println(inputMessage);
return c.apply(scanner.nextLine());
}catch (NumberFormatException e){
System.out.println(errorMessage);
}
}
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
byte i = getInput(Byte::parseByte,"Some input message","Some error message",scan);
}
Of course if you don't want to do this you can just do it like you have so far, except replace the calls to nextByte or next whatever with nextLine and parse after that. I am guessing that's what is going on anyway
austrianpainter
austrianpainterOP6d ago
Thank you so much! Sorry for the little detail it was 3am for me when I asked. I might do that (which my teacher kind of dissaproves of) or just make an entirely new Scanner object in the method
JavaBot
JavaBot6d ago
If you are finished with your post, please close it. If you are not, please ignore this message. Note that you will not be able to send further messages here after this post have been closed but you will be able to create new posts.
JavaBot
JavaBot6d ago
Post Closed
This post has been closed by <@1233964909084147753>.

Did you find this page helpful?