目录
接下来我们进入字符函数和字符串函数的讲解。中秋和国庆即将来临,终于要放假了回家了。
C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在 常量字符串 中或者 字符数组 中。 字符串常量 适用于那些对它不做修改的字符串函数.
我们重点讲解:字符串函数 字符函数 内存函数
关于下面的字符串函数我们将从:作用 头文件 参数 返回值 等方面去介绍。
printf打印字符串是打印\0之前的字符串。看到\0停止打印了
- #include
- int main()
- {
- char arr[10] = "abc\0def";
- printf("%s\n", arr);
- return 0;
- }
需要用到的头文件
- #include
- #include
- #include
- //断言和const修饰的指针在调试讲过
- #include
- #include
- int main()
- {
- char arr1[] = "abcdef";
- size_t ret =strlen(arr1);
- char arr2[] = "abc\0def";//统计的是\0之前的字符串长度
- size_t r = strlen(arr2);
- printf("arr1=%d,arr1=%d", ret, r);
- return 0;
- }
- #include
- #include
- int main()
- {
- char arr1[] = "abcdef";
- size_t ret =strlen(arr1);
- char* p = "abcdef";//这里p存储的就是字符串的首元素地址 起始地址
- size_t r = strlen(p);
- printf("ret=%d r=%d", ret, r);
- return 0;
- }
- #include
- #include
- int main()
- {
- // 3 6
- if (strlen("abc") - strlen("abcdef") > 0)//正数,3为无符号数是一个很大的数
- {
- printf(">\n");
- }
- else
- {
- printf("<\n");
- }
- return 0;
- }
-
- 3为无符号整数的时候
- //00000000 00000000 00000000 00000011 原码
- //为无符号为所以没有符号位,所以全部取反加1
- //11111111 11111111 11111111 11111101 补码
- 6
- //00000000 00000000 00000000 00000110 原码
- //11111111 11111111 11111111 11111010 补码
-
- //3>6
- #include
- size_t my_strlen(char* p)
- {
- int count = 0;
- while (*p)
- {
- count++;
- p++;
- }
- return count;
- }
- int main()
- {
- char arr[] = "abcdef";
- size_t ret = my_strlen(arr);
- printf("%zd\n", ret);
- return 0;
- }
-
-
- #include
- size_t my_strlen(const char* p)
- {
- if (*p == '\0')
- return 0;
- else
- {
- return 1 + my_strlen(p+1);//切记不要p++,++p这种副作用的++
- }
- }
- int main()
- {
- char arr[] = "abcdef";
- size_t ret = my_strlen(arr);
- printf("%zd", ret);
- return 0;
- }
- #include
- int my_strlen(char* p)
- {
- char* r = p;//起始地址
- while (*p != '\0')
- {
- p++;
- }
- return p - r;
- }
- int main()
- {
- char arr[] = "abcdef";
- int ret=my_strlen(arr);
- printf("%d", ret);
- return 0;
- }
下面我们介绍的是长度不受限制的字符串函数。
strcpy - C++ Reference (cplusplus.com)
- #include
- int main()
- {
- char arr1[20] = "xxxxxxxxxxxxx";
- printf("%s\n", arr1);
- char arr2[] = "abcdef";//会将\0拷贝过去,所以不会有xxxxx
- strcpy(arr1, arr2);
- printf("%s", arr1);
- return 0;
- }
- #include
- int main()
- {
- char arr1[1] = { 0 };//不够大
- char arr2[] = "abcdef";
- strcpy(arr1, arr2);
- printf("%s", arr1);
- return 0;
- }
-
- #include
- int main()
- {
- char arr1[1] = "hijklem";//常量字符串
- char arr2[] = "abcdef";
- strcpy(arr1, arr2);
- printf("%s", arr1);
- return 0;
- }
- //逻辑关系
- //
- {
- ;
- }
- //操作符的优先级
- //画图最重要
- //模拟实现strcpy
- #include
- #include
- char* my_strcpy( char*dest, const char* src)
- {
- char* ret = dest;//为了返回目标空间字符串的起始地址,需要先存储起来
- assert(dest && src);//断言
-
- while (*dest++ = *src++)//赋值和等于
- {
- ;
- }
- return ret;
- }
- int main()
- {
- char arr1[20] = {0};
- char arr2[] = "abcdef";
- my_strcpy(arr1, arr2);
- printf("%s\n", arr1);
- return 0;
- }
- //链式访问
- int main()
- {
- char arr1[20] = {0};
- char arr2[] = "abcdef";
- printf("%s\n", my_strcpy(arr1, arr2));//链式访问
- return 0;
- }
-
- //换种写法❌的没有将\0拷贝过去
- #include
- #include
- char* my_strcpy(char* dest, const char* src)
- {
- char* ret = dest;//为了返回目标空间字符串的起始地址,需要先存储起来
- assert(dest && src);//断言
-
- while (*src != '\0')
- {
- *dest = *src;//不是== 是赋值
- dest++;
- src++;
- }
- return ret;
- }
strcat - C++ Reference (cplusplus.com)
- #include
- #include
- int main()
- {
- char arr1[20] = "abc";
- char arr2[20] = "defg";
- strcat(arr1, arr2);
- printf("%s\n", arr1);
- return 0;
- }
- #include
- int main()
- {
- char arr1[20] = "abc";
- strcat(arr1, arr1);
- printf("%s\n", arr1);
- return 0;
- }
- #include
- char* my_strcat(char* str1, const char* str2)
- {
- char* ret = str1;
- while (*str1)
- {
- str1++;
- }
- while (*str2 != '\0')
- {
-
- *str1++ = *str2++;
- }
- return ret;
- }
-
- int main()
- {
- char arr1[20] = "abc";
- char arr2[20] = "defg";
- my_strcat(arr1, arr1);
- printf("%s\n", arr1);
- return 0;
- }
字符串自己追加自己这种方式。在不同编译器上,有的可以,有的不行。编译器的厂商不同,相同的库函数是由不同程序员实现的,所以库函数内部实现是不同的。最好不要这样写 。后面介绍strncat可以实现这种情况。
- //逻辑关系
- //
- {
- ;
- }
- //操作符的优先级
- //画图最重要
- #include
- #include
- #include
- char* my_strcat(char* str1, const char* str2)
- {
- assert(str1 && str2);//断言
- //strcat函数返回的是目标空间的起始地址
- char* ret = str1;
- //1,找到目标空间的末尾
- while (*str1 != '\0')
- // while (*str1++)❌?????????????
- //后置++ 先使用 再*
- {
- str1++;
- }
- //2。数据追加
- while (*str1++ = *str2++)
- //后置++的规则
- {
- ;
- }
- return ret;
- }
-
- int main()
- {
- char arr1[20] = "abc";
- char arr2[20] = "defg";
- my_strcat(arr1, arr2);
- printf("%s\n", arr1);
- return 0;
- }
strcmp - C++ Reference (cplusplus.com)
strcmp的返回值如下:
- #include
- #include
- int main()
- {
- char arr1[] = "abz";
- char arr2[] = "abq";
- if (strcmp(arr1, arr2) > 0)
- {
- printf(">\n");
- }
- else if(strcmp(arr1, arr2) < 0)
- {
- printf("<\n");
- }
- else
- {
- printf("=\n");
- }
- printf("%d", strcmp(arr1, arr2));//不同编译器下的值不同,但是都是以><=0的范围。
- return 0;
- }
- #include
- #include
- #include
- int my_strcmp( const char* p1, const char* p2)
- {
- assert(p1 && p2);
- while (*p1 == *p2)
- {
- if (*p1 == '\0')
- return 0;
- p1++;
- p2++;
- }
- //!=
- if (*p1 > *p2)
- return 1;
- else
- return -1;
- }
- int main()
- {
- char arr1[] = "abz";
- char arr2[] = "abq";
- if (my_strcmp(arr1, arr2) > 0)
- {
- printf(">\n");
- }
- else if (my_strcmp(arr1, arr2) < 0)
- {
- printf("<\n");
- }
- else
- {
- printf("=\n");
- }
- printf("%d", my_strcmp(arr1, arr2));//不同编译器下的值不同,但是都是以><=0的范围。
- return 0;
- }
- //或者
- #include
- #include
- #include
- int my_strcmp( const char* p1, const char* p2)
- {
- assert(p1 && p2);
- while (*p1 == *p2)
- {
- if (*p1 == '\0')
- return 0;
- p1++;
- p2++;
- }
- //!=
- return *p1 - *p2;
- }
- int main()
- {
- char arr1[] = "abz";
- char arr2[] = "abq";
- if (my_strcmp(arr1, arr2) > 0)
- {
- printf(">\n");
- }
- else if (my_strcmp(arr1, arr2) < 0)
- {
- printf("<\n");
- }
- else
- {
- printf("=\n");
- }
- printf("%d", my_strcmp(arr1, arr2));//不同编译器下的值不同,但是都是以><=0的范围。
- return 0;
- }
- int my_strcmp(char* p1, char* p2)
- {
- while (*p1 == *p2)
- {
- if (*p1 == '\0')
- return 0;
- p1++;
- p2++;
- }
- //!=
- return (*p1-*p2);
- }
接下来,我们介绍的是在上面函数的基础上,长度受限制的字符串函数
关于上面的解释过的点,我们将不在介绍,下面我们重点介绍受限制n的差别,和注意点
对比上面长度不受限制的字符串函数,我们发现多了一个size_t num的参数 ,相对安全一些
strncpy - C++ Reference (cplusplus.com)
- #include
- int main()
- {
- char arr1[20] = "xxxxxxxxxxxxxx";
- char arr2[] = "abcdef";
- strncpy(arr1, arr2,3);
- printf("%s", arr1);
- return 0;
- }
那请问是否将'\0'拷贝过去了呢?答案是:没有哦
- #include
- int main()
- {
- char arr1[20] = "xxxxxxxxxxxxxx";
- char arr2[] = "abcdef";
- strncpy(arr1, arr2,3);
- printf("%s\n", arr1);
- strcpy(arr1, arr2);
- printf("%s", arr1);
- return 0;
- }
-
- 对比一下:就只知道'\0'有没有拷贝过去
- #include
- int main()
- {
- char arr1[20] = "xxxxxxxxxxxxx";
- printf("%s\n", arr1);
- char arr2[] = "abcdef";//会将\0拷贝过去,所以不会有xxxxx
- strcpy(arr1, arr2);
- printf("%s", arr1);
- return 0;
- }
调式过后,我们可以发现,当我们num是几,我们就拷贝几个字符过去,并不会将'\0'拷贝
那当我们的num超过了被拷贝的字符串的字符个数,会发生什么呢?
- #include
- int main()
- {
- char arr1[20] = "xxxxxxxxxxxxxx";
- char arr2[] = "abc";
- strncpy(arr1, arr2, 6);
- printf("%s\n", arr1);
- return 0;
- }
当我们调试发现,即便我们没有num超出了被拷贝字符串的字符个数。但是strnpy仍然会达到num的个数。那就是用'\0'去填补缺少的num的个数,必须满足num的字符个数拷贝过去方可。
strncat - C++ Reference (cplusplus.com)
- #include
- int main()
- {
- char arr1[20] = "abc";
- char arr2[] = "defghi";
- strncat(arr1, arr2, 3);
- printf("%s\n", arr1);
- return 0;
- }
那我们的strncat函数是否追加字符串的同时将'\0'追加过去呢?答案是:有。
- #include
- int main()
- {
- char arr1[20] = "abc\0xxxxxxxxxx";
- char arr2[] = "defghi";
- strncat(arr1, arr2, 3);
- printf("%s\n", arr1);
- return 0;
- }
- //如果追加了'\0',那么打印abcdef
- //如果没有追加'\0',那么打印abcdefxxxxxxx
经过调试,我们发现在将源字符串追加到目的地空间字符串的后面时,我们把num的字符追加过去之后,同时会将'\0'追加过去。
那当我们的num超过了被追加的字符串的字符个数,会发生什么呢?
- #include
- int main()
- {
- char arr1[20] = "abc\0xxxxxxxxxx";
- char arr2[] = "defghi";
- strncat(arr1, arr2, 10);
- printf("%s\n", arr1);
- return 0;
- }
当我们调试发现,当num超过源字符串里的元素个数,strncat的源字符串有多少字符元素就追加多少字符元素,并不会用'\0'去弥补空缺。
strcmp - C++ Reference (cplusplus.com)
- #include
- #include
- int main()
- {
- char arr1[] = "abczef";
- char arr2[] = "abcqw";
- int ret = strncmp(arr1, arr2, 4);
- printf("%s\n", ret);
- return 0;
- }
- #include
- #include
- int main()
- {
- char arr1[] = "abcdef";
- char arr2[] = "abcqw";
- int ret = strncmp(arr1, arr2, 4);
- printf("%s\n", ret);
- return 0;
- }
- #include
- int main()
- {
- char arr1[] = "abcdef";
- char arr2[] = "abcdef";
- int ret = strncmp(arr1, arr2, 3);
- printf("%s\n", ret);
- return 0;
- }
这里留下几个任务就是动动小手我们写一写在原来的基础上模拟实现strnpy strncat strncmp,下篇博文讲。🙂🙂🙂🙂🙂
✔✔✔✔✔最后,感谢大家的阅读,若有错误和不足,欢迎指正!下篇博文我们继续字符函数。🆗
当然今天有很开心的事情就是,以为我不能考英语四级了,结果候补有位置了,真的很开心!当然也提醒大家抢四级报名不要慌,也不要一直刷新和操作,这样会和我一样强制下线的┭┮﹏┭┮
代码------→【gitee:唐棣棣 (TSQXG) - Gitee.com】
联系------→【邮箱:2784139418@qq.com】