nextLine() issues with Scanner - java

I have two do-while loops for making custom input validations. The problem is that it automatically enters in the next do-while loop. I have to put a new nextLine() after I correctly insert the name: name = scanner.nextLine();
I am aware of the "glitch" of nextInt() when the cursor stays there and you have to call nextLine() for it to continue. Source: https://www.geeksforgeeks.org/why-is-scanner-skipping-nextline-after-use-of-other-next-functions/
But this is not the case. I am clearly missing something...
String name = "";
boolean flag_name= false;
do{
System.out.print("Name: ");
if(scanner.hasNextInt()){
System.out.println(scanner.nextInt() + " That's not a valid name...\n");
scanner.nextLine();
}else{
name = scanner.nextLine();
flag_name = true;
}
}while(!flag_name);
int age = 0;
boolean good_age = false;
do {
System.out.print("Age: ");
if (!scanner.hasNextInt()){
System.out.println("That's not a valid age.");
}else if(scanner.nextInt() <= 3 || scanner.nextInt() >= 125) {
System.out.println("You must be over 3yo.");
scanner.nextLine();
}else{
age = Integer.parseInt(scanner.nextLine());
good_age = true;
}
}while (!good_age);
Output:
Name: mark
Age: 'mark' That's not a valid age.
Age:

I finally figured out that I already came with a messed up scanner. On the previous step I had an unattended scanner.next(); which made everything that comes after it behaving erratically.
System.out.print("Insert an option (1,2,3): ");
input = scanner.next();
// changed:
input = scanner.nextLine();
That fixed the scanner for the subsequent steps.
I also applied the logic mentioned by #AppleCiderGuy and fixed my second do-while loop.
Final code:
String name = "";
boolean flag_name= false;
do{
System.out.print("Name: ");
if(scanner.hasNextInt()){
System.out.println("That's not a valid name...");
scanner.nextLine();
}else{
name = scanner.nextLine();
flag_name = true;
}
}while(!flag_name);
int age = 0;
boolean good_age = false;
do {
System.out.print("Age: ");
if (!scanner.hasNextInt()) {
System.out.println("That's not a valid age.");
scanner.nextLine();
}else{
age = Integer.parseInt(scanner.nextLine());
if(age <= 3 || age >= 125) {
System.out.println("You must be over 3yo.");
}else{
good_age = true;
}
}
}while (!good_age);
Lessons learned:
You will always need a scanner.nextLine(); for cleaning the scanner when incorrect inputs are reached. Otherwise the incorrect input will stay in the scanner and mess up the subsequent code.
When you use integers, even if correctly assigned to variables, you'll also need to clean the scanner. Is easier for me to use Integer.parseInt(scanner.nextLine()); instead.
Always try to evaluate variables instead of scanner.next* methods. Because the scanner will be waiting more inputs.
Thanks.

Related

Loop not breaking when using user input

public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Queue que = new Queue(50);
System.out.println("Noki's Calculator");
System.out.println("Choose an operation (*, /, +, -)");
String inputOp = input.nextLine();
System.out.println(" ");
System.out.println("Now please enter your numbers. When finished, simply press enter.");
boolean cont = true;
while(true){
System.out.print(" :: ");
String j = input.next();
if(j != null) {
int numb = Integer.parseInt(j);
que.insert(numb);
} else if (j==null) {
input.close();
break;
}
}
que.view(); // PROBLEM: never executes this line
}
My code won't break out of the while loop, instead still asks for user input. When I press enter, it doesn't print "::" again, but never executes que.view()
Use nextLine() instead of next() like below,
String j = input.nextLine();
According to your implementation 'j' will never be null. When you hit enter "" will be assigned to j. You may need to change your logic as follows; Use input.nextLine() instead of input.next()
if(!(j.isEmpty())) {
int numb = Integer.parseInt(j);
que.insert(numb);
} else {
input.close();
break;
}
input.next() does not return "null" when you just press "enter".
change
else if (j==null)
to
else if (j.equals(""))
Edit: this doesn't exactly answer the question but it has already been answered so i am leaving it as is.

Using java scanner to check two conditions while taking user input

