[应用方案] 字符串拷贝

[复制链接]
 楼主| wwppd 发表于 2025-7-22 07:57 | 显示全部楼层 |阅读模式
在C语言中,字符串复制(拷贝)是一个常见的操作。C语言标准库提供了几个用于字符串复制的函数,这些函数既安全又高效。本文将详细介绍这些常用的字符串复制方法,包括它们的函数原型、使用方法以及注意事项。

1. strcpy() 函数
strcpy() 是最基本的字符串复制函数,它将源字符串复制到目标字符串中,包括结尾的空字符'\0'。函数原型:

char *strcpy(char *dest, const char *src);
参数说明:

dest:指向目标数组的指针,用于存储复制的字符串。
src:指向要复制的源字符串的指针。

返回值:返回一个指向目标字符串 dest 的指针。


使用示例:

  1. #include <stdio.h>

  2. #include <string.h>

  3. int main() {

  4.     char src[] = "Hello, World!";

  5.     char dest[20];

  6.     strcpy(dest, src);

  7.     printf("复制后的字符串: %s\n", dest);

  8.     return 0;

  9. }

输出结果:

复制后的字符串: Hello, World!
需要注意的是,strcpy() 函数不会检查目标数组是否有足够的空间来容纳源字符串,如果目标数组空间不足,可能会导致缓冲区溢出,造成程序崩溃或安全漏洞。因此,在使用 strcpy() 时,必须确保目标数组有足够的空间。

2. strncpy() 函数
strncpy() 函数是 strcpy() 的一个更安全的变体,它允许指定要复制的最大字符数。函数原型:

char *strncpy(char *dest, const char *src, size_t n);
参数说明:

dest:指向目标数组的指针,用于存储复制的字符串。
src:指向要复制的源字符串的指针。
n:要复制的最大字符数。

返回值:返回一个指向目标字符串 dest 的指针。


使用示例:

  1. #include <stdio.h>

  2. #include <string.h>

  3. int main() {

  4.     char src[] = "Hello, World!";

  5.     char dest[10];

  6.     strncpy(dest, src, sizeof(dest) - 1);

  7.     dest[sizeof(dest) - 1] = '\0';  // 确保字符串以 null 结尾

  8.     printf("复制后的字符串: %s\n", dest);

  9.     return 0;

  10. }

输出结果:

复制后的字符串: Hello, Wo
strncpy() 函数会复制源字符串中的字符,直到达到指定的最大字符数或遇到源字符串的结束符。如果源字符串的长度小于指定的最大字符数,strncpy() 会用空字符填充目标数组的剩余部分。然而,如果源字符串的长度大于或等于指定的最大字符数,strncpy() 不会自动添加结束符。因此,在使用 strncpy() 时,通常需要手动添加字符串结束符,如示例中所示。

3. memcpy() 函数
虽然 memcpy() 不是专门用于字符串复制的函数,但它可以用来复制任意类型的数据,包括字符串。memcpy() 函数按字节复制数据,不考虑数据的类型。函数原型:

void *memcpy(void *dest, const void *src, size_t n);
参数说明:

dest:指向目标内存区域的指针。
src:指向源内存区域的指针。
n:要复制的字节数。

返回值:返回一个指向目标内存区域 dest 的指针。


使用示例:

  1. #include <stdio.h>

  2. #include <string.h>

  3. int main() {

  4.     char src[] = "Hello, World!";

  5.     char dest[20];

  6.     memcpy(dest, src, strlen(src) + 1);  // +1 是为了包含字符串结束符

  7.     printf("复制后的字符串: %s\n", dest);

  8.     return 0;

  9. }

输出结果:

复制后的字符串: Hello, World!
使用 memcpy() 复制字符串时,需要注意的是要明确指定要复制的字节数。通常,我们会使用 strlen() 函数获取源字符串的长度,并加 1 以包含字符串结束符。memcpy() 不会自动添加字符串结束符,所以在复制时必须包含它。

4. snprintf() 函数
snprintf() 函数虽然主要用于格式化输出,但也可以用于安全地复制字符串。它允许指定输出缓冲区的大小,从而防止缓冲区溢出。函数原型:

int snprintf(char *str, size_t size, const char *format, ...);
参数说明:

str:指向目标缓冲区的指针。
size:目标缓冲区的大小。
format:格式化字符串。
...:可变参数列表。

返回值:返回写入的字符数(不包括结束符),如果发生截断,则返回本应写入的字符数。


