【C/C++】C语言复制字符串及复制函数汇总(strcpy()/memcpy()/strncpy()/memmove())

2023-05-16

目录:

  • strcpy()
    • 举例:
  • memcpy()
    • 举例:
  • strncpy()
    • 举例:
  • memmove()
    • 举例:

我们首先来考虑一个简单的问题,我们定义了一个字符串,然后想要复制这个字符串,在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.

在这里插入图片描述
请添加图片描述
请添加图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【C/C++】C语言复制字符串及复制函数汇总(strcpy()/memcpy()/strncpy()/memmove()) 的相关文章

随机推荐

  • 安装Rust(Windows 10 与 CentOS7)

    注 xff1a 安装及下载需要科学上网 官网下载地址 xff1a Install Rust Rust Programming Language Window安装Rust 0 前提条件 安装C 43 43 编译工具 xff08 如下图所示 x
  • 【辅助驾驶】透视变换、仿射变换(包含鸟瞰图、俯视图、正视图)[3]——汽车全景环视系统

    一 效果 4个不同方向的相机 xff0c 将其鸟瞰变化后 xff0c 进行拼接 xff0c 得到车辆及周围区域的鸟瞰视角图 二 处理流程 1 相机的标定和图片校正 xff1b 2 图像拼接 xff1b 3 拼接缝消除 xff1b 4 移植到
  • 玩客云刷Armbian详细教程

    网上放出了很多关于玩客云的刷机玩法 xff0c 有电视盒子 复古游戏机 Armbian Linux操作系统搭建自己的私有云 可玩性还是很高的 xff0c 而且价格还便宜就入手了一台 下面记录一下我的玩客云折腾之旅 xff0c 机器刷了Arm
  • 原创分析| 入门或者转行音视频,应该要怎么做?

    要不要从事音视频开发 这一两年因为该死的疫情 xff0c 让短视频 超高清视频和实时音视频反而成为需求风口 我的看法当然是觉得音视频这个行业还可以 xff0c 而且从我自己的观察来看 xff0c 做音视频的现在普遍年龄都在 30 43 了
  • while(a<b<c)怎么理解?

    首先计算a lt b 是否成立 xff0c 再计算1 lt c或 0 lt c span class hljs keyword int span main span class hljs keyword int span a 61 span
  • C判断字符输入是否为指定字符串

    题目要求 xff1a 设定口令为 yulingxi 请求输入 xff0c 如果错误循环输入直至正确为止 1 xff0c 偷懒用strcmp 的做法 xff1a span class hljs preprocessor define CRT
  • 犀哥教你用C写贪吃蛇

    一 xff0c 涉及知识点 xff1a 结构体链表 xff0c 动态分配内存 xff0c 键盘输入检测 xff0c 设置光标 二 xff0c 实现逻辑 1 xff0c 可以设置光标 xff0c 就能实现制定位置打印制定符号 2 xff0c
  • C++类的默认继承方式为保护继承

    二义性 xff1a 就是指取值不明确 xff0c 比如下面例子中的D3同时继承与父类D1 D2 而两个父类当中都有成员变量k 此时如果想要用D3的对象 xff0c 访问父类的成员变量K xff0c 则需要加上相应的域名才能访问 并且只有在继
  • 学习笔记(三) 解决Python3.X pycharm中报No module named 'PIL'

    PIL全称Python Imaging Library xff0c 翻译过来就是Python图像处理库 如果报了标题的错误 xff0c 说明在程序涉及图片时少了这个库 解决方法很简单 xff1a 打开命令行 xff1a pip instal
  • 解释一下为啥负数的取值范围比整数要多一个

    这里有一个0值的差别 以最简单的单字节char型为例 占8位 xff0c 最高位为符号位 这样0值就有了 0000 0000 正零 1000 0000 负零 两种 从数学角度上 xff0c 是没区别的 xff0c 可是用两种形式表示一个数
  • 位运算符打印补码的问题

    int a i scanf d amp a getchar char data 61 1 lt lt 7 for i 61 0 i lt 8 i 43 43 data amp a putchar 1 putchar 0 a lt lt 61
  • socket网络编程的一些基础知识

    目录 xff1a 1 什么是套接字 xff1f 2 Internet 套接字的两种类型 3 网络理论 4 结构体 5 本机转换 6 IP 地址和如何处理它们 7 socket 函数 8 bind 函数 9 connect 函数 10 lis
  • JS如何处理超过32位的整数的位运算

    这个问题是已经毕业的学员李佳问到的 本想在网上查一下给他个答案省事 转念一想 如果网上如果他能在网上查到看的明白的方案应该不至于来问我 索性自己给他解一解 因为貌似这个问题还是有点意思的 首先 要知道为什么这个问题会成为一个问题 这里就不得
  • OpenStack环境部署

    这里写目录标题 虚拟机资源信息部署思路资源规划基础环境配置关闭防火墙和系统按群机制 xff0c 修改主机名安装基础环境依赖包VMnet1网卡配置参数 配置主机映射文件三台节点做免交互配置DNS xff0c 配置控制节点时间同步 系统环境配置
  • Mac OSX 打开原生自带读写NTFS功能[10.11.6 work, 10.14.4不work]

    文章目录 一 放开mac的Rootless机制二 查看磁盘的Volume Name三 更改 etc fstab文件四 做快捷方式五 隐藏桌面移动硬盘快捷方式 xff0c 拖入Finder边栏环境 最近买了一个移动硬盘 xff0c 发现在ma
  • 01. Ubuntu下安装nvidia显卡驱动(安装方式简单)

    文章目录 第一步 获取显卡型号第二步 查看GTX970M显卡驱动第三步 查询支持GTX970M显卡的显卡驱动的其他驱动版本第四步 安装第五步 测试nvidia driver是否安装成功环境参考资料 Ubuntu下安装nvidia显卡驱动 x
  • 动态规划——木棍加工

    题目链接 题目描述 一堆木头棍子共有n根 xff0c 每根棍子的长度和宽度都是已知的 棍子可以被一台机器一个接一个地加工 机器处理一根棍子之前需要准备时间 准备时间是这样定义的 xff1a 第一根棍子的准备时间为1分钟 xff1b 如果刚处
  • NodeBB论坛搭建

    NodeBB是一个开源的Node js论坛 xff0c 下面记录下搭建过程 基于Centos7 64位操作系统 xff1a 1 关闭SELinux vim etc sysconfig selinux 2 安装MongoDB 2 1 新建文件
  • centos 卸载mysql

    1 通过rpm命令卸载 查询已安装的mysql组件 rpm qa grep i mysql 卸载上一步查询到的组件 rpm qa grep i 具体的组件 rpm ev nodeps mysql community release el7
  • 【C/C++】C语言复制字符串及复制函数汇总(strcpy()/memcpy()/strncpy()/memmove())

    目录 strcpy 举例 xff1a memcpy 举例 xff1a strncpy 举例 xff1a memmove 举例 xff1a 我们首先来考虑一个简单的问题 xff0c 我们定义了一个字符串 xff0c 然后想要复制这个字符串 x