2017-04-16 147 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.