我目前正在试验一种非常简单的Boyer变体。
一般来说,我的实现可以工作,但是如果我试图在循环中使用它,包含干草堆的字符指针就会被搞砸。我的意思是里面的字符是被改变的或者是混合的。
结果是一致的,即运行相同的测试多次产生相同的错误。
这是循环代码:
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指针。
是在循环中设置指针的方式出错了,还是我的字符串搜索搞砸了?
顺便说一句:这是完整的代码,除了包含和循环代码的主要功能。
编辑:
第一次返回的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());
}发布于 2015-09-01 14:08:26
在您的boyerMoore()函数中,第一个返回不是返回一个值(您只有return;而不是return nullptr;) GCC并不总是对丢失的返回值发出警告,而不返回任何东西是未定义的行为。这意味着,当您将返回值存储在res中并再次调用该函数时,不知道将输出什么。你可以看到一个related discussion here。
此外,您还省略了计算要传入的字符串长度的方便函数。我建议对逻辑进行二次检查,以确保大小是正确的--我假设您使用的是strlen或类似的。
https://stackoverflow.com/questions/32332791
复制相似问题