字符串函数精讲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…

uniapp android播放本地视频

概述 本文将介绍如何在uniapp开发中实现Android平台播放本地视频的功能。首先我们会梳理整个实现过程的流程,并使用表格列出每个步骤需要做的事情。然后,我们会逐步解释每个步骤需要做的事情,并提供相关的代码示例。 流程概览 下面的表格展示了实现uniapp Android播放本地…

【ASP.NET Core】MVC中ViewData和ViewBag的区别和使用

在 ASP.NET MVC 中&#xff0c;ViewBag 和 ViewData 都是用来传递数据从控制器到视图的机制。尽管它们在功能上很相似&#xff0c;但在使用方式上有一些差别。 ViewBag ViewBag 使用动态特性来存储数据。它是 dynamic 类型的&#xff0c;这意味着你可以给它赋任何类型的值。由…

开源 vs 闭源:数字化时代的技术选择

开源 vs 闭源&#xff1a;数字化时代的技术选择 近期&#xff0c;特斯拉CEO马斯克的一番言论引起了广泛关注&#xff1a;OpenAI不该闭源&#xff0c;自家首款聊天机器人将开源。这引发了人们对于开源与闭源软件的辩论&#xff0c;这一话题在技术界一直是热门的讨论焦点。在数字…

C语言面试之旅:掌握基础,探索深度(面试实战之c语言关键词下篇)

一.枚举&#xff08; enum&#xff09; 枚举是 C 语言中的一种基本数据类型&#xff0c;用于定义一组具有离散值的常量&#xff0c;它可以让数据更简洁&#xff0c;更易读。枚举类型通常用于为程序中的一组相关的常量取名字&#xff0c;以便于程序的可读性和维护性。定义一个枚…

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

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…

LeetCode 设计前中后队列

题目 1670. 设计前中后队列 请你设计一个队列&#xff0c;支持在前&#xff0c;中&#xff0c;后三个位置的 push 和 pop 操作。 请你完成 FrontMiddleBack 类&#xff1a; FrontMiddleBack() 初始化队列。void pushFront(int val) 将 val 添加到队列的 最前面 。void pushMidd…

Linux系统平均负载

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

如何扩展服务器存储容量_Maizyun

如何扩展服务器存储容量 随着互联网和数据的快速发展&#xff0c;服务器存储容量往往成为限制业务发展的重要因素。 如何有效扩展服务器的存储容量以满足业务需求是很多公司和个人需要面对的问题。 本文将探讨如何扩展服务器的存储容量来解决存储空间不足的问题。 1.了解存储…

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

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

【华为交换】交换机MSTP+VRRP配置

功能简介 企业用户访问外网的流量&#xff0c;可能会同时包含二层流量和三层流量&#xff08;例如&#xff0c;企业内二层VPN用户和三层VPN用户访问MPLS公网&#xff09;。企业用户希望接入网络既能包含多条接入链路&#xff08;不同链路之间互为备份&#xff09;以保障接入的…

【brpc学习实践十一】session-local与thread-local应用与brpc抽象工厂模式实践

什么是session-local与thread-local 百度内的检索程序大量地使用了thread-local storage (缩写TLS),有些是为了缓存频繁访问的对象以避免反复创建,有些则是为了在全局函数间隐式地传递状态。你应当尽量避免后者,这样的函数难以测试,不设置thread-local变量甚至无法运行。s…

哪些因素会影响香港服务器的下载速度_Maizyun

哪些因素会影响香港服务器的下载速度&#xff1f; 随着互联网的普及和快速发展&#xff0c;越来越多的企业和个人选择使用香港服务器来托管其网站、应用程序和其他在线服务。 然而&#xff0c;很多因素可能会影响香港服务器的下载速度。 本文将探讨影响香港服务器下载速度的几…

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

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