【C语言】字符串函数分析及模拟实现(万字详解!)

目录

  • 前言
  • 1.求字符串长度的字符函数
    • 1.1strlen
      • strlen函数介绍
      • strlen函数简单应用
      • strlen函数模拟实现
  • 2.长度不受限制的字符串函数
    • 2.1strcpy
      • strcpy函数介绍
      • strcpy函数简单应用
      • strcpy函数模拟实现
    • 2.2strcat
      • strcat函数介绍
      • strcat函数简单应用
      • strcat函数模拟实现
    • 2.3strcmp
      • strcmp函数介绍
      • strcmp函数简单应用
      • strcmp函数模拟实现
  • 3.长度受限制的字符串函数
    • 3.1strncpy
      • strncpy函数介绍
      • strncpy简单应用
    • 3.2strncat
      • strncat函数介绍
      • strncat简单应用
    • 3.3strncmp
      • strncmp函数介绍
      • strncmp简单应用
  • 4.字符串查找函数
    • 4.1strstr
      • strstr函数介绍
      • strstr简单应用
    • 4.2strtok
      • strtok函数介绍
      • strtok简单应用
  • 5.错误信息报告函数
    • 5.1strerror
      • strerror函数介绍
      • strerror简单应用
  • 6.字符分类函数
  • 7.内存操作函数
    • memcpy
      • memcpy函数介绍
      • memcpy简单应用
      • memcpy函数模拟实现
    • memmove
      • memmove函数介绍
      • memmove简单应用
      • memmove函数模拟实现
  • 结语


前言

在以前的学习我们掌握了基础的字符函数类型,知道了一些字符串函数如何使用,但不知道具体函数是如何实现的。本篇文章将系统介绍讲解C语言中的字符串函数。通过简洁高效的代码,为友友提供一个清晰明了的讲解,让我们开始吧!


前提!!在使用字符串函数前都要引用头文件#include!!!

1.求字符串长度的字符函数

1.1strlen

strlen函数介绍

先看看C语言编译库是如何定义strlen函数的。

在这里插入图片描述
(不知道如何查询C语言编译库可以看我的这期博客,里面有提到 : qsort函数)

根据定义我们知道是将目标字符串的首元素地址传给strlen来进行测量。

使用时需要注意以下几点:

  • 字符串以 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包 含 ‘\0’ )
  • 参数指向的字符串必须要以 ‘\0’ 结束。
  • 注意函数的返回值为size_t,是无符号的,所以返回值一定大于等于0

strlen函数简单应用

现在尝试运用一下strlen函数,代码如下:

#define  _CRT_SECURE_NO_WARNINGS 1 #include
#include
int main()
{char arr[] = "1234567890";size_t ret = strlen(arr);printf("%zd\n", ret);return 0;
}

结果如下:
在这里插入图片描述

strlen函数模拟实现

通过上面的分析我们知道strlen函数的基本逻辑就是找到字符串的首地址然后一直计数直到遇到’\0‘就返回。那么根据这个逻辑我们试试模拟实现strlen函数,代码如下:

#define  _CRT_SECURE_NO_WARNINGS 1 
#include
#include
//方法1:计数
size_t my_strlen1(const char* arr)
{assert(arr);//检验arr是否为空指针int count = 0;while (*arr != '\0'){count++;arr++;}return count;
}//方法2:指针-指针
size_t my_strlen2(const char* arr)
{assert(arr);const char* arr1 = arr;while (*arr != '\0'){arr++;}return arr - arr1;
}//方法3:递归
size_t my_strlen3(const char * str)
{if(*str == '\0')return 0;elsereturn 1+my_strlen(str+1);
}int main()
{char arr[] = "1234567890";size_t ret1 = my_strlen1(arr);printf("%zd\n", ret1);size_t ret2 = my_strlen2(arr);printf("%zd\n", ret2);size_t ret3 = my_strlen3(arr);printf("%zd\n", ret3);return 0;
}

结果如下:
在这里插入图片描述


2.长度不受限制的字符串函数

2.1strcpy

strcpy函数介绍

在这里插入图片描述
strcpy函数有复制字符串的作用,将source(源字符串)复制到destination(目标空间)。

