JAVA - SCANNER to get user input - java

I have the following block code:
boolean run = true;
while (run) {
Scanner scanner = new Scanner(System.in);
// do something
System.out.println("Another action? [Y/N]");
while (!scanner.hasNext("[YyNn]")) {
System.out.println("Incorrect input");
scanner.next();
}
String choice = scanner.next();
if (choice.toLowerCase().equals("f"))
run = false;
scanner.close();
}
I want to perform something until the user types 'N'.
Currently, I'm able to run the while loop only one time.
The second time I'm not able to type my choice and I have the following error:
Another action? [Y/N] <--- here no chance to type choice
Incorrect input
java.util.NoSuchElementException
at java.util.Scanner.throwFor
at java.util.Scanner.next
What is wrong?
Thanks
EDIT: I think my problem is in "do something". It is in turn a sequence of user input where i close the scanner.

I took off the scanner.close(); and added "fF" to the pattern, it runs until I input f or F:
boolean run = true;
while(run){
System.out.println("Another action? [Y/N]");
while (!scanner.hasNext("[YyNnfF]")) {
System.out.println("Incorrehct input");
scanner.next();
}
String choice = scanner.next();
if(choice.toLowerCase().equals("f"))
run = false;
// scanner.close();
}

The problem in fact is in your while loop condition. Let's debug:
When you only input chars that do not match with the pattern [YyNn] all goes ok (user will always get the Incorrect input message). But when you give, let's say an Y, your while loop will stop but Y will not be consumed. Therefore, this char will be consumed in the next instruction, i.e. in String choice = scanner.next(); (if you print variable choice you will see it has an Y).
After this, we go to the next iteration. Because there are no input to be consumed, scanner.hasNext("[YyNn]") will be false. But your while loop condition is !scanner.hasNext("[YyNn]"), which give us a true and enters inside the loop. Inside the loop we have the instruction scanner.next(). Since there are no input to be consumed, BOOM, you get a java.util.NoSuchElementException, which says the following:
Thrown by the nextElement method of an Enumeration to indicate that there are no more elements in the enumeration.
Other of your problems is in your scanner position. At each iteration you are initializing a new instance and closing it. You could just move the scanner initialization and its closure outside the loops.
Below I provide a similar sample code that does what you want with some explanations.
FULL CODE
public static void main(String[] args) {
boolean run = true;
Scanner scanner = new Scanner(System.in); // Init before loops
String userInput = ""; // tmp var that holds input
while (run) {
// do something
System.out.println("Another action? [Y/N]");
userInput = scanner.next(); // Read first time
// Run while user does not put Y || y || N || n
while (!userInput.matches("[YyNn]")){
System.out.println("Incorrect input");
userInput = scanner.next();
}
// User does not want more actions
if(userInput.matches("[Nn]")){
System.out.println("Do you wish to exit the program? [Y/Any other key]");
String choice = scanner.next();
// Stop the program
if (choice.toLowerCase().equals("y"))
run = false;
}
}
scanner.close(); // Close scanner outside
}
Hope it helped!

I think you should change some lines of code like this
Scanner scanner = new Scanner(System.in);
char choice = 'Y'
while(choice!='n'){
// do something
System.out.print("Another action? [Y/N]");
choice = scanner.nextLine().toLowerCase().charAt(0);
if(choice!='y' || choice!='n'){
continue;
}
}
scanner.close();

If you call the scanner.close() method ,System.in will be closed.
So Use this. Close the scanner outside the loop.
public static void main(String[] args) {
boolean run = true;
Scanner scanner = new Scanner(System.in);;
while(run){
// do something
System.out.println("Another action? [Y/N]");
while (!scanner.hasNext("[YyNn]")) {
System.out.println("Incorrect input");
scanner.next();
}
String choice = scanner.next();
if(choice.toLowerCase().equals("f"))
run = false;
//
}
scanner.close();
}
Output
Another action? [Y/N]
Y
Another action? [Y/N]
Y
Another action? [Y/N]
N
Another action? [Y/N]
N
Another action? [Y/N]
test
Incorrect input

