c言語でFAT12の形式のディスクイメージファイルを読み取り、ディスクイメージファイル内に格納されたファイル名やデータを取り出すプログラムを書いています。一通りデバッグを行った後、実行したところmain文でvoid型の関数を呼び出そうとしてプログラムが異常終了します。詳しい方解決方法をご享受していただけると幸いです。
#include<stdio.h> #include<stdlib.h> #include<string.h> int d[2880*512] = {0}; int hour,minu,sec,year,month,day; int b1(int addr){ return (d[addr]&0xff); // 1 byte 読込 } int b2(int addr){ return b1(addr)+b1(addr+1)*256; // 2 byte 読込 } int b3(int addr){ return b1(addr)+b2(addr+1)*256; // 3 byte 読込 } int b4(int addr){ return b2(addr)+b2(addr+2)*256*256; // 4 byte 読込 } void cTime(int addr){ int v=b2(addr); // 時刻 2 byte解析 hour=(v>>11)&0x1f; minu=(v>>5)&0x3f; sec=(v&0x1f)*2; } void cDate(int addr){ int v=b2(addr); // 日付 2 byte解析 year=((v>>9)&0x7f)+1980; month=(v>>5)&0xf; day=v&0x1f; } int fat(int f){ int v=b3(512+(f/2)*3); // fat 12bit 解析 return (f%2==0)?(v&0xfff):((v>>12)&0xfff); } char* int_to_str(int d[],int begin,int length,char* result){ int i=0; int k = begin+length; char pre_result[1]; for(i=begin;i<=k;i++){ pre_result[0] = (char)d[begin+i]; strcat(result,pre_result); } return result; } void top(char fn[],char str[]){ int i=0,j,f,l,ln,le; FILE * fp = NULL; fp = fopen(fn,"r"); int e[2880*512] = {0}; while(fscanf(fp,"%d",e) != EOF){ d[i] = e[i]; i++; } fclose(fp); for(i=0;i<224;i++){ // ルートディレクトリ中のエントリの処理 int addr=0x2600+i*32; if(d[addr]==0xe5){ continue; } if(d[addr+11]!=0x20 && d[addr+11]!=0x10){ continue; } for(ln=0;ln<8;ln++){ if(b1(addr+ln)==0x20){ break; } }--- for(le=0;le<3;le++){ if(b1(addr+8+le)==0x20){ break; } } printf("%d %d",ln,le); char pre_name1[8]; char pre_name2[3]; puts(int_to_str(d,addr,ln,pre_name1)); puts(int_to_str(d,addr,le,pre_name2)); char name[12]; strcat(name,pre_name1); strcat(name,"."); strcat(name,pre_name2); if(strcmp(name,str)==0){ cTime(addr+14); cDate(addr+16); printf("name=%s\n",name); printf("%02d:%02d:%02d %d/%d/%d\n",hour,minu,sec,year,month,day); f=b2(addr+26); l=b4(addr+28); printf("cluster_no.=%d length=%d\n",f,l); do { for(j=0;j<512&&l>0; j++,l--){ printf("%c\n",(char)(d[0x3e00+f*0x200+j])); } } while( (f=fat(f))!=0xfff ); } } } int main(void){ char fn[] ="os22flp.iso",str[] ="20D1000A.TXT"; top(fn,str); return 0; }
>main文でvoid型の関数を呼び出そうとしてプログラムが異常終了
呼び出そうとして? 呼び出して top 内で?
どこで止まっているのか調べてください。
「一通りデバッグを行った」というのはコンパイルエラーを取ることを言われているのでしょうか。
だとしたらデバックはこれからでしょう。
> int e[2880*512] = {0};
この辺から怪しそうですが。
FAT12 よく知りませんが、ディスクイメージに対して “%d” を fscanf してるのが怪しい気が…。
説明が下手ですみません。
>jimbeさん 「一通りデバッグを行った」というのは-Wallオプションで表示されるエラーや警告については解消したということです。
>hoshi-takanoriさん、y_waiwaiさん
勉強不足でした。ローカル変数だと150万行の配列は定義できないんですね。
ご指摘いただいた個所について以下のように修正したところfscanfで読み込んだファイルデータがすべて0で格納されてしまいました。
while(fscanf(fp,"%d",d) != EOF){
i++;
if(i == 2880*512){
break;
}
}
また、ディスクイメージに対して “%d” を fscanf するのはよくないことなのでしょうか。
fscanf は基本的にテキスト('\0'を終わりとするASCIIコードの可変長バイト列)を対象とする関数です。
ディスクイメージはファイル名等のテキスト以外の部分はバイナリであり、各データのバイト数は決まっているはずです。
> satoume さん
まず、テキストファイルとバイナリファイルの区別をつけるところからでしょうね。この辺が参考になるかも。
https://milestone-of-se.nesuke.com/nw-basic/as-nw-engineer/binary-text-ascii/
https://www.macnica.co.jp/business/semiconductor/articles/intel/133448/
https://9cguide.appspot.com/17-02.html
あと、実際にいろんなテキストファイルやバイナリファイル (C 言語のソースファイルや、os22flp.iso など) をバイナリエディタで開いて内容を観察することをお勧めします。
で、int d[2880*512] = {0}; ですが、要素数 2880*512 = 1474560 って、1.44MB のフロッピーでしょうか? また、os22flp.iso のファイルサイズは 1474560 バイトでしょうか?
そうだとして、d にイメージファイルの中身を全て取り込みたいなら、int の配列じゃなくて char (または unsigned char) の配列にする必要があるし、fscanf ではなく fread を使うことになるでしょうし、OS によっては fopen でファイルを開くときに 'r" ではなく "rb" とする必要があるかも。
https://monozukuri-c.com/langc-funclist-binaryfile/
https://programming-place.net/ppp/contents/c/042.html
> jimbe さん
重箱の隅で申し訳ありませんが、テキストファイルには '\0' は含まれないのが普通かと。
テキスト"ファイル"とは言っていないのですが、考えてみたら "%d" ですので '\0' は関係無いですね。何か string.h 系とごちゃになってました、すいません。
ファイル名部分も '\0' 終わりでなく nstring (文字数+文字列)かもしれません。
ご指摘いただいた個所について以下のように修正したところfgetsで読み込んだファイルデータが文字化けしてしまいました。
char* e = calloc(2880 * 512, sizeof(char));
while(fgets(e,5,fp) != NULL){
printf("%s",e);
d[i] = atoi(e);
i++;
}

回答2件
あなたの回答
tips
プレビュー