学生考试成绩计算平均值不正确

时间:2014-11-03 05:35:54

标签: arrays vb.net function structure average

我有一项建立学生考试成绩申请的任务 我有一个结构来保存一个学生的名字,一个数组可以容纳5个考试成绩,以及一个平均分数。我为6名学生创建了一系列结构。用户输入通过文本框设置。我需要计算每个学生的平均值。 作业要求: 应用程序应具有存储的结构:名称(字符串),测试分数(5个双精度数组)和平均值(双精度数)。它应该有一个由6个结构变量组成的数组来匹配6个学生。它应该允许用户输入每个学生的数据,并计算每个学生的平均测试分数。用户需要能够在文件等中保存,读取和打印数据。

不应接受低于0或高于100的分数。

我已经阅读了几篇帖子,但无法解决现有帖子,并且花了最近两天的时间尝试解决。现在我没有得到正确的平均值 我还需要能够打印和检索信息,但我首先要解决这个问题。我在学生的最大计数中尝试了5和6,在测试的最大计数中尝试了4和5。我相信我的数字是正确的,但很多帖子都有不同的数字,但是当我使用这些数字时,我在调试模式下运行时得到的数量为7,所以我不是100%肯定但是相信这是正确的。似乎总和没有正确添加,我已经尝试了很多方法来修复,甚至尝试初始化回到0然后转到下一个数字,但我到目前为止没有尝试过似乎工作。因此,为每组成绩提供不同的Try Catch声明的原因。我现在离开以防万一我可能需要分开。

这是我的代码。任何帮助表示赞赏 fyi-出于某种原因,当我发布时,代码将不会从Imports System.IO开始,因此初始代码在'在此处输入代码'没有显示为vb。请让我知道如何解决以后的帖子。

谢谢!

Imports System.IO

