以下のプログラムが暴走します。ちなみにビジュアルC++6.0でやりました。
j=99;
    n=1000;の条件で
for(m=1;m<=n;m++){
t=dertat*m;
ey[0]=a*sin(w*t);
if((fp=fopen("jikai","w"))==NULL){
      printf("磁界あきません。n=[%d] hz[%d]\n",m,k);exit(1);
}
for(k=0;k<=j;k++){
  hz[k]=hz[k]+(dertat*(ey[k]-ey[k-1]))/(dertax*u0);
/*printf("hz[%d] = %1.14lf\n",k,hz[k]);*/
fprintf(fp,"%1.14lf\n",hz[k]);
}
/*if((fp=fopen("denkai","w"))==NULL) exit(2);*/
for(k=0;k<=j;k++){
ey[k]=ey[k]+(dertat*(hz[k+1]-hz[k]))/(dertax*eps1);
/*fprintf(fp1,"%1.36lf\n",ey[k]);*/
}

まだプログラムの途中ですがnを1000回に設定してjを99に設定しているのに
nが510回めになるとif((fp=fopen("jikai","w"))==NULL){
      printf("磁界あきません。n=[%d] hz[%d]\n",m,k);exit(1);
の制限がかかりとまってしまいます。hzは99までしかいかないはずなのに
nが510回目になると勝手にないはずのhz[100]計算してしまいとまります。
原因がわかりませんので詳しく教えていただけませんか?あとFILEの
書き込みについてのやり方も教えてください。よろしくお願いします。

A 回答 (5件)

解析をしてわかった部分について回答します。



>nが510回めになるとif((fp=fopen("jikai","w"))==NULL){
>      printf("磁界あきません。n=[%d] hz[%d]\n",m,k);exit(1);
>の制限がかかりとまってしまいます
「nを1000回に設定して・・・」とあるので、1000回ループしてると思いますが、
ループのはじめでファイルをオープンしているのですが、次のループに入る前に閉じていますでしょうか?
ファイルを閉じないで1000回開いてみたところ、私もエラーが発生しました。
1回ループするごとにfcloseで閉じてやれば問題は解決されます。

例)
if((fp=fopen("jikai","w"))==NULL){
      printf("磁界あきません。n=[%d] hz[%d]\n",m,k);exit(1);
}
(なんらかの処理)
fclose(fp)

ファイルを開いたら最後には閉じるのが決まりなので、ファイルはしっかり閉じるようにしましょう。

>あとFILEの
>書き込みについてのやり方も教えてください。よろしくお願いします。
fwriteを使えば書き込むことができます。

fwrite(出力用領域の先頭ポインタ, 出力領域1つの大きさ(バイト), 最大出力データの数, ファイルポインタ)

hz[100]を計算してしまう理由については・・・今も調査中です^^;
    • good
    • 0
この回答へのお礼

ありがとうございました。
おかげでプログラムもうまくいってます.
皆さんのアドバイスがあったからこそ出来ました。
これからもなんかありましたらよろしくお願いします。

お礼日時:2001/02/05 12:09

他の方と回答が重複している部分もあるかと思いますが.



ソースを実際に検証したわけではありません.

-->
for(m=1;m<=n;m++){

  .....
  if((fp=fopen("jikai","w"))==NULL){
   printf("磁界あきません。n=[%d] hz[%d]\n",m,k);exit(1);
  }
  ...
}
<--

ここで、ループするたびに、ファイルを新たに開いている事に
なるので、「ファイルの開きすぎ」を起こしているのでは
ないでしょうか??
開いたら(fopen)、閉じる(fclose)のが原則なのですが
このプログラム上で
-->
/* fprintf(fp1,"%1.36lf\n",ey[k]);*/
fclose(fp); /* 追加 */
}
<--
と単に書いただけだと、fopen した瞬間に今まで書き込んだ
データはパァになってしまいます.

なので、fopen は for ループの中ではなく、ループに入る前に
行い、ループを抜けた後に、fclose すればよいのではないでしょうか??
(ループの中で、fopen をしたい意図があるのかもしれませんが...)

こんな風に書き換えてみるとうまくいくのでは.
-->
if((fp=fopen("jikai","w"))==NULL){
printf("FILE OPEN ERROR",m,k);exit(1);
}
for(m=1;m<=n;m++){
  ......
  .....
}
fclose(fp);
<--

===

hz[100] というのは、エラーメッセージ(fopen の失敗の時)で
表示されているのでしょうか??

だとすれば、それは合っていますよ.

-->
for(k=0;k<=j;k++){
hz[k]=hz[k]+(dertat*(ey[k]-ey[k-1]))/(dertax*u0);
/* printf("hz[%d] = %1.14lf\n",k,hz[k]);*/
fprintf(fp,"%1.14lf\n",hz[k]);
}
<--

このループを抜けてきたときに、k の値は 100 (99 + 1)に
なっている筈です.

ご参考まで.
    • good
    • 0

追加です。


>nが510回目になると勝手にないはずのhz[100]計算してしまいとまります。
とありますが、
for(k=0;k<=j;k++){
ey[k]=ey[k]+(dertat*(hz[k+1]-hz[k]))/(dertax*eps1);
/* fprintf(fp1,"%1.36lf\n",ey[k]);*/
}
jが99なので、k<=jなので、Kが99までまわり、hz[K+1]はhz[100]となります。
hz[100]で宣言しているのであれば、ループの判定は「k<j」です。
変数宣言等がわからないので、的外れかもしれませんが。
    • good
    • 0

ソースが途中なのでなんとも言えませんが、


for(m=1;m<=n;m++){
}
の中で、fopen()を繰り返していますが、fclose()は行っているのでしょうか?
close()を行わないと、いくら同じファイルポインタに代入していても、限界がありますよ。

Windowsがどのくらいファイルを同時オープンできるのかは知らないですが...
    • good
    • 0

fp=fopen("jikai","w"))==NULLの部分はjikai.拡張子はなくていいんでしょうか?



