patternjavaMinor
Taking student scores from a file, calculating averages, and printing
Viewed 0 times
filestudentaveragescalculatingprintingscoresandfromtaking
Problem
This program takes scores for each student from a .txt file and calculates their averages, as well as the average for each assignment and the class overall. This program works properly, just curious if I can make it look more professional.
Scores.txt
StudentGradeBookScores.java
```
import java.util.*;
import java.io.*;
import java.text.*;
public class StudentGradebookScores {
public static void main(String[]args) throws IOException {
File inputFile = new File("scores.txt");
Scanner data = new Scanner(inputFile);
DecimalFormat averages = new DecimalFormat("#.#");
int students = data.nextInt();
int assignments = data.nextInt();
double gradebook[][] = new double [students + 1][assignments + 1];
//putting the scores into the array
for (int i=0; i<students; i++) { //rows
for (int j=0; j<assignments; j++) { //coloums
gradebook[i][j] = data.nextDouble();
}
}
//calculating the average assignment score for each student (coloums)
for (int i=0; i<students; i++) {
double studentTotal = 0;
for (int j=0; j<assignments; j++) {
studentTotal = studentTotal + gradebook[i][j];
}
gradebook[i][assignments] = studentTotal/assignments;
}
//calculating the average score of each assigment for all students (rows)
for (int j=0; j<assignments; j++) {
double assignmentTotal = 0;
for (int i=0; i<students; i++) {
assignmentTotal = assignmentTotal + gradebook[i][j];
}
gradebook[students][j] = assignmentTotal/students;
}
//printing the gradebook
System.out.print("\t\t\t\tAssignment #:\n\t\t");
for (int j=0; j<assignments; j++) {
System.out.print((j+1) + "\t");
}
System.out.println("Avg");
for (int i=0; i<students; i++) {
System.out.print("Student #" + (i+1) + ":\t");
Scores.txt
5
6
95.2 89.1 98.0 78.9 100 67
100 99.6 100 100 90.1 82.2
100 85.5 85.1 74 81 79.4
98.6 71.5 68.9 62.4 56.9 0
100 100 100 88.3 91.6 81.3StudentGradeBookScores.java
```
import java.util.*;
import java.io.*;
import java.text.*;
public class StudentGradebookScores {
public static void main(String[]args) throws IOException {
File inputFile = new File("scores.txt");
Scanner data = new Scanner(inputFile);
DecimalFormat averages = new DecimalFormat("#.#");
int students = data.nextInt();
int assignments = data.nextInt();
double gradebook[][] = new double [students + 1][assignments + 1];
//putting the scores into the array
for (int i=0; i<students; i++) { //rows
for (int j=0; j<assignments; j++) { //coloums
gradebook[i][j] = data.nextDouble();
}
}
//calculating the average assignment score for each student (coloums)
for (int i=0; i<students; i++) {
double studentTotal = 0;
for (int j=0; j<assignments; j++) {
studentTotal = studentTotal + gradebook[i][j];
}
gradebook[i][assignments] = studentTotal/assignments;
}
//calculating the average score of each assigment for all students (rows)
for (int j=0; j<assignments; j++) {
double assignmentTotal = 0;
for (int i=0; i<students; i++) {
assignmentTotal = assignmentTotal + gradebook[i][j];
}
gradebook[students][j] = assignmentTotal/students;
}
//printing the gradebook
System.out.print("\t\t\t\tAssignment #:\n\t\t");
for (int j=0; j<assignments; j++) {
System.out.print((j+1) + "\t");
}
System.out.println("Avg");
for (int i=0; i<students; i++) {
System.out.print("Student #" + (i+1) + ":\t");
Solution
Declaring that
That's a lot of code to be stuffed into a single
Hard-coding an input filename makes it hard to reuse your code. I've modified it to read from either a filename specified on the command line or from
You should be able to avoid having to explicitly specify the dimensions of the data in the file.
Using Java 8 streams removes a lot of tedious looping from the implementation. Here is the rest of my suggested implementation:
main() throws IOException is probably the right thing to do for a simple program like this. A lot of beginners try to catch an exception that they don't have any idea how to handle properly.That's a lot of code to be stuffed into a single
main() function. Ideally, you should develop classes such that main() contains just a minimal amount of code, like this:public static void main(String[] args) throws IOException {
try (Scanner input = args.length > 0 ? new Scanner(new File(args[0])) :
new Scanner(System.in)) {
GradeBook book = new GradeBook(input);
System.out.println(book);
System.out.printf("Overall Average: %s\n",
FMT.format(book.average()));
}
}Hard-coding an input filename makes it hard to reuse your code. I've modified it to read from either a filename specified on the command line or from
System.in.You should be able to avoid having to explicitly specify the dimensions of the data in the file.
Using Java 8 streams removes a lot of tedious looping from the implementation. Here is the rest of my suggested implementation:
import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.IntStream;
public class GradeBook {
private List students;
private static final DecimalFormat FMT = new DecimalFormat("#.#");
public GradeBook(Scanner input) {
this.students = new ArrayList();
while (input.hasNextLine()) {
double[] student = Arrays.stream(input.nextLine().trim().split("\\s+"))
.mapToDouble(Double::parseDouble)
.toArray();
students.add(student);
}
}
public double getScore(int student, int assignment) {
return this.students.get(student)[assignment];
}
public double averageForStudent(int student) {
return Arrays.stream(this.students.get(student))
.average()
.getAsDouble();
}
public double averageForAssignment(int assignment) {
return this.students.stream()
.mapToDouble((assignments) -> assignments[assignment])
.average()
.getAsDouble();
}
public double average() {
return IntStream.range(0, this.students.size())
.mapToDouble((s) -> this.averageForStudent(s))
.average()
.getAsDouble();
}
public String toString() {
StringBuilder out = new StringBuilder();
int numAssignments = this.students.stream()
.mapToInt((assignments) -> assignments.length)
.max()
.getAsInt();
// Header
out.append("\t\t\t\tAssignment #:\n\t\t");
for (int a = 0; a 0 ? new Scanner(new File(args[0])) :
new Scanner(System.in)) {
GradeBook book = new GradeBook(input);
System.out.println(book);
System.out.printf("Overall Average: %s\n",
FMT.format(book.average()));
}
}
}Code Snippets
public static void main(String[] args) throws IOException {
try (Scanner input = args.length > 0 ? new Scanner(new File(args[0])) :
new Scanner(System.in)) {
GradeBook book = new GradeBook(input);
System.out.println(book);
System.out.printf("Overall Average: %s\n",
FMT.format(book.average()));
}
}import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.IntStream;
public class GradeBook {
private List<double[]> students;
private static final DecimalFormat FMT = new DecimalFormat("#.#");
public GradeBook(Scanner input) {
this.students = new ArrayList<double[]>();
while (input.hasNextLine()) {
double[] student = Arrays.stream(input.nextLine().trim().split("\\s+"))
.mapToDouble(Double::parseDouble)
.toArray();
students.add(student);
}
}
public double getScore(int student, int assignment) {
return this.students.get(student)[assignment];
}
public double averageForStudent(int student) {
return Arrays.stream(this.students.get(student))
.average()
.getAsDouble();
}
public double averageForAssignment(int assignment) {
return this.students.stream()
.mapToDouble((assignments) -> assignments[assignment])
.average()
.getAsDouble();
}
public double average() {
return IntStream.range(0, this.students.size())
.mapToDouble((s) -> this.averageForStudent(s))
.average()
.getAsDouble();
}
public String toString() {
StringBuilder out = new StringBuilder();
int numAssignments = this.students.stream()
.mapToInt((assignments) -> assignments.length)
.max()
.getAsInt();
// Header
out.append("\t\t\t\tAssignment #:\n\t\t");
for (int a = 0; a < numAssignments; a++) {
out.append(a + 1).append('\t');
}
out.append("Avg\n");
// Body
for (int s = 0; s < this.students.size(); s++) {
out.append("Student #").append(s + 1).append(":\t");
for (int a = 0; a < numAssignments; a++) {
out.append(FMT.format(this.getScore(s, a))).append('\t');
}
out.append(FMT.format(this.averageForStudent(s))).append('\n');
}
// Footer
out.append("Average\t\t");
for (int a = 0; a < numAssignments; a++) {
out.append(FMT.format(this.averageForAssignment(a))).append('\t');
}
out.append('\n');
return out.toString();
}
public static void main(String[] args) throws IOException {
try (Scanner input = args.length > 0 ? new Scanner(new File(args[0])) :
new Scanner(System.in)) {
GradeBook book = new GradeBook(input);
System.out.println(book);
System.out.printf("Overall Average: %s\n",
FMT.format(book.average()));
}
}
}Context
StackExchange Code Review Q#83066, answer score: 8
Revisions (0)
No revisions yet.