Public Class Form1

    'Class level variables
    Const intMAX_STUDENTS As Integer = 5  'Number of Students
    Const intMAX_TESTS As Integer = 4  'Number of Tests
    Private strFilename As String = "StudentReport.txt"    'Document File name

    Private student(intMAX_STUDENTS) As StudentRecord   'Array for student names

    Structure StudentRecord

        Dim strStudent As String
        Dim dblTestScores() As Double
        Dim dblAverage As Double
    End Structure

    Sub CalcAverage()

        ImportNames()

        'Variable to hold the total of the grades.
        Dim dblGradesTotal0 As Double = 0
        Dim dblGradesTotal1 As Double = 0
        Dim dblGradesTotal2 As Double = 0
        Dim dblGradesTotal3 As Double = 0
        Dim dblGradesTotal4 As Double = 0
        Dim dblGradesTotal5 As Double = 0

        'Add scores to the array
        For intIndex = 0 To intMAX_STUDENTS
            ReDim student(intIndex).dblTestScores(4)  'Scores per student
        Next

        Try
            'Get grades for first student
            student(0).dblTestScores(0) = ValidInput(CDbl(txtGrade00.Text))
            student(0).dblTestScores(1) = ValidInput(CDbl(txtGrade01.Text))
            student(0).dblTestScores(2) = ValidInput(CDbl(txtGrade02.Text))
            student(0).dblTestScores(3) = ValidInput(CDbl(txtGrade03.Text))
            student(0).dblTestScores(4) = ValidInput(CDbl(txtGrade04.Text))

            For Each i As StudentRecord In student
                For Each a As Double In i.dblTestScores
                    dblGradesTotal0 += a
                Next
            Next

            lblAvg0.Text = CStr(dblGradesTotal0 / intMAX_TESTS)
        Catch ex As Exception
            MessageBox.Show("Be sure to enter a valid numeric score")
        End Try

        Try
            'Get grades for second student
            student(1).dblTestScores(0) = ValidInput(CDbl(txtGrade10.Text))
            student(1).dblTestScores(1) = ValidInput(CDbl(txtGrade11.Text))
            student(1).dblTestScores(2) = ValidInput(CDbl(txtGrade12.Text))
            student(1).dblTestScores(3) = ValidInput(CDbl(txtGrade13.Text))
            student(1).dblTestScores(4) = ValidInput(CDbl(txtGrade14.Text))

            For Each i As StudentRecord In student
                For Each b As Double In i.dblTestScores
                   dblGradesTotal1 += b
                Next
            Next

            lblAvg1.Text = CStr(dblGradesTotal1 / intMAX_TESTS)
        Catch ex As Exception
            MessageBox.Show("Be sure to enter a valid numeric score")
        End Try

        Try
            'Get grades for third student
            student(2).dblTestScores(0) = ValidInput(CDbl(txtGrade20.Text))
            student(2).dblTestScores(1) = ValidInput(CDbl(txtGrade21.Text))
            student(2).dblTestScores(2) = ValidInput(CDbl(txtGrade22.Text))
            student(2).dblTestScores(3) = ValidInput(CDbl(txtGrade23.Text))
            student(2).dblTestScores(4) = ValidInput(CDbl(txtGrade24.Text))

            For Each i As StudentRecord In student
                For Each c As Double In i.dblTestScores
                    dblGradesTotal2 += c
                Next
            Next

            lblAvg2.Text = CStr(dblGradesTotal2 / intMAX_TESTS)
        Catch ex As Exception
            MessageBox.Show("Be sure to enter a valid numeric score")
        End Try

        Try
            'Get grades for fourth student
            student(3).dblTestScores(0) = ValidInput(CDbl(txtGrade30.Text))
            student(3).dblTestScores(1) = ValidInput(CDbl(txtGrade31.Text))
            student(3).dblTestScores(2) = ValidInput(CDbl(txtGrade32.Text))
            student(3).dblTestScores(3) = ValidInput(CDbl(txtGrade33.Text))
            student(3).dblTestScores(4) = ValidInput(CDbl(txtGrade34.Text))

            For Each i As StudentRecord In student
                For Each d As Double In i.dblTestScores
                    dblGradesTotal3 += d
                Next
            Next

            lblAvg3.Text = CStr(dblGradesTotal3 / intMAX_TESTS)
        Catch ex As Exception
            MessageBox.Show("Be sure to enter a valid numeric score")
        End Try

        Try
            'Get grades for fifth student
            student(4).dblTestScores(0) = ValidInput(CDbl(txtGrade40.Text))
            student(4).dblTestScores(1) = ValidInput(CDbl(txtGrade41.Text))
            student(4).dblTestScores(2) = ValidInput(CDbl(txtGrade42.Text))
            student(4).dblTestScores(3) = ValidInput(CDbl(txtGrade43.Text))
            student(4).dblTestScores(4) = ValidInput(CDbl(txtGrade44.Text))

            For Each i As StudentRecord In student
                For Each e As Double In i.dblTestScores
                    dblGradesTotal4 += e
                Next
            Next

            lblAvg4.Text = CStr(dblGradesTotal4 / intMAX_TESTS)
        Catch ex As Exception
            MessageBox.Show("Be sure to enter a valid numeric score")
        End Try

        Try
            'Get grades for sixth student
            student(5).dblTestScores(0) = ValidInput(CDbl(txtGrade50.Text))
            student(5).dblTestScores(1) = ValidInput(CDbl(txtGrade51.Text))
            student(5).dblTestScores(2) = ValidInput(CDbl(txtGrade52.Text))
            student(5).dblTestScores(3) = ValidInput(CDbl(txtGrade53.Text))
            student(5).dblTestScores(4) = ValidInput(CDbl(txtGrade54.Text))

            For Each i As StudentRecord In student
                For Each f As Double In i.dblTestScores
                    dblGradesTotal5 += f
                Next
            Next

            lblAvg5.Text = CStr(dblGradesTotal5 / intMAX_TESTS)
        Catch ex As Exception
            MessageBox.Show("Be sure to enter a valid numeric score")
        End Try
    End Sub

    Private Sub mnuFileOpen_Click(sender As Object, e As EventArgs) Handles mnuFileOpen.Click

    End Sub

    Private Sub mnuFileSave_Click(sender As Object, e As EventArgs) Handles mnuFileSave.Click

    End Sub

    Private Sub mnuFilePrint_Click(sender As Object, e As EventArgs) Handles mnuFilePrint.Click

    End Sub

    Private Sub mnuFileExit_Click(sender As Object, e As EventArgs) Handles mnuFileExit.Click

        Me.Close()
    End Sub

    Private Sub mnuReportClear_Click(sender As Object, e As EventArgs) Handles mnuReportClear.Click

    End Sub

    Private Sub mnuHelpAbout_Click(sender As Object, e As EventArgs) Handles mnuHelpAbout.Click

        MessageBox.Show("This contains information regarding the Student Test Scores Application")
    End Sub

    Private Sub btnCalc_Click(sender As Object, e As EventArgs) Handles btnCalc.Click

        CalcAverage()
    End Sub

    Public Function ValidInput(ByVal score As Double) As Double

        If score >= 0 And score <= 100 Then
            Return (score)
        Else
            Return MessageBox.Show("Please enter a valid test score between 0 and 100")
        End If
    End Function

    Sub ImportNames()

        student(0).strStudent = txtStudent0.Text
        student(1).strStudent = txtStudent1.Text
        student(2).strStudent = txtStudent2.Text
        student(3).strStudent = txtStudent3.Text
        student(4).strStudent = txtStudent4.Text
        student(5).strStudent = txtStudent5.Text
    End Sub
