我想将字符串存储在二进制文件中,以及许多其他数据,我使用下面的代码(当我真正使用它时,字符串将被malloc'd)我可以写入该文件。我在十六进制编辑器中看了它。我不确定我是否正确地写了空终结符(或者如果我需要)。当我读回来时,我获得了与我存储的相同的字符串长度,但不是字符串。我做错了什么?
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);
答案 0 :(得分:7)
阅读时你做错了。 你放了&对于指针变量,这就是它给出分段错误的原因。
我删除了它工作正常,它正确返回Hello。
int count = fread(drumReadString, sizeof(char), stringLength, fp);
答案 1 :(得分:6)
我看到了一些问题,有些问题,有些风格。
malloc
,fread
和fwrite
的返回值,因为分配可能会失败,并且不会读取或写入数据。sizeof(char)
总是 1,没有必要乘以它。"Hello\0"
实际上是7个字节长。您不需要添加多余的null终止符。char x[] = "xxx";
,而不是指定一个确定的长度(除非你想要一个比字符串更长的数组)。fread(&drumReadString ...
时,你实际上是在覆盖指针,而不是它指向的内存。这是导致崩溃的原因。它应该是fread(drumReadString ...
。答案 2 :(得分:5)
一些提示:
终止\0
隐含在任何双引号字符串中,并且通过在末尾添加额外的结果,您最终得到两个。以下两个初始化是相同的:
char str1[6] = "Hello\0";
char str2[6] = { 'H', 'e', 'l', 'l', 'o', '\0', '\0'};
所以
char drumReadString[] = "Hello";
就足够了,当像这样初始化时指定数组的大小是可选的,编译器会计算出所需的大小(6个字节)。
在编写字符串时,您也可以一次性写入所有字符(而不是逐个写入sizeOfString次):
fwrite(drumCString, sizeOfString, 1, fp);
尽管普通桌面PC场景不常见,但malloc可以返回NULL,并且您将从开发总是检查结果的习惯中受益,因为在嵌入式环境中,获取NULL不是不太可能的结果。
char *drumReadString = malloc(sizeof(char) * stringLength);
if (drumReadString == NULL) {
fprintf(stderr, "drumReadString allocation failed\n");
return;
}
答案 3 :(得分:0)
你没有写终止NUL,你不需要,但是你必须考虑在阅读时添加它。即malloc stringLength + 1 char,读取stringLength字符并在已读取的内容处添加\0
。
现在常见的警告:如果你按照你在这里的方式编写二进制文件,那么你有很多未说明的假设会使你的格式难以移植,有时甚至是同一编译器的另一个版本 - 我见过结构中的默认对齐在编译器版本之间发生变化。
答案 4 :(得分:0)
要添加到paxdiablo和AProgrammer还有更多内容 - 如果将来要使用malloc,只需从get get开始。它是更好的形式,意味着你不必在切换时进行调试。
此外,我还没有完全看到使用unsigned short,如果你打算编写一个二进制文件,请考虑unsigned char类型通常是大小字节,这使得它非常方便。
答案 5 :(得分:0)
你只需在fread函数中删除你的& drumReadString。你只需在该函数中使用drumReadString作为ganesh提到。因为,drumReadString是一个数组.Array类似于直接指向内存位置的指针。