I have to create a code used to determine the amount of insurance payout. I have to use a while loop after the initial prompt asking if they want to get an analysis. Then I need to use nested do-whiles, 2 do-while loops, in the prompts and if-else-ifs. I need help with the loops.
`
public class Main
{
public static void main(String[] args) {
Scanner input = new Scanner (System.in);
String answer = " ";
String cont = ("%nMUTUALLY ACCIDENTAL, INC." +
"%n%nDo you want an analysis of earthquake coverage" +
"for your property? Enter 'Y' or 'N': ");
System.out.printf (cont);
(Scanner (answer = input.nextLine ()));
while (answer.equalsIgnoreCase ("Y"))
System.out.printf ("%nMUTUALLY ACCIDENTAL, INC." +
"%n%nEarthquake coverage analyzer" +
"%nPlease enter your name: ");
do
System.out.printf("%nPlease enter the insured value of your home: ");
System.out.printf("%nRichter Scale Damage Assessment"+
" 9.0+ Total destruction."+
" 8.0 Most structures dell."+
" 7.0 Many buildings destroyed"+
" 6.0 Many buildings considerably damaged, some collapsed."+
" 4.5 Damage to poorly constructed buildings."+
" 3.5 Felt by many people, no destruction."+
" 0 Generally not felt by people."+
"%n%nPlease enter the Richter scale value for the earthquake: ");
do
system.out.printf("%n“Your Name: “,Xxxxxxxxxx Xxxxxxxxxxxxxxx
“Home’s Insured Vale: “,$ZZZ,ZZZ,ZZZ9.99
“Richter Scale: “,Z9.99 or -Z9.99
“Is this information correct? ‘Y’ or ‘N’: “);
System.out.printf("%nDo you have another property? Enter 'Y' or 'N': ");
coverage = String.format(%n%nPAYOUT FOR EARTHQUAKE "+
"DAMAGE"+
"%N%NHOMEOWNER: %S"+
"$n$nDATE: %tD"+
"%nTime: %tr%n, insured, dateTime, dateTime);
coverage +=String.format("%n%-52s %4s $%,20.2f"+
"%nDeductible $47 $,20,2f"+
"%n46s TOTAL %4s $%,20.2f%n", message, " ", payout, " ", deductible, " ", " ", payout + deductible);
System.out.print(coverage) when richter > 0
exit main()
else
System.out.printf("%nThank you for using the Earthquake" +
"Coverage Analyzer.");
}
}
I can't see a clear question in here so I assume you are stuck on the structure of the loops.
while has the following structure:
// before
while (condition) {
statements;
statements;
}
//after
It first tests the condition. if true, it runs the statements. if the condition is false it skips straight to 'after'
do-while has the following structure:
// before
do {
statements;
statements;
} while (condition);
// after
It first runs the statements. then it tests the condition. if the condition is true it goes back into 'do' and runs the statements again. if the condition is false it goes to after.
You can nest loops like so:
while (someCondition) {
int i = 1;
String s = "";
// other code, just filling this to make it look a bit better
while (otherCondition) {
int j = i + 3; // i is available because this while is inside the block of the other while
}
}
You can do the same with do-while / mix them.
One additional thing: if you use break, you exit the loop you are in. if you have nested loops then you will break from the deepest loop.
while (someCondition) {
while (otherCondition) {
break; // goes to after-inner-while
}
// after-inner-while
}
sometimes you want to jump out of the outer while loop. break can help with this if you use labels. you can name loops like so:
outer: while (someCondition) {
inner: while (otherCondition) {
break outer; // goes to after-outer-while
}
// after-inner-while
}
// after-outer-while
this all also works for for-loops but you specifically asked questions about while loops.
be very careful about not using blocks after your while.
this is allowed but will be hard to read / a source of bugs:
while (someCondition)
doSomething();
it can easily be confuse you into thinking your code works differently than it actually does:
while (someCondition)
doSomething();
doAnotherThing();
the above only runs doSomething inside the loop but someone reading your code will likely think both method calls will be run.
Now to the code you posted:
I think you are expected to do something along the lines of:
boolean answeredYes = false;
while (!answeredYes) {
// ask for user input
// if user input is "Y" set answeredYes to true
}
since you say you need to use a while loop first. I would prefer do-while for this since you can do:
do {
// ask for user input
} while (userinput not what you expect);
My best advice right now is: don't try to write the entire method. Write code for one problem at a time. Start with the Y/N question and what you are supposed to do if the user types Y or N
then move on to the next step and work out what to do and how to do it. Write yourself comments (notes) that let you know what your intentions are.
This is a method within my program and I cannot use a bunch of if-else statements for my code. I need alternatives.
public String bedRoom1(){
int newChoice10 = JOptionPane.showConfirmDialog(null,"Would "
+ "you like to explore this room?",
"question",JOptionPane.YES_NO_OPTION);
if (newChoice10 == JOptionPane.YES_OPTION){ //if the user would lieke to
// explore then they are given the option for which objects they woul like to explore
int newChoice4 = JOptionPane.showConfirmDialog(null,"Explore"
+ " the Rocking chair(type YES) or Window(type NO)?"
, "question",JOptionPane.YES_NO_OPTION);
//The following if else statments are still within
//the first statement of the first if statement
if (newChoice4 == JOptionPane.YES_OPTION){
JOptionPane.showMessageDialog(null,"Chair starts "
+ "rocking with no one in it");
}else{
JOptionPane.showMessageDialog(null, "You see a child outs"
+ "ide on a swing and he suddenly vanishes.");
}
}else if (newChoice10 == JOptionPane.NO_OPTION){
JOptionPane.showMessageDialog(null,"You have chosen not "
+ "to explore Bedroom 1 and therefore continue "
+ "into the following room");
}
return null;
}
Can you please provide examples. Thank you in advance.
you can use showOptionDialog with all your choices instead of showConfirmDialog
and use switch - case instead of if then else
I've looked around and can't seem to find an answer as to what exactly the problem is. It executes fine up until the loop and then it seems to ignore the loop and gets hung up so I am rather confused.
package classGame;
import java.util.*;
public class GameTwo {
static int randomNumber;
static int numOfGuess = 5;
static Scanner GameTwo = new Scanner(System.in);
public static void main(String[] args) {
System.out.println("Frank: Hello there! My name is Frank. This is the introduction to the game.");
System.out.print("Frank: Please tell me what you would like to be called: ");
if(GameTwo.hasNextLine()) {
String userName =GameTwo.nextLine();
System.out.println(userName + ": My name is: " + userName);
System.out.println("Frank: Well " + userName + ", it's nice to meet you. ");
System.out.println("Frank: Lets play a little game, I want you to guess a number, It's already" +
" in my head and it's between 1-10.");
int guessResult = 1;
int randomGuess = 0;
while(guessResult != -1) {
randomGuess = GameTwo.nextInt();
guessResult = checkGuess(randomGuess);
}
while (randomGuess != guessResult) {
System.out.println(userName + ":Is the number: ");
randomGuess = GameTwo.nextInt();
if(randomGuess < 1 || randomGuess > 10 || randomGuess > guessResult || randomGuess < guessResult) {
System.out.println("Frank: Thats not right "+ userName);
} else if (randomGuess == guessResult) {
System.out.println("Frank: Hey...Thats pretty good...You got it!");
}
}
}
}
public static int getRandomNum () {
randomNumber = (int) (Math.random()*10);
return randomNumber;
}
public static int checkGuess(int guess) {
if(guess == randomNumber) {
return -1;
} else {
return guess;
}
}
}
here is what it prints out up to the loop
Frank: Hello there! My name is Frank. This is the introduction to the game.
Frank: Please tell me what you would like to be called: T
T: My name is: T
Frank: Well T, it's nice to meet you.
Frank: Lets play a little game, I want you to guess a number, It's already in my head and it's between 1-10.
I think this is an issue with how Scanner.nextInt() works. nextInt() takes in the next Integer found but it does not clear the buffer like nextLine() does.
See this link for more info about this issue: How does input.nextInt() work exactly?
Try this and see if your loop continues properly:
while(guessResult != -1) {
randomGuess = GameTwo.nextInt();
guessResult = checkGuess(randomGuess);
GameTwo.nextLine();
System.out.println("Random Guess: " + randomGuess); //Try here
}
I think the reason the loop is getting hung up is because nextInt() keeps finding the randomGuess number still in the input buffer and executing over and over again. To test that, simply put System.out.println("Random Guess: " + randomGuess); in the loop and see if it is printing with the same number over and over again.
Otherwise, I would need to see the output of your program to further diagnose the issue.
Edit: Can you post the input/output of your program up to the point it crashes? This will help. Also, did you have the System.out.println() in your loop beginning with while(guessResult != -1) or the second one?
Edit 2: I tested this code with my edits and it seems to work as intended (ish). The initial while loop does not do what is intended. The "game" aspect of guessing the correct number all happens in the first loop. I am "playing" the game and guess numbers but once I get it correct, it moves to the second loop, presumably where you actually wanted to "play". The correct number is gotten in the first loop and then the guessResult variable gets set to -1. Then when the user tries to guess where they are supposed to, the "correct" number is now -1.
I don't think the game was ever "hung up", it was just silently waiting for your input in the first loop. To solve this:
Simply remove the first while loop (and its contents) and the game works as intended.
So, what I am trying to do is get my while loops to do different things based on different key words. What I want is that when I type yes, I want it to exit the program, when I type no, for it to print a new song, and if there is a spelling error, for a message to pop up and allow the user to re enter yes or no to print the same song. I have 4 or 5 songs that I want to print out based on these three commands. In my last while loop. I want it to repeat the song every time the user types continue, and for it to end when the user types yes. I want the same thing to happen where it prompts the user to type again if there is a spelling error. This worked before, and now it does not. When I make a spelling error, it prompts me to enter again but will not print out the song in that loop. It will send me to the last while loop, ignoring all code in between. That last loop will only recognize spelling errors and yes, not continue, even though it did before.
Here is one song loop and my last loop:
import java.io.*;
import java.util.*;
public class FullNurseryRhymes
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
String aBCs, neverEnds, frogs, frogs2, monkeys, hdd, hdd2;
NurseryRhymes rhymes = new NurseryRhymes();
{
System.out.println("Is the baby asleep? yes\\no");
frogs=input.next();
int byeFrog = 2;
for(int i = 3; i >= 1; i--)
{
if (frogs.equalsIgnoreCase("no"))
{
System.out.print(i + " " + rhymes.getFrogs());
System.out.println(" " + byeFrog + " " + rhymes.getFrogs2());
byeFrog -= 1;
}
else if (frogs.equalsIgnoreCase("yes"))
{
System.out.println("The baby is asleep");
System.exit(0);
}
while(!frogs.equalsIgnoreCase("no"))
{
System.out.println("Non requested input, please retry.");
System.out.println("\nIs the baby asleep? continue\\yes");
frogs = input.next();
if(frogs.equalsIgnoreCase("no"))
{
System.out.print(i + " " + rhymes.getFrogs());
System.out.println(" " + byeFrog + " " + rhymes.getFrogs2());
byeFrog -= 1;
}
else if (frogs.equalsIgnoreCase("yes"))
{
System.out.println("The baby is asleep");
System.exit(0);
}
}
}
}
//last loop
{
System.out.println("Is the baby asleep? continue\\yes");
neverEnds = input.next();
while(neverEnds.equalsIgnoreCase("continue"))
{
System.out.println(rhymes.getNeverEnds());
System.out.println("Is the baby asleep? continue\\yes");
neverEnds = input.next();
}
if(neverEnds.equalsIgnoreCase("yes"))
{
System.out.println("The baby is asleep");
System.exit(0);
}
while(!neverEnds.equalsIgnoreCase("continue")||!neverEnds.equalsIgnoreCase("yes"))
{
System.out.println("Non requested input, please retry");
System.out.println("\nIs the baby asleep? continue\\yes");
neverEnds = input.next();
while (neverEnds.equalsIgnoreCase("continue"))
{
System.out.println(rhymes.getNeverEnds());
System.out.println("Is the baby asleep? continue\\yes");
neverEnds = input.next();
if(neverEnds.equalsIgnoreCase("yes"))
{
System.out.println("The baby is asleep");
System.exit(0);
}
}
if (neverEnds.equalsIgnoreCase("yes"))
{
System.out.println("The baby is asleep");
System.exit(0);
}
}
}
Based on the comments, it sounds like there is too much (potentially) relevant code for us to plough through.
There are three ways you could proceed with this.
You could learn how to use the debugger in your IDE. Use breakpoints and single stepping, and figure out where your mistakes are.
You could comment out parts of the code to track down where the problems are. That may also help you to create an MCVE
You could simplify the code by refactoring common / repetitious code into methods. For instance the "last loop" section is incredibly repetitious.
On the last point, it might actually be less work to throw this code away and start again ... after figuring out what common code can be implemented as methods.
Your question is a bit long. We don't need a story, just an explanation of your problem and a BIT of code, not your whole class. Try putting your while loop on the outside. Have a string outside the while loop called babySleep that starts as "no". Then, while(babySleep.equals("no") execute your code. Then at the end, check if the baby is a sleep, if he is, move on, if not, the while loop will re-execute. Also, instead of .equals try .equalsIgnoreCase so the user can type in "Yes" or "yES" etc.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
The following loop is not good practice. Is it due to a String being the main condition of the for loop rather than an int variable, meaning the for loop is infinite? Also, is it due to there being no instance to enter 'end' to stop the loop?
Scanner in = new Scanner(System.in);
int i = 0;
for (String s = in.next(); !s.equals("end"); i++)
{
System.out.println("The value of i is: " + i + " and you entered " + s);
}
How can I rewrite it, so that it conforms to accepted style?
(This is a question in a past exam paper.)
Well your string s is never changing, which can lead to an infinite loop. You probably wanted:
for (String s = in.next(); !s.equals("end"); s = in.next(), i++) {
...
}
Some (me included) might say that i++ shouldn't be in the increment section of this loop, since it's not directly relevant to the condition:
for (String s = in.next(); !s.equals("end"); s = in.next()) {
...
i++;
}
Is it due to a string being the main condition of the for loop rather than an int variable, meaning the for loop is infinite?
The original loop was indeed infinite (at least, after an initial input is entered and assuming "end" wasn't the first input). However, it's not for the reason you state. For-loops are most commonly written using integral loop control variables, but it's not always the case. For example, a common idiom for iterating through a linked list is:
for (Node node = list.head; node != null; node = node.next) {
...
}
The problem with your loop is that the string s is never changed, so it will never equal "end" unless that's the first input.
I would suggest separating the looping condition and the call to Scannner.next():
while (in.hasNext()) {
String s = in.next();
if (s.equals("end")) {
break;
}
System.out.println("The value of i is: " + i + " and you entered " + s);
i++;
}
I think this is much easier to understand than trying to squeeze everything into a for expression.
There are multiple problems with this code:
s never changes after the initial assignment, so it's an infinite loop.
Calling .next() could throw NoSuchElementException or IllegalStateException. Rather than catching these exceptions, I consider it more polite to check .hasNext() beforehand, since running out of input is a foreseeable rather than an exceptional situation. However, the alternative ask-for-forgiveness style could also be acceptable.
The for-loop header does not form a coherent story — it initializes s and tests s, but updates i.
In my opinion, System.out.format() would be slightly more preferable to System.out.println() with concatenation.
I would write it as:
Scanner in = new Scanner(System.in);
int i = 0;
String s;
while (in.hasNext() && !"end".equals(s = in.next())) {
System.out.format("The value of i is: %d and you entered %s\n", i++, s);
}
It might also be a nice user interface touch to tell the user that end is a magic word to terminate the loop (assuming it were modified to work as probably intended).
The common practice with for loops is that the counter variable is repeated in each term:
for(int i=...; i<... ; i++)
In the example above, the code mixes variables. Which is confusing to the reader and probably lead to the bug that the loop only terminates if you input end as the first value.
This loop is a bad idea, because you're taking setting s once from the user input and not in every iteration.
Thus, it will cause you to run infinite time in case s was filled with value different from "end".
You probably wanted something more like this:
for (String s; (s = in.nextLine()).equals("end"); i++)
{
System.out.println("The value of i is: " + i + " and you entered " + s);
}
This isn't a good idea because the string s may never equal "end". You'll probably want to check if the scanner has another string. Also, you only initialize the string to in.next() but you need to set s to the next string after each iteration of the loop.
while(in.hasNext()) {
String s = in.next();
if (s.equals("end")) {
break;
}
// ..
}
This approach is too bad.
The Given Code :-
Scanner in = new Scanner(System.in);
int i = 0;
for (String s = in.next(); !s.equals("end"); i++)
{
System.out.println("The value of i is: " + i + " and you entered " + s);
}
The 1st part of for loop only execute once in life.
String s = in.next() //Execute only once in life
The 2nd part of this for loop never be true , because the input console will never allow to enter the 2nd input.
!s.equals("end")//2nd part
This program will never allow to enter 2nd input from console, because the in.next() will execute only once.And the exit token for this loop is "end" which is not possible to enter after first input.
This type of loops should be implemented by while loop .
Scanner in = new Scanner(System.in);
while(in.hasNext()){
String yourdata=in.next();
if(yourdata.equals("end")){
//Stop the loop
}
//Do you code here
}
It bad practice because it's terminated only if next obtained token is "end". It does'n not consider situation like. e.g. end of input stream.
So when then stream ends and nowhere along "end" appeared you'l get s=null and NullPointerException at s.equals("end").
You can correct it e.g. by changing condition to in.hasNext() && !"end".equals(s).
Also s is never changing after it was initialized.
If the question is "why rewrite it" the answer is basically as others have pointed out, that it's currently an infinite loop, and also that it's not very readable as it stands. Personally I'd rewrite it as a while loop, which several others have already pointed out how to do, as it makes your intentions a little more clear than a for loop with a counter that's counting up to infinity. Someone unfamiliar with how the code is supposed to work could easily confuse an infinite increment to be an oversight by the programmer who wrote it.
The string s is never modified. The loop never ends. What about this :
Scanner in = new Scanner(System.in);
String s = "";
for (int i = 0 ; !s.equals("end"); i++) {
s = in.next();
System.out.println("The value of i is: " + i + " and you entered "
+ s);
}
Others have mentioned that the loop does not end because you are not changing the value of s, so the loop never ends. This may be what your professor intended, and it may not be. Bad code is bad practice, as a rule, but there are other reasons why this is bad practice.
What jumped out to me as being bad practice here, and what the professor could have intended, is the use of a for loop here. As my professor told me, "For loops are for when you know when you want the code to end, while loops are for when you don't know when you want the code to end." So if you have an iterable i such as this code:
for(i = 0; i<100; i++)
{
...
}
In this code, you know that you want to iterate i from 0 to 100. A while loop is what you would want to use in the situation your professor is discussing.
int counter;
while(*(str+counter))
counter++;
You have no idea when the loop is going to end, because you don't know how long the str is, but you know that sometime it will get to the null pointer, and the loop will terminate. This generally what is best practice.
So for the code your professor posted, you may want it to look like this:
Scanner in = new Scanner(System.in);
int i = 0;
while(!s.equals("end"))
{
i++;
String s = in.next();
System.out.println("The value of i is: " + i + " and you entered " + s);
}
It is not in good practice because of two things:
for loops are meant to iterate over a collection of data
a for loop consists of iterator initial state, loop condition and an iterating function that are related
The for statement just intermixes two different information (the stream and the counter). Even if it does work, it isn't good practice to do it.
I think this is bad practice, because there isn't any need for a for loop. In this case, I believe it's useless. It could be just this:
Scanner in = new Scanner(System.in);
String s = in.next();
if (!s.equals("end"))
{
System.out.println("You have enetered" + s);
}
See, there isn't any need for a loop. The loop you had was making things more complicated than they had to be. I was always think that things should be kept as simple as they can be unless they require complexity. For loops are only to be used when you have more than one action that you want the code to do. In the case above, only one thing is happening: the println statement, so there's no need for a loop. It's unnecesary...
Also, the loop never ends. So there's that too, but that's just faulty code. That's not why it's bad practice. It's bad practice because of the unnecesary use of a for loop. It's also faulty, because the code is wrong. So there are two different things going on with this code.
I would have just left a comment, but I don't have the rep yet.
What I haven't seen explained is WHY your s value is not changing.
In a typical for loop:
for(a=1; a<=10; a+=1) {body}
the initial phrase, 'a=1', is ONLY performed once as an initialization.
the third phrase, 'a+=1', is performed once at the end of every cycle, until…
the second phrase, 'a>=10', evaluates false.
so a for loop would be represented in 'psuedo-code' something like this:
a=1 // first phrase
:LoopLabel
{body}
a+=1 // third phrase
if (a<=10) // second phrase (boolean evaluation)
then goto LoopLabel
Likewise, your example, in similar pseudo-code might look like this:
Scanner in = new Scanner(System.in);
int i = 0;
String s = in.next()
:LoopLabel
{
System.out.println("The value of i is: " + i + " and you entered " + s);
}
++i
if (!s.equals("end"))
goto LoopLabel
So the reason your program was an infinite loop was the value of 's' was only set on entry to your loop and never changed during each loop execution, as most likely desired.
for (int i = 0; in.hasNext(); i++) {
String s = in.next();
if (s.equals("end")) {
break;
}
...
Endless loop, or no loop (when s is initially "end").
A number of responses above are correct to say that what you've written is an infinite loop. But I wanted to clarify why this is an infinite loop. The for loop you're using differs from the other form you may be thinking of:
String[] stringArray = { "1", "2", "3" };
for (String s : stringArray) {
System.out.println(s);
}
In that case, the variable s is initialized with the next value from your collection or array on each iteration. But that form of for loop works with collections and arrays and can't be used with iterators like the Scanner class.
The form of for loop you're using differs in that the initialization clause (where you have String s = in.next()) is called ONLY the first time through the loop. s is set that first time, then never changed.
You could re-write like this:
int i = 0;
for (String s = in.next(); !s.equals("end"); s = in.next()) {
System.out.println("The value of i is: " + i++ + " and you entered " + s);
}
But another bad thing in here is that there's no null or end check. It's conceivable if not likely that you would run out of strings before you found one that equaled "end". If that happened, then the for test clause (the middle one) would give you a NullPointerException when it tried to the call to the equals() method. THAT is definitely bad practice. I would probably re-write this like this:
int i = 0;
while (in.hasNext()) {
String s = in.next();
if (s.equals("end")) {
break;
}
System.out.println("The value of i is: " + i++ + " and you entered " + s);
}
If you really want a for loop instead of a while, it would be better to do this:
int i = 0;
for (Scanner in = new Scanner(System.in); in.hasNext();) {
String s = in.next();
if (s.equals("end")) {
break;
}
System.out.println("The value of i is: " + i++ + " and you entered " + s);
}
One last variation that preserves the test against the string in the test clause would look like this:
int i = 0;
String s = "";
for (Scanner in = new Scanner(System.in);
in.hasNext() && !s.equals("end");
s = in.next()) {
System.out.println("The value of i is: " + i++ + " and you entered " + s);
}
You could also add a null check in there before the s.equals("end") for total safety.
It is not a good practice maybe because you are comparing the String s with a String but you are not comparing the value, you are comparing the memory position of the s value.