Java: Why is my break statement not working? - java

This is probably a really simple mistake, but I'm a beginner with Java (and programming in general) and I was curious why the break statement won't work in my program.
public class ValidateStudentNumber
{
public static void main(String[] args)
{
Scanner kb = new Scanner(System.in);
do{
System.out.println("Enter a number: ");
String number = kb.next();
boolean valid = true;
for (int i = 0; i < number.length(); i++){
char c = number.charAt(i);
if(! Character.isDigit(c)) {
valid = false;
break;
}
if ( number.length() != 7) {
valid = false;
}
}
if (valid){
System.out.println("Valid");
}
else{
System.out.println("Invalid");
}
}
while (kb.hasNext());
System.out.println ("Program ending due to end-of-file");
}
}
What I want to accomplish with this code is that as soon as a letter is typed, the breaks out of the for statement and displays "Invalid", yet when I run the program and type something that is a non-digit, it doesn't leave the for loop and allows me to continue typing as usual.
Thank you for your time.

Break statement is working fine. Because it breaks the execution of for loop not for do-while loop. If you want to break do-while loop add break statement in not valid case else block.
public class A
{
public static void main(String[] args)
{
Scanner kb = new Scanner(System.in);
do{
System.out.println("Enter a number: ");
String number = kb.next();
boolean valid = true;
for (int i = 0; i < number.length(); i++){
char c = number.charAt(i);
if(! Character.isDigit(c)) {
valid = false;
break;
}
if ( number.length() != 7) {
valid = false;
}
}
if (valid){
System.out.println("Valid");
}
else{
System.out.println("Invalid");
break;
}
}
while (kb.hasNext());
System.out.println ("Program ending due to end-of-file");
}
}

What I want to accomplish with this code is that as soon as a letter is typed, the breaks out of the for statement and displays "Invalid"
If I understand your question correctly, you want your loop to break when you literally hit a non-digit key on the keyboard while entering a number.
From the Scanner java docs...
A scanning operation may block waiting for input.
What is probably happening is the console is blocked waiting for a carriage return (i.e. for you to hit Enter) to then process your input. So your program is not running for every key press, but is waiting for an entire line to be entered.
This is most apparent when you remove your do-while loop. When that is removed, you can see you can enter many characters until you hit Enter where your program determines if the string entered is valid then the program ends.
In summary, program not run for every key press, just when you hit "Enter".
Edit -
Here's a question (and possible solution to your problem) trying to figure out how to read one character at a time. Looks like you need to put your console in "raw" mode.
How to read a single char from the console in Java (as the user types it)?

You seem like you wanted to break out of the do/while not just the for loop. This can be accomplished by labeling your loops. So you could rewrite your code like:
class ValidateStudentNumber
{
public static void main(String[] args)
{
Scanner kb = new Scanner(System.in);
outer:do{
System.out.println("Enter a number: ");
String number = kb.next();
for (int i = 0; i < number.length(); i++){
char c = number.charAt(i);
if(! Character.isDigit(c) || number.length() != 7) {
System.out.println("Invalid");
break outer;
}
}//end of for loop
}while (kb.hasNext());
System.out.println ("Program ending due to end-of-file");
}
}

break will make you exit the loop containing the break statement i.e. in your code it will break you out of the for-loop. Then it keeps on waiting for input from scanner. As soon as you type something again, condition is true and then the loops re-runs.

Related

Java while loop is doing three iterations by default

