如果在fizzbuzz

时间:2015-08-11 04:28:44

标签: c++ fizzbuzz

我尝试在C ++中实现fizzbuzz,并且对以下代码示例产生的不同输出感到困惑:

int main()
{
    int val1 = 1;
    while (val1 < 101) {
        if (val1 % 15 == 0)
            cout << "FizzBuzz\n";
        if (val1 % 3 == 0)
            cout << "Fizz\n";
        if (val1 % 5 == 0)
            cout << "Buzz\n";
        else cout << val1 << "\n";
        ++val1;
    }
    keep_window_open();
}

对于15的所有倍数,此代码输出

FizzBuzz
Fizz
Buzz

而不只是FizzBuzz。所有(仅)5的倍数都被Buzz正确替换,但所有3的倍数打印出Fizz,然后打印出数字本身。

但是,以下代码完美无缺。如果使其正常工作,我得到了else,但是当val1 = 3,或5或15时,我只是没有看到代码路径是什么。

int main()
{
    int val1 = 1;
    while (val1 < 101) {
        if (val1 % 15 == 0)
            cout << "FizzBuzz\n";
        else if (val1 % 3 == 0)
            cout << "Fizz\n";
        else if (val1 % 5 == 0)
            cout << "Buzz\n";
        else cout << val1 << "\n";
        ++val1;
    }
    keep_window_open();
}

4 个答案:

答案 0 :(得分:3)

在第一个例子中:

    if (val1 % 15 == 0)
        cout << "FizzBuzz\n";
    if (val1 % 3 == 0)
        cout << "Fizz\n";
    if (val1 % 5 == 0)
        cout << "Buzz\n";
    else cout << val1 << "\n";

每个案例都将在每次迭代中进行测试。由于15的所有倍数也是35的倍数,因此您将在屏幕上打印所有三个。

在另一种情况下:

    if (val1 % 15 == 0)
        cout << "FizzBuzz\n";
    else if (val1 % 3 == 0)
        cout << "Fizz\n";
    else if (val1 % 5 == 0)
        cout << "Buzz\n";
    else cout << val1 << "\n";

第一种情况(val1 % 15 == 0)将被测试,如果它是假的,第二种情况将被测试,如果它是假的,第三种情况将被测试。这意味着只有第一个从上到下的四个案例才会在每次迭代中测试为真。

例如,如果您要颠倒515的顺序:

    if (val1 % 5 == 0)
        cout << "FizzBuzz\n";
    else if (val1 % 3 == 0)
        cout << "Fizz\n";
    else if (val1 % 15 == 0)
        cout << "Buzz\n";
    else cout << val1 << "\n";

你会得到Buzz永远不会被打印出来,因为如果每个15值都可以分割,你就会停止第一个val1 % 5 == 0测试,因此打印FizzBuzz

答案 1 :(得分:1)

代码首先捕获的数字是15的倍数,这意味着它们是3 5的倍数。在这种情况下,它会打印“FizzBu​​zz”。任何未通过此测试的数字可能是3 5的倍数,但不是两者。接下来的两个 if 语句分别检查3或5的倍数

while (val1 < 101) {
    if (val1 % 15 == 0)           // multiple of 3 AND 5
        cout << "FizzBuzz\n";
    else if (val1 % 3 == 0)       // multiple of ONLY 3
        cout << "Fizz\n";
    else if (val1 % 5 == 0)       // multiple of ONLY 5
        cout << "Buzz\n";
    else cout << val1 << "\n";
    ++val1;
}

答案 2 :(得分:1)

您的else仅属于最后一个if

if (val1 % 15 == 0)
    cout << "FizzBuzz\n";

if (val1 % 3 == 0)
    cout << "Fizz\n";

if (val1 % 5 == 0)
    cout << "Buzz\n";
else // any val1 which doesn't divide by 5
    cout << val1 << "\n";

这就是为什么,如果val1不能被5整除,它会输出这个值。

此外,15可以被15,5和3整除。它触发所有三个if并输出所有三行。

您可以使用else if来获得正确的结果,但最好的方法是在完成条件下终止执行。 例如,如果你有一个函数,你就可以这样做:

