当前位置:网站首页 > R语言数据分析 > 正文

strncpy详解(strcopy_s)



函数原型

从标准输入读取字符 直到遇到换行字符或文件结束符
如果找到换行字符 则不将其复制到str中
在将字符复制到str后 会自动添加终止字符
请注意 gets与fgets完全不同:
gets不仅使用标准输入作为源 而且不将结束换行符的字符包含在生成的字符串中 也不允许指定str的最大大小(这可能导致缓冲区溢出)
在这里插入图片描述

简单来说gets就是读取一个字符串 包括空格也读取 遇到 或EOF就不读了
读到的内容给参数str
在这里插入图片描述
在这里插入图片描述

Example

在这里插入图片描述

函数原型

  • 参数2拷贝给参数2 包括第一个0
  • 第一个0也作为拷贝停止的标记
  • 参数1要足够大 以放得下参数2
  • 参数2一定要有结束标志0 否则会出bug
  • 返回的是参数1 也就是拷贝完之后的首字符地址
  • 参数1必须是可修改的字符串 不可以是常量字符串(不能被修改)

在这里插入图片描述

常量字符串无法被修改 这里的*p用const修饰是比较合理的
在这里插入图片描述

模拟实现


注意由于要返回destination 但是下面又改变了destination 所以需要暂存destination
擅于使用const(避免运行了才出错 直接编译不通过)

 


可以但没必要啊!
在这里插入图片描述



这种写法必须要注意 要单独拷贝一下’0’

 

官方源码

在这里插入图片描述

函数原型

  • 第一次0出现之前的字符个数 字符串的结束标志就是’0’
  • 返回值是因为字符串长度肯定不可能是负数
  • typedf unsigned int size_t

在这里插入图片描述

关于返回值size_与算术转换的一个易错点

  • (>=int) 就高不就低
    size_t减去size_t 得到的东西肯定也是size_t
  • -3被理解成unsigned int 反正肯定不可能<0 所以会进入if 打印hehe

在这里插入图片描述

模拟实现:递归

注意不要忘记写else的return 0
如果传参的时候写++ 那必须是++s s++会导致死递归
下面三种代码
在这里插入图片描述

模拟实现:指针-指针

指针-指针=指针之间的元素个数(希望求0和首字符之间的元素个数)
在这里插入图片描述

模拟实现:暴力

不是0就++
返回值应该是size_t或者unsigned int
count也最好定义成unsigned int 和返回值保持一致
在这里插入图片描述

官方源码

居然是我认为可读性较差的写法!
不过可能这个源码本来就不是给人读的
因为最后一次解引用发现是0 之后又++了一次
所以最终eos指向0下一个字符 返回的时候需要再-1
在这里插入图片描述

函数原型

● arr目标空间要足够大 确保能放得下追加的结果
● 目标字符串要有0 表示追加的起始位置
● 被追加的字符串也要有0 表示追加的停止位置
● 两者都要有0作为结束标志 因为两者都是字符串
● 目标字符串的0会被覆盖
在这里插入图片描述

注意自己给自己追加的bug

由于追加的时候 会把自己的/0给覆盖 就找不到追加结束的时机了
所以自己给自己追加的时候 不要用strcat函数
在这里插入图片描述

在这里插入图片描述

模拟实现


在这里插入图片描述

 


在这里插入图片描述

函数原型


在这里插入图片描述

返回值的含义

不关心字符串长度的
在这里插入图片描述

模拟实现


从首地址开始 一对一对字符作比较 相等就找下一对继续比较
但是注意::每次找下一对比较之前 必须看看上一对是不是0 == 0
如果已经比较到0 == 0 那就算字符串相等了 return 0即可
因为 0就是字符串结束标志
也许0后面还有字符 但是在strcmp眼里 字符串已经到头了 不关心后面的内容

 
 

上述函数的问题

strcat strcmp strcpy 都是一股脑找到0才停下
长度不受限制 其实是很不安全的
比如说strcpy
它并不关心能不能放得下 反正目标是拷贝到0
在这里插入图片描述

