前提・実現したいこと
コマンドライン引数としてjpgファイルを指定して、そのバイナリファイルを読み込んで、新しいファイルとして書き出したい。
発生している問題
50個のjpegファイルが生成されるはずなのに、生成されない。
該当のソースコード
c
1#include <stdio.h> 2#include <stdlib.h> 3#include <stdint.h> 4#include <string.h> 5 6typedef uint8_t BYTE; 7char* file_name(int count); 8int count = 0; 9char filename[8]; 10 11int main(int argc, char *argv[]) 12{ 13 if (argc != 2) 14 { 15 printf("Usage: ./recover image\n"); 16 return 1; 17 } 18 FILE *file = fopen(argv[1],"r"); 19 if (!file) 20 { 21 printf("Could not open file.\n"); 22 return 1; 23 } 24 25 BYTE bytes[4]; 26 BYTE buffer[512]; 27 while (fread(&buffer, sizeof(BYTE), 1, file)) 28 { 29 fread(bytes, sizeof(BYTE), 4, file); 30 if (bytes[0] == 0xff && bytes[1] == 0xd8 && bytes[2] == 0xff && (bytes[3] & 0xf0) == 0xe0) 31 { 32 char* name = file_name(count); 33 FILE *destination = fopen(name, "w"); 34 if (!destination) 35 { 36 return 1; 37 } 38 do 39 { 40 fwrite(&buffer, 512, 1, destination); 41 } 42 while (!(bytes[0] == 0xff && bytes[1] == 0xd8 && bytes[2] == 0xff && (bytes[3] & 0xf0) == 0xe0)); 43 44 fclose(destination); 45 count++; 46 } 47 } 48 return 0; 49} 50 51char* file_name(int number) 52{ 53 char number2[sizeof(number)]; 54 sprintf(number2,"%d", number); 55 if (strlen(number2) == 1) 56 { 57 sprintf(filename,"00%s.jpg", number2); 58 return filename; 59 } 60 else 61 { 62 sprintf(filename,"0%d%d.jpg", (int)number2[0], (int)number2[1]); 63 return filename; 64 } 65} 66
試したこと
・最初のwhile文のfreadの第二引数の数を1にするといくつかファイルが生成されるが、50個には全然届かない。
・どこまで実行できているかprintf関数を使って調べたところ、最初のwhile文は通り抜けているが、その次のifで通り抜けるものがほぼない。
補足情報(FW/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
なにをしてる(つもりの)コードなのか詳しく説明しましょう
そのコードでどうして50個できるはずなのか説明できますか?
> その次のifで通り抜けるものがほぼない
通り抜けるはずなのに無いということであれば、なぜ抜けないのかをお調べになるしかないでしょう。
bytes の中はどのような値になっているのかや、 fread で読み込む際のファイルポインタの位置が想定通りなのか等は printf で確認されたのでしょうか。
cs50という講座の課題です。その課題にjpgファイルが50個できると記載されておりました。
その際の実行コードは./recover card.raw です。(コンパイル済み)
https://cs50.jp/x/2021/week4/problem-set/recover/
まず最初の方は正しいコマンドライン引数がなかった場合、ファイルが正しくなかった場合は弾いています。
BYTE bytes[4]以降は配列を作成し、freadで読み取れた場合にはif文で16進数でjpegファイルかどうかを判定しています。その後新しいファイルの名前をfile_name関数で決定し、fopenで新規ファイルを作成しています。do-while文では次のjpegファイルが見つかるまで512ブロックを読み取り続けているつもりです。
> fread(bytes, sizeof(BYTE), 4, file);
で jpeg の署名の 4 バイトを読む前に、
> while (fread(&buffer, sizeof(BYTE), 1, file))
の fread で 1バイト読んでしまっているのではないでしょうか。
file_name 関数は恐らく期待通りには動かないと思います。
(s)printf のフォーマットには指定桁数で右詰め"0"埋めする書き方がありますので、お調べになっては如何でしょうか。
> do-while文では次のjpegファイルが見つかるまで512ブロックを読み取り続けているつもり
fwrite しかありませんが。
この質問を読む第三者への質問の背景の説明が足りない(その課題の文を読まないと分からない)です。その課題に含まれている、ダウンロード可能なデータファイル card.rawを実行ファイルrecoverで処理すると、50個のファイルができるはず、と説明されています。
回答2件
あなたの回答
tips
プレビュー