【问题标题】:Why is fwrite writing each character so many times?为什么 fwrite 会多次写入每个字符?
【发布时间】:2019-09-05 23:36:53
【问题描述】:

我正在尝试编写一个程序来解压缩已经使用运行长度编码压缩的文件。由于某种原因,每个字符都会多次打印到文件中。例如,如果输入文件包含1l1i1n...,我的输出文件将显示llllllllll...

我尝试将 reps 变量从 for 循环打印到终端,以确保将其设置为正确的重复次数,甚至尝试使用 fprintf 但得到相同的结果。我不确定它是什么,但这里肯定有我不理解的东西?

顺便说一下,压缩文件也是从主函数以二进制模式打开的。

  int uncompress_file(FILE *fd_compressed, const char *fname_out)
  {
          FILE *fd_out;
          if (fd_compressed == NULL) {
                  fprintf(stderr, ...);
                  return -1;
          }
          if ((fd_out = fopen(fname_out, "wb")) == NULL) {
                  fprintf(stderr, ...);
                  return -1;
          }
          unsigned char cur, reps;
          int i = 0;

          while (fread(&cur, sizeof(unsigned char), 1, fd_compressed) > 0) {
                  if (i % 2 == 0) {
                          reps = cur;
                  }
                  else {
                          for (int j = 0; j < reps; j++)
                                  fwrite(&cur, sizeof(unsigned char), 1, fd_out);
                  }
                  i++;
          }
          fclose(fd_out);
          return 0;
  }

【问题讨论】:

  • 输入文件是否包含"1l1i1n"?如,字符'1'(即字节0x31)?因为'1'1 不一样。

标签: c file io


【解决方案1】:

问题是您的线路reps = cur。如果您的文件是1l1i1n,那么当我们第一次进入循环时,reps 将被分配值1。但这是 ASCII 1,而不是实际数字 1。ASCII 中的 1 映射到十进制 49,因此您将得到 49 l。要将字符从 ASCII 数字转换为正确的 int 值,您可以从中减去 48,即 reps = cur - 48

请注意,这与您的代码一起,仅在可能的最大数字为 9(无两位数)时才有效

【讨论】:

  • 啊,对 C 来说还是新手,所以在写它的时候就让我头晕目眩。这虽然解决了这个问题。谢谢
  • 在计数和实际字符之间使用分隔符是否是使这项工作适用于超过 9 个连续字符的最佳方法?当然我也会编辑压缩函数。
  • 这是一个选项。或者,将限制增加到 255 的简单改进不是使用 ASCII 作为数字,而是使用原始字节,因此 1 将是空字节 (0x00),2 将是 0x01,3 将是 0x02,等等。这样你就可以保持交替每个字节的简单性。尽管它确实有一个缺点,即您的压缩文件将不再易于在文本编辑器中读取。
猜你喜欢
  • 1970-01-01
  • 2016-01-29
  • 1970-01-01
  • 2018-04-18
  • 2012-03-17
  • 1970-01-01
  • 1970-01-01
  • 2023-01-10
  • 1970-01-01
相关资源
最近更新 更多