みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

C言語のプログラミングで困っています

C言語を勉強しています。まだまだ初心者で分からないことだらけなのですが、今回はファイル入出力の部分が分からず苦戦しています。

『100個の実数が入った2つのテキストファイルから数値を読み込み、
 絶対値を求めるなどの計算をする』プログラムを作成しているのですが、
コンパイルし実行すると強制終了してしまいます。

プログラムは、

void main(void)
{
FILE *fp;
double c[50000];
  double d[50000];
  double e[50000];
int n = 0;
  int m = 0;
  int i = 0;
  char fname[80];
  char fname2[80];

printf("ファイル名 : ");
   gets(fname);
if((fp = fopen(fname, "r")) == NULL){
printf("ファイルがオープンできません\n");
exit(1);
}
printf("\n");
while (fscanf(fp,"%lf",&c[i])!=EOF){
printf("%3d : %3lf",++n,c[i]);
printf("\n");
i++;
}
printf("\n");
i=0;
n=0;
printf("ファイル名 : ");
   gets(fname2);
if((fp = fopen(fname2, "r")) == NULL){
printf("ファイルがオープンできません\n");
exit(1);
}
printf("\n");
while (fscanf(fp,"%lf",&d[i])!=EOF){
printf("%3d : %3lf",++n,d[i]);
printf("\n");
i++;
}

…(以下計算)

のようになっています。
整数のデータで計算を行うと、正常に動くのですが…。
コンパイルしてもエラーが出ないので、どこが悪いのかわからず困っています。
どなたか教えていただけないでしょうか。お願いしますm(_ _)m

投稿日時 - 2009-01-19 15:04:03

QNo.4643014

すぐに回答ほしいです

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.4

>整数のデータで計算を行うと、正常に動くのですが…。

オートで確保した配列が巨大過ぎるのが原因。

intなら1つ4バイトでギリギリ動く大きさだったが、doubleは1つ8バイトで、使用するメモリ量が2倍になり、メモリがパンクしてしまい「実行時に強制終了」になっている。

それと
while (fscanf(fp,"%lf",&c[i])!=EOF){
も問題がある。

ファイルが尽きてfscanfからEOFが返された場合は良いが「数値として認識できない文字がファイル中にあった場合」には、無限ループする。

fscanfは「数値として認識できない文字」に出会うと、その文字をストリームに残したまま「その時点までで正常に変換して変数に代入した数」を返す。

つまり「最初に変な文字に出会うと、変数に何も代入せず、0を返す」場合がある。つまり「EOFを返してくれない」のだ。

「ストリームにある変な文字」は「消費されずにストリームに残っている」ので、次のfscanfも、次の次のfscanfも、同じように「変数に何も代入せず、0を返す」のが永久に続く。

つまり
while (fscanf(fp,"%lf",&c[i])!=EOF){
は「永久に止まらなくなる事がある」って事。

まあ、実際には「iが配列の要素数の50000を超え、不正なメモリをアクセスして止まる」だろうから「永久に止まらない」って事は無いが。

とにもかくにも「fscanfが0を返した瞬間、ジ・エンド」って事は間違い無い。

while (fscanf(fp,"%lf",&c[i])!=EOF){
ではなく
while (fscanf(fp,"%lf",&c[i])==1){
にして「正常に変換して変数に代入できた個数が1個の間、ループする」じゃないとダメ。

投稿日時 - 2009-01-20 11:03:46

ANo.3

コンパイラは何でしょうか?
スタックサイズはコンパイラの設定より限定されています。
double c[50000];
double d[50000];
double e[50000];
最近の環境だと、大体 double = 8byte
1200000byteでおよそ1.2MB以上のスタックサイズが必要です。
BCCやVCとかだとデフォルトスタックサイズが1Mなので、
スタックオーバーフローとなります。

コンパイラのスタックサイズの設定を変更するか、
配列のサイズをもう少し少なくすれば動作すると思います。

投稿日時 - 2009-01-19 16:45:55

ANo.2

>double c[50000]; double d[50000]; double e[50000];
自動変数で、こんなに大量のメモリを使用してはダメとしたもの。
「自動変数」とか「スタック」とかで検索してみてください。
ヒント:static
賢くは実行時にローカルヒープから必要なメモリを確保するように
しますが、ポインタ+構造体の知恵が必要です。

投稿日時 - 2009-01-19 15:35:26

ANo.1

double c[50000];
double d[50000];
double e[50000];
配列のサイズが大きすぎるんじゃないでしょうか
8バイト*15万で120万バイトですもんね
1MBのスタックでも足りません

投稿日時 - 2009-01-19 15:31:52

あなたにオススメの質問