谁能解释这个简单逻辑背后的逻辑?我迷路了

Posted

技术标签:

【中文标题】谁能解释这个简单逻辑背后的逻辑?我迷路了【英文标题】:Can anyone explain the logic behind this simple logic? I'm lost 【发布时间】:2017-05-25 01:56:35 【问题描述】:

我只是在 C++ 中尝试 do while 循环,而我想出了一个想法,即在 do while 循环中的 while 之后的括号内包含描述或任何名称,可以做多项事情。 所以这是我的初始逻辑:我已经设置了一个 password 变量和一个 input 变量。如果这两件事匹配,那么它将退出循环并输出“正确的密码”,否则它将继续返回循环,输出“错误的密码”等等。这是我的代码:

// do while
#include<iostream>
using namespace std;
int main()
    int input, password=19960819;
    do
        cout << "Type your password:" ;
        cin >> input;
    while(input!=password && cout << "wrong password" << endl); 
    cout << "correct password" << endl;
    return 0;

我期待即使我输入了正确的答案,我仍然会输出“错误密码”。我认为cout &lt;&lt; "wrong password" &lt;&lt; endl 部分将始终返回为true,无论如何也应该执行,并且唯一的因素是input!=password 部分。然而,结果实际上是完美的,这不是我所期望的......谁能解释一下逻辑?我一直在挑战自己不要使用if 或其他逻辑,而只是使用do while 逻辑来达到这个结果,但我不明白它现在工作的原因......

【问题讨论】:

在您最喜欢的 C++ 书籍中了解 &amp;&amp;(和 ||)的“短路”行为。 值得注意的是,如果你的逻辑期望两个语句都被执行,那么即使短路会导致错误,但对于其他事情来说真的很重要,比如能够做到if ((foo != nullptr) &amp;&amp; (foo-&gt;bar())) 【参考方案1】:

C++ 将short-circuit evaluation 用于内置1 布尔运算符,这意味着当您这样做时:

A && B

仅当Atrue 时才计算B,因为如果Afalse,则整个表达式为false(无论B 的值如何)。

所以在:

input != password && cout << "wrong password" << endl

input != passwordfalse 时(输入正确密码时),第二个操作数cout &lt;&lt; "wrong password" &lt;&lt; endl 不求值,因此不输出任何内容。


条件评估的额外细节:

input != password的类型是boolcout &lt;&lt; "..." &lt;&lt; endl的类型是std::ostream&amp;std::ostream 是 convertible to bool 直接(自 C++11 起)或使用转换为 void* (C++03)。

由于没有operator&amp;&amp;(bool, [const] std::ostream&amp;),并且std::ostream可以转换为bool,所以这里使用了内置的operator&amp;&amp;(bool, bool),所以应用短路评估2

input != passwordtrue(您输入了错误的密码)时,cout &lt;&lt; "..." &lt;&lt; endl 被评估,然后转换为bool 值,大部分时间将由true 进行3,从而允许循环继续。

input != passwordfalse 时,短路会阻止评估cout &lt;&lt; "..." &lt;&lt; endl,并且不会将任何内容发送到输出。

1 对于重载的运算符,短路评估不再适用。见http://en.cppreference.com/w/cpp/language/operator_logical。

2 您可以在main 之前为&amp;&amp; 添加用户定义的重载,例如bool operator&amp;&amp;(bool b, std::ostream &amp;s) return b &amp;&amp; (bool)s; ,看到短路只适用于内置运算符。

3 不能保证这会返回true,因为流可能处于失败状态,但对于std::cout,这不太可能 .

【讨论】:

我会注意到短路只适用于内置类型,而不是当运算符重载时。 @FrançoisAndrieux:实际上只有当&amp;&amp;过载时它才不再适用。 @Bathsheba 是 en.cppreference.com/w/cpp/language/operator_logical 不正确吗? "但重载运算符的行为类似于常规函数调用,并且总是计算两个操作数" @CaptainGiraffe 你可以有一个内置类型,例如A,可转换为bool,因此A() &amp;&amp; A()将与非内置类型进行短路。 ...正是这里发生了什么。最后,&amp;&amp; 始终是一个排序点。【参考方案2】:

cout &lt;&lt; "wrong password" &lt;&lt; endl 的计算结果始终为 true(通过转换为 bool 运算符)并具有输出该文本的副作用。

但由于&amp;&amp; 的短路性质,这仅在input != password 时进行评估。

真的很可爱。不过就个人而言,我会写

while (input != password &amp;&amp; std::cout &lt;&lt; "wrong password\n");

请注意,这依赖于 std::basic_ios::operator bool,它从 C++11 发生了微妙的变化。见http://en.cppreference.com/w/cpp/io/basic_ios/operator_bool。在许多方面,最好避免使用这种华而不实的代码。

【讨论】:

谢谢@Bathsheba,现在一切都说得通了:)【参考方案3】:

这是因为 && 和 ||在短路评估。因此,例如,如果 A 和 B 都(并且只有两者)都为真,则 A && B 将评估为真,但是(这里是短路)如果 A 或 B 为假,则它会为假,所以当 A 为假时,不需要评估B。

在您的场景中,当比较 'input!=password' 为 false(即 input == password)时,它会停止计算表达式。

希望这会有所帮助:)

对不起我的英语。

【讨论】:

谢谢,现在明白了~

以上是关于谁能解释这个简单逻辑背后的逻辑?我迷路了的主要内容,如果未能解决你的问题,请参考以下文章

代码背后的逻辑

ASCII码的排序背后有啥逻辑吗?

包含“for”循环的这行代码背后的逻辑解释是什么?

这个加速度计传感器监听器背后使用了啥逻辑

无法理解这个字谜问题解决方案背后的逻辑[关闭]

DAO是啥啊?谁能帮忙解释一下??