本章也是一个较多较难的部分,本章主要介绍
目录

库函数 strlen的作用就是计算某个字符串的大小。之前在操作符sizeof那一结就看到过strlen,之前就有稍稍做过一些简介。
从这个函数结构看,它返回的是一个size_t 类型的值,这里解释一下size_t。
size_t
size_t 是一些C/C++标准在stddef.h中定义的,size_t 类型表示C中任何对象所能达到的最大长度,它是无符号整数。
那么我们可以来尝试模拟实现一下strlen。上代码
- #include <stdio.h>
- #include <assert.h>
- size_t my_strlen(const char* str)
- {
- assert(str);//对传进的数组进行断言,确保str不为'\0 '
- const char* start = str;
- const char* end = str;
- while (*end != '\0')
- {
- end++;
- }
- return end - start;
- }
- int main()
- {
- char arr[] = "hello bit";
- printf("%d", my_strlen(arr));
- return 0;
- }
介绍一下assert:断言

如果具有函数形式的此宏的参数表达式比较等于零(即表达式为 false),则会将消息写入标准错误设备并调用,从而终止程序执行。
介绍一下const:
我们之前最开始就见过这个玩意,在常量与变量那一章节的时候。被const修饰过的变量,就无法修改了。
常量指针有两种定义:
- const int * p = 20;
- int * const p =20;
第一种定义:const在 * 的左边,表示指针指向的内容,不可以通过指针来改变,但指针本身是可以发生改变的,可以通过一个其他的来改变。
第二种定义:const在 * 的右边,表示,这里修饰的指针变量p,表示指针变量不能被改变,但是之指针所指向的内容是可以发生改变的。
我们这里不希望改变指针str的值,所以对它用const修饰。

将源指向的 C 字符串复制到目标所指向的数组中,包括终止 null 字符(并在该点停止)。
我们也对strcpy进行模拟实现
- #include <stdio.h>
- #include <assert.h>
- char* my_strcpy(char* dest, const char* src)
- {
- assert(dest);//对dest断言防止出现sdest为'\0'的情况
- assert(src);//对src断言防止出现src为'\0'的情况
- char* ret = dest;
- while (*dest++ = *src++)//每次循环将src赋给dest并且同时向后移动指针
- {
- ;//当src为\0时循环结束
- }
- return ret;
- }
-
- int main()
- {
- char arr1[20] = "abc";
- char arr2[] = "hello bit";
- printf("%s\n", my_strcpy(arr1, arr2));
- return 0;
- }

我们在对strcpy进行模拟实现或者是使用都必须注意几点
1.源字符串必须以 '\0' 结束。2.会将源字符串中的 '\0' 拷贝到目标空间。3.目标空间必须足够大,以确保能存放源字符串。4.目标空间必须可变
否则就会发生各种各样的错误。

将源字符串的副本追加到目标字符串。目标中的终止空字符被源的第一个字符覆盖,并且空字符包含在由目标中两者的串联组成的新字符串的末尾。
注意事项:
源字符串必须以 '\0' 结束。目标空间必须有足够的大,能容纳下源字符串的内容。目标空间必须可修改。
模拟实现:
- #include <stdio.h>
- char* my_strcat(char* str1,const char* str2)
- {
- char* ret = str1;//保存ch1的首元素地址
- while (*str1 != '\0')
- {
- str1++;
- }//表示找到了str1也就是ch1的结尾处
- while (*str1++ = *str2++)//追加
- {
- ;
- }
- return ret;
- }
- int main()
- {
- char ch1[20] = "hello ";
- char ch2[] = "world";
- printf("%s", my_strcat(ch1, ch2));
- return 0;
- }
看看结果:

那我们是否可以自己给自己追加呢?
假设ch1 为 " hello " 根据上面代码的思路,我们先找到自己的 ' \0 ' 处,然后将 ‘ h ’ 给到 ' \0 ' ,当这一步进行以后,我们原来的ch1就不再是 " hello " 而是 " helloh "。那我们一直往后追加,就永远追不到结尾' \0 '。直到程序奔溃。
所以我们不可以用strcat给自己追加自己。

对两个字符串的比较。
标准规定:
第一个字符串大于第二个字符串,则返回大于 0 的数字第一个字符串等于第二个字符串,则返回 0第一个字符串小于第二个字符串,则返回小于 0 的数字
- #include <stdio.h>
- #include <assert.h>
- int my_strcmp(const char* str1, const char* str2)
- {
- assert(str1 && str2);//断言
- while (*str1 == *str2)//判断str1 和 str2 每个对于的字符是否相等
- {
- if (*str1 == '\0')//这是在str1 和str2 相等的条件下进行的,当str1 ='\0'时,str2 ='\0'
- {
- return 0;
- }
- str1++;
- str2++;
- }
- return *str1 - *str2;//返回两个差值
- }
- int main()
- {
- char ch1[] = "abc";
- char ch2[] = "abc";
- int key = my_strcmp(ch1, ch2);
- if (key > 0)
- {
- printf("ch1 > ch2\n");
- }
- else if (key < 0)
- {
- printf("ch1 < ch2\n");
- }
- else
- {
- printf("ch1 == ch2\n");
- }
- return 0;
- }

拷贝 num 个字符从源字符串到目标空间。如果源字符串的长度小于 num ,则拷贝完源字符串之后,在目标的后边追加 0 ,直到 num 个。
上代码:
- #include <stdio.h>
- int main()
- {
- char str1[20] = "abcd";
- char str2[]="***";
- strncpy(str1, str2, 2);
- printf("%s\n",str1);
- return 0;
- }

但是需要注意:拷贝的大小尽量不要大于源字符串的大小,我们把上面的2改为8试试。

我们默认添加 ' \0 '虽然对我们的目标影响不大,但是还是得尽量避免。

将源的前 num 个字符追加到目标,外加一个终止空字符。
如果源中 C 字符串的长度小于 num,则仅复制到终止空字符之前的内容。
上代码:
- #include <stdio.h>
- int main()
- {
- char str1[20] = "abcd\0hijkln";//为了区别追加字符串末尾的 '\0'是从str2中获取的还是本身自带的
- char str2[] = "***";
- strncat(str1, str2, 2);
- printf("%s\n", str1);
- return 0;
- }

根据结果可以看见,原来的 ' h ' 被 ' \0 ' 替换了 。
我们之前用strcat自己给自己追加行不通,但是我们可以用strncat来完成,确定要追加多少个字符。


将 C 字符串 str1 的最多数字字符与 C 字符串 str2 的字符进行比较。
此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续执行以下对操作,直到字符不同,直到达到终止空字符,或者直到两个字符串中的数字字符匹配,以先发生者为准。
它的返回值与strcmp一样。
看代码
- #include
- int main()
- {
- int ret = strncmp("abcdef","abc",2);
- printf("%d", ret);
- return 0;
- }

我们把它改为比较前四个试试:

我们这一章先介绍这几个字符串函数,下一章主要讲讲内存函数等等。