This question already has answers here:
How do I ensure that Scanner hasNextInt() asks for new input?
(2 answers)
Closed 6 years ago.
Desired outcome:
Accepts user input
Makes sure user inputs only 1 integer value at a time
Stores that integer in a variable
I tried to achieve this by doing the following:
Store user input in variable
Count number of tokens in variable
If there's not one token, reject the input
If the input is not of data type int, reject the input
Code:
Scanner scan = new Scanner(System.in);
System.out.println("Enter an integer:");
String myString = scan.nextLine();
int tokens = new StringTokenizer(myString, " ").countTokens();
while (tokens != 1 && !scan.hasNextInt()) {
System.out.println("Enter a single integer");
myString = scanner.nextLine();
tokens = new StringTokenizer(myString, " ").countTokens();
}
int number = scanner.nextInt();
System.out.println(number);
This code is full of holes. The output is inconsistent and undesired. It typically ends by throwing a java.util.InputMismatchException error, indicating the value it's trying to store isn't an int. I've experienced this error occur after one loop and after multiple loops, even with the same type and quantity of input (e.g. 2 strings).
Should I keep going with this code, or should I try to approach this problem from a different angle?
I've modified your program a little bit. My approach was to accept a single line of input. If the input contains more than one token, ask the user to re-enter input. If there is only one input, check if the input is an integer, if not, as the user to again provide input.
Seems to work for me:
Scanner scanner = new Scanner(System.in);
String myString;
int tokens;
int number;
do {
System.out.println("Enter a single integer");
myString = scanner.nextLine();
tokens = new StringTokenizer(myString, " ").countTokens();
try {
number = Integer.parseInt(myString);
} catch(NumberFormatException e) {
tokens = 0;
number = -1;
}
}while (tokens != 1);
scanner.close();
System.out.println(number);
Update: Alternate approach without using StringTokenizer
Scanner scanner = new Scanner(System.in);
String myString;
boolean validInput;
int number;
do {
System.out.println("Enter a single integer");
myString = scanner.nextLine();
try {
number = Integer.parseInt(myString);
validInput = true;
} catch(NumberFormatException e) {
validInput = false;
number = -1;
}
}while (validInput == false);
scanner.close();
System.out.println(number);
Update 2: Another approach using regular expressions to validate input before accepting it.
The Scanner allows us to use a regular expression to match the input. If the input matches the pattern, you can use it to accept the input. Otherwise, discard it and ask user to provide input again.
Here's the code:
Scanner scanner = new Scanner(System.in);
System.out.println("Enter a single integer");
String integerPattern = "[+-]?\\d+$"; // positive or negative and digits only
while(scanner.hasNext(integerPattern) == false) {
String x = scanner.nextLine();// capture and discard input.
System.out.println("Enter a single integer. '" + x + "' is an invalid input.");
}
int number = scanner.nextInt(); // capture input only if it matches pattern.
scanner.close();
System.out.println("number: " + number);
Hope this helps!
Related
So I was using this code in my program and whenever I give input consisting of multiple words, the compiler executes the catch block that many times. I've also tried it with different methods & till now all efforts went to vain.
Method 1:
Scanner scanner = new Scanner(System.in);
int size = 0;
while (true)
{
try
{
size = scanner.nextInt();
break;
}
catch (InputMismatchException e)
{
System.out.println("Enter valid input (Digit Only)");
scanner.next();
continue;
}
}
Method 2:
Scanner scanner = new Scanner(System.in);
int size = 0;
boolean bError = true;
while (bError)
{
if (scanner.hasNextInt())
size = scanner.nextInt();
else
{
System.out.println("Enter valid input (Digit Only)");
scanner.next();
continue;
}
bError = false;
}
Method 3:
Scanner scanner = new Scanner(System.in);
int size = 0;
while (true)
{
if (scanner.hasNextInt())
size = scanner.nextInt();
else
{
scanner.next();
System.out.println("Enter valid input (Digit Only)");
continue;
}
String sizeStr = Integer.toString(size);
Pattern pattern = Pattern.compile(new String ("^[0-9]*$"));
Matcher matcher = pattern.matcher(sizeStr);
if(matcher.matches())
{
break;
}
else
{
System.out.println("Enter valid input (Digit Only)");
continue;
}
}
Method 4:
Scanner scanner = new Scanner(System.in);
int size = 0;
while (scanner.hasNext())
{
if (scanner.hasNextInt())
{
size = scanner.nextInt();
System.out.println(size);
break;
}
else
{
System.out.println("Enter valid input (Digit Only)");
scanner.next();
}
}
I'm now able to do the task via taking a String input and then parsing it to int. But the initial doubt still remains that why that was not working properly. The code below is working fine.
Scanner scanner = new Scanner(System.in);
int size = 0;
while (true)
{
try
{
String sizeStr = scanner.nextLine();
size = Integer.parseInt(sizeStr);
break;
}
catch (NumberFormatException e)
{
System.out.println("Enter valid input (Digit Only)");
scanner.next();
continue;
}
}
According to the official Java Doc (https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html):
A Scanner breaks its input into tokens using a delimiter pattern,
which by default matches whitespace. The resulting tokens may then be
converted into values of different types using the various next
methods.
The scanner can also use delimiters other than whitespace.
By default, all the next*() functions of scanner class other than nextLine() read the next token, not the next line. This means it reads until it finds a whitespace. If you want to read all the tokens in a line, you need to use nextLine() and then format the input explicitly as you want.
Consider this input:
abcd xyz
When you do scanner.nextInt() or any of scanner.next*() functions other than scanner.nextLine(), only "abcd" is read because it is the next token. When you do scanner.nextLine(), the complete string in the current line "abcd xyz" is read and the scanner advances to the next line.
However, if you want the nextInt() function to read the whole line, then you can set the delimiter to be new line '\n'.
Scanner scan = new Scanner(System.in).useDelimiter("\n");
Using this, you can get the behaviour that you want.
Below code outputs only "Enter a string" and accepts user input however, does not display the number of characters in the string. Kindly help!
System.out.println("Enter a string");
Scanner scan = new Scanner(System.in);
String result = scan.nextLine();
try {
while (a != null) {
count++;
}
} catch (Exception e) {
System.out.println("Invalid string");
}
System.out.println("The number of characters are : " + count);
You can use String.length() to calculate the length of your input string:
System.out.println("Enter a string");
Scanner scan = new Scanner (System.in);
String a = scan.nextLine();
System.out.println("The number of characters are : " + a.length());
oschlueter is right. Also, when using java.util.Scanner to get a string from user input, you won't need a try/catch to look for invalid strings, as anything the user can input can be a String. However, you will need a Try/Catch when asking for a number through Scanner.nextInt.
Also, it's generally recommended to catch a specific error and not just Exception. In this case, you would catch java.util.InputMismatchException.
I'm trying to read integers entered one after another on a single line separated by a space.
There will be some way for this code to work without using .nextLine, without converting the input to a string and then do the conversion to integer?
The challenge is "not use .nextLine", do not use string or conversions. Reading pure integers and exit from while loop.
public static void scannerInts (){
int[] list = new int[100];
int n=0;
System.out.print("Input data into one line, [ENTER] to finish: ");
Scanner input = new Scanner(System.in);
while (input.hasNext()) {
if (input.hasNextInt()) {
list[n++]= input.nextInt();
} else {
input.next();
}
}
for (int i=0;i<n;i++)
System.out.print(list[i] + " ");
}
PD: I've tried many of the responses from Stack OverFlow and nothing seems to work.
The problem is that System.in is an infinite stream. Calling hasNextXXX will cause System.in to prompt if the Scanner doesn't find a token in what has already been read. The user needs to enter some non-integer to terminate the list.
You may, however, use a second Scanner since Scanner can scan a String e.g.:
Scanner in = new Scanner(System.in);
System.out.print("Enter a list of integers: ");
List<Integer> list = new ArrayList<>();
Scanner line = new Scanner(in.nextLine());
// optional
line.useDelimiter("\\D+");
while(line.hasNextInt()) {
list.add(line.nextInt());
}
System.out.println("You entered " + list);
Using a single Scanner you could also use findInLine:
for(String token; (token = in.findInLine("-?[1-9]\\d*")) != null;) {
list.add(Integer.valueOf(token));
}
I am attempting to make sure the user input int type only and make sure the integer inputted is greater than 0.
I was able to come up with the following to make sure the input is int type:
Scanner scan = new Scanner(System.in);
while(!scanner.hasNextInt())
{
scanner.next();
}
int input = scan.nextInt();
But how should I include a condition checking to make sure the integer is greater than 0 as well?
The problem with your current approach is you've already ready the value from the Scanner before it reaches int input = scan.nextInt();, meaning that by the time you use nextInt, there's nothing in the Scanner to be read and it will wait for the next input from user...
Instead, you could read the String from the Scanner using next, use Integer.parseInt to try and parse the result to an int and then check the result, for example...
Scanner scanner = new Scanner(System.in);
int intValue = -1;
do {
System.out.print("Please enter a integer value greater than 0: ");
String next = scanner.next();
try {
intValue = Integer.parseInt(next);
} catch (NumberFormatException exp) {
}
} while (intValue < 0);
System.out.println("You input " + intValue);
put an if statement inside your while loop like this
if(num <= 0){
System.out.println("Enter a number greater than zero");
}
else{
break;
}
You may use a condition in your code but not in the loop as.
`
Scanner scan = new Scanner(System.in);
abc:
while(!scanner.hasNextInt())
{
scanner.next();
}
int input = scan.nextInt();
if(input <= 0){
goto abc;
}
`
using .isDigit() method then checking to see if that number is greater than 0 if it is a digit
Very Frustrated at my professor, because she did not teach try and catch concepts, neither did she teach us about throw exceptions either, so it is very difficult for me to do this program. The objective is to make a program where the user is asked to input an integer that prints "Hello World" that many times of the integer. The problem is I cannot check to make sure the user input is an integer. For instance, if the user chose to type a character or a double, how do I implement that into my code? And I cannot use throw exceptions or try and catch because we did not learn them yet.Thanks guys!!!
import java.util.Scanner;
public class PrintHelloWorld
{
public static void main( String[] args )
{
Scanner scan = new Scanner(System.in);
int number;
System.out.println("Please enter an integer that shows the " +
"number of times to print \"Hello World\" : ");
//store count
number = scan.nextInt();
System.out.print("Your integer is " + number);
int remainder = number%1;
int counts = 0;
if( number>0 && remainder == 0)
{
while(counts <= number)
{
System.out.println("Hello World!");
counts++;
}
}
else
System.out.print("Wrong, choose an integer!");
}
}
scan.hasNextInt()
will check to see if the next value in the input stream is an integer.
as such:
int number = -1;
System.out.println("Please enter an integer that shows the " +
"number of times to print \"Hello World\" : ");
//store count
if (scan.hasNextInt()) number = scan.nextInt();
if (number != -1) System.out.print("Your integer is " + number);
You can use a loop and validate the input with a regex, like this:
Scanner scan = new Scanner(System.in);
String input = null;
while (true) {
input = scan.nextLine();
if (input.matches("\\d+")) {
break;
}
System.out.println("Invalid input, please enter an integer!");
}
int number = Integer.parseInt(input);
This will keep asking for input until a valid integer is entered.
And I cannot use throw exceptions or try and catch because we did not
learn them yet.
For a first attempt, you could create a method that accepts a String as parameter. You will loop through all the chars of this String and check if each char is a digit. While this method returns false, re-ask the user for a new input.
Then use Integer.valueOf to get the int value..
public static boolean isNumber(String input)
You will have to use sc.nextLine() to get the input
The method Character.isDigit and toCharArray() will be useful