使用示例:

  1. #include <stdio.h>

  2. int main() {

  3.     char src[] = "Hello, World!";

  4.     char dest[10];

  5.     snprintf(dest, sizeof(dest), "%s", src);

  6.     printf("复制后的字符串: %s\n", dest);

  7.     return 0;

  8. }

输出结果:

复制后的字符串: Hello, Wo
snprintf() 函数会确保输出不会超过指定的缓冲区大小,并且总是添加字符串结束符。如果源字符串长度超过目标缓冲区大小,输出会被截断,但不会导致缓冲区溢出。


在选择字符串复制方法时,需要考虑安全性、效率和具体的使用场景:

strcpy() 简单直接但不安全;
strncpy() 提供了一定的安全性但需要注意手动添加结束符;
memcpy() 适用于复制任意数据,包括字符串;
snprintf() 则是一种非常安全的方法,特别适合处理可能超出缓冲区大小的字符串。

mmbs 发表于 2025-8-4 10:32 | 显示全部楼层
必要时使用编译器提供的安全函数              
youtome 发表于 2025-8-4 16:49 | 显示全部楼层
memcpy        复制指定字节数的内存
bartonalfred 发表于 2025-8-5 10:58 | 显示全部楼层
标准库字符串函数本身是线程安全的
claretttt 发表于 2025-8-5 14:24 | 显示全部楼层
复制src的前n个字符到dest,若src长度≥n,则不自动添加\0。
sdlls 发表于 2025-8-10 20:49 | 显示全部楼层
目标缓冲区有足够的空间来容纳源字符串及其终止符。
hearstnorman323 发表于 2025-8-10 22:38 | 显示全部楼层
推荐顺序:strlcpy(安全、自动终止) > strncpy(需手动处理终止符) > memcpy(需手动处理) > strcpy(仅用于固定小缓冲区)。
hilahope 发表于 2025-8-12 03:11 | 显示全部楼层
不要在重叠的内存区域之间使用 strcpy,而是使用 memmove 或 strncpy。
jackcat 发表于 2025-8-12 14:51 | 显示全部楼层
使用 strlcpy              
xiaoyaodz 发表于 2025-8-12 19:52 | 显示全部楼层
使用strlen获取源字符串长度时,结果不包含'\0',因此目标缓冲区大小需至少为strlen(src) + 1。
maqianqu 发表于 2025-8-15 22:46 | 显示全部楼层
源字符串长度 ≥ 目标缓冲区大小,会越界写入,覆盖相邻内存
jonas222 发表于 2025-8-16 18:07 | 显示全部楼层
使用 strlen、printf等函数时会越界读取内存。
hudi008 发表于 2025-8-16 19:29 | 显示全部楼层
C语言中常用的字符串复制函数包括 strcpy、strncpy、strlcpy
mollylawrence 发表于 2025-8-16 20:26 | 显示全部楼层
memcpy:通用内存复制,需手动处理终止符​
mmbs 发表于 2025-8-16 21:12 | 显示全部楼层
避免使用strcpy,优先用strncpy并手动添加'\0'
louliana 发表于 2025-8-16 21:44 | 显示全部楼层
使用 strncpy 时,手动添加终止符;使用 strcpy_s 和 strncpy_s 时,自动添加终止符。
vivilyly 发表于 2025-8-18 19:34 | 显示全部楼层
若源或目标指针为NULL,调用字符串函数会触发未定义行为
jtracy3 发表于 2025-8-19 11:18 | 显示全部楼层
在使用 strcpy 或 strncpy 之前,始终检查目标缓冲区的大小
mattlincoln 发表于 2025-8-19 13:20 | 显示全部楼层
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int safe_strcpy(char *dest, size_t dest_size, const char *src) {
    if (dest == NULL || src == NULL || dest_size == 0) {
        return -1; // 错误处理
    }
    snprintf(dest, dest_size, "%s", src);
    return 0;
}

int main() {
    char src[] = "Hello, World!";
    char dest[10];
    if (safe_strcpy(dest, sizeof(dest), src) != 0) {
        printf("Copy failed!\n");
    } else {
        printf("Copied: %s\n", dest); // 输出: Copied: Hello, W
    }
    return 0;
}
wangdezhi 发表于 2025-8-19 17:02 | 显示全部楼层
检查指针有效性,区分字符串与二进制数据
您需要登录后才可以回帖 登录 | 注册

本版积分规则

53

主题

3059

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部

53

主题

3059

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部