指定長度的strstr函數

前一段工作中用到了,找了幾個方法。都實現了一下,測試了下,都差不多,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);
}


發佈了24 篇原創文章 · 獲贊 12 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章