user input within while loop - java

I was asked to run a loop that asks for user input, applies the change using the adjustPrice() method, print the new information after adjusting the price. and then finishes the loop when the user enters 0.
Right now it does all of the above, just doesn't ask for the user input again and ends with the printed new information. please help!
boolean done = false;
while (!done) {
System.out.print("Enter adjustment to price in percent (0 to quit): ");
double adjustment = in.nextDouble();
if (adjustment == 0) {
done = true;
}else{
swag.adjustPrice(adjustment);
System.out.println(swag.toString());
in.next();
}
}

You have in.next() at the end. This expects the user to input something before the loop will reset to the System.out line. Take out that line.

to allow user input using the end
else {
swag.adjustPrice(adjustment);
System.out.println(swag.toString());
in.next();
}
but beware that this method does not take keys as enter or space to
take into account these keys use.
else {
swag.adjustPrice(adjustment);
System.out.println(swag.toString());
System.in.read();
}

Related

Java Infinite loop

Can someone please advise why the inner loop of the code below will not exit?
I've added an inner loop to check if input from the user of of a particular value and if not prompts for the correct input. When debugging the code and passing in a value which should force the loop to end it doesn't although I can see the correct value in the variable:
while (finished.equalsIgnoreCase("n")) {
System.out.println("Enter a persons name");
names = in.nextLine();
writer.println(names);
System.out.println("Finished? (Y/N)");
finished = in.nextLine();
while( !finished.equalsIgnoreCase("y") || !finished.equalsIgnoreCase("n")) {
System.out.println("Invalid choice; (Y/N)");
finished = in.nextLine();
}
}
Every string is either not not equal to y or not equal to n. You probably meant to use the && operator:
while(!finished.equalsIgnoreCase("y") &&
!finished.equalsIgnoreCase("n")) {
// Code...

Recursion call in java causing incorrect behavior

I have a recursion call which is showing weird behavior.
public String recursionMethod() {
String repeatRun = null;
repeatRun = scanner.next();
if (!("Y".equals(repeatRun) || "N".equals(repeatRun))) {
System.out.println("Please enter the correct value. (Y/N)");
this.recursionMethod();
}
System.out.println("value of the entered variable->"+repeatRun);
return repeatRun;
}
When the method run for the first time, I enter value "no". As expected, it enters the if block and so it calls itself again asking to enter either "Y" or "N". This time, I enter "Y". It does not enter the if block again but the log prints like this.
Do you want to enter another directory? (Y/N)
no
Please enter the correct value. (Y/N)
Y
value of the entered variable->Y
value of the entered variable->no
This behavior is strange. Why is it picking the old value again? On running in debug mode it shows that after the control goes to the return line, it again goes to the line "this.recursionMethod()" which is inside the if block.
Please help me understand and also how to fix this so that my method does not return the previous value.
Try this :
public String recursionMethod() {
String repeatRun = null;
repeatRun = scanner.next();
if (!("Y".equals(repeatRun) || "N".equals(repeatRun))) {
System.out.println("Please enter the correct value. (Y/N)");
return this.recursionMethod();
}
System.out.println("value of the entered variable->"+repeatRun);
return repeatRun;
}
You forgot the return in the if block where you make the recursive call.
When you check if the typed value is Y or N, if the value is wrong, you ask the user to type again a new value, making a recursive call. However, when this recurisve call ends, the method continues till the end, printing the value typed first. The right implementation should be this:
if (!("Y".equals(repeatRun) || "N".equals(repeatRun))) {
System.out.println("Please enter the correct value. (Y/N)");
repeatRun = this.recursionMethod();
}
else {
System.out.println("value of the entered variable->"+repeatRun);
}
return repeatRun;

How to ask user if he/she wants to quit the program and print out the thank you message in Java

I am taking the first Java class and working on my second project. The project is about creating an program as a network of rooms on a virtual three-dimensional work area. Each room provides a virtual environment that together can be assemble into a simulated or virtual world.
Basically, the beginning of the program, I used while loop, and at the end I want to ask user if he/she wants to quit the program, and print a thank you message. However, the while loop does not work. My program quit no matter I entered y or n. Below is my codes.
import java.util.Scanner;
public class Project
{
public static void main(String[] args)
{
Map map = new Map();
int floor = 0;
int row = 0;
int col = 0;
String input = " ";
Scanner scan = new Scanner(System.in);
// Begin user dialog. Welcome message
System.out.println("Welcome to the L.A Underground! (Verson 1.1)");
System.out.println();
String choice = "y";
while(!input.equalsIgnoreCase("quit"))
{
input = scan.nextLine().toLowerCase();
// My codes are here
if (input.equals("south")
{statement}
else
System.out.println("You can't go that way.");
else if (input.equals("quit"))
{ // See if user wants to continue
System.out.println("Do you wish to leave the Underground (Y/N)? >");
choice = scan.nextLine();
System.out.println();
}
// if user enters other words than quit
else
System.out.println("I don't recognize the word '" + input +"'");
}
System.out.println("Thank you for visiting L.A Underground.");
}
}
When I typed "quit" the console printed the message: "Do you wish to leave the Underground? (Y/N)? >". I tried Y/N (y/n) the program terminated. Any help is appreciated. Thank you.
Updated: Sorry for the confusion. What I wanted the program to run is when the user types "quit", the message will print out "Do you wish to leave the Underground (Y/N)?>?" , and if the user types "hello", the message will be "I don't understand the word 'hello'". And when the user type y, the program will quit, otherwise (type n), the program will start over again.
Ask for user input inside of your loop. If input.equalsIgnoreCase("quit"), then prompt the user an "are you sure" message. If the input.equalsIgnoreCase("y"), then break the loop, otherwise, keep going.
Scanner scan = new Scanner(System.in);
String input;
// Begin user dialog. Welcome message
System.out.println("Welcome to the L.A Underground! (Verson 1.1)");
System.out.println();
while (true) {
input = scan.nextLine();
if (input.equalsIgnoreCase("quit")) {
System.out.print("Do you wish to leave the Underground (Y/N)? >");
if (scan.nextLine().equals("y")) {
break;
}
}
// input wasn't "quit", so do other stuff here
}
System.out.println("Thank you for visiting L.A Underground.");
Your code loops until it gets "quit" ... then asks for "yes/no" ... then simply exits, regardless.
You need to change your loop, so that it includes BOTH "MY CODES HERE" AND the "quit y/n" check.
EXAMPLE:
...
boolean done = false;
while(!done) {
//MY CODES ARE HERE
if (input.equalsIgnoreCase("quit") && getYesNo ()) == 'y') {
done = true;
}
}
"getYesNo()" is a method you write. For example:
char getYesNo () {
System.out.print("Do you wish to leave the Underground (Y/N)? >");
String line = scan.nextLine();
return line.charAt(0);
}
In the code you've posted, your loop is being controlled by the condition !input.equalsIgnoreCase("quit"). That is, if input is "quit", the loop is terminated.
But the following block is executed only if input is "quit":
if (input.equals("quit"))
{
// See if user wants to continue
System.out.println("Do you wish to leave the Underground (Y/N)? >");
choice = scan.nextLine();
System.out.println();
}
So if this block is executed, !input.equalsIgnoreCase("quit") evaluates to false and the loop is terminated. And that's not what you want.
Now that you know what's wrong, fixing it is easy. Check the value of choice in the above if block: if choice is not yes, don't quit i.e. reset input to a default value.
I've pasted the working code here on pastebin.

Java .nextLine() repeats line

Everything of my guessing game is alright, but when it gets to the part of asking the user if he/she wants to play again, it repeats the question twice. However I found out that if I change the input method from nextLine() to next(), it doesn't repeat the question. Why is that?
Here is the input and output:
I'm guessing a number between 1-10
What is your guess? 5
You were wrong. It was 3
Do you want to play again? (Y/N) Do you want to play again? (Y/N) n
Here is the code:(It is in Java)
The last do while loop block is the part where it asks the user if he/she wants to play again.
import java.util.Scanner;
public class GuessingGame
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
boolean keepPlaying = true;
System.out.println("Welcome to the Guessing Game!");
while (keepPlaying) {
boolean validInput = true;
int guess, number;
String answer;
number = (int) (Math.random() * 10) + 1;
System.out.println("I'm guessing a number between 1-10");
System.out.print("What is your guess? ");
do {
validInput = true;
guess = input.nextInt();
if (guess < 1 || guess > 10) {
validInput = false;
System.out.print("That is not a valid input, " +
"guess again: ");
}
} while(!validInput);
if (guess == number)
System.out.println("You guessed correct!");
if (guess != number)
System.out.println("You were wrong. It was " + number);
do {
validInput = true;
System.out.print("Do you want to play again? (Y/N) ");
answer = input.nextLine();
if (answer.equalsIgnoreCase("y"))
keepPlaying = true;
else if (answer.equalsIgnoreCase("n"))
keepPlaying = false;
else
validInput = false;
} while (!validInput);
}
}
}
In your do while loop, you don't want the nextLine(), you just want next().
So change this:
answer = input.nextLine();
to this:
answer = input.next();
Note, as others have suggested, you could convert this to a while loop. The reason for this is that do while loops are used when you need to execute a loop at least once, but you don't know how often you need to execute it. Whilst it's certainly doable in this case, something like this would suffice:
System.out.println("Do you want to play again? (Y/N) ");
answer = input.next();
while (!answer.equalsIgnoreCase("y") && !answer.equalsIgnoreCase("n")) {
System.out.println("That is not valid input. Please enter again");
answer = input.next();
}
if (answer.equalsIgnoreCase("n"))
keepPlaying = false;
The while loop keeps looping as long as "y" or "n" (ignoring case) isn't entered. As soon as it is, the loop ends. The if conditional changes the keepPlaying value if necessary, otherwise nothing happens and your outer while loop executes again (thus restarting the program).
Edit: This explains WHY your original code didn't work
I should add, the reason your original statement didn't work was because of your first do while loop. In it, you use:
guess = input.nextInt();
This reads the number off the line, but not the return of the line, meaning when you use:
answer = input.nextLine();
It immediately detects the leftover carriage from the nextInt() statement. If you don't want to use my solution of reading just next() you could swallow that leftover by doing this:
guess = input.nextInt();
input.nextLine();
rest of code as normal...
The problem really lies in a completely different segment of code. When in the previous loop guess = input.nextInt(); is executed, it leaves a newline in the input. Then, when answer = input.nextLine(); is executed in the second loop, there already is a newline waiting to be read and it returns an empty String, which activates the final else and validInput = false; is executed, to repeat the loop (and the question).
One solution is to add an input.nextLine(); before the second loop. Another is to read guess with nextLine() and then parse it into an int. But this complicates things as the input could not be a correct int. On a second thought, the code already presents this issue. Try entering a non-numeric response. So, define a function
public static int safeParseInt(String str) {
int result;
try {
result= Integer.parseInt(str) ;
} catch(NumberFormatException ex) {
result= -1 ;
}
return result ;
}
And then replace your first loop with:
do {
validInput= true ;
int guess= safeParseInt( input.nextLine() ) ;
if( guess < 1 || guess > 10 ) {
validInput= false ;
System.out.print("That is not a valid input, guess again: ");
}
} while( !validInput );
PS: I don't see any problem with do-while loops. They are part of the language, and the syntax clearly indicates that the condition is evaluated after the body is executed at least one time. We don't need to remove useful parts of the language (at least from practice) just because others could not know them. On the contrary: if we do use them, they will get better known!
validInput = false;
do {
System.out.print("Do you want to play again? (Y/N) ");
answer = input.next();
if(answer.equalsIgnoreCase("y")){
keepPlaying = true;
validInput = true;
} else if(answer.equalsIgnoreCase("n")) {
keepPlaying = false;
validInput = true;
}
} while(!validInput);
I changed the coding style as I find this way more readable.
Your problem is that nextInt will stop as soon as the int ends, but leaves the newline in the input buffer. To make your code correctly read the answer, you'd have to enter it on the same line as your guess, like 5SpaceYReturn.
To make it behave more than one would expect, ignore the first nextLine result if it contains only whitespace, and just call nextLine again in that case without printing a message.
I believe the output of input.nextLine() will include the newline character at the end of the line, whereas input.next() will not (but the Scanner will stay on the same line). This means the output is never equal to "y" or "n". Try trimming the result:
answer = input.nextLine().trim();

