I've been given a task that I have to create a Shopping List program. I've done this in Python, and it was relatively straight forward. However, in Java I've hit a bit of a roadblock.
These are my variables, I am aware of the issues with using statics in this way and that it would be best to avoid doing it.
private static Scanner input = new Scanner(System.in);
private static String list_add = "string"; //"string" is just a place holder
private static ArrayList listFull = new ArrayList();
private static ArrayList listPos = new ArrayList();
private static int userIn = 1; //1 is also being used as place holder
Which I use in:
private static void userInput() {
boolean isValid = false;
while (!isValid) {
isValid = true;
try {
userIn=Integer.parseInt(input.next());
}
catch (InputMismatchException e) {
System.out.println("That's not a valid number!");
isValid = false;
}
}
}
The reasoning behind doing it this way is the less one needs to type the quicker the task can be completed. Which was working as nice philosophy up until I tried this. My previous attempt to solve this problem gave an infinite loop, and the second solution that came to mind returned a StackOverflowError. When I asked about avoiding the infinite loop, I was directed to another question (Endless loop while using "try and catch " block inside a "while loop") which I did not believe helpful to begin with, however found that it was (Thank you whoever marked that). I didn't get this solution to work, however, and I cannot see where I went wrong.
After trying different inputs to see if their was one specific type that killed it, these were the errors I received:
Test Case "strin":
Exception in thread "main" java.lang.NumberFormatException: For input string: "strin"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at DebuggingMethods.AllIn(DebuggingMethods.java:17)
at DebuggingMethods.Menu(DebuggingMethods.java:33)
at DebuggingMethods.main(DebuggingMethods.java:58)
Test Case "Ten":
Exception in thread "main" java.lang.NumberFormatException: For input string: "Ten"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at DebuggingMethods.AllIn(DebuggingMethods.java:17)
at DebuggingMethods.Menu(DebuggingMethods.java:33)
at DebuggingMethods.main(DebuggingMethods.java:58)
Test Case int(10):
Which ran with the anticipated outcome.
I had thought that I was missing a module, so I did import java.lang.*; which did not change the error. If someone has a solution, please help me out. I can't find a question that already posted that explains what I am doing wrong. When I pulled it out of the Try-Catch it was working kind of.
Full Piece
import java.util.InputMismatchException;
import java.util.*;
import java.util.Scanner;
import java.lang.*;
public class TestOne {
private static Scanner input = new Scanner(System.in);
private static String list_add = "string";
private static ArrayList listFull = new ArrayList();
private static ArrayList listPos = new ArrayList();
private static int userIn = 1;
private static void userInput() {
boolean isValid = false;
while (!isValid) {
isValid = true;
try {
userIn=Integer.parseInt(input.next());
}
catch (InputMismatchException e) {
System.out.println("That's not a valid number!");
isValid = false;
}
}
}
public static void main(String[] args) {
//titleMain();
userInput(); // For the sake of demonstration
}
}
You've got your exceptions mixed up. You're catching an InputMismatchException, which is what input.nextInt() would have thrown if the input were invalid. But you're actually using Integer.parseInt to parse the input, which throws NumberFormatException in case of invalid input. And since NumberFormatException isn't a subclass of InputMismatchException, it isn't caught and you end up dying with a stack trace.
You don't actually need to do anything with exception at all here. The Scanner can tell you if the next input is a valid integer or not and you can then actively decide what do about it. Think along these lines:
Scanner sc;
//...
System.out.println("Please enter a number");
while (!sc.hasNextInt()){
sc.nextLine(); // throw away the bad input
System.out.println("Please enter a valid number");
}
int theNum = sc.nextInt();
Related
I can't seem to find the issue in my code and was wondering if you wonderful people on here would be willing to help me out. My professor is requiring us to create a 2-D array from information pulled from a file she provided us. Using the Scanner and File class we should be able to accomplish this, however, I have hit a speed bump. My scanner is not recognizing the integer after the delimiter I have set for it. Here is the file she provides us with.
5x7
o,2,3
7,1,3
7,1,1
X,4,2
This info is separated by newlines where there are spaces in the blockquote.
Here is my code:
import java.io.*;
import java.util.*;
public class Battlefield {
// Use the FILL_CHAR for a space that contains no creature.
// Use these chars for creatures so that your code will pass
// the tests used for evaluating your program.
public final char FILL_CHAR = '-';
public final char OGRE = 'o';
public final char CENTAUR = '7';
public final char DRAGON = 'X';
private char[][] field;
public Battlefield(String fn) {
try {
// You write code here.
// Read a file and initialize the field.
// The name of the file is passed in from the driver.
// Keep all the file reading stuff in the try/catch block
// to make file exceptions easier to deal with.
File battlefield = new File(fn);
Scanner scan = new Scanner(battlefield);
scan.useDelimiter("x");
int row = scan.nextInt();
System.out.println(row);
System.out.println(scan.next());
System.out.println(scan.hasNextInt());
int column = scan.nextInt();
char[][] field = new char[row][column];
/**
Scanner scan2 = new Scanner(battlefield);
scan2.useDelimiter(",");
/**
field[scan2.nextInt()][scan2.nextInt()] = OGRE;
field[scan2.nextInt()][scan2.nextInt()] = CENTAUR;
field[scan2.nextInt()][scan2.nextInt()] = CENTAUR;
field[scan2.nextInt()][scan2.nextInt()] = DRAGON;
**/
} catch (IOException ex) {
System.err.println(ex.getStackTrace());
}
}
And my main method/driver class:
public class BattlefieldDrv {
public static void main(String[] args)
{
Battlefield battlefieldOne = new Battlefield("1field.dat");
System.out.println(battlefieldOne.toString());
}
}
Here is my stack trace:
> 5
7
o,2,3
7,1,3
7,1,1
X,4,2
false
Exception in thread "main" java.util.InputMismatchException
at java.base/java.util.Scanner.throwFor(Unknown Source)
at java.base/java.util.Scanner.next(Unknown Source)
at java.base/java.util.Scanner.nextInt(Unknown Source)
at java.base/java.util.Scanner.nextInt(Unknown Source)
at Battlefield.<init>(Battlefield.java:38)
at BattlefieldDrv.main(BattlefieldDrv.java:15)
Thank you for any help or insight you have!
So let's step through this code.
scan.useDelimiter("x");
int row = scan.nextInt();
5 is read into row.
System.out.println(row);
5 is printed.
System.out.println(scan.next());
The rest of the file is read and printed, because that's what comes after the x.
System.out.println(scan.hasNextInt());
There's nothing left to read, so the NoSuchElementException is thrown here.
You need to make the scanner also accept newlines as delimiter; you can do that by using
scan.useDelimiter("(x|\\s)");
(The \\s is the pattern for "any whitespace").
As a side note, it's good practice to use the try-with-resources-construct:
try (Scanner scan = new Scanner(Paths.get("1field.dat"))) {
scan.useDelimiter(...);
...
} catch (IOException e) {
This will result in your file resource being closed automatically.
The code is supposed to read an unidentified number of inputs from the keyboard and return any tabs as *. My program seems to work when I run it in eclipse and get no errors. When I turn in the code on the submission website, this is the error I get.
Exception in thread "main" java.util.NoSuchElementException: No line found at java.util.Scanner.nextLine(Scanner.java:1589) at replaceHW.main(replaceHW.java:9)
import java.util.Scanner;
public class replaceHW {
public static void main(String[] args) {
//write a program that converts all TABS in your code
//with STARS i.e. *
Scanner in = new Scanner(System.in);
String ans;
while(!(ans = in.nextLine()).equals(""))
System.out.println(ans.replace("\t","*"));
}
}
Your problem is simple: nextLine() works in tandem with hasNextLine(): the correct code is:
try (Scanner in = new Scanner(System.in)) {
while (in.hasNextLine()) {
String line = in.nextLine();
if (!"".equals(line)) {
System.out.println(ans.replace("\t","*"));
}
}
The try-with-resources is best practice. But be wary than with System.in, it will close it when done.
hasNextLine() will try to read has much input is needed to find a line.
This question already has answers here:
try/catch with InputMismatchException creates infinite loop [duplicate]
(7 answers)
Closed 6 years ago.
I am new to Java and would like to ask you a question.
I have written the below code where "numOfThreads" should be assigned a valid int value by the user through the Console.
However, I would like to achieve a result where if the input is incorrect and we go in the catch block, the user should be re-prompted to enter "numOfThreads" until it is of correct type and range.
For some reason I seem to go into infinite loop. Can you please assist? Thanks :)
import java.util.Scanner;
public class Main {
public static void main(String args[]){
int numOfThreads;
boolean promptUser = true;
Scanner keyboard = new Scanner(System.in);
while (promptUser)
{
try{
numOfThreads = keyboard.nextInt();
promptUser = false;
}
catch(Exception e){
System.out.println("Entry is not correct and the following exception is returned: " + e);
numOfThreads = keyboard.nextInt(); // DOES NOT SEEM TO BE ASKING FOR A NEW INPUT
}
}
}
}
it doesn´t because nextInt tries to consume the last token. When there is an invalid input it can´t consume it. As a result a following nextInt call wont be able to consume it either. write a keyboard.nextLine before numOfThreads = keyboard.nextInt(); and you are fine.
catch(Exception e){
System.out.println("Entry is not correct and the following exception is returned: " + e);
// this consumes the invalid token now
keyboard.nextLine();
numOfThreads = keyboard.nextInt(); // It wasn´t able to get the next input as the previous was still invalid
// I´d still rewrite it a little bit, as this keyboard.nextInt is now vulnerable to throw a direct exception to the main
}
Why I'm getting infinite loop in recursion method, without a chance to input any symbol to break it?
class Test {
int key=0;
void meth(){
System.out.println("Enter the number here: ");
try(Scanner scan = new Scanner(System.in)) {
key = scan.nextInt();
System.out.println(key+1);
} catch(Exception e) {
System.out.println("Error");
meth();
}
}
}
class Demo {
main method {
Test t = new Test();
t.meth();
}
}
If you try to create an error (putting string value in key and then try to add to it a number), you will get infinite "Error" text in console, instead of that, after first error, program should ask again the number and only then decide what to do.
If nextInt() fails, it throws an exception but doesn't consume the invalid data. From the documentation:
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.
You're then recursively calling meth() again, which will try to consume the same invalid data a second time, fail again (without consuming it), and recurse.
Firstly, I wouldn't use recursion here in the first place. Prefer a simple loop. Next, if you have invalid input you should consume it appropriately before trying again. Finally, consider using hasNextInt instead of just using nextInt and catching the exception.
So maybe something like this:
import java.util.Scanner;
class Test {
public static void main(String[] args){
try (Scanner scanner = new Scanner(System.in)) {
System.out.println("Enter the number here:");
while (!scanner.hasNextInt() && scanner.hasNext()) {
System.out.println("Error");
// Skip the invalid token
scanner.next();
}
if (scanner.hasNext()) {
int value = scanner.nextInt();
System.out.println("You entered: " + value);
} else {
System.out.println("You bailed out");
}
}
}
}
i have tried this code snippet but could not able to figure out the reason for this the exception.
my code is:-
import java.util.*;
class ScannerTest
{
public static void main(String[]args)
{
String csv = "Sue,5,true,3";
Scanner sc = new Scanner(csv);
sc.useDelimiter(",");
int age = sc.nextInt();
System.out.println(age);
}
}
Output is:-
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Unknown Source)
at java.util.Scanner.next(Unknown Source)
at java.util.Scanner.nextInt(Unknown Source)
at java.util.Scanner.nextInt(Unknown Source)
i am new to java so please help me out to know the reason for this exception.
in the javadoc example you can see how it works:
String input = "1 fish 2 fish red fish blue fish";
Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*");
System.out.println(s.nextInt());
System.out.println(s.nextInt());
System.out.println(s.next());
System.out.println(s.next());
s.close();
your first token is a string. if you use next int it expects an integer.
you might want to use something like this (under the conditions that you know the structure of the csv and it doesn't change):
public static void main(String[]args)
{
String csv = "Sue,5,true,3";
Scanner sc = new Scanner(csv);
sc.useDelimiter(",");
sc.next();
int age = sc.nextInt();
System.out.println(age);
}
or
public static void main(String[] args) {
String csv = "Sue,5,true,3";
String ageString = csv.split(",")[1];
System.out.println(ageString);
}
...
to parse a string into int:
int age = Integer.parseInt(ageString);
The Javadoc of the nextInt method of Scanner states
Scans the next token of the input as an int. This method will throw
InputMismatchException if the next token cannot be translated into a
valid int value as described below. If the translation is successful,
the scanner advances past the input that matched.
As your first token is a String, this is what's going on. As in most cases in CSV's you will know what will be presented, you should read them one by one, and/or use the hasNextInt method and its friends to check whether what you expect is actually there.
The scanner is expecting an integer type but the first token is a String - "Sue", To fix, place:
sc.next(); // skip "Sue"
before the call to nextInt() to consume the String token.