【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
#include int main()
{char arr1[20] = "xxxxxxxxxxx";char arr2[] = "abcdef";char* ret = strcpy(arr1, arr2);printf("%s\n", ret);return 0;
}
结果如下:

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


strcpy函数模拟实现
知道了strcpy函数的逻辑,我们来试试模拟实现,代码如下:
#include
#include
#include char* 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
#include void 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
#include void 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!!!

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

