字符串函数及其模拟实现

目录

  • strlen
    • 函数介绍
    • 模拟实现
  • strcpy
    • 函数介绍
    • 模拟实现
  • strcat
    • 函数介绍
    • 模拟实现
  • strcmp
    • 函数介绍
    • 模拟实现
  • strncpy
    • 函数介绍
    • 模拟实现
  • strncat
    • 函数介绍
    • 模拟实现
  • strncmp
    • 函数介绍
    • 模拟实现
  • strtok
  • strstr
    • 函数介绍
    • 模拟实现
  • strerror
    • perror

strlen

函数介绍

函数介绍:
字符串以’\0’作为结束标志,strlen函数返回的是在字符串中’\0’前面出现的字符个数(不包含’\0’)。
参数指向的字符串必须要以’\0’ 结束。
注意函数的返回值为size_t,是无符号的

模拟实现

计数方式:

int my_strlen(const char* str)//const修饰且在*左边,保证指向的内容不被改变
{int count = 0;assert(str);while (*str){count++;str++;}return count;
}

不创建变量方式(递归方式)

int my_strlen(const char* str)
{assert(str);if (*str == '\0')return 0;elsereturn 1 + my_strlen(str + 1);
}

指针 - 指针方式

int my_strlen(char* s)
{assert(str);char* p = s;while (*p != '\0')p++;return p - s;
}

strcpy

函数介绍

char* strcpy(char * destination, const char * source )
实现字符串拷贝,左参数是目标字符串的首地址,右参数是源字符串的首地址。
注意:
源字符串必须以‘ \0 ’ 结束。
strcpy会将源字符串的‘ \0 ’拷贝到目标空间中。
目标空间足够大,以确保能存放源字符串。
目标空间必须可变。

如果目标空间不够大,那么就会造成非法写入,然后报错。
拷贝的方法就是从源字符串的第一个字符开始一直到‘ \0 ’,如果源字符串的末尾没有以0结尾,就会一直读取,一直到0,这样就会非法访问。

模拟实现

方式1

void my_strcpy(char* str, const char* src)
{assert(str && src);while (*src){*str = *src;str++;src++;}*str = *src;
}

方式2,将方式1中while循环里面简化、

void my_strcpy(char* str, const char* src)
{assert(str && src);while (*str++ = *src++);
}

后置++,先使用再进行加操作,就算加了括号也是先使用再进行加操作。返回当前值,就是一直到str等于0的时候才停止循环。

方式3,增加返回值

char* my_strcpy(char* str, const char* src)
{char* ret = str;assert(str && src);while (*str++ = *src++);return ret;
}

strcat

函数介绍

char * strcat ( char * destination, const char * source )
字符串追加函数,在目标字符串后面追加源字符串,目标字符串的最后一个‘ \0 ’,被源字符串的第一个字符占据,追加完成以后会再新增一个‘ \0 ’。
注意:
源字符串必须以‘ \0 ’结束
目标字符串中也得有‘ \0 ’,否则没办法知道追加从哪里开始。
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改。

模拟实现

char* my_strcat(char* str, const char* src)
{char* ret = str;assert(str);assert(src);/*while (*str++ != '\0');在str等于0后要退出判断条件,此时会再进行一次加操作,后置加加不会因为要退出循环就不执行。str--;*/while (*str != '\0'){str++;}while (*str++ = *src++);return ret;
}

我们自己写的函数是无法自己给自己追加的,因为‘ \0 ’,被覆盖了,永远都不会遇到‘ \0 ’。但是库函数strcat可以 ,但是尽量不要这样使用,可以使用strncat来给自己追加。

strcmp

函数介绍

字符串比较函数
int strcmp ( const char * str1, const char * str2 )
第一个字符串大于第二字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字

比较规则是按照字典序比较的,如果是大小写的话就按照ASCII码值比较。ASCII码值大,那么字符串中的字符就大。如果一个字符串结束,另一个字符串就和‘ \0 ’,比较,此时就是‘ \0 ’小。

模拟实现

int my_strcmp(const char* str, const char* src)
{assert(str && src);while (*str == *src){if (*str == '\0')return 0;str++;src++;}return *str - *src;
}

strncpy

函数介绍

char * strncpy ( char * destination, const char * source, size_t num )
前两个参数和strcpy是一个意思,第三个参数是要拷贝的数量
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
如果字符串大于num,就拷贝num个,不补‘ \0 ’。

模拟实现

char* my_strncpy(char* str, const char* src, int num)
{char* ret = str;assert(str&& src);while (*str = *src){str++;src++;num--;if (num == 0)break;}while (num){*str = '\0';str++;num--;}return ret;
}

strncat

函数介绍

char * strncat ( char * destination, const char * source, size_t num )
指定在目标字符串后面追加多少个。
追加后补‘ \0 ’。
如果源字符串不够长,有多少个追加多少个。

模拟实现

char* my_strcat(char* str, const char* src, int num)
{char* ret = str;assert(str);assert(src);while (*str != '\0'){str++;}while (*str++ = *src++){num--;if (num == 0){*str = '\0';break;}}return ret;
}

