fread/fwrite string in C

3

我有一个包含记录的二进制文件。该文件的结构如下:

结构(见下文) 名称字符串 地址字符串

所讨论的结构:

typedef struct{
    char * name;
    char * address;
    short addressLength, nameLength;
    int phoneNumber;
}employeeRecord;
employeeRecord record;

我这样获取名称:

char name[50];
printf("\nName:");
fgets(name,50,stdin);
record.nameLength = strlen(name)-1;
record.name = malloc(sizeof(char)*record.nameLength);
strcpy(record.name,name);

我写出结构、名称,然后是地址(如上所述)。
fwrite(&record.name,sizeof(char),record.nameLength,fp);

其中fp是文件指针。

现在我关闭了文件。 然而,如果我想要从文件中读取数据,我相信我需要先读入结构体,读取nameLength变量,为名称分配足够的内存,然后将名称读入变量中。

如下所示:

char *nameString = malloc(sizeof(char)*record.nameLength);
fread(nameString,sizeof(char),record.nameLength,fp);
printf("\nName: %s",nameString);

然而,当我尝试这样做时,我没有得到有效的数据。 例如:
Input name is: Joseph (6 characters)
Output data: 
Name length is 6 (correct), 
Name is  �A        � (aka garbage)

很明显我做错了什么。有人可以给我一些帮助吗?


1
这并不能解决任何问题,但是你可以使用strdup来代替strlen + malloc + strcpy - zneak
这是一份家庭作业吗? - John Zwinck
添加了作业标签,忘记了这一点。 - Blackbinary
2个回答

2
我看到写操作存在两个问题,你将record.nameLength设置得太小了,并且你向fwrite传递了错误的指针来处理名称。实际上,record.name已经是一个指针。

请更改以下内容:

record.nameLength = strlen(name)-1;
...
fwrite(&record.name,sizeof(char),record.nameLength,fp);

转换为这样

record.nameLength = strlen(name);
...
fwrite(record.name,sizeof(char),record.nameLength,fp);

你读取文件时也会遇到问题,因为你没有将字符串中的终止符\0写入文件。当你读取文件时,你需要显式地添加该终止符。
char *nameString = malloc(sizeof(char)* (record.nameLength + 1));
fread(nameString,sizeof(char),record.nameLength,fp);
nameString[record.NameLength] = '\0';

为什么我需要空终止符?我知道我将要读取的大小,所以我是不是只想把它截断呢? - Blackbinary
如果我以“M”为例使用record.nameLength = strlen(name),返回的长度不是1而是2。 - Blackbinary
strlen函数在计算字符串长度时不包括空字符(除非你自己编写了strlen函数)。例如,strlen("M")将返回1而不是2。 - John Knoeller
C语言中的字符串以空字符('\0')结尾,这样与字符串相关的函数(包括printf)就知道字符串何时结束了。因为C语言中的字符串不像Pascal语言中的字符串一样保留内部字符串长度,所以字符串会一直“延伸”,直到找到一个'\0'字符来终止它。这是新手C程序员常见的问题来源。 - mctylr

1
问题在于您将指向char*的指针传递给了fwrite函数:
fwrite(&record.name,sizeof(char),record.nameLength,fp);

这意味着你写的不是变量名,而是变量的内存地址。Fwrite 函数期望传入一个指向要写入数据的指针——在你的情况下,应该传入指向 char 数据的指针,而不是指向 char 数据指针的指针。

传递 record.name 而不是 &record.name,就可以解决问题了:

fwrite(record.name, sizeof(char), record.nameLength, fp);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接