Java input Exception from file - java

This is a programming project for my introductory Java class. I am supposed to run the program from the Terminal using information input from a text file.
I can set that up but it keeps throwing a No Such Element Exception at me. The exception comes during the second round of the while loop. I have attempted to place all the inputs on the same line and I tried adding an extra line between each pair. I have also tried removing the extra input.nextLine().
Here is the exception:
Enter the price or -1 to quit: $
Is this purchase a pet? y/n:
Enter the price or -1 to quit: $Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1485)
at java.util.Scanner.nextDouble(Scanner.java:2413)
at DAG_PetDiscounterTester.main(DAG_PetDiscounterTester.java:33)
The file input are:
23.56
n
178.97
n
395.88
y
.98
n
1.97
n
57.89
y
12.33
n
-1
The section of code that is throwing the exception is:
while((done == false) && (nItems < ARRAY_SIZE))
//While loop keeps the program going until user enters sentinel or array is full
{
Scanner input = new Scanner(System.in); //Create a scanner
System.out.printf("Enter the price or -1 to quit: $");
price = input.nextDouble();
//Inform user of required input and read it, assigning it to price
while((price <= 0) && (price != -1))
{
System.out.printf("Enter the price or -1 to quit: $");
price = input.nextDouble();
}
//If input is incorrect, continue to prompt until it is
if(price == SENTINEL) //If statement to check for sentinel
{
done = true; //Changing boolean value ends the program
}
else //If the program's not done, continue
{
input.nextLine(); //Clears newline character after price input
System.out.printf("Is this purchase a pet? y/n: ");
pet = input.nextLine();
//Informs user of next information needed and assigns input to pet boolean
while((!pet.equals("Y")) && (!pet.equals("y")) && (!pet.equals("N")) && (!pet.equals("n")))
//Verifies user input
{
System.out.printf("Is this purchase a pet? y/n: ");
pet = input.nextLine();
//If input is incorrect, continue to prompt until it is
}
if((pet.equals("Y")) || (pet.equals("y")))
//Decision statement determines what value to assign to pet boolean
{
isPet[nItems] = true;
}
else
{
isPet[nItems] = false;
}
prices[nItems] = price; //Assigns current item's price to prices array
nItems++; //Increments items counter to track number of items in the arrays
}
}
It specifically occurs at price = input.nextDouble().
Any advice will be greatly appreciated.

The Javadocs for Scanner say this about the nextDouble() method:
Throws:
InputMismatchException - if the next token does not match the Float
regular expression, or is out of range
NoSuchElementException - if the input is exhausted
IllegalStateException - if this scanner is closed
This error is saying that there is not a double to grab with the method.
The issue comes from the Scanner looking at that line that contains just 'n' and being asked to fetch a double from that line, but one does not exist.
To prevent this you can do:
if(input.hasNextDouble()){
price = input.nextDouble();
}

Related

Why does my while loop only work correctly for certain nested "if" statements but not others? [duplicate]

