二次元配列の動的確保、みなさんはどうしてますか?
大体用いられるのは、
a = (int **) malloc ( sizeof(int *) * Y );
for ( y=0; y<Y; y++ ) {
a[y] = (int *) malloc ( sizeof(int) * X );
}
という方法か(まぁこちらは不連続かつ遅いのであまり使わないですが)、
もしくは
a = (int ** ) malloc ( sizeof(int *) * Y );
a[0] = (int *) malloc ( sizeof(int) * Y * X );
for ( y=1; y<Y; y++ ) {
a[y] = a[y-1] + X;
}
という方法だと思います
しかし、これらの方法は関数化して
void **Malloc2D ( int row, int column );
という形にまとめることができません
昔は、型ごとにMalloc2D32fなどと名付けて作っていましたが、非常に無駄な気がします
何かうまい方法はありませんかね?
void **Malloc2D ( size_t s1, size_t s2, int r, int c )
{
void **a;
int i;
a = (void **) malloc ( s1 * r );
a[0] = (void *) malloc ( s2 * r * c );
for ( i=1; i<r; i++ ) {
a[i] = a[i-1] + c;
}
return a;
}
という意味ですか?
void型ポインタのままだとa[i] = a[i-1] + cが計算できないと思うのですが。。。
そこもsizeofの値を使って自分で計算すればいい。
#include <stdlib.h>
void **Malloc2D (size_t s, int r, int c )
{
void **a;
int i;
a = (void **) malloc (sizeof(void*) * r );
a[0] = (void *) malloc ( s * r * c );
for ( i=1; i<r; i++ ) {
a[i] = (char *)a[i-1] + c * s;
}
return a;
}
#include <stdio.h>
#define A 10
#define B 20
int main(){
int i, j;
int **a=(int **)Malloc2D(sizeof(int), A, B);
for (i=0; i<A; ++i)
for (j=0; j<B; ++j)
a[i][j]=i*B+j;
for (i=0; i<A; ++i){
for (j=0; j<B; ++j)
printf("%d ",a[i][j]);
printf("\n");
}
}
動作確認済み。
なお、データ型へのポインタはすべて同一サイズ同一内部表現と仮定。よってsizeofで渡す引数は1個でよい。(そもそもそうでないとこのやり方は通用しないような……)
データ型ポインタのサイズが同一サイズ同一内部表現というのは、
まぁ現実ではよくある話ですが、
Cで標準に定められてるわけではないですからどうかなぁ、と
それを認めるなら、以下の方法の方がmalloc(とfree)が一回で済むので良い気がします
「ポインタへのポインタ」と「ポインタ」の両方を一括でmallocして割り当ててるだけではありますが
void *Malloc2D ( const size_t size, const int row, const int column )
{
int i;
int t = size * column;
char **a;
char *b;
a = (char **) malloc ( (sizeof(char *)+t) * row );
if( a==NULL ) {
perror ( "malloc failed in Malloc2D" )
return NULL;
}
else {
b = (char *) ( a + row );
for ( i=0; i<row; i++, b+=t ) {
a[i] = b;
}
}
return a;
}
とりあえず書きます。
まず、大数の法則ですけど、サイコロにすると、"回数が多い程、各点数の出る回数(確率)が同じになるってこと。
証明するには、とりあえずサイコロを振って、各点数の出る回数を記録したらよい。
アルゴリズムも極に簡単、
(1) 各点数の出る回数を記録する配列を用意。 -> 例え、kaisu[6]
(2) (1)のモノを初期化(全てを0にする。
(3) 0~5の乱数を生成する。
(4) 出た乱数(点数)の回数を記録
(5) オマケに各点数の確率を計算
以上かな?
(3)と(4)はfor文で固定回数で走らせていい。一万回とか。
ありがとうございます!
やってみたんですけど
確率が0にしかなりません
コンパイルはできるんですけど‥
ソースのどこが間違ってるか
見ていただけたら嬉しいです
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
clock_t start,end;
start = clock();
int sai,i,x;
x=0;
srand((unsigned)time(NULL));
for(i=0;i<10000;i++)
{
sai=rand()%6+1;
if(sai==1){
x=x+1;
}
}
printf("確率%d\n",x/10000);
end=clock();
printf("%秒かかった\n",(double)(end-start)/CLOCKS_PER_SEC);
return 0;
}
ちなみに、配列を使って、次数を計算すると
int count[6];
/* 初期化 */
for(i=0;i<6;i++) count[i]=0;
。。。
/* 乱数を取る */
for(i=0;i<10000;i++){
sai=rand()%6;
count[sai]++;
}
。。。
saiで仲介のは面倒と思ったら
count[rand()%6]++;
にしよう。
配列の使いはCの基本だけど、多分少し無理したな。
僕が下手くそで教えるより、ウェブを参考しましょう
http://kzk9.net/column/time.html http://www.cppll.jp/cppreference/stddate_details.html つまり、clockを呼ぶと、今の時間はプログラムが開始してからどのくらい経過したのを教えてくれる。
そこで測ったのはクロック数。大体標準ではCLOCK_PER_SECで一秒間何クロックのを定義している。
故に、最初と最後のクロック数を測って、CLOCK_PER_SECで割ると最後の結果が出る。
ちなみに、単にクロック数をCLOCK_PER_SECで割るとint/intなので、嫌な結果が出る。
なので(end-start)を一度doubleにしてから、CLOCK_PER_SECで割る。
簡単に(end-start)/1.0/CLOCK_PRE_SECでも同じ答えが出る(はず)
もっと簡単な方法はlinuxのtimeコマンドを使うけど、windowsだとサポートしないね
はじめまして、Cを学習中に以下の疑問
が出まして、ネットや書籍で調査しましたが
解決に至らなかった為、本トピックを作成
させていただきました。
■質問内容
1.空白文字を _ に変換する処理の部分で実行時に
エラーが発生しています。
なぜ発生してしまうのかが全くわかりません。
2. *pc を 配列 pc[]にすると問題なく
実行できます。
なぜ配列だとうまくいくのかがわかりません。
■以下が、問題のソースです。
int main()
{
char *pc = "Hello World!\n";
/* 1.pc文字列の空白部分に_を入れる。 */
for ( i = 0; i < length; i++ ){
if( pc[i] == ' '){
pc[i] = '_'; /* 疑問箇所 */
}
}
}
基本的な事でもうしわけございませんが、
なにとぞ、ご教授の程よろしくお願いいたします。