字符串函数精讲1

又是好几天没有更新了,最近有些忙,但这并不是理由,还是怪我自己玩的时间多了!但还是有在每天敲代码的!话不多说,开始这一期的学习:

strlen的使用和模拟实现

• 字符串以 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前⾯出现的字符个数(不包含 '\0' )。

• 参数指向的字符串必须要以 '\0' 结束。

• 注意函数的返回值为size_t,是⽆符号的( 易错 )

• strlen的使用需要包含头文件 

strlen的使用:

 字符串中一共有13个字符,末尾是以\0结尾的,我们strlen函数再计算字符个数时,\0不计入其中,遇到\0才会停下来!如果末尾没有\0的话,strlen就会一直寻找它的\0,直到遇到\0才会停下来,可能会存在越界访问!所以在使用时,一定要注意!而且要加上相应的头文件哦!

strlen的模拟实现:

方法一:

既然它遇到\0就会停止,那么我们就可以创建一个变量(count)来计数,如果arr[i]不为0,那么我们就count++;

#include <stdio.h>
size_t my_strlen(char* str)
{int count = 0;while (*str){count++;str++;}return count;
}
int main()
{char arr[] = "i want to try";size_t len = my_strlen(arr);printf("%zu", len);return 0;
}

方法二:

我们可以利用指针-指针的绝对值等于之间的元素个数来模拟,我们首先保存数组的首元素地址,接着我们找到\0的位置,然后两指针相减就可以知道了。

#include <stdio.h>
size_t my_strlen(char* str)
{char* start = str;while (*str){str++;}return str-start;
}
int main()
{char arr[] = "i want to try";size_t len = my_strlen(arr);printf("%zu", len);return 0;
}

方法三:

第三种方法我们可以利用函数递归的方法进行计算,举个例子:我们要计算的是“hello”这个字符串,那么就是hello-> 1+ello ->1+1+llo ->1+1+1+lo -> +……+1+1+1+1+1+'\0' = 5;

#include <stdio.h>size_t my_strlen(char* str)
{if (*str == '\0'){return 0;}else{return 1 + my_strlen(str + 1);}
}int main()
{char arr[] = "i want to try";size_t len = my_strlen(arr);printf("%zu", len);return 0;
}

strcpy 的使用和模拟实现:

源字符串必须以 '\0' 结束。

会将源字符串中的 '\0' 拷⻉到⽬标空间。

⽬标空间必须⾜够⼤,以确保能存放源字符串。

⽬标空间必须可修改。

strcpy 的使用:

 我们这时可以打开监视,看一看arr里面的情况,是只拷贝了abcd,还是把'\0'也拷贝了过去!

 可以看见是把我们的\0也拷贝过去的,所以这些小细节我们一定要拿捏好,哈哈。

strcpy 的模拟实现:

怎样实现我们strcpy的模拟实现呢?那么就是当我们源字符串不为\0时,我们就改变目的字符串的字符,直到源字符串的字符为0时,我们就跳出循环,接着把\0也copy过去!

#include <stdio.h>
#include <assert.h>char* my_strcpy( char* str1, const char* str2)
{char* ret = str1;//保存str1的首地址,下面需返回首地址打印,ret在下面代码中的位置会被改变assert(str1 && str2);//断言是否为空指针while (*str2 != '\0'){*str1 = *str2;str1++;str2++;}*str1 = *str2;//把\0也拷贝过去return ret;
}int main()
{char arr1[] = "happy new year!";char arr2[] = "hello baby";printf("%s", my_strcpy(arr1, arr2));return 0;
}

其实上述的代码中while部分的代码还可以这样写:

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

加加的优先级高于简引用,后置加加所以是先使用再进行加加运算,当*src为\0时,赋值给*dest后,循环条件终止跳出循环!


strcat 的使用和模拟实现:

 

源字符串必须以 '\0' 结束。
⽬标字符串中也得有 \0 ,否则没办法知道追加从哪⾥开始。
⽬标空间必须有足够的⼤,能容纳下源字符串的内容。
⽬标空间必须可修改。

strcat 的使用:

 就是再arr1后面追加arr2的内容,我们去看一看是否把\0也追加了过去!

那么我们可以看见也是把\0追加了过去!那么我们的这个strcat函数,可以自己给自己追加吗?

 我们可以看出,\0的位置被改成了b,那么我们的arr2就不会指向我们的\0的位置,就会成为死循环状态,那么对于自己给自己追加的话,我们后面会讲到一种函数(strncat),它就能自己给自己追加!

strcat 的模拟实现:

