-1

我有一个程序,让用户输入他们的姓名、年龄和他们上过的课程。这些类作为二维字符数组存储在 main() 函数中,然后将它们传递给 Student 类中的函数,该函数将该数组复制到名为 m_CourseNames 的公共成员 const char* 数组中。我已使用 CLion 中的调试器验证此过程已成功完成。

但是,exit code 11每当我尝试遍历 m_CourseNames 数组并将其内容打印到屏幕上时,程序就会崩溃。

我尝试通过以下方式将数组打印到屏幕上:

  1. 在主函数中:

    for (int count = 0 ; count < 9 ; count++)
        cout << student.m_CourseNames[count] << " ";
    
  2. 通过调用 via 在学生类的成员函数中student.getCourses();

    for (int count = 0 ; count < 9 ; count++)
        cout << m_CourseNames[count] << " ";
    
  3. 在一个重载的运算符函数中,使用与 1) 中相同的方法(请参阅代码以了解我为什么在这里尝试它)

在程序完成之前,尝试将 const char* 数组打印到屏幕的所有三种方式都导致以下错误代码:

如果数组是公共成员变量,不知道为什么不会迭代。调试器验证所有类都正确存储在其中,因此它不是 addCourses() 函数的责任。

请参阅下面的整个程序(注释掉的所有内容都是尝试将数组打印到屏幕上):

--main.cpp--

#include <iostream>
#include "Student.h"

using namespace std;

int main()
{
    char input[10][128] = {(0),(0)};
    char name[128] = {0}, student_check = ' ';
    int age = 0, count = 0;

    cout << "\nPlease state your name and age:\n\n";
    cout << "Name: ";
    cin.getline(name, 128);
    cout << "Age: ";
    cin >> age;

    cin.clear();
    cin.ignore();

    cout << "\n\nThanks!\n\nAre you a student? (Y/N): ";
    cin.get(student_check);

    switch (student_check)
    {
        case 'y':
        case 'Y':
        {
            Student student;
            student.setName(name);
            student.setAge(age);
            char course_check = ' ';
            cout << "\n\nWhat course(s) are you taking?"
            << " (Enter the course prefix and number without any spaces): \n\n";


            while (tolower(course_check) != 'n') {
                cin.clear();
                cin.ignore();

                cout << "Course #" << count + 1 << ": ";
                cin.getline(input[count], 128);
                student.addCourse(input[count], count);


                if (student.addCourse(input[count], count))
                {
                    cin.clear();

                    cout << "Do you want to enter another course? (Y/N): ";
                    cin.get(course_check);

                    count++;
                }
                else
                {
                    cout << "You have exceeded the number of courses you are allowed to enter" << endl << endl;
                    course_check = 'n';
            }
            cout << student;
            student.getCourses();
            //for (int count = 0 ; count < 9 ; count++)
              //  cout << student.m_CourseNames[count] << " ";
        }


        }
        default:
            break;

    }
}

--Student.h---

#ifndef PA2_STUDENT_H
#define PA2_STUDENT_H
#include "Person.h"
#include <ostream>

class Student : public Person
{
    public:
        Student();
        Student(const char* []);
        bool addCourse(const char*, int);
        void getCourses();
        friend std::ostream& operator <<(std::ostream& os, const Student& student);
       const char* m_CourseNames[10];
};

#endif

--student.cpp--
#include "Student.h"
#include <iostream>

using namespace std;

Student::Student() {}

Student::Student(const char* m_CourseNames[])
{
    m_CourseNames[10] = {0};
}

bool Student::addCourse(const char* course, int index)
{
    if (index < 9)
    {
        m_CourseNames[index] = course;
        return true;
    }
    if (index >= 9)
        return false;
}

void Student::getCourses()
{
    cout << ", Courses: ";
    for (int count = 0 ; count < 9 ; count++)
        cout << m_CourseNames[count] << " ";
}

std::ostream &operator<<(std::ostream& os, const Student& student) {
    os << "Name: " << student.m_Name << ", Age: " << student.m_Age;// << ",     Courses: " << Student::m_CourseNames;

//cout << ", Courses: ";
   // for (int count = 0 ; count < 9 ; count++)
       // cout << m_CourseNames[count] << " ";
return os;
}
4

3 回答 3

3

您正在迭代数组中尚未填充的条目。你想要这样的东西:

void Student::getCourses()
{
    cout << ", Courses: ";
    for (int count = 0 ; count < index ; count++)
        cout << m_CourseNames[count] << " ";
}

此外,正如 Arun 指出的那样,您正在越界访问数组。您无法访问十条目数组的第十一个元素,条目 10 是第十一个元素(因为 0 是第一个元素)。

尽管有很多原因,您的代码确实很糟糕。主要问题是您的Person类隐藏了指向它不拥有的内存的指针,这使得该类非常难以使用。为什么不使用std::string

于 2015-09-04T01:20:57.750 回答
1

Student::Student(const char* m_CourseNames[])中,您超出了数组m_CourseNames[10] = {0}; //Index is in [0..9] range

此外,您在哪里为const char * m_CourseNames指针数组分配空间?

请考虑使用std::arrayandstd::string代替 C 类型的数组和指针。

于 2015-09-04T01:13:36.960 回答
1

student.m_CourseNames是一个指向 char 的指针数组。这意味着你会得到一堆指针。你没有任何存储指向,所以如果指针没有指向某个有效的存储,程序就会跑到杂草中去。谁知道会发生什么。也许找到丢失的海盗宝藏。可能会被龙吃掉。可能会导致程序崩溃。

student.m_CourseNames由它设置,student.addCourse(input[count], count);它提供了一个指针(它将被下一个学生覆盖,所以这是一个坏主意)和 m_CourseNames 将被更新的索引。这也是一个坏的,但不是致命的想法。类的目的之一是它们控制自己的数据,因此学生应该维护该索引。

假设我们添加了三个课程:A、B 和 C。for (int count = 0 ; count < 9 ; count++)将尝试打印 9(索引 0 到 8),这意味着至少有六次未定义的行为导致程序崩溃。

解决方案:

不要使用 char 数组。使用标准::字符串。

如果必须使用 char 数组,请提供存储并将源复制到存储中。这样你就知道它是安全的并且不会被覆盖,除非你想要或做一些愚蠢的事情。

不要使用指针数组。使用 std::vector (和真实数据,而不是指向数据的指针)。矢量会随着您添加更多而调整大小,并且始终知道它包含多少项目。如果您不能使用向量,请坚持使用数组,而不是指针数组。如果可能,使用 std::string 数组。

跟踪存储在您的列表中的项目数量,这样您就不会越界。Vector 会为您做到这一点。

封装你的类数据。学生应该知道和管理学生的所有事情。没有人应该告诉学生把它的课程放在哪里,只是它有课程。当您要打印学生的数据时,请让学生为您打印。

于 2015-09-04T01:36:36.513 回答