I am writing a command line program and would like to make the the user to enters a valid age (integer). By using the Scanner class, I have something like this:
int getAge() {
Scanner = new Scanner(System.in);
int age;
boolean isValid = false;
while(!isValid) {
System.out.println("Please enter your age");
if (myScanner.hasNext()) {
if (myScanner.hasNextInt()) {
age = myScanner.nextInt();
isValid = true;
} else {
System.out.println("Please enter an integer");
}
}
}
return age;
}
The problem being that while in the loop it keeps reading input without waiting for a new value. How can I get around this?
You are not reading any token in your else path thus processing the same input over and over again. Just add the following line
myScanner.next();
inside the else-block.
You could also just use something like this. To read an entire line using a BufferedReader then parse the integer from the string and catch any exception that might occur.
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String s = br.readLine();
int intVal;
try {
intVal = Integer.parseInt(s);
}
catch(NumberFormatException nfe) {
//Do Something
}
You could place this inside your loop. (Yes I realize it doesn't use Scanner... just wanted to show an alternate approach.)
Related
In Java, I have two while loops to validate user input and continuously prompt the user if they input the wrong data type. In this program, I only have 2 questions, but I can imagine a scenario where I have more than 10, at which point 10 while loops would be cumbersome code to read and maintain. Is there a more efficient way to check for errors while continuing to prompt the user? My initial thought is to package the while loop and error checks into a separate class function and call it when input is requested.
import java.util.*;
public class IncreaseAge {
public static void main(String args[]){
Scanner userInput = new Scanner(System.in);
boolean validInput = true;
String coolName = "Adam";
int coolAge = 0;
while(validInput){
try{
System.out.print("Hello, what is your first name? ");
coolName = userInput.nextLine();
validInput = false;
}
catch(Exception error){
System.out.println("Invalid input, try again!");
userInput.next();
}
}
validInput = true;
while(validInput){
try{
System.out.print("Hi "+ coolName + "! How old are you?");
coolAge = userInput.nextInt();
validInput = false;
}
catch(Exception error){
System.out.println("Invalid input, try again!");
userInput.next();
}
}
System.out.println("Hello "+ coolName + ", in ten years you will be " + (coolAge+10));
userInput.close();
}
}
Just implement private int getIntegerInput(String prompt) and private String getStringInput(String prompt), each of which will more or less be the same as the two loops you've already coded.
This is a common and frequent way to avoid code repetition - implement "helper" routines to be used in writing your intended functionality.
Even if you don't have repetition to worry about, it's a useful partitioning of code, making it easier to understand - for example, the "get an input" code is clearly distinct from the "process the input" code.
Example:
private String getStringInput(Scanner scanner, String prompt) {
String input = null;
boolean validInput = false;
while (!validInput) {
try {
System.out.print(prompt);
input = scanner.nextLine();
validInput = !input.isEmpty();
}
catch (Exception error) {
System.out.println("Invalid input, try again!");
}
}
return input;
}
Note that I fixed the use of 'validInput' to make sense, and I assume you want to reprompt on an empty input line.
Usage is then like
String coolName = getStringInput(userInput, "What is your first name? ");
I'm new to Java and I wanted to keep on asking for user input until the user enters an integer, so that there's no InputMismatchException. I've tried this code, but I still get the exception when I enter a non-integer value.
int getInt(String prompt){
System.out.print(prompt);
Scanner sc = new Scanner(System.in);
while(!sc.hasNextInt()){
System.out.println("Enter a whole number.");
sc.nextInt();
}
return sc.nextInt();
}
Thanks for your time!
Take the input using next instead of nextInt. Put a try catch to parse the input using parseInt method. If parsing is successful break the while loop, otherwise continue.
Try this:
System.out.print("input");
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("Enter a whole number.");
String input = sc.next();
int intInputValue = 0;
try {
intInputValue = Integer.parseInt(input);
System.out.println("Correct input, exit");
break;
} catch (NumberFormatException ne) {
System.out.println("Input is not a number, continue");
}
}
Shorter solution. Just take input in sc.next()
public int getInt(String prompt) {
Scanner sc = new Scanner(System.in);
System.out.print(prompt);
while (!sc.hasNextInt()) {
System.out.println("Enter a whole number");
sc.next();
}
return sc.nextInt();
}
Working on Juned's code, I was able to make it shorter.
int getInt(String prompt) {
System.out.print(prompt);
while(true){
try {
return Integer.parseInt(new Scanner(System.in).next());
} catch(NumberFormatException ne) {
System.out.print("That's not a whole number.\n"+prompt);
}
}
}
Keep gently scanning while you still have input, and check if it's indeed integer, as you need:
String s = "This is not yet number 10";
// create a new scanner
// with the specified String Object
Scanner scanner = new Scanner(s);
while (scanner.hasNext()) {
// if the next is a Int,
// print found and the Int
if (scanner.hasNextInt()) {
System.out.println("Found Int value :"
+ scanner.nextInt());
}
// if no Int is found,
// print "Not Found:" and the token
else {
System.out.println("Not found Int value :"
+ scanner.next());
}
}
scanner.close();
As an alternative, if it is just a single digit integer [0-9], then you can check its ASCII code. It should be between 48-57 to be an integer.
Building up on Juned's code, you can replace try block with an if condition:
System.out.print("input");
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("Enter a whole number.");
String input = sc.next();
int intInputValue = 0;
if(input.charAt(0) >= 48 && input.charAt(0) <= 57){
System.out.println("Correct input, exit");
break;
}
System.out.println("Input is not a number, continue");
}
I am using java and I have a code as follow:
Scanner scanner = new Scanner(System.in);
while (true) {
String token = scanner.next();
if (token.equals("$")) break;
if (token.equals("(")) do sth;
else if (token.equals(")")) do sth;
else {
do sth
}
}
as you can see in the above code if you enter sth in the console then you enter $ at the end then the program will understand the end of input and the scanner can succesfully get each word of the string succesfully but instead I want when the user push enter then the scanner grabs the whole string and start reading it word by word I tried it this way :
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
String token = scanner.next();
if (token.equals("(")) builder.buildOpenBracket();
else if (token.equals(")")) builder.buildCloseBracket();
else {
int number = Integer.parseInt(token);
builder.buildElement(number);
}
}
but now the proram runs forever and nothing happends
Firstly, to read new line and save it in a String you should use .nextLine()
Anyway I fixed it this way:
Scanner scanner = new Scanner(System.in);
String token = scanner.nextLine();
Scanner scannerToken = new Scanner(token);
while (scannerToken.hasNext()) {
String statement = scannerToken.next();
if (statement.equals("("))
else if (statement.equals(")"))
else {
}
}
My method must request input from the user, check if it is an integer, and if it is return that integer. I attempted this using a try catch and the InputMismatchException.
I am running into an issue when it loops, if I input a non integer, it continuously spits out "Invalid input" "Enter an integer: " instead of actually asking for one.
public int getInteger(){
Scanner i = new Scanner(System.in);
int value = 0;
for(boolean test = false; test == false;){
try{
System.out.println("Enter an integer: ");
value = i.nextInt();
test = true;
return value;
}
catch(InputMismatchException e){System.out.println("Invalid input");}
}
return value;
}
You need a i.nextLine(); at the end of the loop.
catch(InputMismatchException e){System.out.println("Invalid input");}
i.nextLine();
}
What that does is reads the new line character, left unread by i.nextInt(), from the input stream. It's also the reason your i.nextInt() keeps tripping on the subsequent calls.
I suggest you call hasNextInt() before nextInt() instead of trying to catch the Exception. Something like,
public int getInteger() {
Scanner scan = new Scanner(System.in);
while (scan.hasNextLine()) {
if (scan.hasNextInt()) {
return scan.nextInt();
} else {
System.out.printf("%s is not an int%n", scan.nextLine());
}
}
return -1;
}
This is what I have written so far but when exception is raised it does not again ask the user for input.
do {
System.out.println("Enter the number of stones to play with: ");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String temp = br.readLine();
key = Integer.parseInt(temp);
} while (key < 0 && key > 9);
if (key < 0 || key > 10)
throw new InvalidStartingStonesException(key);
player1 = new KeyBoardPlayer();
player2 = new KeyBoardPlayer();
this.player1 = player1;
this.player2 = player2;
state = new KalaGameState(key);
} catch (NumberFormatException nFE) {
System.out.println("Not an Integer");
} catch (IOException e) {
System.out.println(e);
}
As soon as that NumberFormatException is thrown, you jump out of the loop and down to the catch. If your try-catch block is inside your while loop, it'll have the effect you're looking for. You may need to adjust the condition on the loop.
An alternative way is to check if the string input matches a regular expression for an integer. If it doesn't match, you ask for the input again.
See Teleteype.readInt() from the Java Project Template. The basics of it is that you read input as a String, and then you convert it to an integer using Integer.parseInt(), which will throw NumberFormatException if the contents of the String is not an integer, which you can handle by catching the NumberFormatException.
What I would recommend is instead of using all these exceptions is to make separate methods that read specific data types. (Ex.)
import java.util.Scanner;
public class HelloWorld {
public static void main(String[] args){
int n = getInteger("Enter integer: ");
System.out.println(n);
}
public static boolean isInteger(String s){
if(s.isEmpty())return false;
for (int i = 0; i <s.length();++i){
char c = s.charAt(i);
if(!Character.isDigit(c) && c !='-')
return false;
}
return true;
}
public static int getInteger(String prompt){
Scanner input = new Scanner(System.in);
String in = "";
System.out.println(prompt);
in = input.nextLine();
while(!isInteger(in)){
System.out.println(prompt);
in = input.nextLine();
}
return Integer.parseInt(in);
}
}
while (true) {
System.out.println("Enter the number of stones to play with: ");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
key = Integer.parseInt(br.readLine());
if (key > -1 && key < 10)
break;
else
System.out.println("Invalid number of stones. Choose from 0 - 9");
}