类 用于确定最终成绩和平均成绩的代码不起作用

Classes code to determine final grade and average not working

我最近接到一项任务,要求我创建一个 class,其中包含私有变量和成员 functions/void 函数。 类 刚刚被介绍给我,我的老师给我布置了一个我不太理解的作业。我遇到的问题是平均成绩和字母成绩没有正确输出,如下所示。一切都必须在成员函数中进行。另外,我是否正确使用了成员函数?我在网上看到它们是在 class 中定义的,但在我的笔记中我看到它们被引用并像用户定义的函数一样被对待。我遇到的困惑是作业的这一部分:

member functions to set each of the member variables to values given as an argument(s) to the function, member functions to retrieve the data from each of the member variables, a void function that calculates the student’s weighted average numeric score for the entire course and sets the corresponding member variable, and a void function that calculates the student’s final letter grade and sets the corresponding member variable

我的代码如下:

#include <iostream>
#include <cmath>

using namespace std;

class student_records
{
    private:
        double quiz1, quiz2, midterm_exam, final_exam;
        float weighted_avg;
        char final_grade;

    public:
        void setquiz1 (double q1)
        {
            quiz1 = q1;
        }
        void setquiz2 (double q2)
        {
            quiz2 = q2;
        }
        void setmidterm_exam (double mid)
        {
            midterm_exam = mid;
        }
        void setfinal_exam (double finale)
        {
            final_exam = finale;
        }

        void input()
        {
            cout << "Welcome to the Grading Program! Please enter the following information\n";

            cout << "Enter Quiz 1 and 2 results out of 10 points: ";
            cin >> quiz1 >> quiz2;

            cout << "Enter Mid-term result out of 100 points: ";
            cin >> midterm_exam;

            cout << "Enter Final exam result out of 100 points: ";
            cin >> final_exam;
        }

        void weightavg ()
        {
            weighted_avg = ((quiz1 + quiz2)/20 * 0.25 + midterm_exam / 100 * 0.25 + final_exam / 100 * 0.5) * 100;
        }

        void finalg ()
        {
            if (weighted_avg >= 90)
    {
        final_grade = 'A';
    }
    else if (weighted_avg >= 80)
    {
        final_grade = 'B';
    }
    else if (weighted_avg >= 70)
    {
        final_grade = 'C';
    }
    else if (weighted_avg >= 60)
    {
        final_grade = 'D';
    }
    else
    {
        final_grade = 'F';
    }
        }

        double getquiz1 ()
        {
            return (quiz1);
        }
        double getquiz2 ()
        {
            return (quiz2);
        }
        double getmidterm_exam ()
        {
            return (midterm_exam);
        }
        double getfinal_exam ()
        {
            return (final_exam);
        }
        double getweighted_avg ()
        {
            return (weighted_avg);
        }
        double getfinalg ()
        {
            return (final_grade);
        }

};

int main()
{
    student_records values, final_avg, grade, s;

    values.input();
    final_avg.weightavg();
    grade.finalg();

    cout << "The average is " << s.getweighted_avg() << " and your final grade is " << s.getfinalg();
    return 0;
}

输出为:

Welcome to the Grading Program! Please enter the following information
Enter Quiz 1 and 2 results out of 10 points: 10
10
Enter Mid-term result out of 100 points: 100
Enter Final exam result out of 100 points: 100
The average is 1.46101e-38 and your final grade is 0

student_records::input() 将输入的值分配给局部变量,而不是分配给 class 成员变量。因此,这些 class 成员变量在您想要使用它们时仍未初始化。

然后,在 main() 中,您使用了太多 student_records 的实例。你只需要一个!

student_records s;
s.input();
s.weightavg();
s.finalg();

所以我看到您正在使用 Getters 和 Setters。这是一个非常好的做法。 并回答你关于使用成员函数的问题,你已经正确使用了它们。

你也可以在class之外定义成员函数。

关于您的主要问题,在您的 input() 函数中,您没有调用 Setter 函数来设置 class 中的数据成员,因此它们没有任何价值。

您可以在从标准输入获取局部变量后调用setter。

