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.
Related
So I have an assignment in my CISP 1 class that requires me to create a program that displays a bar chart comprised of asterisks based on the amount of sales 5 different stores have had. I've got a base made, but I still want to add a loop that validates the input from the user(i.e. throws an error when the user tries to enter a negative number), and I want to add the option to run the program or exit it. I'm just a little lost on how to do all of that, so I figured I'd reach out on this website and ask. I know a lot of this code could be simplified with arrays, but we haven't started studying that yet - so I'm afraid to be messing with something I don't fully understand. Below is my code:
import java.util.Scanner;
public class BarChart
{
public static void main(String[] args)
{
int store1, store2, store3, store4, store5;
Scanner keyboard = new Scanner(System.in);
System.out.println("This program will display a bar chart " +
" comprised of astericks based on five different stores' " +
"sales. 1 asterick = $100 in sales.");
System.out.print("Enter today's sales for store 1: ");
store1 = keyboard.nextInt();
System.out.print("Enter today's sales for store 2: ");
store2 = keyboard.nextInt();
System.out.print("Enter today's sales for store 3: ");
store3 = keyboard.nextInt();
System.out.print("Enter today's sales for store 4: ");
store4 = keyboard.nextInt();
System.out.print("Enter today's sales for store 5: ");
store5 = keyboard.nextInt();
System.out.println("Sales \t Bar Chart");
System.out.println("----- \t ---------");
System.out.print("\nStore 1: ");
for (int num = 0; num < store1; num += 100)
{
System.out.print("*");
}
System.out.print("\nStore 2: ");
for (int num = 0; num < store2; num += 100)
{
System.out.print("*");
}
System.out.print("\nStore 3: ");
for (int num = 0; num < store3; num += 100)
{
System.out.print("*");
}
System.out.print("\nStore 4: ");
for (int num = 0; num < store4; num += 100)
{
System.out.print("*");
}
System.out.print("\nStore 5: ");
for (int num = 0; num < store5; num += 100)
{
System.out.print("*");
}
}
}
I've tried adding if statements each time the user is asked to enter a sales amount, but that didn't work.
I still want to add a loop that validates the input from the user(i.e.
throws an error when the user tries to enter a negative number)
Here's a quick example that shows how to ask again when an invalind number is entered:
do {
System.out.print("Enter today's sales for store 1: ");
store1 = keyboard.nextInt();
if (store<0) {
System.out.println("Sales must be non-negative!");
}
while (store<0);
I want to add the option to run the program or exit it.
This would be similar to the do { ... } while( ... ); above except you'd put the whole program from below the Scanner line inside the body of the do loop. Then you just ask at the bottom if they want to start over and write your conditional statement in the while portion appropriately.
pls take the time to read through
Solution to the problem
do-while loop
What you're looking for is a while loop that this answer suggests, however you can specify whether to force the user to retry, or break the program and throw an error.
If you'd like to make the user retry and not throw an error that makes the program break, possibly with a retry message every time the user inputs negative numbers, you can use a do-while loop. The do-while loop will execute as "do this then check" rather than the while loop being "check than do this" (you can ensure that your code is more concise this way).
The do-while loop version:
int input; // Declare the variable to be initialized inside the do {} block.
int storeSales; // You can just relax and declare here.
do { // This is the start of the do-while loop
System.out.print("..."); // Your prompt goes here
storeSales = scanner.nextInt(); // Grabbing input from the user
if (storeSales < 0) { // Checking if the input is smaller than 0
System.out.print("..."); // Your message when input is invalid
}
} while (storeSales < 0); // The condition goes here
The caveat of the do-while loop for situations like this is for having conditions in the while loop that the do block will be always executed at least once, requires a variable that isn't initialized first but initialized in the loop itself. Initializing a "user input" variable but then giving it a value of "value that makes a statement work" makes the code awkward and dirty.
while loop
The while loop version will look like this:
int storeSales = -1; // You have to initialize first here, since the while is checked first.
while (storeSales < 0) { // Awkward!
System.out.print(""); // Your prompt goes here
storeSales = scanner.nextInt(); // Grabbing input from the user
if (storeSales < 0) { // Checking if the input is smaller than 0
System.out.print(""); // Your message when input is invalid
}
}
Exceptions
If instead, you'd like to break the program when the input is invalid (smaller than 0):
Introducing the throw statement:
Try this code out:
public class BarChart {
public static void main(String[] args) {
System.out.println(5 / 0);
}
}
You'll yell at me: WTF is this, you're making a program that throws ArithmeticException runtime exception! Division by 0 doesn't make sense!
Well, that's the point. Exceptions in Java are those that happen during runtime because of some condition that doesn't have to do with syntax, clear mistakes like String x = 0, etc. That's the kind of exception you're looking for. To throw such an error similar to the example above , use the throw statement and don't use a loop:
int storeSales = scanner.nextInt();
if (storeSales < 0) {
// Since the exception is related to math, you can use something like ArithmeticException. Your choice though.
throw new ArithmeticException(); // An exception is also an object, so you initialize it that way.
}
CAVEAT, Java doesn't expect exceptions in the first place, and so you have to declare that your method throws exceptions. Even main(). And when you call OTHER methods that ALSO have exceptions, you either have to handle them with a try-catch block, or leave it and add the exceptions to the method definition. But that's for another day I guess.
General improvements
You're doing the same thing, same code, same names (essentially), same print() statements a hard-coded 5 times! You can use a for loop. Unless your names have to be unique and declared separately (which I digress, you names are literally store1, store2, store3, etc.) you can just use a general, reinitialized variable name in every iteration of the for loop.
You can also scan the user input about how many stores (instead of hard-coding 5) to show the data, to make the program completely soft-coded and dynamic (The assignment probably doesn't require you this, refactor the code to your needs)
This code below will be grabbing the user input, then printing it out INSTANTLY AFTER. Now that I look at your solution, maybe it was right after all to define separate variables instead of putting the input in an array, since you want all the input at once then print everything at once.
Here's how it goes:
// You'd want to reformat the code to your preference.
import java.util.Scanner;
public class BarChart {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int storeCount = scanner.nextInt();
for (int i = 0; i < storeCount; i++) { // A loop that repeats 5 times.
// Choose one of the three solutions above and insert them here, I choose the do-while since it's the cleanest
int storeSales;
do {
// You can "concatenate" strings (numbers becomes themselves but in text)
System.out.print("Enter today's sales for store " + (i + 1) + ": ");
storeSales = scanner.nextInt();
if (storeSales < 0) {
System.out.print("Sales cannot be negative, please try again");
}
} while (storeSales < 0);
// Now that the storeSales value has been definitely initialized (or you chose the exceptions solution, I don't blame you) the printing goes here.
System.out.println("Store " + (i + 1) + "'s sales:");
for (int j = 0; j < storeSales; j += 100) {
System.out.print("*");
}
System.out.println();
}
}
}
There's not much to do with your code otherwise, since without the use of arrays, the best you can do is define separate variables, then having a method or two (a reusable piece of code with a name) to do the inputting and printing job for you to make the code cleaner and less repetitive.
In the end, just choose one of the three solutions and apply them to each of your variables. Your code is quite good (if it's intended this way). CHEERS!
oh my god someone read till the end of the post i love you
Scanner keyboard = new Scanner(System.in); // initialize scanner
while (true) { // infinite loop starts
<Do something...> // here you can do the things you need to do (e.g., change variables or record input)
if (condition) { // condition for exiting the loop (e.g., input of positive number)
break; // exiting infinite loop
} // end of IF statement
} // end of WHILE statement
You can use it as separate method and validate each input. It will not let the user to proceed until the valid value will be inputted.
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.
I'm doing the Java Associate level certification and while we are expressly told we won't be tested on labels, we have been shown them. Looking on here though the advice seems to be never use labels?
I'd like to use them in a catch block/user input console as a means of validating input.
do {//Keep calculator going as long as user wants
numInputCheck:
do {
try {//Force user to input a whole number
System.out.print("\nPlease enter the Mark you want to Calculate\n(Enter marks between " + GradeCalculator.getMIN_MARK() + " and " + GradeCalculator.getMAX_MARK() + " only): ");
mark = Integer.parseInt(scn.nextLine());
}catch(NumberFormatException nfe) {
System.out.println("\nInvalid entry - Please ensure entry is a number only.");
continue numInputCheck;
}
gradeCalc.isValidMark(mark);//Ensure input is within valid range
}while(!gradeCalc.getIsValidMark());
*etc*......
Is this bad coding?
EDIT: The code above wasn't doing what I thought it was/wanted it to do - it wasn't actually jumping back to the label at all.
I ended up changing the code to
do {//Keep calculator going as long as user wants
do {//Force user to enter number within valid range
do {//Force user to enter a whole number
try {
System.out.print("\nPlease enter the Mark you want to Calculate\n(Enter marks between " + GradeCalculator.getMIN_MARK() + " and " + GradeCalculator.getMAX_MARK() + " only): ");
mark = Integer.parseInt(scn.nextLine());
isValidInput = true;
}catch(NumberFormatException nfe) {
System.out.println("\nInvalid entry - Please ensure entry is a number only.");
isValidInput = false;
}
}while(!isValidInput);
}while(!gradeCalc.isValidMark(mark));
which I'm fairly sure is working correctly.
Anyway, I think I answered my own question - labels are discouraged because people like me try to use them.
No this is not actual example because continue can do all the job by itself without the help of the label .
A good example is when you have 2 nested loops and you want to break the outer loop from a condition in the inner loop
outerloop:while(condition1) {
while(condition2) {
if(condition3)
break outerloop;
}
{
Continue statement skips all sentences above, you have to use break sentence for stopping the loop. Labels are useful for more than one loop, for example:
label1:
for (int i = 0 ; i<10; i++){
for (int j = 0 ; j<10; j++){
if (i+j = 3)
break label1;
}
}
OK so this is my first post here. (Be kind to me :)) I'm like two weeks old to java and wanted to create an app that can do the jobs of a total, average and average grader.
My question here is. How can I return to a specific line of code after one operation has ended
Eg: I want the code to runString menu1="Input the number of the operation you desire "; after the total or average has been found.
Thanks in advance
import java.util.Scanner;
public class grader
{
public static void main (String args[])
{
Scanner input=new Scanner(System.in);
System.out.println ("Input your Chemistry marks");
float a= input.nextFloat();
System.out.println ("Input your Biology marks");
float b= input.nextFloat();
System.out.println ("Input your Physics marks");
float c= input.nextFloat();
String menu1="Input the number of the operation you desire ";
String op1="1. Total ";
String op2="2. Average ";
String op3="3. Grade ";
String op4="4. Exit ";
System.out.println (menu1+op1+op2+op3+op4);
Scanner menuselect=new Scanner(System.in);
int option= input.nextInt();
float tot=(a+b+c);
float avg=((a+b+c)/3);
if (option==1)
System.out.println ("Your total is "+tot);
else if (option==2)
System.out.println ("Your average is "+avg);
else if (option==3)
if (avg<0.0)
System.out.println ("Please input proper data");
else if (avg<=49.9)
System.out.println ("Fail");
else if (avg<=69.9)
System.out.println ("Pass");
else if (avg<=100.0)
System.out.println ("Excellent");
else
System.out.println ("Please input proper data");
}
}
You should use the do-while loop. How it works is it executes some code, checks to see if a condition evaluates to true, and if so, executes the code again.
do {
//your code here
}
while (/*some condition*/);
Usually when you want to repeat one or more lines of code, you do so using a loop. In general, a loop is set up like this:
while(loopGuard){
//code to repeat
}
Where loopGuard is some boolean statement that gets updated inside your loop. The code inside the loop will continue executing until your loopGuard statement is no longer true.
In your case, you may want to loop until the user presses a certain button, until it has run a certain number of times, or any other arbitrary reason you have chosen. The main thing to remember is to make sure that your loop guard will eventually become false, otherwise you'll find yourself in an infinite loop.
In your case you should use a while loop with the usage of continue and break. A second option, you can use a labeled break statement (explained here).
Btw, in java language there a goto keyword. But it's not implemented (or removed). Read here for more details.
I would suggest a do - while loop . A do while loop runs at least once , which is necessary as you're program needs to be run at least once . Put all the statements from Input the operation number to the calculating statements under do while loop . It should work out just fine .
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.