2015-01-31 5 views
2

공백으로 구분 된 단어 (문자열)가 포함 된 텍스트 파일이 있습니다. 문자열의 크기는 제한되지 않으며 단어의 개수도 아닙니다. 내가해야 할 일은 파일의 모든 단어를 목록에 넣는 것입니다. (목록이 잘 작동한다고 가정하십시오). 무제한 단어 크기 문제를 극복하는 방법을 알아낼 수 없습니다. 나는 이것을 시도 :무제한 단어 크기로 공백으로 구분 된 텍스트 파일을 읽는 중

FILE* f1; 
f1 = fopen("file1.txt", "rt"); 
int a = 1; 

char c = fgetc(f1); 
while (c != ' '){ 
    c = fgetc(f1); 
    a = a + 1; 
} 
char * word = " "; 
fgets(word, a, f1); 
printf("%s", word); 
fclose(f1); 
getchar(); 

내 텍스트 파일은 다음과 같습니다

내가 얻을 수 있었던 모든이 첫 번째 단어는 것을
this is sparta 

공지, 심지어 내가 얻을 때문에 내가 잘못 할 그 오류 :

Access violation writing location 0x00B36860. 

나를 도와 줄 수있는 사람이 있습니까?

+2

'남자 realloc'. –

+0

당신이 알지 못했을 때 (윌리엄의 코멘트에 다소 쌓여있다) 당신은 또한 non-constable 포인터에 잘못 변경되지 않는 메모리 영역의 주소를 잘못 할당 한 다음 그것을 보내어'fgets '전화. – WhozCraig

+0

이 할당의 열쇠는 "unbounded"입니다. C 언어에서는 물건을 저장하기 위해 메모리를 할당해야합니다.그러나 크기를 모르는 경우 어떻게 메모리를 할당하여 메모리를 확보 할 수 있습니까? 위안이라면 C 프로그래머들의 세대가 잘못되어 크래커 나 대본 제작자가 쉽게 사용할 수 있습니다. 배열의 일부 크기를 할당하고 (malloc) 얼마나 꽉 찼는지 추적하고 크기가 가득 차면 크기를 두 배로 재 할당 (realloc)하십시오. 작동시키면서 두 배가 확장 계획이 너무 공격적인지 여부에 대해 생각해보십시오. –

답변

3

위의 주석 작성자로부터 제안을 받으면 충분하지 않거나 충분할 때마다 메모리를 다시 할당합니다.

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

void fatal(char *msg) { 
    printf("%s\n", msg); 
    exit (1); 
    } 

int main() { 
    FILE* f1 = NULL; 
    char *word = NULL; 
    size_t size = 2; 
    long fpos = 0; 
    char format [32]; 

    if ((f1 = fopen("file1.txt", "rt")) == NULL)  // open file 
     fatal("Failed to open file"); 
    if ((word = malloc(size)) == NULL)     // word memory 
     fatal("Failed to allocate memory"); 
    sprintf (format, "%%%us", (unsigned)size-1);  // format for fscanf 

    while(fscanf(f1, format, word) == 1) { 
     while (strlen(word) >= size-1) {    // is buffer full? 
      size *= 2;         // double buff size 
      printf ("** doubling to %u **\n", (unsigned)size); 
      if ((word = realloc(word, size)) == NULL) 
       fatal("Failed to reallocate memory"); 
      sprintf (format, "%%%us", (unsigned)size-1);// new format spec 
      fseek(f1, fpos, SEEK_SET);     // re-read the line 
      if (fscanf(f1, format, word) == 0) 
       fatal("Failed to re-read file"); 
     } 
     printf ("%s\n", word); 
     fpos = ftell(f1);        // mark file pos 
    } 

    free(word); 
    fclose(f1); 
    return(0); 
} 

프로그램 입력

this is sparta 
help 30000000000000000000000000000000000000000 
me 

프로그램 출력 :

** doubling to 4 ** 
** doubling to 8 ** 
this 
is 
sparta 
help 
** doubling to 16 ** 
** doubling to 32 ** 
** doubling to 64 ** 
30000000000000000000000000000000000000000 
me 
1

어떤 플랫폼을 사용하고 있습니까? 당신이 POSIX 틱 플랫폼을 사용하는 경우

는 다음 코드를 재사용하지 만들 정말 판단되는 경우 (무제한의 크기의 라인, 다음 strcspn() 중 하나 strpbrk(), strtok_r(), 또는를 읽을 getline() 사용을 고려) strtok() 단어의 경계를 얻고, 마지막으로 strdup()을 사용하여 단어 사본을 만듭니다. strdup()에 의해 반환 된 포인터는 realloc()을 통해 관리되는 char *의 배열에 저장됩니다.

POSIX-ish 플랫폼이 충분하지 않은 경우 fgets()을 사용하여 실제로 전체 라인을 읽었는지 확인해야합니다. realloc()을 사용하면 초기 라인이 아닌 경우 더 많은 공간을 할당 할 수 있습니다 충분히 길다. 일단 라인이 생기면 이전과 같이 분할 할 수 있습니다.

단 하나의 구분 기호 만 사용한다는 점을 제외하면 POSIX getdelim()을 사용하면 엉망이 될 수 있습니다. 또한 처리 할 수없는 단어와 끝 부분을 표시하기 위해 공백과 줄 바꿈이 필요할 수 있습니다.

, 당신은 충분히 현대 POSIX 시스템에있어 다시, 당신은 scanf()m 수정 사용을 고려할 수 있습니다

char *word = 0; 

while (scanf("%ms", &word) == 1) 
    …store word in your list… 

이 그것을 사용할 수있는 경우에도 간단하다.

관련 문제