I am beginning to learn Java and trying the while loop, I have written a simple program as a simple guessing game where the user tries to guess a letter between A and Z and the computer will print "correct" and repeats if the guessed letter is wrong, however, every time I try to run it the output is three iterations by default, I have tried to change the while loop to do-while and got the same output, I even added the int variable i as a counter to see if its really doing 3 iterations and the value of i always comes as 4 (3 wrong iterations when really it should be 1 plus one when I enter the correct answer).
Can you tell me what is the mistake I am doing?
class Guess {
public static void main (String[] args) throws java.io.IOException {
char answer = 'K', ignore, ch = 'a';
int i=0;
while (ch != 'K') {
System.out.println("I am Thinking of a letter between A and Z, can you guess it?");
ch = (char) System.in.read();
if (ch !='K')
System.out.println("Wrong ! please try again");
i++;
}
System.out.println("Correct!, you guessed after "+i+" attempts");
}
}
The issue is, when you press Enter after typing the character in the console, the loop is executing once for the entered character and again once for the newline which is 10.
So I just edited your code to skip the new line and wait for the next character to be entered, Also I moved the initial prompt outside of the loop. I hope this code would fix your issue:
public static void main(String[] args) throws IOException {
char answer = 'K', ignore, ch = 'a';
int i = 0;
System.out.println("I am Thinking of a letter between A and Z, can you guess it?");
while (ch != 'K') {
ch = (char) System.in.read();
if(!Character.isLetter(ch)){
continue;
}
System.out.println("Wrong ! please try again");
i++;
}
System.out.println("Correct!, you guessed after " + i + " attempts");
}
This is how it should look like.
Your code just missed the else block which is very necessary to break out of the loop,when the user guess the right character.I have added one.
class guess {
public static void main (String[] args) throws java.io.IOException {
char answer = 'K', ignore,ch='a';
int i=0;
while (ch != answer) {
System.out.println("I am Thinking of a letter between A and Z, can you guess it?");
ch = (char) System.in.read();
i++;
if (ch !=answer) {
System.out.println("Wrong ! please try again");
}
else{
System.out.println("Correct!, you guessed after "+i+" attempts");
break;
}
}
}
}
Hi there I got a tip for you.
I personally would use a Scanner instead of System.in.read. A Scanner is an object that reads an input.
To create one, simply tipe this:
Scanner sc = new Scanner(System.in); //System.in referes to a console input
To know what the user typed use sc.nextLine();, which returns, as I said, the input. However it returns a String, not a char. So, in this case, you also needed to change the type of 'ch'.
To compare the answers with the input you will need to used the method equals(). Basically, if two things are the same, it returns true.
That said, your code should look like this:
Scanner sc = new Scanner(System.in);
String answer = "K",ch;
int i=0;
boolean correct = false;
while (!correct) {
System.out.println("I am Thinking of a letter between A and Z, can you guess it?");
ch = sc.nextLine();
i++;
if (!ch.toUpperCase().equals(answer)) { // or ch.equals(answer) == false
System.out.println("Wrong ! please try again");
}else{ //if they are the same
correct = true; //the answer is correct so you can leave the while loop
System.out.println("Correct!, you guessed after "+i+" attempts");
}
}
sc.close(); //you should always close a scanner after you use it, but you can ignore this step for now
Note that I also used a method called toUpperCase(). That method transform all the characters of the string to upper case, so, even if you type "k" instead of "K" you would also quit the loop.

While loop is endless because the break point doesn't work