This question already has answers here:
Scanner is skipping nextLine() after using next() or nextFoo()?
(24 answers)
Closed 1 year ago.
The while loop should ask the user which option they would like to select, and after the option is complete it should go back to the start of the while loop. Right now, it only works correctly for the second else if, and nothing else.
while(flag){
System.out.println("Select an option from the menu below:" +
"\n1: Display consecutive numbers in a right triangle" + //needs better explanation
"\n2: Determine if a number is divisible by 3" +
"\n3: Determine the number of periods and spaces in a string" +
"\n4: Display a right triangle of astrisks" +
"\n5: Exit"); //better explanation
String option = input.nextLine();
if(option.equals("1")){ //does not work
System.out.println("Enter number of columns: ");
int width = input.nextInt();
while(width<=0 || width%1!=0){
System.out.println("Invalid input! Please enter a positive width.");
width = input.nextInt();
}
numOfColumns(width);
}
else if(option.equals("2")){ //does not work
System.out.println("Enter number:");
int num = input.nextInt();
divisibleBy3(Math.abs(num));
}
else if(option.equals("3")){ //works
System.out.println("Enter string:");
String sentence = input.nextLine();
System.out.println("Number of periods and spaces: " + periodsAndSpaces(sentence) + "\n");
}
else if(option.equals("4")){ //does not work
System.out.println("Enter the width of the triangle:");
int length = input.nextInt();
rightTriangle(length, "");
}
else if(option.equals("5")){ //exits the while loop
flag = false;
}
else{
System.out.println("That is not a valid option!");
}
}
For the if/else if statements indicated above, the program will execute the given method, then display the menu, followed by "That is not a valid input!", and then the menu again, even if the user has not entered anything.
As mentioned in comments, you need to consume the rest of the line after you use input.nextInt(); or any other method that does not consume the entire line, because it only takes the input of part of the line and the rest remains on the scanner. You can fix this by input.nextLine(); to advance past the current line so that it is ready for the next input when the while loop restarts, like so:
//Get a partial line input eg "nextInt()"
int someInput = input.nextInt();
//Consume the rest of the line
input.nextLine();
//Now process the input
...
Here is a working solution using the above technique:
if(option.equals("1")){ //does not work
System.out.println("Enter number of columns: ");
int width = input.nextInt();
//Consume the rest of the line
input.nextLine();
//Now process the input
while(width<=0 || width%1!=0){
System.out.println("Invalid input! Please enter a positive width.");
width = input.nextInt();
}
numOfColumns(width);
}
else if(option.equals("2")){ //does not work
System.out.println("Enter number:");
int num = input.nextInt();
//Consume the rest of the line
input.nextLine();
//Now process the input
divisibleBy3(Math.abs(num));
}
else if(option.equals("3")){ //works
System.out.println("Enter string:");
String sentence = input.nextLine();
System.out.println("Number of periods and spaces: " + periodsAndSpaces(sentence) + "\n");
}
else if(option.equals("4")){ //does not work
System.out.println("Enter the width of the triangle:");
int length = input.nextInt();
//Consume the rest of the line
input.nextLine();
//Now process the input
rightTriangle(length, "");
}
else if(option.equals("5")){ //exits the while loop
flag = false;
}
else{
System.out.println("That is not a valid option!");
}
This allows each option to work correctly.
I deduce that your input variable is a Scanner object.
Option number 3 is the only one that works as expected because it is the only one that uses nextLine() for the option-specific input, clearing the newline at the end of the input from the input buffer.
If someone selects option 1, and then enters 3, this is what happens:
input contains the string "3\n"
nextInt() reads 3
input still has "\n" in it that hasn't been read yet
numOfColumns(3) runs
The next iteration of the loop starts
It outputs the menu
nextLine() reads from input, immediately finds the \n that's still there from step 3, clears that character, and returns an empty string
option's value of "" falls through to the invalid input case
The loop starts over again
It outputs the menu
nextLine() waits for new input content to be available again
To get the behavior you were expecting, call input.nextLine() after each input.nextInt() call.

Looping user input until a positive nonzero integer is entered

I'm a complete beginner and I'm trying to trying to create a while loop that keeps asking the user for input until it gets a positive nonzero integer, and then moves on to the next part. Here's what I've got so far:
System.out.println("Enter the speed of the vehicle in "
+ "miles per hour: ");
while (keyboard.hasNext())
{
if (keyboard.hasNextInt())
{
speed = keyboard.nextInt();
while (speed <= 0)
{
System.out.println("Please enter a positive nonzero number: ");
speed = keyboard.nextInt();
}
}
else
{
System.out.println("Please enter a number: ");
speed = keyboard.nextInt();
}
}
Right now, when I run it and enter anything other than an integer, it prints out the line "Please enter a number," but then I immediately get an InputMatchException error and the build fails. If I enter a negative number or zero, it does prompt me to enter a positive number until I do, but then the code just stops executing and keeps running while doing nothing indefinitely, instead of moving on to the part after the loop, which just starts with another system.Output. Thanks in advance for any help.
You need to consume the previously entered non-int, and then attempt to read the following input:
else
{
System.out.println("Please enter a number: ");
// consume and ignore the previous non-int input
keyboard.next();
}
You could do it this way. By asking for a string representation of a numerical value using the Scanner#nextLine() method then applying the String#matches() method with a small Regular Expression (regex) that validates the fact that a positive numerical value was supplied (the "\\d+" expression), for example:
String speedString = "";
while (speedString.isEmpty()) {
System.out.println("Enter the speed of the vehicle in miles per hour: ");
speedString = keyboard.nextLine().trim();
if (!speedString.matches("\\d+") || Integer.valueOf(speedString) < 1) {
System.err.println("Invalid speed value supplied!\n"
+ "Please enter a 'positive' non-zero number.\n");
speedString = "";
}
}
int speed = Integer.parseInt(speedString);

