2016-04-01 21 views
0

Hallo Ich habe eine Frage bezüglich des Einlesens in den unteren Werten eines pgm-Wertes. Ich habe ein 2D-Array erstellt und 2 zusätzliche Leerzeichen für die Höhe und Breite hinzugefügt, um einen Puffer erstellen zu können wenn ich versuche, in die erste ganze Zahl bis zur Breite + 1 zu lesen, funktioniert es nicht. Gibt es Hinweise, warum der Code hier aufhört?Lesen in einer PGM-Datei

FILE *pfile; //pointer to file 
pfile=fopen(input_pgm,"r"); 
int columns,rows,value,line_of_numbers; 
char pformat[50]; 
    if (pfile==NULL){ 
     printf("File is empty lame-o\n"); 
        } 
    else{         //Read from file 
     fscanf(pfile,"%s",pformat);  //Things like P2,P5 
     fscanf(pfile,"%d",&columns);  //Number of columns ,M, Need & or it will store it into address 
     fscanf(pfile,"%d",&rows);  //Number of rows , N 
     fscanf(pfile,"%d",&value);  //Number of value, W 
     //Allocating 2D array to store M numbers 
     //printf("Test"); 
     int **board; 
     board = (int **)malloc((rows + 2) * sizeof(int *)); 
     for (i=0;i<rows+2;i++){ 
      board[i]=(int*)malloc((columns+2)*sizeof(int)); 
      } 
     //printf("Test2"); 
     //INITILIZING TO 0 
     board=memset(board,0,((columns+2)*(rows+2))); 
     //printf("Test"); 
     //reading in numbers on to board from 1->/rows/columns+1 
     for(i=1;i<=rows+1;i++){ 
      for(j=1;j<=columns+1;j++){ 
       //printf("Test3"); /*does not work after this*/ 
       int scanned_num; 
       fscanf(pfile,"%d",&scanned_num); 
       board[i][j]=scanned_num;} 
     } 
+0

Problem könnte überall sein. Bitte lesen Sie, wie Sie [mcve] bereitstellen können. – user694733

+1

Beachten Sie, dass, wenn 'fopen()' 'NULL zurückgibt, bedeutet dies, dass die Datei nicht geöffnet werden konnte, ** nicht **, dass die Datei leer ist. Es existiert möglicherweise nicht oder das Programm ist möglicherweise nicht berechtigt, darauf zuzugreifen, oder es könnte ein anderes Problem auftreten. Es ist möglich, eine leere Datei zu öffnen, und wenn Sie dies erfolgreich über 'fopen()' tun, dann ist der zurückgegebene Zeiger * nicht * 'NULL'. –

+0

Definieren Sie "funktioniert nicht". –

Antwort

0

Sie scheinen ein dynamisches Array von Zeigern zu verwirrend sein (heißen der referent von board) mit einem 2D-Array. Das sind nicht alle gleich. Insbesondere ist zu beachten, dass Sie Speicher für board wie so zuteilen:

board = (int **)malloc((rows + 2) * sizeof(int *)); 

, dass der Speicher ausreichend zu halten rows + 2 Zeiger auf int zuteilt. (Und beachten Sie, dass die Besetzung nicht notwendig ist und ein schlechter Stil von vielen als.) Wie dann macht es Sinn, dies zu tun ...

board=memset(board,0,((columns+2)*(rows+2))); 

? Abgesehen von der Tatsache, dass die Zuweisung des Ergebnisses board nutzlos ist, was macht Sie denken, dass Speicherplatz der Größe von rows + 2 Zeiger auf int ist mindestens ((columns+2)*(rows+2)) Bytes? Wenn columns ziemlich klein ist, werden Sie die Grenzen von *board überschreiten und dadurch undefiniertes Verhalten erzeugen.

Außerdem Sie auch damit zu überschreiben, die alle Zeilenzeiger Sie gerade in *board aufgenommen hatte, sie Wegwerfen und damit den gesamten Speicher undichte Sie für den Zeileninhalt zugeordnet hatte. Wenn anstelle des Absturzes an diesem Punkt das Programm weiterhin entsprechend der C-Semantik für den Rest des Codes ausgeführt wird, rufen Sie später undefinierteres Verhalten auf, wenn Sie versuchen, diese Zeiger in Ihrer Leseschleife zu dereferenzieren (board[i][j]=scanned_num). Beachten Sie auch, dass die Anzahl der von Ihnen eingestellten Bytes nicht korrekt ist, auch wenn board ein 2D-Array ist, für jede int ist größer als ein einzelnes Byte.

Es macht Sinn und ist einfacher, das Raster als ein großer Block zuzuordnen, und wenn Sie mindestens verwenden C99, dann ist der sehr einfachste Weg, dies über eine variable Länge Array ist zu tun:

int board[rows + 2][columns + 2]; 

memset(board, 0, sizeof(board)); 

Dann müssen Sie nicht einmal später die Zuweisung aufheben, obwohl das Array das Ende der Ausführung der Funktion nicht überlebt.

Wenn Sie etwas brauchen Sie von der Funktion zurückkehren können, dann können Sie diese stattdessen tun:

int (*board)[columns + 2]; 

board = calloc(rows + 2, sizeof(*board)); 

In diesem Fall führt calloc() automatische Initialisierung des zugewiesenen Speicherplatz auf alle Nullen, so dass Sie nicht tun muss es selbst tun.

So oder so, das erwirbt den benötigten Platz und füllt ihn mit Nullen; nichts anderes muss getan werden, um es für den Empfang der Daten vorzubereiten. Beachten Sie auch, dass genau wie nur ein Aufruf calloc() im zweiten Fall verwendet wird, genau ein entsprechender Aufruf free() verwendet werden sollte, wenn Sie mit dem dynamisch zugewiesenen Speicherplatz fertig sind.

+0

Tut mir leid, ich bin nicht vertraut mit C, aber als ich versuchte, zu memster ich wollte jeden Index der Platine gleich 0 dann habe ich versucht, nur von Index 1 bis Zeile + 1 zu lesen. –

+0

@ What's_sarcasm, ich sollte auch darauf hinweisen, dass die 'pformat'-Zeichenfolge, die Sie lesen und ignorieren, signifikant ist. Dies ist die "magische Zahl" der Datei und gibt an, in welches Format die Datei geschrieben wurde. Standard PGM hat "P5" für diesen Wert. Ihr Code zum Lesen des Pixelrasters erscheint stattdessen als "normales" PGM-Format, dessen magische Zahl "P2" ist. Wenn Sie tatsächlich nur Letzteres unterstützen möchten, sollten Sie Dateien ablehnen, die nicht die korrekte magische Zahl haben. Wenn Sie beide unterstützen möchten, benötigen Sie zusätzlichen Code für den P5-Fall. –