ようこそ ゲスト さん、新規登録(無料)して気になる疑問を解決しませんか?

質問

質問者:w_t_ エラーがどうしても解消しません。
困り度:
  • 困っています
エラーがどうしても解消しません。
コーディング無視、コメント無しです。
(まだ、そんなレベルに達してません。
プログラムを見て頂ければ分かると思いますが。)

使用環境はXP-sp2
CPAT for Boland C++ Compiler Ver2.31
Boland C++ Compiler5.5

複数のテキストファイルを一つのファイルにまとめるプログラムです。33行目以降は出力です。
読込48ファイル目でエラーが出てしまいます。

やってみた事は7行目のファイルポインタを99に変更、以前は50でした。(改善なし)
19行目のi=0を40に変更したら40から50まではエラー無く終了。(出力までOK)
17行目のファイル数入力で10個のファイルに対して11と入力した時、11個目はエラーとなりますが、出力はでます。
しかし、47個までは正常に終了しますが48個目でエラーが出て強制終了してしまい、出力されません。

解決方法はあるのでしょうか。

宜しくお願いいたします。

1:#include <stdio.h>
2:#include <stdlib.h>
3:#include <string.h>
4:
5:int main(void)
6:{
7: FILE *fp[99],*fpo;
8: char fname0[15];
9: char fname1[15];
10: char fname2[10];
11: char fname3[5];
12: int i,j,n=0;
13:
14:
15: printf("\n Files coupling program \n\n");
16: printf("File name : "); scanf("%s",fname2);
17: printf("How many Files : "); scanf("%d",&n);
18:
19: for (i = 0 ; i < n ; i++)
20: {
21: sprintf(fname3,".s%02d",i+1);
22: strcpy(fname0,fname2);
23: strcat(fname0,fname3);
24:
25:
26: if(NULL == (fp[i] = fopen(fname0, "r")))
27: {
28: fprintf(stderr, "\nCannt openfile : %\n\n",fname0);
29: break;
30: }
31: printf("Read : %s \n",fname0);
32: }
------以降省略------
68:}
質問投稿日時:08/04/21 16:48
質問番号:3965100
この質問に対する回答は締め切られました。
最新から表示回答順に表示良回答のみ表示

回答

 

回答者:chie65536 因みに。

Windowsの前身のMS-DOSでは、コンベンショナルメモリを増やす方法として、CONFIG.SYSファイルに「同時オープン数の上限」が記述出来ます。

例えば
FILES=16
とか。

MS-DOSの起動ドライブのCONFIG.SYSに上記のように書いておくと、同時に開けるファイルが16個だけになります。

そのような環境では、質問者さんのプログラムは、もっと早い段階でエラーで止まります。

なので「ファイルを開いて使い終わったら、使いもしないのに開きっぱなしで放置」したりしてはいけません。

複数のファイルを1つにするプログラムを書く場合は、
1.出力ファイルを開く
2.1つ目の入力ファイルを開く
3.中身を読み書きしてコピー
4.1つ目の入力ファイルを閉じる
5.2つ目の入力ファイルを開く
6.中身を読み書きしてコピー
7.2つ目の入力ファイルを閉じる
8.3つ目の入力ファイルを開く
9.中身を読み書きしてコピー
10.3つ目の入力ファイルを閉じる
11.出力ファイルを閉じる
のような書き方をしましょう。

そうすれば
FILE *ifp,*ofp;
の2つのファイルポインタさえあれば処理できます。
種類:回答
どんな人:一般人
自信:参考意見
回答日時:08/04/21 17:41
回答番号:No.4
この回答へのお礼丁寧に書いて頂ありがとうございます。
大変参考になりました。

今回、質問投稿は初めてなのでポイントの付け方が分かりません。
皆様にと思うのですが、ごめんなさい。

回答

良回答20pt

回答者:chie65536 OSには「同時にファイルを開ける数」に上限があります。

この上限には「すべてのプログラムを通した全部の合計」と「1つのプログラムでの合計」など、色々あります。

また、Cコンパイラの場合、fopenの実装によっては「ファイルポインタは、内部的な、有限個の配列の、1つの要素を返す」と言う実装をしている場合があるのです。

つまり、内部的に
FOPEN_MAX=50
FILE ___file_table[FOPEN_MAX];
みたいな感じで有限個の配列があって、配列の要素の個数がFOPEN_MAX個しかないのです。

で、stdinは___file_table[0]のポインタを差し、stdoutは___file_table[1]のポインタを差し、stderrは___file_table[2]のポインタを差していて、最初に3つ使用済みになっています。

そして、fopenが呼ばれるたびに、___file_table[3]、___file_table[4]のポインタが順に返されます(もちろん、クローズされて未使用になれば、またそれが再利用されて返されますが)

で、この配列がクローズされずに全部埋まっちゃうか、オープン数が1プログラムの上限を越えるか、OSの上限を超えれば「もうダメぽ」って感じでエラーが出て止まります。
種類:回答
どんな人:一般人
自信:参考意見
回答日時:08/04/21 17:28
回答番号:No.3
この回答へのお礼回答ありがとうございます。
みなさんの回答内容が一緒なので、*fpはオープンして使ったらクローズするを心がけて、作り直したいと思います。

回答

 

回答者:sakusaker7 ひょっとしてファイルオープンに失敗するというエラーですか?

条件(OSとかそのへん)によって違いはありますが、
開きっぱなしにできるファイルの数には制限があります。
質問にあるコードではクローズをどのタイミングでやっているのかわかりませんが、

>7: FILE *fp[99],*fpo;

というのをみるに、一辺にオープンして最後にまとめてクローズしようとしてませんか?
種類:補足要求
どんな人:経験者
自信:参考意見
回答日時:08/04/21 17:11
回答番号:No.2
この回答への補足回答ありがとうございます。
ファイルのオープンに失敗します。
一旦、50のファイルをオープンしてから、32行目以降にてfor文でfname1にオープンしたファイルの内容をコピーして*fp[99]を閉じてます。
この回答へのお礼この回答にお礼をつける(質問者のみ)

回答

 

回答者:hidebun stdio.hの中に、FOPEN_MAXという値が定義されています。
これが50になっているのでしょう。
stdin, stdout, stderrがプログラム開始時に3ファイル分使用されて
しまうので、50−3=47個が、同時に開くことが可能な最大数になります。

この値を変更する方法があるかもしれませんが、それよりもロジックを
見直したほうが良いでしょう。
種類:アドバイス
どんな人:一般人
自信:参考意見
回答日時:08/04/21 17:09
回答番号:No.1
この回答へのお礼早速の回答ありがとうございます。
stdio.h の中身がその様になっていたとは思っておりませんでした。
ロジックの見直しをがんばってやってみたいと思います。
関数も余り知らないので、知っている関数を使って一生懸命考えたあげく出たものです。
ありがとうございました。
最新から表示回答順に表示良回答のみ表示