2013-11-27 3 views
0

정보가 줄로 정렬 된 파일이 주어지면 각 줄을 문자열에 저장하는 프로그램을 작성해야합니다. 다음과 같이파일에서 배열로 행 복사 (C)

This is the first line. 
This is the second line. 
This is the third line. 
This is the fourth line. 

내 코드는 다음과 같습니다

#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 
#define MAX 70 
#define NLine 4 
int main() 
{ 
    FILE *arq; 
    char line[MAX]; 
    char *eof; 
    char name[20]; 
    char *nline[NLine]; 
    int i; 
    printf("\nGive me the name of the file: "); 
    fgets(name, 20 , stdin); 
    arq = fopen(name, "r"); 
    while((eof = fgets(line, MAX, arq))!= NULL) 
     { 
      nline[i] = strdup(eof); 
      i++; 
     } 
    printf("\n"); 
    for(i = 0; i < NLine; i++) 
     printf("%s", nline[i]); 
    for(i = 0; i < NLine; i++) 
     free(nline[i]); 
    fclose(arq); 
    return 0; 
} 

내 출력이 세분화 잘못이다; 그러나 arq = fopen(name, "r");arq = fopen("test.txt", "r");으로 대체하면 프로그램이 완벽하게 실행됩니다. 나는 gdb 실행하고 그것이 잘못된 매개 변수로 문자열 배열로 fopen를 호출하는 것입니다

Program received signal SIGSEGV, Segmentation fault. 
0x00007ffff7a7ea2b in fgets() from /lib64/libc.so.6 

를 반환했습니다, 아니면 프로그램의 잘못을 했습니까?

또한 나는 어떻게 일부를

while((eof = fgets(line, MAX, arq))!= NULL) 
     { 
      nline[i] = strdup(eof); 
      i++; 
     } 

작품을 알고 싶습니다. 방금 question 코드를보고 작동하도록 관리했습니다. 그러나 그 함수가 같은 라인을 읽지 않고 다른 라인을 읽는 방법을 이해하지 못했습니다. 왜냐하면 eof이 파일에서 읽혀지는 방법에 명백한 변화가 없기 때문입니다.

답변

1

nline 배열에서 포인터를 초기화하지 않았습니다. 각각을 NULL로 설정해야합니다. 그렇지 않으면 나중에 와서 해방하면 정의되지 않은 동작이 발생합니다.

for(i = 0; i < NLine; i++) nline[i] = NULL; 

또는, 당신은 당신이 만 무료로 읽어 줄 수를 저장할 수 많은 값 대신에 그들 모두 NLine. 값을 인쇄 할 때도 똑같이해야하므로 아마이 작업을 수행해야합니다. 당신은 카운트를 원할 것입니다. 여기에 line_count을 사용했습니다. . 사용자 에 의해 지적,

line_count = 0; 
while(line_count < NLine && fgets(line, MAX, arq)) 
    nline[i++] = strdup(line); 

그리고 또 다른 것은 :

for(i = 0; i < line_count; i++) free(nline[i]); 

당신이 라인을 읽을 때 당신은 잠재적 인 버퍼 오버 플로우가 당신은 당신의 배열 인덱스가 범위에 남아 있는지 확인해야합니다 Myforwik, fgets 문자열에 개행 문자를 남겨두고, 파일 이름에 읽을 때 당신은 스스로를 제거해야합니다

if(fgets(name, 20 , stdin)) { 
    /* Remove line terminator(s) if any: iscntrl() from ctype.h is okay */ 
    for(i = strlen(name)-1; i >= 0 && iscntrl(p[i]); i--) p[i] = '\0'; 
} else { 
    name[0] = '\0'; 
} 
1

fgets에는 이름에 캐러지 리턴이 포함되므로 이름 끝에 캐리지 리턴이있는 파일을 열려고하면 실패합니다. 프로그램이 파일을 성공적으로 열 었는지 확인하지 않으므로 다음 fgets는 정의되지 않은 동작입니다.

시작하려면 fopen을 시도한 후에 if (!arq) { printf("could not open file"); return; }을 추가해야합니다.

다른 부분은 간단합니다. fgets의 출력에 eof를 할당 한 다음 eof와 null을 비교합니다.

다른 많은 문제가 있습니다. char * eof; 문자열에 대한 공간을 할당하지 않습니다. 포인터 만 할당합니다. 당신은 아마도 비슷한 것을 원할 것입니다. char *eof; eof = malloc(1024); 라인 배열에이 문제가 있습니다. 각 줄에 메모리를 할당해야합니다. 문자열을 포인트로 복사 할 수는 없습니다. 포인트는 먼저 메모리를 가리켜 야합니다.

+0

* "char * eof;는 문자열을위한 공간을 할당하지 않습니다"* - 이전에'strdup'를 사용한 적이 있습니까? – paddy

+0

@Myforwik, 방금'if (! arq) {printf ("파일을 열 수 없습니다"); 반환; }'파일을 열려고 시도한 후, 이제는 출력물이 항상 '파일을 열 수 없습니다'라는 오류 메시지가 표시됩니다. 또한,'malloc (20 * sizeof (char)) '로 각'nline [i]를 시작하고 @paddy가 제안한대로'nline [i]'를'NULL'로 초기화했습니다. –

+0

나는 그것을 제안하지 않았다. – paddy

관련 문제