使用时需要注意以下几点:

  • 源字符串必须以 ‘\0’ 结束。
  • 会将源字符串中的 ‘\0’ 拷贝到目标空间
  • 目标空间必须足够大,以确保能存放源字符串。
  • 目标空间必须可更改(不是常量字符串也没有const修饰),否则报错。

strcpy函数简单应用

现在尝试运用一下strcpy函数,代码如下:

#include
#includeint main()
{char arr1[20] = "xxxxxxxxxxx";char arr2[] = "abcdef";char* ret = strcpy(arr1, arr2);printf("%s\n", ret);return 0;
}

结果如下:
在这里插入图片描述

同时我们可以看看arr1数组内部的变化:

在这里插入图片描述
在这里插入图片描述

strcpy函数模拟实现

知道了strcpy函数的逻辑,我们来试试模拟实现,代码如下:

#include
#include
#includechar* my_strcpy(char* str1, const char* str2)
{assert(str1 && str2);char* ret = str1;while (*str1++ = *str2++){;}return ret;
}int main()
{char arr1[20] = "xxxxxxxxxxx";char arr2[] = "abcdef";//char* ret = strcpy(arr1, arr2);char* ret = my_strcpy(arr1, arr2);printf("%s\n", ret);return 0;
}

结果如下:
在这里插入图片描述


2.2strcat

strcat函数介绍

在这里插入图片描述
strcat函数功能是追加字符串,即在目标字符串后接上源字符串实现追加。

使用时需要注意以下几点:

  • 源字符串必须以 ‘\0’ 结束。
  • 会将源字符串中的 ‘\0’ 拷贝到目标空间
  • 目标空间必须足够大,以确保能存放源字符串。
  • 目标空间必须可更改(不是常量字符串也没有const修饰),否则报错。

strcat函数简单应用

那么现在尝试运用一下strcpy函数,代码如下:

#include
#include
int main()
{char arr1[20] = "abcdef";char arr2[] = "12345678";char* ret = strcat(arr1, arr2);printf("%s\n", ret);return 0;
}

结果如下:
在这里插入图片描述

strcat函数模拟实现

strcat函数是找到目标空间的末尾后开始将源字符串存入空间,同时最后也将’\0‘拷贝。
现在知道了strcat函数的逻辑,我们来试试模拟实现,代码如下:

#include
#include
#include
char* my_strcat(char* arr1,const char* arr2)
{char* ret = arr1;assert(arr1 && arr2);while (*arr1){arr1++;}while ((*arr1++ = *arr2++)){;}return ret;}int main()
{char arr1[20] = "abcdef";char arr2[] = "12345678";//char* ret = strcat(arr1, arr2);char* ret = my_strcat(arr1, arr2);printf("%s\n", ret);return 0;
}

结果如下:
在这里插入图片描述


2.3strcmp

strcmp函数介绍

在这里插入图片描述
strcmp函数意思是str compare,字符串比较。可以看到函数返回类型是整型,它通过 依次比较两字符串元素的ASCII值得出结果。那如何通过整型返回值来反映大小关系呢?
我们可以看看C程序编译库中对返回值的解释:
在这里插入图片描述

通过图片我们得知,ptr1是字符串1的地址,ptr2是字符串2的地址,而函数返回值的意思如下:

如果 *ptr1> *ptr2 ,那么就返回大于0的值,str1 > str2。
如果 *ptr1= *ptr2,那么就返回0即可 ’‘’‘’‘’‘ str1 = str2。
如果 *ptr1< *ptr2 ,那么就返回小于0的值,str1 < str2。

strcmp函数简单应用

基本明白之后我们就可以来试着应用一下了,代码如下:

#include
#includevoid my_judge(int ret)//判断结果函数
{if (ret > 0){printf(">\n");}if (ret < 0){printf("<\n");}if (ret == 0){printf("=\n");}
}int main()
{char arr1[] = "abcdef";char arr2[] = "abce";//与arr1元素有不同,与arr1比应输出‘<’char arr3[] = "abcde";//与arr1长度不同,其他元素相同,与arr1比应输出‘>’int ret1 = strcmp(arr1, arr2);my_judge(ret1);int ret2 = strcmp(arr1, arr3);my_judge(ret2);return 0;
}

结果如下:

在这里插入图片描述

我们可以发现,字符串并不是越长值就越大,而是在比较过程中谁先有较大的元素,谁就是较大者 😃。

strcmp函数模拟实现

