【C语言】字符串函数的介绍一(strlen、strcpy、stract)

news2024/10/7 18:22:17

前言

这篇文章是对于字符串操作函数、内存函数的比较详细的介绍。
我们都知道,字符串在C语言中使用的特别频繁,但类型里,却没有字符串这种类型,这时,众多的库函数就可以帮助我们灵活地使用字符串了

这篇文章同样适合已经对于字符串有初步了解的朋友,虽然本篇文章会由浅入深的介绍每个函数,并解释出每个函数是如何实现的,但还是建议您有一定的基础。

下图是本篇文章(共两篇)
在这里插入图片描述
话不多说,让我们正式开始吧

strlen

介绍

下图是函数的使用:
从a的地址向后,直到访问到\0结束
返回的是\0之前的元素个数
在这里插入图片描述

而当字符串中无\0之后,就会一直向后访问,直到遇到\0,
返回的是随机值
在这里插入图片描述

模拟实现strlen

共有三种写法,但这里只介绍第一种,对于剩下的两种,我会单独出一篇文章去讲解

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

int my_strlen(const char* str)//使用const是为了保证str指向的元素不被改变
{
	assert(str);
	int count = 0;
	while (*str != '\0')//\0的ASCII码值是0,所以此处可以直接写成while(*str)
	{
		count++;
		str++;
	}
	return count;
}

int main()
{
	char arr = "abcdef";
	int len = my_strlen(arr);
	printf("%zd\n", len);

	return 0;
}

小测试

下面代码的运行结果是什么

int main()
{
	if (strlen("abc") - strlen("abcdef") > 0)
	{
		printf("11\n");
	}
	else
	{
		printf("00\n");
	}

	return 0;
}

答案

11

讲解

size_t strlen( const char * str );
这是strlen函数的定义

它的返回类型是size_t,那么问题肯定就出在这里了

那么接下来就了解一下size_t
我们转到定义之后,会发现size_t就是unsigned int:无符号整型

typedef unsigned __int64 size_t;

那么再回到这道题,

strlen("abc") == 3
strlen("abcdef") == 6
strlen("abc") - strlen("abcdef") == -3

-3 的类型是无符号整型,所以转换成补码是一个很大的数字,所以判断条件为真

提示:使用int或者size_t来定义strlen时,二者都可,
此处库函数返回值之所以定义成size_t类型,是因为数组的长度不可能是负数
size_t表明函数不会返回负数
int则更方便阅读和理解,二者都可以

strcpy

介绍:

strcpy(arr1, arr2);//arr1是目的地地址,arr2是源字符串,arr2必须以‘\0’结尾

把后者指向的内容,拷贝到前者指向的空间里

此处不可以用arr1 = arr2,把地址赋给地址这种操作,很奇怪

拷贝过程

在这里插入图片描述

注意:
arr2中的\0也必须要拷贝进arr1,如图:
在这里插入图片描述

模拟实现

实现过程

函数传参

在这里插入图片描述

实现拷贝

void my_strcpy(char* dest, const char* src)
{
	assert(dest);
	assert(src);
	while (*src)
	{
		*dest++ = *src++;
	}
	*dest = *src;
}
优化拷贝
my_strcpy(char* dest, const char* src)
{
	assert(dest);
	assert(src);
	while (*dest++ = *src++)
	//表达式的结果是*src,而当*src为\0时,先赋值,再判断,判断结果为假,跳出循环,拷贝结束
	{
		;
	}
}

返回类型

函数定义中,返回类型是char*

char* strcpy(char* destination, const char* source);

我们在函数完成拷贝后,还需要返回s1的首元素地址,来帮助我们找到拷贝之后的字符串,所以我们还需要单独创建一个变量来存储数组s1的首元素地址,来确保我们能找到这个数组。

最终代码:

char* my_strcpy(char* dest, const char* src)
//目标地址发生变化,而源头地址不发生变化,
//所以src前使用const,dest不使用const(要保证目标空间可改)
{
	assert(dest);
	assert(src);
	char* ret = dest;
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}

int main()
{
	char arr1[] = "abcdefghi";
	char arr2[] = "hello";
	
	char* ret = my_strcpy(arr1, arr2);
	printf("%s\n", arr1);
}

strcat

函数定义

char* strcat(char* strDestination, const char* strSource);

作用:把arr2追加到arr1里,首先找到arr1中的\0,将其替换成arr2的首元素,之后向后追加,直到追加完\0结束。

错误示例如下:

int main()
{
	char arr1[] = "hello";
	char arr2[] = "world";
	strcat(arr1, arr2);

	return 0;
}

