I'm trying to make it for that the program will continue to request input of a 5 digit number until the user gives a 5 digit number. When I run the following:
//import scanner to read keyboard input
import java.util.Scanner;
class NumberInverter {
public static void main(String[] args) {
//create a new Scanner object in the memory that reads from the input System.in
Scanner keyboard = new Scanner(System.in);
//display message propmt and input for number
//conditional statement loop to check if the length is any number other than 5
do {
System.out.print("Enter any 5 digit whole number you wish to invert!");
int num = keyboard.nextInt();
int numSize = String.valueOf(num).length();
} while(!isValid(numSize));
}
private static boolean isValid(int numSize){
if(numSize != 5){
System.out.println("Oops! Looks like you gave a number that isn't exactly a 5 digit whole number. Try again!");
return false;
} else return true;
}
}
I get the following error:
NumberInverter.java:20: error: cannot find symbol
} while(!isValid(numSize)); ^
symbol: variable numSize
location: class NumberInverter
1 error
I've tried a bunch of different things, can anyone fluent in java help me out I'm very new?
Thanks ahead of time!
The variable numSize is not in the same scope as the while condition check.
In Java, any variable declared inside a block (a region surrounded by {}) cannot be accessed outside of that block. In this case, since you are declaring numSize right inside the loop, the loop's condition (which is outside that block) cannot access it. Each block creates something called a "block scope", and variables created in there cannot be accessed outside it.
The fix for this is very simple: Declare the variable in the same scope as the while loop. This can be done by putting it right above the do. Notice that you only need to int numSize;, outside, once. You don't put int when you are assigning to it inside the loop, you just do numSize = .... since you are assigning to a previously-declared variable.
You can still assign to the variable from inside the loop, but since it was originally declared outside the loop, stuff outside the loop can access it.
int numSize;
do {
System.out.print("Enter any 5 digit whole number you wish to invert!");
int num = keyboard.nextInt();
numSize = String.valueOf(num).length();
} while(!isValid(numSize));
Some more information about scopes can be found at What is 'scope' in Java?.
Num size is declared inside the loop scope, you're trying to access it outside that scope. For this to work, declare numSize just before the do statement and assign it within the loop. This way, the variable is visible in the whole statement and also inside the loop (for assignment).
int numSize;
do {
// The rest of your code, all variables declared here are
// gone outside the brackets, however you can access the ones
// in outer scopes.
numSize = String.valueOf(num).length();
} while(!isValid(numSize));
See this for more information about different types of scope: https://www.geeksforgeeks.org/variable-scope-in-java/
Create a local variable numSize.
For exemple :
//import scanner to read keyboard input
import java.util.Scanner;
class NumberInverter {
public static void main(String[] args) {
//create a new Scanner object in the memory that reads from the input System.in
Scanner keyboard = new Scanner(System.in);
int numSize;
// int numSize;
//display message propmt and input for number
//conditional statement loop to check if the length is any number other than 5
do {
System.out.print("Enter any 5 digit whole number you wish to invert!");
int num = keyboard.nextInt();
numSize = String.valueOf(num).length();
} while(!isValid(numSize));
}
private static boolean isValid(int numSize){
if(numSize != 5){
System.out.println("Oops! Looks like you gave a number that isn't exactly a 5 digit whole number. Try again!");
return false;
} else return true;
}
}
Related
This question already has answers here:
try/catch with InputMismatchException creates infinite loop [duplicate]
(7 answers)
Closed 7 years ago.
I am currently working on some Java code in Eclipse and trying to use a try-catch statement inside of a do-while statement. My current code is as follows:
import java.util.Scanner;
import java.util.InputMismatchException;
import java.util.Random;
public class GG_HighLowInvalid{
public static void main(String[] args){
Scanner cg = new Scanner(System.in);
//Assign and define variables
int guess, rand;
guess = 0;
rand = 10;
//Create loop
do
try{
guess = 0;
//Ask for a guess
System.out.print("Enter your guess: ");
//Record the guess
guess = cg.nextInt();
}
catch(InputMismatchException exception){
System.out.println("Your guess must be an integer.");
}
while (guess != rand);
}
}
When I put in any number, the code works fine and will loop to ask for another input and when 10 is entered, the code stops as it is supposed to (because guess becomes equal to rand). However, if I put in anything that is not an integer (such as "No"), an infinite loop occurs where the output prints the following:
"Your guess must be and integer."
"Enter your Guess: Your guess must be an integer."
"Enter your Guess: Your guess must be an integer."
"Enter your Guess: Your guess must be an integer."
repeating forever until the program is externally terminated.
Since the while statement is (guess != rand), why is a non-integer causing this infinite loop? Shouldn't the manual input under the try-statement be called again? Any assistance in understanding this would be greatly appreciated. Also, I am pretty new to Java, so sorry in advance if I am having simple issues.
When a scanner throws an InputMismatchException, the scanner will not
pass the token that caused the exception, so that it may be retrieved
or skipped via some other method.
Currently, your Scanner is not moving ahead to read the next input but reading the same continuously. You have to explicitly call some method which can read this incorrect value which was not expected. For example, scanner.next() call in catch block can avoid this infinite loop.
Use the following code:
catch(InputMismatchException exception){
cg.next();
System.out.println("Your guess must be an integer.");
}
After you have unsuccessfully read buffer its value isn't emptied and next time when it came to cg.nextInt() it tries to read same wrong value, and you went to loop. You need "to empty buffer", so next time it will read correct value.
You dont need to use a try catch statement. You just have to check if it is an integer or not with the hasNextInt() method of your object scanner. This is an example, it will solve your problem:
public static void main(String[] args) {
Scanner cg = new Scanner(System.in);
boolean valid = false;
//Assign and define variables
int guess, rand;
guess = 0;
rand = 10;
//Create loop
do{
System.out.println("Enter your guess: ");
if(cg.hasNextInt()){
guess = cg.nextInt();
valid = true;
}else{
System.out.println("Your guess must be an integer.");
cg.next();
}
}while (!valid || guess != rand);
}
Try resetting your variable "guess = 0" in catch block.
Below is some code asking the user to input an integer.
public int getValidInput() {
Scanner user_input = new Scanner(System.in);
do {
System.out.println("Enter an integer >=1 and <=10: ");
int number = user_input.nextInt();
} while (number > 10 || number < 0);
return number;
}
The code as shown does not work although when I initialise number outside the do command i.e. set it to int number; and then in the do loop set number = user_input.nextInt(); it does. Why does it work in one case and not the other?
Because in Java, variables are scoped to the block in which they're declared. In your example, the int number = is within the do...while block, and so the variable only exists within that block.
By moving the declaration out of the block, into the block for the method, the variable exists for the method's entire block (including nested blocks).
Your problem is that you have defined number inside your loop. Variables are scoped in Java, so variables declared inside loops or if statements are not accessible outside those loops or if statements. You can fix your code, simply by moving the declaration, as shown below:
public int getValidInput() {
Scanner user_input = new Scanner(System.in);
int number;
do {
System.out.println("Enter an integer >=1 and <=10: ");
number = user_input.nextInt();
} while (number>10 || number < 0);
return number;
}
The curly braces {} of the do-while open up a so called scope (they always do, wether in methods or loops or ifs). Any declaration inside a scope is only visible while you are within that scope, and also in any inner scope opened within the scope.
The condition of your while is outside the curly braces, so it does not see any variable declared within them. If you put the int number; before the do, it's on the same scope level like the while condition, so it, along with the value it gained inside the loop, is visible to the expressions in the condition.
Conditions are used to enter a body from outside that body, so the variable which decides the truth value of condition has to exist before the body.
And as the body block of do-while loop is the code to be executed, therefore the code which decides to execute it must be other than itself.
The scope of a variable restricted to {}. outside of that braces you cannot access. When you initialised it on top it access across both do and while as the scope is increased.
This method is supposed to return the integer that the user enters as long as it is only an integer (not a String, float, etc.) and as long as that integer is one of the options in the given list of options. I want to use this method throughout my program whenever I give the user a list of options they need to choose from. These lists will have varying sizes thus I pass as an argument the maximum value (maxValue) that the user could possibly choose thus giving the method the size of the list.
//This method handles the players input and checks if the number entered is one of the options listed or not
public static int response(int maxValue){ //the parameter is the number of options in the particular list
response = new Scanner(System.in);
Boolean check = true;
while(check){
try{
int yesOrNo = response.nextInt();
if(yesOrNo > maxValue || yesOrNo <= 0){ //checks if the int entered does not exceed the list size or go below zero
System.out.println("I'm sorry, that number was not one of the options. Please reselect your choice.");
}else{
check = false;
}
}catch(Exception e){ //catches an exception when the user enters a string or anything but an int
System.out.println("Please only use digits to make a selection.");
response(maxValue);
}
}
return yesOrNo; //returns the user's response. Well, it is supposed to.
}
I am a beginner with regards to programming. I am learning Java through online tutorials and trial and error on dumb, little programs I make. I am working on a fun little text-adventure and am still in the beginning stages.
The trouble I'm having is because this method will only return 0. Isn't yesOrNo being assigned the integer that the user inputs through the scanner response? Why is it only returning 0?
Thank you for your responses. I understand now that I needed to declare my int yesOrNo outside of the try because it was out of scope, as you all put it, being declared within.
BUT a few mentioned 'there is a completely unnecessary function call in the catch block'. The only problem is if I remove it there is an infinite loop created with the System.out.println("Please only use digits to make your selection.") when the user inputs Strings or other non-int values.
Here is my updated code:
//This method handles the players input and checks if the number entered is one of the options listed or not
public static int response(int maxValue){ //the parameter is the number of options in the particular list
response = new Scanner(System.in);
Boolean check = true;
int yesOrNo = 0;
while(check){
try{
yesOrNo = response.nextInt();
if(yesOrNo > maxValue || yesOrNo <= 0){ //checks if the int entered does not exceed the list size or go below zero
System.out.println("I'm sorry, that number was not one of the options. Please reselect your choice.");
}else{
check = false;
}
}catch(Exception e){ //catches an exception when the user enters a string or anything but an int
System.out.println("Please only use digits to make a selection.");
response(maxValue);
}
}
return yesOrNo; //returns the user's response. Well, it is supposed to.
}
After reading other post before just asking another question I found many others facing the same issue. It was correct what some were saying that the infinite loop was created because when the Scanner encounters an error it doesn't remove the token of that error thus causing the while loop to read the same error over again infinitely. Here is what i read exactly:
"As per the javadoc for Scanner:
'When a scanner throws an InputMismatchException, the scanner will not pass the token that caused the exception, so that it may be retrieved or skipped via some other method.'
That means that if the next token is not an int, it throws the InputMismatchException, but the token stays there. So on the next iteration of the loop, getAnswer.nextInt() reads the same token again and throws the exception again. What you need is to use it up. Add a getAnswer.next() inside your catch to consume the token, which is invalid and needs to be discarded."
So now that infinite loop problem is fixed :) Onto finding what else I need to learn. Thank you.
yesOrNo goes out of scope because you declared it within the try block. Move the declaration outside to where it is in scope when you return it.
Boolean check = true;
int yesOrNo;
yesOrNo you're returning is not same as
int yesOrNo = response.nextInt();
in your loop. The yesOrNo from the loop disappears (goes out of scope) at the closing } of try.
There has to be another int yesOrNo somewhere. Look for it.
The only this can compile is if yesOrNo is declared as a class or instance variable, unseen in this code snippet.
The declaration of yesOrNo that we do see is declared inside a try block, shadowing the yesOrNo being returned. But there's no reason for it to be a class or instance variable.
Remove it from the class declaration, and declare it locally, before the try block, so it's in scope when it's returned.
int yesOrNo = 0;
try{
yesOrNo = response.nextInt();
I see "int yesOrNo" inside while loop. The value read inside while loop scope is limited to that. Declare that variable outside and try.
I want to make my program loop until the user types in x instead of a number. I tried using a while statement but I do not know how to use it with multiple variables. Here is my code
public static void main(String[] args)
{
int denominatorOne = 1, numeratorOne = 1;
System.out.println("Welcome, type an \"x\" at any point to exit the program");
while (numeratorOne !=x)
{
Scanner in = new Scanner(System.in);
//Prompt the user for fraction one
System.out.print("Enter the first numerator (top number): ");
numeratorOne = in.nextInt();
System.out.print("Enter the first denominator (bottom number): ");
denominatorOne = in.nextInt();
}
}
The exact phrasing from my assignment is The program should run in loop and allow the user to exit with some special character input (e.g. x or X to exit)
First off, 'x' isn't a number and won't be accepted by nextInt or a comparison to 'x', you should trying checking to see if it has next int (in.hasNextInt()) and process depending. Besides the point, you can easily test two variables in a while loop. Assuming you set up the variables right to be chars:
do {
// scan code.
} while(!(numChar1.equals('x') && numChar2.equals('x')))
what you need to do is have a bool value that holds the loop and when have a if statement check for the keydown event in the loop
bool looping = true
while ( looping == true)
{
if (x button was pressed == true)
{looping = false
}
}
try changing it to
while(!numeratorOne.equals("x")){...}
You can just call the method over again in this case main();.
What I suggest however is to create a new method, in the method just checking the users input returning the input as a string. Then you can check the string in your main method, and if that's not the string you wanted then recall the method. Here's an example, please note I didn't use an IDE for this.
public String getMessage(){
Scanner input = System.in();
return input;
}
public void checkMessage(String wantedString){
if(!getMessage().equalsIgnoreCase(wantedString)){
System.out.println("Please retry");
checkMessage();
}
}
public static void main(String[] args){
checkMessage();
}
In order to make my program more streamlined (Without try and catch everywhere), I tried to create a seperate method just for getting data. I have one for Doubles, and Strings, as well.
For some reason, when I try to use this method, it is completely ignored, and passed by like a comment. Is there something I'm doing wrong?
public int inputint(){
Scanner sc = new Scanner (System.in);
int variable = 0;
boolean valid = true;
do{
try{
if (variable >= 0 && valid){
}
else if(valid){
System.out.print("Please enter positive values only: ");
}
valid = true;
}
catch (InputMismatchException e){
System.out.print("Please enter numerical values only: ");
sc = new Scanner(System.in);
valid = false;
}
}while (!valid || variable < 0);
return variable;
}
Well first of all, you're code is insanely hard to understand. (or could just be me I guess)
But if you look at your code
Scanner sc = new Scanner (System.in);
int variable = 0;
boolean valid = true;
You are creating the Scanner object, but nowhere in the method are you actually using it.
The next few lines,
if (variable >= 0 && valid){
}
both of those conditions are met. So with nothing in the brackets, no code is executed. So from there, it just returns the value of the variable, which is 0.
So you need to actually use your Scanner class to grab an integer. Which I believe, though I'm not sure, the method for that is
Scanner.nextInt();
Edit: From the JavaDocs http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Scanner.html
You can simply use
Scanner sc = new Scanner(System.in);
int i = sc.nextInt();
to read an integer from the Scanner.
Your variable variable is assigned 0 and the valid variable is assigned true. Consequently, the while (!valid || variable < 0) expression will always be evaluated to false and the do-while loop will only be executed once (without the Scanner ever being created).
I guess that you would like to read the user input before checking the variable variable, so you would probably like create the Scanner and read the input before doing the if (variable >= 0 && valid) check.
Side note, you can probably skip the valid variable and use variable =sc.nextInt();, compare with #Austin's answer.