I'm trying out the code below but I'm getting a endless loop. The break point doesn't seem to help at all.
import java.util.Scanner;
public class Question2 {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
System.out.print("Enter ID Number: ");
int studentSn = keyboard.nextInt();
System.out.print("Enter your Marks: ");
int Score = keyboard.nextInt();
Scanner scan = new Scanner(System.in);
boolean stop = false;
String answer = "";
String Grade = "";
String msg = "";
int counter = 0;
while (!stop) {
if (Score < 50) {
Grade = "F";
} else if (Score <= 64) {
Grade = "P";
} else if (Score <= 74) {
Grade = "C";
} else if (Score <= 84) {
Grade = "D";
} else if (Score <= 100) {
Grade = "HD";
} else {
msg = "Invalid Input";
}
if (Grade != null) {
System.out.println("Student Serial Number: " + studentSn);
System.out.println("Your Grade is: " + Grade);
System.out.println("Do you want to continue (yes/no): " + answer);
} else {
System.out.println("Student Serial Number: " + studentSn);
System.out.println(msg);
System.out.println("Do you want to continue (yes/no): " + answer);
}
while (answer.equalsIgnoreCase("YES"));
{
counter++;
if (answer.equalsIgnoreCase("NO")) {
break;
}
}
}
}
}
There are multiple infinite loops in this scenario. With
while (!stop) {
// ...
}
you never set "stop" to true, meaning that the loop would end. The break statement in
while (answer.equalsIgnoreCase("YES"));
{
counter++;
if (answer.equalsIgnoreCase("NO")) {
break;
}
}
would only break out of that loop, not the !stop loop. If you wanted to break out of both loops, you'd need to do
MY_LABEL: while (!stop) {
// ...
while (answer.equalsIgnoreCase("YES"));
{
counter++;
if (answer.equalsIgnoreCase("NO")) {
break MY_LABEL;
}
}
or otherwise write stop = true; at some point. However, that is not the only endless loop in your code. In
while (answer.equalsIgnoreCase("YES"));
{
// loop body ^ problem here
}
your loop statement is followed by a semicolon! This should be
while (answer.equalsIgnoreCase("YES"))
{
// loop body
}
since your code right now is the same as writing
while (answer.equalsIgnoreCase("YES"))
; // do nothing
// loop body
because of how Java's syntax works. Your current code compiles because you can have a block without any loops or if statements
// do some stuff
{ // begin new scope
int x = 10;
} // end scope
int y = x; // error because x is not in scope!
but this is clearly not what you intended.
Beyond that, you never read anything into answer meaning it always equals ""-- it never equals "YES" or "NO" at all! At least somewhere you should be saying
answer = scan.nextLine();
to read input.
The entire program is a bit wonky though. Here's how I would lay it out:
// Instead of using "stop", we can just break out of the loop when we're done
while(true) {
// ...
// Prompt for input. I use "print" instead of "println" so that the user's answer will be on the same line as the question, e.g.
// Do you want to continue (yes/no): YES
// instead of
// Do you want to continue (yes/no):
// YES
// and so forth
System.out.print("Do you want to continue (yes/no): ");
// This is how we actually read input.
String answer = scan.nextLine();
// If the user doesn't say "YES" (this could be "NO" or "q" or "asdf" or anything else), break out of the loop
if(!answer.equalsIgnoreCase("YES"))
break;
}
I think you're a bit confused about how loops and input work. Just because you write System.out.println("my question: " + answer) doesn't mean that Java will read the rest of the line into answer. It'll actually write whatever is already in answer, for example
answer = "abc"
System.out.println("Question? " + answer);
// "Question? abc" will be printed, and no input will be read
// answer still equals "abc"
and additionally, if you want to ask a question repeatedly, you have to put all of that questioning into the loop. Java will not read anything new into answer until you readLine() again, so I think that's where the confusion about the while loop comes from. In your answer.equalsIgnoreCase("YES") loop, nothing new will be read unless you put answer = scan.readLine() in it.
You have two while loops going on, your attempt to break has not been executed correctly, is only exiting the inner loop.
Let strip your loop logic back to only describing the variables and logic that will affect the loop itself: I have replaced your other code with method calls to simplify the demo, assume that you already implemented these methods and that they do what the names infer.
This is a good technique for transitioning form pseudo code to actual code but just as useful for evaluating loop constructs that aren't going the way you planned
int studentSn = ReadInt("Enter ID Number: ");
int Score = ReadInt("Enter your Marks: ");
string answer = "";
boolean stop = false;
while(!stop) { // this is never ending, nothing ever sets stop to true
Grade = DetermineGrade(score);
if (Grade != null) {
ShowGrade(studentSn, Grade);
answer = ReadContinuePrompt();
} else {
ShowError(studentSn, "Invalid Input");
answer = ReadContinuePrompt();
}
while (answer.equalsIgnoreCase("YES"));
{
counter++;
if (answer.equalsIgnoreCase("NO")) {
break;
}
// If this user's input was not NO, then this loop is infinite and should run into a stack overflow error when the value of counter exceeds the max value of int
}
}
Your outer loop is based on a stop variable:
while (!stop)
So inside your loop logic, instead of using a break statement, all you need to do is set the value of stop to true. A carefully placed break statement could also do this, but coding a deliberate stop parameter the way you have is a good design that makes the intent very clear.
Now your inner loop is just wrong, I don't want to over analyse it, because you ask for the user input outside of the loop, there is no way to change the answer. So lets replace the inner loop with a simple conditional statement
if(answer.equalsIgnoreCase("NO"))
stop = true; // or break;
else
counter++;
Now we need to go back to how you have coded your outer loop. Again, because the main input is outside of the loop, there is no amount of times with this code where we can say "YES" that will give a different answer, we need to ask the score input inside the loop so the result can be changed
That now gives us this logic:
int studentSn = ReadInt("Enter ID Number: ");
string answer = "";
boolean stop = false;
while(!stop) {
// read the score inside the loop.
int Score = ReadInt("Enter your Marks: ");
Grade = DetermineGrade(score);
if (Grade != null) {
ShowGrade(studentSn, Grade);
answer = ReadContinuePrompt();
} else {
ShowError(studentSn, "Invalid Input");
answer = ReadContinuePrompt();
}
if(answer.equalsIgnoreCase("NO"))
stop = true; // or break;
else
counter++;
}

Provide loop conditions that are not Boolean

I need to accept some positive integers for which I use a for loop as follows:
Scanner in = new Scanner(System.in);
for(int i=0; i<n; i++) {
num = in.nextInt();
//do something with num
}
This requires me to (a) know number of integers n beforehand (b) Use a counter i
I know Java does not accept non-Boolean expressions in loop conditions. But how can I do the same without n and i?
For example, something like:
while( (num = in.nextInt()) ) {
//do something with num
}
Any type of loop (for/while/do-while) will do.
What you can do is something like:
boolean loop = true;
while (loop) {
int num = in.nextInt();
... do something with n
if (whatever) loop = false;
}
for example.
Or you use while (true) together with if (whatever) break.
In other words: you need a boolean condition, but you can control that condition within your loop body as shown above.
Loop until end of input -or- non-integer input (e.g. "exit", blank line):
while(in.hasNextInt()) {
int num = in.nextInt();
}
If you're testing in IntelliJ and want to indicate EOF explicitly: Ctrl+D or ⌘+D
If you want to read a file as your input: java MyClass < numbers.txt
Here is an example on how to use the scanner class: https://www.tutorialspoint.com/java/util/scanner_nextint.htm
You should use the hasNext() method to end the loop and check for integers with the hasNextInt() method:
public class ScannerDemo {
public static void main(String[] args) {
String s = "Hello World! 3 + 3.0 = 6.0 true ";
// create a new scanner with the specified String Object
Scanner scanner = new Scanner(s);
// find the next int token and print it
// loop for the whole scanner
while (scanner.hasNext()) {
// if the next is a int, print found and the int
if (scanner.hasNextInt()) {
System.out.println("Found :" + scanner.nextInt());
}
// if no int is found, print "Not Found:" and the token
System.out.println("Not Found :" + scanner.next());
}
// close the scanner
scanner.close();
}
}
I know Java does not accept non-Boolean expressions in loop conditions.
To my knowledge no programing language allows that. The loop either continues or it does not, this is a boolean decision and that requires a boolean conditional. There is no "the loop maybe continues, we don't know".
With that said Java - of course - requires a boolean condition to continue or not. The question you need to answer is: When shall the loop terminate?
There are three options:
The loop continues forever
while (true)
The loop stops at a special input value
while ((num = in.readInt()) != 0)
The loop is broken from outside
while (running) {
// ...
}
public void stopLoop() {
running= false;
}

When the program loops it prints the line "Enter your name (first and last): " twice?

So in the program I ask the user whether they want to rerun the program but when it does it prints the line "Enter your name," followed by a space, twice. Can someone please help me find the cause of this? It doesn't happen when you run it the first time by the way.
import java.util.Scanner;
public class PirateName
{
static Scanner input = new Scanner(System.in);
static String[]firstNames = {"Captain", "Dirty", "Squidlips", "Bowman", "Buccaneer",
"Two toes", "Sharkbait", "Old", "Peg Leg", "Fluffbucket",
"Scallywag", "Bucko", "Deadman", "Matey", "Jolly",
"Stinky", "Bloody", "Miss", "Mad", "Red", "Lady",
"Shipwreck", "Rapscallion", "Dagger", "Landlubber", "Freebooter"};
static String[]secondNames =
{"Creeper","Jim","Storm","John","George","Money","Rat","Jack","Legs",
"Head","Cackle","Patch","Bones","Plank","Greedy","Mama","Spike","Squiffy",
"Gold","Yellow","Felony","Eddie","Bay","Thomas","Spot","Sea"};
static String[]thirdNames =
{"From-the-West","Byrd","Jackson","Sparrow","Of-the-Coast","Jones","Ned-Head",
"Bart","O'Fish","Kidd","O'Malley","Barnacle","Holystone","Hornswaggle",
"McStinky","Swashbuckler","Sea-Wolf","Beard","Chumbucket","Rivers","Morgan",
"Tuna-Breath","Three Gates","Bailey","Of-Atlantis","Of-Dark-Water"};
static String[] letters = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o",
"p","q","r","s","t","u","v","w","x","y","z"};
public static void main(String[] args) {
System.out.println("Welcome to the pirate name generator");
System.out.println("");
boolean running = true;
while(running){
nameGenerator();
}
}
public static boolean nameGenerator()
{
boolean rerun = false;
int x = 0;
System.out.println("Enter your name (first and last): ");
String userName = input.nextLine();
System.out.println("");
try{
String first = userName.substring(0,1);
for (int i=0;i <= 25 ; i++)
{
if(first.equalsIgnoreCase(letters[i]))
{
first = firstNames[i];
}
}
String last1 = userName.substring(userName.indexOf(' ')+1);
for (int i=0;i <= 25 ; i++)
{
if(last1.substring(0,1).equalsIgnoreCase(letters[i]))
{
last1 = secondNames[i];
}
}
String last2 = userName.substring(userName.length() - 1);
for (int i=0;i <= 25 ; i++)
{
if(last2.equalsIgnoreCase(letters[i]))
{
last2 = thirdNames[i];
}
}
System.out.println("Your pirate name is: ");
System.out.println("");
System.out.println(first+" "+last1+" "+last2);
System.out.println("");
System.out.println("Would you like to try again? (Type 1 for yes, 2- no)");
int a = input.nextInt();
if (a==2)
{
rerun = false;
System.out.println("Good Bye!");
return rerun;
}
else
{
rerun = true;
}
return rerun;
}
catch (Exception e){
System.out.println(" ");
}
return rerun;
}
}
I see at least three problems.
At the end of the method, when you read the value of a, you're pulling an integer from the Scanner, but you're not pulling out the newline character that follows the integer. This means that next time you call nextLine(), all you'll get is a blank line. The cure for this is to add an extra input.nextLine() immediately after input.nextInt().
You're catching exceptions and throwing them away, without even printing their stack traces. That means that if your program does encounter a problem, you'll never find out any information about the problem.
You're not using the value rerun outside the nameGenerator method. When you call it, you're checking if running is true, but running will never change, so you'll just go on calling it forever. So you probably want to change the code that calls it to this.
boolean shouldRun = true;
while (shouldRun) {
shouldRun = nameGenerator();
}
It looks like you are using the input scanner for entering both ints and strings. You should use two separate scanners, or change it so that input is brought in with .nextLine() and then changed to an integer.
The problem is you enter two characters when deciding to try again. The first is the int, the second is the character. The second character is not an integer, so it is left in the buffer. Then when you get input a second time, you are using a scanner that already has characters in the buffer. So it processes the buffer and reads the left over char as an empty line.
http://www.java-forums.org/new-java/24042-input-nextline.html

