我正在使用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;
}
}
答案 0 :(得分:1)
我会一次读取整行来使用扫描仪。然后,我们可以在一个逻辑步骤中处理整行:
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);
}
答案 1 :(得分:1)
您可以像以下示例中那样使用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...
}
}
答案 2 :(得分: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);
}