C ++中的递归布尔函数

时间:2018-01-18 02:32:51

标签: c++ recursion boolean

我对C ++(以及大部分编程)都比较陌生,而且我正在开设一个在线课程,其目的是建立一个游戏。在其中一个控制台应用程序项目中,我们必须编写代码,询问用户是否要再次玩游戏。该程序的那部分目标是通过仅键入“y”或“n”来要求用户回复如果用户通过做其他事情做出回应,则重新询问问题。

我试图编写执行此操作的代码,据我所知,代码工作正常。我的问题是,我写的代码是否在以下意义上有效:

  1. 代码是否会成功完成概述的任务?
  2. 如果这样的代码在以后增长时会出现更多错误吗?
  3. 我遵循的代码。在main函数中:

    .
    .
    .
    do
    {
        PlayGame();
    }
    while (AskToPlayAgain());
    

    AskToPlayAgain的函数定义以及恰当的描述:

    bool AskToPlayAgain()
    {
     bool Play = true;
     string response = "";
     cout << "Would you like to play again? y/n... ";
     getline(cin, response);
    
     if (response == "y") { }
    
     else if (response != "n")
     {
         cout << "Please enter a valid response." << endl;
         // We want AskToPlayAgain called again to ask for a proper response again; however,
         // just calling it outside a conditional will cause the current "Play" value to be returned.
         // This value is true by default and this function will return it even if "n" is entered after
         // an invalid response. As such, in this case, we want this function to be called in the event
         // of an invalid response which will always happen and we don't want the return value of the nested
         // AskToPlayAgain function to be returned, which is true by default unless the program has successfully exited.
         // Furthermore, once the nested AskToPlayAgain returns false, we want the program to exit and not return the "Play"
         // (which is set to true) by the higher level AskToPlayAgain.
    
         if (AskToPlayAgain()) { }
         else { return false; }
     }
    
     else
     {
         Play = false;
         cout << "Thank you for playing! :D" << endl;
     }
    
     return Play;
    }
    

    我在代码注释中提出的推理是否有效?是否有测试用例会失败?我尝试了一些测试用例,但所有测试用例都有效。

    非常感谢您提供任何帮助!

2 个答案:

答案 0 :(得分:3)

您的递归方法没有任何问题,但您可以通过循环简化此操作,并避免与递归相关的潜在问题。循环和递归密切相关。 if (response == "y") { }没有错,但这是一个奇怪的编程习惯。如果你在达到这个条件时不打算做任何事情,那就不要费心去测试了。

使用while循环的另一种方法:

bool AskToPlayAgain()
{
    while(true)
    {
        string response;
        cout << "Would you like to play again? y/n... ";
        getline(cin, response);

        if(response == "y")
        {
            return true;
        }
        else if(response == "n")
        {
            cout << "Thank you for playing! :D" << endl;
            return false;
        }

        cout << "Please enter a valid response." << endl;
    }
}

<小时/> 的 编辑

另一个递归函数的例子:

这次我们为演示添加counter值。

如果您运行此程序并继续提供无效输入,那么counter将会上升。它显示了递归函数如何等待所有其他递归函数完成。

我添加了未使用的char buf[1000]。它的目的是引起问题!

潜在问题:每个函数需要分配1000字节堆栈内存(加上函数中其他堆栈变量的内存,以及std::string的堆内存)。在函数存在之前,不释放该内存,因此它会建立起来。程序中的堆栈限制是几兆字节,所以现在可能存在堆栈溢出错误。

bool AskToPlayAgain(int counter)
{
    char buf[1000]; //<-- allocate lots of stack memory to cause problems!
    cout << "counter start: " << counter << " - memory allocated\n";

    cout << "play again? y/n... ";
    string response;
    getline(cin, response);

    if(response == "y")
    {
        return true;
    }
    else if(response == "n")
    {
        cout << "Thank you for playing! :D\n";
        return false;
    }

    cout << "invalid response\n";
    bool result = AskToPlayAgain(counter + 1);

    cout << "counter: " << counter << " - memory cleanup\n";
    return result;
}

int main()
{
    do
    {
        printf("play...\n");
    } while(AskToPlayAgain(1));
    return 0;
}

因此,最好使用循环来支持递归函数。但是再一次,递归函数有时是有用的,如果内存分配受到控制(如在你的例子中)并且有明确的路径来打破递归,那么继续使用它。

答案 1 :(得分:2)

我建议您在AskToPlayAgain()函数中检查response == "y"response == "n",然后执行else部分。虽然这不会对您的代码产生太大影响,但它更容易阅读和理解,如果稍后出现问题,您将不必花费太多时间再次查看代码。

即。

if (response == "y") { }

else if (response == "n"){
    // your code
}
else {
    // your code to handle the invalid response
}


另外,正如@Barmak Shemirani在评论和答案中所建议的那样,最好只使用一个循环来完成重复询问的任务,直到有效的回复。它比具有多个函数调用“更便宜”。