System.IndexOutOfRangeException VB GradeBook

时间:2018-03-22 15:17:55

标签: vb.net

所以我在尝试运行我的代码时遇到此错误“System.IndexOutOfRangeException:'索引超出了数组的范围。'”我不确定问题是什么。用户应该能够输入3个分配等级,然后查看平均值

  

我在“这就是错误”

标记了我收到错误的行
Public Class GradeBook
Dim grade(9, 2) As Integer 'Store 10 student grades on 3 tests'
Dim studentCount As Integer = 0 'Number of students entered'

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    GradeListBox.Items.Add(vbTab & vbTab & "Test 1" & vbTab & "Test 2" & vbTab & "Test 3" & vbTab & "Average")
End Sub

Private Sub SubmitButton_Click(sender As Object, e As EventArgs) Handles SubmitButton.Click
    grade(studentCount, 0) = Convert.ToInt32(Assignment1TextBox.Text)
    grade(studentCount, 1) = Convert.ToInt32(Assignment2TextBox.Text)
    grade(studentCount, 2) = Convert.ToInt32(Assignment3TextBox.Text)

    Dim output As String = "Student " & studentCount & vbTab
    For column = 0 To grade.GetUpperBound(1)
        If LetterRadioButton.Checked = True Then
            output &= vbTab & LetterGrade(grade(studentCount, column))
        Else
            output &= vbTab & grade(studentCount, column)
        End If
    Next
    output &= vbTab & CalculateStudentAverage(studentCount)
    GradeListBox.Items.Add(output)
    studentCount += 1
    AverageLabel.Text = CalculateClassAverage()
    displayBarChart()
End Sub
Function LetterGrade(ByVal grade As Double) As String
    Dim output As String = ""
    Select Case grade
        Case Is >= 90
            output = "A"
        Case Is >= 80
            output = "B"
        Case Is >= 70
            output = "C"
        Case Is >= 60
            output = "D"
        Case Is >= 50
            output = "E"

    End Select
    Return output
End Function
Function CalculateStudentAverage(ByVal row As Integer) As String
    Dim gradeTotal As Integer = 0
    For column = 0 To grade.GetUpperBound(1)
        gradeTotal += grade(row, column) 'THIS IS THE ERROR'
    Next
    Dim studentAverage As String = String.Empty
    If LetterRadioButton.Checked = True Then
        studentAverage = LetterGrade(gradeTotal / (grade.GetUpperBound(1) + 1))
    Else
        studentAverage = String.Format("{0:F}", (gradeTotal / grade.GetUpperBound(1) + 1))
    End If
    Return studentAverage
End Function
Function CalculateClassAverage() As String
    Dim classTotal As Integer = 0
    For row = 0 To studentCount - 1
        For column = 0 To grade.GetUpperBound(1)
            classTotal += grade(row, column)
        Next
    Next
    Dim classAverage As String = String.Empty
    If LetterRadioButton.Checked = True Then
        classAverage = LetterGrade(classTotal / (studentCount * (grade.GetUpperBound(1) + 1)))
    Else
        classAverage = String.Format("{0:F}", (classTotal / (studentCount * (grade.GetUpperBound(1) + 1))))
    End If
    Return classAverage
End Function
Sub displayBarChart()
    GradeListBox.Items.Clear()
    GradeListBox.Items.Add(vbTab & vbTab & "Test 1" & vbTab & "Test 2" & vbTab & "Test 3" & vbTab & "Average")
    For row = 0 To studentCount - 1
        Dim output As String = "Student " & row & vbTab
        For column = 0 To grade.GetUpperBound(1)
            If LetterRadioButton.Checked = True Then
                output &= vbTab & LetterGrade(grade(row, column))
            Else
                output &= vbTab & (grade(row, column))
            End If
        Next
        output &= vbTab & CalculateStudentAverage(studentCount)
        GradeListBox.Items.Add(output)
        studentCount += 1
        AverageLabel.Text = CalculateClassAverage()
        displayBarChart()
        Assignment1TextBox.Clear()
        Assignment2TextBox.Clear()
        Assignment3TextBox.Clear()
        If studentCount = grade.GetUpperBound(0) + 1 Then
            InputGradeGroupBox.Enabled = False
        End If
    Next
End Sub
End Class

1 个答案:

答案 0 :(得分:0)

说实话,我怀疑你是否以不适合OOP的方式处理它。对多个数据使用数组很容易出错,以后难以维护。

让我们考虑一下您希望如何表示数据。你有一群学生。在一个更完整的例子中,每个学生都会有一个姓名,个人详细信息,例如地址,他们正在接受的课程列表以及每门课程,每个作业的作业列表和分数,也可以表示为级。

所以从本质上讲,你有一个名为Student的类,各种信息都是该学生的属性。

最后你有一个这些学生的名单

在您的代码中,您只需拥有一个学号和三个作业分数。

您的基础学生课程应具有Number,Test1Score,Test2Score和Test3Score的属性。您还希望能够从每个分数,所有分数的平均分数和所有分数的平均分数中获得分数。

下面的代码定义了Student类,并记住了这些信息

