2016-11-06 135 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

感謝您的回覆。 –