常用字符串源代码

1、strstr

strstr函数有两个版本:
[cpp]  view plain  copy
  1. const char * strstr ( const char * str1, const char * str2 );  
  2.       char * strstr (       char * str1, const char * str2 );  

(1) 朴素的实现方式

遍历两个字符串,在str1中逐个匹配str2,时间复杂度O(nm).

(2) KMP算法

strstr的两种实现参考文章: KMP(Knuth-Morris-Pratt)算法


2、strlen

以下两种实现类似,后一种没有借助局部length变量。
[cpp]  view plain  copy
  1. size_t strlen1(const char *str) {  
  2.     assert(str != NULL);  
  3.     unsigned int length = 0;  
  4.     while ((*str++) != '\0')  
  5.         ++length;  
  6.     return length;  
  7. }  
  8.   
  9. size_t strlen2(const char *str) {  
  10.     assert(str != NULL);  
  11.     const char *end = str;  
  12.     while (*end++) ;  
  13.     return ((int)(end - str - 1));  
  14. }  

3、strcat  strncat

注意几点
a. 给源字符加上const属性;
b. 给源地址和目的地址加非零断言;
c. 为了实现链式操作,将目的地址返回,而不是返回void;
d. 考虑源目的区域有重叠的情况;
e. 一定要保证追加操作完后,目的地址最后以空字符'\0‘结尾

[cpp]  view plain  copy
  1. </pre><pre name="code" class="cpp">char *strcat1(char *destination, const char *source) {  
  2.     assert (destination != NULL && source != NULL);  
  3.     char *cp = destination;  
  4.     while (*cp)  
  5.         ++cp;  
  6.     while (*cp++ = *source++) ;  
  7.     return destination;  
  8. }  
  9.   
  10. char* strncat1(char *destination, const char *source, size_t count) {  
  11.     assert (destination != NULL && source != NULL);  
  12.     char *cp = destination;  
  13.     while (*cp)  
  14.         ++cp;  
  15.     while (count-- && *source != '\0')  
  16.         *cp++ = *source++;  
  17.     *cp = '\0';  
  18.     return destination;  
  19. }  

4、strcmp strncmp

注意:下面字符做减法时,要强制类型转换,将char转换为unsigned char,因为strcmp函数是按照ASCII码进行比较的,而ASCII码的范围是0 ~ 255,char的范围是-127 ~ 127,所以当输入为负数时会返回错误。

[cpp]  view plain  copy
  1. int strcmp1(const char *str1, const char *str2) {  
  2.     assert(str1 != NULL && str2 != NULL);  
  3.   
  4.     int result = 0;  
  5.     while ( !(result = *(unsigned char*)str1 - *(unsigned char*)str2) && *str2) {  
  6.         ++str1;  
  7.         ++str2;  
  8.     }  
  9.   
  10.     if (result < 0)  
  11.         return -1;  
  12.     else if (result > 0)  
  13.         return 1;  
  14.     return result;  
  15. }  
  16.   
  17. int strncmp1(const char *str1, const char *str2, size_t count) {  
  18.     assert(str1 != NULL && str2 != NULL);  
  19.   
  20.     int result = 0;  
  21.     //下一行必须将count--写在前边,否则count等于0时还会计算一个ret  
  22.     while (count-- && (!(result = *(unsigned char*)str1 - *(unsigned char*)str2)) && *str2) {  
  23.         ++str1;  
  24.         ++str2;  
  25.     }  
  26.   
  27.     if (result < 0)  
  28.         return -1;  
  29.     else if (result > 0)  
  30.         return 1;  
  31.     return result;  
  32. }  


5、strcpy strncpy

注意几点
a. 给源字符加上const属性;
b. 给源地址和目的地址加非零断言;
c. 为了实现链式操作,将目的地址返回,而不是返回void;
d. 考虑源目的区域有重叠的情况;
e. 一定要保证复制完后,目的地址最后以空字符'\0‘结尾

[cpp]  view plain  copy
  1. char *strcpy(char *destination, const char *source) {  
  2.     assert(destination != NULL && source != NULL);  
  3.   
  4.     if (destination == source)  
  5.         return destination;  
  6.   
  7.     char *cp = destination;  
  8.     while ((*cp++ = *source++) != '\0')  
  9.         ;  
  10.     return destination;  
  11. }  
  12.   
  13. char *strncpy1(char *destination, const char *source, size_t count) {  
  14.     assert(destination != NULL && source != NULL);  
  15.   
  16.     if (destination == source)  
  17.         return destination;  
  18.   
  19.     char *cp = destination;  
  20.     while (count-- && *source != '\0')  
  21.         *cp++ = *source++;  
  22.     *cp = '\0';  
  23.     return destination;  
  24. }  

