C言語関係掲示板

過去ログ

No.519.パスワードを変更するプログラム

[戻る] [ホームページ]
No.4053

ファイルのことで
投稿者---さかぶ(2002/12/25 17:29:02)


例えば
***ファイル,涼羶***
abc
def
ghi
*********************
***ファイル△涼羶***
s100
s200
s300
*********************
ファイル,abc

ファイル△s100
を対にさせたいのですが、どのように対にさせたらよいのですか?
教えてください。よろしくお願いします。

No.4054

Re:ファイルのことで(補足)
投稿者---さかぶ(2002/12/25 17:47:41)


>例えば
>***ファイル,涼羶***
>abc
>def
>ghi
>*********************
>***ファイル△涼羶***
>s100
>s200
>s300
>*********************
>ファイル,abc
>と
>ファイル△s100
>を対にさせたいのですが、どのように対にさせたらよいのですか?
>教えてください。よろしくお願いします。

(ここからが補足になります。)
ファイル,def

ファイル△s200
また、
ファイル,ghi

ファイル△s300
についても対にしたいです。


No.4066

Re:ファイルのことで(補足)
投稿者---ともじ(2002/12/26 00:50:25)


こんばんは。

>ファイル,abc
>>と
>ファイル△s100
>を対にさせたいのですが、どのように対にさせたらよいのですか?

対にするという意味がいまひとつわかり辛かったのですが、
abcs100にして別ファイルに書き込むということでよいでしょうか。
#include <stdio.h>

int main(void)
{
    FILE *rfp1, *rfp2, *wfp;
    char s1[256], s2[256];
    
    if ((rfp1 = fopen("rfile1.txt", "r")) == NULL) {
        printf("rfile1.txt open error!!\n");
        return (1);
    }
    if ((rfp2 = fopen("rfile2.txt", "r")) == NULL) {
        printf("rfile2.txt open error!!\n");
        return (1);
    }
    if ((wfp = fopen("wfile.txt", "w")) == NULL) {
        printf("wfile.txt open error!!\n");
        return (1);
    }

    while (1) {
        if (fscanf(rfp1, "%s", s1) != 1) break;
        if (fscanf(rfp2, "%s", s2) != 1) break;
        fprintf(wfp, "%s%s\n", s1, s2);
    }
    
    fclose(rfp1);
    fclose(rfp2);
    fclose(wfp);
    
    return(0);
}






No.4069

Re:ファイルのことで(補足)
投稿者---さかぶ(2002/12/26 12:03:02)


こんにちは。
対にするという言い方は、わかりにくかったですね。
すみませんでした。
対にするという意味は、ファイル,abcが入力された時だけ
ファイル△s100が認識されるということでした。

上のプログラムのおかげで、少し思いついたことがあるのでのでやってみます。
ともじさんありがとうございました。

No.4077

ファイルのことで(改めまして)
投稿者---さかぶ(2002/12/26 17:25:44)


rfile1.txtには番号がs001からs999まで入っています。
rfile2.txtにはパスワードがp001からp999まで入っています。

