带你快速了解字符(串)函数

淩亂°似流年 2024-04-23 20:25 168阅读 0赞

⭐ 作者:小胡_不糊涂

? 作者主页:小胡_不糊涂的个人主页

? 持续更文,谢谢大家支持 ?

文章目录

  • 本文重点
    1. strlen函数
    • 1.1 模拟实现
    1. strcpy函数
    • 2.1 模拟实现
    1. strcat函数
    • 3.1 模拟实现
    1. strcmp函数
    • 4.1 模拟实现
    1. strncpy函数
    • 5.1 模拟实现
    1. strncat函数
    • 6.1 模拟实现
    1. strncmp函数
    • 7.1 模拟实现
    1. strstr函数
    • 8.1 模拟实现
    1. strtok函数
    1. strerror函数
  • 11.memcpy函数
    1. memmove函数
  • 结束语

本文重点






































函数作用 函数名
求字符串长度 strlen
长度不受限制的字符串函数 strcpy strcat strcmp
长度受限制的字符串函数 strncpy strncat strncmp
字符串查找 strstr strtok
错误信息报告 strerror
内存操作函数 memcpy memmove memset memcmp
字符操作

C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在常量字符串中或者字符数组中。
 
字符串常量适用于那些对它不做修改的字符串函数。

1. strlen函数

功能: 获取字符串长度

  1. size_t strlen ( const char * str );//返回字符串str的长度
  2. //str--字符串

字符串的长度由终止空字符 '\0'确定:字符串的长度与字符串开头和终止空字符之间的字符数一样长(不包括终止空字符本身)。

? 例如:

  1. char str[100]="string ";

定义了一个大小为 100 个字符的字符数组,但初始化 str 时使用的字符串的长度仅为 7 个字符。因此,当 sizeof(str) 的计算结果为 100 时,strlen(str) 返回 7。

在这里插入图片描述

通过 strlen函数 比较两个字符串大小

  1. //有符号
  2. #include<stdio.h>
  3. #include<string.h>
  4. int main()
  5. {
  6. const char* str1 = "abcdef";
  7. const char* str2 = "bbb";
  8. if ((int)strlen(str2) -(int) strlen(str1) > 0)
  9. {
  10. printf("str2>str1\n");
  11. }
  12. else
  13. {
  14. printf("srt1>str2\n");
  15. }
  16. return 0;
  17. }

? 打印结果:
在这里插入图片描述

  1. //无符号的
  2. #include<stdio.h>
  3. #include<string.h>
  4. int main()
  5. {
  6. const char* str1 = "abcdef";
  7. const char* str2 = "bbb";
  8. if (strlen(str2) - strlen(str1) > 0)
  9. {
  10. printf("str2>str1\n");
  11. }
  12. else
  13. {
  14. printf("srt1>str2\n");
  15. }
  16. return 0;
  17. }

? 打印结果:
在这里插入图片描述
因为函数返回值是无符号的

注:
? 字符串str以 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包含 ‘\0’ )。

? 参数指向的字符串必须要以 ‘\0’ 结束。
如果没有 ‘\0’ 结尾,长度会一直计算下去,直到遇到 ‘\0’ 。

? 注意函数的返回值为size_t,是无符号的。

1.1 模拟实现

  1. #include<stdio.h>
  2. size_t my_strlen(const char* str)
  3. {
  4. int count = 0;
  5. while (*str != '\0')//终止条件
  6. {
  7. count++;//累计 计算字符串长度
  8. str++;
  9. }
  10. return count;
  11. }
  12. int main()
  13. {
  14. size_t sz = my_strlen("abc");//无符号类型
  15. printf("%u\n", sz);//打印无符号十进制整型
  16. return 0;
  17. }

2. strcpy函数

功能: 复制字符串

  1. char * strcpy ( char * destination, const char * source );
  2. //destination(目的地)--指向要在其中复制内容的目标数组的指针
  3. //source(源)--要复制的字符串

将源指向的字符串复制到目标指向的数组中,包括终止的 ‘\0’ 字符(并在该点停止)。

为避免溢出,目标指向的数组的大小应足够长,以包含与源相同的字符串(包括终止空字符),并且不应在内存中与源重叠