为了解决这些问题 引入了长度受限制的字符串函数: strncpy strncat strncmp
多了第三个参数 n 即需要操作的字符的个数
在这里插入图片描述

strncpy

如果够三个 那就拷贝abc 不会自己加0
如果不够 那就补0 缺几个补几个

在这里插入图片描述

在这里插入图片描述

strncat

字面常量"defqwer" 其实本质是d的地址 从起始地址开始 往后追加4个 然后再补一个0
因为追加完 肯定还是一个字符串 那就需要一个0
当然如果不够4个 那追加到0就停止了
从参数2往后n个字符的过程 遇到0 就提前终止
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

strncmp

比较arr1前四个和arr2前四个
即比较abcd和abcz
在这里插入图片描述

函数原型

可能有多个子串 但只返回第一个子串的首地址
找不到 返回NULL
在这里插入图片描述
在这里插入图片描述

模拟实现


比如ABBBBCD和BCD
首先str1 和 str2 记录当前判断字符串的起始位置
tmp1 和 tmp2 真正的进行判断 同时都会++ 一对一对比较
每次比较完得出结果 都会更新str2的值(其实就是++) 然后把新的str赋给tmp
str2不会变 str1会+1+1+1+1…直到strlen(tmp1) >= strlen(tmp2)
比较思路:
这就说明已经匹配成功
如果匹配失败 则需要让tmp2重回起点(即str2) 同时让tmp1指向str1的下一位
在这里插入图片描述

 

官方源码

思路:
cp在一个一个往后找(不用cp也行 可能是为了不改变形参的值 更规范)
然后cp找到的字符串和s2匹配
和我不同的是 它认为如果str2是空串 那直接返回str1的首地址 即空串是任何串的子串
这样理解确实更合理

下面匹配的思路跟我也有所不同
我认为调用strlen是节省开销 但是仔细一想好像不一定啊!
下图的思路就是如果*s1 == *s2 并且 s2还没有指向0 那么s1 s2就成对的往前走 继续比较下一个字符
如果有一天内存while结束了 有可能是:
1.*s2指向0了 那就说明上一对比较的s1 s2就是最后一对了 已经匹配成功
2.*s1 != *s2了 这种情况 就说明当前cp开始匹配的字符串就不是子串了 那就需要cp++继续下一对
3.外存循环的条件是cp没有指向0 如果有一天能出了外存循环 就说明一直到cp指向0 还没执行过return (cp) 那就不可能找到了 所以返回NULL
在这里插入图片描述

函数原型

sep参数是个字符串 定义了用作分隔符的字符集合
第一个参数指定一个字符串 它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记
strtok函数找到str中的下一个标记 并将其用 0 结尾 返回一个指向这个标记的指针:下图就会找到第一个. 然后改成0 并返回z的地址 这个时候用%s打印就是zcyxd
在这里插入图片描述


strtok函数会改变被操作的字符串 所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改
第一次调用传参没有传NULL:找到第一个分隔符 改为0 并记住了这个位置
第二次调用传参传的是NULL:记住了第一次0的位置 从下一个字符串开始再找分隔符 上图就是从0往后找 找到一个foxmail 然后把第二个.换成 同时返回f的地址 并记录这次0的位置
第2+n次调用传参传的都是NULL: 都会重复上述动作 直到找不到分隔符了 那就开始返回NULL

在这里插入图片描述
在这里插入图片描述

正确的打开方式

这个函数仿佛有记忆功能
所以猜测里面应该有一个static静态变量
要不然每次调用 函数栈帧都会销毁的

一开始就传参arr2 且只需要调用一次
之后每次都用NULL作为参数 调用一次打印一次 直到返回值是NULL
每次都会拿到一个子串的首地址
打印 或者是拷贝到别的地方 就看具体需求了在这里插入图片描述

函数原型


在这里插入图片描述
在这里插入图片描述

● 文件如果打开失败 fopen()会把错误码放到全局变量errno(errno.h) 里面去

