目录
前言
第三栏复习--字符串追加函数。本篇博客也是先讲解strcat后谈strncat
用法简介
1、简介
char* strcat(char* dest, const char* scr);
dest 为要被追加某些字符的字符串的地址
scr 为某些字符的地址,这个某些字符必须是字符串形式,也就是无论你要追加一个字符还是一堆字符都需要创建为字符串形式,而之所以这样做的关键,我认为应该就是\0这个结束标志。
返回值为 dest 的地址或者说它首字符的地址。
scr所指向的空间存放的字符串追加到dest上即放在dest后面。
为了方便,就叫追加一个字符串了,不管它除了\0还有几个字符。
上个栗子
小注意
i)dest所指向的空间一定要足够大,可以容纳追加一个字符串后的新字符串。
ii)src所指向的空间必须是存放字符串形式即存在\0,要不然就容易越界访问。
iii)在追加字符时,是在原字符串的\0处追加即在\0处放追加的第一个字符,并且最后会将\0也追加上去,其实也就相当于两个字符串的拼接,拼接之后还得是一个字符串呀。
iv)其实strcat还是要依靠\0去寻找字符串的首尾位置,以此来进行追加和停止的操作。
简单实现
简单实现
少罗嗦,上代码。
#include<assert.h>
#include<stdio.h>
char* my_strcat(char* dest,const char* scr)
{
assert(dest);//断言
assert(scr);
if (!*scr)//对scr的判断,如果其为空字符串那就没有追加的必要了
{
return dest;
}
char* ret = dest;//能够来到这里就说说明有追加的必要,
//先将dest的地址拷贝一份,接下来的操作肯定会更改dest的。
while (*(++dest))//先找到dest的字符串的\0的位置。
;
while (*dest++ = *scr++)//从\0处开始追加。
;
return ret;
}
来两个例图:
scr为空的情况:
库中的实现
感觉我的更健壮一些(狗头保命),咱不是大佬,没有那自信啊。
strncat
用法简介
多了个n就说明功能肯定会更加强大了一些。
char* strncat(char * dest, char* scr,size_t num)
其他都是一样的,就是差在了这个num上
这个num就是用来限定追加的字符个数,即规定只能追加scr中从的的第一个开始后的共n个字符(算上第一个)
来个梨子
注意点
1)大体功能与strcat一样,但是多了个n限制个数,不必再依靠\0了。
例子:
2)但是当n一不小心大于scr中的字符串的字符的个数即长度是,它不会像strncpy一样补\0,而是将scr中的字符串都追加过去就完事了。
例子
这两张图就可以看出,strncpy是用\0来补充不够的字符,而strncat不管那个,n过大时他就只管把scr中的字符全追加过去,并不会用\0来充数。
简单实现
char* my_strncat(char* dest, char* scr, size_t num)
{
assert(dest);//断言
assert(scr);
if (!*scr)//对scr的判断,如果其为空字符串那就没有追加的必要了
{
return dest;
}
char* ret = dest;//能够来到这里就说说明有追加的必要,
//先将dest的地址拷贝一份,接下来的操作肯定会更改dest的。
while (*(++dest))//先找到dest的字符串的\0的位置。
;
while (num--)//从\0处开始追加,追加num次,直至num变为0。
if (!(*dest++ = *scr++))//但是当src已经达\0时也就不用再追加了。
return ret;
return ret;
}
图例
库中的实现
strnlen的代码实现纠正
简单思路
那个实现的有些问题,不能补\0,还容易越界访问。
来个改良版的
//拷贝分两种情况(字符的数目不算上\0)
//1)scr中的字符数目大于等于 num,那就正常按个数num拷贝,再补一个\0
//2)scr中的字符数目小于num,先将将scr中的字符都拷过去,之后再补num - strlen(scr)个\0
while版
char* my_strncpy(char* dest, const char* scr, size_t num)
{
assert(dest);//断言
assert(scr);
if (!*scr)//判断是否为空字符串
{
return dest;
}
char* ret = dest; //拷贝dest中的地址,下面的操作会改变dest 的值
while(num--)//拷贝的主体循环
{
if ((*dest++ = *scr++) == '\0')//1)时就很正常了,慢慢拷贝,直至循环结束,进入下面的else语句
{ //2)当i未能自增到num时scr已经没字符了,那就只好跳出拷贝循环了,进入if语句,
//但是重点是此时的dest指向的位置,已经是跟scr中的\0相对应的位置,可以拿个例子带一下。
break;
}
}
if (i < num)
{
while(num--)//在跳出循环时,dest已经来到当时的i对应的下一个位置
{
*dest++ = '\0';
}
}
else
{
*dest = '\0';//末尾补一个\0
}
return ret;
}
for版
char* my_strncpy(char* dest, const char* scr,size_t num)
{
assert(dest);//断言
assert(scr);
if (!*scr)//判断是否为空字符串
{
return dest;
}
unsigned int i = 0;//因为size_t为无符号整形,只好将i也这么定义了
for (i = 0; i < num; i++)//拷贝的主体循环
{
if((*(dest+i) = *(scr+i)) == '\0')//1)时就很正常了,慢慢拷贝,直至循环结束,进入下面的else语句
{ //2)当i未能自增到num时scr已经没字符了,那就只好跳出拷贝循环了,进入if语句
break;
}
}
if (i < num)
{
for (i = i + 1; i < num; i++)
{
*(dest + i) = '\0';
}
}
else
{
*(dest + i + 1) = '\0';//末尾补一个\0
}
return dest;
}
小栗子
我觉得的还是用while循环的好,毕竟拷贝一份地址后你的操作的可以更加轻松与保险,但是for循环不用临时拷贝,用 i 操作的确很爽的样子。
完
Thanks.
See you next time!