#include <stdio.h>
#include <string.h>
int main(void)
{
    FILE    *rfp1, *rfp2, *wfp;
    char    s1[32], s2[32];
    char    num[32],pas[32];
    
    /*wfile.txt作成*/
    /*番号+パスワードをwfile.txtに書き込み*/
    if ((rfp1 = fopen("rfile1.txt", "r")) == NULL) {
        printf("rfile1.txt open error!!\n");
        return (1);
    }
    if ((rfp2 = fopen("rfile2.txt", "r")) == NULL) {
        printf("rfile2.txt open error!!\n");
        return (1);
    }
    if ((wfp = fopen("wfile.txt", "w")) == NULL) {
        printf("wfile.txt open error!!\n");
        return (1);
    }
    while (1) {
        if (fscanf(rfp1, "%s", s1) != 1) break;
        if (fscanf(rfp2, "%s", s2) != 1) break;
        fprintf(wfp, "%s%s\n", s1, s2);
    }
    
    /*rfile1.txtを読み込み入力された番号の有無を確認*/
    /*rfile1.txtに入力された番号が無い場合はエラーを表示*/
    printf("番号を入力してください\n");
    printf(">>>");
    scanf("%s", num);
    /*rfile1.txtを読み込み*/
    if ((rfp1 = fopen("rfile1.txt", "r")) == NULL) {
        printf("rfile1.txt open error!!\n");
        return (1);
    }
    /*ここからが質問です*/
    /*入力された番号とrfile1.txt中にある番号が同じ場合は
      printf("○\n");を一回のみ表示したい。また入力された番号がrfile1.txt中に無い場合はprintf("×\n");を一回の
      み表示したいです。*/
    while (1) {
        if (fscanf(rfp1, "%s", s1) != 1) break;
        fscanf(rfp1, "%s", s1);
        if (strcmp(num,s1)==0){
            printf("○\n");
        }else{
            printf("×\n");
        }
    }
    
    /*rfile2.txtを読み込み入力されたパスワードの有無を確認*/
    /*rfile2.txtに入力されたパスワードが無い場合はエラーを表示*/
    printf("パスワードを入力してください\n");
    printf(">>>");
    scanf("%s", pas);
    /*rfile2.txtを読み込み*/
    if ((rfp2 = fopen("rfile2.txt", "r")) == NULL) {
        printf("rfile2.txt open error!!\n");
        return (1);
    }
    /*ここからが質問です*/
    /*入力されたパスワードとrfile2.txt中にあるパスワードが同じ場合は
      printf("○\n");を一回のみ表示したい.また入力されたパスワードが
      rfile2.txt中に無い場合はprintf("×\n");を一回のみ表示したいです。*/
    while (1) {
        if (fscanf(rfp2, "%s", s2) != 1) break;
        fscanf(rfp2, "%s", s2);
        if (strcmp(pas,s2)==0){
            printf("○\n");
        }else{
            printf("×\n");
        }
    }
    
    
    fclose(rfp1);
    fclose(rfp2);
    fclose(wfp);
    
    return(0);
}

よろしくお願いします。

No.4080

Re:ファイルのことで(改めまして)
投稿者---ともじ(2002/12/26 23:45:44)


次のような感じでしょうか。

ただ、これですと
>対にするという意味は、ファイル,abcが入力された時だけ
>ファイル△s100が認識されるということでした。
とは違うようですが。

