• 字符函数和字符串函数


    本章也是一个较多较难的部分,本章主要介绍中多种常用地库函数。

    目录

    0. 前言

    1.无限制长度的库函数类型

    1.1 strlen

    1.2 strcpy

    1.3 strcat

    1.4 strcmp

     2.限制长度的库函数类型

    2.1 strncpy

     2.2 strcat

    2.3 strncmp


    0. 前言

    C 语言中对字符和字符串的处理很是频繁,但是 C 语言本身是没有字符串类型的,字符串通常放在
    常量字符串 中或者 字符数组 中。
    字符串常量 适用于那些对它不做修改的字符串函数。

    1.无限制长度的库函数类型

    1.1 strlen

     库函数 strlen的作用就是计算某个字符串的大小。之前在操作符sizeof那一结就看到过strlen,之前就有稍稍做过一些简介。

    从这个函数结构看,它返回的是一个size_t 类型的值,这里解释一下size_t。

    size_t

    size_t 是一些C/C++标准在stddef.h中定义的,size_t 类型表示C中任何对象所能达到的最大长度,它是无符号整数。

    那么我们可以来尝试模拟实现一下strlen。上代码

    1. #include <stdio.h>
    2. #include <assert.h>
    3. size_t my_strlen(const char* str)
    4. {
    5. assert(str);//对传进的数组进行断言,确保str不为'\0 '
    6. const char* start = str;
    7. const char* end = str;
    8. while (*end != '\0')
    9. {
    10. end++;
    11. }
    12. return end - start;
    13. }
    14. int main()
    15. {
    16. char arr[] = "hello bit";
    17. printf("%d", my_strlen(arr));
    18. return 0;
    19. }

    介绍一下assert:断言

    如果具有函数形式的此宏的参数表达式比较等于零(即表达式为 false),则会将消息写入标准错误设备并调用,从而终止程序执行。

    介绍一下const:

    我们之前最开始就见过这个玩意,在常量与变量那一章节的时候。被const修饰过的变量,就无法修改了。

    常量指针有两种定义:

    1. const int * p = 20;
    2. int * const p =20;

    第一种定义:const在 * 的左边,表示指针指向的内容,不可以通过指针来改变,但指针本身是可以发生改变的,可以通过一个其他的来改变。

    第二种定义:const在 * 的右边,表示,这里修饰的指针变量p,表示指针变量不能被改变,但是之指针所指向的内容是可以发生改变的。

    我们这里不希望改变指针str的值,所以对它用const修饰。

    1.2 strcpy

    指向的 C 字符串复制到目标所指向的数组中,包括终止 null 字符(并在该点停止)。

    我们也对strcpy进行模拟实现

    1. #include <stdio.h>
    2. #include <assert.h>
    3. char* my_strcpy(char* dest, const char* src)
    4. {
    5. assert(dest);//对dest断言防止出现sdest为'\0'的情况
    6. assert(src);//对src断言防止出现src为'\0'的情况
    7. char* ret = dest;
    8. while (*dest++ = *src++)//每次循环将src赋给dest并且同时向后移动指针
    9. {
    10. ;//当src为\0时循环结束
    11. }
    12. return ret;
    13. }
    14. int main()
    15. {
    16. char arr1[20] = "abc";
    17. char arr2[] = "hello bit";
    18. printf("%s\n", my_strcpy(arr1, arr2));
    19. return 0;
    20. }

     

    我们在对strcpy进行模拟实现或者是使用都必须注意几点

    1.源字符串必须以 '\0' 结束。
    2.会将源字符串中的 '\0' 拷贝到目标空间。
    3.目标空间必须足够大,以确保能存放源字符串。
    4.目标空间必须可变

    否则就会发生各种各样的错误。

    1.3 strcat

    字符串的副本追加到目标字符串。目标中的终止空字符被的第一个字符覆盖,并且空字符包含在由目标中两者的串联组成的新字符串的末尾。

    注意事项:

    源字符串必须以 '\0' 结束。
    目标空间必须有足够的大,能容纳下源字符串的内容。
    目标空间必须可修改。

    模拟实现:

    1. #include <stdio.h>
    2. char* my_strcat(char* str1,const char* str2)
    3. {
    4. char* ret = str1;//保存ch1的首元素地址
    5. while (*str1 != '\0')
    6. {
    7. str1++;
    8. }//表示找到了str1也就是ch1的结尾处
    9. while (*str1++ = *str2++)//追加
    10. {
    11. ;
    12. }
    13. return ret;
    14. }
    15. int main()
    16. {
    17. char ch1[20] = "hello ";
    18. char ch2[] = "world";
    19. printf("%s", my_strcat(ch1, ch2));
    20. return 0;
    21. }

    看看结果:

    那我们是否可以自己给自己追加呢?

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

    所以我们不可以用strcat给自己追加自己。

    1.4 strcmp

     对两个字符串的比较。

    标准规定:

    第一个字符串大于第二个字符串,则返回大于 0 的数字
    第一个字符串等于第二个字符串,则返回 0
    第一个字符串小于第二个字符串,则返回小于 0 的数字
    1. #include <stdio.h>
    2. #include <assert.h>
    3. int my_strcmp(const char* str1, const char* str2)
    4. {
    5. assert(str1 && str2);//断言
    6. while (*str1 == *str2)//判断str1 和 str2 每个对于的字符是否相等
    7. {
    8. if (*str1 == '\0')//这是在str1 和str2 相等的条件下进行的,当str1 ='\0'时,str2 ='\0'
    9. {
    10. return 0;
    11. }
    12. str1++;
    13. str2++;
    14. }
    15. return *str1 - *str2;//返回两个差值
    16. }
    17. int main()
    18. {
    19. char ch1[] = "abc";
    20. char ch2[] = "abc";
    21. int key = my_strcmp(ch1, ch2);
    22. if (key > 0)
    23. {
    24. printf("ch1 > ch2\n");
    25. }
    26. else if (key < 0)
    27. {
    28. printf("ch1 < ch2\n");
    29. }
    30. else
    31. {
    32. printf("ch1 == ch2\n");
    33. }
    34. return 0;
    35. }

     2.限制长度的库函数类型

    2.1 strncpy

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

    上代码:

    1. #include <stdio.h>
    2. int main()
    3. {
    4. char str1[20] = "abcd";
    5. char str2[]="***";
    6. strncpy(str1, str2, 2);
    7. printf("%s\n",str1);
    8. return 0;
    9. }

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

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

     2.2 strcat

    的前 num 个字符追加到目标,外加一个终止空字符。
    如果中 C 字符串的长度小于 num,则仅复制到终止空字符之前的内容。

    上代码:

    1. #include <stdio.h>
    2. int main()
    3. {
    4. char str1[20] = "abcd\0hijkln";//为了区别追加字符串末尾的 '\0'是从str2中获取的还是本身自带的
    5. char str2[] = "***";
    6. strncat(str1, str2, 2);
    7. printf("%s\n", str1);
    8. return 0;
    9. }

    根据结果可以看见,原来的 ' h ' 被 ' \0 ' 替换了 。

    我们之前用strcat自己给自己追加行不通,但是我们可以用strncat来完成,确定要追加多少个字符。

    2.3 strncmp

    将 C 字符串 str1 的最多数字字符与 C 字符串 str2 的字符进行比较。
    此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续执行以下对操作,直到字符不同,直到达到终止空字符,或者直到两个字符串中的数字字符匹配,以先发生者为准。

     它的返回值与strcmp一样。

    看代码

    1. #include
    2. int main()
    3. {
    4. int ret = strncmp("abcdef","abc",2);
    5. printf("%d", ret);
    6. return 0;
    7. }

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

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

  • 相关阅读:
    【Mysql】Mysql内置函数介绍
    376. 机器任务
    python基础篇(4):range语句
    1.4 Apache Hadoop完全分布式集群搭建-hadoop-最全最完整的保姆级的java大数据学习资料
    C#流程控制————分支结构
    【码蹄集新手村 600 题】判断一个公元后的年份是否为闰年的方法
    LLVM系列第二十九章:写一个简单的常量加法“消除”工具(Pass)
    java小项目01:回文数的判断+剪刀石头布
    TiDB 6.0 Placement Rules In SQL 使用实践
    vue-自适应布局-postcss-pxtorem
  • 原文地址:https://blog.csdn.net/weixin_67807492/article/details/126838681