• C语言进阶——字符函数和字符串函数(下)


    在前面我们已经学习了strlen、strcpy、strcat、strcmp几个库函数,今天我们继续学习剩余的库函数。

    上期链接:

    C语言进阶——字符函数和字符串函数(上)_wangjiushun的博客-CSDN博客

    目录:

    3、长度受限制的字符串函数

            strncpy

            strncat

            strncmp

    4、字符串查找

            strstr

            strtok

    5、错误信息报告

            strerror

    6、字符操作

    7、内存操作函数

            memcpy

            memmove

            memset

            memcmp


    三、长度受限制的函数字符串

    1、 strncpy

    函数原型:char* strncpy(char* destination, const char* source, size_t num);

    1、从源字符串拷贝num个字符到目标空间

    2、如果源字符串的长度大于num,则只拷贝num个字符,并不会在目标空间后追加‘\0’字符

    3、如果源字符串的长度小于num,则拷贝玩源字符串之后(包括‘\0’),在目标空间的后面追加‘\0’,直到num个。

    4、源指向的空间与目标空间不能重叠

    5、目标空间必须可变

    讲解:

    (1)strncpy函数的返回类型和参数是怎么设计的?

            strncpy与strcpy相似,只是多了一个参数size_t num,可以自己决定拷贝几个字符源字符串到目标空间中(在决定拷贝几个字符时,我们会考虑目标空间是否足够大),所以相对strcpy函数安全一些。

    (2)拷贝num个字符从源字符串到目标空间

            ①如果源字符串长度大于num,则只拷贝num个字符,并不会在目标后追加‘\0’

    代码实例:

    1. #include
    2. #include
    3. int main()
    4. {
    5. char arr1[20] = "################";
    6. char arr2[] = "abcdef";
    7. //把arr2中的以首字符开始的前3个字符拷贝到arr1中
    8. strncpy(arr1, arr2, 3);
    9. printf("%s\n", arr1);
    10. return 0;
    11. }

            F10调试之后,观察目标空间arr1的内存:

             ②如果源字符串的长度小于num,则拷贝玩源字符串之后(包括‘\0’),在目标空间的后面追加‘\0’,直到num个。

    代码实例:

    1. #include
    2. #include
    3. int main()
    4. {
    5. char arr1[20] = "################";
    6. char arr2[] = "abcdef";
    7. //把arr2中的以首字符开始的前10个字符拷贝到arr1中
    8. strncpy(arr1, arr2, 10);
    9. printf("%s\n", arr1);
    10. return 0;
    11. }

            F10调试之后,观察目标空间arr1的内存:

     (3)模拟实现strncpy

    分析:

            strncpy函数是从源字符串拷贝num个字符到目标空间的,模拟strncpy,那函数的返回类型、参数类型应该一致。

    函数体的实现:

            ①定义char* start变量存储目标空间的起始地址;

            ②将源字符串拷贝num个字符到目标空间:

                    a. 拷贝源字符串:num <= 源字符串

                    b. 判断num是否为0,不为0在目标后追加‘\0’

            ③返回目标空间的起始地址。

    代码演示:

    1. #include
    2. #include
    3. char* my_strncpy(char* dest, const char* src, size_t num)
    4. {
    5. //断言指针的有效性
    6. assert(dest && src);
    7. //存储目标空间的起始地址
    8. char* start = dest;
    9. //将源指向的字符串拷贝num个字符到目标空间
    10. //①num <= 源字符串,拷贝源字符串
    11. while (num)//注意num是无符号类型,写成后置--,易错,所以在后面单独成一条语句
    12. {
    13. if ((*dest++ = *src++) == '\0')
    14. {
    15. break;
    16. }
    17. --num;
    18. }
    19. //②num > 源字符串,在目标后面追加'\0',直至拷贝num个字符
    20. if (num)
    21. {
    22. while (--num)
    23. {
    24. *dest++ = '\0';
    25. }
    26. }
    27. //返回目标空间起始地址
    28. return start;
    29. }
    30. int main()
    31. {
    32. char arr1[10] = "#########";
    33. char arr2[] = "abcde";
    34. //从arr2中拷贝3个字符到arr1
    35. printf("%s\n", my_strncpy(arr1, arr2, 3));
    36. //从arr2中拷贝8个字符到arr1
    37. printf("%s\n", my_strncpy(arr1, arr2, 8));
    38. return 0;
    39. }

            积累:当类型为无符号类型,后置--且为循环条件循环两次是,易错!(后置--,先赋值再-1,可能减到负数,负数在无符号类型下是很大的正数)

    2、 strncat

    函数原型:char* strncat(char* destination, const char* source, size_t num);

    1、从源字符串的第一个字符开始拷贝num个字符到目标空间字符串的尾部,追加完后再外加一个‘\0’字符;(说明:①目标空间的‘\0’被源字符串的第一个字符覆盖②注意只拷贝源字符串‘\0’之前的字符,不拷贝‘\0’)

    2、注意:如果源字符串的长度小于num,则只拷贝‘\0’之前的内容;

    3、源指向的空间与目标空间不可以重叠;

    4、目标空间可变。

    讲解:

    (1)模拟strncat

    分析:

            strncat函数是从源指向的第一个字符开始拷贝num个字符到目标空间字符串的尾部,追加完后再外加终止‘\0’字符,模拟strncat,那函数的返回类型、参数类型应该一致。

    函数体的实现:

            ①定义char* start变量存储目标空间的起始地址;

            ②从源字符串开始拷贝num个字符到目标空间的尾部,追加完后在加终止‘\0’字符:

                    a. 找到目标空间的终止‘\0’字符

                    b. 追加num个字符到目标空间,当满足条件num > 源字符串长度时,则拷贝完源字符串(包括‘\0’)后,直接返回目标空间起始地址

                    c. num < 源字符串长度,追加完num个字符后,再外加终止‘\0’字符

                    d. 返回目标空间起始地址(num < 源字符串)

    代码演示:

    1. //模拟strncat
    2. #include
    3. #include
    4. char* my_strncat(char* dest, const char* src, size_t num)
    5. {
    6. //断言指针的有效性
    7. assert(dest && src);
    8. //存储目标空间的起始地址
    9. char* start = dest;
    10. //追加num个字符到目标空间
    11. //①找到目标空间的\0
    12. while (*dest)
    13. {
    14. dest++;
    15. }
    16. //②追加num个字符到目标空间
    17. while (num)
    18. {
    19. //如果num > 源字符串的长度,则拷贝到\0退出函数
    20. if ((*dest++ = *src++) == '\0')
    21. {
    22. return start;
    23. }
    24. num--;
    25. }
    26. //num < 源字符串长度,追加完后附加\0
    27. *dest = '\0';
    28. return start;
    29. }
    30. int main()
    31. {
    32. char arr1[10] = "######";
    33. char arr2[] = "abc";
    34. printf("%s\n", my_strncat(arr1, arr2, 2));
    35. return 0;
    36. }

    3、 strncmp

    函数原型:int strncmp(const char* str1, const char* str2, size_t num);

    1、比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完

    2、返回值与strncmp一样

    讲解:

    (1)模拟strncmp

    分析:

            strncmp函数是str1和str2比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完,模拟strncmp,那函数的返回类型、参数类型应该一致。

    函数体的实现:

            ①while循环比较num个对应字符:

                    a. 当满足情况——比较到不同字符,*str1 > *str2,返回1,*str1 < *str2,返回-1

                    b. 当满足情况——一个字符串结束(即相等),返回0

            ②比较完num个字符,均未出现不同字符,即相等,返回0

    1. #include
    2. #include
    3. int my_strncmp(const char* str1, const char* str2, size_t num)
    4. {
    5. //断言指针的有效性
    6. assert(str1 && str2);
    7. //比较num个对应字符的ASCII值
    8. while (num)
    9. {
    10. //①比较到不同的字符
    11. if (*str1 != *str2)
    12. {
    13. //如果str1 > str2,返回1,否则返回-1
    14. if (*str1 > *str2)
    15. {
    16. return 1;
    17. }
    18. else
    19. {
    20. return -1;
    21. }
    22. }
    23. //②一个字符串结束,返回0
    24. if (*str1 == '\0')
    25. {
    26. return 0;
    27. }
    28. str1++;
    29. str2++;
    30. --num;
    31. }
    32. //比较完num个字符,均相同,返回0
    33. return 0;
    34. }
    35. int main()
    36. {
    37. char arr1[] = "abcqw";
    38. char arr2[] = "abcaw";
    39. int ret = my_strncmp(arr1, arr2, 4);
    40. if (ret > 0)
    41. {
    42. printf("arr1 > arr2\n");
    43. }
    44. else if (ret == 0)
    45. {
    46. printf("arr1 = arr2\n");
    47. }
    48. else
    49. {
    50. printf("arr1 < arr2\n");
    51. }
    52. return 0;
    53. }

    四、字符串查找

    1、 strstr

    函数原型:char* strstr(const char* str1, const char* str2);

    1、strstr函数查找子字符串;

    2、在str1中找str2中第一次出现的位置,如果找到返回一个指针,指向str2在str1中第一次出现的位置;如果找不到(即str2不是str1的子集),就返回一个NULL指针。

    讲解:

    (1)代码演示:strstr

    1. #include
    2. #include
    3. int main()
    4. {
    5. char str[] = "This is a simple string";
    6. //接收strstr的返回值
    7. char* pch;
    8. //将str字符串中的simple子串修改为sample
    9. //①得到子串在str中第一次出现的位置
    10. pch = strstr(str, "simple");
    11. if (pch != NULL)
    12. {
    13. //②将sample拷贝到子串的位置
    14. strncpy(pch, "sample", 6);
    15. //输出修改后的str
    16. puts(str);
    17. }
    18. else
    19. {
    20. printf("str中子串不存在\n");
    21. }
    22. return 0;
    23. }

    (2)模拟strstr

    分析:

            strstr函数是查找字符串,判断str2是否为str1的子集,是则返回str1中str2第一次出现得我位置,否则返回NULL。

    函数体的实现:

            ①特殊情况:str为‘\0’是,直接返回str1(“特事特办”)

            ②遍历str1,当满足情况str2是str1的子集或str1结束:

                  a. cp指针用来遍历str1,给s1赋值;

                  b. c. s1指针用来每次判断该位置是否为str1中子集str2的位置,不是则str1遍历;

                   c.  s2指针用来遍历str2是否与s1相等,相等则返回s1的起始地址(即cp),不相等则重新回到str2的位置;

    代码演示:

    1. //模拟strstr
    2. /*
    3. 分析:strstr函数查找子字符串,判断str2是否为str1的子集。是则返回子字符串的位置,否则返回NULL
    4. */
    5. #include
    6. #include
    7. char* my_strstr(const char* str1, const char* str2)
    8. {
    9. assert(str1 && str2);
    10. //特殊情况:str2为'\0'时,直接返回str1
    11. if (*str2 == '\0')
    12. {
    13. return (char*)str1;
    14. }
    15. //s1用于从主字符串的第一个字符开始遍历主字符串是否包含子串,
    16. //遍历到不同于子串的字符,又从主字符串的第二个字符开始遍历;
    17. //直至遍历到包含,或遍历到主字符串的\0
    18. const char* s1 = NULL;
    19. //s2每一次新遍历时都会重新回到str2的位置
    20. const char* s2 = NULL;
    21. //存放子串可能的位置,从主字符串的首字符开始
    22. const char* cp = str1;
    23. while (*cp)
    24. {
    25. s1 = cp;
    26. s2 = str2;
    27. while (*s1 != '\0' && *s2 != '\0' && * s1 == *s2)
    28. {
    29. s1++;
    30. s2++;
    31. }
    32. if (*s2 == '\0')
    33. {
    34. return (char*)cp;
    35. }
    36. else if (*s1 == '\0')
    37. {
    38. return NULL;
    39. }
    40. cp++;
    41. }
    42. return NULL;
    43. }
    44. int main()
    45. {
    46. char arr1[] = "abbcdbba";
    47. char* ret = my_strstr(arr1, "bbbd");
    48. if (ret != NULL)
    49. {
    50. printf("%s\n", ret);
    51. }
    52. else
    53. {
    54. printf("没有找到\n");
    55. }
    56. return 0;
    57. }

    2、 strtok

    函数原型:char* strtok(char* str,const char* sep);

    1、sep参数是个字符串,定义了用作分隔符的字符集合;

    2、第一个参数指定一个字符串,它包含了0个或多个由sep字符串中一个或者多个分隔符分割的标记;

    3、strtok函数找到str中的下一个标记,并将其用‘\0’结尾,返回一个指向这个标记的指针(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。);

    4、strtok函数的第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置;

    5、strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记;

    6、如果字符串不存在更多的标记,则返回NULL指针。

    代码演示:

    代码1:

    1. #include
    2. #include
    3. int main()
    4. {
    5. char arr[] = "2809552931@qq.com";
    6. //分割邮箱
    7. //2809552931 qq com
    8. //分割符集合:@.
    9. char* sep = "@.";
    10. //注意:strtok函数会改变被操作的字符串,所以在使用strtok分割的字符串
    11. //一般都是临时拷贝的内容并且可修改。
    12. char arr1[20];
    13. strcpy(arr1, arr);
    14. //strtok函数找到arr中的标记,并将其用\0结尾,返回一个指向这个标记的指针
    15. //①strtok函数的第一个参数不为NULL,函数将找到arr1中第一个标记,
    16. //strtok函数将保存它在字符串中的位置
    17. char* ret = strtok(arr1, sep);
    18. printf("%s\n", ret);
    19. //②strtok函数的第一个参数为NULL,函数将在同一个字符串中
    20. //被保存的位置开始,开始查找下一个标记
    21. ret = strtok(NULL, sep);
    22. printf("%s\n", ret);
    23. //③如果字符串不存在更多的标记,则返回NULL指针
    24. ret = strtok(NULL, sep);
    25. printf("%s\n", ret);
    26. return 0;
    27. }

    代码2:

    1. #include
    2. #include
    3. int main()
    4. {
    5. char arr[] = "2809552931@qq.com";
    6. //分割邮箱
    7. //2809552931 qq com
    8. //分割符集合:@.
    9. char* sep = "@.";
    10. //注意:strtok函数会改变被操作的字符串,所以在使用strtok分割的字符串
    11. //一般都是临时拷贝的内容并且可修改。
    12. char arr1[20];
    13. strcpy(arr1, arr);
    14. char* ret = NULL;
    15. //strtok函数:除第一次调用,其余调用都是传null,这样才会继续向后寻找分隔符
    16. for (ret = strtok(arr1, sep); ret != NULL; ret = strtok(NULL, sep))
    17. {
    18. printf("%s\n", ret);
    19. }
    20. return 0;
    21. }

    五、错误信息报告

    1、strerror

    头文件:“string.h”

    函数原型:char* strerror(int errnum);

    1、返回错误码,所对应的错误信息

    2、注意:要配合printf才能打印出错误信息。

    讲解:

    (1)函数的返回类型和参数:

            返回类型:char* ——字符指针,指向错误码所对应的错误信息的字符串首字符地址

            参数:int ——错误码是一些整数

    (2)返回错误码,所对应的错误信息

            C语言的库函数在调用的时候,如果发生错误,就会将错误码存在一个变量中,这个变量是:errno(头文件:“errno.h”)。

            错误码是一些数字:0 1 2 3 4 5

            每一个错误码都对应一个错误信息。

    代码演示:

    1. #include
    2. #include
    3. int main()
    4. {
    5. printf("%s\n", strerror(0));
    6. printf("%s\n", strerror(1));
    7. printf("%s\n", strerror(2));
    8. printf("%s\n", strerror(3));
    9. printf("%s\n", strerror(4));
    10. printf("%s\n", strerror(5));
    11. return 0;
    12. }

            运行结果:

    (3)strerror的正确使用:

            当C语言的库函数调用时发生错误,会将错误码存放在(全局)变量errno中,使用strerror可以获得错误码所对应的错误信息的字符串首地址,配合printf将错误码打印出来。

     代码示例:如打开文件失败,想知道为什么打开失败

    1. #include
    2. #include
    3. #include
    4. int main()
    5. {
    6. //打开文件
    7. FILE* pf = fopen("test.txt", "r");
    8. if (pf == NULL)
    9. {
    10. printf("%s\n", strerror(errno));
    11. return 1;
    12. }
    13. //读文件
    14. //关闭文件
    15. fclose(pf);
    16. pf = NULL;
    17. return 0;
    18. }

             运行结果:

    2、perror

    头文件:“stdio.h”

    函数原型:void perror(const char* str);

    1、直接打印错误信息,在打印错误信息前,会先打印自定义的信息。

    2、可理解为:perror = printf + strerror

    讲解:

    (1)函数的返回类型和参数:

            返回类型:void —— 没有返回值

            参数:C字符串,包含要在错误信息本身之前打印的自定义信息。如果是NULL,则不会打印前面的自定义信息,但仍会打印错误信息。按照惯例,应用程序本身的名称通常用作参数。

    (2)代码演示:如打开文件失败,想知道为什么打开失败

    1. #include
    2. int main()
    3. {
    4. //打开文件
    5. //‘r’——打开方式:只读(如果该文件路径下,没有该文件则读取失败)
    6. FILE* pf = fopen("test.txt", "r");
    7. //如果文件打开失败,打印失败原因
    8. if (NULL == pf)
    9. {
    10. perror("fopen");
    11. return 1;
    12. }
    13. //读文件
    14. //关闭文件
    15. fclose(pf);
    16. pf = NULL;
    17. return 0;
    18. }

            运行结果:

    六、字符操作

    1、字符分类函数:(头文件:“ctype.h”)

    函数如果他的参数符合下列条件就返回真
    iscntrl任何控制字符
    isspace空白字符:空格‘ ’,换页‘f’,换行‘\n’,回车‘\r’,制表符‘\t’或者水平制表符‘\v’
    isdigit十进制数字0~9
    isxdigit十六进制,包括十进制数字,小写字母a~f,大写字母A~F
    islower小写字母a~z
    isupper大写字母A~Z
    isalpha字母a~z或A~Z
    isalnum字母或者数字,a~z & A~Z & 0~9
    ispunct标点符号,任何不属于数字或者字母的图形字符(可打印)
    isgraph任何图形字符
    isprint任何可打印字符,包括图形字符和空白字符

    代码演示:islower

    1. #include
    2. #include
    3. int main()
    4. {
    5. char ch = 0;
    6. //多组输入,判断输入值是否为小写字母
    7. while ((scanf("%c", &ch)) != EOF)
    8. {
    9. //islower函数判断它的参数是否为小写字母
    10. //是小写字母,为真返回非零的数字
    11. //不是小写字母,为假返回0
    12. printf("%d\n", islower(ch));
    13. //清空缓存区
    14. getchar();
    15. }
    16. return 0;
    17. }

            运行结果:

    2、字符转换

    头文件:ctype.h

    1、大写转小写

    int tolower(int c);

    2、小写转大写

    int toupper(int c);

    代码演示:

    代码1:

    1. #include
    2. #include
    3. int main()
    4. {
    5. //大写字母转小写字母
    6. printf("%c\n", tolower('A'));
    7. //小写字母转大写字母
    8. printf("%c\n", toupper('b'));
    9. return 0;
    10. }

            运行结果:

            代码2:将字符串中的小写字母转换为大写字母

    1. #include
    2. #include
    3. int main()
    4. {
    5. char arr[] = "I Have An Apple.";
    6. int i = 0;
    7. while (arr[i])
    8. {
    9. //如果为小写字母转换为大写字母
    10. if (islower(arr[i]))
    11. {
    12. arr[i] = toupper(arr[i]);
    13. }
    14. printf("%c", arr[i]);
    15. i++;
    16. }
    17. return 0;
    18. }

            运行结果:

    七、内存操作函数

            之前我们学习的库函数只能操作字符串函数,那我们要操作其他类型的数组该怎么办呢?

            答案是:内存操作函数。

    1、memcpy

    函数原型:void* memcpy(void* destination, const void* source, size_t num);

    1、函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存空间;

    2、这个函数在遇到‘\0’的时候并不会停下来;

    3、如果source和destination有任何的重叠,复制的结果都是未定义的。(在VS的平台上memcpy进行了优化与memmove一样,但是不保证所有平台都进行优化)

    讲解:

    (1)函数的返回类型和参数:

            返回类型:void* —— 指向目标空间的起始地址

            参数:①void* dest —— 不知道是指向什么类型地址

                       ②const char* src —— 不知道是指向什么类型地址,且源指向的内容不变

                        ③size_t num —— 拷贝的字节数

    (2)如果source和destination有任何的重叠,复制的结果都是未定义的。(在VS的平台上memcpy进行了优化与memmove一样,但是不保证所有平台都进行优化)

    1. #include
    2. #include
    3. int main()
    4. {
    5. int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
    6. //将arr1中的1,2,3,4,5拷贝到arr1+2中
    7. memcpy(arr1 + 2, arr1 , 20);
    8. int i = 0;
    9. for (i = 0; i < 10; i++)
    10. {
    11. printf("%d ", arr1[i]);
    12. }
    13. return 0;
    14. }

            图示:

            (3)模拟实现memcpy

    1. #include
    2. #include
    3. void* my_memcpy(void* dest, const void* src, size_t num)
    4. {
    5. //断言指针的有效性
    6. assert(dest && src);
    7. //存储目标空间的起始地址
    8. void* ret = dest;
    9. //从src指向的位置拷贝num个字节的数据到dest
    10. //void* 不能直接使用,必须转化为确定的类型才能使用
    11. while (num)
    12. {
    13. *(char*)dest = *(char*)src;
    14. dest = (char*)dest + 1;
    15. src = (char*)src + 1;
    16. --num;
    17. }
    18. return ret;
    19. }
    20. int main()
    21. {
    22. int arr1[10] = { 0 };
    23. int arr2[10] = { 1,2,3,4,5,6,7,8 };
    24. //将arr2中的3,4,5,6,7拷贝到arr1中
    25. my_memcpy(arr1, arr2+2, 20);
    26. //打印arr1
    27. int i = 0;
    28. for (i = 0; i < 10; i++)
    29. {
    30. printf("%d ", arr1[i]);
    31. }
    32. return 0;
    33. }

    2、memmove

    函数原型:void* memmove(void* destination, const void* source, size_t num);

    1、和memcpy的差别就是memmove函数处理的源内存块和目标空间内存块是可以重叠的;

    2、如果源空间和目标空间出现重叠,就得使用memmove函数处理。

    讲解:

    (1)模拟memmove

    分析:

            memmove函数是实现源指向的内容拷贝到目标空间,源空间和目标空间可以重叠。

    函数体实现:(如图)

            代码演示:

    1. #include
    2. #include
    3. void* my_memmove(void* dest, const void* src, size_t num)
    4. {
    5. //断言指针有效性
    6. assert(dest && src);
    7. //保存目标空间的起始地址
    8. void* ret = dest;
    9. //①如果目标空间起始地址 < 源内存起始地址
    10. if (dest < src)
    11. {
    12. //从前向后拷贝,前 ----- 后
    13. while (num--)
    14. {
    15. *(char*)dest = *(char*)src;
    16. dest = (char*)dest + 1;
    17. src = (char*)src + 1;
    18. }
    19. }
    20. //②如果目标空间起始地址 >= 源内存起始地址
    21. else
    22. {
    23. //从后向前拷贝,后 ----- 前
    24. while (num--)
    25. {
    26. *((char*)dest + num) = *((char*)src + num);
    27. }
    28. }
    29. return ret;
    30. }
    31. int main()
    32. {
    33. int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
    34. //将arr1中的1,2,3,4,5拷贝到arr1+2中
    35. my_memmove(arr1 + 2, arr1 , 20);
    36. int i = 0;
    37. for (i = 0; i < 10; i++)
    38. {
    39. printf("%d ", arr1[i]);
    40. }
    41. return 0;
    42. }

    3、memcmp

    函数原型:int memcmp(const void* ptr1,const void* ptr2,size_t num);

    ①比较从ptr1和ptr2指针开始的num个字节、

    ②标准规定:

            ptr1 > ptr2,返回正数

            ptr1 = ptr2,返回零

            ptr1 < ptr2,返回负数

    代码演示:

    1. #include
    2. #include
    3. int main()
    4. {
    5. int arr1[] = { 1,2,3 };
    6. //VS——小端存储:低位存放低地址
    7. //0x:01 00 00 00 02 00 00 00 03 00 00 00
    8. int arr2[] = { 1,2,5 };
    9. //0x:01 00 00 00 02 00 00 00 05 00 00 00
    10. //比较整形数组,从arr1和arr2开始的9个字节
    11. int ret = memcmp(arr1, arr2, 9);
    12. printf("%d\n", ret);
    13. return 0;
    14. }

            运行结果:

    4、memset

    函数原型:void* memset(void* ptr,int value,size_t num);

    1、以字节为单位来设置内存中的数据;

    2、填充内存块,将某一块内存中的内容全部设置为指定的值, 通常为新申请内存做初始化工作。

    讲解:

    (1)函数返回类型和参数:

            返回类型:void* ——返回ptr指向的地址

            参数:①void* ptr —— 指向要填充内存块的指针(因为不知道类型,所以设为空指针)

                       ②int value —— 要设置的值(为整形家族的值且要注意不要太大,因为是以字节为单位来填充内存的)

                       ③size_t num —— 去设置填充的字节数(因为不知道是什么类型)

    代码演示:

    代码1:可以使用memset把整形数组初始化为1吗

    1. #include
    2. #include
    3. int main()
    4. {
    5. int arr[5] = { 1,2,3,4,5 };
    6. memset(arr, 1, 20);
    7. int i = 0;
    8. for (i = 0; i < 5; i++)
    9. {
    10. printf("%d ", arr[i]);
    11. }
    12. printf("\n");
    13. return 0;
    14. }

            运行结果:

            我们发现结果和我们预期结果不同,因为memset函数是以字节为单位来设置内存中的数据的。

            我们F10调试起来,观察arr内存

      

            代码2:

    1. #include
    2. #include
    3. int main()
    4. {
    5. char arr[] = "hello world";
    6. //将arr中的world改为yyyyy
    7. memset(arr + 6, 'y', 5);
    8. printf("%s\n", arr);
    9. //将arr中的hello改为xxxxx
    10. memset(arr, 'x', 5);
    11. printf("%s\n", arr);
    12. return 0;
    13. }

            运行结果:

     字符串函数、内存函数就完结了,希望对大家有帮助。

  • 相关阅读:
    HarmonyOS实现几种常见图片点击效果
    IC设计流程中需要使用到的文件
    秋招应届毕业生求职 如何通过在线测评?
    微机----------------中断技术
    ROS2中如何从欧拉角转换成四元素
    LED智能家居灯 开关调光 台灯落地灯控制驱动 降压恒流IC AP5191
    Python datetime,try-except-else-finally
    C++ std::thread 线程创建和启动
    django认证重写,用户表使用新表,不用默认auth_user
    MemArts :高效解决存算分离架构中数据访问的组件
  • 原文地址:https://blog.csdn.net/wangjiushun/article/details/130781590