? 实例1:

  1. #include <stdio.h>
  2. #include<string.h>
  3. int main()
  4. {
  5. char str1[] = "Sample string";
  6. char str2[40];
  7. char str3[40];
  8. strcpy(str2, str1);//将str1拷贝到str2
  9. strcpy(str3, "copy successful");
  10. printf("str1: %s\nstr2: %s\nstr3: %s\n", str1, str2, str3);
  11. return 0;
  12. }

? 运行结果:

在这里插入图片描述

? 实例2:

  1. #include <stdio.h>
  2. #include<string.h>
  3. int main()
  4. {
  5. char arr1[] = "xxxxxxxxxx";
  6. char arr2[5] = {
  7. 'a', 'b', 'c', 'd', 'e' };
  8. strcpy(arr1, arr2);//将 arr2 里的东西拷贝到 arr1 中
  9. printf("%s\n", arr1);
  10. return 0;
  11. }

? 运行结果:
在这里插入图片描述

为什么结果不是 abcde 呢?
我们在调试时,打开监视窗口观察arr1的变化,虽然 abced 已拷贝给 arr1, 但没有发现结束标志,所以在创建 arr2 时,要在最后加上 ‘\0’
在这里插入图片描述在这里插入图片描述
添加了结束标志的 arr2 :
在这里插入图片描述

注:
? 源字符串必须以 ‘\0’ 结束。

? 会将源字符串中的 ‘\0’ 拷贝到目标空间。

? 目标空间必须足够大,以确保能存放源字符串。

? 目标空间必须可变。

2.1 模拟实现

  1. #include<stdio.h>
  2. #include<assert.h>
  3. char* my_strcpy(char* dest, const char* src)
  4. {
  5. char* ret = dest;
  6. assert(dest != NULL);//若字符串为空,就停止运行,并提示
  7. assert(src != NULL);
  8. while (*src != '\0')
  9. {
  10. *dest = *src;//实现拷贝
  11. dest++;//后移一个字符
  12. src++;
  13. }
  14. *dest = *src;// '\0'
  15. return ret;
  16. }
  17. int main()
  18. {
  19. char arr1[20] = "hello world";
  20. char arr2[] = "xxxxx";
  21. my_strcpy(arr1 + 6, arr2);//从arr1的第六个字符之后开始拷贝arr2
  22. printf("%s\n", arr1);
  23. return 0;
  24. }

? 运行结果:

在这里插入图片描述

?补充:

  1. assert(表达式)--表达式为真时, 程序继续运行, 如果表达式为假, 那程序就会停止运行, 并提示错误信息

3. strcat函数

功能: 连接字符串

  1. char * strcat ( char * destination, const char * source );
  2. //destineion--指向目标数组的指针,该数组应包含字符串,并且足够大以包含串联的结果字符串
  3. //source--要追加的字符串

将源字符串的副本追加到目标字符串。
目标中的终止空字符被源的第一个字符覆盖,并且在目标中由两者串联形成的新字符串的末尾包含一个空字符

目的地和来源不得重叠。

? 实例:

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main()
  4. {
  5. char str1[100]="hello ";
  6. char str2[] = "world";
  7. printf("%s\n", strcat(str1, str2));
  8. return 0;
  9. }

? 运行结果:

在这里插入图片描述

注:
? 源字符串必须以 ‘\0’ 结束。

? 目标空间必须有足够的大,能容纳下源字符串的内容。

? 目标空间必须可修改。

3.1 模拟实现

  1. #include<stdio.h>
  2. char* my_strcat(char*dest, const char *src)
  3. {
  4. assert(dest && src);
  5. char* ret = dest;
  6. //1. 找目标空间中的\0
  7. while (*dest)
  8. {
  9. dest++;
  10. }
  11. while (*dest++ = *src++)//实现拷贝
  12. {
  13. ;
  14. }
  15. return ret;
  16. }
  17. int main()
  18. {
  19. char arr1[20] = "hello ";
  20. char arr2[] = "world";
  21. my_strcat(arr1, arr2);
  22. printf("%s\n", arr1);
  23. return 0;
  24. }

4. strcmp函数

功能: 比较两个字符串

  1. int strcmp ( const char * str1, const char * str2 );

将字符串 str1 与字符串 str2 进行比较。

开始比较每个字符串的第一个字符。如果它们彼此相等,则继续以下对,直到字符不同或达到终止空字符。

此函数执行字符的二进制比较。

