详解字符串函数<string.h>(上)
1. strlen函数的使用和模拟实现
size_t strlen(const char* str);
1.1 函数功能以及用法
字符串长度
strlen函数的功能是计算字符串的长度。在使用时,要求用户传入需要计算长度的字符串的起始位置,并返回字符串的长度。
#include <stdio.h>
#include <string.h>int main()
{char arr[] = "abcdef";int len = strlen(arr);printf("%d\n", len);return 0;
}
1.2 函数的原理
该函数在得到字符串的起始位置之后,会从该起始位置开始依次向后检索并计数,直到遇到'\0'为止。
1.3 注意事项
1. 字符串以 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前⾯出现的字符个数(不包 含 '\0' )。
2. 参数指向的字符串必须要以 '\0' 结束。
3. 注意函数的返回值为size_t,是无符号的( 易错 )
针对第三点,我们给出以下示例
#include <stdio.h>
#include <string.h>
int main()
{const char* str1 = "abcdef";const char* str2 = "bbb";if(strlen(str2)-strlen(str1)>0)//出错{printf("str2>str1\n");} else{printf("srt1>str2\n");}return 0;
}
由于strlen函数返回值的类型为“size_t”(unsigned int),所以两个strlen函数返回值相减,得到的结果的类型也是“size_t”,而该类型的数据一定会是大于等于零的,这与我们的代码所表达的意思不一致。
1.4 模拟实现
strlen的实现较为简单,所以这里给出三种实现方式:
1.4.1 计数器
在函数内部创建一个计数器,用以记录字符的个数
size_t my_strlen1(const char* str)
{assert(str);size_t count = 0;//计数器while(*str != '\0'){count++;str++;}return count;
}
1.4.2 指针-指针
size_t my_strlen2(const char* str)
{assert(str);const char* strx = str;while(*strx != '\0'){strx++;}return strx - str;//指针-指针
}
1.4.3 递归
size_t my_strlen3(const char* str)
{assert(str);if(*str == '\0')return 0;elsereturn 1 + my_strlen3(str+1);
}
2. strcpy函数的使用和模拟实现
char* strcpy(char * destination, const char* source);
2.1 函数功能以及用法
字符串拷贝
该函数会把“source”指向的字符串拷贝到“destination”指向的字符数组数组中,包括'\0'。在使用时,要求用户分别传入目标数组的起始地址和源字符串的起始地址,并返回目标数组的起始地址
#include <stdio.h>
#include <string.h>int main()
{char name[20] = {0};strcpy(name, "zhangsan");printf("%s\n", name);return 0;
}
2.2 函数的原理
“destination”和“source”依次逐字节移动,每次移动前将“source”指向的字符拷贝到“destination”指向的空间,直到将'\0'拷贝到目标数组中为止。
2.3 注意事项
1. 源字符串必须以 '\0' 结束。
2. 会将源字符串中的 '\0' 拷⻉到⽬标空间。
3. ⽬标空间必须⾜够⼤,以确保能存放源字符串。
4. ⽬标空间必须可修改。比如目标空间是处存放的是一个常字符串或者被const修饰的字符数组。
#include <stdio.h>
#include <string.h>int main()
{const char* p = "abcdef";char arr[] = "bit";strcpy(p, arr);return 0;
}
2.4 模拟实现
char* my_strcpy(char* dest, const char* src)
{assert(dest && src);char* ret = dest;while(*dest++ = *src++);return ret;
}
3. strcat函数的使用和模拟实现
char* strcat(char* destination, const char* source);
3.1 函数功能以及用法
字符串追加
该函数会将“source”指向的字符串追加到“destination”指向的字符数组的后面,原本的'\0'会被覆盖,源字符串的'\0'会被一起追加到字符数组之后(某些实现中可能是额外添加的'\0')。在使用时,要求用户分别传入目标数组的起始地址和源字符串的起始地址,并返回目标数组的起始地址。
#include <stdio.h>
#include <string.h>int main()
{char arr1[20] = "hello ";strcat(arr1, "world!");printf("%s\n", arr1);return 0;
}
3.2 函数的原理
首先找到目标数组结尾处的'\0',将其当作目标空间的起始地址的话,接下来的步骤就与strcpy相同了。
3.3 注意事项
1. 源字符串必须以 '\0' 结束。
2. ⽬标字符串中也得有 \0 ,否则没办法知道追加从哪⾥开始。
3. ⽬标空间必须有⾜够的⼤,能容纳下源字符串的内容。
4. ⽬标空间必须可修改。
5. 字符串自己给自己追加可能会出错。
#include <stdio.h>
#include <string.h>int main()
{char arr[20] = "hello";strcat(arr, arr);printf("%s\n", arr);return 0;
}

