有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

如何使用Java方法从循环中处理输入文件linebyline?

我使用Java来处理一个文件,方法是从循环中为每一行输入调用多个方法。问题是,对于循环的每次迭代,方法只读取第一行输入。例如,此输入:

Jones 90 90 90
Brown 80 80 80
Smith 70 70 70

应产生以下结果:

Jones 90 A
Brown 80 B
Smith 70 C

但我最终得到的是:

Jones 90 A
Brown 90 A
Smith 90 A

是否可以在下面的代码中使用studentAveragedetermineGrade方法来处理上述示例中的第二行和第三行输入,或者我需要重新考虑整个循环/方法结构

import java.io.*;
import java.util.Scanner;

public class Lab07Part01
{
    public static void main(String[] args) throws IOException
    {
        File infile = new File("Grades.txt");
        Scanner myfile = new Scanner(infile);
        Scanner counter = new Scanner(infile);

        String studentName = "";
        int testQty = 0;
        int studentQty = -1;
        double studentAvg = 0.0;
        double classSum = 0.0;
        double classAvg = 0.0;
        char letterGrade = 'X';

        while(counter.hasNextLine()) {
            studentQty++;
            counter.nextLine();
        }

        testQty = myfile.nextInt();

        System.out.println("Name   Average   Letter Grade");
        for(int i = 0; i < studentQty; i++) {
            studentName = myfile.next();
            studentAvg = studentAverage(testQty);
            classAvg += studentAvg;
            letterGrade = determineGrade(studentAvg);
            System.out.println(studentName + " " + studentAvg + " " + letterGrade);
            myfile.nextLine();
        }

        classAvg = overallAverage(studentQty, classSum);

        System.out.println("The average test grade is: " + classAvg);

    }

    public static double studentAverage(int testQty) throws IOException
    {
        File infile = new File("Grades.txt");
        Scanner scanavg = new Scanner(infile);
        double studentSum = 0;

        scanavg.nextLine();
        scanavg.next();

        for(int i = 1; i <= testQty; i++) {
            studentSum += scanavg.nextDouble();
        }

        double studentAvg = studentSum / testQty;
        return studentAvg;
    }

    public static char determineGrade(double studentAvg) throws IOException
    {
        char letterGrade = 'X';

        if(studentAvg >= 90.0)
            letterGrade = 'A';
        else if(studentAvg >= 80.0)
            letterGrade = 'B';
        else if(studentAvg >= 70.0)
            letterGrade = 'C';
        else if(studentAvg >= 60.0)
            letterGrade = 'D';
        else if(studentAvg < 60.0)
            letterGrade = 'F';

        return letterGrade;
    }

    public static double overallAverage(int studentQty, double classSum) throws IOException
    {
        double classAvg = classSum / studentQty;
        return classSum;
    }
}

共 (3) 个答案

  1. # 1 楼答案

    代码重复打印平均标记的原因在于这里的方法

    public static double studentAverage(int testQty) throws IOException
        {
            File infile = new File("Grades.txt");
            Scanner scanavg = new Scanner(infile);
            double studentSum = 0;
    
            scanavg.nextLine();
            scanavg.next();
    
            for(int i = 1; i <= testQty; i++) {
                studentSum += scanavg.nextDouble();
            }
    
            double studentAvg = studentSum / testQty;
            return studentAvg;
        }
    

    问题是,尽管您认为您正在读取连续的行,但实际上,每当执行此方法时,您只是在读取文件的第一行,因此最终会得到第一个学生的分数

    解决方案

    如果您对Streams和java感到满意。nio,您可以使用Files.lines()在功能上做得更优雅一点

    public static void main(String... args) throws IOException {
    
            // The following line reads each line from your data file and does some
            // with it.
            Files.lines(Paths.get("/path/to/your/file")).forEach(ThisClass::doSomethingWithLine);
    
            System.out.println("clas average is "+ (classMarks / totalStuds));
        }
    
        static double classMarks=0; //total marks of the class
        static int totalStuds=0; // total students read until now
    
    
        static void doSomethingWithLine(String line) {
            Scanner sc = new Scanner(line);
    
            // Parse the tokens
            // student name (assuming only first name according to your
            //  example) otherwise use pattern to parse multi part names
            String name = sc.next();
    
            // parse student marks
            // (you could create a method for this to make things cleaner)
            int subA = sc.nextInt();
            int subB = sc.nextInt();
            int subC = sc.nextInt();
            //calculate average
            double avg = (subA + subB + subC) / 3;
    
            // calculate class average
            classMarks = classMarks + avg
            totalStuds++;
    
            //determine grade
            char grade = determineGrade(avg);
            System.out.println(name + " " + avg + " " + grade);
        }
    
  2. # 2 楼答案

    您可以在下面的示例中使用类似的BufferedReader。但是你需要自己跟踪文件的结尾

    try (BufferedReader br = new BufferedReader(new FileReader("<path to your file>")));
    
      for (Item item : list) {
    
        String line = br.readLine();
        if (line == null) {
          break; // no more lines to read
        }
        // do something with line...
    
      }
    }
    
  3. # 3 楼答案

    我会使用扫描仪,一次读取一整行数据。然后,我们可以在一个逻辑步骤中处理整条线路:

    File infile = new File("Grades.txt");
    Scanner myfile = new Scanner(infile);
    
    while (myfile.hasNextLine()) {
        String line = myfile.nextLine();
        String[] parts = line.split("\\s+");
        double average = 0.0d;
        for (int i=1; i < parts.length; ++i) {
            average += Double.parseDouble(parts[i]);
        }
        average /= parts.length - 1;
        char letterGrade = determineGrade(average);
    
        System.out.println(parts[0] + " " + average + " " + letterGrade);
    }