标准规定:
? 第一个字符串大于第二个字符串,则返回大于0的数字

? 第一个字符串等于第二个字符串,则返回0

? 第一个字符串小于第二个字符串,则返回小于0的数字

? 实例1:

  1. #include<stdio.h>
  2. #include<string.h>
  3. int main()
  4. {
  5. printf("%d\n", strcmp("bbq","bcq"));
  6. return 0;
  7. }

? 运行结果:
-1

? 实例2:猜动物

  1. #include<stdio.h>
  2. #include<string.h>
  3. int main()
  4. {
  5. char str1[] = "dog";
  6. char str2[80];
  7. do {
  8. printf("Guess my favorite animal? ");
  9. scanf("%s", str2);
  10. } while (strcmp(str1, str2) != 0);
  11. puts("Correct answer!");
  12. return 0;
  13. }

? 运行结果:

在这里插入图片描述

4.1 模拟实现

  1. int my_strcmp(const char* str1, const char* str2)
  2. {
  3. assert(str1 && str2);
  4. while (*str1 == *str2)
  5. {
  6. if (*str1 == '\0')
  7. return 0;
  8. str1++;//后移
  9. str2++;
  10. }
  11. return (*str1 - *str2);
  12. }
  13. int main()
  14. {
  15. int ret = my_strcmp("bbq", "bcq");
  16. if (ret>0)
  17. printf(">\n");
  18. printf("%d\n", ret);//-1
  19. return 0;
  20. }

5. strncpy函数

功能: 从字符串中复制字符

  1. char * strncpy ( char * destination, const char * source, size_t num );
  2. //destination--指向要在其中复制内容的目标数组的指针。
  3. //source--要复制的 C 字符串。
  4. //num--要从源复制的最大字符数。
  5. //size_t 是无符号整数类型。

拷贝num个字符从源字符串到目标空间。

如果源字符串的长度小于 num,则拷贝完源字符串之后,在目标的后边追加0,直到 num个。

? 实例:

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main()
  4. {
  5. char str1[] = "To be or not to be";
  6. char str2[40];
  7. char str3[40];
  8. strncpy(str2, str1, sizeof(str2));
  9. strncpy(str3, str2, 5);
  10. str3[5] = '\0';
  11. puts(str1);//打印字符串
  12. puts(str2);
  13. puts(str3);
  14. return 0;
  15. }

? 运行结果:

在这里插入图片描述

5.1 模拟实现

  1. #include<stdio.h>
  2. #include<assert.h>
  3. char* my_strncpy(char* dest, const char* sou, size_t num)
  4. {
  5. char* ret = dest;
  6. assert(dest != NULL);
  7. assert(sou != NULL);
  8. for (int i = (int)num; i > 0; i--)
  9. *dest++ = *sou++;
  10. return ret;
  11. }
  12. int main()
  13. {
  14. char str1[20] = "abcdef";
  15. char str2[] = "xxx";
  16. my_strncpy(str1, str2, sizeof(str1));
  17. puts(str1);
  18. return 0;
  19. }

? 运行结果:
xxx
在这里插入图片描述

6. strncat函数

功能: 从字符串追加字符

  1. char * strncat ( char * destination, const char * source, size_t num );
  2. //destination--指向目标数组的指针,该数组应包含一个字符串,并且足够大以包含串联的结果字符串,包括其他 null 字符。
  3. //source--要追加的 C 字符串。
  4. //num--要追加的最大字符数。
  5. //size_t是无符号整数类型。

将源的第一个数字字符追加到目标,外加一个终止空字符。

如果源中 C 字符串的长度小于 num,则仅复制终止空字符之前的内容。

? 实例1:

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main ()
  4. {
  5. char str1[20];
  6. char str2[20];
  7. strcpy (str1,"To be ");
  8. strcpy (str2,"or not to be");
  9. strncat (str1, str2, 6);//将str2的前6个字符追加给str1后面
  10. puts (str1);//To be or not
  11. return 0;
  12. }

? 运行结果:
在这里插入图片描述
? 实例2:

  1. int main()
  2. {
  3. char arr1[20] = "abcdef\0yyyyyyyy";
  4. char arr2[] = "xxxxxxxxx";
  5. strncat(arr1, arr2, 3);
  6. puts(arr1);//abcdefxxx
  7. return 0;
  8. }

在这里插入图片描述

