1

我想将字符串以及许多其他数据存储在二进制文件中,我使用下面的代码(当我真正使用它时,字符串将是 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); 
4

6 回答 6

7

我看到了几个问题,一些问题,一些风格。

  • 您应该真正测试 的返回值malloc,因为分配可能会失败,并且可能不会读取或写入任何数据freadfwrite
  • sizeof(char)始终为1,无需乘以它。
  • 字符数组"Hello\0"实际上是 7 个字节长。您不需要添加多余的空终止符。
  • 我更喜欢这个成语char x[] = "xxx";而不是指定一个确定的长度(当然,除非你想要一个比字符串长的数组)。
  • 当你时fread(&drumReadString ...,你实际上是在覆盖指针,而不是它指向的内存。这是你崩溃的原因。应该是fread(drumReadString ...
于 2010-03-10T08:54:08.053 回答
7

你在阅读时做错了。您已将 & 用于指针变量,这就是它给出分段错误的原因。

我删除了它工作正常并正确返回 Hello。

int count = fread(drumReadString, sizeof(char), stringLength, fp);
于 2010-03-10T08:55:38.867 回答
6

几个提示:

1

终止\0在任何双引号字符串中都是隐含的,并且通过在末尾添加一个附加值,您最终会得到两个。以下两个初始化是相同的:

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

所以

char drumReadString[] = "Hello";

就足够了,并且像这样初始化时指定数组的大小是可选的,编译器会计算出所需的大小(6字节)。

2

在编写字符串时,您不妨一次性编写所有字符(而不是逐个写入 sizeOfString 次字符):

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;
}
于 2010-03-10T09:09:44.667 回答
0

你不写终止 NUL,你不需要,但你必须考虑在阅读时添加它。即 malloc stringLength + 1 char,读取 stringLength 字符并\0在已读取内容的末尾添加 a。

现在是通常的警告:如果您以此处的方式编写二进制文件,则有许多未说明的假设使您的格式难以移植,有时甚至移植到同一编译器的另一个版本——我在编译器版本之间的结构更改。

于 2010-03-10T08:54:52.793 回答
0

更多内容要添加到 paxdiablo 和 AProgrammer - 如果您将来要使用 malloc,只需从一开始就这样做。这是更好的形式,意味着您在切换时不必调试。

此外,我还没有完全看到 unsigned short 的使用,如果您打算编写二进制文件,请考虑 unsigned char 类型通常是大小字节,因此非常方便。

于 2010-03-10T08:58:48.920 回答
0

您只需在 fread 函数中删除您的 &drumReadString。您只需在该函数中使用drumReadString,就像 ganesh 提到的那样。因为,drumReadString 是一个数组。数组类似于直接指向内存位置的指针。

于 2010-03-10T09:40:46.530 回答