当前位置: 首页 > news >正文

【C语言】字符串函数strlen #strcpy #strcmp #strcat #strstr及其模拟实现

        在C语言中,有一种特殊的数据类型,即字符串类型。C  并没有专门定义一个字符串类型,这对我们使用字符串造成了一定的麻烦。但是,C标准库<string.h> 中定义了各种字符串函数,这对于我们来说是一件值得庆幸的事情。

        本片着重讲解一些常用的字符串函数,以及它们的实现方法思路,并尝试自己独自模拟实现它们,以便于对字符串操作有更深的理解。


字符串简介 

        C语言中的字符串类型是以字符数组的形式表示的,即用一组字符数组来表示一个字符串,例如:

char str[10] = "hello"; // 定义一个长度为10的字符数组,初始化为"hello"

        其中,char表示字符类型,str表示字符数组的名称,10表示字符数组的长度,"hello"表示初始值。

        C语言中的字符串还可以使用字符串指针来表示,例如:

char *str = "hello"; // 定义一个指向字符数组的指针,指向"hello"

        其中,char *表示字符指针类型,str表示指针变量的名称,"hello"表示字符串常量,也就是一段字符数组的初始值。注意,使用字符串指针表示字符串时,需要保证指针指向的字符串常量是合法的,并且不能修改它的值,否则会发生未定义的行为。

 

头文件<string .h> 

        <string.h>是C语言标准库中的一个头文件,提供了一些字符串处理相关的函数和宏。

统一说明:

统一说明:

        养成良好的代码习惯:

        1.在实现字符串操作的时候,如果不希望字符串被改变,在函数形参前加上const,提高代码的健壮性。

        2.使用指针前判断将要解引用的指针是否是空指针,assert进行断言。

 

        对于每一个函数使用的注意事项放在每个函数模拟实现的末尾! 


strlen

作用:

返回字符串中  ‘\0‘  之前的所有字符数。

函数原型:

 

函数参数: 

        str是存放要操作的字符串的地址的指针

返回值类型:

        size_t(表示无符号整型)的理解:由实际意义,返回的字符数不会是负数;并且看到 size_t的size,就可以知道此类型是表示大小,尺寸的类型。 

模拟实现:

 法一:计数变量法:

#include<stdio.h>int my_strlen(char*p)
{int c = 0;while(*p){c++;p++;}return c;
}
int main()
{char arr[] = "ahufkh";printf("%d",my_strlen(arr));return 0;
}

法二:

指针相减法:


#include<stdio.h>int my_strlen(char* p)
{char* start = p;while(*p){p++;}return p - start;
}
int main()
{char arr[] = "ahufkh";printf("%d",my_strlen(arr));return 0;
}

 

  对size_t的补充:

        易错点:       

        对于无符号整数,运算结果小于0,由于不存在符号位,所以结果会被当做很大的整数。

        e.g.1

