2017-03-22 136 views
-1

我有一些CS50 Pset4的半工作代碼。如果你運行它,你會看到它恢復27 jpg文件,但只有第一幾行是可見的。CS5Ox Pset4恢復:代碼只能恢復部分圖像

有人能指出我正確的方向嗎?

#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

您的文件名太短(空終止?)。花費多個小時......好吧,有點浪費。 –

+0

@Eugene,每個規範的文件名應該是XXX.jpg。考慮到空終止我會認爲我需要8個字符來存儲文件名。還是我錯過了明顯的東西? (我以0經驗開始了cs50 :)) – LegalExperience

+0

@Mark,你可以在這裏找到我的輸出示例:http://imgur.com/3Nf1Ui4。我不知道輸出應該是什麼樣子,但它應該是一個清晰的圖景。 – LegalExperience

回答

0

我看到幾件事情可能導致這個問題。

首先,檢查您的n計數器的順序。應該在實際開始寫入新文件之前添加計數器,但這只是一個優先選擇問題,並且您希望代碼的清潔程度如何。

其次,嘗試用下面的代碼來代替你的else條件:

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

注意:請記住,我已經取代你的else條件的if條件。這是因爲當滿足第一個條件時,它執行這個條件並'跳出塊'。所以else只會執行第一個if條件不會執行。 如果你想保持你的else條件,那麼你應該嵌套另一個if,就像你在代碼中所做的那樣。

通過替換的是else與將始終無論檢查前3個字節的JPG格式的(也就是說,如果不考慮他們爲0x00,0xFF時,0×00),您將獲得一個更清晰的價值的if和可以理解的代碼。

最後,更重要的是:爲什麼你要在同一個操作中對同一個文件寫入兩次?請注意您的n++計數器下方的fwrite()功能。它真的有必要嗎?

換句話說:刪除這一行:

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

其他錯誤,就是你正在閱讀您的文件兩次,兩次提前在每一步,所以你會得到一半的信息。 這就是你得到一半圖像(27左右)的原因。

刪除這兩條線:

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

正如我已經說過了,通過閱讀您的文件中寫了兩次,你得到的信息的一半。這導致了模糊的方式,在這種方式中,您將圖像全部着色爲無意義的顏色(我猜)和一半的圖像文件。

我已經運行check50 2016.recover recover.c與您的代碼和我剛剛提供給您的固定解決方案,它通過所有從CS50的check50檢查。花點時間,思考程序中的所有內容,包括控制流程,這是它的重要組成部分,以及指針的使用。

在沒有任何經驗的情況下啓動CS50可能令人望而生畏。保持。你已經將它變成了第5周。

+1

謝謝Togeri!這真的很有幫助。我沒有意識到我的while循環條件中的fread也提前了指針。更改了我的代碼並通過了check50。到第5周! :d – LegalExperience