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

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

このQ&Aに関連する最新のQ&A

A 回答 (5件)

この質問は参照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);
}

この回答への補足

すみません。ちょっとわからないので、おしえてください。
パスワードを作成するのに時間を種にした乱数を使用してある一文字を取得するのに
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
    • good
    • 0
この回答へのお礼

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

お礼日時:2002/02/07 12:24

文字列の引き算関数を作ってみました。


あと、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));
}
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。私もいろいろ考えてみました。使用できる文字を配列に入れて,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

> どのように関数を設計


問題をどのように解決すればいいか、分解してみてください。

> 配列-配列なんてできるのでしょうか
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
    • good
    • 0
この回答へのお礼

ありがとうございます。大変参考になります。いらないデータの上から上書きして詰めてしまい、残りの要素に0を代入して,破棄するのですね。この"残りの要素に0を代入して破棄する"というような、アイデアがなかなか浮かびません。センスないのでしょうか?やはり私のようなものは、たくさんソースを書いて,いろいろ試してみて経験を積無しかないなと思います。地道にやっていくつもりですので,これからもよろしくお願いいたします。

お礼日時:2002/02/07 10:14

2.の回答です。


見当違いだったらごめんなさい。

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

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

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

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

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

こんなもんでどうでしょうか?
    • good
    • 0
この回答へのお礼

ご丁寧に補足していただきありがとうございます。構造体を使うということは、思案しなかったので,大変参考になります。私の力ではまだ構造体をうまく使いこなせそうにないのですが,本を読みながら考えてみたいと思います。いっしょに勉強している友達も、構造体を使用している人はいないみたいなので、挑戦してみます。どうもありがとうござます。最近だんだん勉強が面白くなってきつつあります。またつまずいてしまうかもしれませんが,これからもよろしくお願いいたします。

お礼日時:2002/02/07 10:06

まずは、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)へ引数を渡すことができます。

※ デバッグしていないので動かないプログラムだったら
  ごめんなさい
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。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

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aと関連する良く見られている質問

Qint main(int argc, char* argv[]) についての質問

こんにちは.つね日ごろ思っている質問させてください.
Cの参考書には,
(1)
void main(void)
{
}

(2)
int main(int argc, char* argv[])
{
return 0;
}
の2つのパターンが記載されていますが,
どういう違いがあるのでしょうか?

(1)の場合main関数は,型を持たず,引数も持たない.
※Turbo Cなどのコンパイラーでは,
return文がないと警告出ます.
(2)の場合は,int 型をかえし,引数はint型 変数と char型ポインタ配列(?)
を指定している.
といったくらいしか分かりません.

(2)に関してもう少し述べれば,
コマンドラインからファイルを指定し,実行することが
できると勉強した記憶があるのですが,
理解があいまいです.

特に(2)の場合のmain関数の意味と,その使い方について
アドバイスお願い致します.

Aベストアンサー

> (1)
> void main(void)
  ...
> (2)
> int main(int argc, char* argv[])
  ...
> の2つのパターンが記載されていますが,どういう違いがあるのでしょうか?

(1) は、間違いです。少なくとも ANSI-C の規格に合致していません。

main() は、特別な関数で、ANSI-C の規格では以下の三通りのうちのどれか
でなくてはいけない、と定められています。

int main(void)
int main(int argc, char *argv[]);
int main(int argc, char *argv[], char *envp[]);

因みに三番目の形式では、三つ目の引数には環境変数が入ります。
以下のようなコードで確認ができます。

int main(int argc, char *argv[], char *envp[])
{
  int i = 0;
  while (envp[i]) {
    printf("envp[%d] = '%s'\n", i, envp[i]);
    ++i;
  }
  return 0;
}


> ※Turbo Cなどのコンパイラーでは,return文がないと警告出ます

Turbo C は、規格に厳格なのでしょう。返り値が void なのはおかしいので、
int だとみなすよ、という警告も出てるはず。で、int が帰り値だとみなし
ているので return が無いと、返り値が不定になるよ、と警告を出している
のでしょう。

> (1)
> void main(void)
  ...
> (2)
> int main(int argc, char* argv[])
  ...
> の2つのパターンが記載されていますが,どういう違いがあるのでしょうか?

(1) は、間違いです。少なくとも ANSI-C の規格に合致していません。

main() は、特別な関数で、ANSI-C の規格では以下の三通りのうちのどれか
でなくてはいけない、と定められています。

int main(void)
int main(int argc, char *argv[]);
int main(int argc, char *argv[], char *envp[]);

因みに三番目の形式では、三...続きを読む

Q引数で argc argvが使用されていないのですが!?

以下のプログラムで
 int main(int argc, char* argv[ ] )
 で質問ですが! 引数の argc argvを定義して
 同プログラム内で他に使われていないのですが!
 なぜですか お叱りを覚悟でご質問いたしました。

 よろしくお願いいたします。 

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

/*構造体に定義*/
struct TestKekka
{
char shimei[80]; /*氏名*/
int kokugo;
int sugaku;
int eigo;
};

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

struct TestKekka sato; /* 佐藤君 */
struct TestKekka tanaka; /* 田中君 */
struct TestKekka suzuki; /* 鈴木君 */

/* 佐藤君んのデータ */
strcpy (sato.shimei, "佐藤一郎");
sato.kokugo = 90;
sato.sugaku = 80;
sato.eigo = 75;

/* 田中君のデータ */
strcpy (tanaka.shimei, "田中次郎");
tanaka.kokugo = 80;
tanaka.sugaku = 70;
tanaka.eigo = 60;

/* 鈴木君データ */
strcpy(suzuki.shimei,"鈴木三郎");
suzuki.kokugo = 70;
suzuki.sugaku = 50;
suzuki.eigo = 100;

