简体   繁体   English

C ++:尝试打印const char *数组时程序崩溃

[英]C++: Program crashes when trying to print const char* array

I have a program that has a user enter their name, age, and the classes that they have taken. 我有一个程序,可以让用户输入他们的姓名,年龄和所参加的课程。 These classes are stored in the main() function as two-dimensional array of chars and then they are passed to a function within a Student class that copies this array into a public member const char* array called m_CourseNames. 这些类作为chars的二维数组存储在main()函数中,然后将它们传递到Student类中的一个函数,该类将该数组复制到名为m_CourseNames的公共成员const char *数组中。 I have verified with a debugger in CLion that this process completes successfully. 我已经在CLion中使用调试器验证了此过程已成功完成。

However, I get exit code 11 and the program crashes whenever I try to iterate through the m_CourseNames array and print it contents to the screen. 但是,当我尝试遍历m_CourseNames数组并将其内容打印到屏幕时,我得到exit code 11 ,并且程序崩溃。

I have tried printing the array to the screen the following ways: 我尝试通过以下方式将阵列打印到屏幕上:

  1. In the main function: 在主要功能中:

     for (int count = 0 ; count < 9 ; count++) cout << student.m_CourseNames[count] << " "; 
  2. In a member function of the student class by calling via student.getCourses(); 在学生类的成员函数中,通过student.getCourses();进行调用student.getCourses(); :

     for (int count = 0 ; count < 9 ; count++) cout << m_CourseNames[count] << " "; 
  3. Inside an overloaded operator function with the same method as in 1) (see code to understand why I tried it here) 在与1中相同的方法的重载运算符函数内部(请参阅代码以了解我为什么在此处尝试)

All three ways of trying to print the const char* array to the screen have resulted in the following error code before the program is finished: 试图将const char *数组打印到屏幕上的所有三种方法在程序完成之前都导致了以下错误代码:

If the array is a public member variable, I do not know why it will not iterate. 如果数组是一个公共成员变量,我不知道为什么它不会迭代。 The debugger verified that all the classes are properly being stored in it, so it is not the responsibility of the addCourses() function. 调试器验证了所有类都已正确存储在其中,因此这不是addCourses()函数的责任。

See entire program below (everything that is commented out is an attempt at achieving printing the array to the screen): 请参阅下面的整个程序(注释掉的所有内容都是试图将阵列打印到屏幕上的尝试):

--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;
}

You are iterating into entries in the array that you have not populated. 您正在迭代尚未填充的数组中的条目。 You want something like: 您想要类似的东西:

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

Also, as Arun pointed out, you are accessing the array out of bounds. 而且,正如Arun指出的那样,您正在访问数组。 You can't access the eleventh element of a ten entry array, and entry 10 is the eleventh element (since 0 is the first). 您无法访问十个条目数组的第11个元素,而第10个条目是第11个元素(因为第一个是0)。

Your code is really bad though for a lot of reasons. 您的代码确实很糟糕,尽管有很多原因。 The main issue is that your Person class stashes pointers to memory it doesn't own, which makes the class very hard to use. 主要问题是您的Person类隐藏了它不拥有的内存的指针 ,这使该类很难使用。 Why not use std::string ? 为什么不使用std::string呢?

In Student::Student(const char* m_CourseNames[]) , you are overstepping the array m_CourseNames[10] = {0}; //Index is in [0..9] range Student::Student(const char* m_CourseNames[]) ,您将超越数组m_CourseNames[10] = {0}; //Index is in [0..9] range m_CourseNames[10] = {0}; //Index is in [0..9] range

Moreover where do you allocate space for array of const char * m_CourseNames pointers? 此外,您在哪里为const char * m_CourseNames指针数组分配空间?

Please consider using std::array and std::string instead of C-type array and pointers. 请考虑使用std::arraystd::string而不是C类型的数组和指针。

student.m_CourseNames is an array of pointers to char. student.m_CourseNames是一个指向char的指针数组。 This means you get a bunch of pointers. 这意味着您将获得一堆指针。 You do not get any storage to point at, so if the pointer is not pointed at some valid storage the program is going to run off into the weeds. 您没有指向任何存储空间,因此,如果指针未指向某个有效存储空间,则程序将运行到杂草中。 Out there who knows what'll happen. 谁知道会发生什么。 Maybe find lost pirate treasure. 也许找到丢失的海盗宝藏。 Maybe get eaten by dragons. 也许被龙吃掉了。 Probably crash the program. 可能会使程序崩溃。

student.m_CourseNames is set by student.addCourse(input[count], count); student.m_CourseNamesstudent.addCourse(input[count], count); which provides a pointer (which will be overwritten by the next student, so this is a bad idea) and the index at which m_CourseNames will be updated. 它提供了一个指针(下一个学生将覆盖它,所以这是个坏主意)以及将更新m_CourseNames的索引。 This is also a bad, but not fatal, idea. 这也是一个坏主意,但不是致命的主意。 One of the purposes of classes is they control their own data, so Student should be maintaining that index. 类的目的之一是它们控制自己的数据,因此Student应该维护该索引。

So say we add three courses: A, B and C. for (int count = 0 ; count < 9 ; count++) is going to try to print 9 (indexes 0 through 8) so that means there are at least six shots off into undefined behaviour to crash the program with. 假设我们添加了三个路线:A,B和C。for for (int count = 0 ; count < 9 ; count++)将尝试打印9(索引0到8),这意味着至少要拍摄六张照片导致程序崩溃的不确定行为。

Solutions: 解决方案:

Don't use char arrays. 不要使用char数组。 Use std::string. 使用std :: string。

If you have to use char arrays, provide storage and copy the source into the storage. 如果必须使用char数组,请提供存储并将源复制到存储中。 That way you know it's safe and not going to be overwritten unless you want to or do something dumb. 这样,您就知道它是安全的,除非您想要或做一些愚蠢的事情,否则不会被覆盖。

Don't use arrays of pointers. 不要使用指针数组。 Use std::vector (and to real data, not to pointers to data). 使用std :: vector(以及实际数据,而不是数据指针)。 Vector resizes as you add more and always know how many items it contains. 向量随着您添加的增加而调整大小,并且始终知道其包含多少项。 If you can't use vectors, stick to using arrays, but not arrays of pointers. 如果不能使用向量,请坚持使用数组,而不要使用指针数组。 Use arrays of std::string if possible. 如果可能,使用std :: string数组。

Keep track of the number of items stored in your lists so you don't go marching out of bounds. 跟踪存储在列表中的项目数,以免行进中。 Vector does this for you. Vector为您做到了。

Encapsulate your class data. 封装您的类数据。 Student should know and manage all things Student. 学生应了解并管理学生的所有事情。 No one should be telling Student where to put it's courses, just that it has courses. 没有人会告诉学生将其放在哪里,只说它有课程。 When you want to print student's data, ask Student to print it for you. 当您要打印学生的数据时,请学生为您打印。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM