ページ 1 / 1
異なる乱数列を複数生成するプログラム
Posted: 2012年1月14日(土) 18:15
by random
プログラムを初めて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次元配列をつくり、すべての配列がそれぞれ一致すれば乱数を作り直す、という関数を作ろうとしました。
が、頭の中で混乱してしまったのと、もっと良い方法がないかと思い、スレッドを作らせていただきました。
ご意見よろしくお願いします。
Re: 異なる乱数列を複数生成するプログラム
Posted: 2012年1月14日(土) 20:21
by Ryo
1.
「長さがn文字分の文字列」をm種類作成する
と考えれば、文字列と文字列の比較となって、簡単にできます
2.
すべてを生成してから比較するのではなく、
一つの文字列を生成したら、すでに作ってあるものとかぶっていないか?を比較し
かぶっていたら、再生成。
かぶっていなかったら保存
ということをm回繰り返すのがいいと思います。
Re: 異なる乱数列を複数生成するプログラム
Posted: 2012年1月14日(土) 22:17
by random
返信ありがとうございます。
文字列を比較ということなのですが、
文字列をひとまとめとして比較することは可能なのでしょうか?
例えば
pass[0][0]=1,pass[0][1]=A,pass[0][2]=b
という配列を「p=1Ab」といったように一つの変数で文字列を表すことはできるのでしょうか?
ネット検索をしてみたのですがでてこなかったので、再度質問させて頂きました。
Re: 異なる乱数列を複数生成するプログラム
Posted: 2012年1月14日(土) 23:44
by beatle
文字列の比較には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]の比較ができます,
Re: 異なる乱数列を複数生成するプログラム
Posted: 2012年1月15日(日) 10:26
by random
ありがとうございます。
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;
}
Re: 異なる乱数列を複数生成するプログラム
Posted: 2012年1月15日(日) 13:03
by みけCAT
コード:
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文の動作と条件も不自然に見えます。
Re: 異なる乱数列を複数生成するプログラム
Posted: 2012年1月16日(月) 21:04
by random
コード:
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' を渡しますです
と出てくるのですが、よく意味が分かりません。
配列のところに何か不備があるのでしょうか。
Re: 異なる乱数列を複数生成するプログラム
Posted: 2012年1月16日(月) 21:17
by beatle
passはchar*型ですので,passとpass[k-1]はchar型になります.(つまり,1文字を表します)
しかしstrncmpは引数として文字列を取りますから,char*型の値を渡す必要があります.
char*型にchar型を無理やり入れようとして警告が出ています.
char型は整数,char*型はポインタなので,整数からポインタを作りました,と言われているのです.
Re: 異なる乱数列を複数生成するプログラム
Posted: 2012年1月16日(月) 21:30
by みけCAT
コード:
for(k = i; k < 0; i--){
上のプログラムを見ると、iには正の値か0が格納されているようです。
しかし、この条件では、まずkにi(>=0)を代入し、直後にk<0の判定をしているため、
その時点でループには入らず、必ずreturn 1;されると思います。
Re: 異なる乱数列を複数生成するプログラム
Posted: 2012年1月16日(月) 21:41
by random
詳しく解答ありがとうございます。
関数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文を足したのですが、考え方が悪いのでしょうか。
Re: 異なる乱数列を複数生成するプログラム
Posted: 2012年1月16日(月) 21:57
by みけCAT
random さんが書きました:関数checkはうまく作れました。
そのソースコードを貼り付けてください。
Re: 異なる乱数列を複数生成するプログラム
Posted: 2012年1月17日(火) 00:04
by random
みけ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;
}
まだおかしいようなので、助言お願いします。
Re: 異なる乱数列を複数生成するプログラム
Posted: 2012年1月17日(火) 07:58
by beatle
for(k = 0; k > i-2; i++){
このfor文はこれでいいのですか?これだとkは0のまま変化しませんが.
Re: 異なる乱数列を複数生成するプログラム
Posted: 2012年1月17日(火) 13:46
by みけCAT
コード:
for(k = 0; k > i-2; i++){
この場合、ループの中でのiの値は、入力されるiが0以上の時、0、1のみです。
(ループの中でkを変更しない場合)
iが2以上の時、k>i-2が偽になるので、ループには入りません。
Re: 異なる乱数列を複数生成するプログラム
Posted: 2012年1月17日(火) 14:24
by random
お二人ともありがとうございます。
コード:
for(k = 0; k > i-2; k++)
これで大丈夫でしょうか。
コアダンプとなってしまいました。
Re: 異なる乱数列を複数生成するプログラム
Posted: 2012年1月17日(火) 14:33
by みけCAT
random さんが書きました:お二人ともありがとうございます。
コード:
for(k = 0; k > i-2; k++)
これで大丈夫でしょうか。
コアダンプとなってしまいました。
iを増やさない限り、kがオーバーフローするまでの実質無限ループになってしまいます。
そのため、配列の添字にkを使っている場合、アクセス違反になりそうですね。
Re: 異なる乱数列を複数生成するプログラム
Posted: 2012年1月17日(火) 15:30
by beatle
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++)で良いですか」は,脳内実験をしていればおのずと「ダメ」なことが分かる質問であると思います.
Re: 異なる乱数列を複数生成するプログラム
Posted: 2012年1月18日(水) 00:14
by random
すみません。頭が混乱してしまい、少し丸投げしていたかもしれないです。
みけ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列目をそれぞれ順番に比較するものを作ったつもりです。
Re: 異なる乱数列を複数生成するプログラム
Posted: 2012年1月18日(水) 07:18
by beatle
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列目をそれぞれ順番に比較するものを作ったつもりです。
はい,良いと思いますが,何を質問なさっているのでしょうか.
作ったよ!っていう報告でしょうか.
Re: 異なる乱数列を複数生成するプログラム
Posted: 2012年1月18日(水) 19:53
by random
頭で整理できなくなったので出直します。
みなさんありがとうございました。