質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

788閲覧

main文でのvoid型関数の呼び出し時に異常終了する。

satoume

総合スコア4

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2023/01/08 13:37

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; }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2023/01/08 13:59 編集

>main文でvoid型の関数を呼び出そうとしてプログラムが異常終了 呼び出そうとして? 呼び出して top 内で? どこで止まっているのか調べてください。 「一通りデバッグを行った」というのはコンパイルエラーを取ることを言われているのでしょうか。 だとしたらデバックはこれからでしょう。 > int e[2880*512] = {0}; この辺から怪しそうですが。
hoshi-takanori

2023/01/08 14:17

FAT12 よく知りませんが、ディスクイメージに対して “%d” を fscanf してるのが怪しい気が…。
satoume

2023/01/09 07:08

説明が下手ですみません。 >jimbeさん 「一通りデバッグを行った」というのは-Wallオプションで表示されるエラーや警告については解消したということです。 >hoshi-takanoriさん、y_waiwaiさん  勉強不足でした。ローカル変数だと150万行の配列は定義できないんですね。 ご指摘いただいた個所について以下のように修正したところfscanfで読み込んだファイルデータがすべて0で格納されてしまいました。 while(fscanf(fp,"%d",d) != EOF){ i++; if(i == 2880*512){ break; } } また、ディスクイメージに対して “%d” を fscanf するのはよくないことなのでしょうか。
jimbe

2023/01/09 07:15 編集

fscanf は基本的にテキスト('\0'を終わりとするASCIIコードの可変長バイト列)を対象とする関数です。 ディスクイメージはファイル名等のテキスト以外の部分はバイナリであり、各データのバイト数は決まっているはずです。
hoshi-takanori

2023/01/09 08:44

> 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' は含まれないのが普通かと。
jimbe

2023/01/09 09:11 編集

テキスト"ファイル"とは言っていないのですが、考えてみたら "%d" ですので '\0' は関係無いですね。何か string.h 系とごちゃになってました、すいません。 ファイル名部分も '\0' 終わりでなく nstring (文字数+文字列)かもしれません。
satoume

2023/01/09 10:22

ご指摘いただいた個所について以下のように修正したところfgetsで読み込んだファイルデータが文字化けしてしまいました。 char* e = calloc(2880 * 512, sizeof(char)); while(fgets(e,5,fp) != NULL){ printf("%s",e); d[i] = atoi(e); i++; }
guest

回答2

0

ベストアンサー

int e[2880*512] = {0}; の前に static を付けてください。
これで静的記憶域期間をもつオブジェクトであるローカル変数を確保でき、
サイズの制限も緩くなります。
または、int *e = calloc(2880 * 512, sizeof(int)); とすると、
e はローカル変数でありながら、割付け記憶域期間をもつデータ領域を確保して、
それを指すことにより、配列としてアクセスできます。

投稿2023/01/09 06:33

kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

int e[2880*512] = {0};

一般的にローカル変数はスタックエリアに取られますが、このスタックエリアは数MByte程度しか確保されません。
ってことで、ローカル変数でこのような巨大な配列は確保できません

投稿2023/01/08 14:00

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問