User input and Exception in Java - java

I want to add an integer to a list based on user input. The user has to type all the integers he/she wishes then press enter. if they finish inputting integer, they are supposed to press the "enter" button without typing anything.
I have made my code, but there are several mistakes
the exception keeps popping up because every time say for example I enter integer 10, then I finish. I press "enter" with nothing. this raises the exception. how do I tackle this problem?
and another thing, how do I make the program so that if the user puts invalid input, instead of crashing or breaking. It asks the user again to prompt the correct input.
this is what I have done
package basic.functions;
import java.util.*;
import java.text.DecimalFormat;
public class Percent {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
reader.useDelimiter(System.getProperty("line.separator"));
List<Integer> list = new ArrayList<>();
System.out.println("Enter Integer: ");
while (true) {
try {
int n = reader.nextInt();
list.add(Integer.valueOf(n));
} catch (InputMismatchException exception) {
System.out.println("Not an integer, please try again");
break;
}
}
reader.close();
}
}
output
Enter Integer:
10
Not an integer, please try again
[10]

I'd suggest you utilise Scanner#hasNextInt to identify whether an integer has been entered or not. As for when the "user presses enter without typing anything", we can simply use the String#isEmpty method.
while (true) {
if(reader.hasNextInt()) list.add(reader.nextInt());
else if(reader.hasNext() && reader.next().isEmpty()) break;
else System.out.println("please enter an integer value");
}
note - in this case, you don't need to catch InputMismatchException because it won't be thrown.

