有一个包含5组8个数字的文件。每套都是参赛者的“分数”(总共5名参赛者)。我的任务是读取文件以获取每组,切出最高和最低分数,然后计算每个参赛者的平均分数。 该任务还要求我们使用一种方法来计算平均值,因此不允许我将整个程序塞入main方法中。
以下是供参考的数据集:
8.4 9.1 8.5 8.4 9.1 8.7 8.8 9.1
7.0 7.0 7.0 7.0 7.0 7.0 7.0 7.0
8.0 7.9 8.0 8.0 8.0 8.0 8.0 8.1
7.0 9.1 8.5 8.4 7.0 8.7 8.8 9.1
7.0 7.9 7.0 7.8 7.0 5.0 7.0 7.5
但是,我遇到了一个问题。每个参赛者的平均值计算为相同。这是因为每次我调用average()方法时,它都会创建文件读取的新实例,因此它每次都读取第一个8位数字。
这是我的代码:
//Code
import java.util.*;
import java.io.*;
public class DhruvPTheWinner{
//Method for averaging
public static double average()
{
double avg = 0.0;
double sum = 0.0;
double val = 0.0;
double highest = -999.0;
double lowest = 999.0;
//This is how we were taught to read a file, using Try and Catch to "import" the file
Scanner inFile = null;
try{
inFile = new Scanner (new File("theWinner.dat"));
}
catch (FileNotFoundException e){
System.out.println("File not found");
System.exit(0);
}
for(int j = 1; j <= 8; j++){
val = inFile.nextDouble();
//If statement to contain highest
if(val > highest)
{
highest = val;
}
//If statement to contain lowest
if(val < lowest)
{
lowest = val;
}
//Add the value (one of 8 #s) to the sum
sum += val;
}
//Take out highest and lowest so avg only includes middle 6
sum = (sum-highest)-lowest;
avg = sum/6;
return avg;
}
public static void main(String[] args){
//Scores for the Contestants
double c1Score = average();
double c2Score = average();
double c3Score = average();
double c4Score = average();
double c5Score = average();
//Printing the scores
System.out.printf("c1 is %.3f \nc2 is %.3f \nc3 is %.3f \nc4 is %.3f \nc5 is %.3f", c1Score, c2Score, c3Score, c4Score, c5Score);
}
}
运行时,这是输出:
c1 is 8.767
c2 is 8.767
c3 is 8.767
c4 is 8.767
c5 is 8.767
如何解决此问题并使计算机继续读取文件,而不是重新开始?
感谢您的帮助。
答案 0 :(得分:2)
问题在于,每次调用average
时,您都将重新打开文件(在开头)。
尝试分为两部分
1)在main
函数中:打开和关闭Scanner
对象,并将一行数据读入数组
2)将数组传递到average
伪代码为
Main
for(int j = 0; j < 8; j++){
val[j] = inFile.nextDouble();
}
average (val);
public static double average(double [] arr)
for(int j = 0; j < 8; j++){
val = arr[j];
.... // as before
}
答案 1 :(得分:0)
或者,您可以将Scanner inFile
声明为静态全局变量,并在调用main()
函数之前仅在average()
中对其进行一次初始化。
这属于类范围:
public class DhruvPTheWinner{
private static Scanner inFile=null;
将其放置在主要位置:
try{
inFile = new Scanner (new File("theWinner.dat"));
}
catch (FileNotFoundException e){
System.out.println("File not found");
System.exit(0);
}
其余的保持不变。
答案 2 :(得分:0)
我同意可怕的袋熊,您必须在Scanner
方法之外声明average()
我认为您可以从面向对象的角度来看这个问题。你到底有什么?您有上下文,其中包含一些数字。另外,上下文具有基于其数据的预先计算的属性。此上下文应从文件中读取。
让我们定义一个上下文并将所有相关计算封装到其中。
public class Contest {
private static int nextId = 1;
public final String id;
private final double[] data; // optionally, you can avoid storing whole array
public final double avg;
public final double sum;
public final double highest;
public final double lowest;
public Contest(String... data) {
id = "c" + nextId++;
// you can calculate all this using one loop (instead of Streams)
this.data = Arrays.stream(data).mapToDouble(Double::parseDouble).toArray();
sum = Arrays.stream(this.data).sum();
avg = Arrays.stream(this.data).average().orElse(Double.NaN);
highest = Arrays.stream(this.data).max().orElse(Double.NaN);
lowest = Arrays.stream(this.data).min().orElse(Double.NaN);
}
}
然后,您需要一个方法,该方法接受所需文件的路径并返回现有竞赛的列表:
public static List<Contest> readContests(Path path) throws IOException {
return Files.lines(path)
.map(line -> line.split("\\s+"))
.map(Contest::new)
.collect(Collectors.toList());
}
如您所见,这是基于OOP的完整设计。然后,您可以使用它并预想一下:avg,sum ...:
List<Contest> contests = readContests(Paths.get("theWinner.dat"));
contests.forEach(contest -> System.out.format(Locale.US, "%s is %.3f\n", contest.id, contest.avg));
输出:
c1 is 8.763
c2 is 7.000
c3 is 8.000
c4 is 8.356
c5 is 7.025