Scanner(System.in) - infinite loop - java

Why I'm getting infinite loop in recursion method, without a chance to input any symbol to break it?
class Test {
int key=0;
void meth(){
System.out.println("Enter the number here: ");
try(Scanner scan = new Scanner(System.in)) {
key = scan.nextInt();
System.out.println(key+1);
} catch(Exception e) {
System.out.println("Error");
meth();
}
}
}
class Demo {
main method {
Test t = new Test();
t.meth();
}
}
If you try to create an error (putting string value in key and then try to add to it a number), you will get infinite "Error" text in console, instead of that, after first error, program should ask again the number and only then decide what to do.

If nextInt() fails, it throws an exception but doesn't consume the invalid data. From the documentation:
When a scanner throws an InputMismatchException, the scanner will not pass the token that caused the exception, so that it may be retrieved or skipped via some other method.
You're then recursively calling meth() again, which will try to consume the same invalid data a second time, fail again (without consuming it), and recurse.
Firstly, I wouldn't use recursion here in the first place. Prefer a simple loop. Next, if you have invalid input you should consume it appropriately before trying again. Finally, consider using hasNextInt instead of just using nextInt and catching the exception.
So maybe something like this:
import java.util.Scanner;
class Test {
public static void main(String[] args){
try (Scanner scanner = new Scanner(System.in)) {
System.out.println("Enter the number here:");
while (!scanner.hasNextInt() && scanner.hasNext()) {
System.out.println("Error");
// Skip the invalid token
scanner.next();
}
if (scanner.hasNext()) {
int value = scanner.nextInt();
System.out.println("You entered: " + value);
} else {
System.out.println("You bailed out");
}
}
}
}

Related

Java. Scanner Trying to to a loop until user quits

I've been trying to make a while loop where I enter in a movie number until the user types 'q' for quit, but every time I enter a valid number, I have to enter it twice before it prompts me with the "Enter movie number" message again. And the break function doesn't work when I wish to leave the loop. I simply wish to enter in the movie number once and break out when I want to.
public class Main {
public static void main(String[] args) {
while(true)
{
System.out.println("Enter in movie number: ");
Scanner input = new Scanner(System.in);
if(!input.hasNextInt())
{
System.out.println("invalid input");
continue;
}
if (Integer.parseInt(input.next()) < 0)
{
System.out.println("invalid no negative numbers");
continue;
}
if(Objects.equals(input.next(), "q"))
break;
}
}
I tried other variations of the while loop, but a similar thing has happened.
I assume your intention is to get one line of input, and if it is a number, process it somehow, and if not check if the user wants to quit.
You've got a couple problems with your program, firstly, you're creating a new Scanner within the while loop, which creates unnecessary overhead. Second, you're trying to get 2 lines of input within your loop, you wait for the user to input an integer, then you try to parse that integer with input.next(). Afterwards, you call input.next() again to check if the user wants to quit. By calling next() twice, you're requiring the user to input 2 lines, causing the issue you were describing.
You can fix this by calling next() once and storing its return value in a variable, then check if it equals q for quit, otherwise you can parse an integer value from it.
Here is working code that applies fixes to these issues:
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while(true) {
System.out.println("Enter in a movie number:");
// Get user input
String input = scanner.next();
// If the input equals q, we break out of the loop
if(input.equalsIgnoreCase("q")) break;
int intInput;
try {
// Get integer input
intInput = Integer.parseInt(input);
} catch(NumberFormatException e) { // Input was not a number
System.out.println("Invalid, must input a number");
continue;
}
if(intInput < 0) {
System.out.println("Invalid, no negative numbers");
continue;
}
}
}
}
Also, a small note, instead of using Object.equals to check if two strings are equal you can just use the equals method inside of the String class like so: str1.equals(str2).

Trying to validate a passed value to a method