This is the correct version of the same using Java8
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ScannerExample {
public static void main(String[] args) {
boolean run = true;
try (Scanner sc = new Scanner(System.in)) {
while (run) {
System.out.println("Another action? [Y/N]");
String option = sc.next();
Pattern patter = Pattern.compile("[YyNn]");
Matcher m = patter.matcher(option);
while (!m.matches()) {
System.out.println("Incorrect input");
option = sc.next();
m = patter.matcher(option);
}
option = sc.next();
if (option.toLowerCase().equals("f")) {
run = false;
}
}
} catch (Exception e) {
// TODO: handle exception
}
}
}
output:
Another action? [Y/N]
Y
N
Another action? [Y/N]
Y
N
Another action? [Y/N]
f
Incorrect input
Y
N
Another action? [Y/N]
f
Incorrect input
Y
f

First thing: You need to move both scanner initialization line and its close() method outside the loop.
Second thing: In the checking condition add fF to let your program exit loop if one of these letters are typed while (!scanner.hasNext("[YyNnFf]")).
public static void main(String[] args) {
boolean run = true;
Scanner scanner = new Scanner(System.in);
while (run) {
// do something
System.out.println("Another action? [Y/N]");
while (!scanner.hasNext("[YyNnFf]")) {
System.out.println("Incorrect input");
scanner.next();
}
String choice = scanner.next();
if (choice.toLowerCase().equals("f")) {
run = false;
}
}
scanner.close();
}

As many of the answers suggests, the problem is with the statement Scanner scanner = new Scanner(System.in);. Following is the corrected version using try-with-resources, a cleaner way to handle resources in Java:
boolean run = true;
try(Scanner scanner = new Scanner(System.in))
{
while (run)
{
System.out.println("Another action? [Y/N]");
while (!scanner.hasNext("[YyNnFf]")) {
System.out.println("Incorrect input");
scanner.next();
}
String choice = scanner.next();
if (choice.toLowerCase().equalsIgnoreCase("f"))
run = false;
}
}
You can see it working here.
NOTE: I have changed the pattern matching statement from [YyNn] to [YyNnFf] and choice.toLowerCase().equals("f") to choice.toLowerCase().equalsIgnoreCase("f"), because It seems a logical error. See if it is as per your need.

Related

How can I validate user input in Java

I am currently experimenting with Java, trying to get the user to input an integer. If the user doesn't enter an integer I want a message to appear saying "You need to enter an Integer: " with a completely new input field to the original one.
Code:
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner inputScanner = new Scanner(System.in);
int counter = 0;
boolean run = true;
int userInput = 0;
while (run) {
System.out.print("Enter an integer: ");
if (inputScanner.hasNextInt()) {
userInput = inputScanner.nextInt();
} else if (!inputScanner.hasNextInt()) {
while (!inputScanner.hasNextInt()) {
System.out.print("You need to enter an Integer: ");
userInput = inputScanner.nextInt();
}
}
System.out.println(userInput);
if (counter == 6) {
run = false;
}
counter++;
}
}
}
At the moment the code above gives an Exception error ("java.util.InputMismatchException"). I have tried to use a try/catch but this doesn't really work because I want the user to see the second message ("You need to enter an Integer") everytime they don't enter an integer and I don't want it to re-loop around the main run loop for the same reason. I'm sure there is a better way to do this, however I am not sure of it. Any help will be massively appreciated, thanks in advance.
In this case it would make more sense for the Scanner to use hasNextLine and then convert the String to an Integer. If that you could do something like this:
try {
new Integer(inputScanner.hasNextLine);
} catch (Exception e) {
System.out.println(“<error message>”)
}
In place of the if(inputScanner.hasNextInt()) due to the fact that the hasNextInt function will error out if there is not an Integer to be read.

How to repeat a question to a user until while loop condition is false?