我们有了上面模拟strcpy的知识,那么对于这个函数,我们就只需要再前面找到arr1\0的位置,然后进行copy就可以了!

#include <stdio.h>
#include <assert.h>
char* my_strcat(char* str1, const char* str2)
{char* ret = str1;assert(str1 && str2);while (*str1){str1++;}//找到str1的\0的位置while (*str1++ = *str2++){;}return ret;
}
int main()
{char arr1[20] = "hello\0xxxxxxx";char arr2[] = "baby";printf("%s", my_strcat(arr1, arr2));return 0;
}

strcmp 的使⽤和模拟实现:

 第⼀个字符串⼤于第⼆个字符串,则返回⼤于0的数字

第⼀个字符串等于第⼆个字符串,则返回0

第⼀个字符串⼩于第⼆个字符串,则返回⼩于0的数字
那么如何判断两个字符串? ⽐较两个字符串中对应位置上字符ASCII码值的⼤⼩。

strcmp 的使用:

 strcmp 的模拟实现:

当我们arr1和arr2指向的位置的字符相等时,我们就指向下一个字符进行比较,当所指向的字符不相等时,我们就比较此时所指向的字符的ASCII值的大小来进行返回值!但是还有一种情况,当我们的arr1所指向的元素为/0时,说明此时已经比较完了,说明两字符串是相等的,那么此时我们就可以返回0!

#include <stdio.h>
#include <assert.h>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;/*if (*str1 > *str2)//也可以写成这种{return 1;}else{return -1;}*/
}
int main()
{char arr1[] = "abcd";char arr2[] = "abcd";int ret = my_strcmp(arr1, arr2);if (ret > 0){printf("大于\n");}else if (ret == 0){printf("等于\n");}else{printf("小于\n");}return 0;
}

strncpy 函数的使用和模拟实现:

 

拷⻉num个字符从源字符串到⽬标空间。
如果源字符串的长度小于num,则拷宝完源字符串之后,在⽬标的后边追加0,直到为num。

 

strncpy 函数的使用 :

我们可以根据打印出来的结果知道,此时并没有把arr2中的copy过去,因为如果copy过去的话,那么我们就只会看见hello!那么我们的num如果大于我们字符串的长度,会是什么结果呢?我们一起来看一看:

我们可以看见当我们的num大于我们的arr2的字符串长度时,我们的\0时拷贝过去了的,那么是拷贝了几个呢?我们一起看看咯:

是两个\0,那么我们就可以知道了:如果源字符串的长度小于num,则拷宝完源字符串之后,在⽬标的后边追加0,直到为num!

​​​​​​​strncpy 函数的模拟实现: 

我们有了上面模拟strcpy的经验,那么对于此函数我们想要模拟也不难咯!那么当我们的num小于等于我们的字符串的长度时,我们此时就以num为循环条件,当我们的num变为0时,我们就跳出循环,返回arr1的首元素地址:

if (num <= len)
{while (num--){*dest = *src;dest++;src++;}return ret;
}

当大于的时候,我们除了copy完我们arr2的字符外,还要copy我们的\0,那么多出来的此数就copy我们的\0!

else
{while (len--){*dest = *src;dest++;src++;}for (size_t i = a; i < num; i++){*dest = '\0';dest++;}return ret;
}

我们来看看整体的代码:

char* my_strncpy(char* dest, const char* src, size_t num)
{char* ret = dest;assert(dest && src);size_t len = strlen(src);size_t a = len;//保存len的值,下面要用,因为len的值被改变了if (num <= len){while (num--){*dest = *src;dest++;src++;}return ret;}else{while (len--){*dest = *src;dest++;src++;}for (size_t i = a; i < num; i++){*dest = '\0';dest++;}return ret;}
}
int main()
{char arr1[20] = "xxxxxxxxxxxx";char arr2[] = "hello";my_strncpy(arr1, arr2, 7);printf("%s", arr1);return 0;
}

我们还可以用其他的方法,用两个for循环就可以解决问题了:

char* my_strncpy(char* dest, const char* src, size_t n) 
{size_t i;for (i = 0; i < n && src[i] != '\0'; i++){dest[i] = src[i];}for (; i < n; i++) {dest[i] = '\0';}return dest;
}

 i < n && src[i] != '\0'这样就很好的解决了我们的问题!


strncat 函数的使用和模拟实现:

Appends the first num characters of source to destination, plus a terminating null-character. (将source指向字符串的前num个字符追加到destination指向的字符串末尾,再追⼀个 \0 符)。
If the length of the C string in source is less than num, only the content up to the terminating null-character is copied.(如果source 指向的字符串的⻓度⼩于num的时候,只会将字符串中到 \0 的内容追加到destination指向的字符串末尾)。