数组arr1空间不够大,直接越界访问,程序报错。

模拟实现

对于my_strcpy函数,需要实现两个功能:
首先需要找到目的字符串(arr1)中的\0
之后进行追加(拷贝)

找\0

while (*dest != '\0')
{
	dest++;
}

追加

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

返回值

此处返回的仍应该是arr1的首元素地址,以便于我们找到字符串arr1
返回类型就是char*

完整代码

char* my_strcat(char* dest, const char* src)
{
	assert(dest && src);
	char* ret = dest;
	while (*dest != '\0')
	{
		dest++;
	}
	while (*dest++ = *src++)
	{
		;
	}
	return ret;

}

小技巧

对于部分库函数,我们可以找到他们是如何实现的
具体操作方法如下:
找到对应的路径、找到要查看的头文件,直接用VS运行即可在这里插入图片描述
这里以strcat为例子
在这里插入图片描述
这就是我们模拟实现中做的三步:
寻找\0
追加字符串
返回数组首元素地址

结语

因为文章长度,这篇文章只介绍三个函数,下篇文章会继续介绍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/882256.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

派克Parker伺服驱动器 高性能电机控制系统的应用详解

派克Parker伺服驱动器及电机是一种高性能的电机控制系统&#xff0c;广泛应用于机器人、医疗设备、工业自动化和航空航天等领域。具有高精度、高可靠性、高动态性能、低噪音、低振动、低能耗等优点&#xff0c;采用了先进的数字信号处理技术&#xff0c;能够实现高精度的位置控…

【es6】函数柯里化(Currying)

柯里化&#xff08;Currying&#xff09;&#xff1a;把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数&#xff0c;并且返回接受余下的参数且返回结果的新函数。 柯里化由 Christopher Strachey 以逻辑学家 Haskell Curry 命名的&#xff0c;它是 Mos…

第四章:前端框架Vue基础入门

文章目录 一、Vue框架概述1.1 声明响应式的数据 二、Vue内置指令2.1、条件渲染指令v-if/v-show2.2 v-for: 列表渲染2.3、v-text/v-html 模板指令2.4 v-on:事件监听器2.6 动态绑定v-bind2.7 v-model表单元素值绑定 三、计算属性与监视3.1 计算属性computed3.2 watch侦听器3.3 wa…

摆脱焦虑,释放技术人的潜能!

引言 在这个瞬息万变的时代&#xff0c;每个人都或多或少会面临职场生涯中的焦虑与迷茫。这种焦虑具有时代性特质&#xff0c;既源于对自我的疑惑&#xff0c;也对这个变化太快的世界感到不安。 对于技术从业者来说&#xff0c;科技变革加速带来的冲击尤为强烈。面对日新月异的…

【Visual Studio Code】--- Win11 C盘爆满 修改 Code 插件数据和缓存的保存路径

Win11 C盘爆满 修改 Code 插件数据和缓存的保存路径 一、概述二、修改 Code 插件数据和缓存的保存路径 一、概述 一个好的文章能够帮助开发者完成更便捷、更快速的开发。书山有路勤为径&#xff0c;学海无涯苦作舟。我是秋知叶i、期望每一个阅读了我的文章的开发者都能够有所成…

天津和则百顺国际贸易有限公司:连接中国和印度汽车品牌的国际间贸易桥梁

全球汽车产业正迎来前所未有的变革,而中国和印度作为两大新兴市场,其汽车品牌也在逐步崭露头角。在这个背景下,天津和则百顺国际贸易有限公司(以下简称和则百顺)以其出色的贸易服务,成为了连接中国和印度汽车品牌的重要国际间贸易桥梁。 中国和印度汽车市场的崛起 中国和印度分…

STM32CubeMx驱动SG90(360度)

SG90 360度是一直转 而不是给定角度转的 pwm周期必须为20ms 0.5ms占空比 反转速度最大 1.5ms 不转 2.5ms正转速度最大

如何实现安全上网

l 场景描述 政府、军工、科研等涉密单位或企业往往要比其他组织更早接触高精尖的技术与产品&#xff0c;相对应的数据保密性要求更高。常规的内外网物理隔离手段&#xff0c;已经满足不了这些涉密单位的保密需求&#xff0c;发展到现在&#xff0c;需求已经演变成既要保证网络…

学习笔记十四:K8S最小调度单元POD概述

K8S最小调度单元POD概述 k8s核心资源Pod介绍Pod是什么Pod如何管理多个容器Pod网络Pod存储代码自动发版更新收集业务日志 Pod工作方式自主式Pod控制器管理的Pod(防误删除) 如何基于Pod运行应用 k8s核心资源Pod介绍 K8s官方文档&#xff1a;https://kubernetes.io/ K8s中文官方文…