?说明了,遇到了结束标志 '\0' 就开始复制源代码

6.1 模拟实现

  1. #include <stdio.h>
  2. #include<assert.h>
  3. char* my_strncat(char* dest, const char* soc, size_t num)
  4. {
  5. char* ret = dest;
  6. int i=0;
  7. int count = 0;
  8. assert(dest != NULL);
  9. assert(soc != NULL);
  10. while (*dest != '\0')
  11. {
  12. dest++;
  13. }
  14. while (num--)//终止条件:复制的个数num
  15. *dest++ = *soc++;//追加
  16. *dest = '\0';
  17. return ret;
  18. }
  19. int main()
  20. {
  21. char arr1[20] = "abcdef\0yyyyyyyy";
  22. char arr2[] = "xxxxxxxxx";
  23. my_strncat(arr1, arr2, 3);
  24. puts(arr1);//abcdefxxx
  25. return 0;
  26. }

? 运行结果:

在这里插入图片描述

7. strncmp函数

功能: 比较两个字符串的字符

  1. int strncmp ( const char * str1, const char * str2, size_t num );

将字符串 str1 的字符数与字符串 str2 的字符数进行比较。

此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续使用以下对,直到字符不同,直到达到终止的空字符,或者直到两个字符串中的 num 字符匹配,以先发生者为准。

标准规定:

? 第一个不匹配的字符在 str1 中的值大于在 str2 中的值,则返回大于0的数字

? 两个字符串的内容相等,则返回0

? 不匹配的第一个字符在 str1 中的值低于 str2 中的值,则返回小于0的数字

? 实例:

  1. //代码1
  2. #include <stdio.h>
  3. #include<string.h>
  4. int main()
  5. {
  6. char arr1[] = "abcioxjnjj";
  7. char arr2[] = "abcdef";
  8. printf("%d\n", strncmp(arr1, arr2, 4));//1
  9. return 0;
  10. }
  11. //代码2:
  12. int main()
  13. {
  14. char arr1[] = "abcdoxjnjj";
  15. char arr2[] = "abcdef";
  16. printf("%d\n", strncmp(arr1, arr2, 4));//0
  17. return 0;
  18. }

7.1 模拟实现

strncmp 函数与 strcmp 函数相似,不过它是比较两个字符串的前n个字符,它比较结束的标志是比较出来前n个字符的不同或者直到 ’\0’ 为止。

  1. #include<stdio.h>
  2. #include<assert.h>
  3. int my_strncmp(const char* str1, const char* str2, size_t num)
  4. {
  5. assert(str1 != NULL);
  6. assert(str2 != NULL);
  7. while (num && *str1 && *str2)
  8. {
  9. if (*str1 > *str2)
  10. {
  11. return 1;
  12. }
  13. if (*str1 < *str2)
  14. {
  15. return -1;
  16. }
  17. else
  18. {
  19. return 0;
  20. }
  21. num--;
  22. str1++;
  23. str2++;
  24. }
  25. return 0;
  26. }
  27. int main()
  28. {
  29. char* str1 = "abcdoxjnjj";
  30. char* str2 = "abcdef";
  31. int ret = my_strncmp(str1, str2, 4);
  32. printf("%d\n", ret);
  33. return 0;
  34. }

? 运行结果:
0

8. strstr函数

功能: 查找子字符串

  1. const char * strstr ( const char * str1, const char * str2 );
  2. //str1--要扫描的字符串。
  3. //str2--包含要匹配的字符序列的字符串

返回指向 str2 中第一次出现的 str1 的指针,如果 str2 不是 str1 的一部分,则返回一个空指针
匹配过程不包括终止空字符,但它到此为止。

? 实例:

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main()
  4. {
  5. char arr1[] = "abbbcdef";
  6. char arr2[] = "bbc";
  7. char* ret = strstr(arr1, arr2);
  8. if (ret != NULL)
  9. printf("%s\n", ret);
  10. else
  11. printf("找不到\n");
  12. return 0;
  13. }

? 运行结果:

在这里插入图片描述

