一、字符串函数
1.strlen
(1)strlen的库函数文档
如下图所示,是strlen在库函数中的文档。
它的参数是const char*类型的,这是考虑到它不会被改变的原因
返回类型是size_t类型的,这是考虑到它计算的是长度不会是负数的原因
这个函数返回的是一个字符串的长度,传入一个地址,计算的是\0字符之前的长度
(2)strlen的模拟实现
在这里我们采用三种方式来实现:循环计数、递归、指针减指针
#include<stdio.h> #include<assert.h> //循环计数 int my_strlen1(const char* str) { assert(str); int count = 0; while (*str != '\0') { count++; str++; } return count; } //递归 int my_strlen2(const char* str) { assert(str); if (*str == NULL) { return 0; } return 1 + my_strlen2(str + 1); } //指针减指针 int my_strlen3(const char* str) { assert(str); const char* start = str; while (*str != '\0') { str++; } return str - start; } int main() { char arr[] = "abcdef"; int len = my_strlen3(arr); printf("%d\n", len); return 0; }
(3)strlen的注意事项
1.字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。
2.参数指向的字符串必须要以 '\0' 结束
3.注意函数的返回值为size_t,是无符号的
关于第三点注意事项,我们在这里着重说一下
#include<stdio.h> #include<string.h> int main() { if (strlen("abc") - strlen("abcdef") > 0) { printf(">\n"); } else { printf("<=\n"); } return 0; }
这段代码的运行结果是
肯定与我们的设想是不一样的,因为strlen("abc")计算出来的是3,strlen("abcdef")计算出来的是6,虽然看上去好像3-6是-3,应该是<=,但是要主要这里的都是无符号的,计算出来的结果也是无符号的。所以这个数其实在内存中来看是一个很大的数。还是大于0的,所以是>
2.strcpy
(1)strcpy的库函数文档
它的参数是char* destination 和const char* source,destination的意思是目标空间的地址,
source的意思是源头空间的地址,这个地址里面的值是不可以被修改的。
功能是将source处的字符串拷贝到destination处
返回类型是char*,意思是将destination处的地址返回
(2)strcpy的使用以及注意事项
1.源字符串必须以 '\0' 结束。
2.会将源字符串中的 '\0' 拷贝到目标空间。
3.目标空间必须足够大,以确保能存放源字符串。
4.目标空间必须可变。
在下面这段代码中
#include<stdio.h> #include<string.h> int main() { char arr1[] = "xxxxxxxxxxxxxxxxxx"; char arr2[] = "hello world"; strcpy(arr1, arr2); printf("%s\n", arr1); return 0; }
我们直接从调试里面查看数组的值
在下面这段代码中
#include<stdio.h> #include<string.h> int main() { char arr1[] = "xxxxxxxxxxxxxxxxxx"; char arr2[] = "hello world"; strcpy(arr2, arr1); printf("%s\n", arr1); return 0; }
出现了错误,这是因为,arr2的空间不是足够大。
在下面这段代码中
#include<stdio.h> #include<string.h> int main() { char* p = "xxxxxxxxxxxxxxxxxx"; char arr2[] = "hello world"; strcpy(p, arr2); printf("%s\n", p); return 0; }
程序直接崩溃,这是因为char* p是不可以被修改的
(3)strcpy的模拟实现
#include<stdio.h> #include<assert.h> char* my_strcpy(char* dest, const char* src) { assert(dest && src); char* ret = dest; while (*dest++ = *src++) { ; } return ret; } int main() { char arr1[] = "xxxxxxxxxxxxx"; char arr2[] = "hello world"; char* p = my_strcpy(arr1, arr2); printf("%s\n", p); return 0; }
运行结果为
3.strcat
(1)strcat的库函数文档
1.它的参数是char* destination和const char* source,与strcpy是一样的。
2.它的功能是将source处的字符串追加到destination后面
3.它的返回类型是char*,返回destination的地址
(2)strcat的使用以及注意事项
1.源字符串必须以 '\0' 结束。
2.目标空间必须有足够的大,能容纳下源字符串的内容。
3.目标空间必须可修改。
4.字符串自己给自己追加,会陷入死循环
#include<stdio.h> #include<string.h> int main() { char arr[20] = "hello "; char* p = strcat(arr, "world"); printf("%s\n", arr); return 0; }
运行结果为
(3)strcat的模拟实现
思路就两步:
1.找到\0字符的位置
2.追加
#include<stdio.h> #include<assert.h> char* my_strcat(char* dest, const char* src) { assert(dest && src); char* ret = dest; //1.找到'\0'字符 while (*dest != '\0') { dest++; } //2.追加 while (*dest++ = *src++) { ; } return ret; } int main() { char arr[20] = "hello "; char* p = my_strcat(arr, "world"); printf("%s\n", arr); return 0; }
(4)strcat自己对自己追加
这个其实是不可以的,会造成死循环的现象
假如说下面的字符串自己对自己追加的话
\0会被修改为a,后面的都会覆盖过去,这样我们就永远也找不到\0了,最终导致分配的空间用完, 使用了未分配的空间而崩溃
下图是我们模拟出来的strcat的自己对自己追加后的效果
如果是官方的库里面的话,似乎没有出现这个问题,这个是visual studio对这个问题进行了优化,在一些其他的ide上可能就会出现这个死循环问题,导致程序出现bug