• Wir präsentieren Dir heute ein Stellenangebot für einen Frontend-Entwickler Angular / Java in Braunschweig. Hier geht es zur Jobanzeige

for-Schleife bricht vorzeitig ab, nachfolgender Programmcode wird ignoriert

W

wantri

Mitglied
Hallo,

ich habe folgende Klasse PPM mit der ein PPM-Bild eingelesen werden kann und dessen Daten als Membervariablen gespeichert werden können.

C++:
#include <iostream>
#include <string.h>

class PPM
{
public:
    char path[255];
    FILE *in;
    char format[3];
    int bildbreite;
    int bildhoehe;
    int maxHelligkeit;
    int* pixelArrayP3;

public:
    PPM(char path[255])
    {
        std::copy(path, path + 255, this->path);
    }

    void einlesen()
    {
        char letter;
        int zahlenInHeaderGespeichert=0;
        in=fopen(path, "rb");

        FILE* out;
        out = fopen("ohneKommentare.ppm", "wb");

        char c;
        //Kommentare entfernen
        while(!feof(in)) {
            c=fgetc(in);
            if(c=='#') {
                do {
                    c=fgetc(in);
                } while(c!='\n');

                continue;
            }
            fprintf(out,"%c",c);
        }
        fclose(in);
        fclose(out);

        //Ab hier wird die neue Datei ohne Kommentare genutzt
        FILE *datei;
        datei=fopen("ohneKommentare.ppm","rb");

        //Informationen der Datei in Membervariablen speichern

            letter=fgetc(datei);
            //Format speichern
            if(letter=='P') {
                format[0]=letter;
                letter=fgetc(datei);
                format[1]=letter;
                format[2]=0;
            }

            //Zahlen für Bildbreite,Helligkeit und max. Helligkeit speichern
            if(!zahlenInHeaderGespeichert) {
                fscanf(datei,"%d",&bildbreite);
                fscanf(datei,"%d",&bildhoehe);
                fscanf(datei,"%d",&maxHelligkeit);
                zahlenInHeaderGespeichert=1;
            }

            //Pixel dezimal speichern, wenn Datei im P3-Format vorliegt
            if(format[0]=='P' && format[1]=='3') {

                int i;
                pixelArrayP3=new int[bildbreite*bildhoehe*3];
                int *ptrP3=pixelArrayP3;

                for(i=0; i<(bildbreite*bildhoehe*3); i++) {
                    fscanf(datei,"%d",ptrP3);
                    ptrP3++;
                    }
            }
     
        //Array hat nur ein Drittel der Länge, falls es ein Graustufenbild ist
            if(format[0]=='P' && format[1]=='2') {
                 int i;
                pixelArrayP3=new int[bildbreite*bildhoehe];
                int *ptrP3=pixelArrayP3;

                for(i=0; i<(bildbreite*bildhoehe); i++) {
                    fscanf(datei,"%d",ptrP3);
                    ptrP3++;
                    }
            }      

            fclose(datei);
    }

    void dateiSchreiben()
    {
        FILE *image;
        image=fopen("image.ppm","wb");
        fprintf(image,"%c",format[0]);
        fprintf(image,"%c\n",format[1]);
        fprintf(image,"%d ", bildbreite);
        fprintf(image,"%d\n", bildhoehe);
        fprintf(image,"%d\n", maxHelligkeit);

        int *ptr=pixelArrayP3;
        if(format[0]=='P' && format[1]=='3') {
            int i;
            for(i=0; i<(bildbreite*bildhoehe*3); i++) {
                fprintf(image,"%d\n",*ptr);
                ptr++;
            }
        }

        if(format[0]=='P' && format[1]=='2') {
            int i;
            for(i=0; i<(bildbreite*bildhoehe); i++) {
                fprintf(image,"%d\n",*ptr);
                ptr++;
            }
        }
        fclose(image);
    }
};

Nun habe ich eine weitere Klasse ImageProcessing entworfen, diese enthält die Methode edgeDetection(), die den Laplace-Filter auf ein PPM-Bild im Graustufenformat anwenden soll.
Im zweiten Block der Methode wird die oberste for-Schleife nicht komplett durchlaufen. Das Programm bricht einfach ab, ohne dass die darunterliegende Methode datei.dateiSchreiben() aufgerufen wird. Das Programm gibt also mehrmals ende1 aber niemals ende2 aus.

Tests via printf haben ergeben, dass der Index i maximal den wert 537 annimmt, obwohl die Bildbreite 539 beträgt. Auch ein Umstellen von
Code:
i++
auf
Code:
++i
oder ein Verändern der Bedingung auf
Code:
 i<datei.bildbreite+1
