C库中部分str函数的用法

C语言str系列库函数在不同的库中有不同的实现方法,但原理都是一样的。因为库函数都是没有进行入口参数检查的,并且str系列库函数在面试中经常容易被面试官喊在纸上写某一个函数的实现,因此本文参考了OpenBSD和vc++ 8.0库中的代码,结合自己的编程习惯,部分整理如下:

1、strcpy

char * strcpy(char *dst, const char *src)  
{  
    char *d;  
  
    if (dst == NULL || src == NULL)  
        return dst;  
  
    d = dst;  
    while (*d++ = *src++)    // while ((*d++ = *src++) != '\0')  
        ;  
  
    return dst;  
}  

2、strncpy

char *strncpy(char *dst, const char*src, size_t n)  
{  
    char *d;  
  
    if (dst == NULL || src == NULL)  
        return dst;  
  
    d = dst;  
    while (n != 0 && (*d++ = *src++))    /* copy string */  
        n--;  
    if (n != 0)  
        while (--n != 0)  
            *d++ == '\0';                /* pad out with zeroes */  
  
    return dst;  
}  

注意 n是unsigned int,在进行n–操作时特别要小心。如果不小心写成下面这样就会出错:

while (n-- != 0 && (*d++ = *src++))  
    ;         
while (n-- != 0)   
    *d++ = '\0';  

第一个while循环中,当n变为0时,仍然会执行n–一,此时n等于经由-1变成的大正数,导致后面对n的使用出错。

3、strcat

char *strcat(char *dst, const char *src)  
{     
    char *d;  
    if (dst == NULL || src == NULL)  
        return dst;  
  
   d = dst;  
   while (*d)  
       d++;  
   //while (*d++ != 0);  
   //d--;  
     
   while (*d++ = *src++)  
       ;  
  
   return dst;  
}  

4、strncat
写法1:

char *strncat(char *dst, const char *src, size_t n)  
{  
    if (NULL == dst || NULL == src)  
        return dst;  
  
    if (n != 0)  
    {  
        char *d = dst;  
        do   
        {  
            if ((*d = *src++) == '\0' )  
                return dst;     //break  
            d++;  
        } while (--n != 0);    
        *d = '\0';  
    }  
      
    return dst;  
}  

写法2:

char *strncat(char *dst, const char *src, size_t n)  
{  
   char *d;  
  
   if (dst == NULL || src == NULL)  
       return dst;  
     
   d = dst;  
   while (*d)  
       d++;  
   //(1)  
   while (n != 0)  
   {  
       if ((*d++ = *src++) == '\0')  
           return dst;  
       n--;  
   }  
  
   //(2)  
   //while (n--)       //这种方式写最后n的值不为0,不过这个n后面不会再被使用  
      // if ((*d++ == *src++) == '\0')  
         //  return dst;  
  
   *d = '\0';  
  
   return dst;  
}  

5、strcmp

int strcmp(const char *s1, const char *s2)  
{   
    if (s1 == NULL || s2 == NULL)  
        return 0;  
    //(1)  
    //while (*s1 == *s2++)  
    //  if (*s1++ == '\0')  
    //      return 0;  
  
    //(2)  
    for (; *s1 == *s2; s1++, s2++)  
        if (*s1 == '\0')  
            return 0;  
    return *(unsigned char*)s1 - *(unsigned char*)s2;  
}  

6、strncmp

int strncmp(const char *s1, const char *s2, size_t n)  
{  
    if (s1 == NULL || s2 == NULL)  
        return 0;  
  
    if (n == 0)  
        return 0;  
    do  
    {  
        if (*s1 != *s2++)  
            return *(unsigned char*)s1 - *(unsigned char*)--s2;  
        if (*s1++ == '\0')  
            break;  
    } while (--n != 0);  
  
    //do   
    //{  
    //  if (*s1 != *s2)  
    //      return *(unsigned char*)s1 - *(unsigned char*)s2;  
    //  if (*s1 == '\0')  
    //      break;  
    //  s1++;  
    //  s2++;  
    //} while (--n != 0);  
  
    return 0;  
}  

7、strstr
写法1:

//成功返回:从前面数组中找到的与find数组内容相同的子字符串的下标到结尾下标的所有字符串
//失败返回:空

char *strstr(const char *s, const char *find)  
{  
    char *cp = (char*)s;  
    char *s1, *s2;  
  
    if (s == NULL || find == NULL)  
        return NULL;  
  
    while (*cp != '\0')  
    {  
        s1 = cp;  
        s2 = (char*)find;  
  
        while (*s1 && *s2 && *s1 == *s2)  
            s1++, s2++;  
  
        if(*s2 == '\0')  
            return cp;  
  
        cp++;  
    }  
   return NULL;  
}  

写法2:参照简单模式匹配算法

char *strstr(const char *s, const char *find)  
{  
    int i = 0, j = 0;  
    while (*(s + i) != '\0' && *(find + j) != '\0')  
    {  
        if (*(s + i + j) == *(find + j))  
            j++;     //继续比较后一字符  
        else  
        {  
            i++;     //开始新一轮比较  
            j = 0;  
        }  
    }  
  
    return *(find + j) == '\0' ? (char*)(s + i) : NULL;  
}  

8、strchr
//成功返回:从前面数组中找到的与ch相同的字符的下标(从数组左端开头开始遍历)
//失败返回:空

char *strchr(const char*str, int ch)  
{  
    while (*str != '\0' && *str != (char)ch)  
        str++;  
  
    if(*str == (char)ch)  
        return (char*)str;  
    return NULL;  
}  

9、strrchr
//成功返回:同strchr(只是遍历操作从右端开始)
//失败返回:空

char *strrchr(const char *str, int ch)  
{  
    if (str == NULL)  
        return NULL;  
  
   char *s = (char*)str;  
  
   while (*s++)  
       ;       /* find end of string */  
  
   while (--s != str && *s != (char)ch)  
       ;       /* search towards front */  
  
   if(*s == (char)ch)  
       return (char*)s;  
   return NULL;  
}  

10、strlen

size_t strlen(const char *str)  
{  
    if (str == NULL)  
        return 0;  
  
    const char *eos = str;  
    while (*eos++)  
        ;  
    return (eos - 1 - str);  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值