strncpy、strncat、strncmp函数的使用说明和模拟实现
在前面的文章中,我已经介绍了长度不受限制的字符串函数。今天我来介绍几个长度受限制的字符串函数,并且模拟实现这些长度受限制的字符串函数。
strncpy函数
strncpy函数也是一个拷贝函数,但是与strcpy函数有所不同,strncpy函数是从源字符串拷贝num个字符到目标字符串,num是strncpy函数的一个参数,当源字符串的字符数目小于num时,在拷贝完源字符串后,会在目标字符串中追加0,直到达到num的数目。
由msdn查询可以得知,strncpy函数的返回值和参数是:
char* strncpy(char* destination,const char* source,size_t num)。注意我们只关注返回类型和参数的类型,参数的名字不管。
接着,继续往下查询strncpy函数的返回值。
由msdn对strncpy的返回值的介绍可知,strncpy函数返回目标字符串的地址。
接下来,我来举一个strncpy函数的使用例子。
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[20] = "abcdef";
char arr2[] = "xxxxxx";
printf("%s\n",strncpy(arr1,arr2,5));
return 0;
}
由运行结果可以知道,strncpy函数确实从源字符串拷贝num个字符到目标字符串。
接下来,我来验证一下strncpy函数的拷贝过程中,源字符串达不到num个字符,那么就会在拷贝完源字符串后,在目标字符串后面补0,直到达到num个字符。
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[20] = "abcdefhij";
char arr2[] = "xxxx";
printf("%s\n",strncpy(arr1,arr2,8));
return 0;
}
在strncpy函数拷贝前,arr1的内容如下:
在strncpy函数拷贝后,arr1的内容如下:
在该程序中,arr2中有4个字符,而strncpy函数却要从arr2中拷贝8个字符到arr1,按照源字符串不足拷贝时,要在源字符串拷贝后补0,那么就要补4个0。由图片可以得知,arr1确实被覆盖了arr1的内容和4个0。
接下来,我来实现strncpy函数的模拟实现。
#include<stdio.h>
#include<assert.h>
#include<string.h>
char* my_strncpy(char* dest,const char* src,size_t len)
{
char* ret = dest;
int offset = 0;
assert(dest != NULL);
assert(src != NULL);
if(strlen(src) < len)
{
offset = len - strlen(src);
len = strlen(src);
}
while(len)
{
*dest++ = *src++;
len--;
}
while(offset)
{
*dest++ = '\0';
offset--;
}
return ret;
}
int main()
{
char arr1[20] = "abcdef";
char arr2[] = "xxxx";
my_strncpy(arr1,arr2,3);
printf("%s\n",arr1);
return 0;
}
由图片可以知道,该模拟实现函数可以满足strncpy函数的要求。
strncat函数
strncat函数与strcat函数功能差不多相同,唯一有区别的是strncat函数是追加count个字符(count是strncat函数的参数),而strcat是将整个字符数组追加到另一个字符数组。
由msdn查询可知,strncat函数的返回类型和参数类型是:
char* strncat(char* dest,const char* src,size_t num),注意,我们只关注返回类型和参数类型,不关注参数名字。
在msdn继续查询可以得知,strncat函数的返回值是目标字符串的地址。(注意这里是返回值,跟上面的返回类型有所不同)
现在,我来举一个strncat函数的使用例子。
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[20] = "abcdef";
char arr2[] = "xyz";
printf("%s\n",strncat(arr1,arr2,2));
return 0;
}
接下来,我来写一个小程序,观察一下strncat函数的更多的细节。
#include<string.h>
int main()
{
char arr1[20] = "abcdef\0qqqqqqqqqqqq";
char arr2[] = "xyz";
strncat(arr1,arr2,2);
return 0;
}
这是arr1开始时存储的内容:
这是arr1数组被追加时的内容:
对比一下arr1被拷贝前和被拷贝后的变化可以发现,strncat还是从’\0’开始覆盖,并且覆盖完后对应的几个字符后,开始在后面加个’\0’。
在上一篇文章中,我已经验证过strcat函数不能用在字符串自己给自己追加,那么与strcat函数功能差不多的是strncat函数,能不能用在字符串自己给自己追加呢?
我用小程序来验证一下。
#include<string.h>
int main()
{
char arr1[20] = "abc";
strncat(arr1,arr1,3);
return 0;
}
arr1被追加字符前:
这是arr1被追加后:
由调试过程中的观察可以得知,strncat的确实现了字符自己给自己追加,我来分析一下成功的原因所在。
在前面文章提到的strcat函数不能用在字符串自己给自己追加的原因是’\0’被覆盖掉,而strcat函数是以从源字符串拷贝到’\0’去到目标字符串作为停止条件,而’\0’却在拷贝的过程中被覆盖掉,那么strcat函数就会持续的拷贝,进入到死循环拷贝。
与strcat函数不同的是,strncat函数是以拷贝完想要拷贝的字符字数(即给strncat函数传参的数字)作为结束标志,并且在拷贝完成的目标字符串后面再添加个’\0’,注意的是,这个’\0’不是从源字符串中拷贝过来的,strncat函数自己添加的,那么,即使arr1中的’\0’早早的就被覆盖掉,也不会影响strncat函数的正常运作。
接下来,我来模拟实现strncat函数。
#include<stdio.h>
#include<assert.h>
char* my_strncat(char* dest,const char* src,size_t num)
{
char* ret = dest;
assert(dest != NULL);
assert(src != NULL);
while(*dest != '\0') //找到'\0'的位置
{
dest++;
}
while(num--) //开始往目标字符串追加字符
{
*dest++ = *src++;
}
*dest = '\0'; //最后覆盖'\0'
return ret;
}
int main()
{
char arr1[20] = "abcdef";
char arr2[] = "abcdef";
printf("%s\n",my_strncat(arr1,arr2,5));
return 0;
}
由运行结果可以发现该模拟实现strncat函数确实满足了我们的要求。
strncmp函数
strncmp函数与strcmp函数都是字符串比较函数,有区别的是strncmp只是比较调用该函数时传参的num个字符,那么我依然来介绍一下该函数的返回类型和参数类型,还有返回值吧。
在msdn查询可以得知,strncmp函数的参数类型和返回类型是:int strncmp(const char* str1,const char* str2,size_t num),与strcmp函数参数类型和返回类型相比,只是多了个参数。
接下来,我来介绍一下该函数的返回值。
1.第一个字符串小于第二个字符串,返回小于0的数字。
2.第一个字符串等于第二个字符串,返回等于0的数字。
3.第一个字符串大于第二个字符串,返回大于0的数字。
接下来,我来举一个strncmp函数的使用例子。
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[20] = "abcdefghi";
char arr2[] = "abcdef";
printf("%d\n",strncmp(arr1,arr2,6));
return 0;
}
运行结果如下:
观察arr1和arr2的字符数组可以得知两者根本不一样,但是我们只想比较前6个字符是否不一样,所以就给strncmp函数传参传6,结果返回了0,也就是前6个元素是一样的。
接下来,我来模拟实现strncmp函数。
#include<stdio.h>
#include<assert.h>
int my_strncmp(const char* str1,const char* str2,size_t num)
{
assert(str1 != NULL);
assert(str2 != NULL);
while(num--)
{
if(*str1 == *str2)
{
str1++;
str2++;
}
else
{
if(*str1 > *str2)
{
return 1;
}
else
{
return -1;
}
}
}
return 0;
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abcdefghijk";
printf("%d\n",my_strncmp(arr1,arr2,6));
return 0;
}
运行结果如下:
该模拟实现strncmp函数确实满足了我们的要求。
今天,我对于长度受限制的字符串函数已经介绍完了,而字符串函数的还多着,关注点一点,下期继续学字符串函数。