#typedef unsigned int uint
int main()
{uint a = 3;uint b = 6;uint c = a - b;//此时c是很大的整数}

        结果为负值,c被当作很大的整数。

 


strcpy

作用:

        将源字符串拷贝到目的地字符串。

函数原型:

函数参数:

        1.char* dest即目的地字符串,const char* sou 即源字符串。

返回值类型:

        返回拷贝后目的地字符串的地址。

模拟实现:

 

#include<stdio.h>
#include<assert.h>
char*  my_strcpy(char* dest,const char* sou)
{char* s = dest;assert(dest && sou);while(*dest++ = *sou++){;}return s;
}
int main()
{char arr1[] = "abcdefghijk";char arr2[] = "iii";char* s = my_strcpy(arr1,arr2);printf("%s",s);return 0;
}

        (记得const与assert断言)

 注意:

1.sou字符串必须有  ’\0‘  作为结尾。

2.dest字符串必须足够大,防止越界;并且可修改,不是常量字符串。


 strcat

作用:

        将源字符串拷贝到目的地字符串中,并且源字符串的的一个字符覆盖掉目的地字符串中的  ’\0‘  。

函数原型:

 函数参数:

        1.const 修饰的源字符串和目标字符串。

返回值类型:

        copy后的目标字符串的地址。

模拟实现:

#include<stdio.h>
#include<assert.h>
char* my_strcat(char* dest,const char* sou)
{char* start = dest;assert(dest && sou);while(*dest){dest++;}while(*dest++ = *sou++){;}return start;
}
int main()
{char arr[50] = "abc";char arr1[] = "defg";char* p = my_strcat(arr,arr1);printf("%s",p);return 0;
}

注意:

        1.cou与dest字符串必有  '\0'  作为结束标志。

        2.目标字符串必须足够大。

        3.strcat的两个函数参数不能相同。(一个字符串对自己追加,那么一开始,自己的结束表示就被覆盖了,这样将造成死循环。)


 strcmp

作用:

        比较两个字符串的大小;

函数原型:

 函数参数:

        两个const 修饰的字符串

返回值类型:

        整型数值——

         if第一个>第二个,返回值>0;

        if第一个=第二个,返回值=0;

        if第一个<第二个,返回值<0。

 模拟实现:

#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* str1,const char* str2)
{while(*str1 == *str2){if(*str1 == '\0'){return 0;}str1++;str2++;}return str1 -str2;
}
int main()
{char arr1[] = "abcde";char arr2[] = "abb";int ret = my_strcmp(arr1,arr2);if(ret > 0){printf("arr1 > arr2");}else if(ret == 0){printf("arr1 == arr2");}else{printf("arr1 < arr2");}return 0;
}

strstr

作用:

        返回str2在str1中第一次出现的位置;若找不到,则返回NULL;字符串的比较匹配不包含  '\0'  ,但是以  ' \0 '  为结束标志。

函数原型:

        

函数参数:

        查找的样本字符串和被查找的目标字符串。

返回值类型:

        str1中str2第一次出现的位置。

模拟实现:

#include<stdio.h>
#include<assert.h>
char* my_strstr(const char* p1,const char* p2)
{assert(p1 && p2);const char* cur = p1;const char* s1 = NULL;const char* s2 = NULL;while(*cur){s1 = cur;s2 = p2;while(*s1 == *s2 && s1 && s2){s1++;s2++;}if(*s2 == '\0'){return (char*)cur;}cur++;}return NULL;
}
int main()
{char arr1[] = "abbbbbcdefg";char arr2[] = "bbc";char* p = my_strstr(arr1,arr2);printf("%s",p);return 0;
}

 思路:

        对于停下来的情况,有:

        1.s1找到'\0'的同时s2也找到'\0',则找到;若s2没有到'\0',则没有找到;

        2.s2到'\0',找到。

        3.*s1 != *s2

        于是,对s1中的每一个位置向后匹配s2的字符,如果有一个匹配失败,则从s1的下一个位置开始匹配。


完~

未经作者同意禁止转载

相关文章:

【C语言】字符串函数strlen #strcpy #strcmp #strcat #strstr及其模拟实现

在C语言中&#xff0c;有一种特殊的数据类型&#xff0c;即字符串类型。C 并没有专门定义一个字符串类型&#xff0c;这对我们使用字符串造成了一定的麻烦。但是&#xff0c;C标准库<string.h> 中定义了各种字符串函数&#xff0c;这对于我们来说是一件值得庆幸的事情。…...

递归实现组合型枚举

递归实现组合型枚举 #include<iostream> #include<vector>int n, m; std::vector<int>res; bool st[30];void Print() {for(int i0;i<res.size();i){printf("%d ",res[i]);}puts(""); }void dfs(int num) {if (res.size() m){Print(…...

SCAU:1065 数组中的指针

1065 数组中的指针 时间限制:1000MS 代码长度限制:10KB 提交次数:3436 通过次数:1692 题型: 编程题 语言: G;GCC Description 设有如下数组定义&#xff1a; int a[3][4]{{1,3,5,7},{9,11,13,15},{17,19,21,23}}; 计算下面各项的值&#xff08;设数组a的首地址为2000&…...

找不到msvcp110.dll如何修复?分享5个亲测有效的修复方法

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“msvcp110.dll丢失”。这个错误通常发生在运行某些程序时&#xff0c;系统无法找到所需的动态链接库文件。那么&#xff0c;msvcp110.dll到底是什么呢&#xff1f;它又有什么作用&#xff1…...

LeetCode刷题笔记第80题:删除有序数组中的重复项 II

LeetCode刷题笔记第80题&#xff1a;删除有序数组中的重复项 II 题目&#xff1a; 删除升序数组中超过两次的元素后的数组长度 想法&#xff1a; 使用快慢指针的方法完成&#xff0c;使用快指针遍历整个数组&#xff0c;使用慢指针完成相同元素最多保留两个。在快指针遍历到…...

【开源存储】minio对象存储部署实践

文章目录 一、前言1、介绍说明2、部署方式3、冗余模式4、约束限制4.1、规格参数4.2、API支持a、minio不支持的Amazon S3 Bucket APIb、minio不支持的Amazon S3 Object API 二、部署说明1、软件安装2、minio单机部署3、minio分布式部署3.1、前置条件3.2、开始运行3.3、操作说明 …...

Java编程强化练习(二)

表达式计算&#xff08;支持空格&#xff0c;连乘&#xff0c;连除&#xff09;&#xff08;选做题&#xff0c;不计分&#xff09; 【问题描述】 从标准输入中读入一个整数算术运算表达式&#xff0c;如5 - 1 * 2 * 3 12 / 2 / 2 。计算表达式结果&#xff0c;并输出。 …...

Redis的高可用模式

1. 什么是高可用&#xff1f; 高可用&#xff08;High Availability, HA&#xff09;是指在信息技术中确保系统、服务或应用程序在绝大多数时间内都是可操作和可访问的能力。这通常涉及以下几个关键方面&#xff1a; 最小化停机时间: 高可用系统的目标是减少因硬件故障、系统升…...

非功能关键知识总结(一)

文章目录 一、稳定性(一)、服务级别协议1、SLA2、OLA3、UC (二)、可用性指标(三)、突发事件等级 三、质量(一)、千行代码缺陷数量(二)、软件质量模型的发展(三)、产品质量模型 四、安全(一)、网络安全 五、灾备(一)、灾备指标(二)、灾难恢复等级(三)、容灾技术分类 一、稳定性 …...

时间序列趋势检验相关检验方法:斜率法、Cox-Stuart检验、Mann-Kendall检验

文章目录 1.斜率法1.1.原理1.2.优缺点1.3.Python代码2.Cox-Stuart检验2.1.原理2.2.优缺点2.3.Python代码3.Mann-Kendall 检验3.1.原理3.1.1.假设前提3.1.2.趋势检验3.1.3.S到Z的变换原理3.1.4.Var(s)是如何得到的3.1.5.衡量趋势的指标:倾斜度...

Redis相关知识

yum安装redis 使用以下命令&#xff1a;直接将redis安装到Linux服务器&#xff08;Xshell&#xff09;中 yum -y install redis 启动redis 使用以下命令&#xff0c;以后台运行方式启动redis redis-server /etc/redis.conf & 操作redis 使用以下命令启动redis客户端 redis-…...

数据管理系统-week10-自由访问控制

文章目录 前言一、用户管理用户管理语句介绍二、数据库管理三、特权(重点考点)Administrative (global) privileges数据库特权表权限列权限四、角色参考文献前言 这节课主要讲了用户管理数据库的具体语句,数据库特权当中的全局特权,数据库特权,表特权与列特权的使用与注意…...

Python遥感开发之批量拼接

Python遥感开发之批量拼接 1 遥感图像无交错的批量拼接2 遥感图像有交错的批量拼接 前言&#xff1a;主要借助python实现遥感影像的批量拼接&#xff0c;遥感影像的批量拼接主要分为两种情况&#xff0c;一种是遥感图像无交错&#xff0c;另一种情况是遥感图像相互有交错。具体…...

【bat】批处理脚本大全

目录 1.概述 2.变量 3.运算符 3.2.重定向运算符 3.3.多命名运算符 3.4.管道运算符 4.命令 4.1.基本命令 4.2.参数传递 4.3.查看脚本内容 4.4.注释 4.5.日期和时间 4.6.启动脚本 4.7.调用其他bat 4.8.任务管理 4.8.1.任务列表查看 4.8.2.任务终止 4.9.文件夹 …...

java设计模式学习之【单例模式】

文章目录 引言单例模式简介定义与用途实现方式&#xff1a;饿汉式懒汉式 UML 使用场景优势与劣势单例模式在spring中的应用饿汉式实现懒汉式实现数据库连接示例代码地址 引言 单例模式是一种常用的设计模式&#xff0c;用于确保在一个程序中一个类只有一个实例&#xff0c;并且…...

UWB高精度定位系统项目源码

在现代社会中&#xff0c;精准定位技术对于各行各业都至关重要。为了满足对高精度定位的需求&#xff0c;超宽带&#xff08;Ultra-Wideband, UWB&#xff09;技术应运而生。UWB高精度定位系统以其出色的定位精度和多样化的应用领域而备受关注。本文将深入探讨UWB高精度定位系统…...

WPF Live Charts2 自学笔记

文章目录 前言实现效果微软平台的历史问题 WPF 项目搭建Nuget添加额外框架添加项目初始化livecharts配置其它LiveCharts2 案例简单案例Demo示例ViewViewModel GPU渲染 Github地址仓库 前言 LiveChart 是C# 上面很受欢迎的统计图 UI控件。最近在学WPFhalcon开发&#xff0c;想想…...

大小堆的实现(C语言)

目录 前言 一种完全二叉树&#xff1a;堆 堆的概念 堆的性质 建堆的时间复杂度 建堆的空间复杂度&#xff1a; 小堆的实现 必要补充 堆的初始化 堆的销毁 向上调整算法 堆的插入 向下调整算法 堆的删除 获取堆顶元素 获取堆中元素个数 堆的判空 最终代码 He…...

Linux系统之centos7编译安装Python 3.8

前言 CentOS (Community Enterprise Operating System) 是一种基于 Red Hat Enterprise Linux (RHEL) 进行源代码再编译并免费提供给用户的 Linux 操作系统。 CentOS 7 采用了最新的技术和软件包&#xff0c;并提供了强大的功能和稳定性。它适用于各种服务器和工作站应用场景&a…...

Lambda表达式与方法引用

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 引子 先来看一个案例 …...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

AGain DB和倍数增益的关系

我在设置一款索尼CMOS芯片时&#xff0c;Again增益0db变化为6DB&#xff0c;画面的变化只有2倍DN的增益&#xff0c;比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析&#xff1a; 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...

iview框架主题色的应用

1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题&#xff0c;无需引入&#xff0c;直接可…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

R 语言科研绘图第 55 期 --- 网络图-聚类

在发表科研论文的过程中&#xff0c;科研绘图是必不可少的&#xff0c;一张好看的图形会是文章很大的加分项。 为了便于使用&#xff0c;本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中&#xff0c;获取方式&#xff1a; R 语言科研绘图模板 --- sciRplothttps://mp.…...

在树莓派上添加音频输入设备的几种方法

在树莓派上添加音频输入设备可以通过以下步骤完成&#xff0c;具体方法取决于设备类型&#xff08;如USB麦克风、3.5mm接口麦克风或HDMI音频输入&#xff09;。以下是详细指南&#xff1a; 1. 连接音频输入设备 USB麦克风/声卡&#xff1a;直接插入树莓派的USB接口。3.5mm麦克…...

小木的算法日记-多叉树的递归/层序遍历

&#x1f332; 从二叉树到森林&#xff1a;一文彻底搞懂多叉树遍历的艺术 &#x1f680; 引言 你好&#xff0c;未来的算法大神&#xff01; 在数据结构的世界里&#xff0c;“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的&#xff0c;它…...