Java: Infinite loop using Scanner in.hasNextInt()

I am using the following code:
while (invalidInput)
{
// ask the user to specify a number to update the times by
System.out.print("Specify an integer between 0 and 5: ");
if (in.hasNextInt())
{
// get the update value
updateValue = in.nextInt();
// check to see if it was within range
if (updateValue >= 0 && updateValue <= 5)
{
invalidInput = false;
}
else
{
System.out.println("You have not entered a number between 0 and 5. Try again.");
}
} else
{
System.out.println("You have entered an invalid input. Try again.");
}
}
However, if I enter a 'w' it will tell me "You have entered invalid input. Try Again." and then it will go into an infinite loop showing the text "Specify an integer between 0 and 5: You have entered an invalid input. Try again."
Why is this happening? Isn't the program supposed to wait for the user to input and press enter each time it reaches the statement:
if (in.hasNextInt())
In your last else block, you need to clear the 'w' or other invalid input from the Scanner. You can do this by calling next() on the Scanner and ignoring its return value to throw away that invalid input, as follows:
else
{
System.out.println("You have entered an invalid input. Try again.");
in.next();
}
The problem was that you did not advance the Scanner past the problematic input. From hasNextInt() documentation:
Returns true if the next token in this scanner's input can be interpreted as an int value in the default radix using the nextInt() method. The scanner does not advance past any input.
This is true of all hasNextXXX() methods: they return true or false, without advancing the Scanner.
Here's a snippet to illustrate the problem:
String input = "1 2 3 oops 4 5 6";
Scanner sc = new Scanner(input);
while (sc.hasNext()) {
if (sc.hasNextInt()) {
int num = sc.nextInt();
System.out.println("Got " + num);
} else {
System.out.println("int, please!");
//sc.next(); // uncomment to fix!
}
}
You will find that this program will go into an infinite loop, asking int, please! repeatedly.
If you uncomment the sc.next() statement, then it will make the Scanner go past the token that fails hasNextInt(). The program would then print:
Got 1
Got 2
Got 3
int, please!
Got 4
Got 5
Got 6
The fact that a failed hasNextXXX() check doesn't skip the input is intentional: it allows you to perform additional checks on that token if necessary. Here's an example to illustrate:
String input = " 1 true foo 2 false bar 3 ";
Scanner sc = new Scanner(input);
while (sc.hasNext()) {
if (sc.hasNextInt()) {
System.out.println("(int) " + sc.nextInt());
} else if (sc.hasNextBoolean()) {
System.out.println("(boolean) " + sc.nextBoolean());
} else {
System.out.println(sc.next());
}
}
If you run this program, it will output the following:
(int) 1
(boolean) true
foo
(int) 2
(boolean) false
bar
(int) 3
This statement by Ben S. about the non-blocking call is false:
Also, hasNextInt() does not block. It's the non-blocking check to see if a future next call could get input without blocking.
...although I do recognize that the documentation can easily be misread to give this opinion, and the name itself implies it is to be used for this purpose. The relevant quote, with emphasis added:
The next() and hasNext() methods and their primitive-type companion methods (such as nextInt() and hasNextInt()) first skip any input that matches the delimiter pattern, and then attempt to return the next token. Both hasNext and next methods may block waiting for further input. Whether a hasNext method blocks has no connection to whether or not its associated next method will block.
It is a subtle point, to be sure. Either saying "Both the hasNext and next methods", or "Both hasnext() and next()" would have implied that the companion methods would act differently. But seeing as they conform to the same naming convention (and the documentation, of course), it's reasonable to expect they act the same, and hasNext()
clearly says that it can block.
Meta note: this should probably be a comment to the incorrect post, but it seems that as a new user I can only post this answer (or edit the wiki which seems to be preferred for sytlistic changes, not those of substance).
Flag variables are too error prone to use. Use explicit loop control with comments instead. Also, hasNextInt() does not block. It's the non-blocking check to see if a future next call could get input without blocking. If you want to block, use the nextInt() method.
// Scanner that will read the integer
final Scanner in = new Scanner(System.in);
int inputInt;
do { // Loop until we have correct input
System.out.print("Specify an integer between 0 and 5: ");
try {
inputInt = in.nextInt(); // Blocks for user input
if (inputInt >= 0 && inputInt <= 5) {
break; // Got valid input, stop looping
} else {
System.out.println("You have not entered a number between 0 and 5. Try again.");
continue; // restart loop, wrong number
}
} catch (final InputMismatchException e) {
System.out.println("You have entered an invalid input. Try again.");
in.next(); // discard non-int input
continue; // restart loop, didn't get an integer input
}
} while (true);

Categories

Resources