How to read a String an an integer from one input in the console?

The instructions read:
Write a program that prompts the user to input a student first name followed by a space and an integer test grade, then the user will press enter and you will prompt them again for a name and a test grade; for a total of 10 students and 10 grades. (Ex: Dawn 100 ) ; You must check that the user enters a grade that is >= 0 and <= 100. If not, you must prompt the user with an error message and the user must input the grade again.
I can't figure out how to do this without getting a java.util.InputMismatchException error message.
Scanner input = new Scanner(System.in);
String[] students = new String[10];
int[] grades = new int[10];
for(int i = 0; i < students.length; )
{
System.out.println("Enter a student name and grade(between 0 and 100): ");
if(input.nextInt() > 0 && input.nextInt() <= 100)
{
students[i] = input.next();
grades[i] = input.nextInt();
i++;
}
else
{
System.out.println("*Error* Grade value must be between 0 and 100. Please Try again");
}
}
Let's take a closer look...
if(input.nextInt() > 0 && input.nextInt() <= 100)
You check the input for nextInt, twice, so you're no longer actually comparing the same value, but also, you've asked for a String and an int value, but you've not checked for the String first...
Assume I entered something like 500 -1, then you're if statement would pass successfully, because 500 is > 0 and -1 is <= 100
And if by some miracle, that worked, you're reading another String and another int from the stream...
students[i] = input.next();
grades[i] = input.nextInt();
So, for this to work, the input would have to be something like 1 2 John 50 ... which would just be completely weird and completely void what you're trying to do.
Instead, ask for one piece of information at a time and process it, for example...
Scanner input = new Scanner(System.in);
System.out.print("User name: ");
String name = input.nextLine();
System.out.print("Grade: ");
String gradeValue = input.nextLine();
Scanner parser = new Scanner(gradeValue);
if (parser.hasNextInt()) {
int grade = parser.nextInt();
if (grade >= 0 && grade <= 100) {
// Good grade
} else {
System.out.println("!! " + grade + " is not a valid grade");
}
} else {
System.out.println("!! " + gradeValue + " is not a valid integer value");
}
Don't keep reading from the Scanner when you're not expecting a value, extract the value you need and process it. Here I've used nextLine to get the grade and a second Scanner to parse it, it's safer and avoids the oddities where the new line is left in the buffer. It also gives you better control to process errors ;)
This is the main culprit:
if(input.nextInt() > 0 && input.nextInt() <= 100)
Your if condition contains two (2) calls to input.nextInt(), so at this point — before reading the name — your program will attempt to read two numbers from input and see if the first is greater than 0 and the second less than or equal to 100. And if it succeeded, it would not store the numbers read into any variables.
Instead you need to read the name into students[i] first. Then read the grade into grades[i]. Then check if the grade read is in the interval. I suggest you use a while loop so that as long as the grade is outside the interval, you print the error message and read the grade anew. If the first grade read was OK, you while loop won’t execute at all, so this is fine.
I can't figure out how to do this without getting a
java.util.InputMismatchException error message.
The first mistake you've made is reading user input incorrectly input.nextInt() > 0 && input.nextInt() this is requiring the user to enter an integer value twice whereas what you want is name (string) & grade (int).
the solution below takes that mistake into consideration, however personally I would use a while loop, but since you're using a for loop already I have decided to incorporate with that.
full solution:
Scanner input = new Scanner(System.in);
String[] students = new String[10];
int[] grades = new int[10];
for(int i = 0; i < students.length; i++)
{
System.out.println("Enter a student name and grade(between 0 and 100): ");
String getInput = input.nextLine();
if(Integer.parseInt(getInput.split(" ")[1]) < 0 || Integer.parseInt(getInput.split(" ")[1]) > 100)
{
System.out.println("*Error* Grade value must be between 0 and 100. Please Try again");
i--;
}
else {
students[i] = getInput.split(" ")[0];
grades[i] = Integer.parseInt(getInput.split(" ")[1]);
}
}
note - the solution given only takes into consideration what you've mentioned within your question i.e it is expecting input as such Ousmane 20, Brendon 23 , jack 30 etc, also you can make the program a bit more robust by adding more validations if needed maybe NumberFormatException, Scanner#hasNextInt() and so forth.