strncmp

函数介绍

int strncmp ( const char * str1, const char * str2, size_t num )
比较前n个字符,返回值与strcmp相同。

模拟实现

int my_strncmp(const char* str, const char* src, int num)
{assert(str && src);while (*str == *src){num--;if (*str == '\0' || num <= 0)return 0;str++;src++;}return *str - *src;
}

strtok

char * strtok ( char * str, const char * delimiters )
sep参数指向一个字符串,定义了用作分隔符的字符集合
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
strtok函数找到str中的下一个标记,并将其用‘ \0 ’ 结尾,返回一个指向这个开始位置的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
strtok函数的第一个参数不为NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
strtok函数的第一个参数为NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
如果字符串中不存在更多的标记则返回NULL

int main()
{char arr[] = "zhangsan@qq.com.cn";char temp = { 0 };temp = strcpy(temp, arr);char* sep = ".@";char* str = NULL;for (str = strtok(arr, temp); str != NULL; str = strtok(NULL, temp)){printf("%s\n", str);}return 0;
}

strstr

函数介绍

const char * strstr ( const char * str1, const char * str2 )
在字符串中找字串,在str1中找str2
返回str2字符串在str1中第一次出现的第一个字符的地址,找不到就返回NULL。

模拟实现

char* my_strstr(const char* str1, const char* str2)
{assert(str1 && str2);const char* cp = str1;const char* s1 = NULL;const char* s2 = NULL;if (*str2 == '\0')//如果字符串是空return str1;while (*cp){s1 = cp;s2 = str2;while (*s1 == *s2 && *s2 && *s1){s1++;s2++;}if (*s2 == '\0')return cp;cp++;}return NULL;
}

strerror

strerror函数可以把参数部分错误码对应的错误信息的字符串地址返回来。
使用strerror需要包含<string.h>

在C语言库函数中设计一些错误码,当我们库函数在调用的过程中发生了各种错误,要记录下来,这时候记录的就是错误码。
在这里插入图片描述

当库函数调用失败的时候会将错误码记录到errno这个变量当中,如过要使用这个变量需要引用<errno.h>这个头文件。
errno是一个C语言的全局变量。

比如我们打开一个文件,不存在那么打开失败,就会把失败的错误码存在errno里面

int main()
{FILE* pf = fopen("add.txt", "r");if (pf == NULL){printf("打开文件失败,原因:%s\n", strerror(errno));return 1;}else{printf("打开文件成功\n");}return 0;
}

在这里插入图片描述

perror

perror直接打印错误码所对应的信息,并且会打印参数,然后加一个冒号一个空格。
相当于printf和strerror(errno)的一个组合功能。

int main()
{FILE* pf = fopen("add.txt", "r");if (pf == NULL){perror("fopen");return 1;}else{printf("打开文件成功\n");}return 0;
}

在这里插入图片描述

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

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

相关文章

Leetcode 17. 电话号码的字母组合

给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 示例 1&#xff1a; 输入&#xff1a;digits “23” 输出&#xff1a;[“a…

清华大学 【战略管理的逻辑】全6讲笔记

讨论从20世纪初的企业管理背景入手&#xff0c;讲述了随着经济和技术的进步&#xff0c;企业管理理念和实践所经历的主要变化。 1.战略管理的重要性及其时代演变 在过去的几十年里&#xff0c;企业管理的理念和方法经历了从重视生产效率到注重市场营销&#xff0c;再到强调战略…

React真的好难用

我发现React就像个宗教一样&#xff0c;网络上总有一群信徒。信徒&#xff1a;React天下第一&#xff0c;谁也不能说他不好。 网络上大佬对React的评价一般有几类&#xff1a; React跟Vue比就是手动档和自动档的区别&#xff0c;高手都开手动档。—— 就一个破打工的&#xf…

Qt——代码崩溃 free() invalid pointer

最近在开发中&#xff0c;使用多个QSharedPointer创建智能指针指向c11 写的单例时&#xff0c;出现了程序崩溃&#xff0c;如标题的错误提示&#xff0c;故此记录&#xff1a; 错误代码&#xff1a; QSharedPointer <Singleton>m_test(Singleton.getInstance()); QShare…

cJSON的使用

文章目录 一、CJSON初识二、CJSON解析器基础三、CJSON解析数据JSON解析基础CJSON解析数组数据CJSON解析嵌套数据 五、创建JSON数据 一、CJSON初识 JSON (JavaScript Object Notation)是一种轻量级的数据交换格式&#xff0c;常用于在网络之间传输数据。它是一种文本格式&#…

笔记:.NET的框架梳理及相关概念了解(“.NET Core“ “.NET“ “.NET Framework“)

一、.NET设计 架构&#xff1a;C/C程序是直接将源码编译成机器码&#xff08;CPU可以识别和运行的指令&#xff09;&#xff0c;对于不同CPU&#xff0c;其指令集不同&#xff0c;机器码也就不同&#xff0c;故&#xff1a;C/C程序编译时&#xff0c;需选择具体的CPU架构&…

【系统架构师】-选择题(五)

