Simple Do-while loop in Java - java

I want to run a loop and continue to accept a string input until "x" is pressed. I'm trying following do-while loop, but it doesn't get in the loop, it runs only once.
Scanner sc = new Scanner(System.in);
String name;
do {
System.out.print("Enter name or 'x' to quit: ");
name = sc.next();
if (name.equals("x")) {
break;
}
System.out.printf("The name is %s", name);
} while (name.equals("x"));

You need to remove if condition so that it doesn't break out of the loop early and modify the break condition, e.g.:
Scanner sc = new Scanner(System.in);
String name;
do {
System.out.print("Enter name or 'x' to quit: ");
name = sc.next();
System.out.printf("The name is %s", name);
} while (!name.equals("x"));

It continues looping when "x" is pressed. So you did the exact opposite.
Add an exclamation mark to negate your while condition:
while (!name.equals("x"))

I might be missing something, but it seems like your code contradicts itself.
You read user input and then check if it equals to x and breaks the loop in that case. If it does not, you continue until the while statement, where x gets checked again for the same condition.
So in summary, you break the loop for the same condition you have for it to run.
You might want to try, changing your condition in the while statement to
while (!name.equals("x"))

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...

hasNextDouble(), my program stops without crashing and without looping

My program seems stuck in the middle of my while loop, without crashing and without looping infinitely. It just stops.
The loop runs for as many input as the user provides, but then does not move on the the next line of code.
It is my first time using the hasNextDouble() in java. Am I doing it right?
Here is the while loop in question:
System.out.print("Grades (separated by a space)");
while(in.hasNextDouble())
{
student1.addGrade(in.nextDouble());
}
And here is a little bit more of my code:
Scanner in = new Scanner(System.in);
String input = "";
Student student1 = new Student();
GradeBook book = new GradeBook();
// Sets the name of the first student
System.out.print("Name: ");
input = in.nextLine();
student1.setNames(input);
// Sets the grades of the first student
System.out.print("Grades (separated by a space)");
while(in.hasNextDouble()){
student1.addGrade(in.nextDouble());
}
// Put the student into the GradeBook
book.addStudent(student1);
// Prints the report
System.out.print(book.reportGrades());
You state you want space separated input, in a single line. I would suggest taking the input as a String, and then splitting it up, like
Scanner in = new Scanner(System.in);
String line = in.nextLine();
for(String s : line.split(" ")){
student1.addGrade(Double.parseDouble(s)); //gives exception if value is not double
}
Scanner.hasNextDouble will continue to return true, until you enter a non-Double value.
With hasNext() you check if there is anything, then with hasNextDouble() check if the next input can be cast to double. You read the value with next(), but the value is still a string, so you need to parse it to double.
Also, you need a way to get out of the loop with break when input is no longer a number.
while (in.hasNext()) {
if (in.hasNextDouble()) {
student1.add(Double.parseDouble(in.next()));
} else {
break;
}
}

How to fix my Java code for validating variables?

