This question already has answers here:
Problem with "scopes" of variables in try catch blocks in Java
(3 answers)
Closed 6 years ago.
What is wrong with my code? I'm trying request prompt a user to enter a number if it is not between 1 and 6 or a number it should say invalid and prompt another try. The user may only have 3 tries.
import java.util.Scanner;
public class Game {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int[] numbers = new int[6];
System.out.println("Enter a number on a die from 1-6:");
String dieinput = input.next();
int invalidcount = 0;
System.out.println("Your number is: " + dieinput);
do{
try
{
// the String to int conversion
int dienum = Integer.parseInt(dieinput.trim());
int dienumOE = 0;
int count=0;
//test number input
if ((dienum >= 1) && (dienum<= 6))
System.out.println("number is " + dienum + oddoreven(dienum));
else
System.out.println("Invalid number, please enter a number 1-6");
count++;
System.out.println("Count" + count);
}
catch (NumberFormatException nfe){
System.out.println("Invalid number, please enter a number 1-6");
System.out.println("Count" + count);
}
while (count <= 3 && count >=0);
}
}
// Check if odd or even
public static String oddoreven(int num) {
String result;
if (num % 2 == 0)
result = "even";
else
result = "odd";
return result;
}
}
Your problem is "wrong" scoping: You can't use a variable within the catch block that is declared within the scope of the try block!
In other words; you need:
int counter = 0;
try { ...
} catch (...
if you want to use counter within both try and catch!
The "rule" is very simple: a variable is only visible up to that } that closes the "block" it is in.
That prevents you from actually compiling your code!
So, the real lesson here is more like: do not write 100 lines of code to then run the compiler. Only write as few lines as possible - every time when you think: this is "enough" to compile .. then compile. And then fix the errors reported to you. The java compiler is really good at giving you specific messages that tell you what you did wrong; but the more messy code you put up, the harder that gets!
And for the record: SO is not a "remote" compiler service that you should use to get your messy code to compile!
Related
I was given the task of splitting my program which which allows the user to enter an array of numbers and after an odd number between 1 and 10 to check whether the odd number is a factor of each of the 5 numbers in the array. I keep on trying out different ways but none seem to work. Could someone help me out or send a sample of how I should sort it? This is the program:
import java.util.Scanner;
public class CheckboxExample{
public static void main(String args[]) {
CheckBox c = new CheckBox();
new CheckboxExample(); // links to checkbox class
Scanner s = new Scanner(System.in);
int array[] = new int[10];
System.out.println ("Please enter 10 random numbers"); // prompts the user to enter 10 numbers
int num; // declares variable num
try{
for (int i = 0; i < 10; i++) {
array[i] = s.nextInt(); // array declaration
}
}catch (Exception e){
System.out.println ("You have an error");
}
System.out.println ("Please enter an odd number between 1 and 10");
try{
num = s.nextInt ();
if (num % 2 == 0){
do{
System.out.println ("\nYour number is even, enter an odd one");
num = s.nextInt ();
}while (num % 2 == 0);
}
if (num < 0 | num > 10){
do{
System.out.println ("Your number is outside of the range, try again");
num = s.nextInt ();
}while (num < 0 | num > 10);
}
for (int i = 0; i < 5 ; i++){
if (array[i] % num == 0) {
System.out.println("Your number is a factor of " + array[i] );
}
}
}catch (Exception e){
System.out.println ("error");
}
}
}
A method should ideally be responsible for one task. In your case you should think about the different things your code try to do and organize them in a sense that each of the methods you call does one thing of the list of things you try to do.
As an example: As far as I understand your code does the following things:
Read an array of 10 values
Read an odd number
Verify the number is odd
Verify the number is in range
Calculate if the number is a factor of one of the 10 numbers in the array
Now one possible approach would be to separate your code in 5 methods that do exactly these things.
At first you call the method that reads the 10 numbers.
Then you call the method to read the odd number.
3. and 4. are actually part of reading the number, since you need to retry on an invalid input, so you could write your method for inputting the odd number in a way that it uses the methods for verifying the input.
Finally when you have all the valid input, you call the method which produces your result (ie. if the number is a factor of the numbers in the list).
A general outlier for your code could look like:
public class CheckboxExample {
public static void main(String args[]) {
CheckBox c = new CheckBox();
new CheckboxExample(); // links to checkbox class
Scanner s = new Scanner(System.in);
int array[] = readInputArray();
int number = readOddValue();
calculateFactors(array, number);
}
private int[] readInputArray() {...}
private int readOddValue() {...}
private void calculateFactors(int[] array, int number) {...}
//additional methods used by readOddValue which verify if the value is actually odd
}
Please note that this is just one way to split your code into methods and there are several ways to design and implement each of these methods.
I made a simple program which generates a random number between 1 to 100 and asks the user to enter a number between 1 and 100. If the number is more than the random number a message is displayed saying that it is more than the random number and if it is less it displays the opposite. The user only has 10 chances to guess the correct number. Here is the code:
import java.util.Scanner;
public class Program {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int random_num = (int) (Math.random() * 100) + 1;
System.out.println("guess a number between 1 and 100");
boolean isCorrect = false;
for (int i = 1; i <= 10; i++) {
int input = sc.nextInt();
if (input > random_num)
System.out.println("It is less than " + input);
else if (input < random_num)
System.out.println("It is more than " + input);
else {
isCorrect = true;
break;
}
}
if (isCorrect)
System.out.println("Congragulation you have guessd the correct number i.e " + random_num);
else
System.out.println("Game over it was " + random_num);
}
}
But I get errors here is the output:
guess a number between 1 and 100
It is more than 10
Exception in thread "main" java.util.NoSuchElementException
at java.base/ java.util.Scanner.throwFor(Scanner.java: 937)
at java.base/ java.util.Scanner.next(Scanner.java: 1594)
at java.base/ java.util.Scanner.nextInt(Scanner.java: 2258)
at java.base/ java.util.Scanner.nextInt(Scanner.java: 2212)
at Program.main(Program.java:15)
You are looping over the Scanner, but not checking if you have any input to fetch.
Here is an excerpt from the Java docs:
public int nextInt()
Scans the next token of the input as an int.
An invocation of this method of the form nextInt() behaves in exactly the same way as the invocation nextInt(radix), where radix is the default radix of this scanner.
Returns:
the int scanned from the input
Throws:
InputMismatchException - if the next token does not match the Integer regular expression,
or is out of range
NoSuchElementException - if input is exhausted
IllegalStateException - if this scanner is closed
Spot your error message ;)
Your code is valid for a standard Java environment.
However since you run the code in the SoloLearn Java container, you run into an error case that normally shouldn't happen.
Which is another thread already closed the input stream.
As Ivar already mentioned, you simply need to change your code to this to make it work on SoloLearn without errors:
for (int i = 1; i <= 10 && sc.hasNextInt(); i++) {
// Your logic
}
But since SoloLearn's implementation needs you to feed all of your input at once (different inputs seperated by a line break), you won't be able to run this correctly with different guesses.
SoloLearn will take those inputs, seperated by line breaks, and reads the different lines one at a time.
Then returns the inputs one at a time to your program.
Once it has no more input, it will close the stream.
However your program still tries to read this stream and then gets a java.util.NoSuchElementException error.
Here is reproducable code of the error with wath I believe happens behind the scenes at SoloLearn:
import java.io.ByteArrayInputStream;
import java.util.Scanner;
public class Program {
private String[] userInput;
private int inputNumber;
public Program(String input) {
this.userInput = input.split(" ");
this.inputNumber = 0;
}
public void startGame() {
int random_num = (int)(Math.random()*100)+1;
System.out.println("Guess the number between 1 and 100!");
boolean isCorrect = false;
for (int i = 1; i <= 10; i++) {
System.out.print("Guess "+ i +": ");
int input = getInput();
if (input > random_num)
System.out.println("It is less than " + input);
else if (input < random_num)
System.out.println("It is more than " + input);
else {
isCorrect = true;
break;
}
}
if(isCorrect)
System.out.println("Congratulations, you have guessed the correct number i.e " + random_num);
else
System.out.println("Game over! The number was " + random_num);
}
private int getInput() {
if (inputNumber < userInput.length)
fakeUserInput();
Scanner sc = new Scanner(System.in);
int input = -1;
input = sc.nextInt();
if (inputNumber == userInput.length)
sc.close();
return input;
}
private void fakeUserInput() {
System.setIn(new ByteArrayInputStream(userInput[inputNumber].getBytes()));
inputNumber++;
}
public static void main(String[] args) {
Program p = new Program("10 20 30");
p.startGame();
}
}
We feed it 3 guesses: 10, 20 and 30
And this is the output:
Guess the number between 1 and 100!
Guess 1: It is more than 10
Guess 2: It is more than 20
Guess 3: It is more than 30
Guess 4: Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:873)
at java.util.Scanner.next(Scanner.java:1496)
at java.util.Scanner.nextInt(Scanner.java:2128)
at java.util.Scanner.nextInt(Scanner.java:2087)
at Program.getInput(Program.java:47)
at Program.startGame(Program.java:24)
at Program.main(Program.java:62)
As you can see, once the inputs are depleted and the stream is closed, we get this error.
I hope this explains your problem and sheds some light on the WHY.
here is answer, I try to do it and I found in main sc.close(). After comment line all work nice! :
#I_code Is this the actual code you are using? It works fine for me. That error is thrown when the the System.in is closed. Are you using sc.close() somewhere that you didn't show in the code?
– #Ivar Mar 15 '19 at 10:10
Good morning you need to initialize the input variable outside the for like this:
int input;
for (int i = 1; i <= 10; i++) {
input = sc.nextInt();
if (input > random_num)
Try this and tell me
This question already has answers here:
Validating input using java.util.Scanner [duplicate]
(6 answers)
Closed 7 years ago.
I need help making a loop that looks at each value from 1 to number-1.
Also how to test each value to see if it is a
divisor of number, and if it is, adding it to the sum.
This is what I have so far:
public static void main(String[] args) {
Scanner input = new Scanner (System.in);
System.out.print("Please enter a positive integer: ");
int n = input.nextInt();
while (n < 0) {
System.out.println(n + " is not positive.");
System.out.print("Please enter a positive integer: ");
n = input.nextInt();
}
}
You can use this as a starting block for your application:
package Testers;
import java.io.Console;
public class Application {
public static void main(String[] args)
{
Console console = System.console();
if (console == null)
{
System.err.println("No console.");
System.exit(1);
}
boolean keepRunning = true;
while (keepRunning)
{
String name = console.readLine("Type your positive integer");
try{
int integer = Integer.parseInt(name);
if(integer < 0){
System.out.println("You must specify a positive integer!");
}
for(int i = 1; i<integer; i++){
// our variable "i" is smaller than "integer". This will parse all the numbers between one and "integer" -1.
if(i % 2 == 0){
//"i" IS divisible by 2. Of course, you can change this value to what you want to change it to.
//Here you can add it to a sum
}else{
//"i" is not divisible by 2. Of course, you can change this value to what you want to change it to.
}
}
}catch(NumberFormatException e){
System.out.println("You must specify a positive integer!");
}
}
}
}
If you want to do something for a known number of times, it is mostly a good idea to use a for loop. If you want to do something for number 1 to n-1, the loop could look like
for(int i = 1; i < n; i++) { // do stuff }
Note that it starts counting from 1 and stops as soon as i is greater or equal than n.
In order to know whether a number, say n, is divisible by some number, say k, the modulo-operator % could be used. If n % k == 0 this means that n is divisible by k. With an if-statement this can be tested and when you have some sum variable you can add whatever you want to that variable to sum things up.
Hope that helps
I have some cool code that takes an int value. I let my little brother test it, and what is the first thing he does? He enters this:
12345678910
And he got this error:
User did not input a number. (Error Code 1)
Well that's not true. Is there a way to give him a different error for "value too large"? Here's my code:
try
{
number = input.nextInt();
}
catch (InputMismatchException e)
{
System.err.println("User did not input a number. (Error Code 1)");
System.exit(1);
}
Thanks!
EDIT
The code that was posted that I used has been modified. This is the code I ended up going with, but the solution is no longer in the comments.
try
{
double intitalinput = input.nextDouble();
if (intitalinput > Integer.MAX_VALUE)
{
System.err.println("User entered a number larger than " + Integer.MAX_VALUE + ". (Error Code 2)");
System.exit(2);
}
else
{
number = (int) intitalinput;
}
}
catch (InputMismatchException e)
{
System.err.println("User did not input a number. (Error Code 1)");
System.exit(1);
}
Thank you to Jay Harris for solving my issue!
EDIT THE SECOND
I added a 'less than zero' check. In case anyone else stumbles upon this question wanting similar help, I'll show the updated code here:
try
{
double intitalinput = input.nextDouble();
if (intitalinput > Integer.MAX_VALUE)
{
System.err.println("User entered a number larger than " + Integer.MAX_VALUE + ". (Error Code 2)");
System.exit(2);
}
else if (intitalinput < 0)
{
System.err.println("User entered a number smaller than 0. (Error Code 3)");
System.exit(3);
}
else
{
number = (int) intitalinput;
}
}
catch (InputMismatchException e)
{
System.err.println("User did not input a number. (Error Code 1)");
System.exit(1);
}
There is plenty of ways to achieve this, for instance check for a larger number and validate it against the max and min size of a Integer using Integer.MAX_VALUE and Integer.MIN_VALUE.
// long userInput = input.nextLong()
// or
double userInput = input.nextDouble();
// expecting an integer but user put a value larger than integer
if (userInput > Integer.MAX_VALUE || userInput < Integer.MIN_VALUE) {
// Throw your error
} else {
// continue your code the number is an int
number = (int) userInput;
}
You could try to get a long instead, but that would only raise the limit, not solve the problem.
The other way would be to get the value as a String and check if its numeric using some regular expression befor trying to convert it. if the conversion fails then the number is to big.
Try using the Scanner.hasNextInt() method:
From http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#hasNextInt()
Returns true if the next token in this scanner's input can be interpreted as an int value in the default radix using the nextInt() method. The scanner does not advance past any input.
if (input.hasNextInt()) {
number = input.nextInt();
} else {
System.err.println("User did not input a number. (Error Code 1)");
System.exit(1);
}
If you want to detect that a number was entered, but that it might be too large to parse, try this approach:
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter a number:");
if (input.hasNextInt()) {
int num = input.nextInt();
System.out.println("num is " + num);
} else {
String s = input.next();
boolean isaNumber = true;
for (int i=0; i<s.length(); i++) {
if (!Character.isDigit(s.charAt(i))) {
isaNumber = false;
break;
}
}
if (isaNumber) {
System.out.println("It appears you entered a number, but it canntot "
+ "be read. It might be too large.");
} else {
System.out.println("Error parsing number.");
}
}
}
Here, I simply check if each character in the input is a digit. If so, I assume it is a number. This code could certainly be cleaned-up, and probably is not 100% bullet-proof. I just wanted to illustrate on possible approach to your question.
As shown in this answer, you could store the input in a long instead, and then check if the number is too big. Or, you could just change all your values to a long type.
A large number will not return an exception from the compiler by itself; the error you ran into may be because an int cannot hold values exceeding around 2 billion. Instead you can try declaring number as a long type.
Another solution would be to first grab the input with a string, as #karfau stated. This could be done specifically by using the length() method; if the string exceeds a certain number of characters, you will know that the input is too long.
You could surround it with a try-catch block.
See the 1st answer to this question for more detailed info.
This question already has answers here:
Java Scanner exception handling
(4 answers)
Closed 7 years ago.
I have written the very simple code (n1 / n2 = sum) whilst trying to learn try / catch exception handling.
I have a do / while loop which is supposed to make x = 2 when run successfully. If not, x = 1, where the user input can be entered again.
The code compiles and runs but if I try, for example n1 = 10, n2 = stackoverflow, the prinln from the caught exception runs forever!
Why is the loop stuck?
Thanks in advance
import java.util.*;
public class ExceptionHandlingMain {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int x = 1; // x originally set to 1
do { // start of do loop
try {
System.out.println("Enter numerator: ");
int n1 = input.nextInt();
System.out.println("Enter divisor");
int n2 = input.nextInt();
int sum = n1 / n2;
System.out.println(n1 + " divided by " + n2 + " = " + sum);
x = 2;
// when the code is completed successfully, x = 2 and do / while loop exits
} catch (Exception e) {
System.out.println("You made a mistake, moron!");
}
} while (x == 1);
}
}
Add input.nextLine() in your catch block to clear the line read.
That's because you are pressing return key post entering the number.
I would suggest you add input.nextLine(); call, so you consume return key as well after reading your input from Scanner.
So with nextInt api, when you type like:
123<return key>
nextInt will just pick up 123 as a string and convert that to a number and leave return key part as is.
Thank you #barak manos (and others who replied)
adding
input.nextLine();
immediately after
System.out.println("You made a mistake, moron!");
clears the input stream and allows the user to enter new data.
cite:
Answer adapted from https://stackoverflow.com/a/24414457/4440127
User: user3580294