我正在努力理解递归,我想我已经好了......我正在尝试构建一个搜索函数(比如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_”它仍然停留在''(空间) - >我怎么能让它'重置's指针?
答案 0 :(得分:9)
++
。您不是试图循环数据结构并以某种方式更改本地变量 - 您每次都试图生成一个全新但更小的问题。因此,所有++
运算符 - 无论是前增量还是后增量 - 都是红旗。您有多个子问题。(...所以单个函数递归并不理想)。
让我们系统地看一下。
假设你有一个工作index_of
而你只想用比你短的输入来调用它,并且干草堆和针都不是空的。那么两件事之一可能是:
大海捞针以与针相同的字母开头,您只需要更深入一点来验证这一点。
- 验证成功后会发生什么 - 如果失败怎么办?这是一个index_of
子问题吗?
......或者大海捞针开始出错,你需要深入了解。
- 正在深入研究干草堆的index_of子问题吗?
请注意,如果haystack 启动确定它并不一定意味着它以完整搜索字符串开头 - 如果它启动正常但没有以完整的搜索字符串开头,你真的不需要继续寻找。这意味着“启动”子问题与子问题的索引根本不同:
可能来说startswith(haystack, needle):= 0==index_of(haystack, needle)
,但显然index_of
是一个更复杂的问题,而且解决方案更加昂贵 - 所以你不应该这样做;起初它也更令人困惑。
确定您的基本情况 - 当针头或干草堆为空时,这是什么意思?
好名字有助于澄清事情,并且在最好的时候很难阅读递归 - 例如Yacoby的回复在这里有一些有意义的选择。
我不打算为你解决你自己的谜题,但回顾一些提示......
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&使用相同的参数,第一次调用它。 (它永远不会回到++ i)。
另外,纯粹是文体,但由于返回类型是一个int,你应该返回0,并保存NULL以便与指针一起使用。
答案 3 :(得分:0)
这里的主要问题是你使用后增量,而(i ++)的结果是i。你必须使用++ i