进行了一系列实践,现在我们可以试试来模拟实现strcmp函数,代码如下:

#include
#include
#includevoid my_judge(int ret)//判断结果函数
{if (ret > 0){printf(">\n");}if (ret < 0){printf("<\n");}if (ret == 0){printf("=\n");}
}int my_strcmp(const char* ptr1, const char* ptr2)
{assert(ptr1 && ptr2);while (*ptr1 == *ptr2){if (*ptr1 == '\0'){return 0;}ptr1++;ptr2++;}if (*ptr1 > *ptr2){return 1;}elsereturn -1;
}int main()
{char arr1[] = "abcdef";char arr2[] = "abce";//与arr1元素有不同,与arr1比应输出‘<’char arr3[] = "abcde";//与arr1长度不同,其他元素相同,与arr1比应输出‘>’//int ret1 = strcmp(arr1, arr2);//my_judge(ret1);//int ret2 = strcmp(arr1, arr3);//my_judge(ret2);int ret1 = my_strcmp(arr1, arr2);my_judge(ret1);int ret2 = my_strcmp(arr1, arr3);my_judge(ret2);printf("\n别忘了点赞三连支持欧o(>ω< )o!!!\n");printf("(深情)\n");return 0;
}

结果如下:

在这里插入图片描述


3.长度受限制的字符串函数

3.1strncpy

strncpy函数介绍

在这里插入图片描述
strncpy函数和strcpy多了一个参数num,具体作用如下:

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

strncpy简单应用

了解明白新内容现在就来简单应用一下!代码如下:

#include 
#include int main()
{char str1[] = "To be or not to be";char str2[40];char str3[40];strncpy(str2, str1, sizeof(str2));strncpy(str3, str2, 5);str3[5] = '\0';  puts(str1);puts(str2);puts(str3);return 0;
}

结果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


3.2strncat

strncat函数介绍

在这里插入图片描述
和strcat函数很像,不过同样多了个num参数,具体作用如下:

函数将源字符串的前 num 个字符复制到目标字符串,外加一个终止空字符’\0’。
如果源字符串的长度小于 num,则只复制终止空字符之前的内容。

strncat简单应用

了解明白新内容现在就来简单应用一下!代码如下:

#include 
#include int main()
{char str1[20];char str2[20];strcpy(str1, "To be ");strcpy(str2, "or not to be");strncat(str1, str2, 6);puts(str1);return 0;
}

结果如下:
在这里插入图片描述
可以看到只在str1后接了6个元素,然后停止,不论是否遇到’\0’。


3.3strncmp

strncmp函数介绍

在这里插入图片描述
一样的道理,多了一个num,具体作用如下:

该函数从每个字符串的第一个字符开始比较。如果两个字符串的第一个字符相等,则继续比较下面的字符对,直到两个字符串的字符不同,或者比较到一个终止的空字符’\0’,或者比较到两个字符串中匹配的字符个数,以先发生者为准。

通俗来讲可以理解成:在strcmp函数功能的基础上,由以往的从头比到尾变成了可以控制在一定长度范围内进行比较

strncmp简单应用

都多余了,开始实践!代码如下:

#include 
#include int main()
{char str[3][5] = { "R2D2" , "C3PO" , "R2A6" };int n;puts("查找 R2 ...");for (n = 0; n < 3; n++)if (strncmp(str[n], "R2xx", 2) == 0){printf("found %s\n", str[n]);}return 0;
}

结果如下:
在这里插入图片描述
可以看到,找到的字符串和“R2XX”后两位还是不一样的,但是还是成功找到了R2,成功使用strncmp!!^ ^


4.字符串查找函数

4.1strstr

strstr函数介绍

在这里插入图片描述
strstr函数具体内容如下:

返回 字符串str1 中第一次完整出现 字符串str2 的指针,如果 str2 不是 str1 的一部分,即查找不到,则返回空指针NULL
匹配过程不包括空字符’\0’,但会在此位置时停止。

strstr简单应用

还是得实操一下才能真正理解,代码如下:

#include 
#include int main()
{char str[] = "This is a simple string";char* pch;pch = strstr(str, "simple");//pch存放查找到对应字符串的首字母地址if (pch != NULL)strncpy(pch, "sample", 6);puts(str);return 0;
}

结果如下:

在这里插入图片描述
也就意味着查找到了地址并用strcpy更改了内容,成功!!


4.2strtok

strtok函数介绍

在这里插入图片描述

sep参数是个字符串,定义了用作分隔符的字符集合。
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
如果字符串中不存在更多的标记,则返回 NULL 指针

strtok简单应用

开始冻手!!代码如下:

#include 
#include int main()
{char arr[] = "tobe@or.not to be";char buf[200] = {0};//"tobe@or.not to be"strcpy(buf, arr);char* p = "@.";char* s = strtok(buf, p);printf("%s\n", s);s = strtok(NULL, p);printf("%s\n", s);s = strtok(NULL, p);printf("%s\n", s);return 0;
}

结果如下:
在这里插入图片描述


5.错误信息报告函数

5.1strerror

strerror函数介绍

在这里插入图片描述

这个函数有些特别,它所返回的是错误码所对应的错误信息的地址

那我就会问了,错误码是什么呢?其实很好理解,我们上网打开网页经常会出现问题,例如“404Not found!!”等等,这些都是错误码。通过strerror函数可以把这些错误码对应的具体问题详细输出,就不仅仅只是个数字在屏幕上了。

strerror简单应用

冻手!冻手!代码如下:

#include 
#include int main()
{int i = 0;for (i = 1; i < 10; i++){printf("%d:%s\n", i, strerror(i));}return 0;
}

结果如下:

在这里插入图片描述
可以看到每个数字对应的错误问题,有意思哦 ^ ^。


6.字符分类函数

在这里插入图片描述


7.内存操作函数

memcpy

memcpy函数介绍

在这里插入图片描述
函数memcpy具体功能实现是从source的位置开始向后复制num个字节的数据到destination的内存位置。这个函数在遇到 ‘\0’ 的时候并不会停下来。

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

memcpy简单应用

那就试试呗,代码如下:

#include 
#include void test()
{char arr1[] = "abcdef";char arr2[5] = { 0 };memcpy(arr2, arr1, 3);printf("%s", arr2);
}int main()
{test();return 0;
}

结果如下:
在这里插入图片描述

memcpy函数模拟实现

在这也试试模拟实现memcpy,代码如下:

#define  _CRT_SECURE_NO_WARNINGS 1 
//模拟实现memcpy
//void* memcpy(void* destination, const void* source, size_t num);
#include
#include
#include
void* my_memcpy(void* dest,const void* str, size_t sz)
{void* ret = dest;while (sz--){*(char*)dest = *(char*)str;djieguoest = (char*)dest + 1;str = (char*)str + 1;}return ret;
}int main()
{char arr1[] = "hello world";char arr2[] = "abc";my_memcpy(arr1, arr2, 3);printf("%s\n", arr1);printf("\n别忘了点赞三连支持欧o(>ω< )o!!!\n");printf("(深情)\n");return 0;
}

结果如下:
在这里插入图片描述


memmove

memmove函数介绍

在这里插入图片描述
这个很好理解,它和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
如果源空间和目标空间出现重叠,就得使用memmove函数处理。

memmove简单应用

尝试着使用一下,都差不多的了,我就不在这里赘述了,我觉得很彳亍 😃

memmove函数模拟实现

那memmove是如何实现的呢?代码如下:

//memmove模拟实现
//void * memmove ( void * destination, const void * source, size_t num );
#include
#include
#include
void* my_memmove(void* dest,const void* str, size_t num)
{assert(dest && str);void* ret = dest;if (dest < str){//从前到后while (num--){*(char*)dest = *(char*)str;dest = (char*)dest + 1;str = (char*)str + 1;}}else//从后到前{dest = (char*)dest + num - 1;str = (char*)str + num - 1;while (num--){*(char*)dest = *(char*)str;dest = (char*)dest - 1;str = (char*)str - 1;}}return ret;
}int main()
{char arr[] = "memmove can be very useful......";void* str = my_memmove(arr + 20, arr + 15, 5);puts(arr);return 0;
}

结语

好了以上就是本篇“【C语言】字符串函数分析及模拟实现”博客的全部内容啦,感谢各位的阅读=v=,如有不足之处欢迎在评论区指出哦!!
觉得可以的话别忘了点赞三连支持一下欧!拜托啦这对我真的很重要o(>ω< )o!!!

请添加图片描述


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部