而且您的局部变量信息似乎也未被使用,如果未被使用,请确保发表评论。

有2个问题:

  • 在 main() 中,您创建了 student_record 的 4 个实例,但您只需要其中一个(比方说)。删除其他的并将“values.input()”替换为“s.input()”等
  • 在input()中,你不是给对象的成员变量赋值,而是给函数结束时被遗忘的局部变量赋值

让我们看看您正在做什么,从 void input(); 中删除 student_records info;,您可以根据自己的意愿进行选择。如评论中所述,当您在 void input() 中声明 student_records info; 时,实例 info 将超出范围并在 input() return 之后被解构。 (还好没用)

使用 classes,成员函数和 friend 函数可以访问 class private: 变量。如果选择在input()中输入,则可以直接对private:变量quiz1, quiz2, midterm_exam, final_exam;进行操作,不需要任何局部变量。但是,您也可以选择读入局部变量,然后调用 setter 函数,例如void setquiz1 (double q1) 将测验 1 的局部变量作为参数传递(这只会增加可忽略不计的开销)。

现在让我们看看如何在 main() 中尝试使用 class 实例 s。你想输出结果:

    std::cout << "The average is " << s.getweighted_avg() << 
                " and your final grade is " << s.getfinalg() << '\n';

只需对您现有的 class 进行微小调整,即可 100% 可行。如果你选择那样做,你不是在使用你的吸气剂和 setters,而是你在做以下事情:

#include <iostream>

class student_records
{
    private:
        double quiz1, quiz2, midterm_exam, final_exam;
        float weighted_avg;
        char final_grade;

    public:
        void input()
        {
            std::cout << "Welcome to the Grading Program! "
                         "Please enter the following information\n";

            std::cout << "Enter Quiz 1 and 2 results out of 10 points: ";
            if (!(std::cin >> quiz1 >> quiz2)) {
                std::cerr << "error: numeric input.\n";
                return;
            }
            
            std::cout << "Enter Mid-term result out of 100 points: ";
            if (!(std::cin >> midterm_exam)) {
                std::cerr << "error: numeric input.\n";
                return;
            }

            std::cout << "Enter Final exam result out of 100 points: ";
            if (!(std::cin >> final_exam)) {
                std::cerr << "error: numeric input.\n";
                return;
            }
        }

        void weightavg ()
        {
            weighted_avg = ((quiz1 + quiz2)/20 * 0.25 + midterm_exam / 100 * 0.25 +
                            final_exam / 100 * 0.5) * 100;
        }

        void finalg ()
        {
            if (weighted_avg >= 90)
            {
                final_grade = 'A';
            }
            else if (weighted_avg >= 80)
            {
                final_grade = 'B';
            }
            else if (weighted_avg >= 70)
            {
                final_grade = 'C';
            }
            else if (weighted_avg >= 60)
            {
                final_grade = 'D';
            }
            else
            {
                final_grade = 'F';
            }
        }

        double getweighted_avg ()
        {
            weightavg();
            return (weighted_avg);
        }
        char getfinalg ()
        {
            finalg();
            return (final_grade);
        }

};

int main ()
{
    student_records s{};
    
    s.input();
    
    std::cout << "The average is " << s.getweighted_avg() << 
                " and your final grade is " << s.getfinalg() << '\n';
    return 0;
}

(注意: double getweighted_avg ()char getfinalg () 的补充,以确保计算 weighted_avg 和 return 类型getfinalg() 已更改为 char。)

另请注意: 每个输入的验证)

例子Use/Output

通过这些更改,您将获得:

$ ./bin/student_weighted_avg
Welcome to the Grading Program! Please enter the following information
Enter Quiz 1 and 2 results out of 10 points: 10 10
Enter Mid-term result out of 100 points: 100
Enter Final exam result out of 100 points: 100
The average is 100 and your final grade is A

现在在你的解释之后,我怀疑你应该做的是将你的界面(你如何与用户交谈并获得输入)与你的实现(你的 class 和你的计算)分离。这是面向对象编程的主要目标之一。不要混淆你的界面和实现(它不是花生酱杯)