End Class

1 个答案:

答案 0 :(得分:1)

欢迎来到SO。将来,请仅发布相关代码,而不是所有内容。在这种情况下,相关代码将是Try-Catch块之一,如果您获得分数和平均值,而不是所有代码加上其余代码。

无论如何,如果不确切知道你看到了什么,我认为你的平均值没有正确出现的原因是因为你计算它们的方式。例如:

For Each i As StudentRecord In student
    For Each f As Double In i.dblTestScores
         dblGradesTotal5 += f
    Next
Next

外部循环将遍历student数组中的所有结构。

然后内部循环将对该学生的所有分数求和。

然后你去找下一个学生....并将所有学生的总分加上以前学生的总分。

对于该学生的分数,您只需要一个循环。您已经知道数组中结构的索引,所以:

For Each f As Double In student(5).dblTestScores
    dblGradesTotal5 += f
Next

然后这一行:

lblAvg5.Text = CStr(dblGradesTotal5 / intMAX_TESTS)

会给你那个学生的平均分。

还需要考虑一些小问题。

  1. 您的Try-Catch块每次都做同样的事情。将代码重构为方法(Sub)并保存手指和键盘:)

  2. ValidInput函数中,您将返回类型指定为Double,但在Else块中,您将返回MessageBox.Show。我甚至不确定会编译,但VB.NET并不像C#那样挑剔。在任何情况下,在Else中返回表示错误的双精度数(-1会很好)并在调用ValidInput的方法中弹出消息框。

  3. 输入验证示例

    验证用户输入至关重要,而且您正好这样做。在编程中有一句老话 - &#34;永远不要相信用户的输入。&#34;

    您当前的方法面临的挑战是,您尝试返回两项中的一项,具体取决于验证结果,并且您只能从方法中返回一种类型(除非您使用out参数)。

    通常,我更喜欢在尝试转换类型时使用TryParse,因为它将返回转换(解析)是否成功的布尔值,以及out参数中解析的结果(第二个参数)。如果转换失败,这可以防止丑陋的运行时错误。此外,CDbl函数是Visual Basic(.NET之前版本)的保留,并且通常认为使用内置的.NET转换运算符会更好。

    执行此操作的一种方法如下:

    Dim score As Double
    
    If Double.TryParse(txtGrade50.Text, score) AndAlso (score >= 0 And score <= 100) Then
        student(5).dbltTestScores(0) = score
    Else
        MessageBox.Show("Please enter a valid test score between 0 and 100")
    End If
    

    请注意在上述AndAlso语句中使用If - 这提供了短路逻辑。如果TryParse失败,则无法评估任何其他内容。

    上面的缺点是,现在你需要重复很多代码。另一个缺点是,在将输入分配给阵列之前,您正在评估输入,并且您没有给出用户输入错误的任何指示。

    我建议在将值分配给结构数组之前验证所有输入 - 这样你就可以告诉用户哪些值是错误的,他们可以纠正它并再试一次。

    这里重要的是确保在处理之前数据是正确的(在要求的限制范围内)。其他任何东西都很有可能很快变得非常丑陋和混乱。

    最后的注意事项 - 在.NET中,匈牙利表示法通常不被认为是最佳实践(即,dblGradesTotal5是匈牙利表示法的一个示例 - 您可以在其中添加一个类型的变量名称)。一个简单的gradesTotal5是正常的。