2014-09-25 47 views
0

免责声明:这是我的第一个问题在StackOverflow,我是一个新手程序员,所以我道歉,如果你是我的代码惊恐或如果我不适当地发布我的问题。(C)找不到原因核心转储错误与动态分配结构

无论如何,我正在研究一个具有动态分配结构的成绩簿。我将成绩簿分为三个结构,学生结构(学生姓名,学生ID),课程结构(课程名称,课程ID)和注册结构(学生ID,课程ID,等级)。

问题:我可以根据需要输入尽可能多的年级,而且没有第一个学生的错误。当我尝试输入第二个学生的成绩时,我的程序核心转储。我已经检查了所有变量,看看它们是否适当地传递给我的函数。以下是我的注册结构和我的添加成绩功能。

typedef struct { 
    int Student_ID; 
    int Course_ID; 
    int *Grade; 
    int GradeCount; 
} Enroll_Database; 

功能...

void addGrade(Enroll_Database *Enroll) 
{ 
    int i = 0, j = 0, b, Course_Num, Student_Num, Grade; 

    printf("Enter Course Number: "); 
    scanf("%d", &Course_Num); 
    printf("Enter Student ID: "); 
    scanf("%d", &Student_Num); 

    /* For loop that traverses through the Enroll array until until it encounters 
     nothing in the Course ID */ 
    for(i = 0; Enroll[i].Course_ID != 0; i++) 
    { 

      /* if the Student Number and the Course Number are equal to their 
        appropriate Enroll element, then ask user to input Grade */ 
      if(Enroll[i].Student_ID == Student_Num && Enroll[i].Course_ID == Course_Num) 
      { 
        printf("Enter Grade: "); 
        scanf("%d", &Grade); 

        if(Enroll[i].GradeCount == 0) 
        { 
          Enroll->Grade = (int *) malloc(sizeof(int)); 
          Enroll[i].Grade[Enroll[i].GradeCount] = Grade; //core dumps 
          Enroll[i].GradeCount++; 

        } 
        else 
        { 
          Enroll->Grade = (int *) realloc(Enroll->Grade, sizeof(int)); 
          Enroll[i].Grade[Enroll[i].GradeCount] = Grade; //core dumps 
          Enroll[i].GradeCount++; 
        } 

      } 
     } 
} 

我已经跑了多次检查和核心转储发生后,我的malloc/realloc的分配和用户输入的登记结构级别值。

我非常感谢任何帮助,如果我的代码不可读或格式错误,我会再次抱歉。 谢谢!

回答

1

这只为一个元素分配空间。并且还重新分配了错误的指针:

Enroll->Grade = (int *) realloc(Enroll->Grade, sizeof(int)); 

它可以被固定这样的:

Enroll[i].Grade = realloc(Enroll[i].Grade, sizeof(int) * (Enroll[i].GradeCount + 1)); 

记住,X->Y(*X).YX[0].Y都意味着同样的事情:你原来的版本实际上重新分配Enroll[0].Grade,而不是Enroll[i].Grade


(这个答案的其余部分是一些可能的作风的改进建议:)

为了避免这种错误,我个人刚过写scanf

Enroll_Database *found = &Enroll[i]; 

和然后使用found->到处,而不是Enroll[i].或者我会考虑有一个单独的函数来实际添加等级(一旦找到数据库条目就调用该等级)。

现在,如果您在设置数据库时将Enroll[i].Grade初始化为NULL,您实际上不需要此if...else语句。由于realloc(NULL, X)的行为与malloc(X)相同,因此相同的代码将处理这两种情况。

请注意,在C你should not cast the value returned by malloc和朋友。

要记住的另一件事是X = realloc(X, ...风格不允许您从分配失败中恢复。要编写健壮的代码,当malloc-系列函数返回NULL时,您需要采取一些合理的操作;这可以像打印消息一样简单并且呼叫exit

+1

我已经得到它的无缝工作。谢谢!我会考虑根据您的建议调整我的代码。 – stancharoen 2014-09-25 04:14:29