在第一个字符拷贝结束时,arr结尾的'\0'就被覆盖了,这时,strcat函数就不知道追加应该何时停止。
3.4 模拟实现
char* my_strcat(char* dest, const char* src)
{assert(dest && src);char* ret = dest;while(*dest){dest++;}while(*dest++ = *src++);return ret;
}
4. strcmp函数的使用和模拟实现
int strcmp(const char* str1, const char* str2);
4.1 函数功能以及用法
字符串比较
C语言标准规定:
第⼀个字符串⼤于第⼆个字符串,则返回⼤于0的数字 。
第⼀个字符串等于第⼆个字符串,则返回0 。
第⼀个字符串⼩于第⼆个字符串,则返回⼩于0的数字。
#include <stdio.h>
#include <string.h>int main()
{char arr1[20] = "zhangsan";char arr2[] = "zhangsanfeng";int ret = my_strcmp(arr1, arr2);if(ret < 0)printf("<\n");else if(ret == 0)printf("=\n");elseprintf(">\n");return 0;
}
4.2 函数的原理
按下标依次比较两个字符串元素的ascll码值。
4.3 注意事项
好像没什么好注意的。
4.4 模拟实现
int my_strcmp(const char* str1, const char* str2)
{assert(str1 && str2);while(*str1 == *str2){if(*str1 == '\0')return 0;str1++;str2++;}return (*str1 - *str2);
}相关文章:
详解字符串函数<string.h>(上)
1. strlen函数的使用和模拟实现 size_t strlen(const char* str); 1.1 函数功能以及用法 字符串长度 strlen函数的功能是计算字符串的长度。在使用时,要求用户传入需要计算长度的字符串的起始位置,并返回字符串的长度。 #include <stdio.h> #…...
1、docker入门
文章目录 1、tocker简介2、tocker的安装&环境配置2、配置阿里云镜像3、基本命令1、镜像命令2、docker基本命令3、镜像基本命令4、Docker 容器常用命令 1、tocker简介 新一代的虚拟化技术 2、tocker的安装&环境配置 uname -r1、首先查看liunx的内核 yum update -y2、更…...
Qt应用软件【测试篇】cppchecker静态代码检查
文章目录 cppcheker简介下载地址与安装检查项目QT Creator使用CPP Cheker开启检查常见错误总结错误信息说明cppcheker简介 Cppcheck 是一个用于 C/C++ 代码的分析工具。它提供独特的代码分析以检测错误,并专注于检测未定义的行为和危险的编码结构。其目标是仅检测代码中的真实…...
[递推与递归]数的计算
题目描述 给出正整数 n,要求按如下方式构造数列: 只有一个数字 n 的数列是一个合法的数列。在一个合法的数列的末尾加入一个正整数,但是这个正整数不能超过该数列最后一项的一半,可以得到一个新的合法数列。 请你求出ÿ…...
Cocos Creator 3.8.x 后效处理(前向渲染)
关于怎么开启后效效果我这里不再赘述,可以前往Cocos官方文档查看具体细节:后效处理官网 下面讲一下怎么自己定义一个后处理效果,想添加自己的后效处理的话只需要在postProcess节点下添加一个BlitScreen 组件即可,然后自己去添加自…...
【前端素材】推荐优质后台管理系统 Adminity平台模板(附源码)
一、需求分析 1、系统定义 后台管理系统是一种用于管理网站、应用程序或系统的管理界面,通常由管理员和工作人员使用。它提供了访问和控制网站或应用程序后台功能的工具和界面,使其能够管理用户、内容、数据和其他各种功能。 2、功能需求 后台管理系…...
身份证号与姓名实名认证接口-二要素实名认证-C++接口代码
翔云(https://www.netocr.com/idenNoOrd.html)身份证二要素实名认证接口在当今的数字化社会中扮演着至关重要的角色,它不仅守护着网络世界的秩序,也悄然影响着现实生活的点滴。看似普通的身份证号实名认证接口也在悄然守护着人们的…...
笑营宝高校选修课报名考勤系统源码开发方案
一、项目背景与目标 (一)项目背景 随着高等教育的普及和教学模式的不断创新,高校选修课程体系日趋复杂多变。学生对课程选择的自由度提高,使得传统的选课和考勤管理方式变得繁琐且效率低下。目前,许多高校仍然采用纸…...
类型字段定义影响WebApi传值及SqlSugar调用Select创建新对象
ASP.NET Core编写的WebApi,由于输入参数较多,专门定义了输入参数类并设置[FromBody]方式传值,但测试时始终无法通过postman将输入参数值传递给WebApi,condition对象的所有属性值一直都为空。同时在WebApi内部调用SqlSugar查询数据…...
golang 函数式编程库samber/mo使用: IO
golang 函数式编程库samber/mo使用: IO 如果您不了解samber/mo库, 请先阅读第一篇 Option 在函数式编程中,副作用和纯函数是最常见的概念。 IO用来封装IO这类副作用。 什么是副作用 副作用是在计算结果的过程中,改变了系统状态…...
在OceanBase使用中,如何优化因Join估算不准导致执行计划选错的问题
作者:胡呈清,爱可生公司旗下的DBA团队成员,擅长故障分析和性能优化。爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。本文约 1600 字,预计阅读需要 15 分钟。 数据库版本&…...
potplayer安装
官网 解压运行即可...
PostgreSQL 与MySQL 对比使用
一、前言 博主的系统既有 用到MySQL 也有用到PostgreSQL ,之所以用到这两种数据库,主要是现在都是国产替代,虽然说这两款数据库也不是国产的,但是相对开源,oracle是不让用了。所以现在使用比较多的就是这两个关系型数据…...
配置nginx代理访问openai接口
环境: 阿里云硅谷地区服务器,ubuntu22 操作步骤 1.安装nginx apt install nginx2.编辑文件/etc/nginx/sites-enabled/default,内容替换如下 server {listen 80;location / {proxy_pass https://api.openai.com;proxy_set_header Host api.…...
使用Python语言实现一个基于动态数组的序列队列
一、动态数组的实现 首先,我们需要创建一个DynamicArray类,该类将管理我们的动态数组。 动态数组能够动态地调整其大小,以容纳更多的元素。 目录 一、动态数组的实现 代码示例: 二、序列队列的实现 接下来,我…...
面试数据库篇(mysql)- 07索引创建原则与失效及优化
索引创建原则 1). 针对于数据量较大,且查询比较频繁的表建立索引。 2). 针对于常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引。 3). 尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高。 4). 如果是字符…...
《互联网的世界》第三讲-tcp
dns 找到了地址,spf 确定了路径,如何运输数据呢?今天讲 tcp。 计算机网络领域的特定技术是最后当你干这个事时才要用的,我对孩子们这样说,实际上你可以随便看一个快递单子来理解端到端传输协议。 源地址,…...
JOSEF约瑟 JZS-7G-42 AC220V静态可调延时中间继电器 端子式导轨安装15ms-10s
系列型号:JZS-7G-57端子排延时中间继电器;JZS-7G-42X端子排延时中间继电器;JZS-7G-22X端子排延时中间继电器;JZS-7G-21端子排延时中间继电器;JZS-7G-41端子排延时中间继电器;JZS-7G-51端子排延时中间继电器…...
Hudi配置参数优化
1)Commits:表示一批记录原子性的写入到一张表中。 2)Cleans:清除表中不再需要的旧版本文件。 3)Delta_commit:增量提交指的是将一批记录原子地写入MergeOnRead类型表,其中一些/所有数据都可以写入增量日志。 4&…...
适用Java SpringBoot项目的分布式锁
在分布式系统中,常用到分布式锁,它有多中实现方式,如:基于redis,database,zookeeper等。Spring integration组件有这三种服务的分布式锁实现,今天来看看用的比较多的redis和database实现方式。 …...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...
Unity中的transform.up
2025年6月8日,周日下午 在Unity中,transform.up是Transform组件的一个属性,表示游戏对象在世界空间中的“上”方向(Y轴正方向),且会随对象旋转动态变化。以下是关键点解析: 基本定义 transfor…...
32单片机——基本定时器
STM32F103有众多的定时器,其中包括2个基本定时器(TIM6和TIM7)、4个通用定时器(TIM2~TIM5)、2个高级控制定时器(TIM1和TIM8),这些定时器彼此完全独立,不共享任何资源 1、定…...
【大模型】RankRAG:基于大模型的上下文排序与检索增强生成的统一框架
文章目录 A 论文出处B 背景B.1 背景介绍B.2 问题提出B.3 创新点 C 模型结构C.1 指令微调阶段C.2 排名与生成的总和指令微调阶段C.3 RankRAG推理:检索-重排-生成 D 实验设计E 个人总结 A 论文出处 论文题目:RankRAG:Unifying Context Ranking…...
【1】跨越技术栈鸿沟:字节跳动开源TRAE AI编程IDE的实战体验
2024年初,人工智能编程工具领域发生了一次静默的变革。当字节跳动宣布退出其TRAE项目(一款融合大型语言模型能力的云端AI编程IDE)时,技术社区曾短暂叹息。然而这一退场并非终点——通过开源社区的接力,TRAE在WayToAGI等…...
虚幻基础:角色旋转
能帮到你的话,就给个赞吧 😘 文章目录 移动组件使用控制器所需旋转:组件 使用 控制器旋转将旋转朝向运动:组件 使用 移动方向旋转 控制器旋转和移动旋转 缺点移动旋转:必须移动才能旋转,不移动不旋转控制器…...
【QT控件】显示类控件
目录 一、Label 二、LCD Number 三、ProgressBar 四、Calendar Widget QT专栏:QT_uyeonashi的博客-CSDN博客 一、Label QLabel 可以用来显示文本和图片. 核心属性如下 代码示例: 显示不同格式的文本 1) 在界面上创建三个 QLabel 尺寸放大一些. objectName 分别…...