string GetOutput(int val)
{
    if (val % 15 == 0) return "FizzBuzz";
    if (val % 3 == 0) return "Fizz"; // 2. val % 15 != 0 implied
    if (val % 5 == 0) return "Buzz"; // 3. val % 15 != 0 && val % 3 != 0 implied
    return to_string(val1); // 4. val % 15 != 0 && val % 5 != 0 && val % 3 != 0 implied
}

int main() {
   cout << GetOutput(val) << endl;
}

它可以工作,因为执行在true条件终止,并且任何条件检查都意味着所有先前的都是假的。在这个例子中,这两个规则保证是正确的:

1. If execution is at lines 2 or 3 - val is not divisible by 15
2. If execution is at line 4 - val is not divisible by 3, 5 and 15

使用这种方法,您无需手动描述这些条件 而且,如果你有越来越多的条件,那么维护和读取这样的函数要比编写很长的逻辑条件容易得多。

例如,

string GetOutput(int val)
{
    if (val % 64 == 0) return "FizzBuzz"; // such wow
    if (val % 32 == 0) return "Fizz"; // much readable
    if (val % 16 == 0) return "Buzz";
    if (val % 8 == 0) return "Muzz";
    if (val % 4 == 0) return "Guzz";
    if (val % 2 == 0) return "Duzz";
    return "Hizz";
}

而不是

if (val % 64 == 0) cout << "FizzBuzz";
if (val % 64 != 0 && val % 32 == 0) cout << "Fizz";
if (val % 64 != 0 && val % 32 != 0 && val % 16 == 0) cout << "Buzz";
if (val % 64 != 0 && val % 32 != 0 && val % 16 != 0 && val % 8 == 0) cout << "Muzz";
if (val % 64 != 0 && val % 32 != 0 && val % 16 != 0 && val % 8 != 0 && val % 4 == 0) cout << "Guzz";
if (val % 64 != 0 && val % 32 != 0 && val % 16 != 0 && val % 8 != 0 && val % 4 != 0 && val % 2 == 0) cout << "Duzz";
if (val % 64 != 0 && val % 32 != 0 && val % 16 != 0 && val % 8 != 0 && val % 4 != 0 && val % 2 != 0) cout << "Hizz";

if (val % 64 == 0) 
{
    cout << "FizzBuzz";
} else {
    if (val % 32 == 0)
    {
        cout << "Fizz";
    } else {
        if (val % 16 == 0) 
        {  
            cout << "Buzz";
        } else {
            if (val % 8 == 0)
            {
                cout << "Muzz";
            } else {
                if (val % 4 == 0)
                {
                    cout << "Guzz";
                } else { 
                    if (val % 2 == 0)
                    {
                        cout << "Duzz";
                    } else {
                        cout << "Hizz";
                    }
                }
            }
        }
    }
}

答案 3 :(得分:1)

15的倍数也是 5的倍数和3的倍数。else上一个 em>如果不是为真,那么就做..“;因此,在一系列非互斥条件中删除它会改变逻辑。

但是,请考虑条件可以互相排斥:

if (val1 % 15 == 0)
    cout << "FizzBuzz\n";

if (val1 % 3 == 0 && !(val1 % 15 == 0))
    cout << "Fizz\n";

if (val1 % 5 == 0 !(val1 % 15 == 0))
    cout << "Buzz\n";

if (!(val1 % 3 == 0) && !(val1 % 5 == 0)) // implies !(val1 % 15 == 0)
    cout << val1 << "\n";

在这种情况下,对于任何整数值,if条件中仅一个将为真。

我还更改了最终else,以显示跨所有路径扩展的互斥。话虽如此,我建议编写这样的代码。

从另一个角度来看,每个else if序列都可以写成'嵌套树'。语义完全相同,但结构可以使路径更容易可视化。在这种情况下,应该清楚的是每个终端案例(“cout”)彼此互斥。

if (val1 % 15 == 0) {
    cout << "FizzBuzz\n";
} else {
    if (val1 % 3 == 0) {
        cout << "Fizz\n";
    } else {
        if (val1 % 5 == 0) {
            cout << "Buzz\n";
        } else {
            cout << val1 << "\n";
        }
    }
}