1

I am having a bit of trouble with my program which holds student names and grades in a 2D string array. Basically, I have a second (1D) array that will hold average grade for each student.

code so far:

class Program
{
    static void Main(string[] args)
    {
        // Create a 2D array for names, and their grades, and an array for average grades
        string[,] studentGrades = new string[5, 8];
        int[] average = new int[studentGrades.GetLength(0)];

        // Set student names/grades manually
        studentGrades[0, 0] = "Steve";
        studentGrades[0, 1] = "69";
        studentGrades[0, 2] = "80";
        studentGrades[0, 3] = "66";
        studentGrades[0, 4] = "75";
        studentGrades[0, 5] = "90";
        studentGrades[0, 6] = "69";
        studentGrades[0, 7] = "98";

        studentGrades[1, 0] = "Bob";
        studentGrades[1, 1] = "73";
        studentGrades[1, 2] = "67";
        studentGrades[1, 3] = "65";
        studentGrades[1, 4] = "91";
        studentGrades[1, 5] = "48";
        studentGrades[1, 6] = "33";
        studentGrades[1, 7] = "94";

        studentGrades[2, 0] = "Lewis";
        studentGrades[2, 1] = "67";
        studentGrades[2, 2] = "80";
        studentGrades[2, 3] = "66";
        studentGrades[2, 4] = "75";
        studentGrades[2, 5] = "90";
        studentGrades[2, 6] = "69";
        studentGrades[2, 7] = "63";

        studentGrades[3, 0] = "Sara";
        studentGrades[3, 1] = "55";
        studentGrades[3, 2] = "58";
        studentGrades[3, 3] = "63";
        studentGrades[3, 4] = "70";
        studentGrades[3, 5] = "55";
        studentGrades[3, 6] = "55";
        studentGrades[3, 7] = "76";

        studentGrades[4, 0] = "Xavier";
        studentGrades[4, 1] = "22";
        studentGrades[4, 2] = "27";
        studentGrades[4, 3] = "25";
        studentGrades[4, 4] = "19";
        studentGrades[4, 5] = "42";
        studentGrades[4, 6] = "18";
        studentGrades[4, 7] = "32";

        // Loop the array dimensions and output/format output the names/grades
        for (int name = 0; name < studentGrades.GetLength(0); name++)
        {
            for (int grade = 0; grade < studentGrades.GetLength(1); grade++)
            {
                Console.WriteLine(studentGrades[name, grade]);
            }
            Console.WriteLine("");
        }

        for (int i = 0; i < studentGrades.GetLength(0); i++)
        {
            for (int j = 0; j < studentGrades.GetLength(1); j++)
            {
                average[j] += int.Parse(studentGrades[i, j]);
            }
        }

    }
}

I get an un-handled exception in regards to the input string not being in the correct format where the average is set.

All help is appreciated!

Update

I've reviewed the solutions of code so far below, and I'm still having issues with getting the grade average to work as intended. I have 5 students with 7 grades. I want the program to output the average of each persons grades below their column.

Code:

static void Main(string[] args)
    {
        // Create a 2D array for names, and their grades, and an array for average grades
        string[,] studentGrades = new string[5, 8];
        int[] average = new int[studentGrades.GetLength(1)];

        // Set student names/grades manually
        //As done above, excluded for brevity reasons


        // Loop the array dimensions and output/format output the names/grades
        for (int grade = 0; grade < studentGrades.GetLength(1); grade++)
        {
            for (int name = 0; name < studentGrades.GetLength(0); name++)
            {
                // Composite formatting is used to align names/grades in grid -- specifically the alignment component.
                // Making the value higher (more neg) will increase spacing between elements
                // Positive number would right align elements instead
                Console.Write("{0, -15}", studentGrades[name, grade]);
            }
            // Moves each printed grade to a new line
            Console.WriteLine("");
        }

        for (int i = 0; i < studentGrades.GetLength(0); i++)
        {
            for (int j = 1; j < studentGrades.GetLength(1); j++)
            {
                average[j] += int.Parse(studentGrades[i, j]);
            }

            average[i] /= studentGrades.GetLength(1) - 1;
        }

        for (int i = 0; i <= average.GetLength(0) - 1; i++)
        {
            Console.Write("{0, -15}", i);
        }
        Console.WriteLine("");


    }