#include <stdio.h>
#include <string.h>
int main(void)
{
    FILE    *rfp1, *rfp2, *wfp;
    char    s1[32], s2[32];
    char    num[32],pas[32];
    int     find;    /*** 追加 ***/
    
    /*wfile.txt作成*/
    /*番号+パスワードをwfile.txtに書き込み*/
    if ((rfp1 = fopen("rfile1.txt", "r")) == NULL) {
        printf("rfile1.txt open error!!\n");
        return (1);
    }
    if ((rfp2 = fopen("rfile2.txt", "r")) == NULL) {
        printf("rfile2.txt open error!!\n");
        return (1);
    }
    if ((wfp = fopen("wfile.txt", "w")) == NULL) {
        printf("wfile.txt open error!!\n");
        return (1);
    }
    while (1) {
        if (fscanf(rfp1, "%s", s1) != 1) break;
        if (fscanf(rfp2, "%s", s2) != 1) break;
        fprintf(wfp, "%s%s\n", s1, s2);
    }
    
    /*rfile1.txtを読み込み入力された番号の有無を確認*/
    /*rfile1.txtに入力された番号が無い場合はエラーを表示*/
    printf("番号を入力してください\n");
    printf(">>>");
    scanf("%s", num);
    /*rfile1.txtを読み込み*/
    /*** 既にオープンしているので、ここは不要
    if ((rfp1 = fopen("rfile1.txt", "r")) == NULL) {
        printf("rfile1.txt open error!!\n");
        return (1);
    }
    ***/
    
    /*ここからが質問です*/
    /*入力された番号とrfile1.txt中にある番号が同じ場合は
      printf("○\n");を一回のみ表示したい。また入力された番号がrfile1.txt中に無い場合はprintf("×\n");を一回の
      み表示したいです。*/
    find = 0;    /*** 追加 ***/
    /*** 既にファイル終端まで読み込んだので、ファイル位置指示子を先頭に移動 ***/
    fseek(rfp1, 0L, SEEK_SET);
    while (1) {
        if (fscanf(rfp1, "%s", s1) != 1) break;
        /*** 既にfscanfしているので不要
        fscanf(rfp1, "%s", s1);
        ***/
        /*** 一致したらbreak; ***/
        if (strcmp(num,s1)==0){
            find++;
            printf("○\n");
            break;
        }
    }
    /*** ループを抜けてから見つかったか判定 ***/
    if (find==0) {
            printf("×\n");
    }
    
    /*rfile2.txtを読み込み入力されたパスワードの有無を確認*/
    /*rfile2.txtに入力されたパスワードが無い場合はエラーを表示*/
    printf("パスワードを入力してください\n");
    printf(">>>");
    scanf("%s", pas);
    /*rfile2.txtを読み込み*/
    /*** 不要 ***
    if ((rfp2 = fopen("rfile2.txt", "r")) == NULL) {
        printf("rfile2.txt open error!!\n");
        return (1);
    }
    ***/
    /*ここからが質問です*/
    /*入力されたパスワードとrfile2.txt中にあるパスワードが同じ場合は
      printf("○\n");を一回のみ表示したい.また入力されたパスワードが
      rfile2.txt中に無い場合はprintf("×\n");を一回のみ表示したいです。*/
    find = 0;    /*** 追加 ***/
    /*** 既にファイル終端まで読み込んだので、ファイル位置指示子を先頭に移動 ***/
    fseek(rfp2, 0L, SEEK_SET);
    while (1) {
        if (fscanf(rfp2, "%s", s2) != 1) break;
        /*** 既にfscanfしているので不要
        fscanf(rfp2, "%s", s2);
        ***/
        /*** 一致したらbreak; ***/
        if (strcmp(pas,s2)==0){
            find++;
            printf("○\n");
            break;
        }
    }
    /*** ループを抜けてから見つかったか判定 ***/
    if (find==0) {
            printf("×\n");
    }
    
    fclose(rfp1);
    fclose(rfp2);
    fclose(wfp);
    
    return(0);
}


No.4089

Re:ファイルのことで(改めまして2)何度もすみません
投稿者---さかぶ(2002/12/28 09:17:18)


ともじさんありがとうございました。
>ただ、これですと
>>対にするという意味は、ファイル,abcが入力された時だけ
>>ファイル△s100が認識されるということでした。
>とは違うようですが。
確かに、ともじさんの言うとおり以前の質問とは違いました。
解からないことがたくさんあるので先ほどの質問をさせていただきました。
また、質問があるのでよろしくお願いします(何度もすみません…)

No.4122

Re:ファイルのことで(改めまして2)何度もすみません
投稿者---ともじ(2002/12/31 22:00:13)


返信遅くなりました。

ご提示のプログラムでは、ファイルの内容を読み込むたびに
fopenしていますが、fopenはファイルの書き込み読み込み前に一度
してください。使い終わったファイルは速やかにfcloseしましょう。
下のプログラムでは、wfile.txtは"w+"モードでfopenしています。
"w+"モードはファイルを新規作成して書き込み+読み込みの動作を
可能にします。

提示のプログラムでは
 fprintf(wfp, "%s\n", s1); /*番号をwfile.txtに書き込み*/
 fprintf(wfp, "%s\n", s2); /*パスワードをwfile.txtに書き込み*/
