当前位置: 首页 > 知识库问答 >
问题:

为什么去掉这个return语句会影响整个递归函数的结果?

姜经武
2023-03-14

我正在使用递归编写回文检查器。我很困惑为什么删除

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

返回false,此时应返回true。

通过测试,表明基本大小写是使用最后一个回文输入的,这意味着函数将其视为有效的回文。但是,我假设程序然后展开调用堆栈,并且当它遍历所有之前的函数调用时,有些东西使函数返回false。

共有3个答案

沈博达
2023-03-14

从非无效函数返回而不通过back关键字显式返回值会调用未定义的行为。根据C规范,调用未定义行为的程序实际上可以自由地做任何事情,并且任何导致的奇怪行为的所有责任都将归咎于编写调用未定义行为的代码的程序员。

在这种情况下,实际可能发生的情况是,当您的函数通过放下函数的结尾返回时(并且不执行< code>return false),存储函数返回值的位置根本不会被写入——这意味着,就调用代码而言,函数返回的值将等于函数返回时恰好出现在该位置的值。在该位置预先存在的值将是任意的和难以预测的,因为它是关于程序如何执行的各种细节的结果,因此程序的行为也将是任意的和难以预测的。

解决方案是确保始终显式返回值;在编译器中启用警告将允许它在您忘记在某些代码路径中返回值时发出警告,从而帮助您完成该任务。

曹季同
2023-03-14

可能是

// ...

if (tempCleanText.at(firstChar) == tempCleanText.at(lastChar))

{
   return palindromeCheck(tempCleanText, ++firstChar, --lastChar); 
}

else
    return false;
// ...
高运诚
2023-03-14

首先,这个函数在任何情况下都是不正确的。例如,对于字符串< code >“1231”,函数返回< code>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

将被完全移除。

对于您的问题,如果没有最后一个返回语句,函数将具有未定义的行为,因为它在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
 类似资料:
  • 为什么以下未有效使用的行(在方法中:getAllDefinedVars)会对最终结果产生影响: List collect=AllVars.Stream().Filter(v->false).collect(Collectors.ToList()); 如果我删除整个方法和调用此方法的一行代码(generateOneSetOfBools中的第一行),我最终会得到另一个结果。 如果... 提到的行对列表

  • 我在构建递归函数时继续遇到一个问题,其中返回的值与我期望返回的值不同。我很确定这与函数的递归性质有关,但我不知道发生了什么。 在这个缩小的例子中,我有一个带有字符串的函数foo和一个默认值为0的int。给定字符串“测试”并且没有整数,我希望递归函数为每个调用增加numberToBack并将新值传递给下一个调用。这一定是部分正确的,因为如果我在到达基本情况时cout numberToBack,我将获

  • 我试图编写一个函数repeat(s:String,n:Int),它将串接字符串s n次并返回它,但由于某种原因,我没有得到正确的结果,并且得到了一个错误,即它不是尾部递归的,我在逻辑上很难理解为什么它不是尾部递归的。 在连接完成之前,是否必须处理递归?我该如何解决这个问题?使递归重复(s,n-1)不起作用,因为它会递归s太多次,但我不确定还有什么其他方法可以做到。 ps:我这么做主要是为了练习递归

  • return语句用来从一个函数 返回 即跳出函数。我们也可选从函数 返回一个值 。 使用字面意义上的语句 例7.7 使用字面意义上的语句 #!/usr/bin/python # Filename: func_return.py defmaximum(x, y):     ifx > y:         returnx     else:         returny printmaximum(

  • 问题内容: 目前,我正在努力学习Python,而在递归函数方面却陷入了停滞。在Think Python中 ,练习之一是编写一个函数,该函数使用以下定义来确定 a 是否为 b 的幂: “如果a被b整除,则a是b的幂,而a / b是b的幂。编写一个名为is_power的函数,该函数接受参数a和b,如果a是b的幂,则返回True。” 我函数的当前状态是: 实际上,这产生了我期望的结果。但是,本章着重于编

  • 很抱歉问了一个关于已经讨论过很多次的论点的非常基本的问题,我就是想不出答案。我试着在论坛上搜索已经在主题上提出的问题,但没有找到确切的答案(或者不理解)。 当以不同顺序调用时,为什么此函数会打印两次从i到10的数字?它不应该按同样的顺序打印出来吗?我一直听说递归就是这样工作的:每个函数在其代码中调用另一个相同的函数,只应用于较小的域,直到满足结束条件为止。此时,它应该返回(回溯)到原始函数;这就是