8.1 模拟实现

  1. #include <stdio.h>
  2. char* my_strstr(char* str1, char* str2)
  3. {
  4. char* cp = str1;
  5. char* s1 = cp;
  6. char* s2 = str2;
  7. if (*str2 == '\0')
  8. return str1;
  9. while (*cp)
  10. {
  11. //开始匹配
  12. s1 = cp;
  13. s2 = str2;
  14. while (*s1 && *s2 && *s1 == *s2)
  15. {
  16. s1++;
  17. s2++;
  18. }
  19. if (*s2 == '\0')
  20. return cp;
  21. cp++;
  22. }
  23. return NULL;
  24. }
  25. int main()
  26. {
  27. char arr1[] = "abbbcdef";
  28. char arr2[] = "bbc";
  29. char* ret = my_strstr(arr1, arr2);
  30. if (ret != NULL)
  31. printf("%s\n", ret);
  32. else
  33. printf("找不到\n");
  34. return 0;
  35. }

9. strtok函数

功能: 将字符串拆分为标记

  1. char * strtok ( char * str, const char * delimiters );
  • sep 参数是个字符串,定义了用作分隔符的字符集合。
  • 第一个参数指定一个字符串,它包含了0个或者多个由 sep 字符串中一个或者多个分隔符分割的标记。
  • strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。

(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改)

? 实例:

  1. #include<string.h>
  2. #include <stdio.h>
  3. int main()
  4. {
  5. char* p = "woaiCyuyan.com/cn";
  6. const char* sep = "./";
  7. char arr[30];
  8. char* str = NULL;
  9. strcpy(arr, p);//将数据拷贝一份,处理arr数组的内容
  10. for (str = strtok(arr, sep); str != NULL; str = strtok(NULL, sep))
  11. {
  12. printf("%s\n", str);
  13. }
  14. return 0;
  15. }

? 运行结果:

在这里插入图片描述

10. strerror函数

功能: 返回错误码,所对应的错误信息

  1. char * strerror ( int errnum );

? 实例:

  1. #include <stdio.h>
  2. #include<string.h>
  3. #include <errno.h>//必须包含的头文件
  4. int main()
  5. {
  6. int i = 0;
  7. for (i = 0; i < 10; i++)
  8. {
  9. printf("%d: %s\n", i, strerror(i));
  10. }
  11. return 0;
  12. }

? 运行结果:
在这里插入图片描述

11.memcpy函数

功能: 复制内存块

  1. void * memcpy ( void * destination, const void * source, size_t num );
  2. //destination--指向要在其中复制内容的目标数组的指针,类型转换为 void* 类型的指针。
  3. //source--指向要复制的数据源的指针,类型转换为 const void* 类型的指针。
  4. //num--要复制的字节数。
  5. //size_t 是无符号整数类型。

? 函数 memcpy 从 source 的位置开始向后复制 num 个字节的数据到destination的内存位置。

? 这个函数在遇到 ‘\0’ 的时候并不会停下来。

? 如果 source 和 destination 有任何的重叠,复制的结果都是未定义的。

? 实例:

  1. #include <stdio.h>
  2. #include <string.h>
  3. struct {
  4. char name[40];
  5. int age;
  6. } person, person_copy;
  7. int main()
  8. {
  9. char myname[] = "peter";
  10. memcpy(person.name, myname, strlen(myname) + 1);
  11. person.age = 46;
  12. memcpy(&person_copy, &person, sizeof(person));
  13. printf("person_copy: %s, %d \n", person_copy.name, person_copy.age);
  14. return 0;
  15. }

? 运行结果:
在这里插入图片描述

12. memmove函数

功能: 移动内存块,将字节数的值从源指向的位置复制到目标指向的内存块

  1. void * memmove ( void * destination, const void * source, size_t num );

? 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。

? 如果源空间和目标空间出现重叠,就得使用memmove函数处理。

? 实例:

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main ()
  4. {
  5. char str[] = "i love C";
  6. memmove(str , str +2, 3);
  7. //从l开始的三个字符(lov)移动到str中,且覆盖了str原来的前三个字符
  8. puts (str);
  9. return 0;
  10. }

? 运行结果:

在这里插入图片描述


结束语

有关字符(串)的函数还有很多,我们还需要勤加练习,慢慢消化。
  加油^_^
  我们下一篇文章再见。
在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,168人围观)

还没有评论,来说两句吧...

相关阅读

    相关 了解Spring~

    文章目录 第一章:Spring框架的介绍 第二章:创建Hello world 第三章:Spring IOC容器 第四章:Spring框架的Bean管理 -------