strncat 函数的使用:

 我们的num值为3,那么·追加过去的除了wor三个字符,还有我们的\0。那么如果我们追加的Num值大于字符串长度呢?又会是什么样的结果呢?一起来看一看:

那么可以看见不管多了多少,也只是在后面追加了一个\0!

strncat 函数的模拟实现:

这里就直接展示代码嘛:有了上面的经验,相信大家都是会的吧!

#include <stdio.h>
#include <assert.h>
//方法一:
char* my_strncat(char* dest, const char* src, size_t num)
{char* ret = dest;assert(dest && src);int j = 0;while (dest[j]){j++;}size_t i = 0;for (i = 0; i < num && src[i] != '\0'; i++){dest[j] = src[i];j++;}dest[j] = '\0';return ret;
}//方法二:
//char* my_strncat(char* destination, const char* source, size_t num)
//{
//    char* ptr = destination;
//    while (*ptr) 
//    {
//        ptr++;
//    }
//
//    while (*source && num) 
//    {
//        *ptr++ = *source++;
//        num--;
//    }
//
//    *ptr = '\0';
//
//    return destination;
//}
//
//int main() 
// {
//    char str1[30] = "Hello \0xxxxxxxx";
//    char str2[] = "World!";
//
//    printf("%s\n", my_strncat(str1, str2, 9));
//
//    return 0;
//}

strncmp函数的使用:

⽐较str1和str2的前num个字符,如果相等就继续往后⽐较,最多⽐较num个字⺟,如果提前发现不⼀ 样,就提前结束,⼤的字符所在的字符串⼤于另外⼀个。如果num个字符都相等,就是相等返回0.

这里就讲一下怎么使用的,感兴趣的伙伴可以去模拟实现一下看看哦!

相信你们一定可以的!本期的内容就到此了,我们下期再见!

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

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

相关文章

前端:实现二级菜单(二级菜单悬浮在一级菜单左侧)

效果 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width, i…

每日一题:LeetCode-283. 移动零

每日一题系列&#xff08;day 08&#xff09; 前言&#xff1a; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f50e…

聚观早报 |亚马逊AWS发布新AI芯片;拼多多Q3营收增长94%

【聚观365】11月30日消息 亚马逊AWS发布新AI芯片 拼多多Q3营收增长94% Redmi K70全新国风配色揭晓 英伟达扩大自动驾驶中国团队 华为nova 12参数细节曝光 亚马逊AWS发布新AI芯片 在美国时间周二举办的Reinvent大会上&#xff0c;亚马逊旗下的云计算部门AWS发布了新的人工…

Docker—更新应用程序

在本部分中&#xff0c;你将更新应用程序和映像。您还将了解如何停止和移除容器。 一、更新源代码 在以下步骤中&#xff0c;当您没有任何待办事项列表项时&#xff0c;您将把“空文本”更改为“您还没有待办事项&#xff01;在上面添加一个&#xff01;” 1、在src/static/…

C#,数值计算——插值和外推,径向基函数插值(RBF_multiquadric)的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { public class RBF_multiquadric : RBF_fn { private double r02 { get; set; } public RBF_multiquadric(double scale 1.0) { this.r02 Globals.SQR(scale); } publi…

智能客服核心技术——预测会话与答案生成

1.信息检索 2. 句型模板匹配标准问题生成答案 3.根据知识图谱推理得到答案

vue发送请求携带token,拼接url地址下载文件

封装请求 &#xff0c;该请求为普通的get请求 该请求返回值为&#xff1a; 请求成功之后拼接URL地址下载文件 代码块 downTemplateRequest(activeKeys.value).then((res) > {let url http://47.169.168.99:18888/media/${res.data.name};var elink document.createElemen…

ApiSix的docker 容器化部署及使用

⼀&#xff0e;etcd安装 Docekr安装Etcd 环境准备 此处安装&#xff0c;是利⽤下载的 etcd 源⽂件&#xff0c;利⽤ docker build 构建完整镜像&#xff0c;具体操作如下&#xff1a; 1.环境准备 1.1. 新建⽂件夹 在磁盘某个路径下新建⼀个⽂件夹&#xff0c;⽤处操作 Dockerfi…

Linux系统平均负载

我们经常会使用 top 命令来查看系统的性能情况&#xff0c;在 top 命令的第一行可以看到 load average 这个数据&#xff0c;如下图所示&#xff1a; load average 包含 3 列&#xff0c;分别表示 1 分钟、5 分钟和 15 分钟的 系统平均负载 系统平均负载&#xff1a; 如果将 …

