[英]Recursive Boolean Function in C++
我對C ++相對較新(大多數情況下通常都是編程),並且正在參加在線課程,其后進行教學以建立游戲為目標。 在控制台應用程序項目之一中,我們必須編寫代碼來詢問用戶是否要再次玩游戲。該部分程序的目標是要求用戶僅鍵入“ y”或“ n”來進行答復然后重新詢問該問題,即用戶是否通過其他方式做出響應。
我已經嘗試編寫執行此操作的代碼,據我所知,代碼工作正常。 我的問題是,我編寫的代碼在以下意義上是否有效:
我的代碼如下。 在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;
}
我在代碼注釋中提出的推理有效嗎? 是否有一個測試用例會失敗? 我已經嘗試了一些測試用例,但是所有這些都有效。
非常感謝您對此提供的任何幫助!
遞歸方法沒有什么問題,但是您可以使用循環簡化此過程,並避免與遞歸相關的潛在問題。 循環和遞歸緊密相關。 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; }
因此,最好使用循環來支持遞歸函數。 但是再說一次,遞歸函數有時很有用,並且如果內存分配處於控制之下(如您的示例中所示),並且有明確的路徑可以打破遞歸,則繼續使用它。
我建議您在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的回答中所建議的那樣,最好使用循環來完成重復詢問直到得到有效答復的任務。 它比具有多個函數調用更“便宜”。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.