C语言函数:字符串函数及模拟实现strncpy()、strncat()、strncmp()
在了解strncpy、strncat()、前,需要先了解strcpy()、strncat():
C语言函数:字符串函数及模拟实现strlen() 、strcpy()、 strcat()_srhqwe的博客-CSDN博客
strncpy():
作用:拷贝受限制长度的字符串,意思是:可以指定拷贝字符的个数到目标字符串内。
限制字符串个数是为了让程序相对安全,降低访问越界等情况出现的可能性。但是不会绝对安全,一个程序员要写bug如挥手一般简单.
参数部分:
char * __cdecl strncpy ( char * dest, const char * source, size_t count )
count是指定传入的个数。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
char de[20] = "abcdef";
char so[] = "qwer";
strncpy(de, so, 2);//拷贝2个字符
printf("%s\n", de);
//结果:qwcdef
return 0;
}
当拷贝的字符串的个数超出原字符串的个数时,多出的部分会传\0进去:
strncpy函数的实现:
在strcpy基础上,写strncpy并不难。
因此直接展示源码:
char * __cdecl strncpy (
char * dest,
const char * source,
size_t count
)
{
char *start = dest;
while (count && (*dest++ = *source++) != '\0') /* copy string */
count--;
if (count) /* pad out with zeroes */
while (--count)
*dest++ = '\0';
return(start);
}
因为多了count用于控制长度,所以while循环也多了一个count:
当count不为0时,while循环继续。
直到count为0时,自动跳出。
(*dest++ = *source++) != '\0') 和strcpy一样。其中!=\0可以去掉。
当没有\0时,dest和source一起++找下一个字符。
当在source找到\0时,把\0传入后while循环结束
if语句是为了保证count被置为0,因为count是我们需要拷贝的字符串个数。
就是上面所说的,如果超越了source本身的个数,会自动补\0
最后return 最初的dest,即start
strncat():
作用:追加受限制的字符串。
参数部分:
char * __cdecl strncat ( char * front, const char * back, size_t count )
int main()
{
char de[20] = "abcd";
char so[] = "qwer";
strncat(de, so, 2);
printf("%s\n", de);
//结果:abcdqw
return 0;
}
与strncpy一样,如果追加的个数超出so的范围呢?会和strcpy一样?
int main()
{
char de[20] = "abcd";
char so[] = "qwer";
strncat(de, so, 6);
printf("%s\n", de);
//结果:abcdqwer
return 0;
}
并不会,具体是怎么做的呢?那就先看看这个函数的实现:
strncat的实现:
strncat的源码:
char * __cdecl strncat (
char * front,
const char * back,
size_t count
)
{
char *start = front;
while (*front++)
;
front--;
while (count--)
if ((*front++ = *back++) == 0)
return(start);
*front = '\0';
return(start);
}
第一个while循环,和strcat一样,先找到front的\0,然后从\0开始向后追加。
第二个while循环,count--作为条件语句,意思是循环count次,从而可以保证追加的个数。
while循环的if语句,是从front的\0开始向后追加back的元素,当在back中遇到是\0时,==0,那么就直接返回。因此如果追加的个数超出范围,不会追加\0,而是直接返回。
当count==0时,while循环退出,说明目前为止,已经把想传入的字符串传完了,因为上面是后置++,所以此时的front已经指向了最后一个元素的后面的指针。所以直接将此时指针指向的front的元素改成\0,即: *front = '\0';
最后return 原front地址
strncmp():
在了解strncmp()前,需要先了解strcmp():
C语言函数:字符串函数及模拟实现strcmp()_srhqwe的博客-CSDN博客
作用:对比受限制的两串字符串
strncmp和strcmp其实相差并不大,只是限制了对比的范围。返回值与strcmp是一样的
参数部分:
int __cdecl strncmp ( const char *first, const char *last, size_t count )
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
char de[20] = "abcd";
char so[] = "aba";
strncmp(de, so, 3);
printf("%s\n", de);
//结果:1
return 0;
}
输入3比较的就是de和so的前三个字符
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
char de[20] = "abad";
char so[] = "aba";
int ret = strncmp(de, so, 7);
printf("%d\n",ret );
//结果:1
return 0;
}
即使输入的数字超出了两个字符串的个数也没事,因为往后比较的都是\0。与strcmp基本一致。
strncmp()函数的实现:
strncmp函数源码:
int __cdecl strncmp
(
const char *first,
const char *last,
size_t count
)
{
size_t x = 0;
if (!count)
{
return 0;
}
if( count >= 4 )
{
/* unroll by four */
for (; x < count-4; x+=4)
{
first+=4;
last +=4;
if (*(first-4) == 0 || *(first-4) != *(last-4))
{
return(*(unsigned char *)(first-4) - *(unsigned char *)(last-4));
}
if (*(first-3) == 0 || *(first-3) != *(last-3))
{
return(*(unsigned char *)(first-3) - *(unsigned char *)(last-3));
}
if (*(first-2) == 0 || *(first-2) != *(last-2))
{
return(*(unsigned char *)(first-2) - *(unsigned char *)(last-2));
}
if (*(first-1) == 0 || *(first-1) != *(last-1))
{
return(*(unsigned char *)(first-1) - *(unsigned char *)(last-1));
}
}
}
/* residual loop */
for (; x < count; x++)
{
if (*first == 0 || *first != *last)
{
return(*(unsigned char *)first - *(unsigned char *)last);
}
first+=1;
last+=1;
}
return 0;
}
第一个if语句,如果count==0那么就不用比较了,因为比较的区间没有。
第二个if语句只是将区间划分成[0,4]和(4,正无穷)讨论
之后的语句就是把每个每个字符进行比较,返回比较的结果。