一些常见函数的内部实现(原)

一些常见函数的内部实现(原)

Wentao Sun

1. 子串查找:

/* strtok_s */
/*
 * strtok_s, wcstok_s ;
 * uses _Context to keep track of the position in the string.
 
*/
_SAFECRT__EXTERN_C
char * __cdecl strtok_s(char *_String, const char *_Control, char **_Context);

#if _SAFECRT_USE_INLINES

__inline
char * __cdecl strtok_s(char *_String, const char *_Control, char **_Context)
{
    unsigned 
char *str;
    
const unsigned char *ctl = (const unsigned char *)_Control;
    unsigned 
char map[32];
    
int count;

    
/* validation section */
    _SAFECRT__VALIDATE_POINTER_ERROR_RETURN(_Context, EINVAL, NULL);
    _SAFECRT__VALIDATE_POINTER_ERROR_RETURN(_Control, EINVAL, NULL);
    _SAFECRT__VALIDATE_CONDITION_ERROR_RETURN(_String != NULL || *_Context != NULL, EINVAL, NULL);

    /* Clear control map */
    
for (count = 0; count < 32; count++)
    {
        map[count] 
= 0;
    }

    
/* Set bits in delimiter table */
    
do {
        map[
*ctl >> 3|= (1 << (*ctl & 7));
    } 
while (*ctl++);

    
/* If string is NULL, set str to the saved
    * pointer (i.e., continue breaking tokens out of the string
    * from the last strtok call) 
*/
    
if (_String != NULL)
    {
        str 
= (unsigned char *)_String;
    }
    
else
    {
        str 
= (unsigned char *)*_Context;
    }

    
/* Find beginning of token (skip over leading delimiters). Note that
    * there is no token iff this loop sets str to point to the terminal
    * null (*str == 0) 
*/
    
while ((map[*str >> 3& (1 << (*str & 7))) && *str != 0)
    {
        str
++;
    }

    _String 
= (char *)str;

    
/* Find the end of the token. If it is not the end of the string,
    * put a null there. 
*/
    
for ( ; *str != 0 ; str++ )
    {
        
if (map[*str >> 3& (1 << (*str & 7)))
        {
            
*str++ = 0;
            
break;
        }
    }

    
/* Update context */
    
*_Context = (char *)str;

    
/* Determine if a token has been found. */
    
if (_String == (char *)str)
    {
        
return NULL;
    }
    
else
    {
        
return _String;
    }
}
#endif

/* wcstok_s */
_SAFECRT__EXTERN_C
wchar_t 
* __cdecl wcstok_s(wchar_t *_String, const wchar_t *_Control, wchar_t **_Context);

#if _SAFECRT_USE_INLINES

__inline
wchar_t 
* __cdecl wcstok_s(wchar_t *_String, const wchar_t *_Control, wchar_t **_Context)
{
    wchar_t 
*token;
    
const wchar_t *ctl;

    
/* validation section */
    _SAFECRT__VALIDATE_POINTER_ERROR_RETURN(_Context, EINVAL, NULL);
    _SAFECRT__VALIDATE_POINTER_ERROR_RETURN(_Control, EINVAL, NULL);
    _SAFECRT__VALIDATE_CONDITION_ERROR_RETURN(_String != NULL || *_Context != NULL, EINVAL, NULL);


    
/* If string==NULL, continue with previous string */
    
if (!_String)
    {
        _String 
= *_Context;
    }

    
/* Find beginning of token (skip over leading delimiters). Note that
    * there is no token iff this loop sets string to point to the terminal null. 
*/
    
for ( ; *_String != 0 ; _String++)
    {
        
for (ctl = _Control; *ctl != 0 && *ctl != *_String; ctl++)
            ;
        
if (*ctl == 0)
        {
            
break;
        }
    }

    token 
= _String;

    
/* Find the end of the token. If it is not the end of the string,
    * put a null there. 
*/
    
for ( ; *_String != 0 ; _String++)
    {
        
for (ctl = _Control; *ctl != 0 && *ctl != *_String; ctl++)
            ;
        
if (*ctl != 0)
        {
            
*_String++ = 0;
            
break;
        }
    }

    
/* Update the context */
    
*_Context = _String;

    
/* Determine if a token has been found. */
    
if (token == _String)
    {
        
return NULL;
    }
    
else
    {
        
return token;
    }
}
#endif

 

 2. 使用strsafe.h时需要注意将其放到其他string操作头文件的后面,以免不必要的编译错误。

可以参考:http://www.programfan.com/club/showtxt.asp?id=235904
我今天在编译的适合也碰到过这个问题。

再次强调,使用strsafe.h最好是放在cpp文件中,而非头文件中。

在微软的tchar.h中明确的有个#error put strsafe.h behind thar.h。 strsafe.h被要求放在tchar.h的后面。如果不这样,会得到一堆很奇怪的错误。

 

 

posted on 2008-09-27 11:06  SunWentao  阅读(534)  评论(0编辑  收藏  举报