从这个角度来看,您可以选择是将 input() 设为成员函数,还是使其完全独立并将对 class 实例的引用作为参数传递。将其保留为成员函数,然后您将执行:

        void input()
        {
            double q1, q2, mt, fe;
            
            std::cout << "Welcome to the Grading Program! "
                            "Please enter the following information\n";
        
            std::cout << "Enter Quiz 1 and 2 results out of 10 points: ";
            if (!(std::cin >> q1 >> q2)) {
                std::cerr << "error: numeric input.\n";
                return;
            }
            setquiz1 (q1);
            setquiz2 (q2);
            
            std::cout << "Enter Mid-term result out of 100 points: ";
            if (!(std::cin >> mt)) {
                std::cerr << "error: numeric input.\n";
                return;
            }
            setmidterm_exam(mt);
        
            std::cout << "Enter Final exam result out of 100 points: ";
            if (!(std::cin >> fe)) {
                std::cerr << "error: numeric input.\n";
                return;
            }
            setfinal_exam(fe);
            
            weightavg();
            finalg();
        }

您将删除对 getweighted_avg()getfinalg() 的添加,因此您的整个代码将作为:

#include <iostream>

class student_records
{
    private:
        double quiz1, quiz2, midterm_exam, final_exam;
        float weighted_avg;
        char final_grade;

    public:
        void setquiz1 (double q1)
        {
            quiz1 = q1;
        }
        void setquiz2 (double q2)
        {
            quiz2 = q2;
        }
        void setmidterm_exam (double mid)
        {
            midterm_exam = mid;
        }
        void setfinal_exam (double finale)
        {
            final_exam = finale;
        }

        void input()
        {
            double q1, q2, mt, fe;
            
            std::cout << "Welcome to the Grading Program! "
                            "Please enter the following information\n";
        
            std::cout << "Enter Quiz 1 and 2 results out of 10 points: ";
            if (!(std::cin >> q1 >> q2)) {
                std::cerr << "error: numeric input.\n";
                return;
            }
            setquiz1 (q1);
            setquiz2 (q2);
            
            std::cout << "Enter Mid-term result out of 100 points: ";
            if (!(std::cin >> mt)) {
                std::cerr << "error: numeric input.\n";
                return;
            }
            setmidterm_exam(mt);
        
            std::cout << "Enter Final exam result out of 100 points: ";
            if (!(std::cin >> fe)) {
                std::cerr << "error: numeric input.\n";
                return;
            }
            setfinal_exam(fe);
            
            weightavg();
            finalg();
        }
        
        void weightavg ()
        {
            weighted_avg = ((quiz1 + quiz2)/20 * 0.25 + midterm_exam / 100 * 0.25 +
                            final_exam / 100 * 0.5) * 100;
        }

        void finalg ()
        {
            if (weighted_avg >= 90)
            {
                final_grade = 'A';
            }
            else if (weighted_avg >= 80)
            {
                final_grade = 'B';
            }
            else if (weighted_avg >= 70)
            {
                final_grade = 'C';
            }
            else if (weighted_avg >= 60)
            {
                final_grade = 'D';
            }
            else
            {
                final_grade = 'F';
            }
        }

        double getquiz1 ()
        {
            return (quiz1);
        }
        double getquiz2 ()
        {
            return (quiz2);
        }
        double getmidterm_exam ()
        {
            return (midterm_exam);
        }
        double getfinal_exam ()
        {
            return (final_exam);
        }
        double getweighted_avg ()
        {
            return (weighted_avg);
        }
        char getfinalg ()
        {
            return (final_grade);
        }

};

int main ()
{
    student_records s{};
    
    s.input();
    
    std::cout << "The average is " << s.getweighted_avg() << 
                " and your final grade is " << s.getfinalg() << '\n';
    return 0;
}

(结果相同)

所以无论哪种方式都可以,我怀疑最后一种方式更接近您被要求做的事情。还可以考虑简单地删除 input() 作为成员函数并传递引用。那将完全分离接口和实现。查看所有内容,如果您还有其他问题,请告诉我。