我们首先来考虑一个简单的问题,我们定义了一个字符串,然后想要复制这个字符串,在C语言中,我们可以 for循环 指针 实现,假如我们用指针来操作

#include <stdio.h>
char  str1[20]= "Zxiaoxuan";
char  str2[20];
char * pts1 = str1 ;
char * pts2 = str2;
int main () {
	pts2=pts1;
	return  0;

这样pts2只是复制字符串str1的地址,而不是复制整个字符串。

那么如何进行整个字符串的复制呢

  1. 我们可以采用数组的方式来进行
#include<stdio.h>
void copy_string(char str1[],char str2[]) {
	int i = 0;
	while(str2[i] != '\0') {
		str1[i] = str2[i];
		i++;
	str1[i] = '\0';
int main() { 
	char a[100]="zxiaoxuan"; 
    char b[100]=" ";
	copy_string(b,a);
	printf("%s\n",b);
	return 0;

输出:
在这里插入图片描述
2. 可以采用指针的方式来进行

#include<stdio.h>
void copy_string(char *p1,char *p2) {
	while(*p2 != '\0') {
		*p1 = *p2;
		*p1++;
		*p2++;
	*p1 = '\0';
int main() {
	char a[100]="zxiaoxuan";
	char b[100]=" ";
	copy_string(b,a);
	printf("%s\n",b);
	return 0;

除了上面两种,C语言有没有内置的函数来进行拷贝复制呢,当然是有的,下面我们来逐一介绍。

strcpy()

使用头文件:#include <string.h>

定义:char *strcpy(char *dest, const char *src);

destinin:目标字符数组;
source:源字符数组;

函数说明strcpy()会将参数src 字符串拷贝至参数dest 所指的地址。 用于对字符串进行复制,识别到字符串的结束符号‘\0’自动停止

返回值:返回参数dest 的字符串起始地址。

  • 参数 dest 的内存空间要足够大,否则拷贝可能会造成缓冲溢出。
  • strcpy() 在复制结束后会添加结束符\0,这点和strncpy()不同

strcpy()的参数是两个字符串指针,其中 *src源字符串可以是指针,数组名,或者字符串常量,但是*dest目标字符串必须位一个确定的数据对象(字符数组),而且应该已经开辟好了存储空间(已经做好初始化)

#include <stdio.h>
#include <string.h>
int main ()
    char  str1[]= "Zxiaoxuan";
    char  str2[20];
    char  str3[20];
    strcpy  (str2,str1);
    strcpy  (str3, "copy successful");
    printf  ( "str1: %s\nstr2: %s\nstr3: %s\n",str1,str2,str3);
    return  0;

memcpy()

使用头文件:C语言:#include <string.h> C++:#include<cstring>

定义:void memcpy(void *dest, const void *src, size_t n);

destinin:目标地址;
source:源地址;
n:复制的字节长度。

函数说明memcpy()复制 src 所指的内存数据的 n 个字节到 dest所指的内存地址上。也就是从源地址复制n 个字节到目标地址

第一个和第二个指针都是void型且第二个指针不能被修改,第三个参数是需要拷贝的内存长度按字节记。

返回值:返回指向 dest 的指针。返回的指针类型是void。

  • memcpy()并不限制被复制的数据类型,只是逐字节地进行复制,任何数据类型都可以进行复制,例如字符数组、整型、结构体、类等

  • memcpy() 会完整的复制 num个字节,不会遇到‘\0’而结束,这点与 strcpy() 不同

  • dest 和 src所指的内存空间地址不能重叠

  • 参数 dest 的内存空间要足够大,起码要大于等于 num个字节

  • 通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy

#include  <string.h>
#include  <stdio.h>
#include  <stdlib.h>
#define N (20)
int main() {
	char *p1 = "zxiaoxuan";
	char *p2 = (char *)malloc(sizeof(char) * N);
	memcpy(p2, p1, N);
	printf("p2 = %s\n", p2);
	system("pause");
	return 0;

strncpy()

使用头文件:#include <string.h>

定义:char *strncpy(char *dest, const char *src, size_t len);

destinin:目标字符数组;
source:源字符数组;
len:复制的字符串长度。

函数说明strncpy()复制字符串 src 的前 len 个字节到 dest所指的内存地址上。

返回值:返回字符串dest

  • strncpy()在复制结束后不会向dest结尾添加’\0’结束符 这个是很重要的一个点,要记住
  • 如果source(源字符数组)的长度>复制的字符串数len,则只复制source(源字符数组)的前len个字符,不会自动添加结束符\0
  • 如果source(源字符数组)的长度<复制的字符串数len,则以NULL填充dest(目标字符数组),直到复制完n个字节
  • 参数 dest 的内存空间要足够大,起码要大于等于 num个字节
  • 在使用strncpy()的时候,拷贝长度最好为strlen(src)+1,以保证最后的结束符\0也能被复制
#include <stdio.h>
#include <string.h>
int main () {
	char str1[]= "Z Xiao Xuan";
	char str2[40];
	char str3[40];
	/* 拷贝到缓冲区: */
	strncpy ( str2, str1, sizeof(str1)+1); //拷贝长度为 str1+1,将结束符\0也进行拷贝
	/* 拷贝 5 个字符: */
	strncpy ( str3, str2, 5 );
	str3[5] = '\0';   /* 手动加上终止符 */
	puts (str1);
	puts (str2);
	puts (str3);
	system("pause");
	return 0;

memmove()

使用头文件:#include <string.h>

定义:void *memmove( void* dest, const void* src, size_t count );

destinin:目标地址;
source:源地址;
count:复制的字节长度。

函数说明memmove()复制 src 所指的内存数据的 n 个字节到 dest所指的内存地址上。也就是从源地址复制n 个字节到目标地址。如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,但复制后源内容会被更改。但是当目标区域与源区域没有重叠则和memcpy函数功能相同。

缓冲区重叠这个需要讲解一下:

根据dest(目标字符数组)内存区域和src(源字符数组)内存区域可分为三种情况:

  1. src内存区域和dest内存区域完全不重叠
  1. src(源字符数组)内存区域和dest(目标字符数组)内存区域存在重叠 且dest所在区域在src所在区域前
    在这里插入图片描述
    如上图,dest(目标字符数组)src(源字符数组)存在三个字节的内存区域重叠

但是在复制的时候,先把src的前三个字节复制到了dest的前三个内存区域内,再继续复制到重叠区域时,就算被覆盖,也不会有数据错误 所以这样可以正常复制

  1. src(源字符数组)内存区域和dest(目标字符数组)内存区域存在重叠,且在dst所在区域在src所在区域后面
    在这里插入图片描述
    这时候如果使用memcpy()进行复制,会把三个重叠内存字节覆盖为src的前三个字节内容,导致复制到重叠部分的时候出现错误

如果使用memmove(),会先将src(源字符数组)中的内容复制到缓冲区,然后再复制到dest(目标字符数组)中去,有效的避免了数据重叠。

下面举一个例子:

首先定义一个字符串str:memmove can be very useful......

然后把字符串的第15个字节~第25个字节的11个字节数据,复制到第20个字节~第30个字节中去

src(源字符数组)very useful
dest(目标字符数组)useful.....

重叠部分: 第20个字节~第25个字节

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main () {
	char str[] = "memmove can be very useful......";
	memmove (str+20,str+15,11);
	puts (str);
	system("pause");
	return 0;

先将11个字节的src(源字符数组)数据(very useful)内容复制到缓冲区中,再用缓冲区中的内容覆盖dest(目标字符数组)指向的内存(第20个字节~第30个字节),这样就避免了第20个字节~第25个字节的重叠

在这里插入图片描述
最后就变成了memmove can be very very useful.

头文件:#include &lt;string.h&gt;定义函数:char *strcpy(char *dest, const char *src);函数说明:strcpy()会将参数src 字符串拷贝至参数dest 所指的地址。返回值:返回参数dest 的字符串起始地址。 #include char *str_contact(const char *,const char *); char *str_contact(const char *str1,const char *str2) char *result = (char*) malloc(strlen(str1) + strlen(str2) + 1); if(!result) printf(Er void strmncpy(char *s, int m, int n, char *t); 参数 s 指向源字符串,t 指向字符串复制的目标单元,函数功能为将 s 指向字符串从第 m 个(从0开始编号)字符开始的连续 n 个字符复制到 t 指向的存储单元; 如果第 m 个字符后面的字符数不足 n 个,则复制到 ‘\0’为止; 如果 s 的长度不到 m,则复制空串。 char *s = "abcdefghijklmn";
snprintf sprintf不能检查目标字符串的长度,可能造成众多安全问题, snprintf是的sprintf的安全版本,他的特点是安全,不管怎么着,它都能保证结果串str以\0结尾,哪怕dst_size不够大,它都能做好截断,同时在末尾添加上\0。 int snprintf(char *str, size_t size, const char *format, ...); 函数说明: 最多从源串中拷贝size-1个字符到目标串中,然后再在后面加一个0。所以如果目标串的大小为size的话,将不会溢出
1.strcpy()函数 原型声明:char strcpy(char dest, const char *src);功能:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间 说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。 返回指向dest的指针。 2.strcpy_s() _s函数是微软自己加的, 不是标准库, 最直观
1.1、strcpy 函数原型char *strcpy(char *dest, const char *src) 需要注意的是如果目标数组 dest 不够大,而源字符串的长度又太长,可能会造成缓冲溢出的情况,所以在实际使用一定要注意dest的空间一定要大于strlen(src)+1,最后有一个结束符‘\0’ 1.2、strncpy 函数原型char *strncpy(char *dest, const char *src, size_t n) 把 src所指向的字符串
C++类用三个特殊的成员函数复制构造函数、赋值操作符和析构函数 来决定类对象之间的初始化或赋值时发生什么。所谓的“复制控制”即通过这三个成员函数控制对象复制的过程。本篇文章将介绍复制构造函数。   复制构造函数   复制构造函数是什么   复制构造函数首先是一个构造函数,它同所有其他的构造函数一样与类同名,没有返回值。它有一个的参数,是该类类型的引用(一般将它声明为const,源于用于赋值的对象一般不用改变它本身的值)。于是复制构造函数的原型为: class BOOK public: BOOK(const BOOK& rhs); //构造函数一 BOOK(string &
void fgo(char c[],char d[]); char a[]="听我说谢谢你~",b[]="你要结婚啦~"; printf("a=%s\n",a);printf("b=%s\n",b); printf("将a复制到b:"); fgo(a,b); printf("\na=%s\n",a);printf("b=%s\n",b); void fgo(char c[],char.