【C】库函数之 strcpy

目录

1. Copy string

2. 多种方式实现

3. 测试用例

4. 输出结果


1. Copy string

#include <string.h>
char * strcpy ( char * destination, const char * source );

Copies the C string pointed by source into the array pointed by destination, including the terminating null character (and stopping at that point).

To avoid overflows, the size of the array pointed by destination shall be long enough to contain the same C string as source (including the terminating null character), and should not overlap in memory with source.

上述内容是 cplusplus 对 strcpy 函数的介绍,可以看出 strcpy 函数用于复制字符串,它将 source 指向的 C 字符串复制到目标所指向的数组中,包括终止空字符('\0'),当遇到 '\0' 时,复制结束。

在复制的过程中,需要注意的是目标指向的数组大小应该足够长,这样才能包含与源字符串相同大小的字符串,并且目标字符串不能是"abc" 这样的常量字符串,因为这样的字符串不能写,只能读,最重要的一点,目标字符串不能与源字符串重叠

如果目标数组大小 小于 源字符串,也会 复制成功,但是这导致了缓冲区溢出,是不安全的,比较安全的实现是指定复制的字符串的大小,可以参考 strncpy函数实现

2. 多种方式实现

接下来通过介绍几种实现 strcpy 函数的方法来说明下如何写出高质量代码:

void MyStrcpy(char *dest, char *src) {
	while ('\0' != (*src)) {
		*dest = *src;
		src++;
		dest++;
	}

	// 循环跳出来时 *src=='\0',将 '\0' 赋给 *dest
	*dest = *src;

	return;
}

 不足:while 循环内部的语句过于繁琐。

 改进:优化 while 循环内部的语句为一句。

void MyStrcpy(char *dest, char *src) {
	while ('\0' != (*src)) {
		// 后置 ++ 优先级高于 *,而后置 ++ 是先赋值再加 1,
		// 因此先赋值的是 src 原来的字符(*src),一次赋值结束后
		// src+1, dest+1
		*dest++ = *src++;
	}

	// 循环跳出来时 *src=='\0',将 '\0' 赋给 *dest
	*dest = *src;

	return;
}

 不足:*src 要分成两种情况('\0' != *src 和 '\0' == *src)去讨论。

 改进:优化 while 循环内部的语句作为循环条件。

void MyStrcpy(char *dest, char *src) {
	while (*dest++ = *src++) {
		;
	}

	return;
}

 不足:没有判断指针的有效性。

 改进:检查指针的有效性。

void MyStrcpy(char *dest, char *src) {
	if ((NULL != dest) && (NULL != src)) {
		return;
	} else {
		while (*dest++ = *src++) {
			;
		}
	}
}

 不足:上述代码每次都需要判断指针是否为空。

 改进:添加 assert 断言。

void MyStrcpy(char *dest, char *src) {
	assert((NULL != dest) && (NULL != src));

	while (*dest++ = *src++)
		;

	return;
}

 不足:假如把 dest 与 src 的顺序写反了,程序只会在运行中报错。

 改进:保证 src 这个源字符串内容不可修改(添加 const),这样当传错 dest 和 src 时,会在编译时报错。

void MyStrcpy(char *dest, const char *src) {
	assert((NULL != dest) && (NULL != src));

	while (*dest++ = *src++)
		;

	return;
}

 不足:上述代码不能作为参数传入函数内部。

 改进:修改函数返回类型为 char *,以实现链式访问。

char *Strcpy(char *dest, const char *src) {
	char *cp = dest;

	assert((NULL != src) && (NULL != cp));

    while (((*cp++) = (*src++)))
		;

	return dest;
}

那如何写出高质量的代码呢?

  • 使用 assert;
  • 尽量使用 const;
  • 良好的编码风格;
  • 必要的注释。

3. 测试用例

#include <stdio.h>
#include <assert.h>

void test() {
    char str1[10] = "abc";
    char *str2 = "xyz";
 
    printf("call Strcpy before, str1: %s, str2: %s\n", str1, str2);
    //Strcpy(str1, str2);
    //printf("call Strcpy after, str1: %s, str2: %s\n", str1, str2);
    printf("call Strcpy after, str1: %s, str2: %s\n", Strcpy(str1, str2), str2);
}
 
int main(void) {
    test();
 
    return 0;
}

4. 输出结果

call Strcpy before, str1: abc, str2: xyz
call Strcpy after, str1: xyz, str2: xy

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值