ページ 1 / 1
再 ABCの乱数編
Posted: 2008年12月10日(水) 11:59
by しょしょしょしんしゃ
C言語 乱数と文字列
学校の宿題ですが
乱数を使用して、文字列を作成するのですが
分かりません。問題は以下のとおりです。
ランダムな文字列を作成する関数void passwd()作成
1、使用できる文字はアルファベット大文字のAからZ,小文字のaからzおよび数字の2から9の合計60文字。
2、文字列の長さは7文字から10文字のランダムに決められた値とする。
3、文字列に大文字・小文字・数字すべてが入っている文字列しか生成しない。
たとえば、E4F7ukYはいいが、kuh8ghandは大文字がないので、やり直しという風です。
分かりにくい部分がありますが、よろしくお願いします。
一応、条件1、2はクリアできたのですが、条件3のやり直しする部分をどのようにするか分かりません、
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main (void){
int nc;
char pwd[11];
int n;
char c;
int k;
char yn[2];
srand((unsigned)time(NULL));
nc = 7+rand()%4;
n = 0;
do{
k=rand()%3;
switch(k){
case 0:
c='2'+rand()%8;break;
case 1:
c='a'+rand()%26;break;
case 2:
c='A'+rand()%26;break;
}
pwd[n++] = c;
}while(n<nc);
pwd[n]='\0';
printf("生成されたパスワード:%s\n",pwd);
return 0;
}
Re:再 ABCの乱数編
Posted: 2008年12月10日(水) 12:07
by Mist
while(1) {
パスワード作成
完成したパスワードをチェック
→OK break;
}
でいいと思いますが。
Re:再 ABCの乱数編
Posted: 2008年12月10日(水) 12:26
by バグ
1:大文字から1文字を選択
2:小文字から1文字を選択
3:数字から1文字を選択
4:残り部分を大文字・小文字・数字から選択
5:シャッフル
でいいんでは?
この方法なら、文字列の判定が不要になり、その結果として、やり直す事も考慮する必要がなくなります。
Re:再 ABCの乱数編
Posted: 2008年12月10日(水) 13:01
by バグ
私が書き込みしたアルゴリズムで実装すると、こんな感じでしょうか?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
/* A~Zから1文字を取得する関数 */
char getAlphabetBig()
{
return 'A' + (char)(rand() % 26);
}
/* a~zから1文字を取得する関数 */
char getAlphabetSmall()
{
return 'a' + (char)(rand() % 26);
}
/* 2~9から1文字を取得する関数 */
char getNumber()
{
return '2' + (char)(rand() % 8);
}
/* A~Z、a~z、2~9の中から1文字を取得する関数 */
char getAllSymbol()
{
switch (rand() % 3)
{
case 0:
return getAlphabetBig();
case 1:
return getAlphabetSmall();
default:
return getNumber();
}
}
/* 文字列をシャッフルする */
void shuffleString(char* pwd)
{
char buf = '\0';
unsigned int i;
int swap;
for (i = 0; i < strlen(pwd); ++i)
{
/* ランダムに選択された箇所の文字と入れ替える */
swap = rand() % strlen(pwd);
buf = pwd;
pwd = pwd[swap];
pwd[swap] = buf;
}
}
int main(void)
{
char pwd[11] = {'\0', };
int i;
srand((unsigned)time(NULL));
/* 最初の3文字には大文字、小文字、数字を各1文字ずつ選択する */
pwd[0] = getAlphabetBig();
pwd[1] = getAlphabetSmall();
pwd[2] = getNumber();
/* 残りの7文字は大文字、小文字、数字の全ての中から選択する */
for (i = 3; i < 10; ++i)
{
pwd = getAllSymbol();
}
/* 文字列をシャッフルする */
shuffleString(pwd);
/* 文字列の表示 */
printf("生成されたパスワード:%s\n", pwd);
}
Re:再 ABCの乱数編
Posted: 2008年12月10日(水) 15:13
by lbfuvab
こんな感じですかね。(間違ってる可能性あり)
const char str[60]="qwertyuioplkjhgfdsazxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM23456789";
char GetBigAlpha(void){
return str[rand()%26];
}
char GetSmlAlpha(void){
return str[26+rand()%26];
}
char GetNum(void){
return str[52+rand()%8];
}
char GetRndCh(void){
return str[rand()%60];
}
int __cdecl RndCmp(void* a,void *b){
return (rand()%2)?1:-1;
}
void Password(char *buf){
int len=7+rand()%4,i=0;
buf[i++]=GetBigAlpha();
buf[i++]=GetSmlAlpha();
buf[i++]=GetNum();
for(;i<len;i++)
buf=GetRndCh();
qsort(buf,(size_t)len,sizeof(char),RndCmp);
}
Re:再 ABCの乱数編
Posted: 2008年12月10日(水) 16:14
by non
>たとえば、E4F7ukYはいいが、kuh8ghandは大文字がないので、
やり直しという風です。
やり直しって指示があるなら、やり直しした方がいいでしょう。
なるべく、本人が作った部分を壊さないように作りました。
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main (void)
{
int nc;
char pwd[11];
int n;
char c;
int k;
char yn[2];
unsigned char sw=0; //何が使われたかのスイッチ
srand((unsigned)time(NULL));
while(sw!=0x07){ // 3つのビットが1になるまで繰り返し
n=0;
nc = 7+rand()%4;
do{
k=rand()%3;
switch(k){
case 0:
sw |=0x01; // 0ビット目を1にする
c='2'+rand()%8;break;
case 1:
sw |=0x02; // 1ビット目を1にする
c='a'+rand()%26;break;
case 2:
sw |=0x04; // 2ビット目を1にする
c='A'+rand()%26;break;
}
pwd[n++] = c;
}while(n<nc);
pwd[n]='\0';
}
printf("生成されたパスワード:%s\n",pwd);
return 0;
}
Re:再 ABCの乱数編
Posted: 2008年12月10日(水) 16:31
by Mist
やり直したときのswの再初期化が抜けてると思う。
Re:再 ABCの乱数編
Posted: 2008年12月10日(水) 17:09
by non
あら、本当だ。失礼しました。
どこに入れれば、いいかはわかりますよね。
Re:再 ABCの乱数編
Posted: 2008年12月11日(木) 00:03
by しょしょしょしんしゃ
遅くなりましたが、
興味深い プログラムの例文ありがとうございました。
おかげ様
で 参考になりました。
また お願いします。
Re:再 ABCの乱数編
Posted: 2008年12月11日(木) 00:04
by しょしょしょしんしゃ
kaiketu
入れ忘れました。