Java: Adding User Input to ArrayList, ask for another entry until user exits

I need help creating a loop for user entry in my arrayList. I want the user to enter real numbers continuously until they enter -999 to exit (after that the program will total and average the values). I am new to Java so skills are limited. I want the user to enter an unlimited number of values, then when -999 is entered the program displays the values entered, the total of the values and the average of the values.
static void option2(){
Scanner keyboard=new Scanner(System.in);
double numEntered;
ArrayList<Double> list2=new ArrayList<Double>();
System.out.println("Please enter a value: ");
while (keyboard.hasNextDouble()){
double d = keyboard.nextDouble();
if (d == -999){
System.out.println("You have ended the arrayList\n");
break;
}
list2.add(d);
}
Check the value you get isn't -999 (and if it is, break out of the loop). Something like,
while (keyboard.hasNextDouble()){
double d = keyboard.nextDouble();
if (d == -999) {
break;
}
list2.add(d);
}

Why is my for loop printing 2 of my prompts at one time while using (scanner).nextLine();

Is there a problem in my while or for loops by chance or am I missing something? First run through works fine but on the second I get this:
Enter course NAME: class name
Enter course HOURS: 4
Enter course GRADE: 4.0
You have entered class: jeff graves, class hours: 4 and, class grade 4.0
Do you want to continue:
y
Enter course NAME: Enter course HOURS:
It works just fine using (scanner).next(); but then I can only take one word from the user and it will throw an error from the nextInt when it rolls over.
public class GetGrades { //open class GetGrades
public static void main(String[] args) {
/**creating new instance of scanner named input to read user input*/
Scanner input = new Scanner(System.in); // create new instance of scanner object
boolean repeat = true; //boolean value for while loop holding array input
String s; // create string to store user input value for exiting loops
/** create 3 arrays to store course name, hours, and grades*/
String[] name = new String[20]; //type string array for class name
int[] hours = new int[20]; // type int array for class hours
float[] grade = new float[20]; //type float array for class grade
outerloop: // set break point for nested for loops exit on user input
while(repeat != false) {// while loop with boolean value to let user exit array input
for (int i=0; i<name.length; i++) { //for loop for name array
System.out.print("Enter course NAME: "); //prompt user for input
name[i] = input.nextLine(); //read next line value and store in array name
System.out.print("Enter course HOURS: "); //prompt user for input
hours[i] = input.nextInt(); //read the next int and store in array hours
System.out.print("Enter course GRADE: "); //prompt user for input
grade[i] = input.nextFloat(); //read the next float value and store in array grade
/**Print line to console summing um what the user has entered*/
System.out.println("You have entered class: " + name[i] + ", class hours: " + hours[i] +
" and, class grade " + grade[i]);
/**prompt user if wanted to enter more grades, break loop on n or N*/
System.out.println("Do you want to continue:");
s = input.next();
if ( s.equals("y") || s.equals("Y")) { //open if statement
repeat = true;
} else { //close if and open else
break outerloop;
} //close else statement
}//close for loop with i as count
}//close while
input.next() will read the next word. input.nextLine() will read up until the next time you press enter.
This means that when you write "y" and hit enter, you've input both a word "y", as well as the next enter, filling in both prompts at the same time and causing the next prompt to be written.
You can simply replace your next() with nextLine() when you ask to continue:
System.out.println("Do you want to continue:");
s = input.next();
becomes
System.out.println("Do you want to continue:");
s = input.nextLine();
thereby reading both the "y" and the enter. The next prompt is now free to accept new input.
When you input the grade, for example 12.3 and enter, "input.nextFloat();" will only take "12.3" but not "enter", so "enter" will be taken by the next scanner.
In my opinion,
first, change "s = input.next()" to "s = input.nextLine()", but it will take the "enter" of previous scanner "grade[i] = input.nextFloat();", so, second, put it into a while loop as a condition. like this
while((s = input.nextLine()).equals("")) {}
therefore, it won't stop til get the expect input.
try this..
System.out.print("Do you want to continue:");
while((s = input.nextLine()).equals("")) {}
if (s.equals("y") || s.equals("Y")) { // open if statement
repeat = true;
} else { // close if and open else
break outerloop;
} // close else statement

Categories