質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

1106閲覧

ログイン機能が作れない

bob2017

総合スコア18

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2017/10/02 12:01

###前提・実現したいこと
ログイン機能
入力されたデータをファイルから読み取ったデータと同じかチェックする

###発生している問題
複数ユーザーのときできない

###該当のソースコード

C

1unsigned int Login(const char *username, const char *password) { 2 FILE *FilePointer; 3 char username2[USERNAME_MAX], password2[PASSWORD_MAX]; 4 short count = 0, EqualCount = 0, count2 = 0, equal = 0; 5 6 // Check username 7 if (fopen_s(&FilePointer, "files\system\usernames", "r") != 0) { 8 Error("Cannot open file."); 9 _getch(); 10 exit(EXIT_FAILURE); 11 } 12 while (fgets(username2, USERNAME_MAX, FilePointer) != NULL) { 13 count++; 14 if (!strcmp(username, username2)) { 15 EqualCount++; 16 break; 17 } 18 } 19 if (EqualCount == 0)return 1; 20 fclose(FilePointer); 21 22 // Check password 23 if (fopen_s(&FilePointer, "files\system\passwords", "r") != 0) { 24 Error("Cannot open file."); 25 _getch(); 26 exit(EXIT_FAILURE); 27 } 28 while (fgets(password2, PASSWORD_MAX, FilePointer) != NULL) { 29 count2++; 30 if ((count == count2) && (!strcmp(password, password2)))equal = 1; 31 } 32 fclose(FilePointer); 33 34 if (equal) { 35 strcpy_s(Username, USERNAME_MAX, username); 36 return 0; 37 } 38 else return 1; 39} 40

###補足情報(言語/FW/ツール等のバージョンなど)
VisualStudio2017
よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決

標準入力からの入力のときに改行文字を取り除いていたのに、ファイルからの入力のときには改行文字を取り除いておらず、それを比較したのが原因でした。

C

1if(username2[strlen(username2) - 1] == '\n') 2 username2[strlen(username2) - 1] = '\0';

を書き足して解決しました。

わざわざソースコードまで書いていただき本当にありがとうございました。

投稿2017/10/07 03:46

bob2017

総合スコア18

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

LouiS0616

2017/10/07 03:59

『関数を二回目以降に呼び出したとき、予期せぬ結果になる』だったのですね。 ファイル入力が絡んでくる処理は、サンプルデータがあるかどうかで解決のしやすさが断然違うので... 何らかの方法でダミーデータ自体を配布するか、生成するプログラムがあるといいですね。
bob2017

2017/10/07 04:14

そうではなく、ファイルにユーザー名とパスワードが書いてあって、main関数でユーザー名とパスワードを標準入力から入力し、それをlogin関数に渡し、0が返されたら成功として続行し、1が返されたら失敗としてエラーを出してもう一度入力させる設計になっています。 複数ユーザーのときできないというのは、ファイルに複数のユーザー名とパスワードが書いてあるときに、なぜかログインができないということです。これの原因が、入力の最後の改行文字を取り除いたのにもかかわらず、ファイルのほうは取り除いておらず、この二つを比較したことです。 改行文字の差でstrcmp関数は等しくないと処理したようです。 説明不足で本当にすみませんでした。
guest

0

複数ユーザーのときできない

質問がいくらでも多重解釈出来ますが、次のうちのどれかでしょうか。

  • 結果をグローバル変数で受け取りたい

グローバル変数Usernameで結果を受け取るという仮定によるもの。
ユーザ名を複数保存したいなら、これを配列にするしかないでしょう。
しかし、どうせloginに返り値を設定したのですから、グローバル変数は必要ないのでは。

C

1char login_users[LOGIN_USER_MAX][USERNAME_MAX] = {}; 2int uc = 0; 3while (uc < LOGIN_USER_MAX) { 4 char input_username[USERNAME_MAX] = {}; 5 char input_password[PASSWORD_MAX] = {}; 6 7 // 入力を受け付ける 8 9 if (!login(username, password)) { 10 strcpy_s(login_users[uc++], USERNAME_MAX, username); 11 } 12 13 if (入力を辞める) break; 14}
  • 多重ログインを出来るように関数を書き換えたい

やめといた方がいいでしょう。複数回関数を呼び出す設計にしましょう。

  • 関数を二回目以降に呼び出したとき、予期せぬ結果になる

テストデータがないのでなんとも言えません。再現できるデータを用意してください。

さて、どれでしょうかね。


とりあえず、関数loginはもうちょっと整理できます。

C

1typedef struct { 2 char username_[USERNAME_MAX]; 3 char password_[PASSWORD_MAX]; 4} LOGIN_INFO; 5 6int login_info_equals(const LOGIN_INFO *info1, const LOGIN_INFO *info2) { 7 if (strcmp(info1->username_, info2->username_) return -1; 8 if (strcmp(info1->password_, info2->password_) return -1; 9 return 0; 10} 11 12int login(const LOGIN_INFO *info) { 13 FILE *fp_username, *fp_password; 14 15 // Open files 16 if (fopen_s(&fp_username, "files\system\usernames", "r") != 0) { 17 Error("Cannot open file."); 18 system("PAUSE"); 19 exit(EXIT_FAILURE); 20 } 21 if (fopen_s(&fp_password, "files\system\passwords", "r") != 0) { 22 Error("Cannot open file."); 23 fclose(fp_username); 24 system("PAUSE"); 25 exit(EXIT_FAILURE); 26 } 27 28 // Check info 29 LOGIN_INFO tmp_info; 30 while (fgets(tmp_info.username_, USERNAME_MAX, fp_username) != NULL) 31 && fgets(tmp_info.password_, PASSWORD_MAX, fp_password) != NULL) { 32 33 if (!login_info_equals(info, &tmp_info)) { 34 fclose(fp_username); 35 fclose(fp_password); 36 return 0; 37 } 38 } 39 40 // Cannot find 41 fclose(fp_username); 42 fclose(fp_password); 43 return -1; 44}

デバッグはしてないです、どこかしらミスはあるかと思います。

投稿2017/10/02 13:48

編集2017/10/02 13:53
LouiS0616

総合スコア35660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問