hz[k]=hz[k]+(dertat*(ey[k]-ey[k-1]))/(dertax*u0);
k=0→99の部分ですが、ey[k-1]がk=0の時、ey[-1]になってますね。
けど、これだと1回目のループで不正な処理のメッセージがでて止まるはずなんだけど。。。
fileの書きこみは、別にこれでいいと思います。スピード上げようするんなら、バイナリで書き出すって手もありますが。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aと関連する良く見られている質問

Qfp = fopen(argv[1], "r");を”w" "a" "r+"・・・で試したらどうなる

http://oshiete.goo.ne.jp/qa/8897349.html
 以上のプログラムで
 以下をfp = fopen(argv[1], "r");の
 ”r"以外で以下を入れた場合の結果がどうなるかお聞きしたいです。
"r" 読み込みモード。ファイルが存在しているとする。
"w" 書き出しモード。すでにファイルがあれば内容を削除し、なければ新たに作成する。
"a" 追加モード。すでにファイルがあればその最後に追加し、なければ新たに作成する。
"r+" 更新モード。ファイルが存在しているとする。
"w+" 更新モード。すでにファイルがあれば内容を削除し、なければ新たに作成する。
"a+" 追加更新モード。すでにファイルがあればその最後に追加し、なければ新たに作成する。
 以上ですが、試す環境がございませんので、よろしくお願いいたします。

Aベストアンサー

お書きのとおりで合ってますよ。大丈夫です。

Q&str[n]とpstr + nと&pstr[n]

あるプログラミングの本で

&str[n]
pstr + n
&pstr[n]

は同じだと書いてあり、考えたのですが、
上の二つはstr[n]のアドレスを表しているとしても、
三つ目はstr[n]のポインタのアドレスを表していると思うのですが
どこが間違っているのでしょうか?教えてください。

Aベストアンサー

>本にも突然でてきているのでよくわからないのですが・・・。

よくわからないもの同士が同じかと聞かれても、よくわからないというのが答えです。
本当に、突然出てきているのなら、そんな本は捨てましょう。

Qchar *name1[4] とchar name2[][4] の違いについて

C言語のことで質問があります。

char *name1[4]は
char *name1[4] = {"abcdefghi","jkl","l","mn"};
と宣言でき,ポインタを4つ確保した形となりました。

char name2[][4]は
char name2[][4] = {"abc","def","ghi","jkl","mno","pqr","stu","vwx"};
と4文字以内の文字列を初期化した数だけ確保した形となりました。

この結果からchar *name1[4]の意味は,char name2[][4]ではなくchar name2[4][]に近いと思いました。
しかし,char name2[4][]ではポインタを4つ確保した事にはならないみたいでコンパイルが通りません。
*name1[4]では4つのポインタを確保できるのに~と思ってしまいます。

ポインタと配列は別物と考えるべきなのでしょうか?
訳の分からない質問かもしれませんが,
何卒ご指導いただくようよろしくお願いします。

Aベストアンサー

ポインタと配列の違いというのは、変数と定数の違いのようなものです。