golang—kafka架构原理快速入门以及自测环境搭建(docker单节点部署)

kafka Apache Kafka 是一个分布式的流处理平台。它具有以下特点&#xff1a; 支持消息的发布和订阅&#xff0c;类似于 RabbtMQ、ActiveMQ 等消息队列支持数据实时处理能保证消息的可靠性投递支持消息的持久化存储&#xff0c;并通过多副本分布式的存储方案来保证消息的容错高…

Java中xml映射文件是干什么的

Java中的XML映射文件主要用于将Java对象与XML文档之间进行转换。它通常用于处理数据交换和存储&#xff0c;例如将Java对象转换为XML格式以便在网络上传输或保存到文件中&#xff0c;或者将XML文档解析为Java对象以进行处理。这种转换可以通过Java的JAXB&#xff08;Java Archi…

springMVC实验(二)—调式工具APIFOX的使用

【知识要点】 后端开发调试工具 前后端分离已经成为互联网类软件开发主流模式&#xff0c;没有前端操作的支持&#xff0c;如何调试后端程序的就是开发人员必须解决的问题。如&#xff1a;get类请求可以直接使用浏览器就能模拟测试&#xff0c;但是post、put等类型的请求&…

Ubuntu 环境下 NFS 服务安装及配置使用

需求&#xff1a;公司内部有多台物理服务器&#xff0c;需要A服务器上的文件让B服务器访问&#xff0c;也就是两台服务器共享文件&#xff0c;当然也可以对A服务器上的文件做权限管理&#xff0c;让B服务器只读或者可读可写 1、NFS 介绍 NFS 是 Network FileSystem 的缩写&…

可以在电脑桌面展示工作计划表的软件

很多上班族都表示自己在工作时&#xff0c;会面临大量且复杂的工作任务&#xff0c;这时候就会拖延工作&#xff0c;或者感觉时间不够用&#xff0c;所以需要有明确的工作计划来指导自己如何分类时间和精力&#xff0c;确保每项工作任务都能够按时完成。如果需要制定每天的工作…

C++学习之路(十二)C++ 用Qt5实现一个工具箱(增加一个XML文本格式化功能)- 示例代码拆分讲解

上篇文章&#xff0c;我们用 Qt5 实现了在小工具箱中添加了《进制转换器功能》功能。为了继续丰富我们的工具箱&#xff0c;今天我们就再增加一个平时经常用到的功能吧&#xff0c;就是「 XML文本格式化 」功能。下面我们就来看看如何来规划开发一个这样的小功能并且添加到我们…

模拟算法【1】

文章目录 &#x1f600;1576. 替换所有的问号&#x1f606;题目&#x1f929;算法原理&#x1f642;代码实现 &#x1f60a;495.提莫攻击&#x1fae0;题目&#x1f609;算法原理&#x1f917;代码实现 模拟算法 通俗的来说&#xff0c;模拟算法就是依葫芦画瓢&#xff0c;将题…

React 签字手写签名组件 react-signature

安装依赖包 npm install uiw/react-signature示例代码 import React, { useRef } from "react"; import Signature from uiw/react-signature;export default function App() {const $svg useRef(null);const handle (evn) > $svg.current?.clear();return (…

[ISCTF2023] Crypto/PWN/Reverse

最近新生赛还挺多&#xff0c;不过这个开始后注册页面就被删了&#xff0c;没注册上。拿别人的附件作了下。 Crypto 七七的欧拉 这题只给了n,e,c这种情况一般正常没法解&#xff0c;猜n不正常 import gmpy2 import libnum from crypto.Util.number import *flagbISCTF{****…

【C/C++笔试练习】this指针的概念、初始化列表、const对象调用、构造和析构函数、继承和组合、重载和多态、虚函数的定义、计算日期到天数转换、幸运的袋子

文章目录 C/C笔试练习选择部分&#xff08;1&#xff09;this指针的概念&#xff08;2&#xff09;初始化列表&#xff08;3&#xff09;const对象调用&#xff08;4&#xff09;构造和析构函数&#xff08;5&#xff09;继承和组合&#xff08;6&#xff09;重载和多态&#x…

7Docker搭建es和kibana

一、安装es 1.拉取镜像 sudo docker pull elasticsearch:7.12.0 elasticsearch:7.12.0:我安装的版本是7.12.0&#xff0c;可以根据实际的情况安装 创建docker容器挂在的目录&#xff1a; sudo mkdir -p /opt/elasticsearch/config sudo mkdir -p /opt/elasticsearch/data s…