Как использовать метод Java для построчной обработки входного файла из цикла? - PullRequest
0 голосов
/ 27 ноября 2018

Я использую 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

Возможно липолучить методы studentAverage и determineGrade в приведенном ниже коде для обработки второй и третьей строк ввода, как в примере выше, или мне нужно пересмотреть всю структуру цикла / метода?

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 ]

0 голосов
/ 27 ноября 2018

вы можете использовать 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...

  }
}
0 голосов
/ 27 ноября 2018

Причина, по которой ваш код многократно печатает средние оценки, заключается в том, что этот метод здесь

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;
    }

Проблема в том, что, хотя вы думаете, что читаете последовательные строки, вы на самом деле просто читаете первую строкуфайла всякий раз, когда выполняются эти методы, и, следовательно, вы получаете первые оценки учащихся.

A Решение

Если вам удобно 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);
    }
0 голосов
/ 27 ноября 2018

Я бы использовал сканер, читая всю строку за раз.Затем мы можем обработать всю эту строку за один логический шаг:

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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...