● 返回NULL就说明打开失败了 strerror就能把错误码转换成错误信息 可以得知为什么打开失败了
在这里插入图片描述
这样写只知道打开失败了 但是 不知道为什么
在这里插入图片描述

perror更佳(stdio.h)

在这里插入图片描述

它会自己主动去捕获errno的错误码
perror的头文件是:stdio.h
strerror只是获得错误信息的起始地址 不会打印
perror拿到错误信息 会直接打印出错误信息
在这里插入图片描述

:如果他的参数符合下列条件就返回真(非0)

常用:
:十进制数字 0~9
:小写字母a~z
:大写字母A~Z
:字母a-z或A-Z
:字母或者数字 a-z或A-Z或0-9

了解:
:是不是十六进制数字 包括所有十进制数字,小写字母a-f,大写字母A-F
:标点符号 任何不属于数字或者字母的图形字符
:任何图形字符
:任何可打印字符 包括图形字符和空白字符
:任何控制字符
:任何控制字符

判断是不是小写 不是就返回0 否则是非0
在这里插入图片描述

 

可以看出 都是值传递
所以只会返回当前字母对应的大小写字母的码值
不会直接修改当前字母
在这里插入图片描述

函数原型


在这里插入图片描述

在这里插入图片描述
● 指针变量的一个优势
在这里插入图片描述

模拟实现

 


有一个注意点
这种写法是临时的强转 dest++的时候

在这里插入图片描述
在这里插入图片描述

这样才对 前置对 后置不对
在这里插入图片描述
在这里插入图片描述

自己给拷贝给自己的一个问题

● 这里实际上拷贝的是1 2 1 2 1

在这里插入图片描述

函数原型

memmove已经包含了memcpy的功能
但是他能实现重叠内存的拷贝

但是实际上:
C语言对memcpy的要求只有60分
但是 在VS里 VS对memcpy的实现有一百昏!
所以在VS里用memcpy 并不会出现3.1的问题
在这里插入图片描述

模拟实现

需要分情况讨论:

  1. 如果dest在src的左边 从src开始 按顺序从左往右拷贝给dest即可
    在这里插入图片描述
  2. 如果dest在src的右边 从src最右边的7开始 从dest最右边开始 从右往左把src的值拷贝给dest
    在这里插入图片描述
  3. 总结 其实右三种可能
    即dest在src的左边:前–>后
    dest在src之间:后–>前
    deest在src末尾的右边–>不重叠 无所谓

在这里插入图片描述
4. 注意要么dest和src都从右 要么都从左

 


如果是写给别人看的 比如考试 建议用for
如果只是实现一个函数给别人用 这个也好
在这里插入图片描述


在这里插入图片描述

一个字节一个字节比较(其实大小端的比较结果都是一样的) 当==的时候 继续往下比较
在这里插入图片描述

字节为单位 来设置内存中的数据

在这里插入图片描述
在这里插入图片描述

这是按照字节处理的 1写成俩16进制位就是01
但是数组元素每个都是4字节 是0对应的十进制
在这里插入图片描述
在这里插入图片描述

注意第二个参数是int char也属于整型家族
在这里插入图片描述

一般memset这么用 把每个字节都改成0
每个字节都变成0 相当于每个元素都是0在这里插入图片描述

到此这篇strncpy详解(strcopy_s)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • hippter官网下载(hipc官网下载)2024-12-28 16:36:04
  • strace工具(strace工具安装)2024-12-28 16:36:04
  • u raise me up什么意思(you raise me up是)2024-12-28 16:36:04
  • seaters(seaters 飞机)2024-12-28 16:36:04
  • 群晖 root(群晖 root用户能干什么)2024-12-28 16:36:04
  • .hprof文件可以删除吗(hprof文件占用太多内存)2024-12-28 16:36:04
  • gmscore官方下载(gmscore服务下载官网)2024-12-28 16:36:04
  • transformer复现(shiro复现)2024-12-28 16:36:04
  • hpl是什么文件(hprof是什么文件)2024-12-28 16:36:04
  • airplay是什么意思啊(airplay怎么投屏到电视上)2024-12-28 16:36:04
  • 全屏图片