2013-02-22 4 views
2

나는 과제를 가지고 다소 방해가된다. 다음 코드는 파일에서 입력을 가져 와서 내가 정의한 구조체로 읽어 들이고 입력 행의 수에 제한없이 사용하도록되어 있습니다. 그 시점에서 나는 정적 배열을 사용하여 동적 크기 변경을 원하고 있지만,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 } 

내가 전에 코드를 테스트 : 그러나, 라인 에서 세그먼테이션 폴트 (segfault). 그러나 gdb조차도 줄 번호 외에도 거의 도움이되지 않습니다. 각각 학생 구조체를 개별적으로 malloc해야합니까, 아니면 완전히 다른 것을 놓치고 있습니까? 그래서이 문제를 해결 한 것으로 보인다

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

:

편집 : 나는 통해 while 루프의 각 학생에 메모리를 할당 할 때 코드를 보인다 작동합니다. 확실히하기 위해 몇 가지 테스트를 해보겠습니다.

+0

이상한 링크 목록 \ 2D 배열처럼 보입니다. 어느 쪽을 원하니? – andre

+0

입력 줄의 형식을 설명해 주시겠습니까? ' "% d % [^,], % s % f"'왜'', ''로하고 있니? –

+1

andre, 그건 감시 였고, 사과드립니다. 나는 LL 접근법을 일찍 시도했지만 그것이 내가 필요로하는 것이 아니라는 것을 발견했다. @ AdriánLópez 입력 데이터의 형식은 , 입니다. 나는 단지 쉼표를 제거하기 위해 스캔 세트를 사용하고 있습니다. 그건 언급하지 않은 것에 대해 사과드립니다! – user991710

답변

0

온라인으로 19 학생은 N 개의 학생용 포인터에 충분한 공간을 할당하지만 학생을위한 공간을 할당하지 않으면 자신을 구성합니다. 당신은 같은 것을 할 필요가있을 것이다 : 당신의 malloc 문제 외에도

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

편집자가 자신의 질문에 답변 한 것처럼 보입니다. –

+0

나는 그랬지만 올바른 대답이기 때문에 대답을 받아 들일 것이다. 고맙습니다. – user991710

1

을, 당신은 당신의 lnamefname 필드의 크기는 33 문자의 배열을 고정하는 것을

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 

하나의 문제는 두 라인의 주요 문제가 즉, 입력 한 지점이 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