前一段工作中用到了,找了幾個方法。都實現了一下,測試了下,都差不多,glibc的實現方法相比還是快一些,stristrex也不慢,至於qi_strnstr,是自己的一個想法實現的,不過可悲的是,他是最慢的。
char *glibc_strnstr (const char *phaystack, const char *pneedle, int len)
{
typedef unsigned chartype;
const unsigned char *haystack, *needle;
const unsigned char *rneedle;
chartype b;
const unsigned char *pEnd = (const unsigned char *)phaystack + len;
haystack = (const unsigned char *) phaystack;
if ((b = *(needle = (const unsigned char *) pneedle)))
{
chartype c;
haystack--; /* possible ANSI violation */
{
chartype a;
do
{
a = *++haystack;
if (pEnd == haystack)
goto ret0;
}
while (a != b);
}
if (!(c = *++needle))
goto foundneedle;
++needle;
goto jin;
for (;;)
{
{
chartype a;
if (0)
jin:{
if ((a = *++haystack) == c)
goto crest;
}
else
a = *++haystack;
do
{
for (; a != b; a = *++haystack)
{
if (pEnd <= haystack || pEnd <= haystack + 1 )
goto ret0;
if ((a = *++haystack) == b)
break;
}
}while ((a = *++haystack) != c);
}
crest:
{
chartype a;
{
const unsigned char *rhaystack;
if (*(rhaystack = haystack-- + 1) == (a = *(rneedle = needle)) && pEnd > rhaystack)
do
{
if(!a)
goto foundneedle;
if (*++rhaystack != (a = *++needle))
break;
if(!a)
goto foundneedle;
}while (*++rhaystack == (a = *++needle) && pEnd > rhaystack);
needle = rneedle; /* took the register-poor aproach */
}
if(!a)
break;
}
}
}
foundneedle:
return (char *) haystack;
ret0:
return 0;
}
char *qi_strnstr (const char *phaystack, const char *pneedle, int len)
{
int needlelen = strlen(pneedle);
if( len < needlelen )
return NULL;
int cmplen = len-needlelen;
const char* pEnd = phaystack + cmplen;
for( char* pCur = (char*)phaystack; pCur <= pEnd ; pCur++ )
{
char* pneedCur = (char*)pneedle;
char* phayCur = pCur;
int ilen = needlelen;
for( ; ilen; )
{
if( ilen >= 8 )
{
if( *(var_u8*)phayCur != *(var_u8*)pneedCur )
break;
ilen-=8;
phayCur += 8;
pneedCur += 8;
}
else if( ilen >= 4 )
{
if( *(var_u4*)phayCur != *(var_u4*)pneedCur )
break;
ilen-=4;
phayCur += 4;
pneedCur += 4;
}
else if( ilen >= 2 )
{
if( *(var_u2*)phayCur != *(var_u2*)pneedCur )
break;
ilen-=2;
phayCur += 2;
pneedCur += 2;
}
else if( ilen >= 1 )
{
if( *(var_u1*)phayCur != *(var_u1*)pneedCur )
break;
ilen-=1;
phayCur += 1;
pneedCur += 1;
}
}
if(ilen == 0)
return (char*)pCur;
}
return NULL;
}
static char* _stristrex( const char * src, long src_len, const char * substr, long substr_len )
{
char ch, chOtherCase;
const char * p;
const char * pend;
if ( src == NULL || 0==*src || substr == NULL || 0==*substr || src_len <= 0 || substr <= 0 )
{
return NULL;
}
ch = *substr;
chOtherCase = ch;
if ( ch >= 'a' && ch <= 'z')
{
chOtherCase = ch - 'a' + 'A';
}
else if (ch > 'A' && ch <= 'Z')
{
chOtherCase = ch - 'A' + 'a';
}
p = src;
pend = p + src_len;
while ( p < pend )
{
if ( *p == ch || *p == chOtherCase )
{
if ( strnicmp( p, substr, substr_len ) == 0)
{
return (char*)p;
}
}
p++;
}
return NULL;
}
static char* strnstr( const char * src, long src_len, const char * substr, long substr_len )
{
char ch, chOtherCase;
const char * p;
const char * pend;
if ( src == NULL || 0==*src || substr == NULL || 0==*substr || src_len <= 0 || substr <= 0 )
{
return NULL;
}
p = src;
pend = p + src_len - substr_len;
while ( p < pend )
{
if ( *p == *substr )
{
if ( memcmp( p, substr, substr_len ) == 0)
{
return (char*)p;
}
}
p++;
}
return NULL;
}
用測試程序測試了一下。最簡單的strnstr是最快的。
static void test_strnstr()
{
var_1 *strAll = "abcdefghijklmno./pqrstuvwxyzadfefsdffcbthddfhnapdsfou4htgfunovnchxb v89cb df90v8ua=g0fvn p 0aer9g8h=3240tgin 4]eg 0e4tg8h4]g08b9gf ";
var_1 *strfnd = "u4htgfunovnchxb";
var_4 len = strlen(strAll);
var_4 cs = 100*1000000;
var_4 start = GetTickCount();
printf("start = %llu,cs=%d\n", start,cs);
while(cs--)
{
var_4 pos = rand()%10;
glibc_strnstr(strAll, strfnd,len - pos);
//printf("%s\n",strAll+pos);
}
printf("glibc_strnstr耗時 = %d\n\n", GetTickCount()-start);
cs = 100*1000000;
start = GetTickCount();
printf("start = %llu,cs=%d\n", start,cs);
while(cs--)
{
var_4 pos = rand()%10;
qi_strnstr(strAll, strfnd,len - pos);
//printf("%s\n",strAll+pos);
}
printf("qi_strnstr耗時 = %d\n\n", GetTickCount()-start);
cs = 100*1000000;
start = GetTickCount();
printf("start = %llu,cs=%d\n", start,cs);
while(cs--)
{
var_4 pos = rand()%10;
_stristrex(strAll, len - pos, strfnd, 12);
//printf("%s\n",strAll+pos);
}
printf("_stristrex耗時 = %d\n\n", GetTickCount()-start);
cs = 100*1000000;
start = GetTickCount();
printf("start = %llu,cs=%d\n", start,cs);
while(cs--)
{
var_4 pos = rand()%10;
strnstr(strAll, len - pos, strfnd, 12);
//printf("%s\n",strAll+pos);
}
printf("strnstr耗時 = %d\n\n", GetTickCount()-start);
}