異なる乱数列を複数生成するプログラム

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
random

異なる乱数列を複数生成するプログラム

#1

投稿記事 by random » 13年前

プログラムを初めて1年未満の初心者です。
異なる乱数列を複数個生成するプログラムを作っています。
入力nとmをそれぞれ列数と個数として、数字、大英文字、小英文字の乱数を出力させます。
ここまでのプログラムはできました。
さらに、この列がそれぞれ違う列になりm通りのものとなっているように変更したいです。
aaaa1とaaaa2など、一文字でも違えば、違うものの扱いとします。

コード:

 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int makeRand(int min,int max){						//乱数生成
	return min+(int)(rand()*(max-min+1.0)/(1.0+RAND_MAX));
}

main(void){
int i, j;
int n, m;

while(1){
   printf("n=");scanf("%d",&n);						//文字列n
   if(n==0){break;}
   else{printf("m=");scanf("%d",&m);}					//文字列の数m
   for(i=0;i<m;i++){
	for(j=0;j<n;j++){
		int sw,Num,Large,Small;
		char pass[j][i];
		sw = makeRand(1,3);
		switch(sw){
			case 1:						//数字
				Num = makeRand(0,9);
				printf("%c",Num+48);
				pass[j][i] = Num+48;
				break;
			case 2:						//大文字
				Large = makeRand(0,25);
				printf("%c",Num+65);
				pass[j][i] = Num+65;
				break;
			case 3:						//小文字
				Small = makeRand(0,25);								printf("%c",Num+97);
				pass[j][i] = Num+97;
				break;
		}
	}
    	printf("\n");
    }
}
return 0;
}


2次元配列をつくり、すべての配列がそれぞれ一致すれば乱数を作り直す、という関数を作ろうとしました。
が、頭の中で混乱してしまったのと、もっと良い方法がないかと思い、スレッドを作らせていただきました。
ご意見よろしくお願いします。

Ryo

Re: 異なる乱数列を複数生成するプログラム

#2

投稿記事 by Ryo » 13年前

1.
「長さがn文字分の文字列」をm種類作成する
と考えれば、文字列と文字列の比較となって、簡単にできます

2.
すべてを生成してから比較するのではなく、
一つの文字列を生成したら、すでに作ってあるものとかぶっていないか?を比較し
かぶっていたら、再生成。
かぶっていなかったら保存
ということをm回繰り返すのがいいと思います。

random

Re: 異なる乱数列を複数生成するプログラム

#3

投稿記事 by random » 13年前

返信ありがとうございます。
文字列を比較ということなのですが、
文字列をひとまとめとして比較することは可能なのでしょうか?
例えば
pass[0][0]=1,pass[0][1]=A,pass[0][2]=b
という配列を「p=1Ab」といったように一つの変数で文字列を表すことはできるのでしょうか?
ネット検索をしてみたのですがでてこなかったので、再度質問させて頂きました。

beatle
記事: 1281
登録日時: 13年前
住所: 埼玉
連絡を取る:

Re: 異なる乱数列を複数生成するプログラム

#4

投稿記事 by beatle » 13年前

文字列の比較にはstrncmpが使えます.
strncmp(pass[0], pass[1], n);
とすればpass[0][0], pass[0][1], ... , pass[0][n - 1]とpass[1][0], pass[1][1], ... , pass[1][n - 1]の比較ができます,

random

Re: 異なる乱数列を複数生成するプログラム

#5

投稿記事 by random » 13年前

ありがとうございます。
beatleさんのご意見を参考に、今までの文字列と比較を行う関数checkを作成し、同じ列があれば繰り返すように
while文を追加しました。
実行してみたところ、空白が出力されてしまいました。その後色々変更してみたものの、改善点がわかりませんでした。
何かありましたらお願いします。

コード:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

int makeRand(int min,int max){						//乱数生成
	return min+(int)(rand()*(max-min+1.0)/(1.0+RAND_MAX));
}

int check(int i, int n, char *pass){					//追加
int k;
	for(k = i; k < 0; i--){		
		if(strncmp(pass[i],pass[k-1],n) != 0){
		   break;
		}else if(strncmp(pass[i],pass[k-1],n) == 0){
		   return 0;
		}
	}
	return 1;
}

main(void){
int i, j, k;
int n, m;

while(1){
   printf("n=");scanf("%d",&n);						//文字列n
   if(n==0)exit(-1);
   else{printf("m=");scanf("%d",&m);}					//文字列の数m
   char pass[n][m];
   for(i=0;i<m;i++){
	for(j=0;j<n;j++){
	    while(check(i,n,pass)==0){       //追加部分
		int sw,Num,Large,Small;
		sw = makeRand(1,3);
		switch(sw){
			case 1:						//数字
				Num = makeRand(0,9);
				printf("%c",Num+48);
				pass[j][i] = Num+48;
				break;
			case 2:						//大文字
				Large = makeRand(0,25);
				printf("%c",Num+65);
				pass[j][i] = Num+65;
				break;
			case 3:						//小文字
				Small = makeRand(0,25);				
				printf("%c",Num+97);
				pass[j][i] = Num+97;
				break;
		}
	   }
	}
    	printf("\n");
    }
}
return 0;
}

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 異なる乱数列を複数生成するプログラム

