Scope of Variables in a While Loop - java

int i = 1;
while(i == 1) {
if (answerHold.equals(generate)) {
qgCharacter();
i++;
} else if (answerHold.equals(create)) {
qcCharacter();
i++;
}
}
The above code keeps running until a desired value is entered.
How would I maintain the accessibility of the variable inside of the while loop, instead of the variable having to be outside of the loop?
Would using a different loop make more in sense in this situation?

Use the "break" keyword instead of changing the value of "i".
while(true) {
if (answerHold.equals(generate)) {
qgCharacter();
break;
} else if (answerHold.equals(create)) {
qcCharacter();
break;
}
}

The following construct would make more sense in my opinion. Without a variable!
while (true) {
if (answerHold.equals(generate)) {
qgCharacter();
break;
} else if (answerHold.equals(create)) {
qcCharacter();
break;
}
}

Related

Find bug in implementation of algorithm that finds minimum of an array of integers

Recently, I tried to write a Java program which searches for the minimum of an array.
I tried to write it in a different way, I know there are more simple ways to do that but I want to know why my program does not work.
Here is the source code :
public int minimum(int [] t) {
int min,i,j;
i=j=t.length/2;
min=t[t.length/2];
while(j!=0 || i!=t.length-1) {
while( t[i]>=min) {
i++;
if(i==t.length) {
i=t.length-1;
continue;
}
}
while(t[j]>=min) {
j--;
if(j==-1) {
j=0;
continue;
}
}
if(t[i]<=min && t[j]<=min) {
if(t[i]<=t[j]) min=t[i];
else min=t[j];
}
}
return min;
}
Thanks.
Before you read the answer you should try debugging your code to figure this out by yourself.
I think your code loops infinitely in one of those inner while loops because the end condition
if(i==t.length) {
i=t.length-1;
continue;
}
only resets the i one step back and the continue restarts the while loop. You probably meant to have the break keyword there instead of the continue in which case your code will continue with the other inner while loop.
there is some logic errors in my code , and it get infinitely going through the two loops , i fixed the loops by changing continue with break and i modify the last condition by setting || instead of && (that was a logic mistake), and it works now .
thanks guys.
here is the new source code:
public int minimum(int [] t) {
int min,i,j;
i=j=t.length/2;
min=t[t.length/2];
while(j!=0 || i!=t.length-1) {
while( t[i]>=min) {
i++;
if(i==t.length) {
i=t.length-1;
break;
}
}
while(t[j]>=min) {
j--;
if(j==-1) {
j=0;
break;
}
}
if(t[i]<=min || t[j]<=min) {
if(t[i]<=t[j]) min=t[i];
else min=t[j];
}
}
return min;
}

Break while loop only when all conditions in for loop are met

