此函数采用包含'*'和'?'的字符串wild
通配符,并使用nodeT *w
从树数据库中替换带有可能字符的通配符。 out
包含一个临时字符串。每个候选人都被添加到参考的bst。
void Lexicon::matchRegExpHelper(nodeT *w, string wild, Set<string> &matchSet, string out)
{
if (wild == "") matchSet.add(out);
else {
if (wild[0] != '*' || wild[0] != '?') { //this parses up to the wildcard, earlier versions used a position parameter and looped through the prefix chars recursively
for (int j = 0; j < w->alpha.size(); j++)
if (wild[0] == w->alpha[j].letter) matchRegExpHelper(w->alpha[j].next, wild.substr(1), matchSet, out+=wild[0]);
} else {
for (int i = 0; i < w->alpha.size(); i++) {
if (wild[0] == '?') matchRegExpHelper(w->alpha[i].next, wild.substr(1), matchSet, out+=w->alpha[i].letter);//follow path
else { //logically, wild[0] == '*' must be true
if (ontLength == (wild.length() + out.length())) matchRegExpHelper(w->alpha[i].next, wild.substr(1), matchSet, out+=w->alpha[i].letter); //ontology is full, treat like a '?'
else matchRegExpHelper(w->alpha[i].next, wild.substr(1), matchSet, out+=(w->alpha[i].letter+'*')); //keep adding chars
}
}
}
}
}
当第一个通配符到达时,函数重新开始 - 我尝试用for循环重写它,没有循环,以及不同的'prune'方法。我遗漏了一些基本的东西,并怀疑这是一个回溯问题。最终堆栈溢出。
问题:1)我在概念上缺少什么,以及2)如何修复此功能?
没有for循环的版本 - 测试用例有点不同但相似,我必须测试才能再找到它
else {
if (wild[0] == '?'){
matchRegExpHelper(w, wild, ++pos, matchSet, out);//return and check next path
matchRegExpHelper(w->alpha[pos].next, wild.substr(1), 0, matchSet, out+=w->alpha[pos].letter);//follow path
}
if (wild[0] == '*'){
matchRegExpHelper(w, wild, ++pos, matchSet, out);//return and check next path
if (ontLength == (wild.length() + out.length()))matchRegExpHelper(w->alpha[pos].next, wild.substr(1), 0, matchSet, out+=w->alpha[pos].letter); //ontology is full, treat like a '?'
else matchRegExpHelper(w->alpha[pos].next, wild.substr(1), 0, matchSet, out+=(w->alpha[pos].letter+'*')); //keep adding chars
}
if (wild[0] == w->alpha[pos].letter) matchRegExpHelper(w->alpha[pos].next, wild.substr(1), 0, matchSet, out+=wild[0]);
matchRegExpHelper(w, wild, ++pos, matchSet, out);//check next path
}
for (int i = 0; i < w->alpha.size(); i++) matchRegExpHelper(w->alpha[i].next, wild.substr(1), 0, matchSet, out+=wild[0]);//step over char
最后的for循环是尝试修复溢出,我想也许某些线程没有任何情况,但我希望那些修剪,所以不知道该怎么做
答案 0 :(得分:2)
这种情况总是如此: (wild [0]!='*'|| wild [0]!='?')
因为任何一个角色都不同于两个中的一个,也许你的意思是(wild [0]!='*'&amp;&amp; wild [0]!='?')
我希望这有助于你取得一些进展......
从概念上讲,我通常不会在递归函数中使用'for',尝试重写它而不使用'for'可能它会更清晰,可能效率不高但是一旦它工作,你就可以开始微调算法了。
答案 1 :(得分:1)
每次递归都应该有一个基本终止条件。
我有种感觉
if (wild[0] != '*' || wild[0] != '?')
是错误的(该测试始终为真,因为某个字符不能同时为'*'
和'?'
),它应该是一个&&
合取而不是一个分离{ {1}}
但正如我在评论中所说,你真的应该学习如何使用debugger (即提出breakpoints,要求backtraces,查询价值变量)。
熟悉调试是一项技能,除了这个特定的程序(或家庭作业)之外,对你的一生都有价值。
答案 2 :(得分:0)
此代码存在三个问题:
@Basile_Starynkevitch注意到使用调试器遵循路径的重要性 - 在这种情况下使用VS2008,堆栈允许解析步骤并注意通过几个函数返回的路径。@Picarus正确地注意到终止条件中的错误
这些解决方案导致发现:
解决方案,这个void函数需要两个return;
,一个在终止条件之后终止,另一个在结束时捕获已修剪的线程。从阅读几个网站看来,似乎void函数中的return;
是不寻常的,但这种情况下有递归和多个路径,这是必需的。