STM32--TIM定时器(3)

文章目录 输入捕获简介频率测量输入捕获通道输入捕获基本结构PWMI的基本结构输入捕获模式测量PWM频率和占空比代码 编码器接口正交编码器工作模式接口基本结构TIM编码接口器测速代码&#xff1a; 输入捕获简介 输入捕获IC(Input Capture)&#xff0c;是处理器捕获外部输入信号…

DDPM: Denoising Diffusion Probabilistic Models

DDPM: Denoising Diffusion Probabilistic Models 去噪扩散模型前向过程-加噪声反向过程-去噪声 去噪扩散模型 论文题目&#xff1a;Denoising Diffusion Probabilistic Models (DDPM) 论文来源&#xff1a;NIPS, 2020 论文地址&#xff1a;https://arxiv.org/abs/2006.11239 论…

ubuntu18.04安装cuda

卸载之前安装的驱动 sudo apt-get purge nvidia*安装驱动 方法1&#xff1a; 查看显卡适配的NVIDIA的驱动 ubuntu-drivers devices安装recommend推荐的版本 sudo apt-get install nvidia-driver-455方法2&#xff1a; 或者直接使用下面命令安装 sudo ubuntu-drivers au…

Python程序设计——函数

学习目标 定义带形参的函数。用实参来调用函数。区分带返回值和不带返回值的函数。使用位置参数和关键字参数调用函数。通过传参数的引用值来传递参数。开发可重用代码来模块化程序&#xff0c;使程序易读、易调试和易维护。为可重用函数创建模块。决定变量的作用域。定义带默认…

纷享销客位列“2023企业客户关系管理(CRM)服务TOP10”第一名

近日&#xff0c;《互联网周刊》&eNet研究院发布“2023企业客户关系管理(CRM)服务TOP10”榜单&#xff0c;纷享销客连接型CRM凭借出色的产品实力和服务实践&#xff0c;位居 CRM企业排名首位。 2023年&#xff0c;穿越周期&#xff0c;用数字化的力量重塑企业经营与增长的逻…

cesium加载天地图

成果图 源码 const tiandituTk 你的tokenvar viewer new Cesium.Viewer("cesiumContainer", {imageryProvider: new Cesium.WebMapTileServiceImageryProvider({url: "http://t0.tianditu.com/img_w/wmts?servicewmts&requestGetTile&version1.0.0&a…

Win10设置代理操作步骤

1、依次点击打开控制面板--》网络和internet-》internet选项 2、选择“连接”--》点击打开局域网设置 3、勾选“为LAN使用代理服务器”&#xff0c;并根据自己需要设置地址和端口&#xff0c;点击【确定】按钮保存即可 4、使用完后千万记得关闭代理&#xff08;即取消勾选上一步…

alertmanager创建nginx-ingress basic auth鉴权

步骤 生成密码 printf "admin:$(openssl passwd -crypt xxxxxx)\n" >> auth 创建新的 Kubernetes 密钥 kubectl create secret generic basic-auth --from-file auth -n victoria-metrics 修改 ingress 以使用 secret 中的凭证来实现基本身份验证 编辑 P…

RabbitMQ和JMeter,一个完美的组合!优化你的中间件处理方式

RabbitMQ是实现了高级消息队列协议&#xff08;AMQP&#xff09;的开源消息中间件&#xff0c;它是基于Erlang语言编写的&#xff0c;并发能力强&#xff0c;性能好&#xff0c;是目前主流的消息队列中间件之一。 RabbitMQ的安装可参照官网&#xff08; https://www.rabbitmq.c…

每日汇评:黄金在 200 日移动平均线附近似乎很脆弱,关注美国零售销售

1、金价预计将巩固其近期跌势&#xff0c;至 6 月初以来的最低水平&#xff1b; 2、对美联储再次加息的押注继续限制了贵金属的上涨&#xff1b; 3、金融市场现在期待美国零售销售报告带来一些有意义的推动&#xff1b; 周二金价难以获得任何有意义的牵引力&#xff0c;并在…

JAVA毕业设计094—基于Java+Springboot+Vue的人事管理系统(源码+数据库+8000字论文)

基于JavaSpringbootVue的人事管理系统(源码数据库8000字论文)094 一、系统介绍 本系统前后端分离 本系统分为管理员、HR、员工三种角色 用户角色包含以下功能&#xff1a; 登录、个人培训、个人奖惩、个人调动、员工打卡、个人中心、密码修改、在线聊天 HR角色包含以下功…