我支持使用Borland C ++ Builder 5.02(从1997年)编写的C ++应用程序。 Borland字符串类中的find()方法不符合我的预期:
#include <cstring>
#include <iostream>
int main (int argc, char *argv[])
{
string needle = "length == eighteen";
string haystack = "<" + needle + ">";
if (haystack.find(needle) != NPOS)
cout << "Found it!" << endl;
else
cout << "Not found" << endl;
return 0;
}
此程序输出Not found
。如果我将针更换为更短的针,则输出Found it!
。如果我为其他角色交换尖括号,则会找到它。空间有效,但括号也没有。
请注意,我在这里使用Borland字符串库:如果我#include <string>
并使用std::string
,那么它的工作方式与我的预期相符。遗憾的是,改变整个应用程序以使用STL字符串并不是一个可行的答案!
从文档中可以看出Borland使用基于散列的算法进行字符串搜索。我找不到更多有关这方面的细节,而且我已经完成了反汇编,但并不是更明智。
我发现很难相信这确实是字符串库中的一个错误,特别是因为如果是这样的话,我希望能够找到一篇关于它的文章或其他内容。我找不到任何此类信息。
然而,我已经没想完了!这是一个已知的错误?有修复吗?
编辑:再看一下反汇编,我认为它正在尝试做类似Rabin-Karp算法的事情,其中哈希函数计算为mod 33554393(最大素数&lt; 2 ^ 25)。它很可能是基数为32的多项式散列函数(即a_0 + 32 a_1 + 32 ^ 2 a_2 + .. + 32 ^ n a_n)但这只是一种预感。听起来丹尼尔费舍尔建议可能出现溢出。答案 0 :(得分:2)
我从1998年发现了一个引用,表明Borland的搜索字符串实现有一个错误:
https://groups.google.com/forum/?fromgroups=#!searchin/borland.public.cpp.language/cstring $ 20bug / borland.public.cpp.language / XBzjaJmCYpk / gtMPm-j8jugJ
此外,似乎在历史的某个时刻,C ++委员会认为字符串类是标准C ++的一部分,而cstring的字符串类是这个的残余:
https://groups.google.com/forum/?fromgroups=#!searchin/borland.public.cpp.language/borland $ 20cstring / borland.public.cpp.language / 2psY2seRmS4 / ywVrqwU1C2wJ
答案 1 :(得分:2)
如果您有原始的BC ++ 5.02安装盘,则可以在BC5 \ SOURCE \ RTL \ SOURCE \ STRING下找到字符串类源。
以下是string :: find_case_index()函数代码的摘录(由string :: find()调用):
const long q = 33554393L;
const long q32 = q<<5;
size_t testlength = length() - startindex;
size_t patternlength = patl = strlen(cp);
if( testlength < patternlength )
return NPOS;
if( patternlength == 0 )
return 0;
long patternHash = 0;
long testHash = 0;
const char _FAR *testP = c_str()+startindex;
const char _FAR *patP = cp;
long x = 1;
size_t i = patternlength-1;
while( i-- )
x = (x<<5)%q;
for( i=0; i<patternlength; i++ )
{
patternHash = ( (patternHash<<5) + *patP++ ) % q;
testHash = ( (testHash <<5) + *testP++ ) % q;
}
testP = c_str()+startindex;
const char _FAR *end = testP + testlength - patternlength;
while (1)
{
if(testHash == patternHash)
if( !get_paranoid_check_flag() ||
!strncmp( testP, cp, patternlength) )
return (size_t)(testP-c_str());
if( testP >= end )
break;
// Advance & calculate the new hash value:
testHash = ( testHash + q32 - *testP * x ) % q;
testHash = ( (testHash<<5) + *(patternlength + testP++) ) % q;
}
return NPOS; // Not found.
答案 2 :(得分:1)
您没有使用Borland字符串库。 String
(大写S)是Borland字符串类。 string
(小写s)与std::string
完全相同,是STL字符串类,它不是Borland实现(BCB5中的STL是RogueWave STL)。您对#include <cstring>
的使用可能会将std::string
带入全局命名空间,这就是您的代码编译的原因。但您确实应该使用#include <string>
和std::string
代替。对于NPOS
,您应该使用string::npos
,因为这是string::find()
实际返回的内容。
#include <cstring>
#include <iostream>
int main (int argc, char *argv[])
{
string needle = "length == eighteen";
string haystack = "<" + needle + ">";
if (haystack.find(needle) != string::npos)
cout << "Found it!" << endl;
else
cout << "Not found" << endl;
return 0;
}
或者:
#include <string>
#include <iostream>
int main (int argc, char *argv[])
{
std::string needle = "length == eighteen";
std::string haystack = "<" + needle + ">";
if (haystack.find(needle) != std::string::npos)
std::cout << "Found it!" << std::endl;
else
std::cout << "Not found" << std::endl;
return 0;
}