【问题标题】:Recursive strstr function递归 strstr 函数
【发布时间】:2015-02-14 12:16:26
【问题描述】:

使用以下签名编写函数strstr,使其成为递归函数(不是递归包装器)。

简而言之,strstr 返回 substr 首先出现在 str 中的位置的索引,如果没有找到,则返回 -1。更多here

这是我的尝试:

int strstr1(char *str, char *substr){

    if (*str == 0 || *substr == 0)//basis, if any of the strings is empty, will return -1
        return -1;
    else{
        strstr1(str + 1, substr); //forward the address of str
        if (*str == *substr)    //for each level check if the first char matches, then it should match each pair
            strstr(str + 1, substr + 1);

但我被卡住了。我意识到在递归中可能需要回溯,但我不知道如何去做,也不知道如何通过所有级别的递归传递索引......

请问有什么提示或建议吗?

【问题讨论】:

  • 你的 strstr() 函数可以调用其他函数。在 str1 中匹配 str2 的第一个字符后,只要下一个字符也匹配,就可以递归调用“strmatch()”。如果整个 str2 匹配,strmatch() 将返回成功,否则失败。如果它返回成功,你就完成了。如果返回失败,则递归地进入 str1 并在第一个字符匹配后重试。
  • @user2225104 但是如何将正确的索引传递到所有级别?
  • 返回索引时似乎需要原始指针或累加器。
  • 为用户函数使用库名称是一个非常糟糕的主意。我知道这应该是一个学习练习,但他们可以将函数命名为 my_strstr() 或其他名称。
  • 不需要“回溯”。您只需要正确地进行递归,返回递归调用的返回值。return strstr(str + 1, substr);

标签: c function recursion


【解决方案1】:

"Real" strstr() 返回一个 char *(或 const char *)。在 C++ 标准中,有 2 个重载。为了避免链接器问题,我将 strstr() 重命名为 strstr1()。

#include <stdio.h>
#include <string.h>

int strmatch( const char *str, const char *substr)
{
    while ( '\0' != (*substr) && (*str == *substr) )
    {
        substr++;
        str++;
    }
    if( '\0' == *substr )
        return 0;
    else
        return -1;
}

const char * strstr1( const char *str, const char* substr)
{
    printf("strstr(%s,%s)\n", str,substr );
    if( '\0' == (*str) )
        return NULL;
    if( *str == *substr )
    {
        if( 0 == strmatch( str, substr ) )
        {
            return str; // success value or something.
        }
    }
    return strstr1( str + 1, substr );
}



int main( int argc, const char * argv[] )
{
    const char * s1 = "Hello World";
    const char * ss1 = "World";

    if( NULL != strstr1( s1, ss1 ) )
    {
        printf("%s contains %s!\n", s1, ss1 );
    }
    else
    {
        printf("%s does not contain %s!\n", s1, ss1 );
    }

    const char * s2 = "Hello Universe";
    const char * ss2 = "World";

    if( NULL != strstr1( s2, ss2 ) )
    {
        printf("%s contains %s!\n", s2, ss2 );
    }
    else
    {
        printf("%s does not contain %s!\n", s2, ss2 );
    }

    const char * s3 = "Hello World World World World";
    const char * ss3 = "World";

    const char * foo = s3;
    while( NULL != foo )
    {
        foo = strstr1( foo, ss3 );
        if( NULL != foo )
        {
            puts("another match!");
            foo = foo + strlen(ss3);
        }
        else
        {
            puts("no more matches.");
        }
    }

    return 0;
}

【讨论】:

  • 我确实指定了...它应该返回匹配位置的索引。就像原来的 strstr 函数(我链接的)一样。
  • @kuhaku "real" strstr() 返回一个字符 *。 cplusplus.com/reference/cstring/strstr
  • 好吧,我确实指定了。
  • @kuhaku 但是为什么你的代码使用 int 作为返回值呢?好吧-这是您的完整作业;) 顺便说一句,您也可以递归地编写 strmatch() 。最后同样重要的是,C/C++ 不支持尾递归,因此,如果你的字符串太长,就会发生堆栈溢出。
【解决方案2】:

使用以下规则:如果 substr 是空字符串,则查找 strstr 的规范以找到您应该返回的内容。否则,如果 str 为空字符串,则返回 NULL。否则,如果 strcmp (str, substr) == 0 则返回 str。否则,返回 strstr (str + 1, substr)。

也就是说,这是一个相当愚蠢的递归示例,因为实际上您会使用一个循环,只要 *str != '\0' 就将 str 增加 1。

也就是说,strstr 是一个标准库函数。如果您实现一个名为 strstr 的函数,您将有未定义的行为。如果你实现了一个名为 strstr 的函数,它的规范与标准库函数不同,你最终会进入 DS。

【讨论】:

  • 那些规则没有意义。我的意思是,这绝对是不正确的。
  • 看C标准。规则将准确返回 C 标准库函数 strstr 将返回的内容。并且可以完全忽略名为 strstr 的函数的任何其他规范。当你说它绝对不正确时,你肯定可以告诉我哪里错了。但我打赌你不能。
  • 是的,我知道它应该有一个不同的名称,另外,int 函数如何返回 NULL 或 str??
  • @gnasher729:好吧... strcmp?你需要strncmp
猜你喜欢
  • 2013-05-30
  • 2015-03-01
  • 2010-12-23
  • 1970-01-01
  • 2010-12-25
  • 2023-04-02
  • 2016-01-06
相关资源
最近更新 更多