I have a program that is trying to validate a passed value. I want a user to input anything and the method that I pass it to will validate whether the input would work.
This is my code:
public static void main(String[]args) {
Scanner input = new Scanner(System.in);
ChequingAccount a = new ChequingAccount();
double deposit = inputCheck("Enter deposit amount: ", input);
a.setDeposit(deposit);
}
public static double inputCheck(String prompt, Scanner input) {
boolean userValid = false;
do {
System.out.print(prompt);
double user;
try {
user = input.nextDouble();
if (user < 0) {
throw new IllegalArgumentException("Value cannot be lower than 0");
}
userValid = true;
} catch (InputMismatchException e) {
System.out.println("The value entered is not a number");
user = inputCheck(prompt, input);
input.nextLine();
} catch (IllegalArgumentException ex) {
System.out.println(ex.getMessage());
user = inputCheck(prompt, input);
}
return user;
} while (!userValid);
}
The code works except for the fact that when the method catches the InputMismatchException, the code then will loop a bunch of times and breaks the program. I thought adding a doWhile loop would solve the issue but it didn't do anything.
you don't need a loop , you need recursion
public static double inputCheck(String prompt, Scanner input) {
double user;
try {
user = input.nextDouble();
if (user < 0) {
throw new IllegalArgumentException("Value cannot be lower than 0");
}
return user;
} catch (InputMismatchException e) {
System.out.println("The value entered is not a number");
return inputCheck(prompt, input);
} catch (IllegalArgumentException ex) {
System.out.println(ex.getMessage());
return inputCheck(prompt, input);
}
}
You're calling your own method from inside; the inputCheck method's code calls inputCheck. This is a somewhat creative way to write a loop.
You also have... a loop.
So you 2 loops, to do the job that one loop should do. That's why all heck breaks loose here. Pick one: Either use the do/while construct (so do not call yourself), or, don't loop, and call yourself. Either one can be made to work here.
The nextLine stuff is irrelevant and not the problem here (in general don't call that; just set the delimiter properly; call scanner.useDelimiter("\\r?\\n") and to get entire lines, use next(), not nextLine().
There are number of approaches that can work for this – iteration, recursion, exception catching, etc. Your solution is mixing several of them together which makes it harder to understand and also harder to fix.
Here is an example that uses a simple while loop, no recursion, no exception catching. It uses hasNextDouble() and, depending on the result, either proceeds to capture the double (by calling nextDouble()), or prints a message (along with consuming and ignoring whatever non-double token is present by calling next()).
public static double inputCheck(String prompt, Scanner input) {
while (true) {
System.out.print(prompt);
if (input.hasNextDouble()) {
double number = input.nextDouble();
if (number < 0) {
System.out.println("Value cannot be lower than 0. Please try again.");
} else {
return number;
}
} else {
System.out.println("The value entered is not a number. Please try again.");
input.next(); // consume and ignore whatever non-double input is waiting on the scanner
}
}
}

Teach me why this code fails to check if my input is a int, and how I can fix it

import java.util.Scanner;
public class HelloWorld {
public static int num;
public static Scanner scan;
public static void main(String[] args) {
System.out.println("Hello World");
/* This reads the input provided by user
* using keyboard
*/
scan = new Scanner(System.in);
System.out.print("Enter any number: ");
// This method reads the number provided using keyboard
check();
// Closing Scanner after the use
// Displaying the number
System.out.println("The number entered by user: "+num);
}
public static void check(){
try{
num = scan.nextInt();
}
catch (Exception e){
System.out.println("not a integer, try again");
check();
}
}
}
Im new to coding, and am taking this summer to teach myself some basics. I was wondering if someone could advise me on how I can create this method to take in a int, and check the input to make sure thats its a int. If the input is not a int, I would like to re run in.
Simple. Say you have something as shown below . . .
NumberThing.isNumber(myStringValue);
.isNumber() determines if your string is a numerical value (aka a number). As for putting the code in a loop to continue to ask the user for input if their input is invalid, using a while loop should work. Something like . . .
while (. . .) {
// use something to exit the loop
// depending on what the user does
}
You might consider moving the user request code to the check method. Also, use a break statement to exit your while loop after a valid number is entered.
while ( true )
{
System.out.println( "Enter an integer.");
try
{
num = scan.nextInt();
break;
}
catch (Exception e)
{
System.out.println("not a integer");
}
}

Why won't this print any integers?

try {
Scanner sc = new Scanner(new File("testing.txt"));
while (sc.hasNextInt()){
int i = sc.nextInt();
//timing.add(i);
System.out.println(i);
}
sc.close();
}catch (FileNotFoundException e) {
e.printStackTrace();
}
The text file does have int and strings in it. I can get it to print words from the text file, but not the numbers.
The text file includes the following:
Michael 3000 7000 Bilbo I like the number 2000 do you? No,
I like 9000
Your first value ("Michael") isn't an integer, therefore it never gets inside of the body of the loop.
Perhaps you want to change the code to loop until it reaches the end of the file, reading and printing integers, but consuming (without printing) non-integer values. So something like this:
import java.util.*;
import java.io.*;
public class Test {
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(new File("test.txt"));
while (sc.hasNext()) {
if (sc.hasNextInt()) {
System.out.println(sc.nextInt());
} else {
// Just consume the next token
sc.next();
}
}
sc.close();
}
}
You never enter your while loop. Because the first input Michael is not a number.
A solution would be to take .next() and use a try-catch to parse an int out of it:
while (sc.hasNext() {
String input = sc.next();
try {
int printInt = Integer.parseInt(input);
System.out.println(printInt);
} catch () {}
The problem is that hasNextInt will return false for your initial string token ("Michael"), hence your loop will never execute any statement within.
You can parse every line and infer whether the tokens are convertible to integer types instead:
while (sc.hasNext()) {
try {
System.out.println(Integer.parseInt(sc.next()));
} catch (NumberFormatException nfe) {
// nope
}
}
Will print...
3000
7000
2000
9000
The issue is that you have a mix of words and numbers. When you call sc.hasNextInt(), it checks against "Michael", which isn't an integer, so it returns false and never executes. In this case, you can read the entire line, and split it on spaces. Then check if each word is an integer using regex. You can also check by using a try...catch block and attempting to parse an integer inside of that block.
Scanner sc = new Scanner(new File("StackTxtFiles/text.txt"));
while(sc.hasNextLine()){
String [] lineSplitArray = sc.nextLine().split(" ");
for(String wordInLine : lineSplitArray){
if(wordInLine.matches("-?\\d+(\\.\\d+)?")){
System.out.println(Integer.valueOf(wordInLine));
}
}
}
sc.close();
The problem is you are checking for an int first. There is not an int first so it will exit your while loop without doing anything:
while (sc.hasNextInt()){
Michael 3000
Michael is not an int it is a String so there is no hasNextInt() there is a hasNext() and hasNextLine()...
What you can do is:
while (sc.hasNext()){
try
{
System.out.println(Integer.parseInt(sc.next());
}catch(Exception e){}
}

Why does my while loop needs this line of code to run?

I just completed an application which prompts the user for a text File input IO but I have something to clarify as the final part, While loop I actually managed to refer it to a tutorial on google. In this loop, there is a if-else statement and for the else part I don't understand why is it necessary.
Here's my code:
import java.io.*;
import java.util.*;
class FileReadingExercise2 {
public static void main(String[] args) {
Scanner userInput = new Scanner(System.in);
Scanner fileInput = null;
do {
try {
System.out.println("Please enter the name of a file or type QUIT to finish");
String a = userInput.nextLine();
if (a.equals("QUIT")) { // if user inputs QUIT then stop application
System.exit(0);
}
fileInput = new Scanner(new File(a)); // the file contains text and integers
} catch (FileNotFoundException e) {
System.out.println("Error - File not found");
}
} while (fileInput == null);
int sum = 0;
while (fileInput.hasNext()) // continues loop as long as there is a next token
{
if (fileInput.hasNextInt()) // if there is an int on the next token
{
sum += fileInput.nextInt(); // then adds the int to the sum
} else {
fileInput.next(); // else go to the next token
}
}
System.out.println(sum);
fileInput.close();
}
}
As you can see, as long as the fileInput Scanner has a next token to look up to then operate the if else statement. If fileInput has a next Int then adds it up to the sum variable. So from what I think is that this will be sufficient. Once fileInput has no more token to read, it shall get out of the while loop isn't it? Why does it has still go onto the next token? I'm confused. Please advise thanks! ;)
Why does it has still go onto the next token?
That is because when nextInt() is executed it will consume the int number within the file but within it, it has a newLine character that needs to be consume and that is when next is executed to consume that newLine after the int number.
sample file content:
1
what actually in there is 1 character and newline \n character
In this loop, there is a if-else statement and for the else part I don't understand
why is it necessary.
fileInput.hasNexInt() method returns true if int value found and than it performs adding operation. if next value is not int type than else part will perform where fileInput.next() will return next value(pointer will points after that value), performs nothing means escaping next value(which can be any type except int-type). Again if condition will check for int.

Categories

Resources