Friend Class Student

    Public Property Number As Integer

    Public Property Test1Score As Integer

    Public Property Test2Score As Integer

    Public Property Test3Score As Integer


    Public Function Test1Grade() As String
        Return LetterGrade(Test1Score)
    End Function

    Public Function Test2Grade() As String
        Return LetterGrade(Test2Score)
    End Function

    Public Function Test3Grade() As String
        Return LetterGrade(Test3Score)
    End Function

    Friend Shared Function LetterGrade(ByVal grade As Double) As String
        Dim output As String = ""
        Select Case grade
            Case Is >= 90
                output = "A"
            Case Is >= 80
                output = "B"
            Case Is >= 70
                output = "C"
            Case Is >= 60
                output = "D"
            Case Is >= 50
                output = "E"
            Case Else
                output = "F"
        End Select
        Return output
    End Function

    Friend Function AverageScore() As Double
        Return (Test1Score + Test2Score + Test3Score) / 3
    End Function

    Friend Function AverageGrade() As String
        Dim avgscore As Double = AverageScore()
        Return LetterGrade(avgscore)
    End Function

End Class 

LetterGrade函数为Shared,因此可以在主表单中使用它来计算整个班级的平均成绩。

确定接下来想想您希望程序如何运作。你需要一份学生名单,所以在你的表格课程开始时,你需要这个......

Public Class Form1
    Private Students As New List(Of Student)

这样,您可以使用列表中的studentCount属性.Count,而不是尝试跟踪变量Students.Count。您不需要添加任何内容,因为Students列表会自动跟踪它。

接下来,您将需要计算班级平均分数/成绩的函数。

Function CalculateClassAverage() As String
    Dim classTotal As Integer = 0
    For Each tmpStudent As Student In Students
        With tmpStudent
            classTotal += .Test1Score + .Test2Score + .Test3Score
        End With
    Next
    Dim classAverage As String = String.Empty
    If LetterRadioButton.Checked = True Then
        classAverage = Student.LetterGrade((classTotal / Students.Count) / 3)
    Else
        classAverage = String.Format("{0:F}", (classTotal / (Students.Count)) / 3)
    End If
    Return classAverage
End Function

正如您所看到的,由于您的数据存储方式,这里存在许多差异,但您应该能够遵循它。一个区别是With语句,这允许您节省输入。在With.. End With块内,您只需输入tmpstudent.Test1Score

,而不是键入.Test1Score等。

另一点需要注意的是这条线..

classAverage = Student.LetterGrade(... etc

您可能认为没有声明名为Student的变量。有一个类,但不是变量。这实际上是在调用LetterGrade类定义中共享的Student函数。看看共享函数。

接下来是在ListBox中显示信息的代码。我没有改变名称,即使它误导了btw。

Sub displayBarChart()
    GradeListBox.Items.Clear()
    GradeListBox.Items.Add(vbTab & vbTab & "Test 1" & vbTab & "Test 2" & vbTab & "Test 3" & vbTab & "Average")
    For Each tmpstudent As Student In Students
        Dim output As String = "Student " & tmpstudent.Number & vbTab
        With tmpstudent
            If LetterRadioButton.Checked = True Then
                output &= .Test1Grade & vbTab & .Test2Grade & vbTab & .Test3Grade & vbTab & .AverageGrade
            Else
                output &= .Test1Score & vbTab & .Test2Score & vbTab & .Test3Score & vbTab & .AverageScore
            End If
        End With
        GradeListBox.Items.Add(output)
        AverageLabel.Text = CalculateClassAverage()
    Next
    If Students.Count = 10 Then
        InputGradeGroupBox.Enabled = False
    End If
End Sub

再次使用With..End With语句,但其余内容应该直截了当。

一点点代码..当您点击LetterRadioButton时,listBox和ClassAveragelabel中的数据将使用相应的字母/成绩进行刷新

Private Sub LetterRadioButton_CheckedChanged(sender As Object, e As EventArgs) Handles LetterRadioButton.CheckedChanged
    AverageLabel.Text = CalculateClassAverage()
    displayBarChart()
End Sub

最后,要将所有内容整合在一起,您需要点击按钮的代码..

Private Sub SubmitButton_Click(sender As Object, e As EventArgs) Handles SubmitButton.Click
    Dim tmpStudent As New Student With {.Number = Students.Count + 1,
                                        .Test1Score = Convert.ToDouble(Assignment1TextBox.Text),
                                        .Test2Score = Convert.ToDouble(Assignment2TextBox.Text),
                                        .Test3Score = Convert.ToDouble(Assignment3TextBox.Text)}

    Dim output As String = "Student " & tmpStudent.Number & vbTab

    With tmpStudent
        If LetterRadioButton.Checked = True Then
            output &= vbTab & .Test1Grade & vbTab & .Test2Grade & vbTab & .Test3Grade
        Else
            output &= vbTab & .Test1Score & vbTab & .Test2Score & vbTab & .Test3Score
        End If
    End With
    Students.Add(tmpStudent)
    If LetterRadioButton.Checked Then
        output &= vbTab & tmpStudent.AverageGrade
    Else
        output &= vbTab & tmpStudent.AverageScore
    End If
    GradeListBox.Items.Add(output)
    AverageLabel.Text = CalculateClassAverage()
    displayBarChart()
    Assignment1TextBox.Clear()
    Assignment2TextBox.Clear()
    Assignment3TextBox.Clear()
End Sub

希望除了我对您的问题的评论之外,这还可以更好地了解OOP。