/* 学生ごとに3科目の平均点を表示する */
heikin = (sato.kokugo + sato.sugaku + sato.eigo) / 3;
printf("%sの平均点 : %d\n", sato.shimei, heikin);

heikin = (tanaka.kokugo + tanaka.sugaku + tanaka.eigo) / 3;
printf ("%sの平均点 : %d\n", tanaka.shimei, heikin);

heikin = (suzuki.kokugo + suzuki.sugaku + suzuki.eigo) / 3;
printf("%s平均点数 : %d\n", suzuki.shimei, heikin);

return 0;
}

以下のプログラムで
 int main(int argc, char* argv[ ] )
 で質問ですが! 引数の argc argvを定義して
 同プログラム内で他に使われていないのですが!
 なぜですか お叱りを覚悟でご質問いたしました。

 よろしくお願いいたします。 

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

/*構造体に定義*/
struct TestKekka
{
char shimei[80]; /*氏名*/
int kokugo;
int sugaku;
int eigo;
};

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

struct TestKekka sato; /*...続きを読む

Aベストアンサー

既に#2の方が述べていますが
int main(int argc, char* argv[ ] )の書き方は
main関数特有の決まりごとだと覚えてください。
そして、argc,argvは使っても良いし、使わなくても良いのです。
つまり、定義した変数は、必ず使わないといけないという規則はC言語にはないのです。
(ほかの言語も同様ですが・・・)
普通、変数は、使用するために定義しますが、それを定義だけして使用しなくても良いのです。
これは、例えば、あなたが提示されたプログラムのint heikin;の次の行に、
int i;
と追加し、この変数iを使用しなくても、かまわないということです。
使用しなくても良いという意味は、使用しなくてもエラーには、ならないという意味であり、
それが良いプログラムであるということではありません。
int i;の定義を他の人が見たら、使わないのに何故定義をしているんだという、つっこみが入るかもしれませんで、使わない変数は定義しないほうが、一般的には良いでしょう。

Qmain関数のとる引数(argc , *argv[])の意味について

 今日は、Cの初心者です宜しくお願いします。
 
 main関数(main(int argc , *argv[]))のとる引数、argcのCと*argv[]のVはどのような意味の略なのでしょうか、
なにか意味があるようなきがするのですが。
 宜しくお願いします。

Aベストアンサー

文字列の個数(argument count)

"ARGument Vector" の略という説と、"ARGument Value" の略という説がある。

Qmain(int argc,char **argv[])の意味を教えて下さい

 今晩は、Cの初心者です宜しくお願いします。
 main関数の引数で、int main(int argc,char **argv[])とint main(int argc,char *argv[])と書かれている場合がありますが、
「**argv」と「*argv」の意味の違いはどのようなもので、どのように使い分けるのでしょうか。
また、必ずポインタ型でとるという決まりでしょうか。
宜しくお願いします。

Aベストアンサー

これは質問者さん向けというより、半分他の回答者さんに向けたコメントですが、

おそらく質問者さんの本当の意図は、ポインタと配列の違いではなく、
main関数の引数宣言の仕方に2パターンあるが、これはどう使い分けるのか、
というところにあるのではないでしょうか。
私はそう考えて回答3を書きました。

ところが、質問者さんが**argv を **argv[]と書き間違えちゃったために、
質問を深読みしちゃって
C言語におけるポインタとは何か、というかなり難易度の高い議題で
回答がいっぱい集まっちゃったと。

で、ちょっとだけ質問者さんを弁護。

質問者さんは回答1のお礼欄に

> int main(int argc,char **argv) でした、すみません、どのような意味でしょうか。

と書かれています。

わたしが回答3を書こうとした時点で、すでにこのコメントがあったため、
私は回答3で関数の引数宣言における **argv と *argv[] の違いについて回答しています。

質問者さんは、こういう訂正は、こういうのはお礼ではなく補足コメントにすべきだったと思いますが、

回答された方々も、回答される前に、既に付けられた回答と、そこへの
質問者者さんのコメントなどをちゃんと読んでから回答していれば、
ここまでムダな回答が続くことが無かったんではないかと思います。

これは質問者さん向けというより、半分他の回答者さんに向けたコメントですが、

おそらく質問者さんの本当の意図は、ポインタと配列の違いではなく、
main関数の引数宣言の仕方に2パターンあるが、これはどう使い分けるのか、
というところにあるのではないでしょうか。
私はそう考えて回答3を書きました。

ところが、質問者さんが**argv を **argv[]と書き間違えちゃったために、
質問を深読みしちゃって
C言語におけるポインタとは何か、というかなり難易度の高い議題で
回答がいっぱい集まっちゃっ...続きを読む

Qプログラミング(argcとargv)

入力された数の合計とその計算式を表示するプログラムをつくっています。惜しい(?)ところまでいったのですがその先がなかなか進みません。以下のプログラムのどこを修正したらよいでしょうか?教えてください。
#include <stdio.h>
#include <stdlib.h>

#define nMAX 10

int main(int argc, char **argv){
int sum = 0;

if(argc < 2){
printf("Too few option!\n");
return 1;
}

int i, n;
for(i = 1; i < argc; i++){
n = atoi(argv[i]);
sum = sum + n;
}
printf("%d\n", sum);

}

Aベストアンサー

合計は出ているので、計算式の表示で困っているということでしょうか。
暇なので計算式表示部分を書いてみました。
printf("%d\n", sum); の部分と置き換えます。
参考にしてください。

for (i=1; i<argc; i++) {
n = atoi(argv[i]);
if (i == 1) printf("%d", n);
else printf("%+d", n);
}
printf("=%d\n", sum);

実行結果はこんな感じ。

$ ./sum -1 2 -3 4 0
-1+2-3+4+0=2


人気Q&Aランキング

おすすめ情報