微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C ++-按统计分配的数组打印对象会导致分段错误

如何解决C ++-按统计分配的数组打印对象会导致分段错误

因此,我正在创建一个程序,该程序实现代表学校及其学生和课程的几个班级。当我尝试在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) {}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。