C语言学习之字符串、字符和字节第二讲

这篇博客详细介绍了C语言中用于字符串处理的函数,包括`strchr`、`strrchr`、`strpbrk`、`strstr`、`strspn`和`strcspn`。通过实例代码展示了这些函数如何查找字符、子串,以及如何进行字符串分割。同时,还提供了自定义实现的版本,帮助理解其工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.字符串查找基础

        1.1查找一个字符

            函数原型: char *strchr( char  const  *str , int ch);

            函数原型: char *strrchr( char  const  *str , int ch);

                                 第一个参数是被查罩数组指针而第二个参数是int型,但是他包含了一个字符值。函数1为返回第一次出现ch的位置指针而第二个函数是返回最后一次出现ch的位置即最右侧地址。查找失败均返回NULL指针。

           例子:

           char  srting[20] = "Hello  there, honey.";

          char   *ans;

          ans = strchr( string , 'h')

  1. /* 
  2. *copyright@nciaebupt 转载请注明出处 
  3. *原型:char *strchr(const char *s,int c); 
  4. *用法:#include <string.h> 
  5. *功能:查找字符串s中首次出现字符c的位置 
  6. *说明:返回首次出现c的位置的指针,如果s中不存在c则返回NULL。 
  7. *使用C函数库中的strchr 
  8. */  
  9. #include <cstdio>  
  10. #include <cstring>  
  11.   
  12. int main(int args,char ** argv)  
  13. {  
  14.     char s[] = "This sample string";  
  15.     char *p = strchr(s,'p');  
  16.     if(p != NULL)  
  17.     {  
  18.         printf("find the char in : %d\n",p - s + 1);  
  19.     }  
  20.     else    printf("could not find the char\n");  
  21.   
  22.     getchar();  
  23.     return 0;  
  24. }  
  25.   
  26. /* 
  27. *copyright@nciaebupt 转载请注明出处 
  28. *原型:char *strchr(const char *s,int c); 
  29. *用法:#include <string.h> 
  30. *功能:查找字符串s中首次出现字符c的位置 
  31. *说明:返回首次出现c的位置的指针,如果s中不存在c则返回NULL。 
  32. *自己实现strchr 
  33. */  
  34. #include <cstdio>  
  35.   
  36. char * _strchr(const char * s,int ch)  
  37. {  
  38.     while(*s && (*s != (char)ch))  
  39.     {  
  40.         s++;  
  41.     }  
  42.     if(*s == (char)ch)  return (char *)s;  
  43.     return NULL;  
  44. }  
  45.   
  46. int main(int args,char ** argv)  
  47. {  
  48.     char s[] = "This sample string";  
  49.     char *p = _strchr(s,'p');  
  50.     if(p != NULL)  
  51.     {  
  52.         printf("find the char in : %d\n",p - s + 1);  
  53.     }  
  54.     else    printf("could not find the char\n");  
  55.   
  56.     getchar();  
  57.     return 0;  
  58. }  
C函数库中的strchr实现

  1. /* 
  2. *copyright@nciaebupt 转载请注明出处 
  3. *原型:extern char *strrchr(char *s,char c); 
  4. *用法:#include <string.h> 
  5. *功能:查找字符串s中最后一次出现字符c的位置 
  6. *说明:返回最后一次出现c的位置的指针,如果s中不存在c则返回NULL。 
  7. *使用C函数库中的strrchr 
  8. */  
  9. #include <cstdio>  
  10. #include <cstring>  
  11.   
  12. int main(int args,char ** argv)  
  13. {  
  14.     char str[] = "This is a sample string";  
  15.     char *pch;  
  16.     pch = strrchr(str,'s');  
  17.     printf("The last occurence of 's' found at : %d",pch - str + 1);  
  18.   
  19.     getchar();  
  20.     return 0;  
  21. }  
  22.   
  23. /* 
  24. *copyright@nciaebupt 转载请注明出处 
  25. *原型:char *strrchr(const char *s,int ch); 
  26. *用法:#include <string.h> 
  27. *功能:查找字符串s中最后一次出现字符c的位置 
  28. *说明:返回最后一次出现c的位置的指针,如果s中不存在c则返回NULL。 
  29. *自己实现strrchr 
  30. */  
  31. #include <cstdio>  
  32.   
  33. char * _strrchr(const char * str,int ch)  
  34. {  
  35.     char * start = (char *)str;  
  36.     while(*str++)/*get the end of the string*/  
  37.         ;  
  38.     while(--str != start && *str != (char)ch)  
  39.         ;  
  40.     if(*str == (char)ch)  
  41.         return((char *)str);  
  42.     return NULL;  
  43.   
  44. }  
  45.   
  46. int main(int args,char ** argv)  
  47. {  
  48.     char str[] = "This is a sample string";  
  49.     char *pch;  
  50.     pch = _strrchr(str,'s');  
  51.     printf("The last occurence of 's' found at : %d",pch - str + 1);  
  52.   
  53.     getchar();  
  54.     return 0;  
  55. }  