while (true) is generally a bad sign, if you ever have that in your code you are almost certainly wrong.
What you probably want is something like this:
String input;
do {
input = reader.next();
// Parse the input to an integer using Integer.valueOf()
// Add it to the list if it succeeds
// You will need your try/catch etc here
while (!input.isEmpty());
Here the loop is checking the exit condition and running until it meets it. Your processing is still done inside the loop as normal but the program flow is a lot cleaner.

Related

Correctly implementing a try/catch statement with regards to integer ArrayLists

I'm writing a Java application which allows the user to enter a number of integer values and insert them into an ArrayList. The user should be asked after each item is entered, whether to continue entering data or to exit the application.
As well as that I have to enter a double value to see the type of exception thrown. Once identified, to write a Try/Catch statement which deals with the specific exception and allows the user to continue entering data (rather than having the application crash).
Here's what I have so far:
import java.util.Scanner;
import java.util.ArrayList;
public class Tester{
public static void main(String[] args){
ArrayList<Integer> myArrayList = new ArrayList<Integer>();
Scanner input = new Scanner(System.in);
while (true) {
System.out.println("please enter an integer: ");
integer.add(input.next());
So far, I have creating the ArrayList and prompting the user for input done, now I'm having trouble with continuing to ask the user for input or asking them to stop the process (how do I do this?)
Also how do I write the try/catch block part? I understand that the 'try' part must contain statements that may cause an exception. So how can I write something like:
try {
if input = double
System.out.print("This is an error")?
}
catch(inputMismatchexception e){
....
}
This is what you need:
try{
myArrayList.add(input.nextInt());
}catch(InputMismatchException e){
}
catch(NoSuchElementException e1){
}
catch(IllegalStateException e2){
}
This will throw an InputMismatchError if the input is not an Integer, thus covering your Double input case.
After this, just prompt the user to confirm if they want to continue (something similar to what Ravi wrote in his answer).
I'm having trouble with continuing to ask the user for input or asking
them to stop the process
Inside your while loop
System.out.println("Do you want to continue ?? (Y/N) ");
String str = input.next();
if(str.equals("N")
{
break;
}
input.next() always give you a string, so what you need to do is using Integer.parseInt(input) and check for NumberFormatException.
import java.util.Scanner;
import java.util.ArrayList;
public class Tester{
public static void main(String[] args){
ArrayList<Integer> myArrayList = new ArrayList<Integer>();
Scanner input = new Scanner(System.in);
while (true) {
System.out.println("please enter an integer: ");
try {
int value = Integer.parseInt(input.next());
myArrayList.add(value);
} catch (NumberFormatException e) {
// TODO whatever you want to do here
}
}
}
You are going down a wrong path: you intend to use exceptions to control the flow of your program.
That is possible; but not regarded "good practice" in java.
As the name says, exceptions are for exceptional (aka error) scenarios. But the user wanting to stop the program - that is not an exceptional thing; that should be a core part of your logic!
In that sense: simply use your Scanner object to ask the user for string. And before turning those strings into numbers; you could check if the string is empty for example. Or if the string is equalIgnoreCase() to "quit". Allowing the user to stop the program by just hitting "enter", or by typing "quit".
For the record: you could also use exceptions; just going for Integer.parseInt("any string that is not a int number") will throw a NumberFormatException.
But as said: catching those and assuming the user did that on purpose to the end the loop is a bad idea. What if the user didn't pay attention; made a typo and didn't want to stop?! Wouldn't it be better if you told him "you didnt enter a valid number, try again"?

Using Nested Scanners to Check for Blank Inputs, but [Return] key must be pressed twice

This question serves as a follow-up to a previous question.
I am trying to create a program that converts from one currency to another.
First, I'll post and explain the relevant code, then describe the desired outcome and some problems I came across.
do {
try {
invalidInput = false;
String line = input.nextLine();
Scanner lineScan = new Scanner(line);
BigDecimal moneyInput = lineScan.nextBigDecimal();
// second do-while loop that tries to emulate the outermost do-while loop
// introduces a second set of nested scanners
// re-prompts user for valid currency if they try a blank input
do {
try {
String line2 = input.nextLine();
Scanner lineScan2 = new Scanner(line2);
String currency = lineScan2.next();
if (currency.equals("USD")) {
// convert USD to CNY
} else if (currency.equals("CNY")) {
// convert CNY to USD
}
} catch (NoSuchElementException e) {
invalidInput = true;
System.err.print("Please enter a valid CURRENCY: "); // prompts user for currency ONLY
}
} while (invalidInput);
} catch (NoSuchElementException e) {
invalidInput = true;
System.err.print("Please enter the VALUE followed by the CURRENCY: ");
}
} while (invalidInput);
The outer do-while loop runs as long as invalidInput is true. At the beginning of the first try block, invalidInput is false, and it remains false unless the user enters an invalid input (e.g. blank input or non-numeric). Here, invalidInput becomes true, and the program loops back to the top of the try block after re-prompting the user for both moneyInput and currency.
Next, I wanted to find someway to check the validity of moneyInput and currency separately. The first set of nested Scanners is meant to process moneyInput. If the user inputs something invalid, it will re-prompt the user Please enter the VALUE followed by the CURRENCY:, and it will continue to do so until something valid is entered.
I then wanted to add the exact same functionality to check currency exclusively. This is the intended purpose of the second set of nested scanners (lineScan2). If a valid input is entered for moneyInput but not for currency, e.g. 100.00 abc, I'd like the program to retain the value of moneyInput, re-prompt the user for only currency, and continue to do so until a valid currency is entered (including if the user enters a blank input).
Here are some problems I'm running into:
The program is only reading moneyInput in the first line, instead of reading both moneyInput and currency. Secondly, for each input, the user must press [return] twice (note each of the empty lines in between each input).
The program also terminates inconsistently. In the image example above, after it finally accepts a valid moneyInput and currency and converts the value, the program does not terminate. It terminates prematurely if the moneyInput is entered first, followed by an invalid currency on a second line, like so:
But here, it terminates properly after a successful run (although this still isn't exactly right because it only is "successful" if moneyInput and currency are input on separate lines; ideally, the user should be able to enter both on the same line and the program prints the appropriate conversion):
However, one thing the program does do well is responding repeatedly to invalid (specifically, blank inputs):
And actually, in the case above, aside from the fact that [return] had to be entered twice when prompting for moneyInput and that it didn't terminate after a successful run, everything is working exactly as desired:
the user gets to try repeatedly until a valid input, and in the case
where moneyInput is valid but currency is not, the user only has
to enter a valid input for currency (i.e. they don't have to
re-enter moneyInput when only the currency was invalid).
So overall I am looking for ways to modify the code above to achieve the desired results. As mentioned in the comment section of the linked question at the very top of this post, another method I tried was another do-while loop inside (in place of the inner do-while loop) to check currency, and this worked except for when a blank input was entered, which is basically problem I had at the beginning of that post (here is my code: pastebin.com/raw/CT0qjBPk and example screenshots: imgur.com/a/mjfaL).
Sorry if this post is excessively specific and lengthy. I am a beginner programmer and trying to study Java as thoroughly as possible, and this process of improving code has been of great educational value. Thanks so much for reading and providing feedback.
Your implementation is overly-complex because you're using input in several different places. Here's essentially the pattern I suggested in my answer to your previous question:
try (Scanner in = new Scanner(System.in)) {
while (in.hasNextLine()) {
String line = in.nextLine();
doSomethingWithALineOfInput(line);
}
}
Here's roughly what your code is doing:
boolean invalidInput = false;
try (Scanner in = new Scanner(System.in)) {
while (in.hasNextLine()) {
do {
String line = input.nextLine();
invalidInput |= doSomethingWithALineOfInput(line);
do {
String line2 = input.nextLine();
invalidInput |= doSomethingWithASecondLineOfInput(line2);
} while (invalidInput);
} while (invalidInput);
}
}
Notice in particular that you're calling input.nextLine() in two separate places, which makes your code hard to reason about. One of the primary goals when programming is to reduce your problem into smaller subproblems - interleaving input.nextLine() calls everywhere (let alone inside nested do-while loops) forces you to continue dealing with one big problem.
So instead of mixing your line-processing and your token-processing code together, isolate them from each other. The only thing that should interact with input is the very outer while loop. Once you've read a line you're done with input for the remainder of that iteration.
Consider something like this (notice the use of a class to contain the values as we read them in):
class PromptForMoney {
private BigDecimal amount;
private String currency;
public void prompt(Scanner in) {
System.out.print("Enter an amount of money and currency to convert: ");
while (in.hasNextLine()) {
try {
processLine(in.nextLine());
return;
} catch (InputMismatchException | NoSuchElementException e) {
// we use the exception message to describe the problem to the user
// if Scanner generates exceptions with unclear messages you can
// catch them in processLine() and throw your own with a better message.
System.out.print("Invalid input - " + e.getMessage() + ": ");
}
}
throw new NoSuchElementException(
"No more input to read, but a valid amount or currency was not entered.");
}
private void processLine(String line) {
Scanner lineScanner = new Scanner(line);
if (amount == null) {
// this line will raise an exception if the line is empty
// or if it doesn't start with numerical token
amount = lineScanner.nextBigDecimal();
}
if (currency == null) {
// this line will raise an exception if the user didn't specify a currency
String c = lineScanner.next();
if (isValidCurrency(c)) {
currency = c;
} else {
throw new InputMismatchException(c + " is not a valid currency");
}
}
// if we get this far without raising an exception we've read a valid
// amount and currency from the user.
}
}
Notice how prompt() deals solely with lines, and processLine() deals solely with the contents of a single line. This cleanly separates the problem into smaller, easier-to-reason-about parts.
You'd use PromptForMoney like so:
public static void main(String[] args) throws IOException {
PromptForMoney prompt = new PromptForMoney();
try (Scanner in = new Scanner(System.in)) {
prompt.prompt(in);
}
System.out.println(convert(prompt.getAmount(), prompt.getCurrency());
}
There's another separation of concerns - only main() is responsible for directly interacting with System.in. As far as PromptForMoney is concerned its Scanner could be backed by a string or a file and it would work exactly the same.
Caveat: there are some best practices I'm not emphasizing for the sake of space and simplicity (e.g. preferring final instance variables). If you're interested in improving your code quality even further I strongly suggest reading Effective Java which goes into great detail about Java design patterns.

How to ask te user and depending on his response run all the code again?

I'm a newbie in Java. I started these days and I'm practicing the catch and try exception. I have this code below which solve an operation between to numbers and I'd like to know what can I do, if for example I want that the user, once he makes an operation and get his result, that this has the possibility to make another operation. something like comes up a question asking if he wants to realize another problem and the code run again from the beginning.
package justpractice;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner Operation = new Scanner(System.in);
int x=1;
while(x==1){
try{
System.out.println("Insert numerator");
int n1 = Operation.nextInt();
System.out.println("Insert denominator");
int n2=Operation.nextInt();
double division = n1/n2;
System.out.println(division);
x=2;
}
catch(Exception e){
System.out.println("Insert a valid value");
}
}
}
}
You can do, for example, adding an if statement with a
System.out.println("Do you want to recalculate ? (1/0 Yes/No)");
Operation.nextInt();
then if the input is 1, keep x = 1, else do x = 2.
Try this code amendment;
package justpractice;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner Operation = new Scanner(System.in);
//better practice
while(true){
try{
System.out.println("Insert numerator");
int n1 = Operation.nextInt();
System.out.println("Insert denominator");
int n2=Operation.nextInt();
double division = n1/n2;
System.out.println(division);
System.out.println("Continue? (y/n)");
String response = Operation.nextLine();
if (response.equals("n")){
break;
}
}
catch(Exception e){
System.out.println("Insert a valid value");
}
}
}
}
To allow your user to calculate division again, you could use a do-while loop. With this loop you can execute the code inside once, ask the user if they would like to calculate again, and repeat the code if they do.
An outline of your code with the loop would something like this:
...
boolean again = true;
do { //Main loop
try {
... //Your division code
... //Put code to ask the user if they want to calculate again here
} catch(Exception e) {
...
}
} while(again == true); //Repeat if the user wants to continue
To get input on if the user wants to calculate again, I recommend using another do-while loop with your Scanner. This loop will allow you to repeat the code when the answer is invalid. In this case, when it's not "y" or "n".
String input;
do {
System.out.println("Would you like to continue? (y/n)");
input = operation.next();
} while(!input.equalsIgnoreCase("y") && !input.equalsIgnoreCase("n"));
After you have got the user's input, you still need to terminate the loop if they said "n". To do this you could use an if statement.
if(input.equalsIgnoreCase("n")) {
again = false; //Terminate the main loop
operation.close(); //Prevent any resource leaks with your Scanner
}
There is no need to check if the user input "y" as again is set to true by default.
Side Note: Variables should always be camelCase. Look at the Java Naming Conventions to learn more about naming things in Java.
EDIT:
The reason the console is repeatedly logging that you entered a non-number even though you entered it once, I'm not exactly sure. I think it's because the call to nextInt() never finishes because of the InputMismatchException being thrown, causing the next call to nextInt() (After the do-while repeats) to think that the letter/symbol you just entered is the one you want to process, repeating the exception over and over again.
To solve this, add this line into your catch block:
if(operation.hasNext()) operation.next();
This will call next() and complete the process of marking the letter/symbol you just entered as already processed, then repeat the do-while loop as normal.

Checking if user entered anything?

I am trying to check if a user entered a number and if not, then it uses a default number like 10. How do i check if the user just presses enter and doesn't enter anything in Java
input = scanner.nextInt();
pseudo code:
if(input == user just presses enter without entering anything){
input = 10;
}
else just proceed with input = what user entered
//scanner is a Scanner
int i; // declare it before the block
try {
i = scanner.nextInt();
}
catch (InputMismatchException ime) {
i = 10;
}
// i is some integer from the user, or 10
First things first, geeeeeez guys, when the OP says something like
"I don't want an exception, i want i = 10 if nothing is entered, so what do i do"
That should clue you in that he probably doesn't know too much about exceptions (maybe even java) and might need a simple answer. And if that's not possible, explain to him the difficult ones.
Alright, here's the plain and simple way to do it
String check;
int input = 10;
check = scanner.nextLine/*Int*/();
if(check.equals(""))
{
//do nothing since input already equals 10
}
else
{
input = Integer.parseInt(check);
}
Let me explain what this code is doing. You were originally using nextInt() to get your number for input, correct? The problem is, nextInt() only responds if the user actually inputs something, not if they press enter. In order to check for enter, we used a method that actually responds when the user presses enter and used that to ensure that our code does what we wanted to. One thing I recommend using is an API, Java has one.
Here's the link for the API HERE
And here's the link for the actual method I used HERE. You can find descriptions and instructions on many methods you'll run into on this API.
Now, back to my answer, that's the easy way to do it. Problem is, this code isn't necessarily safe. It'll throw exceptions if something goes wrong, or if someone is trying to hack into your system. For example, if you were to enter a letter instead of pressing enter or entering a number, it would throw an exception. What you've been seeing in the other answers is what we call exception handling, that's how we make sure exceptions don't happen. If you want an answer that'll catch most of these exceptions, you need to make sure your code catches them, or avoids them all together (I'm simplifying things immensely). The above answer is working code, but isn't safe code, you wouldn't ever use something like this all by itself in real life.
Here is something that might be considered safe code. And no exceptions to keep it simple! ;)
import java.util.Scanner;
public class SOQ15
{
public Scanner scanner;
public SOQ15()
{
scanner = new Scanner(System.in);
int input = 10;
boolean isAnInt = true;
String check;
check = scanner.nextLine/*Int*/();
if(check.equals(""))
{
//do nothing since input already equals 10
}
for(int i = 0; i < check.length(); i++)
{
if(check.charAt(i) >= '0' && check.charAt(i) <= '9' && check.length() < 9)
{
//This is if a number was entered and the user didn't just press enter
}
else
{
isAnInt = false;
}
}
if(isAnInt)
{
input = Integer.parseInt(check);
System.out.println("Here's the number - " + input);
}
}
public static void main(String[] args)
{
SOQ15 soq = new SOQ15();
}
}
I don't have time to go into all the details right now, but ask and I'll gladly respond when I get the time! :)
Well if you are using scanner, given the details provided, you can try:
Scanner in = new Scanner(System.in);
if in.hasNextInt(){ //Without this, the next line would throw an input mismatch exception if given a non-integer
int i = in.nextInt(); //Takes in the next integer
}
You said you wanted a default of 10 otherwise so:
else {
int i = 10;
}

Switch returning same statement multiple times

I'm making a school assignment and this time around I thought about using a switch statement since it looked more efficient.
It's just something basic but if I enter a letter for example and after that number 1 for example it would return case 1 twice?
This is my code for the entire class so far:
import java.util.InputMismatchException;
import java.util.Scanner;
public class Test {
private int option;
public static void main(String[] args) {
Test t = new Test();
t.start();
t.optionMenu();
}
public void start() {
System.out.println("Make your choice:");
System.out.println("1: Play");
System.out.println("2: Options");
System.out.println("3: Exit");
}
public void optionMenu() {
try {
Scanner sc = new Scanner(System.in);
this.option = sc.nextInt();
System.out.println(this.option);
} catch (InputMismatchException e) {
System.out.println("Please enter a number");
optionMenu();
}
switch (this.option) {
case 1:
System.out.println("Game starting...");
break;
case 2:
System.out.println("Loading options");
break;
case 3:
System.out.println("Game exiting...");
System.exit(0);
break;
default:
System.out.println("Enter a valid number (1, 2 or 3");
break;
}
}
}
Any help would be much appreciated, thanks!
When you call sc.nextInt() without first asking if (sc.hasNextInt()), you are open to some strange behavior when end-users start typing unexpected input, such as letters. In this case the scanner would not advance its reading pointer, so your program will get stuck reading the same incorrect output.
To fix this issue, add a loop that "clears out" the invalid entry before attempting to read an int again, like this:
while (!sc.hasNextInt()) {
System.out.print("You need to enter an integer.");
sc.nextLine(); // Clear out the bad input
}
int val = sc.nextInt(); // At this point we know that sc.hasNextInt(), because that's the loop condition
Another point is that it is not a good idea to do with recursion what can be done with iteration: the recursive call to optionsMenu is going to accumulate as many levels of invocation as the number of times the end-user enters an incorrect value, so a very persistent user could theoretically force a stack overflow on your program by entering invalid data repeatedly.
Using the code fragment above would free you from the need to call optionsMenu recursively, and also from catching the input exception.
It's just something basic but if I enter a letter for example and after that number 1 for example it would return case 1 twice?
I'm not sure what you mean here. Firstly, your idea works, this code should be fine!
Second, if you enter anything besides just the number 1, 2, or 3, you will go to the "default:" block of code. Since you are prompting the user again if they fail, typing "a" or "a1" into the prompt just shows the menu again. The user needs to just type "1", "2", or "3" to successfully select a menu option.

Categories