我一直致力于这项任务,我需要读取“记录”并将其写入文件,然后能够在以后阅读/查找它们。在程序的每次运行中,用户可以决定编写新记录,或者读取旧记录(通过名称或#)
该文件是二进制文件,这是它的定义:
typedef struct{
char * name;
char * address;
short addressLength, nameLength;
int phoneNumber;
}employeeRecord;
employeeRecord record;
程序的工作方式,它将存储结构,然后是名称,然后是地址。名称和地址是动态分配的,这就是为什么必须首先读取结构以查找名称和地址的大小,为它们分配内存,然后将它们读入内存。
出于调试目的,我目前有两个程序。我有我的文件编写程序和文件读取。
我的实际问题是这样,当我读到我写的文件时,我在结构中读到,打印出手机#以确保它有效(哪种方法正常),然后记下名字(现在能够使用record.nameLength报告正确的值)。 但是,Fread不返回可用的名称,它返回空白。
我看到两个问题,要么我没有正确地将文件写入文件,要么我没有正确读取它。 这是我如何写入文件:其中fp是文件指针。 record.name是一个正确的值,因此是record.nameLength。我也写了包括空终止符的名字。 (例如'Jack \ 0')
fwrite(&record,sizeof record,1,fp);
fwrite(record.name,sizeof(char),record.nameLength,fp);
fwrite(record.address,sizeof(char),record.addressLength,fp);
然后我关闭文件。 这是我如何阅读文件:
fp = fopen("employeeRecord","r");
fread(&record,sizeof record,1,fp);
printf("Number: %d\n",record.phoneNumber);
char *nameString = malloc(sizeof(char)*record.nameLength);
printf("\nName Length: %d",record.nameLength);
fread(nameString,sizeof(char),record.nameLength,fp);
printf("\nName: %s",nameString);
注意那里有一些调试内容(名称长度和数字,两者都是正确的)。所以我知道文件打开正常,我可以使用名称长度罚款。为什么我的输出是空白的,换行符,或类似的东西? (输出只是名称:后面没有任何内容,程序完成就好了)
感谢您的帮助。
答案 0 :(得分:1)
我尝试了你的代码并且运行正常。按顺序,这里是输出,文件的hexdump,以及编译的源代码。
更新:更新了代码以从stdin或命令行参数中读取名称和地址。
prompt$ g++ -g -Wall -o test_records test_records.cpp
prompt$ echo -e "Test User\nSomeplace, Somewhere" | ./test_records
sizeof(employeeRecord) = 24
Number: 5551212
Name Length: 9
Name: Test User
prompt$ hexdump -C employeeRecord
00000000 90 f7 bf 5f ff 7f 00 00 70 f7 bf 5f ff 7f 00 00 |..._....p.._....|
00000010 14 00 09 00 6c b4 54 00 54 65 73 74 20 55 73 65 |....l.T.Test Use|
00000020 72 53 6f 6d 65 70 6c 61 63 65 2c 20 53 6f 6d 65 |rSomeplace, Some|
00000030 77 68 65 72 65 |where|
00000035
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct{
char * name;
char * address;
short addressLength, nameLength;
int phoneNumber;
}employeeRecord;
int main(int argc, char *argv[])
{
employeeRecord record;
#if 0
// Commmand line arguments
if (argc < 3)
return 1;
record.nameLength = strlen(argv[1]);
record.name = (char *)malloc(sizeof(char)*(record.nameLength + 1));
strncpy(record.name, argv[1], record.nameLength + 1);
record.addressLength = strlen(argv[2]);
record.address = (char *)malloc(sizeof(char)*(record.addressLength + 1));
strncpy(record.address, argv[2], record.addressLength + 1);
#else
// stdin
char input[1024];
fgets(input, sizeof(input), stdin);
record.nameLength = strlen(input);
record.name = (char *)malloc(sizeof(char)*(record.nameLength + 1));
strncpy(record.name, input, record.nameLength + 1);
fgets(input, sizeof(input), stdin);
record.addressLength = strlen(input);
record.address = (char *)malloc(sizeof(char)*(record.addressLength + 1));
strncpy(record.address, input, record.addressLength + 1);
#endif
record.phoneNumber = 5551212;
FILE *fp = NULL;
printf("sizeof(employeeRecord) = %lu\n", sizeof(employeeRecord));
// Write
fp = fopen("employeeRecord","w");
fwrite(&record,sizeof(employeeRecord),1,fp);
// Note: we're not including terminating NULLs.
fwrite(record.name,sizeof(char),record.nameLength,fp);
fwrite(record.address,sizeof(char),record.addressLength,fp);
fclose(fp);
// Read
fp = fopen("employeeRecord","r");
fread(&record,sizeof(employeeRecord),1,fp);
printf("Number: %d\n",record.phoneNumber);
char *nameString = (char *)malloc(sizeof(char)*(record.nameLength + 1));
printf("\nName Length: %d",record.nameLength);
fread(nameString,sizeof(char),record.nameLength,fp);
nameString[record.nameLength] = '\0';
printf("\nName: %s",nameString);
printf("\n");
fclose(fp);
return 0;
}
答案 1 :(得分:0)
我想添加我的输入....因为你将内存结构转储到磁盘,用于保存数据的指针地址在转储之前肯定是有效的,但是当从它们读取时,指针地址可能无效....这可以解释为什么字符指针没有显示名称......
答案 2 :(得分:0)
首先,一个挑剔:你永远不需要sizeof(char) - 根据定义它总是1。
至于空白名称输出:你可能需要在%s之后换行才能刷新输出吗?当你把它留下来时,我已经看到了奇怪的行为,而你没有说明你正在使用哪个平台。如果平台的printf()被奇怪地实现,你可以打印和刷新格式字符串,但是当程序退出时,名称本身会卡在C库的缓冲区中。
我从不高兴阅读或编写二进制数据blob,如文件中的结构。意识到通过这样做,你承诺你的程序只会读取它在同一平台上写的 。您无法在64位主机上写入文件,并在16位微波炉控制器上读回文件。