How to skip a block in Java?

In the program given I have to make sure that if two consequtive characters are the same. I shouldn't increase the value of the variable (Count)... I have tried "break;", but that skips me out of the "for loop" which is very counter-productive. How can I skip the given part and still continue the "for loop"?
Currently my output for "Hello//world" is 3. It should be 2 (the '/' indicates a ' '(Space)).
Code
import java.util.Scanner;
class CountWordsWithEmergency
{
public static void main()
{
Scanner input = new Scanner(System.in);
System.out.println("Please input the String");
String inp = input.nextLine();
System.out.println("thank you");
int i = inp.length();
int count = 1;
for(int j=0;j<=i-1;j++) //This is the for loop I would like to stay in.
{
char check = inp.charAt(j);
if(check==' ')
{
if((inp.charAt(j+1))==check) //This is the condition to prevent increase for
//count variable.
{
count = count; //This does not work and neither does break;
}
count++;
}
}
System.out.println("The number of words are : "+count);
}
}
You can use the keyword continue in order to accomplish what you are trying to do.
However you can also inverse your conditional test and use count++ only if it is different (!= instead of == in your if) and do nothing otherwise
if ((inp.charAt(j+1)) != check) {
count++;
}
The word you are looking for is "continue".
Try this:
if ((inp.charAt(j+1)) != check) {
count++;
}
Increment the value of count by checking with !=.
Try using continue where you want to skip an block.
Use "continue;" when you want to break the current iteration.
continue is a keyword in java programming used to skip the loop or block of code and reexecutes the loop with new condition.
continue statement is used only in while,do while and for loop.
You may want to use the continue keyword, or modify the logic a little bit:
import java.util.Scanner;
class CountWordsWithEmergency
{
public static void main()
{
Scanner input = new Scanner(System.in);
System.out.println("Please input the String");
String inp = input.nextLine();
System.out.println("thank you");
int i = inp.length();
int count = 1;
for(int j=0;j<=i-1;j++) //This is the for loop I would like to stay in.
{
char check = inp.charAt(j);
if(check==' ')
{
if((inp.charAt(j+1))!=check)
{
count++;
}
}
}
System.out.println("The number of words are : "+count);
}
}
Edit:
You may want to use the split method of the String class.
int wordsCount = str.split(' ').length;
Hope it helps :)
The following should work.
import java.util.Scanner;
class CountWordsWithEmergency
{
public static void main()
{
Scanner input = new Scanner(System.in);
System.out.println("Please input the String");
String inp = input.nextLine();
System.out.println("thank you");
int i = inp.length();
int count = 1;
for(int j=0;j<=i-1;j++) //This is the for loop I would like to stay in.
{
char check = inp.charAt(j);
if(check==' ')
{
if((inp.charAt(j+1))==check) //This is the condition to prevent increase for
//count variable.
{
continue;
}
count++;
}
}
System.out.println("The number of words are : "+count);
}
}

Categories