2017-03-22 1 views
-1

Ich habe einige semi-working-Code für CS50 Pset4. Wenn Sie es ausführen, werden Sie sehen, dass es 27 JPG-Dateien wiederherstellt, aber nur die ersten paar Zeilen sind sichtbar.CS5Ox Pset4 Recover: Code nur teilweise Bilder wiederhergestellt

Kann mir jemand in die richtige Richtung zeigen?

#include <stdio.h> 
#include <stdint.h> 
#include <stdlib.h> 

typedef uint8_t BYTE; 

int main (int argc, char *argv[]) 
{ 
    // ensure proper usage 
    if (argc != 2) 
    { 
     fprintf(stderr, "Usage: ./recover infile\n"); 
     return 1; 
    } 

    // open file to be recovered 
    FILE *infile = fopen(argv[1], "r"); 
    if (infile == NULL) 
    { 
     fprintf(stderr, "Could not open infile.\n"); 
     return 2; 
    } 

    // temp storage for blocks 
    BYTE buffer[512]; 

    // variable to store filename 
    char filename[8]; 

    //store number of recovered files 
    int n = 0; 

    // temp storage for outfiles 
    FILE* outfile = NULL; 

    // iterate over all blocks of memory until end of SD card is reached 
    while (fread(buffer, 512, 1, infile) != 0) 
    { 
     // read one block 
     fread(buffer, 512, 1, infile); 

     // check if block is start of jpeg 
     if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0) 
     { 
      //close previous file if already open 
      if(outfile != NULL) 
      { 
       fclose(outfile); 
      } 

      // creeate new outfile 
      sprintf(filename, "%03i.jpg", n); 
      outfile = fopen(filename, "w"); 

      // write block to outfile 
      fwrite(buffer, 512, 1, outfile); 

      n++; 
     } 
     else 
     { 
      // write block to current outfile 
      if(outfile != NULL) 
      { 
       fwrite(buffer, 512, 1, outfile); 
      } 
     } 
    } 

    //close last outfile 
    fclose(outfile); 

    //close infile 
    fclose(infile); 
} 
+0

Ihr 'Dateiname' ist zu kurz (Nullterminierung?). Mehrere Stunden damit verbringen ... naja, ein bisschen verschwenderisch. –

+0

@Eugene, der Dateiname der Spezifikation sollte XXX.jpg lauten. In Anbetracht der Null-Terminierung würde ich denken, dass ich 8 Zeichen brauche, um den Dateinamen zu speichern. Oder fehlt mir etwas Offensichtliches? (ich begann cs50 mit 0 vorherige Erfahrung :)) – LegalExperience

+0

@Mark, finden Sie ein Beispiel für meine Ausgabe hier: http://imgur.com/3Nf1Ui4. Ich habe keine Vorstellung davon, wie die Ausgabe aussehen soll, aber es sollte ein klares Bild sein. – LegalExperience

Antwort

0

Ich sehe mehrere Dinge, die dieses Problem verursachen könnten.

Überprüfen Sie zuerst die Reihenfolge Ihres Zählers n. Der Zähler sollte hinzugefügt werden, bevor Sie mit dem Schreiben der neuen Datei beginnen, aber das ist nur eine Frage der Präferenz und wie sauber der Code sein soll.

Zweitens, versuchen Sie Ihr else Zustand mit dem folgenden Code zu ersetzen:

if(outfile != NULL)       
     { 
     fwrite(buffer, 512, 1, outfile); 
} 

Hinweis: Bitte beachten Sie, dass ich Ihre else Bedingung für eine if Bedingung ersetzt haben. Dies ist aufgrund der Tatsache, dass, wenn die erste if Bedingung erfüllt ist, dann führt es diese Bedingung und "springt aus dem Block". So wird die else ausgeführt werden nur die erste if Bedingung wird nicht ausgeführt. Wenn Sie Ihre else Bedingung beibehalten möchten, dann sollten Sie eine weitere if verschachteln, wie Sie es in Ihrem Code getan haben.

Durch Substitution dass else mit einem if, die immer unabhängig von dem Wert der ersten drei Bytes Ihrer jpg überprüft werden (das heißt, unabhängig davon, ob sie sind 0x00, 0xFF, 0x00), erhalten Sie eine viel klar erhalten und verständlicher Code.

Zuletzt, und noch wichtiger: Warum schreiben Sie zweimal in die gleiche Datei in der gleichen Operation? Achten Sie auf die fwrite() Funktion unter Ihrem n++ Zähler. Ist es wirklich notwendig?

Mit anderen Worten: löschen Sie diese Zeile:

// read one block fread(buffer, 512, 1, infile);

Andere Fehler, ist, dass Sie Ihre Datei zweimal lesen, und vorher zweimal in jedem Schritt, so dass Sie die Hälfte Informationen erhalten. Dies ist der Grund, warum Sie die Hälfte der Bilder (27 oder so) bekommen.

Erase diese beiden Linien:

// read one block fread(buffer, 512, 1, infile);

Wie ich gesagt habe, durch das Lesen und zweimal innerhalb von Dateien zu schreiben, erhalten Sie die Hälfte der Informationen. Dies führt zu der unscharfen Art, in der Sie Ihre Bilder alle in sinnlosen Farben (ich denke) und die Hälfte der Bilddateien färben.

Ich habe check50 2016.recover recover.c mit Ihrem Code und mit den festen Lösungen, die ich Ihnen gerade zur Verfügung gestellt habe, und es besteht alle Prüfungen von CS50 Check50. Nehmen Sie sich Zeit und denken Sie über alles in Ihrem Programm nach, einschließlich des Kontrollflusses, der ein wichtiger Teil davon ist, sowie der Verwendung der Zeiger.

Starten CS50 ohne vorherige Erfahrung kann entmutigend sein. Mach weiter. Du hast es schon fast in Woche 5 geschafft.

+1

Danke Togeri! Das war sehr hilfreich. Ich habe nicht bemerkt, dass der Freed in meiner while-Schleife auch den Zeiger weitergeführt hat. Mein Code wurde geändert und check50 übergeben. Bis zur 5. Woche! : D – LegalExperience