話を簡単にするために、一次元配列から考えましょう。

char *p1; と定義した時のp1は、いうまでもなくポインタで、
これは変数です。p1は任意の文字列を指すことができます。
char a1[4]; と配列の形で定義した場合のa1については、
a1[0]やa1[1]等を、通常のchar型の変数と全く同じように扱うことが
できます。しかし、a1自体は、例えば a1 = p1; のように値を代入する
ことができません。(逆の p1 = a1; は可能。)つまり、この場合のa1は、
変数ではなく、定数のようなものなのです。

複合的なケースについて見てみましょう。
char **q1; ポインタへのポインタ
 q1,*q1,**q1,q1[0],*q1[0],q1[0][0] のいずれも変数として
 扱うことができます。(値を代入することが文法的に許されます。
 ただし、実行時にはアクセス違反になる場合もあります。)
char q2[4][4]; 二次元配列
 q2,q2[0]は変数として扱うことができません。q2[0][0]のように
 して、初めて変数として扱えるようになります。
char *q3[4]; ポインタの配列
 q3は変数として扱うことができませんが、q3[0],*q3[0],q3[0][0]
 はいずれも変数として扱うことができます。
 なお、この定義は char *(q3[4]); とした場合と全く同じ意味です。
char (*q4)[4]; 配列へのポインタ
 q4,(*q4)[0],q4[0][0]はいずれも変数として扱うことができます。
 しかし、*q4,q4[0]は変数として扱うことができません。

char *name1[4]; と char name2[4][]; は確かに似ています。しかし
違うところもあります。それは、name1[0] が変数として扱えるのに
対し、name2[0] には値を代入できないという点です。(データの
具体的な構造については、inthefloiさんが書いておられる通りです。
> char name2[4][]ではポインタを4つ確保した事にはならないみたい
というのも、全くその通りで、配列の定義では、ポインタ変数の領域
を確保する余地はないのです。

ポインタと配列の違いというのは、変数と定数の違いのようなものです。

話を簡単にするために、一次元配列から考えましょう。

char *p1; と定義した時のp1は、いうまでもなくポインタで、
これは変数です。p1は任意の文字列を指すことができます。
char a1[4]; と配列の形で定義した場合のa1については、
a1[0]やa1[1]等を、通常のchar型の変数と全く同じように扱うことが
できます。しかし、a1自体は、例えば a1 = p1; のように値を代入する
ことができません。(逆の p1 = a1; は可能。)つまり...続きを読む

Qfp = fopen(argy[1], "r");の[1]の意味は

https://oshiete.goo.ne.jp/qa/8940272.html
 の11行目に
fp = fopen(argv[1], "r");の[1]の意味が分かりません。
試したいのですが、ソフトがうまく動きません
 よろしくお願いいたします。

Aベストアンサー

前の例題も読みました。

大分苦戦しているようですが、配列については理解が進みましたでしょうか?
お答えしますと、最初のパラメータ文字列が代入されています。

古いC言語の約束でして大変有名なものです。

コマンドラインコンソールから実行ファイル名を書いて、
パラメータをスペースで区切って指定したとします。

このパラメータ文字列が[1]以降に入ります。
例として、"test"と言う名前の実行ファイルがあったとします。

例)> test test1 test2 3 4

このようにコマンドラインから入力し実行すると、

argc = 5
argv[0] = "test"
argv[1] = "test1"
argv[2] = "test2"
argv[3] = "3"
argv[4] = "4"

と文字列が入ってきます。

以下はサンプル。

void main( int argc , char *argv[])
{
if( argc < 2 )
{
// パラメータ指定がなかった場合の表示
printf( "test に続けて4つまでパラメータを入力できます\n");
exit(0);
}
if( argc > 5 )
{
 // パラメータが5つ以上あった場合の表示
printf( "5つ以上のパラメータは受け付けません\n");
exit(-1);
}

// 正常ルート
printf( "パラメータの数は%d個ですね?ニヤッ\n", argc-1);
printf( "最初のパラメータは%sでしょ?\n", argv[1]);
printf( "残りはargv[2]以降ですが、面倒なので表示しません\n");
}

と言う具合に、引数を活用できます。argv[0]には、実行ファイル名が入ります。
argc は実行ファイルの名前も含めてカウントされます。

プログラムによっては必要な引数の数が変わりますし、
ユーザーのコマンドラインからの入力ミスなどでパラメータがなかったり、
必要なパラメータが不足していたりしますので、
argcとargvを使って最初にシンタックスエラーチェックをするのが常道です。

