2012-11-15 4 views
1

어떤 이유로 든 이전 데이터의 끝에 새 파일을 추가하여 데이터를 저장하기 위해 외부 파일 (.DAT)을 만들어야합니다.C 타입을 .DAT 파일에서 읽는 중 오류가 발생했습니다.

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

int main() { 
    typedef struct { 
     char *Name; 
     int Index; 
    } DataFile; 

    static FILE *file; 
    size_t result; 
    DataFile *DataTable; 

    file = fopen("database.DAT","ab"); 
    DataTable = (DataFile *) malloc (sizeof(DataFile)); 
    DataTable[0].Name = "somefile.txt"; 
    DataTable[0].Index = 7; 
    printf("%s %d \n",DataTable[0].Name,DataTable[0].Index); 
    result = fwrite(DataTable,sizeof(DataFile),1,file); 
    fclose(file); 
    free(DataTable); 
    return 0; 
} 

위의 코드를 실행 한 후에 데이터가 올바르게 저장되었는지 확인합니다. 그래서 아래 코드를 만듭니다.

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

int main() { 
    typedef struct { 
     char *Name; 
     int Index; 
    } DataFile; 

    static FILE *file; 
    size_t result; 
    long size; 
    int i; 
    DataFile *DataTable; 

    file = fopen("database.DAT","rb"); 
    if (file == NULL) printf("Error1"); 

    // Determine the size of file 
    fseek(file,0,SEEK_END); 
    size = ftell(file); 
    rewind(file); 

    DataTable = (DataFile *) malloc ((size/sizeof(DataFile)) * sizeof(DataFile)); 
    if (DataTable == NULL) printf("Error2"); 

    result = fread(DataTable,sizeof(DataFile),size/sizeof(DataFile),file); 
    fclose(file); 

    for (i=0; i<result; i++) { 
     printf("%s %d \n",DataTable[i].Name,DataTable[i].Index); 
    } 
    free(DataTable); 
    return 0; 
} 

그러나, 제 2 코드 블록으로부터의 출력을

somefile.txt 7 
첫 번째 코드 블록에서와

Error1 7 

을 준다. .DAT 파일을 열거 나 DataTable에 메모리를 할당 할 때 오류가 발생했기 때문에 문제가 아닌 것을 알았습니다. 또한 int 형식 (인덱스) 있지만 char * 형식 (이름) .DAT 파일에서 읽을 때 작동하지 않습니다. 이 char * -type 읽기 문제 (그리고 'error1'이 어디서 왔는지)를 해결하기 위해 무엇을해야하는지 잘 모른다. (심지어 구글도 나에게 답을 준다.)

+0

보통 'DataTable = (DataFile *) malloc (sizeof (DataFile));은'DataTable = malloc (sizeof * DataTable);으로 작성하는 것이 더 좋습니다. [C에서 malloc()의 리턴 값을 던지 지마.] (http://stackoverflow.com/a/605858/28169), 불필요하게 반복하지 마라. – unwind

답변

2

구조체 DataFile은 하나의 포인터와 하나의 정수를 저장합니다. 파일에 쓸 때 문자열에 대한 프로그램 특정 포인터와 정수를 씁니다.

읽을 때 포인터와 정수로 구조체를 다시 채우면 DataFile.Name은 아마 초기화되지 않은 메모리 세그먼트에 대한 포인터가됩니다. 그러나 처음으로 하드 코딩 된 문자열 ("filename.txt")을 가리키는 파일을 만들었으므로 일부 정의되지는 않았지만 이해할 수있는 동작이 발생하고이 경우 포인터는 두 번째 프로그램에 쓴 첫 번째 하드 코딩 된 문자열을 가리 킵니다. Error1)

정말로 원하는 것은 파일에 실제 문자열을 쓰는 것입니다.당신이 구멍 쓰기 구조를 유지하려면 원하는 경우

간단한 해결책은 것은

typedef struct { 
     char Name[512]; 
     int Index; 
    } DataFile; 

다음 포인터 대신 배열을 만들

strncpy(DataTable[0].Name, "somefile.txt", sizeof(DataTable[0].Name) - 1); // just to make sure you dont overflow your array size 
DataTable[0].Name[sizeof(DataTable[0].Name) - 1] = '\0'; 

및 사용하여 데이터를 초기화하는 것입니다 자신이했던 방식대로 데이터를 검토하십시오.

+0

고마워요 @ 톰, 귀하의 답변 마크를 누르십시오. 난 항상 포인터와 문자열 것들과 혼동 스러웠다. :) – user1825826

0

당신의 글쓰기 코드에서 당신은 char *Name에 대한 기억 장치를 할당하지 않았다. DataTable[0].Name = "somefile.txt" 명령어를 수행하면 Name이 가리키는 메모리에 실제로 "somefile.txt"이 복사되지 않고 실제로는 Name에 상수 문자열을 가리키는 값이 할당됩니다. (또한 문자열이 rvalue이므로 매달린 포인터가됩니다. 즉, doesn 경유되는 기억이있다). 파일을 읽는 코드도 마찬가지입니다. 에 당신이 필요합니다 :

  1. Name에 대한 스토리지를 할당합니다.
  2. memcpy 또는 이와 유사한 문자를 사용하여 할당 된 저장소에 문자열을 복사합니다.
1

char*은 포인터, 즉 문자열을 포함하는 문자 배열의 주소 일뿐입니다. 문자열 자체는 파일에 쓰지 않습니다. 파일을 읽은 후 동일한 문자열이 메모리에 같은 주소에 없으면 응용 프로그램이 실패합니다.

문자열 자체를 파일로 저장하는 방법을 찾아야합니다. 아마도 처음에는 길이를 쓰고 내용을 쓰는 것입니다. 읽을 때 길이 정보를 사용하여 메모리를 동적으로 할당 한 다음 해당 메모리를 읽을 수 있습니다.

관련 문제