-2

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

不想单独写给每个成员struct

4

2 回答 2

4

C没有“指令”。

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

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

但这并非没有缺点:

  1. 这使得文件格式取决于您当前的 CPU 和编译器,这通常是个坏主意;这将使保持互操作性变得非常困难。
  2. 写入可能部分成功;对于这种情况,您需要将其包装在一个循环中。
于 2013-03-20T11:38:55.357 回答
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 一 \0 \0 \0 \0 \0 \0 \0 开
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 二\0 \0 \0 \0 \0
0000060 \0 \0 二 \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),它们不是可打印字符. 另请注意,所有 10 个字符name1和所有 20 个字符name2都写入文件,这可能是您想要的,也可能不是。

如果您的结构包含指针,情况会变得更加复杂,因为存储到文件中的是指针值,而不是指向的内容:

#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
一一一
2 二 二

您当然可以将该操作包装在您自己的函数中,例如

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

但最后,这很简单。

如果您不关心可读性和可移植性,该fwrite解决方案效果很好,但如果结构中有任何指针成员,您仍然必须小心。

于 2013-03-20T12:23:24.550 回答