2017-04-16 139 views
0

我想爲我的程序做一個簡單的驗證用戶名和密碼。 我不知道什麼是錯我的代碼,但我想我有一些邏輯錯誤C++驗證登錄代碼

這裏是我的一段代碼

  string usernameinput,passinput; 
string username[]={"mmm","nnnn","rrrr","aaa"}; 
string password[]={"1234","1212","1234","1212"}; 
bool flag=false; 

while(flag==false){ 
    cout << "username: "<<endl; 
    cin>>usernameinput; 
    cout << "password: "<<endl; 
     cin>>passinput; 
     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; 
      } 

     } 
} 
+0

題外話:而不是密碼和用戶名分離成自己陣列使用配對結構將它們分組,並只有一個陣列。需要較少的簿記。 – user4581301

回答

0

你不需要第二if聲明,else就足夠了。即使你保留它,它也必須是||而不是&&,因爲任何一個不匹配都會將標誌設置爲false。

事實上,你甚至不需要else聲明。由於您將標誌初始化爲false,因此它將保持爲false,直到它被設置爲true,這隻有在用戶名和密碼都匹配時纔會發生。一旦匹配,您想停止比較,因此您必須使用break來結束for循環。錯誤消息應該在for循環之外,因爲您不希望它顯示,直到您檢查完所有值。

bool flag=false; 

while(flag==false){ 
    cout << "username: "<<endl; 
    cin>>usernameinput; 
    cout << "password: "<<endl; 
    cin>>passinput; 
    for(int i=0;i<=3;i++){ 
     if(usernameinput ==username[i] && passinput==password[i]) 
     { 
      flag=true; 
      break; 
     } 
    } 
    if(!$flag) { 
     cout<<"please enter correct username and password"<<endl; 
    } 
} 
0

問題

程序不會停止找到一個匹配後搜索匹配。由於比賽結束後測試的數值將不匹配,因此會出現混亂。

讓我們來看,當我們爲分別MMM和用戶名和密碼,輸入執行下面的代碼出現這種情況:

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:

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; 
    } 

現在,因爲沒有任何事情告訴程序匹配已經找到,我們可以停止查找,我們繼續進行迭代2:

if("mmm" == "nnnn" && "1234" == "1212") // false 
    { 
     flag=true; 
    } 
    else if ("mmm" != "mmm" && "1234" != "1234") // both false, enter 
    { 
     flag=false; // flag is now false Ooops. 
     cout<<"please enter correct username and password"<<endl; 
    } 

輸出,即使憑據是正確的,flag將是錯誤的,用戶將被警告三次漏報。呸。

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仍然是錯誤的,入侵者沒有進入,但這看起來很醜,仍然給你三條錯誤信息。我們可以做得更好。

解決方案

做一個函數:

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; 
} 

注意,檢查密碼函數什麼都不做,但檢查的憑據。所有與用戶的通信都在其他地方完成。這使得該功能很簡單。它只做一件事,它是由函數名稱描述的一件事。

安全提示:在向用戶返回消息之前等待一些小的隨機數量的時間。這與試圖通過對響應進行計時來猜測憑證的大小或憑證數據庫的大小的任何人的首腦混淆。

這可以通過將用戶名和密碼配對並只有一個數組進行進一步清理。這可確保用戶名與密碼匹配,並且沒有人添加用戶名而不添加密碼。

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.