鼠标一般多少钱:ANSI C 字符串库函数的实现

来源:百度文库 编辑:九乡新闻网 时间:2024/07/14 00:50:51
Monday, Nov. 24, 2008

Note: part of this article is referenced from Microsoft CRT Source Code in Visual Studio 6.0.

If you wanna become an Embedded Software Enginner or Staff C Programmer, you must have some fundamental ideas on how the ANSI C string library functions were implemented. Furthermore, these functions are very common in an C/C++ programmer interview, esp., strrev() (note: strrev() is not ANSI C standard) and strtok(). I'm now trying to implment all of these string functions for your reference. Please debug them for me if possible.

strrev()
/* Referenced from Microsoft CRT source code,    efficient and easy to understand */char* strrev(char* s){    char* left = s;    char* right = s, c;    while(*right++);    right -= 2;    while(left < right)        c = *left, *left++ = *right, *right-- = c;    return s;}
strtok()
/* Efficient(?) and easy to understand.   It may be more efficient in Microsoft CRT source code,   but it's very hard to understand                                       */char* strtok(char* s, const char* ct){    static char* ntok; /* Next token */    char*        cp;   /* For moving s */    char*        cq;   /* For moving ct */    if ( !s ) s = ntok; /* Not first call */    /* Skip the non-token characters, i.e., ones in ct */    cp = s;    while ( *cp )    {        cq = (char*)ct;        while ( *cq && *cp-*cq )            ++cq;        if ( !*cq ) /* Found the token beginning */        {            s = cp; /* For returning */            break;        }        ++cp;    }    if ( !*cp ) /* No more token can be found. */        return NULL;    /* else: found a new word */    cp = s;    while ( *cp )    {        cq = (char*)ct;        while ( *cq && *cp-*cq )            ++cq;        if ( *cq ) /* Found a new word ending */        {            *cp  = 0; /* Set to '\0' as definition says */            ntok = cp + 1; /* Move ntok to next search beginning */            return s;        }        ++cp;    }    ntok = cp; /* Not: ntok = cp + 1 */    return s; /* For the last token */}
strstr()
/* Referenced from Microsoft CRT source code,    efficient and easy to understand */char* strstr(const char* cs, const char* ct){    char* cp = (char*)cs;    char* s1, * s2;    if ( !*ct )        return (char*)cs;    while ( *cp )    {        s1 = cp;        s2 = (char*)ct;        while ( *s1 && *s2 && !(*s1-*s2) )            ++s1, ++s2;        if ( !*s2 )            return cp;        ++cp;    }    return NULL;}
strlen()
/* Referenced from Microsoft CRT source code,    efficient and easy to understand */int strlen(const char* cs){    const char* e = cs;    while ( *e++ );    return (int)(e - cs - 1);}
strcpy()
/* Efficient and easy to understand */char* strcpy(char* s, const char* ct){    char* start = s;    while ( *s++ = *ct++ );    return start;}
strcat()
/* Referenced from Microsoft CRT source code,    efficient and easy to understand */char* strcat(char* s, const char* ct){    char* start = s;    while ( *s ) ++s;    while ( *s++ = *ct++ );    return start;}
strcmp()
/* Referenced from Microsoft CRT source code,    efficient and easy to understand */int strcmp(const char* cs, const char* ct){    int ret;    while ( !(ret = *(unsigned char*)cs-*(unsigned char*)ct) && *ct )        ++cs, ++ct;    return ret;}
strchr()
/* Referenced from Microsoft CRT source code,    efficient and easy to understand */char* strchr(const char* cs, int c){    while ( *cs && *cs!=(char)c )        ++cs;    return *cs == (char)c ? (char*)cs : NULL;    /* Cannot handle c == NULL :       return *cs ? (char*)cs : NULL; */}
strspn()
/* Efficient(?) and easy to understand.   It may be more efficient in Microsoft CRT source code,   but it's very hard to understand  */int strspn(const char* cs, const char* ct){    char* cp = (char*)cs;    char* cq;    while ( *cp )    {        cq = (char*)ct;        while ( *cq && *cp-*cq )            ++cq;        if ( !*cq )            return cp - cs;        ++cp;    }    return cp - cs;}
strcspn()
/* Efficient(?) and easy to understand.   It may be more efficient in Microsoft CRT source code,   but it's very hard to understand  */int strcspn(const char* cs, const char* ct){    char* cp = (char*)cs;    char* cq;    while ( *cp )    {        cq = (char*)ct;        while ( *cq && *cp-*cq )            ++cq;        if ( *cq )            return cp - cs;        ++cp;    }    return cp - cs;}
strpbrk()
/* Efficient(?) and easy to understand.   It may be more efficient in Microsoft CRT source code,   but it's very hard to understand  */char* strpbrk(const char* cs, const char* ct){    char* cp = (char*)cs;    char* cq;    while ( *cp )    {        cq = (char*)ct;        while ( *cq && *cp-*cq )            ++cq;        if ( *cq )            return (char*)cp;        ++cp;    }    return NULL;}
Microsoft CRT Source Code for strspn(), strcspn() and strpbrk()

