我目前正在试验一个非常简单的Boyer-Moore变体
通常我的实现工作,但如果我尝试在循环中使用它,包含干草堆的字符指针搞砸了。我的意思是其中的人物被改变或混合
结果是一致的,即多次运行相同的测试会产生相同的螺旋。
这是循环代码:
string src("This haystack contains a needle! needless to say that only 2 matches need to be found!");
string pat("needle");
const char* res = src.c_str();
while((res = boyerMoore(res, pat)))
++res;
这是我对字符串搜索算法的实现(上面的代码调用了一个方便的包装器,它可以拉出字符串和字符串的长度):
unsigned char*
boyerMoore(const unsigned char* src, size_t srcLgth, const unsigned char* pat, size_t patLgth)
{
if(srcLgth < patLgth || !src || !pat)
return nullptr;
size_t skip[UCHAR_MAX]; //this is the skip table
for(int i = 0; i < UCHAR_MAX; ++i)
skip[i] = patLgth; //initialize it with default value
for(size_t i = 0; i < patLgth; ++i)
skip[(int)pat[i]] = patLgth - i - 1; //set skip value of chars in pattern
std::cout<<src<<"\n"; //just to see what's going on here!
size_t srcI = patLgth - 1; //our first character to check
while(srcI < srcLgth)
{
size_t j = 0; //char match ct
while(j < patLgth)
{
if(src[srcI - j] == pat[patLgth - j - 1])
++j;
else
{
//since the number of characters to skip may be negative, I just increment in that case
size_t t = skip[(int)src[srcI - j]];
if(t > j)
srcI = srcI + t - j;
else
++srcI;
break;
}
}
if(j == patLgth)
return (unsigned char*)&src[srcI + 1 - j];
}
return nullptr;
}
循环产生了这个输出(即这些是算法收到的干草堆):
正如您所看到的,输入在第二次运行后完全搞砸了。我错过了什么?我认为内容无法修改,因为我正在传递const
指针
在循环中设置指针的方法是错误的,还是我的字符串搜索搞砸了?
Btw:这是完整的代码,除了包含和循环代码的主要功能。
修改
第一次返回时丢失的nullptr
是由于复制/粘贴错误造成的,因为它实际上存在于源中。
为了澄清,这是我的包装函数:
inline char* boyerMoore(const string &src, const string &pat)
{
return (const char*) boyerMoore((const unsigned char*) src.c_str(), src.size(),
(const unsigned char*) pat.c_str(), pat.size());
}
答案 0 :(得分:1)
在boyerMoore()
函数中,第一个返回值不是返回值(您只有return;
而不是return nullptr;
)GCC并不总是警告丢失返回值,而不返回任何内容是未定义的行为。这意味着当您将返回值存储在res
中并再次调用该函数时,无法确定将打印出来的内容。您可以看到related discussion here。
另外,你省略了便利函数来计算你传入的字符串的长度。我建议仔细检查那个逻辑以确保大小正确 - 我假设你正在使用{{ 1}}或类似的。