C函数库中的strrchr实现

        1.2查找仁和几个字符

            函数原型: char  *strpbrk( char const  *str , char  const  *group);

                                函数功能是查找仁和一组字符第一次在字符串中出现的位置,返回值为指向第一个匹配group中仁和一个字符的字符位置,未匹配则返回一个NULL指针。

             例子:
                               char  string[20] = "Hello there. honey.";

                               char *ans;

                              ans = strpbrk ( string , "aeiou");

                              ans所指向的位置为string+1,因为这个位置是第二个参数中的字符第一次出现的位置。查找一个字符一样这个函数也是区分大小写的。

  1. /* 
  2. *copyright@nciaebupt 转载请注明出处 
  3. *原型:char *strpbrk(const char *s1, const char *s2); 
  4. *用法:#include <string.h> 
  5. *功能:在字符串s1中寻找字符串s2中任何一个字符相匹配的第一个字符的位置, 
  6. *   空字符NULL不包括在内。 
  7. *说明:返回指向s1中第一个相匹配的字符的指针,如果没有匹配字符则返回空指针NULL。 
  8. *使用C函数库中的strpbrk 
  9. */  
  10. #include <cstdio>  
  11. #include <cstring>  
  12.   
  13. int main(int args,char ** argv)  
  14. {  
  15.     char str[] = "This is a sample string";  
  16.     char keys[] = "aeiou";  
  17.     printf("Vowels in '%s' : ",str);  
  18.     char * pch;  
  19.     pch = strpbrk(str,keys);  
  20.     while(pch != NULL)  
  21.     {  
  22.         printf("%c ",*pch);  
  23.         pch = strpbrk(pch + 1,keys);  
  24.     }  
  25.     getchar();  
  26.     return 0;  
  27. }  
  28.   
  29. /* 
  30. *copyright@nciaebupt 转载请注明出处 
  31. *原型:char *strpbrk(const char *s1, const char *s2); 
  32. *用法:#include <string.h> 
  33. *功能:在字符串s1中寻找字符串s2中任何一个字符相匹配的第一个字符的位置, 
  34. *   空字符NULL不包括在内。 
  35. *说明:返回指向s1中第一个相匹配的字符的指针,如果没有匹配字符则返回空指针NULL。 
  36. *自己实现strpbrk 
  37. */  
  38. #include <cstdio>  
  39. #include <cstring>  
  40.   
  41. char * _strpbrk(const char * string,const char * control)  
  42. {  
  43.     const unsigned char *str = (const unsigned char *)string;  
  44.     const unsigned char *ctrl = (const unsigned char *)control;  
  45.     unsigned char map[32];  
  46.     int count;  
  47.     /*clear the map*/  
  48.     memset(map,0,32*sizeof(unsigned char));  
  49.     /*set bit in the control map*/  
  50.     while(*ctrl)  
  51.     {  
  52.         map[*ctrl >> 3] |= (0x01 << (*ctrl & 7));  
  53.         ctrl++;  
  54.     }  
  55.     /*search control in str*/  
  56.     while(*str)  
  57.     {  
  58.         if((map[*str >> 3] & (1 << (*str & 7))))  
  59.             return((char *)str);  
  60.         str++;  
  61.     }  
  62.     return NULL;  
  63.   
  64. }  
  65.   
  66. int main(int args,char ** argv)  
  67. {  
  68.     char str[] = "This is a sample string";  
  69.     char keys[] = "aeiou";  
  70.     printf("Vowels in '%s' : ",str);  
  71.     char * pch;  
  72.     pch = _strpbrk(str,keys);  
  73.     while(pch != NULL)  
  74.     {  
  75.         printf("%c ",*pch);  
  76.         pch = _strpbrk(pch + 1,keys);  
  77.     }  
  78.     getchar();  
  79.     return 0;  
  80. }  