となっていますが、これですと次にwfile.txtに対して番号を調べに行く
ときに、パスワードと同じものを入力してもOKになりますので、
下のプログラムでは番号の後に\nを書き込んでいません。

同じファイルに対してパスワードを変更するには、パスワードの長さ
を固定にする必要があります。可変ですと、変更で長さが異なった場合、
それ以降のデータを全てずらす必要があります。下のプログラムでは
長さがよくわからないので、番号とパスワードの長さをマクロ定義
しています。
 sprintf(nform, "%%%ds", NLEN);
 sprintf(pform, "%%%ds", PLEN);
これは、マクロ定義を書式に反映するための処置です。

 fprintf(wfp, "%*s", -NLEN, s1);
 fprintf(wfp, "%*s\n", -PLEN, s2);
これは、wfile.txtに固定の長さで番号とパスワードを書き込む処理です。

御提示のプログラムは、ネストが深いので、番号のチェック、パスワード
のチェック、パスワードの変更処理をそれぞれ独立させました。

 (void)getchar();
 printf("\t\t数字を入力してください\n");
このgetcharは、謝って数字以外を入力したときに、入力バッファに
入力値が残っているので、読み捨てています。

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

#define NLEN 10        /* 番号の長さ */
#define PLEN 32        /* パスワードの長さ */

int main(void)
{
    FILE *rfp1, *rfp2, *wfp; 
    char s1[NLEN+PLEN+1], s2[PLEN+1];
    char num[NLEN+1], pas[PLEN+1], newpas[PLEN+1];
    char nform[20], pform[20];
    int find, len;
    int res;

    /* 番号とパスワードの読み込み書式を作成 */
    sprintf(nform, "%%%ds", NLEN);
    sprintf(pform, "%%%ds", PLEN);

    if ((rfp1 = fopen("rfile1.txt", "r")) == NULL) {
        printf("rfile1.txt open error!!\n");
        return (1);
    }
    if ((rfp2 = fopen("rfile2.txt", "r")) == NULL) {
        printf("rfile2.txt open error!!\n");
        return (1);
    }
    /* wfile.txtを書き込み+読み込みでオープン */
    if ((wfp = fopen("wfile.txt", "w+")) == NULL) {
        printf("wfile.txt open error!!\n");
        return (1);
    }
    
    for (;;) {
        if (fscanf(rfp1, nform, s1) != 1) break;
        if (fscanf(rfp2, pform, s2) != 1) break;
        fprintf(wfp, "%*s", -NLEN, s1);    /*番号をwfile.txtに書き込み*/
        fprintf(wfp, "%*s\n", -PLEN, s2);  /*パスワードをwfile.txtに書き込み*/
    }
    
    fclose(rfp1);
    fclose(rfp2);

    printf("番号を入力してください\n");
    printf(">>>");
    scanf(nform, num);
    find = 0;
    fseek(wfp, 0L, SEEK_SET);
    len = strlen(num);
    /* wfile.txtに入力番号があるか */
    while (1) {
        if (fgets(s1, sizeof(s1), wfp) == NULL) break;
        if (strncmp(num, s1, len)==0){
            find++;
            printf("番号○\n");
            break;
        }
    }
    
    /* 一致番号があればパスワードチェック */
    if (find != 0) {
        printf("パスワードを入力してください\n");
        printf(">>>");
        scanf("%s", pas);
        len = strlen(pas);
        if (strncmp(pas, s1+NLEN, len) == 0) {
            printf("パスワード○\n");
        }
        else {
            printf("×パスワードエラー!\n");
            fclose(wfp);
            return (0);
        }
    }
    else {
        printf("×番号エラー!\n");
        fclose(wfp);
        return (0);
    }
    
    /* パスワードの変更処理 */
    printf("[1.パスワード変更]\t[2.終了]\n");
    for (;;){
        printf("動作>>>");
        if(scanf("%d", &res) == 1){
            if(res == 1){
                printf("新しいパスワードを入力してください\n");
                printf(">>>");
                scanf(pform, newpas);
	       fseek(wfp, -PLEN, SEEK_CUR);
                fprintf(wfp, "%*s\n", -PLEN, newpas);
                break; 
            }
            else if(res == 2){ 
                break;
            }
            else{
                printf("\t\t1か2を入力してください\n");
            }
        }
        else{
            (void)getchar();
            printf("\t\t数字を入力してください\n");
        }
    }
    fclose(wfp);

    return(0);
}




