2016-11-06 78 views
-1

我在PSET4(whodunit)中遇到了一个问题。我真的不明白为什么在下面的例子中出现错误,尽管编译没有提出警告。C中的结构

在这个问题中,我应该读取给定.bmp文件的每个像素,用白色像素替换每个红色像素,并在新的.bmp文件中写入新图像。

这是我的代码的2个版本。在第一个列表中有一个正确的代码版本,并且程序可以正常工作。在第二个列表中有一个成功编译的代码示例,但像素仍然相同,或者发生奇怪。

正确版本

// iterate over infile's scanlines 
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++) 
{ 
    // iterate over pixels in scanline 
    for (int j = 0; j < bi.biWidth; j++) 
    {             //CORRECT VERSION 
     // temporary storage 
     RGBTRIPLE triple; 

     // read RGB triple from infile 
     fread(&triple, sizeof(RGBTRIPLE), 1, inptr); 
     if((triple.rgbtRed == 0xff) && (triple.rgbtGreen == 0x00) && (triple.rgbtBlue == 0x00)) 
     { 
      triple.rgbtBlue = 0xff; 
      triple.rgbtGreen = 0xff; 
      triple.rgbtRed = 0xff; 
     } 

     // write RGB triple to outfile 
     fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr); 
    } 

不正确的版本

// iterate over infile's scanlines 
for (int i = 0, biHeight = abs(bi.biHeight); i < biHeight; i++) 
{ 
    // iterate over pixels in scanline 
    for (int j = 0; j < bi.biWidth; j++) 
    {             //INCORRECT VERSION 
     // temporary storage 
     RGBTRIPLE triple[i][j]; 

     // read RGB triple from infile 
     fread(&triple, sizeof(RGBTRIPLE), 1, inptr); 
     if((triple[i][j].rgbtRed == 0xff) && (triple[i][j].rgbtGreen == 0x00) && (triple[i][j].rgbtBlue == 0x00)) 
     { 
      triple[i][j].rgbtBlue = 0xff; 
      triple[i][j].rgbtGreen = 0xff; 
      triple[i][j].rgbtRed = 0xff; 
     } 

     // write RGB triple to outfile 
     fwrite(&triple, sizeof(RGBTRIPLE), 1, outptr); 
    } 

据 “阵列” 吸取(和实施例以 “生” 结构,CS50),需要事在“执行”循环执行期间为数组和变量包含索引[i]和[j]。但是在这种情况下,如果我把这些索引放在代码中,一切都会失效。如果我不写这些索引,一切都可以。为什么这个逻辑在这里打破,结构?

+0

你......你做了什么。 – Havenard

+0

@Havenard有什么不对? –

+1

正如dasblinkenlight在他的回答中指出的那样,您应该在访问数组时指定数组的索引,而不是在声明时指定数组的索引。声明它时,应指定其总大小,范围从索引0到大小-1。如果你每次迭代处理一个元素,你应该在循环之外声明数组,就好像你在循环内部做的那样,它每次都会被重新声明,并且它可能会有不一致(也就是未定义的行为)。 – Havenard

回答

4

当你声明RGBTRIPLE triple[i][j];时,你制作了一个二维数组,其索引号为0..i-10..j-1。访问triple[i][j]是未定义的行为;这就是为什么你的第二个解决方案失败

但是,您不需要整个数组RGBTRIPLE,因为您一次处理它们一个。这就是你的第一个解决方案的原因。

如果需要读取整个阵列,其声明前用正确的尺寸外循环:

RGBTRIPLE triple[abs(bi.biHeight)][abs(bi.biWidth)]; 

小心使用这种解决方案,因为你可能会导致崩溃为bi.biHeight*bi.biWidth非常大的值。

+0

感谢您的回复。 –