I'm currently doing a project in my computer science class and we are suppose to validate each character of a variable to see if it is legal or not. If it starts with a number it's illegal. If it starts with a special character it's legal but bad style. If it has a space it is again illegal. I'll post my current code now:
import java.util.Scanner;
public class classOfValidation {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String theVariable = null;
System.out.println("This program checks the validity of variables");
System.out.println("Please enter a variable (or press 'q' to quit");
theVariable = scan.nextLine();
do {
System.out.println("The variable is illegal");
theVariable = scan.nextLine();
} while (theVariable.startsWith("[0123456789]"));
do {
System.out.println("The variable is illegal");
theVariable = scan.nextLine();
} while (theVariable.contains("[ ]"));
do {
System.out.println("The variable is legal, but has bad style");
theVariable = scan.nextLine();
} while (theVariable.startsWith("[!##$%^&*]"));
}
}
If you couldn't already tell i'm new to programming and as confused as i possibly could be. If you have any advice or anything else you need me to explain then please leave a comment. Thanks everyone
You can use the single regex to validate your input via String#matches() method. But as for the example you've provided, you should use while loop, but not do-while, because in do while case, you are always running it's body once befor condition checked. So, you better do it like:
theVariable = scan.nextLine();
while (theVariable.startsWith("[0123456789]")) {
System.out.println("The variable is illegal");
theVariable = scan.nextLine();
}
while (theVariable.contains("[ ]")) {
System.out.println("The variable is illegal");
theVariable = scan.nextLine();
}
while (theVariable.startsWith("[!##$%^&*]")) {
System.out.println("The variable is legal, but has bad style");
theVariable = scan.nextLine();
}
The second, in your solution, you are using String.startsWith() method and passing into it some regex. Take a look at javadoc for this method. It's said there:
Tests if this string starts with the specified prefix.
That means, that this method doesn't support regexes, but simply checks whether the string starts with the passed string. So, your conditions seems, never to become true. I don't think, someone will input the [0123456789] or [!##$%^&*].
One more, any conditions are checked once, but after that user can modify the input and the previewsly passed condition will not be checked again. Seems, it's better to run into infinite loop with continue and break in some conditions, like:
//infinit loop, until user enter the `q` or the input is correct
while (true) {
//read the input
theVariable = scan.nextLine();
//chtck, whether is `quit` command entered
if ("q".equals(theVariable)) {
break;
}
//if string starts with digit or contains some whitespaces
//then print alert and let the user to
//modify the input in a new iteration
if (theVariable.matches("^\d+.*|.*\s+.*")) {
System.out.println("The variable is illegal");
continue;
}
//if string contains some special characters print alert
//and let the user to modify the input in a new iteration
if (theVariable.matches("^[!##$%^&*].*")) {
System.out.println("The variable is legal, but has bad style");
continue;
}
//if all the conditions checked, then break the loop
break;
}
I think the best way if you are use regex.
Here is an answer how to do that.

Why is my message printing twice when I break out of the inner if?

I am having a little problem with my code. Compiling and running works well, however, when I attempt to break out of the inner loop,
System.out.println("Type which category you want to add to.");
System.out.println("Homework, Classwork, Labs, Test, Quizzes, Midterm, Final");
The code above is printing twice to the terminal when I only want it to print once.
I have a feeling that is a simple mistake with the way my brackets are aligned but I am having difficulty with figuring out how to do it. Any help would be greatly appreciated!
import java.util.Scanner;
public class GetGrade {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
final int MAX = 15;
int[] homework = new int[MAX];
int[] classwork = new int[MAX];
int[] lab = new int[MAX];
int[] test = new int[MAX];
int[] quizzes = new int[MAX];
int[] midterm = new int[MAX];
int[] fin = new int[MAX];
int hwCount, clCount, labCount, testCount, quizCount, midCount, finCount;
double hwTotal, clTotal, labTotal, testTotal, quizTotal, midTotal, finTotal;
double grade = 0;
String selection = "";
System.out.println();
System.out.println("Welcome to GetGrade!");
System.out.println();
while (true) {
System.out.println("Type which category you want to add to.");
System.out.println("Homework, Classwork, Labs, Test, Quizzes, Midterm, Final");
selection = input.nextLine();
if (selection.equals("homework")) {
System.out.print("What percentange of your grade is homework? > ");
double hwPercent = input.nextDouble();
System.out.println("Now begin typing your grades. When you are finished, type -1.");
for (int i = 0; i < homework.length; i++) {
homework[i] = input.nextInt();
hwTotal = homework[i] * hwPercent;
grade += hwTotal;
if (homework[i] == -1) break;
}
}
}
}
}
It's just as trivial as it seems:
The call to input.nextInt(); in your inner loop does not include the newline.
So you are breaking of the innerloop, receiving the next line which only contains the newline - character in input.nextLine(); which is the remaining input of your "-1\n" line and proceed with the main loop again as it does not match "homework".
Try setting the conditional variable in your while loop to an actual boolean rather than true.
Also, when you invoke "break", you are only breaking out of the for loop. If you reassign a boolean variable to false at this point, you would exit the while loop completely.
Just before while loop ends, add a "Do you want to continue? (Y/N)" functionality.
If user enters "N" or anything else, execute another break. And that break will make you get out of the while loop.
The simple way to get your code working is to change
selection = input.nextLine();
to
selection = input.next();
next() only reads in a string value (which is what you are actually doing in your code) instead of the newline character as Peter has suggested.
So the an extra iteration of the while does not take place when you read the newline character.
When you use a scanner to read a line from the keyboard, it reads everything up to and including the newline character the user types to submit their input. So for example:
Type which category you want to add to.
Homework, Classwork, Labs, Test, Quizzes, Midterm, Final
>
If you type "homework" and then ENTER, the actual input becomes "homework\n". input.nextLine() will scan the input until it encounters the first newline character, '\n', which it will consume and then it returns everything up to that point (i.e. "homework").
Your problem here is that input.nextInt() does NOT consume a newline character, and so there is still a newline character in the input buffer by the time your while loop starts another round.
Now begin typing your grades. When you are finished, type -1.
> ...
> -1
=> User input is "-1\n"
-------------------------------
// Meanwhile, back in the code...
for (int i=0;i<homework.length;i++) {
homework[i] = input.nextInt(); // <--- This call consumes "-1" but leaves '\n'
hwTotal = homework[i] * hwPercent;
grade += hwTotal;
if (homework[i] == -1) break;
}
That newline is consumed by the next call to input.nextLine(), leaving the input buffer empty.
while (true) {
System.out.println("Type which category you want to add to.");
System.out.println("Homework, Classwork, Labs, Test, Quizzes, Midterm, Final");
selection = input.nextLine(); // <--- This call consumes the leftover '\n' and returns the empty string
...
And because "" is not equal to "homework", the while loop goes around one more time, but this time the input buffer is empty, and so the call to input.nextLine() behaves as you would expect.
// selection is empty, so this condition fails and the program loops back around
if (selection.equals("homework")) {
...
There are two easy solutions to this problem. You can
Use Integer.parseInt(input.nextLine()) instead of input.nextInt()
Add an extra call to input.nextLine() at the end of your while loop to consume the final newline character
The first option is probably the most robust, and you get the added benefit of a run-time error being thrown if they do not give you a valid integer as input.

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();

Categories

Resources