My code is supposed to keep looping until a valid input is given, ie: if a letter is given it will loop, but if a valid number is given, the code should store it into cSec. Is there anyway to do this?
byte cSec;
boolean contCSec = true;
while(contCSec == true) {
System.out.println("Enter course section: ");
cSec = sc.nextByte();
if(cSec>0)
contCCode = false;
}
cSec can't be used outside the loop.
A rather less verbose form of what you wrote might be:
byte cSec;
do {
System.out.println("Enter course section: ");
cSec = sc.nextByte();
} while (cSec <= 0);
where 'cSec <= 0' denotes an invalid value, per your original, though I imagine there's more to validation than that.
This does not match your title (initialize within loop) since to me that's exactly what you don't want to do.
I think this is clearer than your original since it involved no flag values, and the do...while loop shows up the 'ask then decide to loop' nature a little better.
Adding more validation:
byte cSec;
do {
System.out.println("Enter course section: ");
try {
cSec = sc.nextByte();
}
catch (InputMismatchException ex) {
System.out.println("A number is required");
cSec = -1;
}
} while (cSec <= 0);
In addition to another-dave's wonderful answer, you can suppress the compiler warning by initializing cSec outside of the loop.
byte cSec = 0;
boolean contCSec = true;
while(contCSec == true) {
System.out.println("Enter course section: ");
cSec = sc.nextByte();
if(cSec>0)
contCSec = false;
}
The reason that you get the warning without the first declaration is because, as strange as it sounds, the compiler does not analyze the contents of your boolean in while(contCSec == true). It sees that there is a while loop, and it sees that there will be a boolean resulting from (contCSec == true), but as far as the compiler is concerned, any boolean going into your while condition could be true, or could be false. This means that you could enter the while loop, or you could... not.
As far as the compiler is concerned, anything inside the while loop could happen, or could not happen, and there is no way to know without actually running the code. (If you want to know why this is actually a strict limitation for computers, check out the halting problem.) That means that the compiler has no idea whether cSec = sc.nextByte(); will ever happen or not. Hence, the warning.
Related
For example, like this.
while ((input = kb.nextInt()) != 0) {
if (input % 2 == 0) {
System.out.println("even");
} else {
System.out.println("odd");
}
instead of only checking the value of the input variable inside the condition and getting the number from Scanner inside the loop, like so:
while (input != 0) {
input = kb.nextInt();
...code here...
Just wondering if the first one is bad practice or anything like that.
Using nextInt() as part of a loop condition, while perfectly legal, can be problematic from the standpoint of dealing with errors arising from bad input. Actual humans sitting in front of a keyboard entering data (which the Scanner variable name kb seems to suggest is exactly what you're dealing with here) are notoriously unreliable in terms of their data entry quality, so bad input is something you should be prepared for.
nextInt() will throw an InputMismatchException exception if the next available input is not a valid representation of an integer. In order to catch and handle this exception, the nextInt() call must be executed inside of a try block. However, with the nextInt() being part of the control condition of the while loop, the only way to do that is to enclose the entire loop in the try block:
try {
while ((input = kb.nextInt()) != 0){
...
}
} catch (InputMismatchException ime){
...
}
Unfortunately, this means that any exception raised by nextInt() will kill the while loop. If you wanted to keep processing user inputs after an input error, you'd have to provide a means of starting the while loop over again, and keep starting it over until the "real" user-signaled end-of-input condition had been reached. You might be able to do it with a clunky workaround like this one:
boolean keepGoing = true;
while (keepGoing){
try {
while ((input = kb.nextInt()) != 0) {
...
}
keepGoing = false;
} catch (InputMismatchException ime) {
String junk = kb.next();
System.out.println("Didn't understand your input: " + junk);
System.out.println("Please type a valid integer");
}
}
But depending on what the ... code inside the loop was doing, this relatively simple workaround might be inadequate; you might need something even more complicated and unreadable.
But by moving the nextInt() call out of the control logic of the loop and into the loop body, you gain considerable flexibility in terms of your options for recovery from bad input. With nextInt() inside the loop body, you can now catch and handle any exception entirely within one iteration of the loop, without having to terminate the loop itself:
do {
try {
input = kb.next();
if (input != 0) {
...
}
} catch (InputMismatchedException ime) {
String junk = kb.next();
System.out.println("Didn't understand your input: " + junk);
System.out.println("Please type a valid integer");
}
} while (input != 0);
You'd also have the option of avoiding an exception altogether by using hasNextInt() to ensure that a valid input is present before trying to read it with nextInt():
for(;;) {
if (!kb.hasNextInt()) {
String junk = kb.next();
System.out.println("Didn't understand your input: " + junk);
System.out.println("Please type a valid integer");
} else {
input = kb.nextInt();
if (input == 0) {
break;
else {
...
}
}
}
The second one doesn't have the input defined for testing the condition input!=0 hence the first one is right but if you're going to use the second format I'd suggest to change the while loop to do-while loop.
Your two code samples are not equivalent and do different things (the second version probably doing not what you want it to do).
You would need another if (input != 0) inside the loop and assignment of input before the loop for the second version. Moving the assignment to the end and duplicating it before the loop is also a viable option:
input = kb.nextInt();
while (input != 0) {
if (input % 2 == 0) {
System.out.println("even");
} else {
System.out.println("odd");
}
input = kb.nextInt();
}
And the duplicated first and last line in this version is very likely the reason for the somewhat complicated code. This type of loop loop ((x = input()) != 0) can be seen in a lot of C code but is sometimes "required" in Java too when you want to reduce code-duplication when processing input. This is caused by the fact that nextInt returns a value and mutates the underlying state.
Trying to create a simple program that has three options for text input. If the user types one of the three, the program moves on. If the user types something else, the program loops back and asks for the input again until a proper response is given.
Using a drop down list or other method will not work, as this is for an assignment.
System.out.print("Enter one of the following: cheese, water, or burger: ");
userMedium = user_input.nextLine( ); // store user input as a string
mediumConvert = userMedium.toLowerCase();
boolean verifyName;
if (mediumConvert.equals("cheese") || mediumConvert.equals("water") || mediumConvert.equals("burger")){
verifyName = false;
} else {
verifyName = true;
}
while (verifyName = true){
System.out.println("Please input a valid medium (cheese, water, or burger): ");
userMedium = user_input.nextLine( );
mediumConvert = userMedium.toLowerCase();
}
This is what I have set up so far, but this just keeps repeating the loop OVER AND OVER. After this section I want to execute a switch to work off each of the three correct responses.
I've spent the last hour on google and YouTube, but everything I found is using integers. It seems pretty easy to validate user input when it is just a number and an operand. But how do I use three possible strings?!
while (verifyName = true)
↑
You're assigning and not comparing. The expression of the assignment returns the assigned value, so your loop is equivalent to:
while (true)
You should change it to:
while (verifyName)
Basically, you should write while (verifyName == true), but it's redundant since it's like asking "Is it true that verifyName has the value true?". Also it prevents potential bugs, like just inserting one = instead of two..
Noticed two things:
1.) By doing
while(verify = true)
you are actually assigning the value true to verifyName. You need to use
while(verifyName)
2.) Where do you reassign the value of verifyName?
You should be validating and reassigning inside the while block.
Also you should consider cleaner alternative solution, but that can wait for another day.
You will never break out of the whileloop because the variable verifyName is never updated inside the loop. This means that you'll either never execute the loop because the user inserted the input you wanted or you'll end up with an infinite loop.
You need to do your input verification inside the loop as well and be careful with the boolean validation as well.
Something like:
while (verifyName) {
System.out.println("Please input a valid medium (air, water, or steel): ");
userMedium = user_input.nextLine( );
mediumConvert = userMedium.toLowerCase();
if (mediumConvert.equals("cheese") || mediumConvert.equals("water") || mediumConvert.equals("burger")){
verifyName = false;
} else {
verifyName = true;
}
}
I am attempting to validate user input. I have tried some if statements and attempted Boolean. I cant get anything to give the output or rather the validation I am wanting
Users are asked to choose between "red" or "blue" I want them to be required to type either "red" or "blue". I know this could be solved easier through buttons but I am trying to use string input. the code below give an example of where i am.
custColorMsg = "Which color do you want your shirt to be red or blue?";
customerColor = getstringInput(custColorMsg);
String color = null
if( customerColor.equalsIgnoreCase("yes")) {
color = true}
if( customerColor.equalsIgnoreCase("no")) {
color = true}
else if(!customerColor.equalsIgnoreCase("yes" || "no") {
color = false}
I know this last portion is wrong I am just unsure how to go about fixing it. Customers will have three chances to input a valid response then the program will terminate, this portion i can handle. If i can just figure out how to accept "yes" or "no" and refuse anything else.
In terms of the design of this program, I would recommend adding a for loop, that goes from 0 to 2 (this will iterate 3 times). Within the loop, the program can determine what the user's input is. I would also recommend looking at my syntax for the for loop below, I use ifs, else ifs and elses to evaluate the data set more efficiently.
The implementation of the program could be:
for(int i = 0; i < 3; i++)
{
customerColor = getstringInput(custColorMsg);
String color = null
if( customerColor.equalsIgnoreCase("yes")) {
color = true;
break;
}
else if( customerColor.equalsIgnoreCase("no")) {
color = true;
break;
}
else{
color = false;
}
custColorMsg = "Invalid Input, Please Input Again";
}
This will give the user 3 times to input the data, and if they input it correctly, it will stop asking, however, if they do not, it will ask again until they run out of attempts.
There's a few things wrong with your approach.
The semantics of your variable names are a bit off. Which makes the code difficult to read. For example, the variable color which you have defined here as a String, but consistently use as a Boolean is a bit confusing. I'm guessing you mean to define it as a Boolean type and intend to use it as the breaking condition from your loop - it would be more meaningful to name the it as isValidColor or something along those lines.
The following line doesn't do what you think it does:
customerColor.equalsIgnoreCase("yes" || "no")
The method equalsIgnoreCase() takes in a String and not a Boolean like this line of your code will have for an argument. Since the || will resolve to a Boolean value of true or false. Furthermore, those are bad operand types for that operator and the code won't compile.
For your control structure you can use a while loop which will exit when you have reached the max amount of tries or entered a valid response.
Here's a working Console version of what you are trying to accomplish:
String custColorMsg = "Which color do you want your shirt to be red or blue?";
String customerColor;
Boolean validInput = false;
Scanner in = new Scanner(System.in);
int tries = 0;
while (tries < 3 && !validInput)
{
System.out.println(custColorMsg);
customerColor = in.nextLine();
if( customerColor.equalsIgnoreCase("red")) {
validInput = true;
}
else if( customerColor.equalsIgnoreCase("blue")) {
validInput = true;
}
tries++;
}
What the program does: Reads two values from input, asks user whether to add, subtract, or find the product. If user enters one of the three options, it calculates, otherwise the program will loop back to the beginning. The program should STOP after calculation if the user enters one of the three options.
I'm not sure why it keeps on looping. How do I make the script loop only when the user types in a string other than "sum", "difference", or "product"? Also, how can I make the code simpler? Is there any way to loop the program without using do ... while?
import java.util.Scanner;
import java.util.Random;
public class simp_calculator
{
public static void main (String[] args)
{
Scanner scan = new Scanner (System.in);
double a, b;
String response;
boolean noresponse;
do
{
System.out.println ("Please enter first number.");
a = scan.nextDouble();
System.out.println ("Please enter second number.");
b = scan.nextDouble();
System.out.println ("Would you like to find the sum, difference, product?");
response = scan.next();
if (response.equalsIgnoreCase ("sum"))
{
System.out.println (a + b);
}
if (response.equalsIgnoreCase ("difference"))
{
System.out.println (a - b);
}
if (response.equalsIgnoreCase ("product"))
{
System.out.println (a * b);
}
else
{
noresponse = true;
System.out.println ("Starting again...");
}
}
while (noresponse = true);
}
}
You are using the assignment operator, =, so noresponse will always be true. The result of the assignment expression is thus true.
You want to check if it is true, so use the comparison operator ==:
while (noresponse == true);
or, because it's already a boolean:
while (noresponse);
Also, you may be getting a compiler error that noresponse may not have been initialized. You will need to make sure that it's initialized in all cases, and that something sets it to false so the loop will eventually end.
change while (noresponse = true); to while (noresponse == true);.
= is an assignment operation - where as == comparison.
Two errors:
The else applies only to the last if; so for any value, other that "product", noresponse becomes true and the loop goes on. Replace all your ifs from the second on with else ifs.
noresponse should be given the value false at the beginning of the loop.
There are 2 issues:
Currently you are looping while noreponse equals true. So to exit that loop, you need to setnoresponse to false when a particular condition is met :) I could give you the answer, but you should be able to figure it out with the info I've given you. (hint: at some point you need to set noresonse to false).
Also, you are setting noresponse to equal, rather than comparing it. You need to use == to compare.
So make while (noresponse = true); into while (noresponse == true);.
just change while (reponse = true) to while(reponse) and name the variable ..
I am trying to make a test of whether an inputted word is a palindrome or not (the same spelled forward and backward). From what I can see it should work but Eclipse says "The value of the local variable isPalindrome is not used" , but it is used. The problem is that even if the word is not a palindrome it says it is.
import java.util.Scanner;
public class Palindrome {
public static void main(String[] args) {
String phrase;
char[] phraseLetters;
int endChar;
boolean isPalindrome;
Scanner input = new Scanner(System.in);
System.out.println("Enter a word or phrase.");
phrase = input.nextLine();
input.close();
phrase = phrase.toLowerCase();
phrase = phrase.replaceAll(" ","");
phraseLetters = phrase.toCharArray();
endChar = phraseLetters.length - 1;
for (int i = 0; i < phraseLetters.length; i++) {
if (phraseLetters[i] != phraseLetters[endChar]) {
isPalindrome = false;
} else {
isPalindrome = true;
endChar -= 1;
}
}
if (isPalindrome = true) {
System.out.println("This word or phrase entered is a palindrome.");
} else {
System.out.println("This word or phrase is not a palindrome.");
}
}
}
EDIT: I have tried the if statement being
if (isPalindrome == true)
and
if (isPalindrome)
In both cases Eclipse says "The local variable isPalindrome may not have been initialized," in this if condition.
FINAL EDIT:
I have since moved on, and rewritten this code, however I just went back and fixed my original code if anyone still looks at this.
I initialized isPalindrome at the beginning of the code:
Boolean isPalinddrome = True;
I changed the for-loop condition to:
for (int i = 0; (i < phraseLetters.length) && (isPalindrome); i++)
Finally I changed if (isPalindrome = true) to if (isPalindrome)
if (isPalindrome = true) should be if (isPalindrome == true) (or if (isPalindrome) better! Actually this error is another good reason why not asking if someBoolean == true which is a bad style)
By typing if (isPalindrome = true) you're assigning, again, the value true to the variable isPalindrome. And since you're only assigning value to it, the compiler warns you about unused variable.
It's also good to know this:
At run time, the result of the assignment expression is the value of
the variable after the assignment has occurred. The result of an
assignment expression is not itself a variable.
So, when you do if (isPalindrome = true) then the if condition is always satisfied.
You should assing some boolean value to isPalindrome in the main scope.
For example:
boolean isPalindrome = true
You have a typo.
if (isPalindrome = true)
{
System.out.println("This word or phrase entered is a palindrome.");
}
else
{
System.out.println("This word or phrase is not a palindrome.");
}
Look at the if condition. You used = instead of ==. So, you are setting isPalindrome to true, only the true block is executed, and the compiler sees that isPalindrome never matters.
Now, your class has some logic flaws and some programming traps.
If the first and last characters are not equal, isPalindrome is set to false, and then the program continues. Break out of the loop; don't let isPalindrome be set to true later. Incidentally, your version actually cares only about the first and last characters.
Don't write if (x == true). Just write if (x).
Don't name your boolean isAnything. After all, you may do this in a JavaBean class, and then you'll end up with a method named isIsAnything or getIsAnything. This will annoy your readers.
In the future, don't write all your code in the main(String[]) method. Have the main method use the arguments to construct an instance of the class, and use that instance. This way, you can write unit tests for the class; you can't for main. You can break the code into a few methods. One checks for being a palindrome, while another provides the human-readable output.
It's actually a bad idea to use the no-argument forms of String.toLowerCase() and String.toUpperCase() One day, you might need to write an internationalized application, and you will have to deal with the Turkish locale. You might end up mumbling to yourself, “What the heck is a dotless i?”
Don't use i and j as variable names here. Use names that show the variable's purpose. Something like:
for (int start = 0, end = phraseLetters.length - 1; start < end; start++, end--) {
...
}
After all, when start passes end, you're just repeating yourself.
There are an error and bad practice here.
The bad practice is not to initialize the variabale:
boolean isPalindrome = true;
alththough all primitives in java have a default value (for boolean it's false) it's still always better to intialize the varibale explicitly in order enhance code redability.
The error is in the if clause:
if (isPalindrome = true) {
in this line you assign the value and not checking the variabale , all assigment return the value of the assignment meaning that this expression will always return true. Because of this your code always retrun true.