[英]Why does the removal of this return statement affect the outcome of the entire recursive function?
我正在使用遞歸編寫回文檢查器。 我很困惑為什么要刪除
return true
函數末尾的語句會影響返回值。
int firstChar = 0;
int lastChar = 0;
// These two variables are used to transverse the string from both ends
// eventually meeting
代碼#1:
bool palindromeCheck (string text, int firstChar, int lastChar)
{
string tempCleanText = text;
// Removes all punctation and space
if (firstChar == 0)
{
// Cleans text, ignore.
tempCleanText = cleanString(tempCleanText);
// Sets this variable to the end of the string
lastChar = tempCleanText.size() - 1;
}
// Base Case
if (firstChar >= lastChar)
{
return true;
}
if (tempCleanText.at(firstChar) == tempCleanText.at(lastChar))
{
palindromeCheck(tempCleanText, ++firstChar, --lastChar);
}
else
{
return false;
}
return true; // Keeping this in works
}
這將返回 true,對於所有回文應該是這樣,對於所有非回文返回 false。
代碼#2:
bool palindromeCheck (string text, int firstChar, int lastChar)
{
string tempCleanText = text;
// Removes all punctation and space.
if (firstChar == 0)
{
// Cleans text, ignore.
tempCleanText = cleanString(tempCleanText);
// Sets this variable to the end of the string
lastChar = tempCleanText.size() - 1;
}
// Base Case
if (firstChar >= lastChar)
{
return true;
}
if (tempCleanText.at(firstChar) == tempCleanText.at(lastChar))
{
palindromeCheck(tempCleanText, ++firstChar, --lastChar);
}
else
{
return false;
}
// there is no return true here, and so the output is no longer correct
}
這僅對某些回文返回 true,對所有非回文返回 false。
回文,例如,
amanaplanacanalpanama <- 尺寸長度 21
返回 false,當它應該返回 true 時。
通過測試,顯示基本情況是使用最后一個回文輸入的,這意味着函數將其視為有效的回文。 但是,我假設程序然后展開調用堆棧,並且當它執行所有先前的函數調用時,某些事情會使函數返回 false。
對於初學者來說,該功能在任何情況下都是不正確的。 例如,對於字符串"1231"
,函數返回true
。 我希望你能自己檢查一下。
這部分功能
if (tempCleanText.at(firstChar) == tempCleanText.at(lastChar))
{
palindromeCheck(tempCleanText, ++firstChar, --lastChar);
}
else
{
return false;
}
return true; // Keeping this in works
至少應該替換以下代碼片段
if (tempCleanText.at(firstChar) == tempCleanText.at(lastChar))
{
return palindromeCheck(tempCleanText, ++firstChar, --lastChar);
}
else
{
return false;
}
那就是這個返回語句
return true; // Keeping this in works
將被完全刪除。
至於您的問題,那么如果沒有最后一個 return 語句,該函數具有未定義的行為,因為它在 if 語句之后不返回任何內容。 這就是 if 語句
if (tempCleanText.at(firstChar) == tempCleanText.at(lastChar))
{
palindromeCheck(tempCleanText, ++firstChar, --lastChar);
}
else
{
return false;
}
成功執行,前提是
tempCleanText.at(firstChar) == tempCleanText.at(lastChar))
執行 if 語句的子語句后,函數返回什么? 沒有! :)
此外,除了字符串本身之外,聲明兩個附加參數(索引)也沒有意義,因為在任何情況下,字符串都是按值傳遞的,您始終可以通過調用成員函數size()
來獲取其大小。
我可以建議該函數的以下實現與您的函數類似,該函數實現在傳遞空字符串的情況下返回 true。
#include <iostream>
#include <iomanip>
#include <string>
#include <cctype>
bool palindromeCheck( std::string s )
{
if ( s.size() < 2 )
{
return true;
}
else if ( ispunct( ( unsigned char )s.front() ) || isspace( ( unsigned char )s.front() ) )
{
return palindromeCheck( s.substr( 1 ) );
}
else if ( ispunct( ( unsigned char )s.back() ) || isspace( ( unsigned char )s.back() ) )
{
return palindromeCheck( s.substr( 0, s.size() - 1 ) );
}
else if ( s.front() == s.back() )
{
return s.size() == 2 ? true : palindromeCheck( s.substr( 1, s.size() - 2) );
}
else
{
return false;
}
}
int main()
{
std::cout << std::boolalpha << palindromeCheck( "" ) << '\n';
std::cout << std::boolalpha << palindromeCheck( "1" ) << '\n';
std::cout << std::boolalpha << palindromeCheck( "1 1" ) << '\n';
std::cout << std::boolalpha << palindromeCheck( "1,2,2,1" ) << '\n';
std::cout << std::boolalpha << palindromeCheck( "1 2 3 2 1" ) << '\n';
std::cout << std::boolalpha << palindromeCheck( "12341" ) << '\n';
return 0;
}
程序輸出是
true
true
true
true
true
false
或許
// ...
if (tempCleanText.at(firstChar) == tempCleanText.at(lastChar))
{
return palindromeCheck(tempCleanText, ++firstChar, --lastChar);
}
else
return false;
// ...
從非 void 函數返回而不通過return
關鍵字顯式返回值會調用undefined behavior 。 根據 C++ 規范,調用未定義行為的程序實際上可以自由地做任何事情,任何由此產生的怪異行為都將歸咎於編寫調用未定義行為的代碼的程序員。
在這種情況下可能實際發生的情況是,當您的函數通過刪除函數的末尾(並且不執行return false
)返回時,存儲函數返回值的位置根本不會被寫入 - 即意味着,就調用代碼而言,您的函數返回的值將等於您的函數返回時該位置碰巧出現的任何值。 該位置的預先存在的值將是任意且難以預測的,因為它是有關程序如何執行的各種細節的結果,因此程序的行為也將是任意且難以預測的.
解決方案是確保始終明確返回一個值; 如果您忘記在某些代碼路徑中返回值,則在您的編譯器中啟用警告將允許它通過警告您來幫助您完成該任務。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.