如何在文件中编写完整的结构?

时间:2013-03-20 11:34:58

标签: c

在我的程序中,我从键盘接收输入。我将该输入放在struct中,其中包含两个char字段和一个int字段。如何仅使用函数写入整个struct

想要分别写入struct的每个成员。

2 个答案:

答案 0 :(得分:4)

C没有"指令"。

您应该能够使用单个函数调用,例如:

fwrite(&mystructure, sizeof mystructure, 1, myfile);

但这并非没有缺点:

  1. 这使得文件格式取决于您当前的CPU和编译器,这通常是一个坏主意;这将使保持互操作性变得非常困难。
  2. 写作可能部分成功;你需要将它包装在一个循环中。

答案 1 :(得分:1)

这取决于您struct的定义方式,是否希望您的输出是人类可读的,以及输出文件是否要在不同的架构上读取。

其他人提供的fwrite解决方案会将结构的二进制表示写入输出文件。例如,给出以下代码:

#include <stdio.h>

int main(void)
{
  struct foo {
    int x;
    char name1[10];
    char name2[10];
  } items[] = {{1,"one","ONE"}, {2,"two","TWO"}};

  FILE *output = fopen("binio.dat", "w");

  fwrite( items, sizeof items, 1, output );

  fclose( output );
  return 0;
}

如果我向控制台显示binio.dat的内容,我会得到以下内容:

john@marvin:~/Development/Prototypes/C/binio$ cat binio.dat
oneONEtwoTWOjohn@marvin:~/Development/Prototypes/C/binio$ 

john@marvin:~/Development/Prototypes/C/binio$ od -c binio.dat
0000000 001  \0  \0  \0   o   n   e  \0  \0  \0  \0  \0  \0  \0   O   N
0000020   E  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
0000040  \0  \0  \0  \0 002  \0  \0  \0   t   w   o  \0  \0  \0  \0  \0
0000060  \0  \0   T   W   O  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
0000100  \0  \0  \0  \0  \0  \0  \0  \0
0000110

整数值显示为垃圾(以上未再现),因为它们已被存储为字节序列01,00,00,00和02,00,00,00(x86是little-endian),它们是不可打印的字符。另请注意,name1的所有10个字符和name2的所有20个字符都会写入文件,这可能是您想要的,也可能不是。

如果你的struct包含指针,情况会变得更加复杂,因为存储到文件中的是指针值,而不是指向的东西:

#include <stdio.h>

int main(void)
{
  struct foo {
    int x;
    char *name1;
    char *name2;
  } items[] = {{1,"one","ONE"}, {2,"two","TWO"}};

  FILE *output = fopen("binio.dat", "w");

  fwrite( items, sizeof items, 1, output );

  fclose( output );
  return 0;
}

这次我

john@marvin:~/Development/Prototypes/C/binio$ cat binio.dat
��������john@marvin:~/Development/Prototypes/C/binio$ 

john@marvin:~/Development/Prototypes/C/binio$ od -c binio.dat
0000000 001  \0  \0  \0 260 205 004  \b 264 205 004  \b 002  \0  \0  \0
0000020 270 205 004  \b 274 205 004  \b
0000030

请注意,文件中根本没有出现任何字符串;如果您使用其他程序读取此文件,它将看到(很可能)无效地址。

如果您希望输出是人类可读的,您希望能够在不同的架构上读取这些值,那么您几乎必须使用格式化输出,这意味着您必须编写每个成员分开:

#include <stdio.h>

int main(void)
{
  struct foo {
    int x;
    char *name1;
    char *name2;
  } items[] = {{1,"one","ONE"}, {2,"two","TWO"}};

  FILE *output = fopen("binio.dat", "w");
  int i;
  for (i = 0; i < sizeof items / sizeof items[0]; i++)
  {
    fprintf(output, "%d %s %s\n", items[i].x, items[i].name1, items[i].name2);
  }
  fclose( output );
  return 0;
}
john@marvin:~/Development/Prototypes/C/binio$ cat binio.dat
1 one ONE
2 two TWO

你当然可以将这个操作包装在你自己的函数中,比如

int printFoo( FILE *output, const struct foo item )
{
  return fprintf( output, "%d %s %s\n", item.x, item.name1, item.name2);
}

但最终,这就像它变得一样简单。

如果您不关心可读性和可移植性,fwrite解决方案很有用,但如果您在结构中有任何指针成员,则仍需要小心。