I would like to break a while loop only when all of the "bots" are upright. (*These bots being referred to are mini USB robots).
.upRight() returns true when a bot is standing and false when not.
public static boolean checkSomething() throws ... {
while (true) {
for (i = 0; i < bots; i++) { // bots = 2
if (!theMainBots[i].isUpright()) {
...
Thread.sleep(1000);
}
else {
return true;
}
}
}
The issue I'm facing, is that if the isUpright() method returns true for the first "bot", then all other bots are left unchecked and may return false. The intention is to wait for the user to place the bot in an upright position before proceeding.
You should check all the bots first, then act on the result. Don't try to act on the result inside the check loop.
Also, since the code doesn't return until all bots are upright, the method is misnamed and shouldn't return a value.
public static void waitUntilAllUpright() throws InterruptedException {
for (;;) { // forever loop
boolean allUpright = true;
for (i = 0; i < bots; i++) {
if (! theBots[i].isUpright()) {
allUpright = false;
break;
}
}
if (allUpright)
return;
System.out.println("Please ensure I'm upright");
Thread.sleep(500);
} // loop back to check all bots again
}
If you want to wait until the user makes the bot upright you could change the if to a while:
while (true) {
for (i = 0; i < bots; i++) { // bots = 2
while(!theBots[i].isUpright()) {
System.out.println("Please ensure I'm upright");
Thread.sleep(500);
}
}
return true;
}
This will loop through each element in the Array and while any given bot is not upright, it will loop and sleep until the bot is turned upright. In which case, you do not need to while(true) loop:
public static boolean checkUpright() throws InterruptedException {
for (i = 0; i < bots; i++) { // bots = 2
while(!theBots[i].isUpright()) {
System.out.println("Please ensure I'm upright");
Thread.sleep(500);
}
}
return true;
}
One way to achieve this, is using a variable that will determine when to leave the loop. Your problem here, is that you also need to change your for loop for a while loop. Why is that? Because you don't know if the bot you just checked was moved or not. Also, the outer loop is unnecessarily, unless you wanted to recheck again. So the code would end looking something like this.
public static boolean checkUpright() throws InterruptedException {
int counter = 0;
while (counter <= theBots.length) { // bots = 2
if (!theBots[i].isUpright()) {
System.out.println("Please ensure I'm upright");
Thread.sleep(500);
} else {
counter ++;
}
}
}
The context is not completely clear, but mixing logical control with user interaction might be the problem. Perhaps this approach might work:
public static boolean checkUpright() throws InterruptedException {
while (!areAllBotsUpright()) {
System.out.println("Please ensure I'm upright");
Thread.sleep(500);
}
}
public static boolean areAllBotsUpright() {
for (i = 0; i < bots; i++) {
if (!theBots[i].isUpright()) {
return false;
}
}
return true;
}
you can create a list from array of bots , iterate over this list using iterator
if a particular bot is upright , remove it from this list using iterator.remove.
outer while will run until list is not empty.
public static boolean checkUpright() {
ArrayList<Bot> notUprightBots= (ArrayList<Bot>) Arrays.asList(theBots);
while (!notUprightBots.isEmpty()) {
Iterator<Bot> iterator=notUprightBots.iterator();
while(iterator.hasNext()){
Bot bot=iterator.next();
if (!bot.isUpright()) {
System.out.println("Please ensure I'm upright");
try{
Thread.sleep(500);
}catch(InterruptedException e){
}
}else {
iterator.remove();
}
}
}
return true;
}

Which one is better, conditional for loop or for loop with a break (for short block of code)?

I am trying to find out which practices make your code more readable, specifically when your block of the code is short. Please look at these two versions of the for loop and let me know which one is more readable;
private boolean isValid(String guessInput)
{
boolean result = true;
for (int i = 0; i < guessInput.length(); i++)
{
if (!Character.isDigit(guessInput.charAt(i)))
{
result = false;
break;
}
}if (result)
{
int guessInputInt = Integer.parseInt(guessInput);
if (guessInputInt >= minGuess && guessInputInt < maxGuess)
guesses.add(guessInput);
else
result = false;
}else
System.out.println("Your input is not valid.");
return result;
}
Version 2
private boolean isValid(String guessInput)
{
boolean result = true;
for (int i = 0; i < guessInput.length() && result; i++)
{
if (!Character.isDigit(guessInput.charAt(i)))
{
result = false;
}
}if (result)
{
int guessInputInt = Integer.parseInt(guessInput);
if (guessInputInt >= minGuess && guessInputInt < maxGuess)
guesses.add(guessInput);
else
result = false;
}else
System.out.println("Your input is not valid.");
return result;
}
Approach to break the loop is better amongst the two. Also, you can move the Sysout statement inside the loop e.g.:
private boolean isValid(String guessInput){
for (int i = 0; i < guessInput.length() && result; i++){
if (!Character.isDigit(guessInput.charAt(i))){
return false;
}
}
return true;
Update
Here's another way to do it (using java 8 stream):
public static boolean isValid(String s){
return !s.chars()
.filter(c -> !Character.isDigit((char)c))
.findFirst()
.isPresent();
}
Agreed with Mark Jeronimus's point. You should call this method and print the messages in calling the method rather than having Sysout in the valildating method.
How about a third option:
private boolean isValid(String guessInput) {
boolean result = isNumeric(guessInput);
if (result)
// ...
}
private boolean isNumeric(String input) {
for (int i = 0; i < guessInput.length(); i++)
if (!Character.isDigit(guessInput.charAt(i)))
return false;
return !input.isEmpty();
}
Or even simpler:
private boolean isValid(String guessInput) {
try {
int guessInputInt = Integer.parseInt(guessInput);
if (guessInputInt >= minGuess && guessInputInt < maxGuess) {
guesses.add(guessInput);
return true;
}
} catch (NumberFormatException nfe) {
System.out.println("Your input is not valid.");
}
return false;
}
On a side note, the method name isValid() implies a read-only getter, which is very misleading when you're modifying state.
In your loops, if you can accurately specify your loop breaking condition in the for loop itself, that is always better.
I always think of break as a hack/patch/fix, never a solution.
Specifically to the question on the usage of break in the loop in your example, I don't think there is a difference in code readability, since it is so short.
However, in general I would prefer the break approach, because:
There is no reason to continue execution once the result is set to false. Depending on the length of "guessInput", and how the compiler may optimize your code, the code with break can be a lot more efficient.
Although the code inside for loop is short in your example, in practice it may likely to grow as the condition become more complex. By always breaking out of the loop where it should, it will become a lot easier follow the code logic when the code inside loop becomes longer or more complex.
Therefore, I would always prefer to use break where it should in a loop.
For this I like the use of
public boolean isValid(String s) {
if (isNum(s)) {
Integer num = Integer.parseInt(s);
return inRange(num, maxGuess, minGuess);
}
return false;
}
private boolean inRange(Integer i, Integer max, Integer min) {
return (i < max && i >= min);
}
private boolean isNum(String s) {
return s.chars().allMatch(Character::isDigit);
}
As others have mentioned System.out.println("Your input is not valid."); is best done by the consumer of the isValid function,
Breaking isValid into smaller operations helps with MURDER!
You can read about murder here
If your intention is to validate numbers, any numbers, then you'd use the API for that, and handle the exception if the number is invalid.
Caveat: In your code, if your string is over 2147483647, the exception is thrown anyway and unhandled, leading to bugs.
Here's a better version, although I'd still argue about splitting up responsibilities in a pure checking method and another method that adds it to the guesses and/or prints stuff.
private boolean isValid(String guessInput)
{
try {
int guessInputInt = Integer.parseInt(guessInput);
if (guessInputInt >= minGuess && guessInputInt < maxGuess) {
guesses.add(guessInput);
} catch (NumberFormatException ex) {
System.out.println("Your input is not valid.");
return false;
}
return true;
}

Repeat an increment of loop

For my science fair project, I'm wanting to give a graphical update to a French-teaching program that's so old it's emulated in DosBOX. That's all well and good but I'm having problems. I'm writing the base logic of the program in a console application just to get that together. I've created a Question class that's in a array list/collection known as "test1".
I have a loop that iterates through the list and with each iteration, it runs another method called evaluate:
public static boolean evaluate(Question question, Scanner scanner)
{
System.out.println(question.getPhrase()); // prints the question
String answer = scanner.nextLine(); // gets the answer
if (answer.compareTo(question.getCorrectAnswer()) == 0)
return true; // compares the answer to the correct answer w/i the current instance of "Question"
else
return false; // if it's not right, returns "false" meaning the question wasn't correct
}
The loop looks as such:
for (Question question : test1)
{
if (evaluate(question, scan))
{
incorrect = 0;
continue;
}
else
{
incorrect++;
System.out.println(incorrect);
}
if (incorrect == 3)
System.out.println("you have failed");
break;
}
I want to make it so that if you answer a question incorrectly, it spits out the phrase again and increases "incorrect" by 1 and, if you hit 3, terminates the list (I think I've got this implemented correctly if I could just get it to repeat the question). Right now it moves to the next item in the list and thus the next question even if and I don't want that.
Sorry if my code is awful, I'm still relatively new to programming.
Create a while loop inside of the for loop that says if the question isn't answered correctly, then repeat so that way in each question the question will be asked until its correct. Keep everything inside the for loop in the while loop that you should create:
for (Question question : test1)
{
while(!evaluate(question, scan)) {
if (evaluate(question, scan))
{
incorrect = 0;
continue;
}
else
{
incorrect++;
System.out.println(incorrect);
}
if (incorrect == 3)
System.out.println("you have failed");
break;
}
}
Instead of doing a foreach loop the way you're doing it now, you can do the following:
for (int i = 0; i < test1.size(); i++) {
Question question = test1.get(i);
if (evaluate(question, scan)) {
...
} else {
incorrect++;
test1.add(question);
}
if (incorrect == 3) { ... }
}
This is assuming you're using a data structure that uses size() and add() as methods; you can adjust it to what you're using.
This will repeat questions later, though not immediately after. If you want to repeat it immediately after, just decrement i-- in the else case:
for (int i = 0; i < test1.size(); i++) {
Question question = test1.get(i);
if (evaluate(question, scan)) {
...
} else {
incorrect++;
i--;
}
if (incorrect == 3) { ... }
}
You can also nest a loop for the else case:
for (Question question : test1) {
boolean passed = True;
incorrect = 0;
while (!evaluate(question, scan)) {
incorrect++;
if (incorrect == 3) { passed = False; break; }
}
if (!passed) { System.out.println("you have failed"); break; }
}

how to jump from inner loop to outer loop

Here is the structure of my program:
for(loop1){
if(condition1)
{
for(loop2)
{
for(loop3)
{
if(condition1_3)
{
As condition1_3 is true continue with loop2's next iteration,
No need to execute loop3's remaining iteration
}
else
{
As condition1_3 is false no need to execute remaining part of loop3 and
loop 2 but continue with loop1's remaining part i.e. condition1_1
}
}
}
}
if(condition1_1)
{
some code here
}
}
I know I have to use continue and break statement but don't understand exactly how?
Please tell me how to achieve this mechanism?
If I understand your question, you could use the labeled continue,
loop1: for (;;) {
if (condition1) {
loop2: for (;;) {
loop3: for (;;) {
if (condition1_3) {
continue loop2;
} else {
continue loop1;
}
}
}
}
}
You can do as follows:
for(loop1){
if(condition1)
{
for(loop2)
{
boolean flag=false;
for(loop3)
{
if(condition1_3)
{
break;
}
else
{
flag=true;
break;
}
}
if(flag)
break;
}
}
if(condition1_1)
{
some code here
}
}
Do like the following -
for(loop1){
boolean flag = false;
if(condition1)
{
for(loop2)
{
if(flag == true)
break;
for(loop3)
{
if(condition1_3)
{
break;
}
else
{
flag = true;
break;
}
}
}
}
if(condition1_1)
{
some code here
}
}
An option would be to use variables - but you have to think about correct setting of values:
boolean runFor1 = true;
boolean runFor2 = true;
boolean runFor3 = true;
for(loop1 && runFor1)
{
for(loop2 && runFor2)
{
for(loop3 && runFor3)
{
setRunForX here to skip/unskip loops
}
}
}
}
Have a exit flags which is set when you want to exit a particular loop and check in each respective loops whether to continue or exit.
boolean exitLoop2 = false;
for(loop1){
if(condition1)
{
for(loop2)
{
for(loop3)
{
if(condition1_3)
{
//As condition1_3 is true continue with loop2's next iteration,
//No need to execute loop3's remaining iteration
break;
}
else
{
//As condition1_3 is false no need to execute remaining part of loop3 and
//loop 2 but continue with loop1's remaining part i.e. condition1_1
exitLoop2 = true;
break;
}
}
if(exitLoop2)
{
break;
}
}
}
if(condition1_1)
{
some code here
}
}
To break out and not continue the loop3 use break; if (condition1_3) break; The break; statement only breaks out of the current loop i think, not the loop it is nested in.
Edit: Missread the question
To break out of both loops you can make a boolean flag before both loops and at the end of both loops have an if (breakOut) break; This will solv the question
I'm not really shure what do you mean exactly. For me it simply looks like you want to jump out of the loops if a specific condition is satisfied. So you can either can define a label for your loops and use the continue labelLoopX; statement or you can satisfy the exit condition of loop3 if condition1_3==true resp. the exit condition of loop3 and loop2 if condition1_3==false. e.g. if loop3 looks like for ( int i = 0; i < 10; i++ ) like this:
if(condition1_3){
//do something important
i=10; //sets i to 10 and condition i < 10 is unsatified
}
else{
//do some other important stuff
i=10; //satify loop3's exitcondition
j=10; //satify loop2's exitcondition
}

Categories