プロが教える店舗&オフィスのセキュリティ対策術

Cで作ったプログラムなのですが最後の部分でファイルに出力すると数字が
文字化けして出てきます(‰など)その原因を教えて頂ければ嬉しいです
他にも何かあれば教えてください
プログラミングは詳しくないのでゴロゴロ見つかるかもしれません

【プログラム】
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>

int a,i,j,k,t;
double p,p1,b;
int X[999][1000],Y[999][1000];
int s0,s1,delta;

int main(void)
{
int**X = calloc(sizeof(int),sizeof(int)*1000);
int**Y = calloc(sizeof(int),sizeof(int)*1000);
FILE *output;
output=fopen("monte.dat","w");
b = 0.01; /*逆温度*/
srand((unsigned int)time(0));

/*メモリの確保*/
if( X == NULL ){
exit( EXIT_FAILURE );
}
for(i=0; i<=999; ++i){ /* 各列分の領域を割り当てる */
X[i] = (int*)calloc(sizeof(int),sizeof(int)*1000);
}

if( Y == NULL ){
exit( EXIT_FAILURE );
}
for(i=0; i<=999; ++i){ /* 各列分の領域を割り当てる */
Y[i] = (int*)calloc(sizeof(int),sizeof(int)*1000);
}
/*終わり*/

/*初期配列の設定*/
for(i=0;i<1000;i++){
X[0][i]=a;
a = (int)((rand() / ((double)RAND_MAX+1.0)) * 2);//debag
}
/*終わり*/

for(t=0;t<2;t++){ //debag
/*配列中a番目を抽出*/
a = 10; //debag
/*終わり*/

/*a番目のスピンを逆にした配列作成*/
for(j=0;j<1000;j++){
Y[t][j] = X[t][j];
}
Y[t][a] = (X[t][a]+1)%2;
/*終わり*/

/*遷移確率p1計算*/
s0=0;
s1=0;
for(k=0;k<1000;k++){
s0=s0+pow(-1,X[t][k]+X[t][k+1]);//(11),(00)なら値1
s1=s1+pow(-1,Y[t][k]+Y[t][k+1]);//(10),(01)なら値-1
}
delta = -s1 + s0;
p1 = 0.5 * (1 - tanh(0.5 * b * delta));
printf("%d %d %d %f ",s0,s1,delta,p1); //←この時点ではX[t][]は正しく出力する
/*終わり*/

/*新しい配列(i番目の符号を交換するか)*/
p = (double)((rand() / ((double)RAND_MAX+1.0)) * 1);
for(j=0;j<1000;j++){
X[t+1][j] = X[t][j];
}
if(p<=p1){
X[t+1][a] = (X[t][a]+1)%2;
printf("交換したよ! %d → %d\n",X[t][a],X[t+1][a]);
}
else{
X[t+1][a] = X[t][a];
printf("交換しないよ!\n");
}
/*終わり*/
}
/*記入*/
for(i=0;i<1000;i++){
fprintf(output,"%d ",X[0][i]); //←ここが文字化けする
}
fprintf(output,"\n");
for(i=0;i<1000;i++){
fprintf(output,"%d ",Y[0][i]); //←出力されない
}
/*終わり*/

fclose(output);
return 0;
}
【プログラム終】

A 回答 (4件)

>int**X = calloc(sizeof(int),sizeof(int)*1000);


>int**Y = calloc(sizeof(int),sizeof(int)*1000);
>for(i=0; i<=999; ++i){ /* 各列分の領域を割り当てる */
>X[i] = (int*)calloc(sizeof(int),sizeof(int)*1000);
>}
>for(i=0; i<=999; ++i){ /* 各列分の領域を割り当てる */
>Y[i] = (int*)calloc(sizeof(int),sizeof(int)*1000);
>}

上記の行は、何のためにあるのでしょうか?
関数の外で定義してある

>int X[999][1000],Y[999][1000];

との整合性はどうなっていますか?

この回答への補足

配列X,Yの要素数を大きく取りたいので配列のためにメモリを確保しようとしてます
外の定義は初め抜いていたのですがエラーになるのでやむなく付け足しました

補足日時:2011/05/04 12:38
    • good
    • 0
この回答へのお礼

書くところを間違った・・・ すみません
解答ありがとうございます

お礼日時:2011/05/04 12:48

少なくとも、手許で実験するかぎりでは文字化けはしませんが。


本当に monte.txt の中が文字化けしているのですか?
> printf("交換したよ! %d → %d\n",X[t][a],X[t+1][a]);
> printf("交換しないよ!\n");
画面に表示されるこっちじゃないですか?
    • good
    • 0
この回答へのお礼