実行ファイル名の指定がなく、プログラムが実行されることはないと思われます
から、argcは1以上の値になります。

argc, argvの活用は、
実行コマンドを手打ちで打ち込むコンソール形式でよく用いられる基本的な
アプリケーションの開発手法です。

ご質問の箇所は、
第一パラメータにプログラム内で読み込むファイルのファイル名を指定してるの
でしょう。(よくあります)

しかし、Windowsなどのウィンドウを使用するアプリケーションは、
これとは違っておりますので注意が必要です。
(C言語とは別に、Windowsに特化した開発ノウハウの勉強が必要です)

Windows系で上記の様な基本的なプログラムを作成する場合は、
プロジェクトの作成時に(VisualStudioなどで)コンソールアプリケーション
を選んで作成します。実行時にコンソールが開きます。

Linuxの場合は、コンソールがデフォルトになっているでしょうから、
(特殊な設定がなければ)そのまま作成できます。

テキストエディタでソースを記述し、gcc などでコンパイルします。
実行形式ファイルが出来ていれば、想定どおりの動作をするでしょう。

ファイルの読み込みが出来るようになったら、
ファイルの内容を書き換えて保存したり、
ファイル名を変えたり、
ディレクトリ内のファイルを全て表示したり、
ファイル内に含まれる文字列を検索し、該当するファイルをリストしたりなど、

有用なサンプルプログラムを沢山作って練習します。

ファイルを読み込む先は、char型の配列でバイトサイズのメモリーとして確保
します。メモリーと変数の関係を充分に理解することをお勧めします。
殆どのプログラムは、このメモリーの確保やメモリーサイズの計算と格闘する
場合が多くなるからです。

バイナリー形式のファイル(すべてはバイナリー形式として良いのですが)に
ついて理解が深まった後は、
bmpの画像ファイル、wavなどの音声ファイルをあけて、
これの中身を書き換えて遊びます。

特にwavファイルは、音量の変更や周波数フィルタなども掛けれますので、
メモリ、配列、ファイルの関係を(焦らずに)ゆっくり理解するだけで、
今の知識レベルでも面白いことが沢山出来ます。

以上、ご参考に成れば。

前の例題も読みました。

大分苦戦しているようですが、配列については理解が進みましたでしょうか?
お答えしますと、最初のパラメータ文字列が代入されています。

古いC言語の約束でして大変有名なものです。

コマンドラインコンソールから実行ファイル名を書いて、
パラメータをスペースで区切って指定したとします。

このパラメータ文字列が[1]以降に入ります。
例として、"test"と言う名前の実行ファイルがあったとします。

例)> test test1 test2 3 4

このようにコマンドラインから...続きを読む

Qchar c = 'a'; char h[1] = c; エラー

char型のものを char[]型に代入したいです。

char c = 'a';
char h[1] = c;

として、

h[0] は \x97
h[1] は \x00

にしたいです。
型変換の方法を教えてください。

Aベストアンサー

とりあえず、確認を。

C では、'a'の表す値は 0x61 = 97 であって、 \x97 ではないと思います。
(\xnnn を、十六進数の意味に取りましたが、あってますでしょうか?
この場合、C では通常 0xnnn のように書くと思います。)
ので、 これは 0x61 のことをおっしゃっていると仮定します。

> char h[1] = c;
っと、これではたぶんコンパイルが通りません。

char h[1] = {c};

のように、配列であることを明示して代入してください。
この式では、前半でh という名前の、*長さ1 の* char の配列変数を確保します。
後半で、その中を初期化しています。
添え字は 0 からはじまるので、この場合、h[0] に c の内容が代入されます。
1個しか場所を確保していないので、 h[1] の位置のデータは内容が不定です。
文字列として h を扱いたいのであれば、 C の文字列には終端として 0 が必要ですから、
char c = 'a';
char h[2] = { c, '\0'};

のような書き方が必要になります。
これで、お望みのデータになると思います。

とりあえず、確認を。

C では、'a'の表す値は 0x61 = 97 であって、 \x97 ではないと思います。
(\xnnn を、十六進数の意味に取りましたが、あってますでしょうか?
この場合、C では通常 0xnnn のように書くと思います。)
ので、 これは 0x61 のことをおっしゃっていると仮定します。

> char h[1] = c;
っと、これではたぶんコンパイルが通りません。

char h[1] = {c};

のように、配列であることを明示して代入してください。
この式では、前半でh という名前の、*長さ1 の* char の配列変数...続きを読む


人気Q&Aランキング

おすすめ情報