C进阶-字符串+内存函数的介绍

1.字符与字符串类型的区别:

2.字符串的存储:

第一组:

第二组:

3.求字符串长度--strlen(string lenth):

①字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )

②参数指向的字符串必须要以 '\0' 结束

例一:

例二:

例三:

解释:

③#include<string.h>是strlen函数的库函数:

无库函数:

有库函数:

④注意函数的返回值为size_t,是无符号的( 易错 )整型

为什么会是这么个与预期相反的输出结果?

因为(无符号)3 - (无符号)6的输出结果是个非常大的整型数

修改一:强制类型转换

修改二:比大小

4.模拟实现strlen:

方法一:用计数器方法进行模拟:

方法二:使用函数递归不创建临时变量进行实现:

方法三:利用指针-指针得到的是中间元素个数来实现:

注:这种方法的思想就是找到'\0'的地址减去首元素的地址就是中间元素的个数即为字符串长度.

5.长度不受限制的字符串函数--strcpy

①将source的字符复制给destination

输出结果:

②源字符串必须以 '\0' 结束

输出结果:程序崩溃

修改一:

输出结果:

修改二:

输出结果:

③会将源字符串中的'\0'拷贝到目标空间

展示:

输出结果:

缺点:printf遇到'\0'就停止输出

④目标空间必须足够大,以确保能存放源字符串

输出结果:警告栈破坏(撑破),点击中止后输出正确的结果(表明strcpy确实将源字符串复制了过去,真是个愣头青)

注:这就是字符串长度不受限制

⑤目标空间必须可变

输出结果:程序崩溃

解释:

⑥模拟实现strcpy:

解释:

精简版:

6.长度不受限制的字符串函数--strcat

①将源字符串追加给目标空间,

输出结果:

②追加时从目标空间'\0'处开始覆盖,直到把源字符串的'\0'复制过去为止

覆盖前:

覆盖后:

③源字符串必须以 '\0' 结束

输出结果:

④目标字符串必须以'\0'结束:

输出结果:

⑤目标空间必须有足够的大,能容纳下源字符串的内容

⑥目标空间必须可修改

⑦模拟实现strcat:

输出结果:

⑧字符串自己给自己追加,如何?

输出结果:程序崩溃

解释:

注:把字符串的\0覆盖后就停不下来了,即进入死循环了

7.长度不受限制的字符串函数--strcmp:

①此函数不是比较字符串的长度,而是比较字符串中对应位置上的字符大小(ASCLL码值),如果相等就比较下一组,直到不同或者都遇到\0

.

标准规定:

第一个字符串大于第二个字符串,则返回大于0的数字

第一个字符串等于第二个字符串,则返回0

第一个字符串小于第二个字符串,则返回小于0的数字

注:VS中分别返回的是 1、0 、-1

输出结果:

③模拟实现strcmp:

8.长度受限制的字符串函数--strncpy

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

输出结果:

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

覆盖前:

覆盖后:

输出结果:

9.长度受限制的字符串函数--strncat

输出结果:

①复制时源字符串的\0会被复制过去,同时目标空间复制的起点是\0

覆盖前:

覆盖后:

10.长度受限制的字符串函数--strncmp

输出结果:

解释:

11.提一下容易与strcmp搞错的知识

①数组一 < 、> 、= 数组二 :比较两数组的地址

②"字符串1" >、<、= "字符串2" :比较两字符串首字母的地址

12.字符串查找--strstr

①返回一个在str1中指向与str2相同字符串的首元素地址,如果没有则返回NULL

输出结果:

②模拟实现strstr:

解释:

part 1:

part 2:

完整版:

part 1:

part 2:

part 3:

完整版:

13.字符串查找--strtok

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

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

③strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。

输出结果:

解释:

④(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)

字符串被改变举例演示:

输出结果:

临时拷贝举例演示:

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

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

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

输出结果:

解释:

对上面案例(\0充当结尾分隔符,以及返回NULL指针)再举一例说明:

原理:

⑧标准写法:

输出结果:

14.错误信息报告--strerror

errno:错误码,属于全局变量

注:我们打开网页时遇到404,网页打开失败。404就是一个错误码。

strerror函数的功能:返回错误码所对应的错误信息的起始位置

输出结果:

案例:

输出结果:

解释:

15.perror:

功能:

①把错误码转化为错误信息

②打印错误信息(包含了自定义的信息)

输出结果:

解释:

举例说明:

输出结果:

16.字符分类函数

注:

①字符分类函数包含于头文件ctype.h中

②字符分类函数内的内容为真时返回一个非0的随机整型数,为假时返回0

举isdigit为真例:

输出结果:

举isdigit为假例:

举islower为真例

输出结果:

17.字符转换函数:

举例:

输出结果:

18.内存操作函数--memcpy

①函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置

②这个函数在遇到 '\0' 的时候并不会停下来

③如果source和destination有任何的重叠,复制的结果都是未定义的

举例:

覆盖前:

覆盖后:

解释:

19.模拟实现memcpy:

原理:

那我想试试自我拷贝:

预期输出:1 2 1 2 3 4 5 6

实际输出:

解释:源空间和目标空间出现重叠

20.内存操作函数--memmove:

①和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的

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

输出结果:

21.模拟实现memmove:

解释:

①覆盖拷贝所在的问题:

此处,我们就要重点注意覆盖拷贝的问题,因为会导致未被拷贝的数值已招到更改。以图为例

②解决方法:

  • 重新开辟一个空间,便于原数据的储存。

  • 以不同的角度,以逆序拷贝or顺序拷贝以保证未进行拷贝的数据,保持原样

方法一:会有一个严重的问题,根本不知道需要开辟多大的空间(本人使用vs2019)。小了,会出现程序错误;大了,会导致空间浪费。所以在此看来,这样的不行的。

方法二:在针对不同的情形下,只要考虑完全,这就是很完美的选择,同时也不会浪费空间

src在dest之前:后—>前

我们可以发现自src下标小端拷贝,就不会出现之前的未进行拷贝就被更改的情况--逆顺序

dest在src之前:前—>后

我们可以发现自src下标大端拷贝,就不会出现之前的未进行拷贝就被更改的情况——顺顺序

22.内存操作函数--memcmp:

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

②返回值如下:

str1<str2 <0

str1=str2 =0

str1>str2 >0

用法:

通过输入字节数n,比较前后两个数组从首地址开始的n个字节

arr1在内存中的样子:

arr2在内存中的样子:

当比较16个字节时,相等

当比较17个字节时,

依然是相等

原因是:在第17个字节处刚好相等(这里是小端字节序)

当比较18个字节时

结果是-1

原因是在第18个字节处出现了不一样,arr2是33,arr1是00

23.内存设置函数--memset:

覆盖前:

覆盖后:

注:memset是以字节为单位来初始化内存的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值