No.4123

ありがとうございました。
投稿者---さかぶ(2003/01/01 07:40:53)


やっと、やりたいことができました。
本当にありがとうございました。
そして明けましておめでとうございます。

No.4139

Re:ファイルのことで(改めまして2)何度もすみません
投稿者---かずま(2003/01/03 03:00:45)


>#define NLEN 10        /* 番号の長さ */
>#define PLEN 32        /* パスワードの長さ */

>    char s1[NLEN+PLEN+1], s2[PLEN+1];

>        fprintf(wfp, "%*s", -NLEN, s1);    /*番号をwfile.txtに書き込み*/
>        fprintf(wfp, "%*s\n", -PLEN, s2);  /*パスワードをwfile.txtに書き込み*/

>        if (fgets(s1, sizeof(s1), wfp) == NULL) break;
>        if (strncmp(num, s1, len)==0){
wfp に書き込むときは、NLEN + PLEN + 1 で、43バイト。
wfp から読み込むときは、sizeof(s1) が 43バイト。
fgets は、最後に '\0' を付けるので、42バイトしか読み込まず、
NLEN + PLEN だけ読み込まれて、次の fgets で、'\n' だけが読み込まれる。
その '\n' は strncmp ではじかれますが、これは、意図したことでしょうか。

No.4183

Re:ファイルのことで(改めまして2)何度もすみません
投稿者---ともじ(2003/01/05 21:51:57)


不在にしていたため、返信が遅くなり申し訳ありません。

>その '\n' は strncmp ではじかれますが、これは、意図したことでしょうか。

いえ、意図したことではなく、完全な抜けです。

上記No.4122を以下のように修正します。
修正箇所は
    char s1[NLEN+PLEN+2], s2[PLEN+1];    /*** s1[NLEN+PLEN+2]に修正 ***/

    fseek(wfp, -PLEN-2, SEEK_CUR);       /*** -PLEN-2に修正 ***/
の2箇所です。
なお、-PLEN-2の-2は、'\r''\n'を戻すため2になります。
#include <stdio.h>
#include <string.h>

#define NLEN 10        /* 番号の長さ */
#define PLEN 32        /* パスワードの長さ */

int main(void)
{
    FILE *rfp1, *rfp2, *wfp; 
    char s1[NLEN+PLEN+2], s2[PLEN+1];    /*** s1[NLEN+PLEN+2]に修正 ***/
    char num[NLEN+1], pas[PLEN+1], newpas[PLEN+1];
    char nform[20], pform[20];
    int find, len;
    int res;

    /* 番号とパスワードの読み込み書式を作成 */
    sprintf(nform, "%%%ds", NLEN);
    sprintf(pform, "%%%ds", PLEN);

    if ((rfp1 = fopen("rfile1.txt", "r")) == NULL) {
        printf("rfile1.txt open error!!\n");
        return (1);
    }
    if ((rfp2 = fopen("rfile2.txt", "r")) == NULL) {
        printf("rfile2.txt open error!!\n");
        return (1);
    }
    /* wfile.txtを書き込み+読み込みでオープン */
    if ((wfp = fopen("wfile.txt", "w+")) == NULL) {
        printf("wfile.txt open error!!\n");
        return (1);
    }
    
    for (;;) {
        if (fscanf(rfp1, nform, s1) != 1) break;
        if (fscanf(rfp2, pform, s2) != 1) break;
        fprintf(wfp, "%*s", -NLEN, s1);    /*番号をwfile.txtに書き込み*/
        fprintf(wfp, "%*s\n", -PLEN, s2);  /*パスワードをwfile.txtに書き込み*/
    }
    
    fclose(rfp1);
    fclose(rfp2);

    printf("番号を入力してください\n");
    printf(">>>");
    scanf(nform, num);
    find = 0;
    fseek(wfp, 0L, SEEK_SET);
    len = strlen(num);
    /* wfile.txtに入力番号があるか */
    while (1) {
        if (fgets(s1, sizeof(s1), wfp) == NULL) break;
        if (strncmp(num, s1, len)==0){
            find++;
            printf("番号○\n");
            break;
        }
    }
    
    /* 一致番号があればパスワードチェック */
    if (find != 0) {
        printf("パスワードを入力してください\n");
        printf(">>>");
        scanf("%s", pas);
        len = strlen(pas);
        if (strncmp(pas, s1+NLEN, len) == 0) {
            printf("パスワード○\n");
        }
        else {
            printf("×パスワードエラー!\n");
            fclose(wfp);
            return (0);
        }
    }
    else {
        printf("×番号エラー!\n");
        fclose(wfp);
        return (0);
    }
    
    /* パスワードの変更処理 */
    printf("[1.パスワード変更]\t[2.終了]\n");
    for (;;){
        printf("動作>>>");
        if(scanf("%d", &res) == 1){
            if(res == 1){
                printf("新しいパスワードを入力してください\n");
                printf(">>>");
                scanf(pform, newpas);
                   fseek(wfp, -PLEN-2, SEEK_CUR);        /*** -PLEN-2に修正 ***/
                fprintf(wfp, "%*s\n", -PLEN, newpas);
                break; 
            }
            else if(res == 2){ 
                break;
            }
            else{
                printf("\t\t1か2を入力してください\n");
            }
        }
        else{
            (void)getchar();
            printf("\t\t数字を入力してください\n");
        }
    }
    fclose(wfp);

    return(0);
}




No.4192

Re:ファイルのことで(改めまして2)何度もすみません
投稿者---かずま(2003/01/06 00:07:14)


> 上記No.4122を以下のように修正します。
> 修正箇所は
> 
>     char s1[NLEN+PLEN+2], s2[PLEN+1];    /*** s1[NLEN+PLEN+2]に修正 ***/
> 
>     fseek(wfp, -PLEN-2, SEEK_CUR);       /*** -PLEN-2に修正 ***/
>
> の2箇所です。
> なお、-PLEN-2の-2は、'\r''\n'を戻すため2になります。

Windows ならこれで動きますが、UNIX や Mac OS では、改行コードが
1文字なのでだめでしょう。どの環境でも動くようにしようとすれば、

・新しい変数 fpos_t pos; を追加する。

・if (fgets(s1, sizeof(s1), wfp) == NULL) break; の直前で、
 fgetpos(wfp, &pos); を実行して、その行の先頭のファイル上の位置を取得する。

・  fseek(wfp, -PLEN-2, SEEK_CUR);
    fprintf(wfp, "%*s%*s\n", -NLEN, -PLEN, newpas);

 の代わりに、

    sprintf(s1 + NLEN, "%-*s\n", PLEN, newpas);  /* 新しい行を作る */
    fsetpos(wfp, &pos);  /* 行の先頭にシークする */
    fputs(s1, wfp);

  とする。


No.4205

Re:ファイルのことで(改めまして2)何度もすみません
投稿者---ともじ(2003/01/06 03:17:17)


>Windows ならこれで動きますが、UNIX や Mac OS では、改行コードが
>1文字なのでだめでしょう。どの環境でも動くようにしようとすれば、

はい、おっしゃるとおりです。
付け焼刃な修正をして申し訳ありません。