为什么这个 while 循环在询问名称之前执行两次

发布于 2024-12-11 21:05:30 字数 732 浏览 0 评论 0原文

我有一个函数可以验证用户的名字和姓氏。但是, while 循环执行了两次,我找不到原因......任何帮助

string getName()
{
     string name = "";
     bool stop = false;
     string::iterator it;

     while(!stop)//name validation loop
     {
           cout << "enter name: ";
           getline(cin, name);

           for(it = name.begin(); it < name.end(); it++)
           {
                if(tolower(*it) > 'z' || tolower(*it) < 'a' && tolower(*it) != ' ') 
                { 
                      cout << "Error, only letters! \n"; 
                      break;
                }
                if(it == name.end()-1) { stop = true; }
           }
           cout << "here\n";
     }
     return name;
}

I have a function which validates a user's first and last name. However, the while loop executes twice, and I can't find out why.... any help

string getName()
{
     string name = "";
     bool stop = false;
     string::iterator it;

     while(!stop)//name validation loop
     {
           cout << "enter name: ";
           getline(cin, name);

           for(it = name.begin(); it < name.end(); it++)
           {
                if(tolower(*it) > 'z' || tolower(*it) < 'a' && tolower(*it) != ' ') 
                { 
                      cout << "Error, only letters! \n"; 
                      break;
                }
                if(it == name.end()-1) { stop = true; }
           }
           cout << "here\n";
     }
     return name;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

时光病人 2024-12-18 21:05:30

如果 cin 缓冲区中仍有一些 newspace 字符,则可能会发生这种情况。 std::ws 从流中正确文本之前提取空格,例如换行符、空格、制表符。尝试一下:

string getName()
{
     string name = "";
     bool stop = false;
     string::iterator it;

     while(!stop)//name validation loop
     {
           cout << "enter name: ";
           std::cin >> std::ws;   // <--- drop whitespaces
           getline(cin, name);

           for(it = name.begin(); it < name.end(); it++)
           {
                if(tolower(*it) > 'z' || tolower(*it) < 'a' && tolower(*it) != ' ') 
                { 
                      cout << "Error, only letters! \n"; 
                      break;
                }
                if(it == name.end()-1) { stop = true; }
           }
           cout << "here\n";
     }
     return name;
}

It may happen if there is still some newspace character in cin buffer. std::ws extracts white spaces like newline character, space, tabulator from stream before right text. Try that:

string getName()
{
     string name = "";
     bool stop = false;
     string::iterator it;

     while(!stop)//name validation loop
     {
           cout << "enter name: ";
           std::cin >> std::ws;   // <--- drop whitespaces
           getline(cin, name);

           for(it = name.begin(); it < name.end(); it++)
           {
                if(tolower(*it) > 'z' || tolower(*it) < 'a' && tolower(*it) != ' ') 
                { 
                      cout << "Error, only letters! \n"; 
                      break;
                }
                if(it == name.end()-1) { stop = true; }
           }
           cout << "here\n";
     }
     return name;
}
棒棒糖 2024-12-18 21:05:30

您的循环存在一些问题,这就是我重写它的方式,使其与您的实现尽可能相似:

string getName()
{
   bool stop;
   string name;
   string::iterator it;

   do {
      stop = true;
      cout << "enter name: ";
      getline(cin, name);

      for(it = name.begin(); it < name.end(); it++)
      {
          if( (tolower(*it) > 'z' || tolower(*it) < 'a') && tolower(*it) != ' ' )
          { 
                cout << "Error, only letters! \n"; 
                stop = false;
                break;
          }
      }
      cout << "here\n";

     } while (!stop);

   return name;
}

使用您在这里的内容:

if(tolower(*it) > 'z' | | tolower(*it) < 'a' && tolower(*it) != ' ')

由于 & 具有更高的优先级,因此它相等到:

if(tolower(*it) > 'z' ||(tolower(*it) <'a ' && tolower(*it) != ' '))

这不是你想要的。

编辑:因为' '(空格)是< 'a' 你的代码实际上不会引起问题,但我不确定你是故意这样做的。

我也不喜欢这样: if(it == name.end()-1) { stop = true; },并且 do...while 循环更适合。

编辑:您可能还想添加对空输入(所有空格)的检查,因为这看起来是一个无效的名称。

编辑(再次): Loki 是对的,在调用 getName 之前,输入流上必须有垃圾。您可以使用 Mścisław 的解决方案或 cin.ignore()

There are a few problems with your loop and this is how I'd rewrite it, keeping it as similar to your implementation as possible:

string getName()
{
   bool stop;
   string name;
   string::iterator it;

   do {
      stop = true;
      cout << "enter name: ";
      getline(cin, name);

      for(it = name.begin(); it < name.end(); it++)
      {
          if( (tolower(*it) > 'z' || tolower(*it) < 'a') && tolower(*it) != ' ' )
          { 
                cout << "Error, only letters! \n"; 
                stop = false;
                break;
          }
      }
      cout << "here\n";

     } while (!stop);

   return name;
}

With what you had here:

if(tolower(*it) > 'z' || tolower(*it) < 'a' && tolower(*it) != ' ')

Due to && having higher precedence, it equates to:

if(tolower(*it) > 'z' ||(tolower(*it) < 'a' && tolower(*it) != ' '))

which is not what you want.

EDIT: since ' ' (space) is < 'a' your code won't actually cause problems, but I'm not sure you did it like that on purpose.

I also don't like this: if(it == name.end()-1) { stop = true; }, and a do...while loop is better suited.

EDIT: You might also want to add a check for empty input (all whitespace), since that would seem an invalid name.

EDIT(again): Loki's right, you must have junk on the input stream before calling getName. You can use Mścisław's solution or cin.ignore().

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文