1

I am writing a program that reads the text file and display the name and the grad of the first student and the average of the class. For the file given above, the result would be as follows: The first in the class is Ahmad Hamwi has 16.00 The average of the class is 12.25 This is thew text file i am trying to read from

    public class GradesReader {

/**
 * @param args the command line arguments
 * @throws java.io.FileNotFoundException
 */
public static void main(String[] args) throws FileNotFoundException {
    File grades = new File ("C:\\Users\\the_k\\OneDrive\\Documents\\NetBeansProjects\\GradesReader\\src\\gradesreader\\grades.txt");
    Scanner scan = new Scanner(grades);

    int lineNumber= 0;
    double grade;
    String StudentName;
    double min = 999;
    double max = -999;
    int sum = 0;
    int count=0;

    while (scan.hasNextLine()) {
        lineNumber++;

    StudentName = scan.next();
    grade = scan.nextDouble();
    count++;    
    if(grade>max){
     max=grade;
    }
    if(grade<min){
     min=grade;
    }

    System.out.println("The first in class is" + StudentName + "has" + max );
    double avg = sum /count;
    System.out.println("The average of the class is " + avg);

    }

}

This is the error I keep getting

> Exception in thread "main" java.util.InputMismatchException
    at java.util.Scanner.throwFor(Scanner.java:864)
    at java.util.Scanner.next(Scanner.java:1485)
    at java.util.Scanner.nextDouble(Scanner.java:2413)
    at gradesreader.GradesReader.main(GradesReader.java:37) 

I have been trying for hours now. I know the error is in line 37. It has something to do maybe with the type. I tried int and float but same.

David Conrad
  • 15,432
  • 2
  • 42
  • 54

2 Answers2

2

The next() method of scanner will only read until it encounters a delimiter, which is space by default. Since your names are in the format "Firstname Lastname" when you do

StudentName = scan.next();

You will only read in the "Firstname" part of that name, and then when you call

grade = scan.nextDouble();

It will try to read "Lastname" as a double value, which of course will not work and throw your error.

If all your names are in said format of "Firstname Lastname" you should be able to read them correctly by using the next() method twice:

StudentName = scan.next() + " " + scan.next();
OH GOD SPIDERS
  • 3,091
  • 2
  • 13
  • 16
2

Here's how I did it:

public class GradeReader {
private class Student {
    private String name;
    private float score;
    
    public Student(String name, float score) {
        this.name = name;
        this.score = score;
    }
    
    public String getName() {
        return name;
    }
    
    public float getScore() {
        return score;
    }
}
public List<Student> readFile(File file) {
    List<Student> students = new ArrayList<>();
    try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
        String line = null;
        while ((line = reader.readLine()) != null ) {
            int idx = line.lastIndexOf(" ");
            String name = line.substring(0, idx);
            float score = Float.parseFloat(line.substring(idx+1, line.length()));
            students.add(new Student(name, score));
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    
    return students;
}

public static void main(String [] args) {
    GradeReader reader = new GradeReader();
    
    File file = new File("<Path to File>");
    List<Student> students = reader.readFile(file);
    Optional<Student> highestStudent = students.stream().max(Comparator.comparing(Student::getScore));
    if (highestStudent.isPresent()) {
        System.out.println("The first in class is " + highestStudent.get().getName() + " with a score of " + highestStudent.get().getScore());
    }
    double average = students.stream().mapToDouble(Student::getScore).average().orElse(0.0);
    System.out.println("The average of the class is " + average);
}

}

Ryan
  • 1,762
  • 6
  • 11
  • I would have `split` the "line" by spaces into an array, then dealt with the pieces of the array, but this works, too. – computercarguy Jan 21 '22 at 16:28
  • @computercarguy That wouldn't work (at least not cleanly) as you don't know now many spaces are in the students name. If the score is always the last entry in the string, then finding the last space and going from there is far easier. Consider dutch name like "firstname van der blah" or if some students have middle names included, or multiple middle names. – Ryan Jan 21 '22 at 16:33
  • Sure, but if the file format ever gets changed, then you have to change your version of logic to something more like mine. With `split`, you can remove the last instance of the array for anything not the name (while assigning it to the model), then use the remaining bits for the name. Using an array in reverse order is a great trick when you know more about the end of the array than the beginning. – computercarguy Jan 21 '22 at 16:38