Program ignoring the last row in the file in calculation

Tags: , , , ,



I have a text file with data that looks like this (TestData.txt):

Name|Test1|Test2|Test3|Test4|Test5|Test6|Test7|Test8|Test9|Test10
John Smith|82|89|90|78|89|96|75|88|90|96
Jane Doe|90|92|93|90|89|84|97|91|87|91
Joseph Cruz|68|74|78|81|79|86|80|81|82|87
Suzanne Nguyen|79|83|85|89|81|79|86|92|87|88
Richard Perez|100|84|73|81|92|84|95|96|95|100
Ivan Dyer|77|91|90|75|97|94|76|89|90|92
Craig Palmer|91|84|98|89|82|75|78|96|100|97
Madeline Rogers|75|79|78|93|91|76|80|88|100|81
Chelsea Roxas|87|94|89|96|95|85|88|92|86|86
Jasper Bautista|100|83|93|100|98|97|96|97|97|98
Tyler Perez|82|89|90|78|89|96|75|88|90|96

My code parses the file and does some calculations with it.

However, in the method arrangeList() within which calls another method called getTestAvg() (calculates column means), the program ignores Tyler Perez’s scores.

I noticed that the results I am getting were inaccurate so I went and printed the whole 2d array with all the test scores and the last column is nowhere to be found.

My entire code is below and I hope someone could point out what causes this.

I keep getting an IndexOutOfBounds error whenever I try to switch N (# of students) and M (# of tests) to see what happens. At first, I have 10 students and 10 tests, and all the calculations were correct, but when I added another student, the calculations became inaccurate.

I apologize in advance if my code isn’t as well-designed as I’m not an experienced programmer.

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

public class TestAverages
{
  private static int[] grades;
  private static int[] testTotal;
  private static int N;
  private static double classTotal;
  private static int M;
  
  public static void main(String[] args) throws FileNotFoundException
  {
    File input = new File("TestData.txt");
    Scanner in = new Scanner(input);
    parseFile(in); 
  }
  
  
  public static void parseFile(Scanner in) throws FileNotFoundException
  {
    TestAverages t = new TestAverages();
    in.nextLine(); 
    double total = 0.0;
    
    ArrayList<Double> testScores = new ArrayList<Double>();
    int index = 0;
    while(in.hasNextLine())
    {
      String line = in.nextLine();
      String[] data = line.split("\|");
      String name = data[0];
      
      grades = new int[data.length - 1];
      N = grades.length;

      for(int i = 0; i < N; i++){
        grades[i] = Integer.parseInt(data[i + 1]);
        testScores.add((double)grades[i]);
      }
      
      System.out.println(name + "t");
      System.out.println("Student Average: " + t.getStudentAvg(grades) + "%n");
      total += t.getStudentAvg(grades);
      
      M++;
      
    }
    t.arrangeList(testScores);
    System.out.printf("nClass Average: %.1f%%n", t.getClassAvg(total));
    

    
  }
  
  
  public double getStudentAvg(int[] grades)
  {
    double total = 0.0;
    double avg = 0.0;
    int N = grades.length;
    
    for(int i = 0; i < N; i++){
      total += grades[i];}
    
    avg = total / N;
    
    return avg;
  }
  
  
  public double getClassAvg(double total)
  {
    double classAvg = total / M;
    
    return classAvg;
  }
  

  public double[][] arrangeList(ArrayList testScores)
  {
    double[][] tests = new double[N][N];
    
    int len = tests.length;
    for(int i = 0; i < len; i++)
    {
      for(int j = 0; j < len; j++)
      {
        tests[i][j] = (Double) testScores.get(i*N + j);
      }
    }

    for(int i = 0; i < len; i++)
    {
      double avg = getTestAvg(tests, i);
      System.out.printf("nTest " + (i + 1) + " Average: %.1f%%n", avg);
    }
    return tests;
  }
  

  public double getTestAvg(double[][] testScores, int index)
  {
    double testAvg = 0.0;
    for(int i = 0; i < N; i++)
    {
      testAvg += testScores[i][index]; 
    }

    return testAvg / N;
  }
}

Here are the numbers I’m supposed to be getting (top) compared to what my program outputs (bottom). enter image description here enter image description here

Answer

As the other responses already stated, you had quite the issue with your variables and loops. I now changed N to # of students and M to # of tests to be as you stated in your question.

Next time, maybe try to improve your variable naming, so you don’t get confused. (e.g. switch out n and m for s (students) and t (tests), if you like your variable names short).

This should work now. Just check against your code to see the changes.

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

public class TestAverages {
    private static int[] grades;
    private static int n = 0; // amount of students
    private static int m; // amount of tests

    public static void main(String[] args) throws FileNotFoundException {
        File input = new File("TestData.txt");
        Scanner in = new Scanner(input);
        parseFile(in);
    }

    public static void parseFile(Scanner in) throws FileNotFoundException {
        TestAverages t = new TestAverages();
        in.nextLine();
        double total = 0.0;

        ArrayList<Double> testScores = new ArrayList<Double>();
        while (in.hasNextLine()) {
            String line = in.nextLine();
            String[] data = line.split("\|");
            String name = data[0];

            grades = new int[data.length - 1];
            m = grades.length;

            for (int i = 0; i < m; i++) {
                grades[i] = Integer.parseInt(data[i + 1]);
                testScores.add((double) grades[i]);
            }

            System.out.println(name + "t");
            System.out.println("Student Average: " + t.getStudentAvg(grades) + "%n");
            total += t.getStudentAvg(grades);

            n++;
        }
        t.arrangeList(testScores);
        System.out.printf("nClass Average: %.1f%%n", t.getClassAvg(total));
    }

    public double getStudentAvg(int[] grades) {
        double total = 0.0;
        double avg = 0.0;

        for (int i = 0; i < grades.length; i++) {
            total += grades[i];
        }

        avg = total / grades.length;

        return avg;
    }

    public double getClassAvg(double total) {
        double classAvg = total / n;

        return classAvg;
    }

    public double[][] arrangeList(ArrayList<Double> testScores) {
        double[][] tests = new double[n][m];

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                tests[i][j] = (Double) testScores.get(i * m + j);
            }
        }

        for (int i = 0; i < m; i++) {
            double avg = getTestAvg(tests, i);
            System.out.printf("nTest " + (i + 1) + " Average: %.1f%%n", avg);
        }
        return tests;
    }

    public double getTestAvg(double[][] testScores, int index) {
        double testAvg = 0.0;
        for (int i = 0; i < n; i++) {
            testAvg += testScores[i][index];
        }

        return testAvg / n;
    }
}


Source: stackoverflow