2013-02-22 29 views
2

我有一個任務,並遇到了一些障礙。下面的代碼應該從文件中獲取輸入,並將其讀入我已定義的結構中,並且不會限制輸入行的數量。然而,出現segfaults在線路:使用fscanf將數據輸入到動態結構指針數組中?

1 #include <stdio.h> 
2 #include <stdlib.h> 
3 #include <string.h> 
4 
5 typedef struct __student { 
6   int ID; 
7   char fname[33]; 
8   char lname[33]; 
9   float grade; 
10 } student; 
11 
12 void partA(FILE *fp) { 
13 
14   int i, r; 
15   i = r = 0; 
16   int N = 1000; 
17   student **S; 
18 
19   S = (student **)malloc(sizeof(student *) * N); 
20 
21 
22   while(!feof(fp)){ 
23     fscanf(fp, "%d %[^,], %s %f", &S[i]->ID, S[i]->lname, S[i]->fname, &S[i]->grade); // segfault occurs on this line 
24     printf("%d %s %s %f\n", S[i]->ID, S[i]->fname, S[i]->lname, S[i]->grade); 
25     i++; 
26     printf("Something's happening, at least"); 
27     if(i == N){ 
28       N *= 2; 
29       S = (student **)realloc(S, sizeof(student) * N); 
30       if(S == NULL) { 
31         printf("Memory reallocation failed; Fatal error."); 
32         break; 
33       } 
34     } 
35   } 
36 } 

我測試之前的代碼,雖然在這一點上我使用靜態數組和想改變爲動態大小。但是,除了行號之外,即使gdb也只提供很少的幫助。我是否需要單獨malloc每個學生結構,還是我錯過了一些完全不同的東西?

S[i] = (student *)malloc(sizeof(student)); 

所以這似乎已經解決了這一問題:

編輯:當我在while循環通過分配內存給每個學生看來代碼工作。我會運行一些測試來確保。

+0

這看起來像一個奇怪的鏈接列表\二維數組。你要哪個? – andre 2013-02-22 20:22:23

+0

你能解釋輸入行的格式嗎? '「%d%[^,],%s%f」'你爲什麼用''''做這個? – 2013-02-22 20:24:24

+1

安德烈,那是一個疏忽,我很抱歉。我早些時候嘗試了LL方法,但發現它不是我所需要的。 @AdriánLópez輸入數據的格式爲。我只是使用掃描集來擺脫逗號。我很抱歉沒有提及! – user991710 2013-02-22 20:26:17

回答

0

在第19行中,您爲N個學生指針分配了足夠的空間,但沒有爲學生自己的結構分配空間。你需要做的是這樣的:

for(int i = 0; i < N; i++) { 
    S[i] = malloc(sizeof(struct __student)); 
} 
+0

哦哎呀看起來像你回答自己的問題與編輯。 – 2013-02-22 20:30:35

+0

我做過了,但我會以任何方式接受答案,因爲它是正確的答案。謝謝。 – user991710 2013-02-22 20:32:44

1

除了你的malloc問題,你有兩行

while(!feof(fp)){ 
    fscanf(fp, "%d %[^,], %s %f", &S[i]->ID, S[i]->lname, S[i]->fname, &S[i]->grade); // segfault occurs on this line 

的一個問題是,你的lnamefname字段都是固定的大小33字符數組的重大問題,這意味着如果你的輸入在這一點上有超過32個字符,你會跑掉數組的末尾並破壞東西。另一個問題是,您不檢查fscanf的返回值以查看是否有問題(例如EOF),從而導致您在到達文件結尾時嘗試打印垃圾記錄。你想要的東西是這樣的:

while (fscanf(fp, "%d %32[^,],%32s%f", &S[i]->ID, S[i]->lname, S[i]->fname, &S[i]->grade) == 4) { 

爲您的循環控制。

編輯

while(!feof(fp))(以及爲什麼它幾乎總是一個錯誤)問題後,你一直在努力,讀到文件的結尾是feof(fp)只返回true。讀完最後一行後,feof(fp)仍然返回false,因此您再次進入循環並嘗試讀取另一行。該讀取失敗,但由於您沒有檢查fscanf的返回值,所以您沒有意識到它,而是在數組中獲得垃圾額外值。

+0

謝謝你的回答。我不檢查輸入大小的原因是因爲,正如我所說,這是一個分配和輸入大小保證是一致的。當然,我會檢查其他情況。 感謝您提及返回值,但我確實應該習慣於儘可能地使用它來檢測錯誤。有一件事:while(!feof(fp))和while(fscanf(...)== 4)之間的區別是什麼?由於我從一致的輸入中讀取,不能匹配項目將基本上等同於EOF,不是嗎?謝謝。 – user991710 2013-02-23 05:02:46