I am getting a NoSuchElementException which is probably due to Scanner and I get it after I add a student and go back to the menu.
My main method:
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
static ArrayList<Student> students = new ArrayList<>();
static Scanner scan = new Scanner(System.in);
static Student s = new Student();
public static void main(String[] args) {
menu();
}
public static void menu() {
System.out.println(" ***Students Manage***\n");
System.out.println("1 - Insert a student");
System.out.println("2 - Display students");
System.out.println("3 - Remove student\n");
option();
}
public static void option() {
int option;
do {
System.out.print("Choose an option: ");
option = scan.nextInt();
}while(option < 1 || option > 3);
switch(option) {
case 1:
s.addStudent();
students.add(s);
break;
case 2:
showAllStudents();
}
menu();
}
private static void showAllStudents() {
for(int i = 0; i < students.size(); i++) {
students.get(i).toString();
}
}
}
My Student method:
import java.time.LocalDate;
import java.util.Scanner;
public class Student {
String name;
int studentNumber;
static int count = 1;
int yearNumber;
public Student() {
}
public void addStudent() {
Scanner scan = new Scanner(System.in);
LocalDate year = LocalDate.now();
yearNumber = year.getYear();
studentNumber = count++;
studentNumber += yearNumber * 10000;
System.out.print("Enter the student name: ");
name = scan.nextLine();
if(name == null || name.trim().equals("") || !name.contains(" "))
{
do{
if(name.trim().equals("")){
System.out.print("Please enter a valid name.\nEnter your name: ");
} else if(!name.contains(" ")) {
System.out.print("You should write at least 2 names(name and surname).\nEnter your name: ");
}
name = scan.nextLine();
}while(name == null || name.trim().equals("") || !name.contains(" "));
}
scan.close();
System.out.println("The student "+name+" was added to the student list "
+ "and his/her student number is "+studentNumber);
}
#Override
public String toString(){
return name+" - "+studentNumber;
}
}
The error that I'm getting:
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 StudentSchool.Main.option(Main.java:29)
at StudentSchool.Main.menu(Main.java:21)
at StudentSchool.Main.option(Main.java:40)
at StudentSchool.Main.menu(Main.java:21)
at StudentSchool.Main.option(Main.java:40)
at StudentSchool.Main.menu(Main.java:21)
at StudentSchool.Main.main(Main.java:13)
You have two problems in how you're using Scanner. The first is that you are opening a second Scanner on System.in while you have one already open and reading from it. This produces strange results due to buffering. You should create and use only a single Scanner object that you never close. You can do this by passing the Scanner you create in your main() method into your addStudent() method so that it can use that same Scanner instead of creating and later closing a new one. So...
public void addStudent(Scanner scan) {
// Scanner scan = new Scanner(System.in);
....
// scan.close();
....
public static void option() {
....
s.addStudent(scan);
...
When you do this, a second problem will arise. When you mix calls to nextInt and nextLine on a Scanner object, you run into a problem where nextInt only reads the numeric digits from the input stream, but leaves the newline character produce by the user hitting Return. When you then call readLine, it reads that newline that's already on the input stream, so instead of waiting for your input, it reads an empty line as the next result. To avoid this problem, you should add an extra call to readLine right after you call readInt to consume this stray newline character. So...
System.out.print("Choose an option: ");
option = scan.nextInt();
scan.nextLine();
Making these two changes should cause your program to behave as you desire.
Related
this error seems to be a very common issue. I've looked up on other Stack Overflow posts that ask about this and tried to implement their solutions, but I'm still getting the same error. The complete error is:
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 src.file.main(file.java:29)
I'm sure there's something really simple I'm missing, but I can't quite find it as when I read through my code, the logic seems good. This is my file:
public class file {
public static void main(String[] args) throws IOException {
int choice = 0;
Scanner myVal = new Scanner(System.in);
while(choice != 3) {
System.out.println("1. enter info \n2. print info \n3.exit");
System.out.println("Enter a choice: ");
choice = myVal.nextInt(); //Line 29
if(choice == 1) {
enterInfo();
}
else if(choice == 2) {
print();
}
else if(choice == 3) {
System.exit(0);
}
}
}
static ArrayList<newType> studInfo = new ArrayList<src.newType>();
static void enterInfo() {
Scanner keyboard = new Scanner(System.in);
System.out.println("Enter the information (Program year average lastname): ");
String info = keyboard.nextLine().trim();
if(info.isEmpty()) {
System.out.println("Error, no input was made.");
keyboard.close();
return;
}
String[] tokens = info.split(" ");
int size = tokens.length;
String prgm = tokens[0];
int yr = Integer.parseInt(tokens[1]);
String lastname = tokens[3];
Double avg = Double.parseDouble(tokens[2]);
newType inf = new newType(prgm, yr, avg, lastname);
studInfo.add(inf);
System.out.println("Information added.");
keyboard.close();
return;
}
Example input: math 5 76 Smith, this information is added to the arraylist of type newType where it can be printed, or another profile can be added.
The program compiles without errors or warnings, and I can successfully run the program. When I choose option 1, I enter all the information, in the correct format, to which I get the information added message, signaling it was a successful process. After this message, the exception appears. This leads me to believe the error doesn't actually lie within my enterInfo function, as I first thought, but rather when it reaches line 29 for the second time. I don't know how to fix this error, could anyone help? Thanks in advance!
Apart from the mistakes done in using Scanner, the standards followed in java is also missing.
Classname should start with caps (file should be as File, same with newType as well. It should be NewType)
If you are naming any class then it should be a noun and so should be named as per the goal to be achieved in the program such as AddingNumbers, ReverseNumbers.
Pls refer here why we shouldn't use multiple scanner in a program : Why does closing a scanner seem to break new scanners?
I have made few changes in your code.Hope this works !!!
// modified code
public class File {
static Scanner myVal = new Scanner(System.in); // Use this scanner throughout the program
static ArrayList<newType> studInfo = new ArrayList<src.newType>();
public static void main(String[] args) throws IOException {
int choice = 0;
while (choice != 3) {
System.out.println("1. enter info \n2. print info \n3.exit");
System.out.println("Enter a choice: ");
choice = myVal.nextInt(); // Line 29
if (choice == 1) {
enterInfo();
} else if (choice == 2) {
// print();
} else if (choice == 3) {
System.exit(0);
}
}
myVal.close(); // Can be closed once the need is over.
}
static void enterInfo() {
// Scanner keyboard = new Scanner(System.in); No need of multiple scanners.
System.out.println("Enter the information (Program year average lastname): ");
String info = myVal.nextLine().trim();
if (info.isEmpty()) {
System.out.println("Error, no input was made.");
// keyboard.close();
return;
}
String[] tokens = info.split(" ");
int size = tokens.length;
String prgm = tokens[0];
int yr = Integer.parseInt(tokens[1]);
String lastname = tokens[3];
Double avg = Double.parseDouble(tokens[2]);
newType inf = new newType(prgm, yr, avg, lastname);
studInfo.add(inf);
System.out.println("Information added.");
// keyboard.close();
return;
}
}
I am trying to achieve a certain result or output before terminating the loop.
Here is my code:
import java.util.Scanner;
public class learnjava {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("How old are you?");
int age = scanner.nextInt();
scanner.nextLine();
System.out.println("Do you prefer cats or dogs?");
String animal = scanner.nextLine();
if (age > 10 || animal.equals("cats"))
{System.out.println("welcome!");}
else {System.out.println("No access");}
scanner.close();
}
}
Ideally I want to create a loop that makes my code run until system prints out welcome, so that I can avoid restarting the program. I want to provide the user another chance at inputting right answers once the first input fails without running again, hence the console should ask again "how old are you?"
You can use a do while loop for this use case. The actual validation logic can be put within the loop and the loop will be terminated only if the condition is invalid.
So in you case, the loop will check the condition age < 10 || !animal.equals("cat"). So the loop will run till the age exceeds 10 or the animal is "cat". As this is an exit check loop, it will exit only after printing "Welcome" to the console.
The code is as follows,
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String animal;
int age;
do{
System.out.println("How old are you?");
age = scanner.nextInt();
scanner.nextLine();
System.out.println("Do you prefer cats or dogs?");
animal = scanner.nextLine();
if (age > 10 || animal.equals("cats"))
{
System.out.println("welcome!");
}
else {
System.out.println("No access");
}
}while(age < 10 || !animal.equals("cat"));
scanner.close();
}
}
You use loops in java for repeated task. while loop is one of them
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (true) {
if (askUser(scanner)) {
System.out.println("welcome!");
break;
} else {
System.out.println("No access");
}
}
scanner.close();
}
private static boolean askUser(Scanner scanner) {
System.out.println("How old are you?");
int age = scanner.nextInt();
scanner.nextLine();
System.out.println("Do you prefer cats or dogs?");
String animal = scanner.nextLine();
return (age > 10 || animal.equals("cats"));
}
How about wrapping the logic in a while loop with a boolean variable to indicate the isFinished status:
import java.util.Scanner;
public class learnjava {
private static final String WELCOME = "welcome!";
private static final String ACCESS_DENIED_TRY_AGAIN = "No access";
public static void main(String[] args) {
boolean isFinished = false;
Scanner scanner = new Scanner(System.in);
while (!isFinished) {
System.out.println("How old are you?");
int age = scanner.nextInt();
System.out.println("Do you prefer cats or dogs?");
String animal = scanner.nextLine();
if (age > 10 || animal.equals("cats")) {
System.out.println(WELCOME);
isFinished = true;
} else {
System.out.println(ACCESS_DENIED_TRY_AGAIN);
}
}
scanner.close();
}
}
import java.util.Scanner;
public class LoopsEndingRemembering {
public static void main(String[] args) {
// program in this project exercises 36.1-36.5
// actually this is just one program that is split in many parts
Scanner reader = new Scanner(System.in);
System.out.println("Type numbers: ");
int input = Integer.parseInt(reader.nextLine());
while(true){
if(input == -1){
break;
}
}
System.out.println("Thank you and see you later!");
}
}
The user should be able to put in multiple numbers until -1 is reached. Once its reached it should break the loop and print the last line.
You need to put
System.out.println("Type numbers: ");
int input = Integer.parseInt(reader.nextLine());
into your loop, else it will never get new user input
You need call scanner inside loop
import java.util.Scanner;
public class LoopsEndingRemembering {
public static void main(String[] args) {
while(true){
Scanner reader = new Scanner(System.in);
System.out.println("Type numbers: ");
int input = Integer.parseInt(reader.nextLine());
if(input == -1){
break;
}
}
System.out.println("Thank you and see you later!");
}
}
I'm newbie in Java and I'm trying to read data from keyboard but I'm getting an exception and I don't know why and how to fix it.
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Test r = new Test();
System.out.println("Type a int number : " + r.readInteger());
System.out.println("type a double number: " + r.readDouble());
}
public int readInteger() {
Scanner input = new Scanner(System.in);
int val = 0;
while(true) {
if(input.hasNextInt()) {
val = input.nextInt();
input.nextLine();
break;
}
else {
System.out.println("Invalid data type.");
input.nextLine();
}
}
input.close();
return val;
}
double readDouble() {
Scanner input = new Scanner(System.in);
double val = 0;
while(true) {
if(input.hasNextDouble()) {
val = input.nextDouble();
input.nextLine();
break;
}
else {
System.out.println("Invalid data type.");
input.nextLine();
}
}
input.close();
return val;
}
}
The excpetion:
[roger#archroger ~]$ java Test
3
Type a int number : 3
Invalid data type.
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Scanner.java:1540)
at Test.readDouble(Test.java:44)
at Test.main(Test.java:8)
Don't close the scanner when it's input stream is System.in. This will close the standard input as well and statements like scanner.nextLine() will throw a NoSuchElementException when you do not check if the line is present. You check with scanner.hasNextInt() if another integer token is available and then try to get another line with scanner.getNextLine() without testing if this line exists at all. Use scanner.hasNextLine().
Why when I run my program and enter 5, it allows me to enter my records, but when the main menu runs again and I enter 6, the changePhoneNumber method is not run and it goes back to the main menu. Is the while(true) loop somehow messing things up?
I have a class called Record that looks like:
public static void main(String[] args) {
BankMethods method = new BankMethods();
Scanner input = new Scanner(System.in);
int optionSelected = 0;
while(true){
System.out.println("5. Add a New Record");
System.out.println("6. Change the Phone Number in the Current Record");
optionSelected = input.nextInt();
if (optionSelected == 5){
Scanner getRecord = new Scanner(System.in);
System.out.println("Enter First Name: ");
String firstName = getRecord.nextLine();
System.out.println("Enter Last Name: ");
String lastName = getRecord.nextLine();
System.out.println("Enter Phone Number: ");
String phoneNumber = getRecord.nextLine();
method.addNewRecord(firstName, lastName, phoneNumber);
}
if (optionSelected == 6){
System.out.println("What would you like to change your phone "
+ "number to? ");
String newNumber = input.nextLine();
method.changePhoneNumber(newNumber);
}
and the other class...BankMethods:
public class BankMethods {
LinkedList recordInformation = new LinkedList();
Bankdata mainMenu = new Bankdata();
public void addNewRecord(String firstName, String lastName,
String phoneNumber){
recordInformation.add(firstName); recordInformation.add(lastName);
recordInformation.add(phoneNumber);
}
public void changePhoneNumber(String newNumber){
recordInformation.set(2, newNumber);
System.out.println(recordInformation);
}
The problem is that you are using 2 Scanners to read the one InputStream. When you open the second Scanner you will not be able to read using the original one as the second will have exclusive access to it.
For this application you could easily use a single Scanner.
See: Do not create multiple buffered wrappers on a single InputStream
The correct way is to use one read(scanner) for a input stream. Edited the previous answer to use single read option
Complete program that works is given below
package com.stackoverflow.framework;
import java.util.LinkedList;
import java.util.Scanner;
public class Record {
static Scanner input = new Scanner(System.in);
public static String readData() {
return (input.nextLine());
}
public static void main(String[] args) {
BankMethods method = new BankMethods();
int optionSelected = 0;
while (true) {
System.out.println("5. Add a New Record");
System.out
.println("6. Change the Phone Number in the Current Record");
optionSelected = Integer.parseInt(readData());
if (optionSelected == 5) {
// Scanner getRecord = new Scanner(System.in);
System.out.println("Enter First Name: ");
String firstName = readData();
System.out.println("Enter Last Name: ");
String lastName = readData();
System.out.println("Enter Phone Number: ");
String phoneNumber = readData();
method.addNewRecord(firstName, lastName, phoneNumber);
}
if (optionSelected == 6) {
System.out.println("What would you like to change your phone "
+ "number to? ");
// Scanner getRecord = new Scanner(System.in);
String newNumber = readData();
method.changePhoneNumber(newNumber);
}
}
}
}
class BankMethods {
LinkedList recordInformation = new LinkedList();
public void addNewRecord(String firstName, String lastName,
String phoneNumber) {
recordInformation.add(firstName);
recordInformation.add(lastName);
recordInformation.add(phoneNumber);
}
public void changePhoneNumber(String newNumber) {
recordInformation.set(2, newNumber);
System.out.println(recordInformation);
}
}