要想模拟实现这两个库函数,首先得明白它们到底是干嘛的,然后考虑它有哪些需要注意的地方,最后才是具体的去实现每一个细节。
strcpy:
功能:把源字符串src里面的字符串拷贝到目标字符串dest中去
注意:1、目标字符串要有足够大的空间可以容下源字符串。
2、目标字符串要是可修改的。
现在我们来讨论一下它的具体实现。首先考虑它的参数,既然是把一个字符串拷到另一个字符串中去,那我们就必须得知道两个字符串的首元素地址,那么,参数的类型就是char *,此时要注意到只是把源字符串拷到目标字符串中,源字符串本身是不需要做任何改变的。所以,第二个参数可用const修饰。其次来考虑它是否需要返回一个值,若需返回,那么它的返回值类型是什么?(这个我在代码中再来讲解)
下边来看代码
#include <stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
char* my_strcpy(char *dest, const char *src)
{
assert(dest != NULL);
assert(src != NULL);
//判断两个指针时候为空指针,若为空,后边对它进行解引用的话就会使程序崩溃
char *ret = *dest;//创建一个临时指针来记住目标字符串的首元素地址
while (*dest++ = *src++)//当把字符串src的‘\0’拷过去之后,while里边就是0了,循环就停下来了
{
;
}
return ret;
}
可以看到这里有一个char *类型的返回值,其实,不用返回值也可以实现我们的字符串拷贝,那为什么还要加个返回值呢?
为了实现链式访问。
下边举个例子:
#include <stdio.h>
#include <assert.h>
char* my_strcpy(char *dest, const char *src)
{
assert(dest != NULL);
assert(src != NULL);
char *ret = *dest;
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char buf1[20] = "abcdefghijk";
char buf2[] = "mnopq";
my_strcpy(buf1, buf2);
printf("%s\n", buf1);
return 0;
}
运行结果为:
strncpy:
其功能也是字符串拷贝,它比strcpy多了一个参数n(要拷贝的字符的个数)。所以我们需要判断n与源字符串src长度(length)哪个大并对其分别进行处理。需要说明的是,这里的长度是将'\0'也包括进来的。
下边来讨论n与len作比较的三种情况。
1、n<length
这是最好处理的一种情况,只要将源字符串的前n个字符拷贝到目标字符串dest中就行了。
2、n=length
此种情况就相当于strcpy
3、n>length
这种情况相对来说要麻烦一点,当把源字符串拷完了之后多出去的需拷几个字符就用‘\0’代替
注意:
1、目标字符串要有足够大的空间可以容下源字符串。
2、目标字符串要是可修改的。
下面看代码:
#include <stdio.h>
#include <assert.h>
char *my_strncpy(char *dest, const char *src, int n)
{
assert(dest != NULL);
assert(src != NULL);
char *ret = *dest;
//此循环用于处理n小于或等于源字符串src的长度(length)的情况
while (n && (*src))//当n等于0或者*src为'\0'的时候while循环停下
{
*dest++ = *src++;
n--;
}
//此循环用于处理n大于源字符串src的长度的情况
while (n > 0)//若进入了该循环说明上一个循环是因为*src='\0'而退出的,及n>length
{
*dest++ = 0;
n--;
}
return ret;
}
下边举个例子将三种情况都看一下
#include <stdio.h>
#include <assert.h>
char *my_strncpy(char *dest, const char *src, int n)
{
assert(dest != NULL);
assert(src != NULL);
char *ret = *dest;
while (n && (*src))
{
*dest++ = *src++;
n--;
}
while (n > 0)
{
*dest++ = 0;
n--;
}
return ret;
}
int main()
{
char dest[20] = "abcdefghijk";
char src[] = "hello";
my_strncpy(dest, src, 3);
printf("%s\n", dest);
my_strncpy(dest, src, 6);
printf("%s\n", dest);
my_strncpy(dest, src, 8);
printf("%s\n", dest);
return 0;
}
运行结果
:虽然第二个和第三个结果看起来一样,事实上,在内存里边存的是不一样的,调试,在窗口打开内存,对my_strncpy函数取地址会出现这样的一串数据,看图
发现当源字符串被拷贝完了之后,之后的三个字符都被拷贝成了‘\0’
总结:
strcpy只是拷贝字符串,但不限制拷贝的数量,很容易造成缓冲溢出。strncpy相对要安全一些。