0

我一直在做这个作业,我需要读入“记录”并将它们写入文件,然后才能稍后读取/查找它们。在程序的每次运行中,用户可以决定写入一条新记录,或者读取一条旧记录(通过名称或#)

该文件是二进制文件,这是它的定义:

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

程序的工作方式,它将存储结构,然后是名称,然后是地址。名称和地址是动态分配的,这就是为什么需要先读取结构以找到名称和地址的大小,为它们分配内存,然后将它们读入该内存的原因。

出于调试目的,我目前有两个程序。我有我的文件写入程序和文件读取。

我的实际问题是,当我读取我编写的文件时,我读取了结构,打印出电话 # 以确保它工作正常(工作正常),然后读取名称(现在可以使用 record. nameLength 也报告了正确的值)。然而,Fread 不返回可用的名称,它返回空白。

我看到两个问题,要么我没有将名称正确写入文件,要么我没有正确读取它。这是我写入文件的方式:其中 fp 是文件指针。record.name 是一个合适的值,record.nameLength 也是如此。我也在写包含空终止符的名称。(例如“杰克\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);

请注意,那里有一些调试内容(名称长度和编号,两者都是正确的)。所以我知道文件正确打开,我可以很好地使用名称长度。那为什么我的输出是空白的,或者换行符,或者类似的东西?(输出只是名称:后面什么都没有,程序完成就好了)

谢谢您的帮助。

4

3 回答 3

1

我试过你的代码,效果很好。按顺序,这里是输出,文件的十六进制转储,以及您的编译源。

更新:更新代码以从标准输入或命令行参数中读取名称和地址。

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;
}
于 2010-03-08T18:19:54.877 回答
0

我想添加我的输入....因为您要将内存结构转储到磁盘,用于保存数据的指针地址在转储之前肯定是有效的,但是从它们读取时,指针地址可能是无效的....这可以解释为什么字符指针不显示名称...

于 2010-03-08T18:09:03.790 回答
0

首先,挑剔:你永远不需要 sizeof (char) - 根据定义,它总是 1。

至于空白名称输出:您是否可能需要在 %s 之后换行来刷新输出?当您将其忽略时,我看到了奇怪的行为,并且您没有说明您正在使用哪个平台。如果平台的 printf() 实现得足够奇怪,您可以打印并刷新格式字符串,但是当您的程序退出时,名称本身会卡在 C 库的缓冲区中。

而且我从不喜欢从文件中读取或写入像结构这样的二进制数据块。意识到这样做是在向您的程序保证它只会读取它在同一平台上编写的内容。你不能在 64 位主机上写入文件,然后在 16 位微波炉控制器上读回文件。

于 2010-03-08T22:43:05.763 回答