1、某公司拟开发一个轿车巡航定速系统&#xff0c;系统需要持续测量车辆当前的实时速度&#xff0c;并根据设定的期望速度自动控制轿车的油门和刹车。针对上述需求&#xff0c;采用( 过程控制)架构风格最为合适。 某企业内部现有的主要业务功能已封装成为Web服务。为了拓展业务…

河南新办灌溉排涝乙级资质预算分析

河南新办灌溉排涝乙级资质的预算分析是一个涉及多方面因素的综合考量。以下是对该预算的详细分析&#xff1a; 首先&#xff0c;人员费用是预算中的重要组成部分。这包括聘请符合资质要求的技术人员、工程师和其他相关人员的薪酬、社保等费用。这些费用会根据所需人员的数量、资…

JavaScript云LIS系统源码 前端框架JQuery+EasyUI+后端框架MVC+SQLSuga大型医院云LIS检验系统源码 可直接上项目

JavaScript云LIS系统源码 前端框架JQueryEasyUI后端框架MVCSQLSuga大型医院云LIS检验系统源码 可直接上项目 云LIS系统概述&#xff1a; 云LIS是为区域医疗提供临床实验室信息服务的计算机应用程序&#xff0c;可协助区域内所有临床实验室相互协调并完成日常检验工作&#xff…

【SHADER】Shader实例学习1:UI noise halo

Shader实例学习1&#xff1a;UI noise halo 简介源码注释关键步骤总结 简介 又换方向做图形相关的工作了&#xff0c;门槛确实有一点&#xff0c;数学、图形什么的都要学&#xff0c;算轨迹用到力学什么的也是基本操作。大力出奇迹&#xff0c;跟着shadertoy里的众多大神学起来…

zynq dcache一致性问题

使能dcahce后&#xff0c;写内存不正常。 http://static.stmcu.com.cn/upload/pdf_html/93bd41d6e1e3dfc64cecbea29ccdef41.html FPGA - ZYNQ Cache一致性问题 FPGA - ZYNQ Cache一致性问题-CSDN博客

Unity类银河恶魔城学习记录15-5,6 p157 Audio time limiter p158 Area sound

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili​​ AreaSound.cs using System.Collections; using System.Collections.G…

视频输入c++ 调用 libtorch推理

1、支持GPU情况 libtorch 支持GPU情况比较奇怪&#xff0c;目前2.3 版本需要在链接器里面加上以下命令&#xff0c;否则不会支持gpu -INCLUDE:?ignore_this_library_placeholderYAHXZ 2 探测是否支持 加一个函数看你是否支持torch&#xff0c;不然不清楚&#xff0c;看到…

Hive函数详解

Hive 是一个建立在 Hadoop 上的数据仓库基础架构&#xff0c;它提供了类似于 SQL 的查询语言&#xff0c;称为 HiveQL&#xff0c;用于对存储在 Hadoop 分布式文件系统中的数据进行查询和分析。 1.函数简介 Hive会将常用的逻辑封装成函数给用户进行使用&#xff0c;类似于Jav…

Web前端开发 小实训(一) 成绩分类统计

用于学生web前端开发课程实训练习&#xff0c;掌握基本语法和数据类型 实训目的 使用分支语句&#xff0c;完成分数统计与等级对比,通过输入框输入分数&#xff0c;可以根据分数多少划分等级。 参考思路&#xff1a; 分析题目&#xff1a;根据输入分数进行等级划分。 操作过…

springboot如何使用RedisTemplate

第一步&#xff1a;创建一个spring boot项目 第二步&#xff1a;pom导入redis相关依赖 <!--reids依赖--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId> </depen…

Go语言中的goroutine调度是如何实现的?

文章目录 一、M:N调度模型二、GMP模型三、调度过程四、调度优化五、示例代码 在Go语言中&#xff0c;goroutine是一种轻量级的线程&#xff0c;它使得并发编程变得更加简单和高效。而goroutine的调度则是Go运行时&#xff08;runtime&#xff09;系统负责的一个核心任务&#x…

std::remove_if

template <class ForwardIterator, class UnaryPredicate>ForwardIterator remove_if (ForwardIterator first, ForwardIterator last,UnaryPredicate pred);std::remove_if函数删除容器中满足pred的元素&#xff0c;返回最后一个没被移除的元素后面一个迭代器&#xff0…

阿米巴经营之深入解读

目录 什么是阿米巴&#xff1f; 一、阿米巴经营的来历 二、阿米巴经营的三大好处和运作方式 三、阿米巴经营常见的两大问题与解决方案 稻盛和夫被誉为日本的经营之神。上个世纪&#xff0c;他创办经营的京瓷公司、KDDI公司等&#xff0c;先后成为了世界500强企业。2010年&…

Postman,一个功能强大的API开发和测试工具

最近有小伙伴说在找 postman 的使用教程&#xff0c;案例等文章。 那么今天我就来写一个。 Postman 是一个功能强大的 API 开发和测试工具&#xff0c;它提供了丰富的功能&#xff0c;帮助开发人员更好地管理、测试和文档化 API。无论是单独开发还是团队协作&#xff0c;Postma…