OKWAVEのAI「あい」が美容・健康の悩みに最適な回答をご提案!
-PR-
解決
済み

C言語の基礎

  • 暇なときにでも
  • 質問No.212839
  • 閲覧数113
  • ありがとう数5
  • 気になる数0
  • 回答数5
  • コメント数0

お礼率 67% (55/82)

1.main関数の引数である、int argc と char **argvはどのように使用するのでしょうか?

2.特定の文字列(UserID)を入力し,それぞれの文字が使用可能文字列(数字とアルファベット(大文字小文字)と一致したら,使用可能文字列(配列)から削除し,残りの配列の文字を使って6~8文字のパスワードを作成するにはどのように関数を設計すればいいでしょうか?
パスワードを作成するのに時刻を種とした乱数を使用してある一文字を取得するという方法を考えました。
srand(unsigned time(NULL);
パスワードはUserIDに使用した文字を含まないようにしたいので,(使用可能文字列)-(UserID)= パスワードに使用できる文字列になると思うのですが,
配列-配列なんてできるのでしょうか?実力不足のため,変な質問をして申し訳ございません。どうかご教授ください。
通報する
  • 回答数5
  • 気になる
    質問をブックマークします。
    マイページでまとめて確認できます。

質問者が選んだベストアンサー

  • 回答No.5
レベル12

ベストアンサー率 48% (325/664)

この質問は参照URLの続きですよね?

こうしたほうがいいと言った立場上、答えさせていただきます。

あのアドバイスをしたとき、私の頭にあったのは次のようなソースでした。
(ちなみに、このソースは必要な処理を色々抜かしてある上、空白を全角で入力しているためそのままでは動きません。)

/*使用可能な文字テーブル:62だと乱数に偏りが出るため64にしてある*/
char g_acTable[64]; /*=10(数字)+26(大文字)+26(小文字)+2(穴埋め)*/

main( int argc, char** argv )
{
 int i;
 char szPassword[8]; /*パスワード格納スペース*/
 int nLength;    /*パスワードの文字列長*/
 int nCount=0;    /*処理中の文字が何文字目か?*/
 int nLetter;    /*文字候補がテーブルの何文字目か?*/

 /*使用可能な文字テーブルの初期化*/
 for(i=0;i<10;i++){
  g_acTable[i]='0'+i;
 }
 for(i=0;i<26;i++){
  g_acTable[i+10]='A'+i;
 }
 for(i=0;i<26;i++){
  g_acTable[i+36]='a'+i;
 }
 g_acTable[62]=g_acTable[63]=-1;

 /*パラメータのチェックルーチンがここに入る*/

 /*ユーザーIDと一致する文字を使わないようにする*/
 for(i=0;argv[1][i]!=0;i++){
  if(isdigit(argv[1][i])){
   g_acTable[argv[1][i]-'0']=-1;
  }else if(isupper(argv[1][i])){
   g_acTable[argv[1][i]-'A'+10]=-1;
  }else if(islower(argv[1][i])){
   g_acTable[argv[1][i]-'a'+36]=-1;
  }
 }

 nLength=atoi(argv[2]);

 /*パスワード作成*/
 while(nCount<nLength){
  nLetter=rand()%64;
  /*パスワードに使えない文字だった場合は乱数の出しなおし*/
  if(g_acTable[nLetter]==-1){
   continue;
  }
  szPassword[nCount]=nLetter;
  nCount++;
 }

 /*完成したパスワードの表示*/
 printf("Password for %s : %s\n",argv[1],szPassword);
}
補足コメント
kiroro302

お礼率 67% (55/82)

すみません。ちょっとわからないので、おしえてください。
パスワードを作成するのに時間を種にした乱数を使用してある一文字を取得するのに
while(nCount<nLength){
srand(ungigned int time(NULL));
nLetter=rand()%64;
--------------------------
というところで、%64の意味がわかりません。%64は余りという意味でしょうか?
rand()は0から32767までの数値を返すのですよね。RAND_MAXは定義されている定数で、2の15乗‐1に変換されるということを本で見たのですが,どういうことでしょうか? %64とすると0~63までの乱数を取得できるということになるということですが、この意味が理解できないのですが、ご教授願えますでしょうか?あまりに知識がなさ過ぎて申し訳ありません。よろしくお願いいたします。
投稿日時 - 2002-02-07 15:30:54
お礼コメント
kiroro302

お礼率 67% (55/82)

前回に引き続き、ご丁寧なご教授を賜り,ありがとうございます。パラメータのチェックルーチンは
if(1==argc) return help() (←help()関数は単に使用方法を表示したもの)
としました。使用可能な文字テーブル上の、UserIDに使用されている文字を使用できなくしてしまう方法はすばらしいですね。私が関数を作ると長くなってしまい効率が悪いプログラムになってしまっているようです。UserIDと一致する文字を使わないようにするやり方は参考にさせていただきます。もう少しでできそうですので,がんばってみます。どうもありがとうございました。今後もよろしくお願いいたします。
投稿日時 - 2002-02-07 12:24:33
-PR-
-PR-

その他の回答 (全4件)

  • 回答No.1
レベル6

ベストアンサー率 21% (3/14)

まずは、1.質問から回答します あまり綺麗なプログラムではありませんが main(argc, argv) intargc ; char*argv[] ; { int i ; if(argc<= 1) { printf("引数がありません\n") ; } else { for(i = 1;i < argc;i ...続きを読む
まずは、1.質問から回答します
あまり綺麗なプログラムではありませんが

main(argc, argv)
intargc ;
char*argv[] ;
{
int i ;

if(argc<= 1) {
printf("引数がありません\n") ;
}
else {
for(i = 1;i < argc;i ++)
printf("引数は%s\n",argv[i]) ;
}
}

例えば、上記のようなプログラムが
fnc.exeのmain関数だったとします。

このとき、
fnc.exe(Enter)
と、実行すると
argc=1,argv[0]="fnc.exe"が渡されます。

もしも、fnc.exe a b(enter)
とすると
argc=3,
argv[0]="fnc.exe"
argv[1]="a"
argv[2]="b"が渡されます。

このように、argc,argvを使うと
main関数(EXE)へ引数を渡すことができます。

※ デバッグしていないので動かないプログラムだったら
  ごめんなさい
お礼コメント
kiroro302

お礼率 67% (55/82)

ご回答ありがとうございます。fnc.exe a b(enter)とすると
argc=3,
argv[0]="fnc.exe"
argv[1]="a"
argv[2]="b"が渡されます
ということですが、argc=3の3は引数の数が3つあるということでしょうか?
argv[0]には実行するファイルそのものを渡されるのですね。この配列が勝手に作られるのはC言語の仕様なのでしょうか?
投稿日時 - 2002-02-06 19:07:52


  • 回答No.2
レベル6

ベストアンサー率 21% (3/14)

2.の回答です。 見当違いだったらごめんなさい。 まず使用可能文字列の配列を2次元以上に取ります 例えばこんな風に struct TBL { int flag ; char moji[9] ; }Tbl[256] ; 文字数最大8文字までの使用可能文字列を 256用意します。 UserIDと比較を行い、一致した使用可能文字列には flagをONすることによって、そ ...続きを読む
2.の回答です。
見当違いだったらごめんなさい。

まず使用可能文字列の配列を2次元以上に取ります
例えばこんな風に

struct TBL
{
int flag ;
char moji[9] ;
}Tbl[256] ;

文字数最大8文字までの使用可能文字列を
256用意します。
UserIDと比較を行い、一致した使用可能文字列には
flagをONすることによって、その文字列を
使わないようにします。

また、UserIDと比較は完全一致のみで
あれば、strcmp関数等関数で比較を行えば用意にできると
思いますが。

UserID+他の文字等の場合は、一文字ずつ比較する
関数を作る必要があります。

こんなもんでどうでしょうか?
お礼コメント
kiroro302

お礼率 67% (55/82)

ご丁寧に補足していただきありがとうございます。構造体を使うということは、思案しなかったので,大変参考になります。私の力ではまだ構造体をうまく使いこなせそうにないのですが,本を読みながら考えてみたいと思います。いっしょに勉強している友達も、構造体を使用している人はいないみたいなので、挑戦してみます。どうもありがとうござます。最近だんだん勉強が面白くなってきつつあります。またつまずいてしまうかもしれませんが,これからもよろしくお願いいたします。
投稿日時 - 2002-02-07 10:06:28
  • 回答No.3
レベル9

ベストアンサー率 33% (33/98)

> どのように関数を設計 問題をどのように解決すればいいか、分解してみてください。 > 配列-配列なんてできるのでしょうか C++ でなら可能と言えば可能です^^; 配列の変わりにvectorを使って、、、(とりあえず、それるので、以下略でおいておきます。 Cでやる場合、擬似的なのですが、一致したら、次以降の奴で上書きするという感じで書きます。 # いらばいデータのぶん詰め ...続きを読む
> どのように関数を設計
問題をどのように解決すればいいか、分解してみてください。

> 配列-配列なんてできるのでしょうか
C++ でなら可能と言えば可能です^^;
配列の変わりにvectorを使って、、、(とりあえず、それるので、以下略でおいておきます。

Cでやる場合、擬似的なのですが、一致したら、次以降の奴で上書きするという感じで書きます。
# いらばいデータのぶん詰めてしまう、と言うことです。
char array[size]
int i, pos=0;
for(i=0; i<size; i++) {
 if (array[i] が UserIDに含まれていなければ) {
  array[pos] = array[i];
  pos++;
 }
}
for(i=pos; i<size; i++) array[i] = 0; // 残りを破棄する
array_size = pos; // 新しい配列の大きさはpos
お礼コメント
kiroro302

お礼率 67% (55/82)

ありがとうございます。大変参考になります。いらないデータの上から上書きして詰めてしまい、残りの要素に0を代入して,破棄するのですね。この"残りの要素に0を代入して破棄する"というような、アイデアがなかなか浮かびません。センスないのでしょうか?やはり私のようなものは、たくさんソースを書いて,いろいろ試してみて経験を積無しかないなと思います。地道にやっていくつもりですので,これからもよろしくお願いいたします。
投稿日時 - 2002-02-07 10:14:31
  • 回答No.4
レベル14

ベストアンサー率 24% (612/2465)

文字列の引き算関数を作ってみました。 あと、2.で使えるような感じのソースを書いてみました。 char *subtraction(char *retval, char *userID); で引数の、前の文字列-後ろの文字列の結果が関数値で返ります。 呼出先よりこの関数を上に置くか、上の形でプロトタイプ宣言してください。 まあ、普通パスワードはcrypt関数を使うんだけど、標準ではライブラリに ...続きを読む
文字列の引き算関数を作ってみました。
あと、2.で使えるような感じのソースを書いてみました。
char *subtraction(char *retval, char *userID);
で引数の、前の文字列-後ろの文字列の結果が関数値で返ります。
呼出先よりこの関数を上に置くか、上の形でプロトタイプ宣言してください。

まあ、普通パスワードはcrypt関数を使うんだけど、標準ではライブラリにくっついていないんで...

後は自分で調べて勉強してください。
---
#include <stdio.h>
#include <strings.h>

#define BASE_MAX 62
char base[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

char *subtraction(char *retval, char *userID) {
int i, cnt;
char *cret;

for (i=0; i<strlen(userID); i++) {
cret = strchr(retval, userID[i]);
cnt = (int)(cret - retval);
if (cret && cnt != strlen(retval)) {
strcpy(&retval[cnt], &cret[1]);
}
else if(cnt == strlen(retval)){
base[cnt-1] = 0;
}
}
return retval;
}

main(){
char tmp[BASE_MAX];
strcpy(tmp, base);
printf("%s\n",subtraction("sodivubv", tmp));
strcpy(tmp, base);
printf("%s\n",subtraction("zoyivubv", tmp));
}
お礼コメント
kiroro302

お礼率 67% (55/82)

ご回答ありがとうございます。私もいろいろ考えてみました。使用できる文字を配列に入れて,UserIDの文字と比較し,等しかったらフラグを1にし、不等だったら、0にして、フラグが0だったら、usablestrという配列にいれて、パスワードに使用できる文字の配列をつくるというような、関数を考えてみました。
void makecharset(char *account, char *usablestr)
{
int i, j, k, n;
const char c[62] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

n = 0;

for( i=0; i < 62; i++ )
{
k=0;

for( j=0; j < strlen(account); j++ )
{
if ( account[j] == c[i] )
{
k=1;
break;
}
}
if(0 == k) usablestr[n++] = c[i];
}
usablestr[n] = '\0';
}
ご教授いただいたソースを自分なりに消化し,参考させていただきます。
ご丁寧にご回答いただき本当にありがとうございました。これからもよろしくお願いいたします。
投稿日時 - 2002-02-07 10:27:24
このQ&Aで解決しましたか?
関連するQ&A
-PR-
-PR-
こんな書き方もあるよ!この情報は知ってる?あなたの知識を教えて!
このQ&Aにはまだコメントがありません。
あなたの思ったこと、知っていることをここにコメントしてみましょう。

その他の関連するQ&A、テーマをキーワードで探す

キーワードでQ&A、テーマを検索する
-PR-
-PR-
-PR-

特集


いま みんなが気になるQ&A

関連するQ&A

-PR-

ピックアップ

-PR-
ページ先頭へ