Update 2

It seems that the average array is not being properly populated. It seems to just print out 1, 2, 3, 4, 5, 6, 7 if I remove the average division. Furthermore, if I change averages' length to 5 -- or the length of the amount of names since there will only be 5 values, it breaks. This is likely because it's trying to add 7 items to a 5 item array.

1
  • 3
    I'd consider changing the type to a Dictionary<string, List<int>> instead. Should be easier to work with. Commented Dec 15, 2015 at 23:36

4 Answers 4

2

Every studentGrages[*, 0] element is not integer so you can't parse it to int

Skip the first elements

 for (int i = 0; i < studentGrades.GetLength(0); i++)
 {
       for (int j = 1; j < studentGrades.GetLength(1); j++)
       {
                average[j] += int.Parse(studentGrades[i, j]);
       }
 }
Sign up to request clarification or add additional context in comments.

Comments

1

You have to change this part of code:

// Store the average as a double array, otherwise you can't have averages with decimal values.
double[] average = new double[studentGrades.GetLength(0)];

for (int i = 0; i < studentGrades.GetLength(0); i++)
{
    // Start from j = 1, as j = 0 would get a name instead of a grade.
    for (int j = 1; j < studentGrades.GetLength(1); j++)
    {
        // Here use average[i] instead of average[j], because you want
        // the average grade for each student.
        average[i] += int.Parse(studentGrades[i, j]);
    }

    // Finish calculating the average.
    // GetLength(0) - 1 because the first item is a name, not a grade.
    average[i] /= studentGrades.GetLength(1) - 1;
}

for (int i = 0; i <= average.GetLength(0) - 1; i++)
{
    // Show at most 2 decimal digits.
    Console.Write("{0, -15:#.##}", average[i]);
}

2 Comments

I've updated the post with more info, could you please take a look at that, I'm not getting the results I expected.
I've updated my answer. You can find the full working example here: gist.github.com/ClaudiuGeorgiu/4674d227756ab1c42681
1

Your trying to include the string of the names (on the 0 index) with the average. e.g int.Parse("Steve") which is causing the exception, just skip on the first element on each colum.

for (int j = 1; j < studentGrades.GetLength(1); j++)

Comments

1

As other have rightly pointed out, you need to change the 0 to a 1 in the following line:

for (int j = 1; j < studentGrades.GetLength(1); j++)

Otherwise you're going to try to parse the name as an integer.

Also you need to change the index on average inside the loop to i rather than j.

average[i] += int.Parse(studentGrades[i, j]);

The other issue that you're going to have is that you're using integer mathematics - so when you do something like 7 / 2 you get an answer of 3 and not 3.5.

If I were you, and you don't want to change your data structure, I would do it this way:

var results =
    studentGrades
        .Cast<string>()
        .Select((x, n) => new { x, n })
        .GroupBy(xn =>  xn.n / studentGrades.GetLength(1), xn => xn.x)
        .Select(xs => new
        {
            student = xs.First(),
            average = xs.Skip(1).Select(x => int.Parse(x)).Average(),
        })
        .ToArray();

That gives me:

results

Alternatively, I would suggest that you change your data structure to this:

var studentGrades = new []
{
    new { student = "Steve", grades = new [] { 69, 80, 66, 75, 90, 69, 98, } },
    new { student = "Bob", grades = new [] { 73, 67, 65, 91, 48, 33, 94, } },
    new { student = "Lewis", grades = new [] { 67, 80, 66, 75, 90, 69, 63, } },
    new { student = "Sara", grades = new [] { 55, 58, 63, 70, 55, 55, 76, } },
    new { student = "Xavier", grades = new [] { 22, 27, 25, 19, 42, 18, 32, } },
};

Then this should work for you:

var results =
    studentGrades
        .Select(sg => new
        {
            sg.student,
            average = sg.grades.Average(),
        })
        .ToArray();

2 Comments

I have changed that line in the update code, but it doesn't seem to even be working correctly in the sense of population of the array. It fills the array with 0 - 7. Additionally, I'd want 5, as there are 5 people, but this obviously gives an out-of-bounds error.
@ryderd - You also have an issue with your index on average. I've edited my answer to show you what the issue is.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.