문제

나는 이진 파일에 문자열을 저장하고 다른 많은 데이터와 함께 아래 코드를 사용하고 싶습니다 (실제에 사용하면 문자열이 malloc'd). 파일에 쓸 수 있습니다. Ive는 16 진 편집자에서 그것을 보았습니다. 나는 널 터미네이터를 올바르게 작성하는 메신저 (또는 필요한 경우) 다시 읽을 때 나는 내가 저장된 것과 동일한 문자열 길이를 얻지 만 문자열은 아닙니다. 내가 뭘 잘못하고 있죠?

FILE *fp = fopen("mybinfile.ttt", "wb");

char drumCString[6] = "Hello\0";
printf("%s\n", drumCString);    
//the string length + 1 for the null terminator
unsigned short sizeOfString = strlen(drumCString) + 1;
fwrite(&sizeOfString, sizeof(unsigned short), 1, fp);

//write the string
fwrite(drumCString, sizeof(char), sizeOfString, fp);

fclose(fp);

fp = fopen("mybinfile.ttt", "rb");  

unsigned short stringLength = 0;
fread(&stringLength, sizeof(unsigned short), 1, fp);

char *drumReadString = malloc(sizeof(char) * stringLength);
int count = fread(&drumReadString, sizeof(char), stringLength, fp);

//CRASH POINT
printf("%s\n", drumReadString);

fclose(fp); 
도움이 되었습니까?

해결책

당신은 읽는 동안 잘못하고 있습니다. 포인터 변수에 대해서는 세분화 오류를 제공하는 이유입니다.

잘 작동하는 것을 제거하고 Hello가 올바르게 돌아옵니다.

int count = fread(drumReadString, sizeof(char), stringLength, fp);

다른 팁

나는 몇 가지 문제, 문제가 있고 스타일이 있습니다.

  • 실제로 반환 값을 테스트해야합니다 malloc, fread 그리고 fwrite 할당이 실패 할 수 있고 데이터를 읽거나 기록 할 수 없기 때문입니다.
  • sizeof(char) ~이다 언제나 1, 그것에 곱할 필요가 없습니다.
  • 캐릭터 배열 "Hello\0" 실제로 7 바이트 길이입니다. 불필요한 널 터미네이터를 추가 할 필요가 없습니다.
  • 나는 관용구를 선호합니다 char x[] = "xxx"; 확실한 길이를 지정하는 대신 (물론 문자열보다 더 긴 배열을 원하지 않는 한).
  • 때를 fread(&drumReadString ..., 당신은 실제로 그것을 덮어 쓰고 있습니다 바늘, 그것이 가리키는 기억이 아닙니다. 이것이 당신의 충돌의 원인입니다. 그것은해야한다 fread(drumReadString ....

몇 가지 팁 :

1

종료 \0 이중 인용 문자열에 암시 적이며 마지막에 추가를 추가하면 두 가지가됩니다. 다음 두 가지 초기화는 동일합니다.

char str1[6] = "Hello\0";
char str2[6] = { 'H', 'e', 'l', 'l', 'o', '\0', '\0'};

그래서

char drumReadString[] = "Hello";

충분하고, 배열의 크기를 지정하는 것은 다음과 같이 초기화 될 때 선택 사항입니다. 컴파일러는 필요한 크기 (6 바이트)를 파악합니다.

2

문자열을 쓸 때, 당신은 한 번에 모든 캐릭터를 한 번에 쓰는 것만으로도 (하나의 문자 sizeofstring time을 작성하는 대신) :

fwrite(drumCString, sizeOfString, 1, fp);

3

일반적인 데스크탑 PC 시나리오에서는 일반적이지 않더라도 Malloc은 Null을 반환 할 수 있으며, 내장 환경에서는 Null을 얻는 것이 결과가 좋지 않기 때문에 항상 결과를 확인하는 데 대한 혜택을 얻는 이점을 얻을 수 있습니다.

char *drumReadString = malloc(sizeof(char) * stringLength);
if (drumReadString == NULL) {
        fprintf(stderr, "drumReadString allocation failed\n");
        return;
}

당신은 종료 NUL을 쓰지 않고, 당신은 필요하지 않지만 읽을 때 그것을 추가 할 생각이 필요합니다. 즉, malloc stringlength + 1 char, stringlength chars를 읽고 추가 \0 읽은 것의 끝에.

이제 일반적인 경고 : 이진 파일을 여기에서 수행하는 방식으로 작성하는 경우, 형식을 포트하기가 어렵고 때로는 동일한 컴파일러의 다른 버전으로도 포트가 어려워지는 많은 정보가없는 가정이 많이 있습니다. 기본 정렬을 보았습니다. 컴파일러 버전 간의 구조 변경.

Paxdiablo와 Aprogrammer에 추가해야 할 일부 - 미래에 Malloc을 사용하려는 경우, 그냥 갈 때부터하십시오. 더 나은 형태이며 전환 할 때 디버깅 할 필요가 없음을 의미합니다.

또한 서명되지 않은 단편의 사용을 완전히보고 있지 않습니다. 이진 파일을 작성하려는 경우 서명되지 않은 Char 유형의 크기가 크기 때문에 그 목적에 매우 편리합니다.

Fread 함수에서 & drumreadstring을 제거합니다. Ganesh가 언급 한 것처럼 해당 기능에서 Drumreadstring을 사용합니다. Drumreadstring은 배열이므로 메모리 위치를 직접 가리키는 포인터와 유사합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top