1

The error should not have occurred as I have closed the Scanner object I declared in the registerN() function and declared a new one for setInfo() to use. But still, I kept getting the following output every time I input "register" as the value of option.

Exception in thread "main" java.util.NoSuchElementException: No line found
    at java.util.Scanner.nextLine(Unknown Source)
    at Student.setInfo(student.java:37)
    at Group.registerN(student.java:87)
    at Manage.main(student.java:168)

This is the code,

import java.util.*;
import java.io.File;
import java.io.PrintWriter;

// **** Student details ****// 
class Student {
    // Identity description
    String name;
    char sex;
    int age;
    String id;
    // Educational description
    String department;

    void setInfo(){
        Scanner input = new Scanner(System.in);

        System.out.println("Please input the following information about the student...");
        System.out.print("Name:\t");
        name = input.nextLine();
        System.out.print("Sex:\t");
        sex = Character.toLowerCase(input.next().charAt(0));
        System.out.print("Age:\t");
        age = input.nextInt();
        System.out.print("Department:\t");
        department = input.nextLine();
        System.out.print("ID:\t");
        id = input.nextLine();

        input.close();
    }

}
// **** **** **** **** **** **** //


// **** Collection of the students **** //
class Group {
    ArrayList<Student> DB = new ArrayList<Student>();

    Student temp = new Student();

    void registerN(){
        Scanner input = new Scanner(System.in);
        System.out.print("How many students would you like to register: ");
        int n = input.nextInt();
        input.close();

        for(int i = 1; i <= n; ++i){
            temp.setInfo();
            DB.add(temp);
            System.out.println("Student(s) " + i + " out of " + n + " registered.");
        }
    }
}
//**** **** **** **** **** **** //

// **** A class to make use of the objects **** //
class Manage {

    public static void main(String[] args){
        Scanner input = new Scanner(System.in);

        Group base = new Group();
        // option string
        String option = "";

        // I specify the options a user can input here

        while(true){
            System.out.print("option: ");
            option = input.nextLine();
            option = option.toLowerCase();

            if(option.equals("register")){
                base.registerN();
            }
            else
                System.out.println("\t\"" + option + "\" not recognized!\n\tReview options list.");
        }
        input.close();
    }
}

I put a breaking point at the point control is passed to the function base.registerN(); which in turn passes control to temp.setInfo(). But immediately after that happens and setInfo() prints out Please input the following information about the student... Name:, I get the error I put above. Why is that?

  • 3
    That's a *lot* of code, most of which I strongly suspect is irrelevant. Please reduce this to a [mcve]. – Jon Skeet Dec 14 '17 at 10:40
  • 1
    Can you shorten this to a [mcve]? – achAmháin Dec 14 '17 at 10:40
  • I'm sure that's better now –  Dec 14 '17 at 10:43
  • Possible duplicate of [java.util.NoSuchElementException - Scanner reading user input](https://stackoverflow.com/questions/13042008/java-util-nosuchelementexception-scanner-reading-user-input) – achAmháin Dec 14 '17 at 10:46
  • No, it's still not a [mcve]. Do we really need all those options in order to reproduce the problem? – Jon Skeet Dec 14 '17 at 10:49
  • @Jon Skeet thank's for the comment there, I'm not just a "java" beginner but also a "stackoverflow.com" one. How about now? –  Dec 14 '17 at 10:58
  • Definitely getting there - but I don't think we need three classes here, do we? We don't need 5 different properties for each student, either, or an "option" where we can only type "register". Keep reducing it... (This isn't just an exercise in futility - this is how you should go about diagnosing problems. It's a skill that takes a while to learn, so now is a good time to practise.) – Jon Skeet Dec 14 '17 at 11:00

2 Answers2

1

Below method you have closed input stream by calling input.close();

void registerN(){
        Scanner input = new Scanner(System.in);
        System.out.print("How many students would you like to register: ");
        int n = input.nextInt();
        input.close();

If you call the method input.close() ,System.in will be closed. It wont accept any further input.

If you want to avoid this, create a global variable of scanner which can be used by all classes

System.in. was not instantiated by by your code, but by the JVM.

JVM will take care of closing it if needed.

Vishnu T S
  • 3,476
  • 2
  • 23
  • 39
0

When you dispose of a Scanner by calling close() you can no longer read from its input stream, even if you construct a new Scanner around it. That is why closing the Scanner inside registerN method leads to an error inside setInfo method.

You should change the approach by passing one Scanner object around your code, rather than constructing one "on demand" inside setInfo method:

void setInfo(Scanner input){
    ...
    name = input.nextLine();
    ...
}

Also pass Scanner to registerN:

if(option.equals("register")){
    base.registerN(input);
}

This way you would use a single Scanner created in main, and never close it.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523