問題
プログラムは、一致が検出された後、一致の検索を停止しません。試合後にテストされた値は一致しないので、混乱が続く。今
if("mmm" == "mmm" && "1234" == "1234") // both true. Enter
{
flag=true; // flag is now true
}
else if ("mmm" != "mmm" && "1234" != "1234")
{
flag=false;
cout<<"please enter correct username and password"<<endl;
}
:
for(int i=0;i<=3;i++){
if(usernameinput ==username[i] && passinput==password[i])
{
flag=true;
}
else if (usernameinput !=username[i] && passinput!=password[i])
{
flag=false;
cout<<"please enter correct username and password"<<endl;
}
}
反復1:我々はMMMとユーザー名とパスワードの、それぞれの入力のために次のコードを実行したときに起こる
レッツ・ウォッチプログラムに一致が見つかったことを示すものは何もないので、探しを止めることができます。繰り返し2に進みます:
出力は、資格情報が正しい場合でも、flag
はfalseになり、ユーザーはfalse negativeに3回警告されます。ヤック
please enter correct username and password
please enter correct username and password
please enter correct username and password
マッチしたときにループを終了する必要がありました。明白な解決策は次のようなものです:
if(usernameinput ==username[i] && passinput==password[i])
{
flag=true;
break;
}
しかし、待ってください!もっとたくさん!入力がmmmとの場合はどうなりますか?
反復1:
if("mmm" == "mmm" && "1235" == "1234") //Second case fails
{
flag=true;
break;
}
else if ("mmm" != "mmm" && "1234" != "1234") // first case fails
{
flag=false;
cout<<"please enter correct username and password"<<endl;
}
我々はいずれかの場合は入力しないでください。 flag
は偽のままで、侵入者は侵入しませんが、これはちょっと醜いように見えますが、3つのエラーメッセージが表示されます。私たちはより良いことができます。
ソリューション
機能を作成します。
bool checkcredentials(const std::string & uname,
const std::string & pword)
{
bool rval = false;
for(int i=0;i<=3;i++)
{
if(uname== username[i])
{
if (pword==password[i])
{
rval = true; // could just return true here, but some folk get uptight
// over multiple returns in a function
}
break;
}
}
return rval;
}
呼び出し関数は、チェック・パスワード機能は何もしないことを
if (checkcredentials(usernameinput, passinput))
{
// let the user in.
}
else
{
cout<<"please enter correct username and password"<<endl;
}
ノートのようなものがありませんが、資格情報を確認してください。ユーザーとのコミュニケーションはすべて他の場所で行われます。これにより、関数は単純なままになります。それは一つのことだけを行い、それは関数名で記述されるものです。
セキュリティ上の注意:ユーザーにメッセージを返す前に、少し時間がかかります。これは、レスポンスを計時することによって、資格情報のサイズまたは資格データベースのサイズを推測しようとしている人の頭部と混乱します。
これは、ユーザー名とパスワードをペアにしてアレイを1つだけ設定することで、さらにクリーンアップすることができます。これにより、ユーザー名がパスワードと一致し、パスワードを追加せずにユーザー名を追加したユーザーはいません。
pair<string, string> credentials[]={ // array of pairs
{"mmm", "1234"},
{"nnnn", "1212"},
{"rrrr", "1234"},
{"aaa", "1212"}
};
bool checkcredentials(const std::string & uname,
const std::string & pword)
{
bool rval = false;
for(auto & cred: credentials)
{
if(uname == cred.first)
{
if (pword == cred.second)
{
rval = true;
}
break;
}
}
return rval;
}
Documentation on pair.
そして、これは、よりスマートなデータ構造を改善することができます。 map
は、キー、ユーザー名に基づいてこの例では値、パスワードを参照する関連コンテナです。
オフトピック
map<string, string> credentials={
{"mmm", "1234"},
{"nnnn", "1212"},
{"rrrr", "1234"},
{"aaa", "1212"}
};
bool checkcredentials(const std::string & uname,
const std::string & pword)
{
auto cred = credentials.find(uname); // look for user name
if (cred != credentials.end() && // username exists
cred->second == pword) // password matches
{
return true;
}
return false;
}
Documentation on map.
:というよりも、自分の配列にパスワードとユーザー名を分離するには、グループにそれらをペアリング構造を使用し、唯一の配列を持っています。帳簿の節約が必要です。 – user4581301