I need to user to enter an int between 1 and 301.
I have this simple loop here to check for user input.
I just want a single number from the user, and if the user enters anything other than an int between 1 and 301, I want to display the print line and prompt the users to try again until they enter a valid input.
while (!sc.hasNextInt()) {
System.out.print("Invalid Input. Please enter a valid number between 1 and 301: ");
sc.next();
}
int numToCheck = sc.nextInt();
// do stuff with numToCheck
This checks that the input is an int, but I can't seem to find a way to give the int input a bound. I tried to assign the user input to a variable and then check the conditions input < 1 or input > 301, but I get InputMismatchException if user enters a letter. How should I store the user input? (I want to store it as an int to check the conditions, but can't do that since I don't know what the user will enter).
Perhaps there is a better design to accomplish all this. Those are welcomed too.
Thanks in advance.
You're not saving the value of the of the input. So your program is waiting on the user to enter a number each time it see "sc.nextInt()" Assign the input to a variable, and then check the condition.
EDIT: okay, I'll go the extra mile for you. See if this works.
***Accounted for the case where the user might enter a character instead of a number.
import java.util.*;
public class HelloWorld{
public static void main(String []args){
Scanner sc = new Scanner(System.in);
int input;
while (true){
if (sc.hasNextInt()){
input = sc.nextInt(); // Assign the next integer to a variable
if (input <= 301 && input >= 1){ // Check if integer meets condition
break; // Condition met, break out of loop
}
}else{
sc.next();
}
System.out.println("Invalid Input. Please enter a valid number between 1 and 301: ");
}
}
}
I ran this code, to see if it would show a better performance than yours.
Scanner sc = new Scanner(System.in);
boolean valid = true;
do {
if (!valid) {
System.out.print("Invalid Input. ");
}
System.out.print("Please enter a valid number between 1 and 301: ");
String input = sc.next();
try {
int value = Integer.parseInt(input);
valid = (value >= 1 && value <= 301);
} catch (NumberFormatException nfex) {
valid = false;
}
} while (!valid);
When the conversion to integer fails, the JVM hangs a little. I believe your problem has more to do with the try / catch mecanism that Scanner performs under the hood, than with design.
Assuming you want only 1 input from the user, try following simple code, which takes input from the user until user enters a valid input.
Scanner in = new Scanner(System.in);
int flag = 0,x=0;
while(flag == 0){
x = in.nextInt();
if(x<1 || x>301){
flag = 0;
System.out.println("Invalid Input.");
}
else{
flag = 1;
}
}
And if you want user to input more than 1 inputs (i.e 3 here), than set a counter that increases with every valid input of the user, as following:
Scanner in = new Scanner(System.in);
int flag = 0,x=0,count = 1;
while(flag == 0){
x = in.nextInt();
if(x<1 || x>301){
flag = 0;
System.out.println("Invalid Input.");
}
else{
//executes when input is valid
if(count == 3){
flag = 1;
}
count++;
}
}
Edit:
If you also want to check whether the input is Integer or not, than you have to add one extra condition in above code. And as you said you want only one input from user rather than 3, you have to change exit condition. Change code as following:
Scanner in = new Scanner(System.in);
int flag = 0,count = 1,x=0,flag1 = 0;
String y;
while(flag == 0){
y = in.next();
flag1 = 0;
try{
x = Integer.parseInt(y);
}
catch(NumberFormatException e){
flag1 = 1;
System.out.println("Invalid Input.");
}
if((x<1 || x>301)&&flag1 == 0){
flag = 0;
System.out.println("Invalid Input.");
}
else if(flag1 == 0){
//executes when input is valid
if(count == 1){ // put count == 3 if you want 3 inputs from user.
flag = 1;
}
count++;
}
}
Here we are taking the input as a String and than converting the String into the Integer by using Integer.parseInt(). If the String is not Integer, than it will throw the exception and we will continue the loop till the valid input is entered by the user.
Use DO WHILE for result
do{
System.out.print("value of x : " + x );
x++;
System.out.print("\n");
}while( x < 20 );
OK ?

Scanner loop doesn't cycle when hitting enter twice