#6

投稿記事 by みけCAT » 13年前

コード:

int check(int i, int n, char *pass){                    //追加
int k;
    for(k = i; k < 0; i--){     
        if(strncmp(pass[i],pass[k-1],n) != 0){
           break;
        }else if(strncmp(pass[i],pass[k-1],n) == 0){
           return 0;
        }
    }
    return 1;
}
最初のk==iの時、必ずbreak;してreturn 1;するか、もしくはreturn 0;するかとなり、
ループの意味が無いように見えますが、意図した動作ですか?
for文の動作と条件も不自然に見えます。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

random

Re: 異なる乱数列を複数生成するプログラム

#7

投稿記事 by random » 13年前

コード:

int check(int i, int n, char *pass){				
int k;
	for(k = i; k < 0; i--){		
		if(strncmp(pass[i],pass[k-1],n) == 0){
		   return 0;
		}
	}return 1;
}
ありがとうございます。
同じ文字列があれば0を返し、ループが最後まで終わった時点で1を返すように変更しました。

出てくる警告文が
In function `check':
警告: 引数 1 個の `strncmp' を渡しますにより、キャストなしで整数からポインタを作りました
警告: 引数 2 個の `strncmp' を渡しますにより、キャストなしで整数からポインタを作りました
In function `main':
警告: 互換性のないポインタ型からの引数 3 個の `check' を渡しますです
と出てくるのですが、よく意味が分かりません。
配列のところに何か不備があるのでしょうか。

beatle
記事: 1281
登録日時: 13年前
住所: 埼玉
連絡を取る:

Re: 異なる乱数列を複数生成するプログラム

#8

投稿記事 by beatle » 13年前

passはchar*型ですので,passとpass[k-1]はchar型になります.(つまり,1文字を表します)
しかしstrncmpは引数として文字列を取りますから,char*型の値を渡す必要があります.
char*型にchar型を無理やり入れようとして警告が出ています.
char型は整数,char*型はポインタなので,整数からポインタを作りました,と言われているのです.

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 異なる乱数列を複数生成するプログラム

#9

投稿記事 by みけCAT » 13年前

コード:

for(k = i; k < 0; i--){
上のプログラムを見ると、iには正の値か0が格納されているようです。
しかし、この条件では、まずkにi(>=0)を代入し、直後にk<0の判定をしているため、
その時点でループには入らず、必ずreturn 1;されると思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

random

Re: 異なる乱数列を複数生成するプログラム

#10

投稿記事 by random » 13年前

詳しく解答ありがとうございます。
関数checkはうまく作れました。

しかし実行してみたところ、33行目のwhile文のループが抜け出さなくなり永遠に出力してしまう、という状況になりました。
また、

コード:

	    while(check(i,n,m,pass[n][m])==0){
		int sw,Num,Large,Small;
		sw = makeRand(1,3);
		switch(sw){
			case 1:						//数字
				Num = makeRand(0,9);
				printf("%c",Num+48);
				pass[j][i] = Num+48;
				break;
			case 2:						//大文字
				Large = makeRand(0,25);
				printf("%c",Num+65);
				pass[j][i] = Num+65;
				break;
			case 3:						//小文字
				Small = makeRand(0,25);
				printf("%c",Num+97);
				pass[j][i] = Num+97;
				break;
		}
		if(check(i,n,m,pass[n][m])==1)break;
	   }
のようにbreakを入れて、1のときはループを抜けるようにしてみると今度は空白が出力されるという状況になりました。
文字列が一緒のものを作りたくないので、このように関数をつくりwhile文を足したのですが、考え方が悪いのでしょうか。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 異なる乱数列を複数生成するプログラム

#11

投稿記事 by みけCAT » 13年前

random さんが書きました:関数checkはうまく作れました。
そのソースコードを貼り付けてください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

random

Re: 異なる乱数列を複数生成するプログラム

#12

投稿記事 by random » 13年前

みけCATさんのアドバイスをもとにforの中身を作りなおしました。

i列目の文字列と、それまでに格納していた文字列(i-1列目~0列目)を比較するようなループを作りたいのですが、
どうすればよかったのでしょうか。

コード:

int check(int i, int n,int m, char p[n][m]){					
int k;
	for(k = 0; k > i-2; i++){		
		if(strncmp(p[i],p[k],n) == 0){
		   return 0;
		}
	}return 1;
}
まだおかしいようなので、助言お願いします。

beatle
記事: 1281
登録日時: 13年前
住所: 埼玉
連絡を取る:

Re: 異なる乱数列を複数生成するプログラム

#13

投稿記事 by beatle » 13年前

for(k = 0; k > i-2; i++){
このfor文はこれでいいのですか?これだとkは0のまま変化しませんが.

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 異なる乱数列を複数生成するプログラム

#14

投稿記事 by みけCAT » 13年前

コード:

for(k = 0; k > i-2; i++){
この場合、ループの中でのiの値は、入力されるiが0以上の時、0、1のみです。
(ループの中でkを変更しない場合)
iが2以上の時、k>i-2が偽になるので、ループには入りません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

random

Re: 異なる乱数列を複数生成するプログラム

#15

投稿記事 by random » 13年前

お二人ともありがとうございます。

コード:

	for(k = 0; k > i-2; k++)
これで大丈夫でしょうか。
コアダンプとなってしまいました。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 異なる乱数列を複数生成するプログラム

#16

投稿記事 by みけCAT » 13年前

random さんが書きました:お二人ともありがとうございます。

コード:

	for(k = 0; k > i-2; k++)
これで大丈夫でしょうか。
コアダンプとなってしまいました。
iを増やさない限り、kがオーバーフローするまでの実質無限ループになってしまいます。
そのため、配列の添字にkを使っている場合、アクセス違反になりそうですね。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

beatle
記事: 1281
登録日時: 13年前
住所: 埼玉
連絡を取る:

Re: 異なる乱数列を複数生成するプログラム

#17

投稿記事 by beatle » 13年前

random さんが書きました:お二人ともありがとうございます。

コード:

	for(k = 0; k > i-2; k++)
これで大丈夫でしょうか。
コアダンプとなってしまいました。
自分でちゃんと考えてから投稿してますか?
今回のことでいうなら,自分の頭の中で,for文の動作を追いかけてますか,ということです.

まず,for文に到達するとkが0になりますよね.
次にk > i - 2が評価されます.
iを有り得そうな仮の値に固定しておき(例えば0とか1とか),そのiの値を使ってk > i - 2が成り立つかなーと調べます.
k > i - 2が成り立つならfor文の中身が実行されて,最後にk++されます.
するとこの時点でkは1です.
またk > i - 2が評価されます.k > i - 2が成り立つかなーと調べます.
成り立つならfor文の中身が実行されて,最後にk++されます.
...

という具合に,自分の頭の中で実験するんです.
実験して,でもやっぱり分からない場合にのみ,質問します.
「私の考えでは,この部分がこうなるはずなのですが,実際はこうなってしまいます」などと,脳内実験により得た結果と実際の結果が異なる,ということを書くと,良い質問になります.
自分で脳内実験もしていないのに(脳内実験してたらごめんなさい),これでいいですか,と質問するのは,丸投げしてるようなものですよ.C言語力も上がりません.

そして,今回の質問「for(k = 0; k > i-2; k++)で良いですか」は,脳内実験をしていればおのずと「ダメ」なことが分かる質問であると思います.

random

Re: 異なる乱数列を複数生成するプログラム

#18

投稿記事 by random » 13年前

すみません。頭が混乱してしまい、少し丸投げしていたかもしれないです。
みけCAT さんが書きました: iを増やさない限り、kがオーバーフローするまでの実質無限ループになってしまいます。
そのため、配列の添字にkを使っている場合、アクセス違反になりそうですね。
iを増やすという意味がよく理解できないので、もう少し詳しく説明いただけないでしょうか。

少しまた変えました。

コード:

	for(k = i; k > 0; k--){		
		if(strncmp(p[i],p[k-1],n) == 0){
		   return 0;
		}
脳内では、例えばiが4の場合、
最初にkは4であるから、4列と3列目を比較する。
kは0以上でkを減らす。
次にkは3であるから、4列目と2列目を比較する。
次にkは2であるから、4列目と1列目を比較する。
次にkは1であるから、4列目と0列目を比較する。
結果的にi列目と0からi-1列目をそれぞれ順番に比較するものを作ったつもりです。

beatle
記事: 1281
登録日時: 13年前
住所: 埼玉
連絡を取る:

Re: 異なる乱数列を複数生成するプログラム

#19

投稿記事 by beatle » 13年前

random さんが書きました:iを増やすという意味がよく理解できないので、もう少し詳しく説明いただけないでしょうか。
iを増やさなければならないというのは
for(k = 0; k > i-2; k++)
に対する回答でした.

もし,iが0または1なら,このfor文はkがint型の最大値まで増え続けます.なぜなら,i==0のとき
for(k = 0; k > -2; k++)
と同じだからです.kは(オーバーフローしない限り)減ることはありませんので,k > -2は常に成り立ちます.

だからみけCATさんは
「i(の値)を増やさない限り、kがオーバーフローするまでの実質無限ループになってしまいます。」
と書いたのです.
random さんが書きました:少しまた変えました。

コード:

	for(k = i; k > 0; k--){		
		if(strncmp(p[i],p[k-1],n) == 0){
		   return 0;
		}
脳内では、例えばiが4の場合、
最初にkは4であるから、4列と3列目を比較する。
kは0以上でkを減らす。
次にkは3であるから、4列目と2列目を比較する。
次にkは2であるから、4列目と1列目を比較する。
次にkは1であるから、4列目と0列目を比較する。
結果的にi列目と0からi-1列目をそれぞれ順番に比較するものを作ったつもりです。
はい,良いと思いますが,何を質問なさっているのでしょうか.
作ったよ!っていう報告でしょうか.

random

Re: 異なる乱数列を複数生成するプログラム

#20

投稿記事 by random » 13年前

頭で整理できなくなったので出直します。
みなさんありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る