The Microsoft CRT source code for strspn(), strcspn() and strpbrk() is very hard to understand. However, I will be dedicated to it in the near future :-). See the CRT code at your local disk VS6.0 was installed C:\Program Files\Microsoft Visual Studio\VC98\CRT\SRC\STRSPN.C or the code below I copied:

/****strspn.c - find length of initial substring of chars from a control string**       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.**Purpose:*       defines strspn() - finds the length of the initial substring of*       a string consisting entirely of characters from a control string.**       defines strcspn()- finds the length of the initial substring of*       a string consisting entirely of characters not in a control string.**       defines strpbrk()- finds the index of the first character in a string*       that is not in a control string********************************************************************************//* Determine which routine we're compiling for (default to STRSPN) */#define _STRSPN         1#define _STRCSPN        2#define _STRPBRK        3#if defined (SSTRCSPN)#define ROUTINE _STRCSPN#elif defined (SSTRPBRK)#define ROUTINE _STRPBRK#else  /* defined (SSTRPBRK) */#define ROUTINE _STRSPN#endif  /* defined (SSTRPBRK) */#include #include /****int strspn(string, control) - find init substring of control chars**Purpose:*       Finds the index of the first character in string that does belong*       to the set of characters specified by control.  This is*       equivalent to the length of the initial substring of string that*       consists entirely of characters from control.  The '\0' character*       that terminates control is not considered in the matching process.**Entry:*       char *string - string to search*       char *control - string containing characters not to search for**Exit:*       returns index of first char in string not in control**Exceptions:********************************************************************************//****int strcspn(string, control) - search for init substring w/o control chars**Purpose:*       returns the index of the first character in string that belongs*       to the set of characters specified by control.  This is equivalent*       to the length of the length of the initial substring of string*       composed entirely of characters not in control.  Null chars not*       considered.**Entry:*       char *string - string to search*       char *control - set of characters not allowed in init substring**Exit:*       returns the index of the first char in string*       that is in the set of characters specified by control.**Exceptions:********************************************************************************//****char *strpbrk(string, control) - scans string for a character from control**Purpose:*       Finds the first occurence in string of any character from*       the control string.**Entry:*       char *string - string to search in*       char *control - string containing characters to search for**Exit:*       returns a pointer to the first character from control found*       in string.*       returns NULL if string and control have no characters in common.**Exceptions:********************************************************************************//* Routine prototype */#if ROUTINE == _STRSPNsize_t __cdecl strspn (#elif ROUTINE == _STRCSPNsize_t __cdecl strcspn (#else  /* ROUTINE == _STRCSPN */char * __cdecl strpbrk (#endif  /* ROUTINE == _STRCSPN */        const char * string,        const char * control        ){        const unsigned char *str = string;        const unsigned char *ctrl = control;        unsigned char map[32];        int count;        /* Clear out bit map */        for (count=0; count<32; count++)                map[count] = 0;        /* Set bits in control map */        while (*ctrl)        {                map[*ctrl >> 3] |= (1 << (*ctrl & 7));                ctrl++;        }#if ROUTINE == _STRSPN        /* 1st char NOT in control map stops search */        if (*str)        {                count=0;                while (map[*str >> 3] & (1 << (*str & 7)))                {                        count++;                        str++;                }                return(count);        }        return(0);#elif ROUTINE == _STRCSPN        /* 1st char in control map stops search */        count=0;        map[0] |= 1;    /* null chars not considered */        while (!(map[*str >> 3] & (1 << (*str & 7))))        {                count++;                str++;        }        return(count);#else  /* ROUTINE == _STRCSPN */        /* 1st char in control map stops search */        while (*str)        {                if (map[*str >> 3] & (1 << (*str & 7)))                        return((char *)str);                str++;        }        return(NULL);#endif  /* ROUTINE == _STRCSPN */}