我有一个程序让用户输入他们的名字,年龄和他们所学的课程。这些类作为二维chars数组存储在main()函数中,然后传递给Student类中的一个函数,该函数将该数组复制到名为m_CourseNames的公共成员const char *数组中。我已经使用CLion中的调试器验证了此过程是否成功完成。
但是,当我尝试遍历m_CourseNames数组并将其内容打印到屏幕时,我得到exit code 11
并且程序崩溃。
我尝试过以下方式将数组打印到屏幕上:
在主要功能中:
for (int count = 0 ; count < 9 ; count++)
cout << student.m_CourseNames[count] << " ";
通过student.getCourses();
致电学生班的成员函数:
for (int count = 0 ; count < 9 ; count++)
cout << m_CourseNames[count] << " ";
在重载的操作符函数中使用与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;
}
答案 0 :(得分:3)
您正在迭代未填充的数组中的条目。你想要这样的东西:
void Student::getCourses()
{
cout << ", Courses: ";
for (int count = 0 ; count < index ; count++)
cout << m_CourseNames[count] << " ";
}
此外,正如Arun指出的那样,您正在访问数组越界。您不能访问十个条目数组的第十一个元素,条目10是第十一个元素(因为0是第一个)。
由于很多原因,你的代码非常糟糕。主要问题是你的Person
类将指针存储到它不拥有的内存中,这使得该类很难使用。为什么不使用std::string
?
答案 1 :(得分:1)
在Student::Student(const char* m_CourseNames[])
中,您超越了数组m_CourseNames[10] = {0}; //Index is in [0..9] range
此外,您在哪里为const char *
m_CourseNames
指针数组分配空间?
请考虑使用std::array
和std::string
而不是C型数组和指针。
答案 2 :(得分: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数组。使用std :: string。
如果必须使用char数组,请提供存储并将源复制到存储中。这样你知道它是安全的,除非你想要或做一些愚蠢的事情,否则不会被覆盖。
不要使用指针数组。使用std :: vector(和实际数据,而不是指向数据的指针)。矢量会在您添加更多内容时调整大小,并始终知道它包含的项目数量。如果你不能使用向量,那么坚持使用数组,而不是使用指针数组。如果可能,请使用std :: string数组。
跟踪列表中存储的项目数量,这样您就不会走出界限。 Vector为你做到这一点。
封装您的班级数据。学生应该了解和管理所有学生。没有人应该告诉学生在哪里上课,只是它有课程。如果要打印学生的数据,请让学生为您打印。