boolean loop = false;
double numberOfStudents;
System.out.print("Enter a number: ");
if ((scnr.nextLine().trim().isEmpty()) ) {
loop = true;
}
while (loop) {
System.out.println("Enter a number");
if (scnr.hasNextDouble() ){
System.out.println("Loop has stopped");
numberOfStudents = scnr.nextDouble();
loop = false;
}
}
System.out.println("You're outside the loop!");
I'm trying to get the program to say "Enter a number" until the user has entered an actual number (no white spaces or letters or signs). When the user has entered a number, it sets numberOfStudents equal to that number and breaks out of the loop.
But if you hit enter twice, it doesn't iterate. It only displays "Enter a number" once.
What is wrong with the loop logic? Why isn't it looping until valid input is taken?
For the actual answer to your question of "Why doesn't 'Enter a number' display more than once?" see Tom's comment (update: Tom's answer).
I've rewritten your loop in a way which preserves your code, but also makes it a little easier to handle format exceptions (though at the risk of silently swallowing an exception -- should be acceptable for this use case).
Can be up to you to use this design, here is an SO post on why empty catch blocks can be a bad practice.
public static void main(String args[])
{
boolean loop = true;
double numberOfStudents;
Scanner scnr = new Scanner(System.in);
while(loop){
System.out.print("Enter a number: ");
String input = scnr.nextLine();
try{
numberOfStudents = Double.parseDouble(input);
loop = false;
}catch(NumberFormatException e){
}
}
System.out.println("You're outside the loop!");
}
Output:
Enter a number:
Enter a number:
Enter a number:
Enter a number: 50
You're outside the loop!
First of all: Since you're reading from System.in a call to the input stream will block until the user entered a valid token.
So let's check first scan using your scnr variable:
scnr.nextLine()
nextLine() reads everything til the next line delimiter. So if you just press return, then it will successfully read it and will perform the next stuff.
The next call is:
scnr.hasNextDouble()
This call expects a "real" token and ignores white spaces, except as a delimiter between tokens. So if you just press return again it doesn't actually read that input. So it still waits for more (for the first token). That is why it stucks in your loop and you won't get another "Enter a number" output.
You can fix that by either enter a real token, like a number, or by changing the loop like trobbins said.
I hope you now understand your program flow a bit more :).
While trobbins code basically solves your problem, it's bad practice to use exceptions for flow control.
I used a small regexp to check if the value is a number. But this example is not complete, it will still crash it the user enters for example two decimal points. So you would need to create a proper number check or just use integers where the check is much easier.
Someone in the comments pointed out that people may want to enter scientific notation like 5e10, so this would also be another case to check for. If this is just some code you need as a proof of concept or something quick and dirty, you can go with the exception handling method but in production code you should avoid using exceptions this way.
double numberOfStudents;
Scanner scnr = new Scanner(System.in);
while(true) {
System.out.print("Enter a number: ");
String input = scnr.nextLine().trim();
if(input.matches("^[0-9\\.]{1,}$")) {
System.out.println("Loop has stopped");
numberOfStudents = Double.parseDouble(input);
break;
}
}
System.out.println("You're outside the loop!");
The following code should help you:
double numberOfStudents = 0;
Scanner scnr = new Scanner(System.in);
boolean readValue = false; //Check if the valid input is received
boolean shouldAskForNumber = true; //Need to ask for number again? Case for Enter
do {
if (shouldAskForNumber) {
System.out.print("Enter a number:");
shouldAskForNumber = false;
}
if (scnr.hasNextDouble()) {
numberOfStudents = scnr.nextDouble();
readValue = true;
} else {
String token = scnr.next();
if (!"".equals(token.trim())) { //Check for Enter or space
shouldAskForNumber = true;
}
}
} while (!readValue);
System.out.printf("Value read is %.0f\n", numberOfStudents);
System.out.println("You're outside the loop!");
Update
Understood the following statement in question different way:
But if you hit enter twice, it doesn't loop back. It only displays
"Enter a number" once.
The code is set to print "Enter a number" only once if the user hits RETURN/ENTER or enters space character. You may remove the special check and use the code if needed.
import java.util.Scanner;
public class Testing {
public static boolean checkInt(String s)
{
try
{
Integer.parseInt(s);
return true;
} catch (NumberFormatException ex)
{
return false;
}
}
public static void main(String[] args) {
boolean loop = false;
double numberOfStudents;
Scanner scnr = new Scanner(System.in);
String input = "";
while (!(checkInt(input))) {
System.out.println("Enter a number");
input = scnr.nextLine();
}
numberOfStudents = Integer.parseInt(input);
System.out.println("Number of students: " + numberOfStudents );
}
}
//this code is working fine, if you want you check it out.
//In your code your taking another input if the first is an int/double; if the first input is not a number then you have mentioned to take input again..
Use a debugger to see what the code is actually doing. Here's a guide on debugging in Eclipse. After you have finished debugging your code, you will probably know what the problem is.
Below code will help you
boolean loop = true;
double numberOfStudents;
Scanner scnr = new Scanner(System.in);
System.out.print("Enter a number: ");
String input = scnr.nextLine();
while(!scnr.hasNextDouble()){
System.out.print("Enter a number: ");
try{
numberOfStudents = Double.parseDouble(input);
break;
}catch(NumberFormatException e){
}
input = scnr.nextLine();
}
System.out.println("You're outside the loop!");
The following code is working,
boolean loop = true;
double numberOfStudents;
Scanner scnr=new Scanner(System.in);
while(loop) {
System.out.println("Enter a number");
if ((scnr.nextLine().trim().isEmpty()) ) {
loop = true;
}
if (scnr.hasNextDouble() ){
System.out.println("Loop has stopped");
numberOfStudents = scnr.nextDouble();
loop = false;
}
}
System.out.println("You're outside the loop!");
The output is,
run:
Enter a number
hj
po
Enter a number
lhf
Enter a number
o
Enter a number
p
Enter a number
a
Enter a number
34
Loop has stopped
You're outside the loop!
You have to scan the next line if you want to get more values form the scanner again. The code should be like:
while (loop) {
System.out.println("Enter a number");
if(!(scnr.nextLine().trim().isEmpty())){
if (scnr.hasNextDouble() ){
System.out.println("Loop has stopped");
numberOfStudents = scnr.nextDouble();
loop = false;
}
}
}

