C ++递归问题<confused> </confused>

时间:2010-02-12 15:48:57

标签: c++ pointers recursion search

我正在努力理解递归,我想我已经好了......我正在尝试构建一个搜索函数(比如std :: string.find()),它在给定的字符串中搜索另一个字符串例如:

  

给(大)字符串:“ru the running cat”   

搜索(小)字符串:“运行”

我正在尝试返回我正在搜索的单词的索引(在上面的情况下它将是** 7)我的递归方法如下 - 我似乎无法得到它正确地返回索引。

调用递归函数:

index = index_of(imput.c_str(), search.c_str())

递归方法:

int index_of( const char * i, const char * s) {
 int j;
 if (*s == '\0') { return; }
 if (*i == '\0') {
  return NULL;
 }
 else if ( *i == *s ) {
  index_of((i++), (s++));
 }
 else {
  j += index_of((i++), s);
 }
 return j;
}

另一个可预见的问题是,当(例如 - 好的它很糟糕但我需要一个有效)它到达“ru_”它仍然停留在''(空间) - &gt;我怎么能让它'重置's指针?

4 个答案:

答案 0 :(得分:9)

  1. 请勿更改任何状态变量。您的代码不应包含运算符++ 。您不是试图循环数据结构并以某种方式更改本地变量 - 您每次都试图生成一个全新但更小的问题。因此,所有++运算符 - 无论是前增量还是后增量 - 都是红旗。
  2. 您有多个子问题。(...所以单个函数递归并不理想)。

    让我们系统地看一下。

    假设你有一个工作index_of而你只想用比你短的输入来调用它,并且干草堆和针都不是空的。那么两件事之一可能是:

    • 大海捞针以与针相同的字母开头,您只需要更深入一点来验证这一点。
      - 验证成功后会发生什么 - 如果失败怎么办?这是一个index_of子问题吗?

    • ......或者大海捞针开始出错,你需要深入了解。
      - 正在深入研究干草堆的index_of子问题吗?

    请注意,如果haystack 启动确定它并不一定意味着它以完整搜索字符串开头 - 如果它启动正常但没有以完整的搜索字符串开头,你真的不需要继续寻找。这意味着“启动”子问题与子问题的索引根本不同:

    • index_of :此处,未能在索引0处找到搜索字符串意味着您需要进一步查看。
    • starts_with :此处,未能在索引0处找到搜索字符串意味着您需要停止。

    可能来说startswith(haystack, needle):= 0==index_of(haystack, needle),但显然index_of是一个更复杂的问题,而且解决方案更加昂贵 - 所以你不应该这样做;起初它也更令人困惑。

  3. 确定您的基本情况 - 当针头或干草堆为空时,这是什么意思?

  4. 好名字有助于澄清事情,并且在最好的时候很难阅读递归 - 例如Yacoby的回复在这里有一些有意义的选择。

  5. 摘要

    我不打算为你解决你自己的谜题,但回顾一些提示......

    • 避免更改局部变量:您正在尝试定义子问题,然后只为那些较新的较短参数调用正确的函数。不要使用副作用,它们会使事情变得非常复杂。
    • 递归并不一定意味着只有一个函数A调用A - 它可以是最终终止的任何循环调用图;你可以使用更多功能
    • 如果针头和干草堆以相同的字母开头,这并不意味着整个针头都在大海捞针的开头 - 如果不是,你还需要继续搜索
    • 这一行错误:if (*s == '\0') { return 1; }

答案 1 :(得分:4)

我就是这样做的,它通过将其移动到不同的功能来简化一切。未经测试但希望能给你一个想法。

/**
 * Checks if one string starts with another string. This returns an
 * incorrect result if it is called where prefix is an empty string.
 */
bool starts_with_impl(const char* haystack, const char* prefix) {
    if ( *prefix == 0 ){ 
        //reached the end of prefix without having found a difference in characters
        return true;
    }else if ( *haystack == 0 || *prefix != *haystack ){
        //either prefix is longer than haystack or there is a difference in characters.
        return false;
    }
    //move along the haystack and prefix by one character
    return starts_with_impl(++haystack, ++prefix);
}
/**
 * Wrapper around starts_with_impl that returns false if prefix is an empty string
 */
bool starts_with(const char* haystack, const char* prefix) {
    return *prefix ? starts_with_impl(haystack, prefix) : false;
}

int get_substr_impl(const char* haystack, const char* const needle, int index) {
    if ( *haystack == 0 ){
        //reached the end of haystack with no match, -1 is no string found
        return -1;
    }else if ( starts_with(haystack, needle) ){
        //we have found a substring match.
        return index;
    }
    //move along haystack by one character
    return get_substr_impl(++haystack, needle, ++index);
}
/**
 * Wrapper function for the above to hide the fact we need an additional argument.
 * I am avoiding using a default argument as it makes a messy api
 */
int get_substr(const char* haystack, const char* const needle) {
    return get_substr_impl(haystack, needle, 0);
}

来自评论

  

你在get_substr_impl方法中有2个const ....

故意。

// means that the data is constant, in other words I can't change the value of needle
const char* needle;

//means that as well as the data being constant 
//I can't change the address that the pointer points to.
const char* const needle;
  来自main方法的

我不会用get_substr中给出的相同参数调用teh get_substr_impl吗?

我把它分开,因为get_substr_impl有一个额外的(必需的)参数int index,它是函数内部工作所必需的,应该始终从0开始。你可以调用get_substr_impl("abc", "a", 0); ,它看起来更好,调用get_substr("abc", "a");更容易理解,它可以避免错误(比如调用get_substr_impl("abc", "a", 1);

答案 2 :(得分:3)

首先,您的代码中有两个i。这甚至不应该编译。

此外,index_of((i++), (s++));实际上与:

相同
index_of(i, s); 
++i;
++s;

换句话说,你调用index_of over&amp;使用相同的参数,第一次调用它。 (它永远不会回到++ i)。

另外,纯粹是文体,但由于返回类型是一个int,你应该返回0,并保存NULL以便与指针一起使用。

答案 3 :(得分:0)

这里的主要问题是你使用后增量,而(i ++)的结果是i。你必须使用++ i