I'm bulding a console application where I am trying to force a user to enter an int as a possible answer to a question otherwise the same question is repeated to the user.Thus, the user cannot move on without entering the proper data type.
below is my sample code.
Scanner scanner = new Scanner(System.in);
int userInput = 0;
do {
AskQuestion();
if(scanner.hasNextInt()) {
userInput = scanner.nextInt();
}
}
while(!scanner.hasNextInt()) ;
While I know this can be done in C#, I'm not exactly sure how to do it in java without getting stuck in an infinite loop. How do I get my code to do what I want to do? Please help!
You can use something like this. It'a a pretty simple flag combined with the use of the Scanner class.
boolean flag = false;
int val = 0;
while(!flag){
System.out.println("Something");
if(sc.hasNext()){
if(sc.hasNextInt()){
val = sc.nextInt();
flag = true;
}
else{
sc.next();
}
}
}
Try this:
Scanner scanner = new Scanner(System.in);
int userInput;
while(true) {
AskQuestion();
if (scanner.hasNextInt()) {
userInput = scanner.nextInt();
break;
}
scanner.next(); // consume non-int token
}
Another alternative which utilizes the Scanner#nextLine() method along with the String#matches() method and a small Regular Expression (RegEx) to ensure that the supplied string does indeed contain all numerical digits:
Scanner scanner = new Scanner(System.in);
String userInput = "";
int desiredINT = 0; // Default value.
while (desiredINT == 0) {
AskQuestion();
userInput = scanner.nextLine();
if (userInput.matches("\\d+")) {
desiredINT = Integer.parseInt(userInput);
if (desiredINT < 1 || desiredINT > 120) {
System.out.println("Invalid Input! The age supplied is not "
+ "likely! Enter a valid Age!");
desiredINT = 0;
}
}
else {
System.out.println("Invalid Input! You must supply an Integer "
+ "value! Try Again...");
}
}
System.out.println("Your age is: --> " + desiredINT);
And the AskQuestion() method:
private void AskQuestion() {
System.out.println("How old are you?");
}
This is nice and short one
Scanner scanner = new Scanner(System.in);
do askQuestion();
while(!scanner.nextLine().trim().matches("[\\d]+"));
Tell me if you like it
Note it just tell you if number was an int , and keeps repeating if not, but doesn't give you that int back , tell me if you need that, i shall find a way
My solution might be a bit bloated, but I hope it's nice and clear what's going on. Please do let me know how it can be simplified!
import java.util.Scanner; // Import the Scanner class
class Main {public static void main(String[] args) {
Scanner myObj = new Scanner(System.in); // Create a Scanner object
String unit;
// unit selector
while (true) {
System.out.println("Did you measure ion feet or meters? Type 'meters' or 'feet': ");
String isUnit = myObj.nextLine();
if (isUnit.equals("feet") || (isUnit.equals("meters"))) {
unit = isUnit;
break;
} else {
System.out.println("Please enter either 'meters' or 'feet'.");
}
}
System.out.println("Use selected " + unit);
}

Java won't respond to my input

I'm budding into java and I've been trying to write this basic program where it asks you a yes or no question, you give it an answer and then it does something based off that answer. currently my code is this.
import java.util.Scanner;
public class Main {
public static void main(String args[])
{
Scanner inputvar = new Scanner (System.in);
String yes, no;
System.out.println("Enter yes or no");
yes = inputvar.nextLine();
no = inputvar.nextLine();
if (inputvar.equals(yes))
{
System.out.println("You said yes!");
}
else if (inputvar.equals(no)){
System.out.println("You said no");
}
}
}
I don't get any errors when compiling but when I run the program It doesn't reply when I put anything in. It allows me to enter two lines of text then it terminates.
Your code yes, no variables are not correct, you invoke nextLine() twice in your code, that's why you are asked to enter inputs twice.
yes = inputvar.nextLine();
no = inputvar.nextLine();
inputvar is a Scanner instance, not a String object, you cannot try
inputvar.equals(yes)
You should only define:
String myInput = inputvar.nextLine();
and checks
if (myInput.equals("yes")){
//do some stuff
}else if(myInput.equals("no")){
//do other stuff
}
Scanner inputvar = new Scanner (System.in);
String yes, no;
System.out.println("Enter yes or no");
yes = inputvar.nextLine(); // You enter the first line
no = inputvar.nextLine(); // You enter the second line
if (inputvar.equals(yes)) // You try to compare an instance of
// Scanner with the firstline (not equal)
{
System.out.println("You said yes!");
}
else if (inputvar.equals(no)){ // You try to compare an instance of
// Scanner with the firstline (not equal)
System.out.println("You said no");
}
// You terminate the program
You should do something like:
String yes = "yes";
String no = "no";
String input = inputvar.nextLine();
if(yes.equals(input)) { [...]
You should change your code to this
Scanner inputvar = new Scanner (System.in);
String input;
System.out.println("Enter yes or no");
input = inputvar.nextLine();
if (input.equals(yes))
{
System.out.println("You said yes!");
}
else if (input.equals(no)){
System.out.println("You said no");
}
Hope this helps and best of luck.

How to make a scanner be able to take in both an INT and String. Java

I had a bit of a hard time figuring this part out for a school project of mine.
So looking for a bit of clarification.
Generally, the user had to input a number (column) to insert a game piece.
However, if the user were to enter "q" the program would close down.
We were pointed into the direction of using "parseInt", however i am looking for a bit of clarification as to how this works?
while(response.equalsIgnoreCase("q"));
{
System.out.println("Do you want to play again?");
response = scan.next();
}
System.out.println("Do you want to play again?");
response = scan.next(); // this revisits the while loop that
// prompted the player to play.
import java.util.Scanner;
public class ScanInteger {
public static void main(String...args)throws Throwable {
int num = 0; String s= null;
System.out.print("Please enter a number : ");
Scanner sc = new Scanner(System.in);
do{
try{
s = sc.next();
num= Integer.parseInt(s);
System.out.println("You have entered: "+num+" enter again : ");
}catch(NumberFormatException e){
if(!s.equalsIgnoreCase("q"))
System.out.println("Please enter q to quit else try again ==> ");
}
}while(!s.equalsIgnoreCase("q"));
sc.close();
}
}
See http://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html#parseInt(java.lang.String)
public static int parseInt(String s)
throws NumberFormatException
You want to apply a try-catch block around the Integer.parseInt(userInput) call to catch a NumberFormatException
In the catch body, you can set a flag that the input was invalid. Put the whole thing in a while loop based on the boolean isInputIsValid.
boolean isValidNumber = false, wantsToQuit = false;
while (!isValidNumber) {
// Ask user for a value any way you want and save it to userInput
String userInput = "";
try {
Integer.parseInt(userInput);
isValidNumber = true;
} catch (NumberFormatException e) {
isValidNumber = false;
if (userInput.equals("q")) {
wantsToQuit = true;
break;
}
}
}
wantsToQuit is not a necessary variable, just showing what the purpose of that section is

assistance with looping code in java

I need help with looping my code in Java. So far I have:
import java.util.Scanner;
public class chara{
public static void main(String[]args){
int count = 0;
Scanner input = new Scanner(System.in);
System.out.println("Input a string");
String user=input.nextLine();
if(user.length()<7)
{
return;
}
else
{
}
System.out.println("Now input a letter to be replaced");
String letter = input.next();
if(letter.length()!=1)
{
return;
}
else
{
}
String user2 = user.replace(letter, "-");
String user3 = user.replace(letter, "");
count += (user.length() - user3.length());
System.out.println(user2);
System.out.println(user3);
System.out.println("#"+letter+"'s: "+count);
}
}
The code does everything I want it to except that when the string condition is not met (user<7, letter!=1) the program terminates and what I need it to do is ask the question again. Does anyone know how I can achieve this?
You need to put your looping code in method that can be called, then when the conidtion is not met you can go back to your question, and depending on that condidtion, quit the program, or call the loop method.
You just need a loop with a break condition, this should do it for you:
Scanner input = new Scanner(System.in);
System.out.println("Input a string");
String user=input.nextLine();
while (true)
{
if(user.length() <7 ) {break;}
input = new Scanner(System.in);
System.out.println("Too long, input a string < 7");
user=input.nextLine();
}
if(user.length()<7)......
A simple way would be to wrap your main logic within a loop with a boolean condition. This condition stays true when there is an "error" in the input. The condition is then false when the user proceeds as wanted.
Your code would look as so :
import java.util.Scanner;
public class Tester{
public static void main(String[]args){
int count = 0;
boolean keepGoing = true;
Scanner input = new Scanner(System.in);
while(keepGoing) {
System.out.println("Input a string");
String user=input.nextLine();
if(user.length()<7)
{
keepGoing = true;
//enter an error message here
}
else
{
System.out.println("Now input a letter to be replaced");
String letter = input.next();
if(letter.length()!=1)
{
keepGoing = true;
//enter an error message here
}
else
{
String user2 = user.replace(letter, "-");
String user3 = user.replace(letter, "");
count += (user.length() - user3.length());
System.out.println(user2);
System.out.println(user3);
System.out.println("#"+letter+"'s: "+count);
keepGoing = false;
}
}
}
input.close(); //Close resources
}
}
Unrelated
The convention is that class names start with a capital letter. In your case your class should be Chara, not chara.
Also, when opening resources make sure you close them. This is to avoid having resources leaked. Some IDEs will tell you something like this Resource leak: 'input' is never closed. It's a good idea to use a good IDE to help you with potential problems like this one.

Categories