6、strpbrk

有两个版本:
[cpp]  view plain  copy
  1. const char * strpbrk ( const char * str1, const char * str2 );  
  2.       char * strpbrk (       char * str1, const char * str2 );  

[cpp]  view plain  copy
  1. /* 
  2. Returns a pointer to the first occurrence in str1 of any of the  
  3. characters that are part of str2, or a null pointer if there are no matches. 
  4. The search does not include the terminating null-characters 
  5. 该函数也是两个版本:const和非const版本 
  6. */  
  7. char *strpbrk1(char *str1, const char *str2) {       
  8.     assert((str1 != NULL) && (str2 != NULL));       
  9.     const char *s;       
  10.     while (*str1 != '\0') {       
  11.         s = str2;       
  12.         while (*s != '\0'){       
  13.             if (*str1 == *s)       
  14.                 return str1;       
  15.             ++ s;       
  16.         }       
  17.         ++ str1;       
  18.     }       
  19.     return NULL;       
  20. }     

7、memcpy

         该函数不检查source结尾的null字符,仅仅拷贝count个字节。为了避免溢出,destination和source指针所指的数组必须最少有count个字节,而且两个区域不能重叠。
         如果区域有重叠,那么要使用memmove这个更安全的方式。
[cpp]  view plain  copy
  1. void *memcpy1(void *destination, const void *source, size_t count) {  
  2.     assert (destination != NULL && source != NULL);  
  3.   
  4.     void *address = destination;  
  5.     while (count--) {  
  6.         *(char*)destination = *(char*)source;  
  7.         destination = (char *)destination + 1;  
  8.         source = (char *)source + 1;  
  9.     }  
  10.     return address;  
  11. }  

8、memmove

        和memcpy函数一样,该函数也不会检查source末尾的空字符null,仅仅拷贝count个字节;为了避免溢出,destination和source指针所指的数组必须最少有count个字节。但是该函数允许源和目的区域重叠

[cpp]  view plain  copy
  1. void *memmove1(void *destination, const void *source, size_t count) {  
  2.     assert (destination != NULL && source != NULL);  
  3.   
  4.     char *pdest = (char*)destination;  
  5.     char *psrc = (char*)source;  
  6.     //pdest在psrc后面,且两者距离小于count,从尾部开始移动,  
  7.     //其他情况从头部开始移动  
  8.     if ((pdest > psrc) && (pdest - psrc < count)) {  
  9.         while (count--)  
  10.             *(pdest + count) = *(psrc + count);  
  11.     }  
  12.     else {  
  13.         while (count--)  
  14.             *pdest++ = *psrc++;  
  15.     }  
  16.     return destination;  
  17. }  

9、memset

[cpp]  view plain  copy
  1. void *memset1(void *str, int value, size_t count) {  
  2.     if (str == NULL)  
  3.         return NULL;  
  4.   
  5.     void *p = str;  
  6.     while (count--) {  
  7.         *(char*)p = (char)value;  
  8.         p = (char *)p + 1;  
  9.     }  
  10.     return str;  
  11. }  

10、strchr  memchr

memchr函数功能:查找在num字节内,value(解释为unsigned char)第一次出现的位置,返回指向它的指针。
两个版本:
[cpp]  view plain  copy
  1. const void * memchr ( const void * ptr, int value, size_t num );  
  2.       void * memchr (       void * ptr, int value, size_t num );  

[cpp]  view plain  copy
  1. void *memchr1(void *str, int value, size_t count) {  
  2.     if (str == NULL)  
  3.         return NULL;  
  4.     while (count--) {  
  5.         if (*(char*)str == value)  
  6.             return (void*)str;  
  7.         str = (char*)str + 1;  
  8.     }  
  9.     return NULL;  
  10. }  

strchr也有两个版本:
[cpp]  view plain  copy
  1. const char * strchr ( const char * str, int character );  
  2.       char * strchr (       char * str, int character );  

[cpp]  view plain  copy
  1. //查找字符串s中首次出现字符c的位置       
  2. char *strchr1(char *str, int c)     {       
  3.     assert(str != NULL);       
  4.     for (; *str != (char)c; ++ str)       
  5.         if (*str == '\0')       
  6.             return NULL;       
  7.     return str;       
  8. }    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值