问题描述
因此,我正在创建一个程序,该程序实现代表学校及其学生和课程的几个班级。当我尝试在studentCoursePairs []数组中打印出所有Taken对象时出现分段错误,该数组代表接受特定课程的Student对象。我认为我的细分错误来自School.cc中的addTaken()函数,该函数的工作是查找具有给定学生编号和课程ID的学生对象和课程对象,然后使用找到的学生和课程创建一个新的Taken对象对象以及等级。然后,我尝试将这个新对象添加到Taken集合的后面,该集合是StudentCoursePairs。
当我注释出studentCoursePairs [i]-> print()时,分割错误消失了。我不确定自己做错了什么,将不胜感激。
我不确定是否需要School.cc以外的其他课程,但无论如何我还是将它们包括在内以帮助理解。
School.cc:
#include <iostream>
#include <iomanip>
using namespace std;
#include <string.h>
#include "School.h"
School::School(string s1) : name(s1){
numTaken = 0;
}
void School::addTaken(string number,int code,string grade){
Student* s = nullptr;
Course* c = nullptr;
for(int i = 0; i < numTaken; ++i){
if((studentsCollection->find(number,&s)) && (coursesCollection->find(code,&c))){
Taken* taken = new Taken(s,c,grade);
studentCoursePairs[i] = taken;
++numTaken;
}
}
}
void School::printTaken(){
cout << name << " === TAKEN: "<< endl;
for(int i = 0; i < sizeof(studentCoursePairs)/sizeof(studentCoursePairs[0]); ++i){
studentCoursePairs[i]->print(); //seg fault
}
}
其他文件:
StudentCollection.cc
bool StudentCollection::find(string num,Student** s){
for(int i = 0; i < size; ++i){
if(students[i]->getNumber() == num){ //find student number
*s = students[i];
}
}
}
CoursesCollection.cc
bool CoursesCollection::find(int id,Course** c){
for(int i = 0; i < numCourses; ++i){
if(courses[i]->getId() == id){ //find course id
*c = courses[i];
}
}
}
我还有一个Student类和Course类,它们仅声明和初始化信息,例如学生的姓名,课程,gpa以及课程代码,讲师,姓名,课程年份。
解决方法
您的School对象存在两个主要问题。让我们从您在问题中发布的内容开始:
void School::printTaken(){
cout << name << " === TAKEN: "<< endl;
for(int i = 0; i < sizeof(studentCoursePairs)/sizeof(studentCoursePairs[0]); ++i){
studentCoursePairs[i]->print(); //seg fault
}
}
此for循环将始终准确运行MAX_PAIRS次,因为此变量的定义为
Taken* studentCoursePairs[MAX_PAIRS];
所以sizeof(studentCoursePairs) === MAX_PAIRS * sizeof(studentCoursePairs[0])
。
相反,您只想在实际上包含有效指针的前几个插槽中循环。为此,您有一个变量:numTaken
。因此,将条件更改为i < numTaken
,您的打印循环将起作用。
第二个主要问题是在addTaken
中:
void School::addTaken(string number,int code,string grade){
Student* s = nullptr;
Course* c = nullptr;
for(int i = 0; i < numTaken; ++i){
if((studentsCollection->find(number,&s)) && (coursesCollection->find(code,&c))){
Taken* taken = new Taken(s,c,grade);
studentCoursePairs[i] = taken;
++numTaken;
}
}
}
让我们玩电脑,弄清楚如果传入的数字和代码有效,会发生什么情况
- 如果numTaken为0,则循环立即停止(因为
0 < 0
为false),并且numTaken不递增。您可以随意拨打addTaken
,它永远不会改变numTaken
- 假设您已解决问题,让我们假设numTaken =5。在第一次迭代中,您检查条件并同意这是有效的数字代码组合。因此,您将创建一个新的Taken对象,并用新对象覆盖
studentCoursePairs[0]
。在第二次迭代中,您执行相同操作,并用等效对象覆盖studentCoursePairs[1]
。
这可能不是预期的行为。
相反,您可能想在studentCoursePairs[numTaken]
中放置一个新对象并碰撞numTaken
:
void School::addTaken(string number,string grade){
Student* s = nullptr;
Course* c = nullptr;
if((studentsCollection->find(number,grade);
studentCoursePairs[numTaken] = taken;
++numTaken;
}
}
练习如何解决传递的组合无效或超过MAX_PAIRS个组合的情况。
编辑:CoursesCollection中存在第三个主要问题:在将一个对象new Course()
视为数组时,您为其分配了空间,并将结果存储在局部变量而不是成员中。您的构造函数应该看起来像:
CoursesCollection::CoursesCollection(){
courses = new Course*[MAX_COURSES];
numCourses = 0;
}
或使用成员初始化程序列表:
CoursesCollection::CoursesCollection()
: courses(new Course*[MAX_COURSES]),numCourses(0) {}