C函数库中的strpbrk实现

        1.3查找一个子串

              函数原型:char  *strstr( char const  *s1, char  const *s2);

              函数原型:char *strrstr ( char const *s1 , char  const *s2);

             函数功能在s1中查找整个s2第一次出现的起始位置,并返回一个指向该位置的指针如果s2并没有完整地出现在s1的任何地方,则返回NULL指针如果第二个函数为空则返回s1。,第二个是搜索s2最有出现位置,并返回一个指向该位置的指针。

      

  1. /* 
  2. *copyright@nciaebupt 转载请注明出处 
  3. *原型:char *strstr(const char *haystack, const char *needle); 
  4. *用法:#include <string.h> 
  5. *功能:从字符串haystack中寻找needle第一次出现的位置(不比较结束符NULL)。 
  6. *说明:返回指向第一次出现needle位置的指针,如果没找到则返回NULL。 
  7. *使用C函数库中的strstr 
  8. */  
  9. #include <cstdio>  
  10. #include <cstring>  
  11.   
  12. int main(int args,char ** argv)  
  13. {  
  14.     char str[] = "This is a simple string";  
  15.     char * pch = _strstr(str,"simple");  
  16.     strncpy(pch,"sample",6);  
  17.     printf("%s\n",str);  
  18.     getchar();  
  19.     return 0;  
  20. }  
  21.   
  22. /* 
  23. *copyright@nciaebupt 转载请注明出处 
  24. *原型:char *strstr(const char *haystack, const char *needle); 
  25. *用法:#include <string.h> 
  26. *功能:从字符串haystack中寻找needle第一次出现的位置(不比较结束符NULL)。 
  27. *说明:返回指向第一次出现needle位置的指针,如果没找到则返回NULL。 
  28. *自己实现strstr 
  29. */  
  30. #include <cstdio>  
  31. #include <cstring>  
  32.   
  33. char * _strstr(const char * str1,const char * str2)  
  34. {  
  35.     char * cp = (char *)str1;  
  36.     char * s1;  
  37.     char * s2;  
  38.     if(!*str2)  
  39.         return ((char *)str1);  
  40.     while(*cp)  
  41.     {  
  42.         s1 = cp;  
  43.         s2 = (char *)str2;  
  44.         while(*s1 && *s2 && !(*s2 - *s1))  
  45.         {  
  46.             s1++;  
  47.             s2++;  
  48.         }  
  49.         if(!*s2)  
  50.             return (cp);  
  51.         cp++;  
  52.     }  
  53.     return NULL;  
  54. }  
  55.   
  56. int main(int args,char ** argv)  
  57. {  
  58.     char str[] = "This is a simple string";  
  59.     char * pch = _strstr(str,"simple");  
  60.     strncpy(pch,"sample",6);  
  61.     printf("%s\n",str);  
  62.     getchar();  
  63.     return 0;  
  64. }  
C函数库中的strstr实现

        #include <string.h>                  //在字符串s1中查找字符串s2最后出现的位置,并返回一个指向该位置的指针。
        char  *strrstr ( cahr const  *s1, char const *s2)
        {
                register  char  *last;
                register  char  *current;    //把指针初始化为找到的第一个位置
                last = NULL;                 //旨在第二个字符串不为空的时候才找,如果为空,返回NULL
                if ( *s2 != '\0')                   //查找s2在s1中出现的位置
                {
                        chrrent  = strstr (s1,s2);  //每次找到是,让指针指向它的起始位置。然后查找下一个匹配位置。
                        while ( current  != NULL)
                       {
                              last = current ;
                              current  = strstr ( last +1, s2);
                        }
                }
               return last ;   //返回指向我们找到的最后一次匹配的起始位置指针。  

        }
