2014-09-25 28 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