haben nichts verändert.
Davon abgesehen scheint das Array korrekt befüllt zu werden.

C++:
#include <iostream>
#include <string.h>
#include "ppm.cpp"

class ImageProcessing
{
    char path[255];

public:
    ImageProcessing(char path[255])
    {
        std::copy(path, path + 255, this->path);
    }

    void edgeDetection(PPM datei)
    {
        datei.einlesen();
        double filter[3][3]= {{-1,-1,-1},{-1,8,-1},{-1,-1,-1}};

        //Pixel des PPM-Objekts in zweidimensionalem Array speichern
        int** pixelZweidimensional=new int*[datei.bildhoehe];

        int i;
        for(i = 0; i < datei.bildhoehe; i++) {
            pixelZweidimensional[i] = new int[datei.bildbreite];
        }
        int indexPixelArrayP3=0;

        while(indexPixelArrayP3<(datei.bildbreite*datei.bildhoehe)) {
                int j;
            for(j = 0; j < datei.bildhoehe; j++) {
                int k;
                for(k = 0; k < datei.bildbreite; k++) {
                    pixelZweidimensional[j][k] = datei.pixelArrayP3[indexPixelArrayP3];
                    indexPixelArrayP3++;
                }
            }
        }

        //Filter auf Array anwenden
        indexPixelArrayP3=0;
        while(indexPixelArrayP3<(datei.bildbreite*datei.bildhoehe)) {
        for(int i=0; i<datei.bildhoehe; i++) {
                printf("i: %d\n",i);
            for(int j=0; j<datei.bildbreite; j++) {
                int pixel=0;
                pixel+=pixelZweidimensional[0+i][0+j]*filter[0][0];
                pixel+=pixelZweidimensional[0+i][1+j]*filter[0][1];
                pixel+=pixelZweidimensional[0+i][2+j]*filter[0][2];
                pixel+=pixelZweidimensional[1+i][0+j]*filter[1][0];
                pixel+=pixelZweidimensional[1+i][1+j]*filter[1][1];
                pixel+=pixelZweidimensional[1+i][2+j]*filter[1][2];
                pixel+=pixelZweidimensional[2+i][0+j]*filter[2][0];
                pixel+=pixelZweidimensional[2+i][1+j]*filter[2][1];
                pixel+=pixelZweidimensional[2+i][2+j]*filter[2][2];
                if(pixel<0){
                    pixel=0;
                }
                if(pixel>255){
                    pixel=255;
                }
                datei.pixelArrayP3[indexPixelArrayP3]=pixel;
                //printf("datei.pixelArrayP3[%d]: %d\n", indexPixelArrayP3, datei.pixelArrayP3[indexPixelArrayP3]);
                indexPixelArrayP3++;
            }
            printf("ende1\n");
        }
        printf("ende2\n");
    }
    datei.dateiSchreiben();
    }
};

int main()
{
    char path[255];
    scanf("%s", path);
    PPM file(path);
    ImageProcessing ip(path);
    ip.edgeDetection(file);
    return 0;
}


Es wäre wirklich sehr nett, wenn mir jemand weiterhilft.

Vielen Dank im Voraus!
 
Zuletzt bearbeitet:
kneitzel

kneitzel

Top Contributor
Du greifst über die Array-Grenzen zu. Je nach Compile-Optionen / Compiler kommt dabei Quatsch oder eben ein Abbruch zustanden. Auf Grund Deiner Beschreibung vermute ich, dass Du ohne Optimierungen übersetzt hast so dass dies erkannt wird und die Applikation abgebrochen wird. Vermutlich wirst Du auch einen Code Dump bekommen haben.

a) Bitte sowas immer genau angeben!
b) Ggf. einfach mal in Google schauen, wie Du so einen Code Dump auslesen kannst um den Fehler zu erkennen.

Die Problematik in kurzen Worten erläutert:

i beim letzten Durchgang - i ist also 538. Da du aber auf Element i+1 zugreifen willst, versuchst Du auf Element 539 zuzugreifen und dadurch wird die Applikation abgebrochen.

Wobei mich gerade wundert, dass es dazu überhaupt kommt, denn Du greifst ebenso auf die j-Elemente zu....

Und bei der Behebung bitte beachten: Du hast bis zu 2+j / 2-j -> die Grenzen der Schleife müssen also entsprechend definiert sein!
 
M

M.L.

Top Contributor
MS Visual Studio Community Edition wirft insgesamt drei Fehlermeldungen aus: C26495 (PPM::xxxxxx nicht initialisiert), C6031 (Rückgabewert wird ignoriert: "fscanf") sowie C4996 (fscanf_s anstelle von fscanf)
 

Ähnliche Java Themen

Anzeige

Neue Themen


Oben