2.高级字符串查找

        2.1查找一个字符串前缀

              函数原型:size_t strspn ( char  const  * str, char  const  *group);

       函数说明:strspn()从参数str字符串的开头计算连续的字符,而这些字符都完全是group 所指字符串中的字符。简单的说,若strspn()返回的数值为n,则代表字符串str 开头连续有n 个字符都是属于字符串group内的字符,返回字符串str开头连续包含字符串group内的字符数目。

  1. /* 
  2. *copyright@nciaebupt 转载请注明出处 
  3. *原型:size_t strspn(const char * str1,const char * str2); 
  4. *用法:#include <string.h> 
  5. *功能:若strspn()返回的数值为n, 
  6. *       则代表字符串str1开头连续有n个字符都是属于字符串str2内的字符. 
  7. *说明:返回字符串str1开头连续包含字符串str2内的字符数目. 
  8. *使用C函数库中的strspn 
  9. */  
  10. #include <cstdio>  
  11. #include <cstring>  
  12.   
  13. int main(int args,char ** argv)  
  14. {  
  15.     char str[] = "12999th";  
  16.     char keys[] = "1234567890";  
  17.   
  18.     int i = strspn(str,keys);  
  19.   
  20.     printf("the initial string has %d numbers\n",i);  
  21.   
  22.     getchar();  
  23.     return 0;  
  24. }  
  25.   
  26. /* 
  27. *copyright@nciaebupt 转载请注明出处 
  28. *原型:size_t strspn(const char * str1,const char * str2); 
  29. *用法:#include <string.h> 
  30. *功能:若strspn()返回的数值为n, 
  31. *       则代表字符串str1开头连续有n个字符都是属于字符串str2内的字符. 
  32. *说明:返回字符串str1开头连续包含字符串str2内的字符数目. 
  33. *自己实现strspn 
  34. */  
  35. #include <cstdio>  
  36. #include <cstring>  
  37.   
  38. size_t _strspn(const char * string,const char * control)  
  39. {  
  40.     const char * str = (const char *)string;  
  41.     const char * ctrl = (const char *)control;  
  42.     unsigned char map[32];  
  43.     int count = 0;  
  44.     /*clear the map*/  
  45.     memset(map,0,32*sizeof(unsigned char));  
  46.     //memset(map,0,32);  
  47.     /*set bits in control map*/  
  48.     while(*ctrl)  
  49.     {  
  50.         map[*ctrl >> 3] |= (0x01 << (*ctrl & 7));  
  51.         ctrl++;  
  52.     }  
  53.     /*count the str's char num in control*/  
  54.     if(*str)  
  55.     {  
  56.         count = 0;  
  57.   
  58.         while((map[*str >> 3] & (0x01 << (*str & 7))))  
  59.         {  
  60.             count++;  
  61.             str++;  
  62.         }  
  63.         return count;  
  64.     }  
  65.     return 0;  
  66. }  
  67.   
  68. int main(int args,char ** argv)  
  69. {  
  70.     char str[] = "129th";  
  71.     char keys[] = "1234567890";  
  72.   
  73.     int i = _strspn(str,keys);  
  74.   
  75.     printf("the initial string has %d numbers\n",i);  
  76.   
  77.     getchar();  
  78.     return 0;  
  79. }  

      C函数库中的strspn实现

      函数原型:size_t strcspn ( char  const  * str, char  const  *group);

       函数说明:strcspn()从参数str 字符串的开头计算连续的字符, 而这些字符都完全不在参数group所指的字符串中. 简单地说, 若strcspn()返回的数值为n, 则代表字符串str 开头连续有n 个字符都不含字符串group内的字符。

  1. /* 
  2. *copyright@nciaebupt 转载请注明出处 
  3. *原型:size_t strcspn(const char *s1,const char *s2); 
  4. *用法:#include <string.h> 
  5. *功能:在字符串s1中搜寻s2中所出现的字符。 
  6. *说明:返回第一个出现的字符在s1中的下标值, 
  7. *   亦即在s1中出现而s2中没有出现的子串的长度。 
  8. *使用C函数库中的strcspn 
  9. */  
  10. #include <cstdio>  
  11. #include <cstring>  
  12.   
  13. int main(int args,char ** argv)  
  14. {  
  15.     char str[] = "fcb373";  
  16.     char keys[] = "1234567890";  
  17.   
  18.     int i = strcspn(str,keys);  
  19.   
  20.     printf("The first number in str is in position : %d",i +1);  
  21.   
  22.     getchar();  
  23.     return 0;  
  24. }  
  25.   
  26. /* 
  27. *copyright@nciaebupt 转载请注明出处 
  28. *原型:size_t strcspn(const char *s1,const char *s2); 
  29. *用法:#include <string.h> 
  30. *功能:在字符串s1中搜寻s2中所出现的字符。 
  31. *说明:返回第一个出现的字符在s1中的下标值, 
  32. *   亦即在s1中出现而s2中没有出现的子串的长度。 
  33. *自己实现strcspn 
  34. */  
  35. #include <cstdio>  
  36.   
  37. size_t _strcspn(const char * string,const char * control)  
  38. {  
  39.     const unsigned char * str = (const unsigned char *)string;  
  40.     const unsigned char * ctrl = (const unsigned char *)control;  
  41.   
  42.     unsigned char map[32];  
  43.     int count = 0;  
  44.   
  45.     //clear the bit map  
  46.     for(count = 0;count < 32;count++)  
  47.     {  
  48.         map[count] = 0;  
  49.     }  
  50.     //set bit in control map  
  51.     while(*ctrl)  
  52.     {  
  53.         map[*ctrl >> 3] |= (0x01 << (*ctrl & 7));  
  54.         ctrl++;  
  55.     }  
  56.   
  57.     count = 0;  
  58.     map[0] |= 1;/*null chars not considered*/  
  59.     while(!(map[*str >> 3] & (0x01 << (*str & 7))))  
  60.     {  
  61.         count++;  
  62.         str++;  
  63.     }  
  64.     return count;  
  65. }  
  66.   
  67. int main(int args,char ** argv)  
  68. {  
  69.     char str[] = "fcb373";  
  70.     char keys[] = "1234567890";  
  71.   
  72.     int i = _strcspn(str,keys);  
  73.   
  74.     printf("The first number in str is in position : %d",i +1);  
  75.   
  76.     getchar();  
  77.     return 0;  
  78. }  
