簡體   English   中英

C ++中的遞歸布爾函數

[英]Recursive Boolean Function in C++

我對C ++相對較新(大多數情況下通常都是編程),並且正在參加在線課程,其后進行教學以建立游戲為目標。 在控制台應用程序項目之一中,我們必須編寫代碼來詢問用戶是否要再次玩游戲。該部分程序的目標是要求用戶僅鍵入“ y”或“ n”來進行答復然后重新詢問該問題,即用戶是否通過其他方式做出響應。

我已經嘗試編寫執行此操作的代碼,據我所知,代碼工作正常。 我的問題是,我編寫的代碼在以下意義上是否有效:

  1. 代碼將成功完成概述的任務嗎?
  2. 如果這樣的代碼在以后增加,是否會出現更多錯誤?

我的代碼如下。 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM