为什么这个简单的逻辑不起作用?

时间:2015-06-24 07:11:48

标签: c++

我无法弄清楚为什么while循环中的这个简单逻辑不起作用。

基本上该函数的作用是,它接受一个参数并检查while循环以查看它是否为“yes”或“no”然后继续循环。

void getAnswer(string answer) {

    string newAnswer = "";
    newAnswer = answer;
    while (newAnswer != "Yes" || newAnswer != "yes" || newAnswer != "Y" || newAnswer != "y" || newAnswer != "No" || newAnswer != "no") {
            cout << "Enter yes or no.." << endl;
            cin >> newAnswer;

        }

        if (newAnswer == "Yes" || newAnswer == "yes" || newAnswer == "Y" || newAnswer == "y") {
            chooseOptions();
        } else {
            cout << "Bye See you again " << endl;
            exit(1);
        } 
}

但即使我输入“是”或“否”,它仍会循环播放。

4 个答案:

答案 0 :(得分:17)

De Morgan's laws声明:

"not (A and B)" is the same as "(not A) or (not B)"

根据您的条件适用此法律:

newAnswer != "Yes" || newAnswer != "yes" || ...

!(newAnswer == "Yes" && newAnswer == "yes" && ...)

现在更容易理解为什么这是错误的。

如果newAnswer不是“是”或“是”,它将被评估为真,而这不是你想要的。

解决方案是将||更改为&&

答案 1 :(得分:6)

想一想。我问你一个是或否的问题。你告诉我&#34;不&#34;。

我走下我的名单,然后停下来,因为我得到了一个真实的陈述,因为那是什么逻辑或意味着什么。

newAnswer!=&#34;是&#34; &GT;&GT;真正。完成。继续循环。

很好,你说。这一次,你回答&#34;是&#34;。

newAnswer!=&#34;是&#34; &GT;&GT;假

newAnswer!=&#34;其他任何事情&#34; &GT;&GT;真正。完成。继续循环。

这是同义反复。它不可能使OR条件为假。你应该使用AND。

用你自己的话说,它不是&#34;而不是是或否&#34;但是&#34;虽然不是,但不是没有和不是n而不是y ...&#34;

答案 2 :(得分:2)

除了&amp;&amp;和和||所有的回答都谈到了,让我更进一步,使另一个谬误显而易见(不是真正的错误,而是设计上的弱点):你问&#34;是或否&#34;接受任何事情,如果答案看起来像是&#34;是&#34;你退出其他任何东西都像没有。甚至&#34;一杯咖啡&#34;。

反转所有逻辑具有相同的谬误:检查 N,n,否,否决定不退出意味着退出,如果&#34;茶和饼干&#34 ;得到回答。

此外,getAnswer接听并致电chooseOptions(后者将获得一些输入以提供给getAnswer):您不会循环:你正在重新开始。而且你正在从两个不同的地方做同样的事情(从输入中得到答案)。如果我想用其他流更改std::cin,会发生什么?一切都要改变?在多少个不同的地方?

更好的逻辑应该强迫答案保持一致。

在你的主程序中,你应该做的很像

bool do_exit = false;
while(!do_exit)
{
    //All useful stuff and then ...

    do_exit = getAnswer(std::cin, std::cout, 
      "Do you want to exit? [yes/no]", 
      "please answer yes or no");
}

或者,更简洁,

for(bool do_exit=false, !do_exit, do_exit=getAnswer(
      "Do you want to exit? [yes/no]", 
          "please answer yes or no") )
{
  //usefull stuff here
}

现在,让我们进入答案逻辑:

你必须得到一行输入(不只是一个单词:一行,因为我可以输入&#34;是的,我想&#34;),所以cin>>string不能很好地发挥作用:更好std::get_line。如果它是&#34;是&#34;返回true,如果&#34; no&#34;返回false,如果还有其他重复读数。

bool getAnswer(std::istream& istr, std::ostream& ostr, 
   const std::string& prompt, const std::string& reprompt)
{
  ostr << prompt << std::endl;
  for(;;)
  {
     std::string line;
     std::getline(istr,line);
     if(line == "yes" || line == "Yes" || line == "Y" || line == "y") 
        return true;
     if(line == "no" || line == "No" || line == "N" || line == "n") 
        return false;
     ostr << reprompt << std::end;
  }
}

这使你接受众所周知的&#34;是或否&#34;变种,但拒绝任何其他。

更进一步说,我们可以提出cin / cout可以是其他类型的流的想法,并且可能没有人&#34;打字&#34;。

为避免进入无限循环,我们可以引入尝试限制并在达到时抛出异常:

bool getAnswer(std::istream& istr, std::ostream& ostr, 
   const std::string& prompt, const std::string& reprompt)
{
  ostr << prompt << std::endl;
  for(int attempt=5; attempt>0; --attempt)
  {
     std::string line;
     std::getline(istr,line);
     if(line == "yes" || line == "Yes" || line == "Y" || line == "y") 
        return true;
     if(line == "no" || line == "No" || line == "N" || line == "n") 
        return false;
     if(attempt>1)
       ostr << reprompt << " ("<<attempt-1<<" attempts remaining)"<<std::endl;
  }
  throw std::domain_error("cannot get valid input");
}

让调用者最终捕获并执行其他操作,或最终正常终止。

此外,我们不仅可以参与i / o和问题的参数化,还可以参考答案,但这已经太过分了。

答案 3 :(得分:1)

逻辑如下:

如果你的字符串输入是yes

newAnswer != "yes"  --> false

newAnswer != "Yes" --> true
newAnswer != "Y" --> true
newAnswer != "y" --> true
newAnswer != "No" --> true 
newAnswer != "no" --> true

多个or和一个true的逻辑falsetrue。这意味着对于yes输入的输入,循环将继续。 如果您将所有or更改为and s,则多个and和一个true的逻辑false将为false。如果输入是yes输入,则循环将不会继续。