未检测到 EOF

Not detecting EOF

我希望这不是一个问题。我检测 EOF 的条件似乎不起作用。代码继续通过 EOF 并在语句中处理。当我重新创建文本时,它看起来很合适,但是整个带有垃圾代码的 bmp 也打印出来告诉我文本标志的结尾从未被编码。我在下一个 else 条件中放置了一个 printf 语句,但它从未输入要打印的语句。我看不出问题是什么,如果它就在我面前,或者更不祥的东西。一如既往的感谢!

/*******************************************************************************
 * This code is to take a text document and using steganography techniques, hide
 * the text within a bmp. It will take each character of the text, parse it into
 * four 2 bit pieces and inject those bits into the two least significant bits
 * of each pixel color (BGR) byte as well as the line padding.
 ******************************************************************************/
#include <stdio.h>

/*******************************************************************************
 * getIntFromArray (borrowed from class notes). Takes unsigned character array
 * and assembles/returns an int value using bit shifting with OR.
 ******************************************************************************/
int getIntFromArray(unsigned char bytes[])
{
  int n =
          bytes[0] |
          bytes[1] << 8 |
          bytes[2] << 16 |
          bytes[3] << 24;
  return n;
}

/*******************************************************************************
 * bitWise. Take unsigned char pointer and character, parses the character
 * using bitwise manipulation and injects 2 bits into the 2 least significant
 * bits of each pixel color byte as well as padding.
 ******************************************************************************/
void bitWise(unsigned char* bytes, char character)
{
  int i;
  char tmpChar;
  for(i = 0; i < 4; ++i)
  {
    tmpChar = character;
    tmpChar &= 3;
    bytes[i] &= 252;
    bytes[i] |= tmpChar;
    character = character >> 2;
  }
}

int flag = 0;

int main(int argc, char **argv)
{
  char *infilename = argv[1];
  char *outfilename = argv[2];

  unsigned char header[54];

  FILE *in = fopen(infilename, "rb");/*Command line input.*/
  FILE *out = fopen(outfilename, "wb");/*Command line input.*/

  int pixelWidth;
  int pixelHeight;
  int i;
  int j;

  fread(header, 1, 54, in);/* read header into array */

  pixelWidth = getIntFromArray(&header[18]);
  pixelHeight = getIntFromArray(&header[22]);

  fwrite(header, 1, sizeof(header), out);/* write header to output file */

  for(i = 0; i < pixelHeight; ++i)/*Loop to read pixel data from bmp.*/
  {
    for(j = 0; j < pixelWidth; ++j)
    {
      unsigned char bytes[4];
      unsigned char character = 0;

      fread(&bytes, 1, 4, in);/*Reads sequentially pixel and padding bytes.*/
      if(flag == 0)/*Breakout flag, initially set to 0.*/
      {
        character = getchar();/*Takes in characters from stdin.*/
        if(character != EOF)/*Breakout if EOF.*/
        {
          bitWise(bytes, character);
        }
        else
        {
          bitWise(bytes, 0);/*Sets end of hidden text with 4 bytes LSB to 0.*/
          flag = 1;
        }
      }
      fwrite(&bytes, 1, 4, out);
    }
  }
  fclose(in);
  fclose(out);
  return 0;
}

您正在将 signed int 分配给 unsigned int。结果将不是您期望的那样。它将是一个所有位都设置为 1 的值。 (EOF 的值为 -1,因此它已签名)。

长话短说应该是 int。简单的 int character 就可以达到目的。

还有一件事getchar() returns intint getchar(void);

还有一些事情要做:-

  • fread return 应检查值。

    size_t fread(void * restrict ptr,size_t size, size_t nmemb,FILE * restrict stream);

The fread function returns the number of elements successfully read, which may be less than nmemb if a read error or end-of-file is encountered. If size or nmemb is zero, fread returns zero and the contents of the array and the state of the stream remain unchanged

  • 另一件事是检查 fopen() 的 return 值。如果失败,return 值将是 NULL.

这里有两个严重但 常见的 问题,这让我相信您没有读一本有声望的书,或者您遇到了严重的问题,因为有声望的本书将在前面的章节中涵盖这些问题。

也许我们应该看看其他一些选择,因为您现在使用的任何东西显然都不适合您。您可能一直在阅读您的书,在反复试验中苦苦挣扎,而您的书应该可以很好地指导您解决这些常见问题

底线是:你需要尊重return价值观

  • 在检查 return 值之前,不要尝试转换它们。unsigned char character; character = getchar(); 中,您正在从书籍和 getchar manual 说是 intunsigned char,然后再尝试对照 EOF 检查它。该转换 可能会导致数据丢失 。您想知道丢失了哪些数据吗?

如果您正在努力理解 K&R2E 或手册,您应该写一个关于您不理解的问题,而不是继续困惑地编写依赖于猜测的代码。在 C 等语言中,任何猜测都是危险的。

您还应该检查 fread 的 return 值,我希望看到 size 参数传递 54,count 参数传递 1你的情况。这样,您可以处理 fread 仅读取 53 字节(或 52,或 fifty-one) 就好像它是输入的结尾,而不是将 意外地短 输入当作是预期的大小。就像getchar手册一样,你可以从the fread manual.

中找到关于fread的所有信息

哦,现在我收到了很多 "but the Youtube videos" 回复。 Youtube 不能很好地替代知名书籍。任何人都可以跳到那里 "just wing it",您观看的视频可能与您自己的猜测一样有缺陷。另一方面,一本有声望的书在计划、同行评审、测试(针对学生,因为这些书通常是由教授 类 教授)和重构(基于测试,以更好地处理发生的 "hiccups")。

选择应该是显而易见的,吃布丁就是证明。如果您尝试过 "youtube" 或 "try it and see" 方法,则它们对您不起作用;你现在看到的就是它的结果。试试别的。祝你好运!