2016-11-06 4 views
-1

Ich habe mit einem Problem in PSET4 (whodunit) konfrontiert. Ich verstehe wirklich nicht, warum im folgenden Fall Fehler auftreten, obwohl compile keine Warnung gibt.Strukturen in C

In diesem Problem sollte ich jedes Pixel der angegebenen .bmp-Datei lesen, jedes rote Pixel durch weißes Pixel ersetzen und neues Bild in eine neue .bmp-Datei schreiben.

Hier sind zwei Versionen meines Codes. In der ersten Auflistung gibt es eine korrekte Version des Codes, und das Programm funktioniert ordnungsgemäß, wie ich es wollte. In der zweiten Liste gibt es ein Beispiel für Code, der erfolgreich kompiliert wurde, aber Pixel entweder immer noch gleich oder passiert etwas seltsam.

richtige Version

// 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); 
    } 

unkorrekte Version

// 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); 
    } 

Nach dem "Arrays" lessons (und zB mit "Studenten" Struktur in CS50), ist es erforderlich, was um die Indizes [i] und [j] für die Array- und Strukturvariablen während der Ausführung von "for" -loop einzuschließen. Aber in diesem Fall wird alles ungültig, wenn ich diese Indizes in den Code lege. Und alles ist in Ordnung, wenn ich diese Indizes nicht schreibe. Warum bricht diese Logik hier mit Strukturen?

+0

Sie ... was haben Sie getan. – Havenard

+0

@Havenard was ist los? –

+1

Wie von dasblinkenlight in seiner Antwort darauf hingewiesen wurde, sollten Sie den Index des Arrays angeben, wenn Sie darauf zugreifen, nicht wenn Sie es deklarieren. Bei der Deklaration sollten Sie die Gesamtgröße angeben, die vom Index 0 bis zur Größe 1 reicht. Und wenn Sie ein Element pro Iteration behandeln, sollten Sie das Array außerhalb der Schleife deklarieren, als ob Sie es innerhalb der Schleife tun würden. Es wird jedes Mal neu deklariert und es können Inkonsistenzen auftreten (auch undefiniertes Verhalten). – Havenard

Antwort

4

Wenn Sie RGBTRIPLE triple[i][j]; deklarieren, erstellen Sie ein 2D-Array mit den Valud-Indizes 0..i-1 und . Zugriff auf triple[i][j] ist undefiniertes Verhalten; deshalb schlägt deine zweite Lösung fehl.

Sie benötigen jedoch kein ganzes Array von RGBTRIPLE, weil Sie sie einzeln verarbeiten. Deshalb funktioniert Ihre erste Lösung.

Wenn Sie das gesamte Array lesen müssen, erklären sie vor die äußere Schleife mit korrekten Abmessungen:

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

mit dieser Lösung vorsichtig sein, denn Sie bi.biHeight*bi.biWidth einen Absturz für sehr große Werte von verursachen kann .

+0

danke für Ihre Antwort. –