C函数库中的strcspn实现

     2.2查找标记

              函数原型:char *strtok ( char  *str , char  const *sep);

         函数功能:函数说明:strtok()用来将字符串分割成一个个片段。参数s 指向欲分割的字符串,参数delim 则为分割字符串,当strtok()在参数s 的字符串中发现到参数delim 的分割字符时则会将该字符改为\0 字符。在第一次调用时,strtok()必需给予参数s 字符串,往后的调用则将参数s 设置成NULL。每次调用成功则返回下一个分割后的字符串指针。

返回值:返回下一个分割后的字符串指针,如果已无从分割则返回NULL。

范例

   
  1. #include <string.h>
  2. main(){
  3. char s[] = "ab-cd : ef;gh :i-jkl;mnop;qrs-tu: vwx-y;z";
  4. char *delim = "-: ";
  5. char *p;
  6. printf("%s ", strtok(s, delim));
  7. while((p = strtok(NULL, delim)))
  8. printf("%s ", p);
  9. printf("\n");
  10. }

执行结果:
ab cd ef;gh i jkl;mnop;qrs tu vwx y;z     //-与:字符已经被\0 字符取代


[cpp]  view plain copy
  1. //strtok源码剖析 位操作与空间压缩  
  2. //http://blog.youkuaiyun.com/morewindows/article/details/8740315  
  3. //By MoreWindows( http://blog.youkuaiyun.com/MoreWindows )  
  4. #include <stdio.h>  
  5. // strtok源码剖析  
  6. char* __cdecl MyStrtok(char * string, const char * control)  
  7. {  
  8.     unsigned char *str;  
  9.     const unsigned char *ctrl = (const unsigned char *)control;  
  10.     static unsigned char* _TOKEN = NULL;   
  11.     //注意这里使用了static类型,实际的strtok函数出于线程安全会使用TLS  
  12.   
  13.     //由于char类型占一个字节取值范围为0~255  
  14.     //所以可以打个bool flag[255]这样的哈希表  
  15.     //来记录哪些字符为delimiter characters  
  16.     //然后根据《位操作基础篇之位操作全面总结》中的位操作与空间压缩  
  17.     //http://blog.youkuaiyun.com/morewindows/article/details/7354571#t6  
  18.     //可以将数组大小取255/8即32  
  19.     unsigned char map[32];  
  20.     int count;  
  21.   
  22.     // Clear control map  
  23.     for (count = 0; count < 32; count++)  
  24.         map[count] = 0;  
  25.   
  26.     // Set bits in delimiter table  
  27.     do {  
  28.         //map[*ctrl >> 3] |= (1 << (*ctrl & 7));//strtok原来的代码  
  29.         map[*ctrl / 8] |= (1 << (*ctrl % 8));  
  30.     } while (*ctrl++);  
  31.   
  32.     // Initialize str   
  33.     // If string is NULL, set str to the saved pointer   
  34.     //(i.e., continue breaking tokens out of the string from the last strtok call)  
  35.     if (string != NULL)  
  36.         str = (unsigned char *)string;  
  37.     else  
  38.         str = (unsigned char *)_TOKEN;  
  39.   
  40.     // Find beginning of token (skip over leading delimiters). Note that  
  41.     // there is no token iff this loop sets str to point to the terminal  
  42.     // null (*str == '\0')  
  43.     //while ( (map[*str >> 3] & (1 << (*str & 7))) && *str )//strtok原来的代码  
  44.     while ( (map[*str / 8] & (1 << (*str % 8))) && *str )  
  45.         str++;  
  46.   
  47.     string = (char *)str;  
  48.   
  49.     // Find the end of the token. If it is not the end of the string,  
  50.     // put a null there.   
  51.     for ( ; *str ; str++ )  
  52.     {  
  53.         //if ( map[*str >> 3] & (1 << (*str & 7)) ) //strtok原来的代码  
  54.         if ( map[*str / 8] & (1 << (*str % 8)) )   
  55.         {  
  56.             *str++ = '\0';  
  57.             break;  
  58.         }  
  59.     }  
  60.   
  61.     // Update nextoken (or the corresponding field in the per-thread data structure  
  62.     _TOKEN = str;  
  63.   
  64.     // Determine if a token has been found.   
  65.     if ( string == (char *)str )  
  66.         return NULL;  
  67.     else  
  68.         return string;  
  69. }  
  70. int main()  
  71. {  
  72.     printf("   strtok源码剖析 位操作与空间压缩\n");    
  73.     printf(" - http://blog.youkuaiyun.com/morewindows/article/details/8740315 -\n");    
  74.     printf(" - By MoreWindows( http://blog.youkuaiyun.com/MoreWindows ) - \n\n");   
  75.   
  76.     //char szText[] = "MoreWindows  (By http://blog.youkuaiyun.com/MoreWindows)";  
  77.     //char szFind[] = " ";  
  78.     char szText[] = "ab,c...d(e)f(g)hj";  
  79.     char szFind[] = ",.()";  
  80.   
  81.     printf("原字符串为: %s\n", szText);  
  82.     printf("分隔后为: \n");  
  83.     char *pToken = MyStrtok(szText, szFind);  
  84.     while (pToken != NULL)  
  85.     {  
  86.         printf("%s\n", pToken);  
  87.         pToken = MyStrtok(NULL, szFind);  
  88.     }  
  89.     return 0;  
strtok源码剖析

C函数库中的strtok实现

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值