あら、本当ですか
自分のところでは何度やってもmonte.dat内が
‰‱‰‰‱‱‰‰‰‱‰‱‰‱‱‱‰(略 となります
画面の方はちゃんと動作してます

お礼日時:2011/05/04 13:36

これが何をやっているプログラムなのか、私にはわかりませんが、


『とにかく大きなメモリを確保する』という方法は、気付かぬバグを内包する元です。

mainの外で、X,Yにそれぞれ約1M*intのサイズ(私の環境では2MByte)程の領域を確保しています(int X[999][1000])が、mainの中で、int1000個分のサイズのメモリをintサイズ分(私の環境では4MByte)確保(int **X=calloc~)しています。さらに、『int1000個分のメモリをintサイズ分』を1000個確保(/*各配列の領域を*/の部分)しそのポインタをXに並べています。(私の環境では、4M)



それでいて、XとYは、直接intの配列として使われています。X,Yは、2×1000の配列として使っているようですが、一部疑問があります。メモリをふんだんに確保しているので、エラーにはなっていませんが、

 s0=s0+pow(-1,X[t][k]+X[t][k+1]);//(11),(00)なら値1
 s1=s1+pow(-1,Y[t][k]+Y[t][k+1]);//(10),(01)なら値-1
の「k+1」の部分は、意図したとおりですか?X[t][1000]をアクセスしてしまいますが、大丈夫ですか?

また、
 X[t+1][j] = X[t][j];
の部分も、「X[2][j]」をアクセスしてしまいますが、大丈夫ですか?

文字化けに関しては、ウチでも一応表示していますので、(「0」か「1」の羅列ですよね?)環境を提示するといいと思います。
たぶん、先に書いたメモリ確保、X,Yの定義などの問題では?
    • good
    • 0
この回答へのお礼

モンテカルロ法で1次元イジングモデルを熱浴法を用いて解こうとしてこんなのが出来ました(手元には疑似コードが載った資料があるくらいです)

定義が二重になっていてメモリを食っているのは理解できました。またfor文内のアクセスについては間違ってますね。ご指摘ありがとうございます。

monte.datには0と1の羅列が出ればひとまず成功です
自分の環境としては
Win7,RAM=4M,
コンパイラ:Borland C++ Compiler 5.5
プログラム作成に"C言語を始めよう!"というソフトを用いています

お礼日時:2011/05/04 14:00

よくみたら。


> int**X = calloc(sizeof(int),sizeof(int)*1000);
> int**Y = calloc(sizeof(int),sizeof(int)*1000);
> X[i] = (int*)calloc(sizeof(int),sizeof(int)*1000);
> Y[i] = (int*)calloc(sizeof(int),sizeof(int)*1000);

callocのマニュアルは読んでますか?
calloc( 確保したい要素数, 1要素あたりのサイズ ) ;
です。
これだと、 1要素sizeof(int)*1000 x sizeof(int)個 だけの領域を確保します。

> int**X = calloc(sizeof(int),sizeof(int)*1000);
の方では int * を 1000個
> X[i] = (int*)calloc(sizeof(int),sizeof(int)*1000);
の方では int を1000個 確保したいんですよね?
マニュアルに従えば
int**X = calloc(1000,sizeof(int *));
X[i] = calloc(1000,sizeof(int));
で必要数だけ確保できます。

多く確保することができたのなら、メモリーリーク等の致命的なエラーになるケースは少ないです。
ですが、メモリ自体が少なければ、そもそもの確保に失敗する場合があります。

適切に確保するのと、エラーチェックすることを心掛けましょう。
for(i=0; i<=999; ++i){ /* 各列分の領域を割り当てる */
X[i] = calloc(1000,sizeof(int));
if ( X[i] == NULL ) {
exit( EXIT_FAILURE );
}
}


ただ、これと文字化けとは直接関係無いと思います。
%dで変換して出力しているので、引数がどんな値でも0123456789-以外の文字は出力していないはずです


> 配列X,Yの要素数を大きく取りたいので配列のためにメモリを確保しようとしてます
外の配列X,Yと、mainの中のX,Yは別です。
int** Xとすることで、main関数の中だけで有効なローカル変数として宣言されています。
また、callocで確保される領域とも関係ないです。
よって、このプログラムではまったく意味を為していません。

>外の定義は初め抜いていたのですがエラーになるのでやむなく付け足しました

エラーになるのは
> int a,i,j,k,t;
> double p,p1,b;
> int s0,s1,delta;
ここまで削っているからではないですか?
これらの変数がここでしか宣言されていないからではないでしょうか
    • good
    • 0
この回答へのお礼

>外の配列X,Yと、mainの中のX,Yは別
なるほど その当たり良く分っていませんでした

callocの所はネットで調べたものを放り込んでいます^^;
分かって使わないといけませんね・・・

文字化けについては皆さんのところだと問題ないようでひとまず安心です 一旦締め切りますがまた質問があった時は皆様解答よろしくお願いします

訂正;メモリは4GBです

お礼日時:2011/05/04 17:41

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