How to stop a while loop if the user entered a special character

I'm writing a program in java and I'm getting some numbers from the user and I wanna say if the user entered '#' exit the while loop.
Any help is appreciated.
After you have gotten the user input, you can see if the input equals "#" like so:
input.equals("#");
You can get the user input using Scanner:
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
You can break from a loop by using break.
The while loop would look like this:
while (true) {
String input = scanner.nextLine();
if (input.equals("#")) {
break;
}
int number = Integer.parseInt(input);
// do stuff
}
To terminate any kind of loop, you use a break statement.
Scanner scanner = new Scanner(System.in);
String entrada="a";
while(!entrada.equals("#")){
System.out.println("hola");
entrada = scanner.nextLine();
}
Use break to stop your loop
string userInput = "sdfss £sdf";
while(true)
{
if(userInput.matches("[^ \w]"))
{
break;
}
}
I use while loop here to terminate if user enter -1 and get the total of user input numbers
while(true){
System.out.print("Input the number :");
int number = input.nextInt();
if(number >=0)
total += number;
if(number == -1)
break;
}
System.out.println("Total: " + total);

trying to get a positive integer output from a while loop with console.hasNextInt

Scanner console = new Scanner(System.in);
System.out.print("type your age: ");
while(!console.hasNextInt()|| console.nextInt() <= 0){
System.out.print("enter a valid age: ");
console.next();
}
int age = console.nextInt();
System.out.println(age);
when only using !console.hasNextInt(), it was able to print an integer. After adding console.nextInt() <= 0 and trying to get a positive number, weird things happened. Can anyone tell me where is wrong here and how I can fix this problem in this while loop? Thx.
Your question is discarding the user input to check if it's in the valid range. I believe you'll find the easiest answer is to default to an invalid input and continue checking until the input is valid. So, something like -
int age = -1;
while (age < 0) {
System.out.print("enter a valid age: ");
if (console.hasNextInt()) {
age = console.nextInt();
} else if (console.hasNext()) {
console.next();
} else {
System.err.println("Console closed. Exiting.");
System.exit(1);
}
}

Categories

Resources