常用的字符串与内存操作函数(1)

news2024/11/28 5:44:47

Tips

1. 

2.  

3. 在进行数值计算的时候,补码能算对,因此计算机里面放的都是补码,运算的对象都是补码
但是与真实数值吻合的是原码,因此打印,求值等都要转化为原码 

4.  for (exp1 ; exp2 ; exp3),是先执行exp1,然后判断exp2,为真的话再执行循环体,再执行exp3,然后在进行判断。

5. 

前言 

  

strlen() 

1. 指针指向的字符串必须要有\0

1. 这个函数是用来求字符串长度的,字符串以\0为结束标志,而strlen从给定的起始指针开始,向后一直找\0,并统计\0之前的字符个数 

2. 这个函数非常在意\0,因此指针指向的字符串必须得有\0,如果没有的话,那么结果就是不可控的随机值

3.  尤其要注意,strlen()的返回值是size_t(typedef size_t unsigned int),其实这个好理解,因为字符串的长度不可能为负的嘛。但是,就会牵扯到一些使用时的细节问题。

如: 

这个应该是比较好解释的,因为strlen的返回值的类型是无符号的整型,当3-6的操作内存中的二进制补码在进行计算的时候,对于结果的类型解读自然也是无符号的整型,那么就不可能为负数,事实上数值就变为很大很大一个数了

4. 模拟实现版本1:(计数法)

#include <assert.h>
size_t my_strlen(const char* str)
{
	assert(str);
	size_t count = 0;
	while (*str++)
	{
		count++;
	}
	return count;
}

5. 模拟实现版本2:(递归法)

#include <assert.h>
size_t my_strlen(const char* str)
{
	assert(str);
	if (*str)
		return 1 + my_strlen(str + 1);
	else
		return 0;
}

6. 模拟实现版本3:(指针相减法) 

注:指针减去指针的结果是两个指针之间数组元素个数 

#include <assert.h>
size_t my_strlen(const char* str)
{
	assert(str);
	const char* start = str;
	while (*str)
	{
		str++;
	}
	return str - start;
}

7. strlen与转义字符结合在一起的一些注意点(对sizeof也适用)

   1. 转义字符为一个字符,比如说\n,只计为一个字符,两者是一个整体。

   2. 当\不起任何作用时,则单个\不计算在结果内。

   3. 编译器会把\000或者\00当成\0,道理对\x000.....也一样。

   4. 当strlen()碰到\0时就会停下来不在计数!\0不包括在内!,而sizeof()没有影响

 strlen非常注意\0,而sizeof完全不在乎,直接统计在内 ,字符串末尾默认带有一个\0的!

  

strcpy() 

1. 源头指针指向的字符串必须要有\0

2. 并且\0也必须一起拷贝过来

  

1,这个函数就是拷贝字符串,那拷贝到什么时候会停止呢?源头的数据拷贝到\0的时候就停止。

2. 拷贝的时候源头指针指向的字符串的\0也会被拷贝过来,并且覆盖掉目标指针指向的字符串的\0

3. 如果在源头指针指向的字符串里面提前放个\0,那么拷贝就会提前终止 

4. 并且目标空间必须足够大

5. 并且目标指针指向的内存空间必须是可以修改的,如果说是一个字符串常量,那就完了

6. 并且当源头指针指向的字符串长度小于目标指针指向的字符串长度时,

7, 并且strcpy的返回值是目标指针

8. 模拟实现strcpy() 

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

strcat() 

1. 源头指针与目标指针指向的字符串都要有\0

2. 会将目标指针指向的字符串末尾\0覆盖掉

1. 是用来完成追加字符串的,其函数原型与strcpy一模一样

2.  把源头指针指向的字符串追加到目标指针指向的字符串后面

3. 我得找到目标指针指向的字符串的\0才能追加,因为必须以此作为追加的起点

4. 同时源头指针指向的字符串也必须有\0存在,表明追加到什么时候停下来

5. 当然,目标空间也必须得十分大,同时,返回的也是目标指针

6,如果提前在目标指针指向的字符串里面遇见了\0,就直接开始以此为起点追加 

7. 模拟实现strcat() 

char* my_strcat(char* dest, const char* src)
{
	char* ret = dest;
	while (*dest)
	{
		dest++;
	}
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}

8, 用strcat自己给自己追加的时候会有bug,因为会把我自己的\0给自己覆盖掉,这下好了,\0没了,直接死循环裂开了

strcmp()

1. 两两对应位置字符的ASCII码一一比较时,\0可能会参与比较 

 

1. 这个是比较两个字符串

2. 是一一比较对应位置上字符的ascii码值,不是比较字符串长度 

3.  其函数返回形式与qsort函数的比较函数十分类型

4. strcmp()模拟实现 

int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);
	while (*str1 == *str2)
	{
		if (*str1 == '\0')
		{
			return 0;
		}
		str1++;
		str2++;
	}
	if (*str1 > *str2)
	{
		return 1;
	}
	else
	{
		return -1;
	}
}

上面我们讲的如strcpy,strcat,strcmp都是长度不受限制的字符串函数,什么意思呢?一切到\0为止,我压根儿才不关心你几个,无所谓没有长度限制,一直到\0为止,我才不关心能不能放得下或者说拷贝几个,一直下去到\0为止 

长度受限制的字符串函数 

1. 但是这会让人很不安全,为了稍微安全一点,就有了 长度受限制的字符串函数如:strncpy,strncat,strncmp

2. 它们在原先的基础之上参数也多了一个,当然之前的参数肯定是不会发生变化的

3. 多的参数就是n, 也就是拷贝几个字符?追加几个字符?比较几个字符?

strncpy() 

如果我要拷贝的字符数小于源头指针指向的字符串字符数 

这时候你会发现\0是不会被拷贝过来的

如果我要拷贝的字符数大于源头指针指向的字符串字符数 

这时候你会发现多余拷贝的内容用\0来代替 

strncat()

如果我要追加的字符数小于源头指针指向的字符串字符数

你会发现你要求的我追加完后会在结尾放入一个\0

如果我要追加的字符数大于源头指针指向的字符串字符数

 

你会发现如果source中C字符串的长度小于num,则只追加到结束空字符的内容 

strncmp() 

这个就很为简单了

字符串查找函数 

1. strstr( )

2. strtok( ) 

strstr() 

1, 其实就是在str1中查找str2在str1中第一次出现的位置/地址

2. 如果能在str1中找到字串str2,返回 str2在str1中第一次出现的位置/地址

3,如果找不到,返回空指针NULL

4.  模拟实现strstr()

#include <assert.h>
char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	if (*str2 == '\0')
		return (char*)str1;
	char* cp = (char*)str1;
	char* s1 = NULL;
	char* s2 = NULL;
	while (*cp)
	{
		s1 = cp;
		s2 = str2;
		while (*s1 == *s2)
		{
			s1++;
			s2++;
			if (*s2 == '\0')
				return cp;
		}
		cp++;
	}
	return NULL;
}

附:

怪异函数strtok() 

  

1. 第一个参数要么是一个指向字符串的指针,要么是一个空指针NULL

2. 第二个参数一个指向字符串的指针,该字符串是当作分隔符的字符集合  

(标记:在字符串中被分隔符分隔开的若干个字符集合就是标记,比如说“ad.fgf.ddffss”,那么如果.是分隔符,则,ad,fgf,ddffss这三个东西就被称为标记 

怪异函数工作步骤 

1.  如果第一个参数不是一个NULL,而是一个指向字符串的指针的话,

2.  那么就先找到第一个标记。

3.  将找到的标记的结尾把分隔符去掉变成\0

4.  返回指向该标记(小字符串)的指针

5.  有记忆功能(实质就是函数体里面有static修饰的变量),strtok函数将保存第一个标记在字符串
中的位置。

6.  如果下一次调用strtok()此时第一个参数是NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记。如果字符串中不存在更多的标记,则返回 NULL 指针。

实例演示 

 

但事实上,上面这种写法就显得有点痤,可以这样子写: 

注:
strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容
并且可修改。(strcpy派上用场了)

 

 

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

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

相关文章

从0到1完成一个Vue后台管理项目(十九、地图区域样式设置、区域文字和立体设置)

往期 从0到1完成一个Vue后台管理项目&#xff08;一、创建项目&#xff09; 从0到1完成一个Vue后台管理项目&#xff08;二、使用element-ui&#xff09; 从0到1完成一个Vue后台管理项目&#xff08;三、使用SCSS/LESS&#xff0c;安装图标库&#xff09; 从0到1完成一个Vu…

上半年要写的博客文章25

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…

分享86个NET源码,总有一款适合您

NET源码 分享86个NET源码&#xff0c;总有一款适合您 链接&#xff1a;https://pan.baidu.com/s/1JOY-9pJIM7sUhafxupMaZw?pwdfs2y 提取码&#xff1a;fs2y 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c;大家下载…

Blender里的三种绑定:(一)主从绑定

文章目录Blender里的三种绑定.主从绑定.进行物体绑定.进行顶点绑定.解除绑定.保持变换.无反向.进行晶格绑定.Blender里的三种绑定. 1 Blender中一共有三种绑定模式&#xff0c;分别是 主从绑定&#xff0c;约束&#xff0c;骨骼 主从绑定. 1 主从绑定即父子关系&#xff0c;…

【Spark常用算子合集】一文搞定spark中的常用转换与行动算子

&#x1f680; 作者 &#xff1a;“大数据小禅” &#x1f680;文章简介&#xff1a;本篇文章属于Spark系列文章&#xff0c;专栏将会记录从spark基础到进阶的内容 &#x1f680; 内容涉及到Spark的入门集群搭建&#xff0c;核心组件&#xff0c;RDD&#xff0c;算子的使用&…

【数据结构与算法】——第六章:图

文章目录1、图的定义1.1 图的其他定义1.2 图的顶点与边之间的关系1.3 连通图相关术语2、图的存储结构2.1 邻接矩阵2.2 邻接表3、图的遍历3.1 深度优先遍历3.2 广度优先遍历4、最小生成树4.1 普利姆算法(Prim)4.2 克鲁斯卡尔(kruskal)5、最短路径5.1 迪杰斯特拉(Dijkstra)算法5.…

Sentinel限流-@SentinelResource注解配置

SentinelResource 配置-上 &#xff08;按资源名配置限流规则&#xff09; 1&#xff09; Sentinel 控制台配置流控规则&#xff1a; 2&#xff09;java 代码&#xff1a; GetMapping("/byResource")SentinelResource(value "byResource", blockHandler …

Django项目——通过APIView实现API访问

前提 该文章在已有项目的基础上进行修改 https://blog.csdn.net/qq_38122800/article/details/128583379?spm1001.2014.3001.5502 1、配置序列化器 序列化器包含序列化和反序列化两个过程,简单点理解就是 序列化 : 将从数据库中查的数据变为前端页面可以接受的json数据 反…

Odoo 16 企业版手册 - 库存管理之重订货规则

重订货规则 在Odoo 库存模块中&#xff0c;您可以配置一组规则&#xff0c;帮助您确保库存永远不会用完。Odoo将尝试使用重订货规则在您的库存中保持至少最低数量的产品。让我们看看此功能在Odoo 16中是如何工作的。为此&#xff0c;您可以从库存模块中选择一个可存储的产品。 …

qt学习记录

一、新建项目时只有pro文件而没有其他文件 此时需要在Kits界面将所有编译器选择&#xff0c;即可出现其他文件 二、QMainWindow、QWidget、QDialog的区别 ①QWidget继承于QObject和QPaintDevice&#xff0c;QDialog和QMainWindow则继承于QWidget&#xff0c;QDialog、QMainWi…

[ 数据结构 ] 弗洛伊德算法(Floyd)--------最短路径问题

0 Floyd算法介绍 和 Dijkstra 算法一样&#xff0c;弗洛伊德(Floyd)算法也是一种用于寻找给定的加权图中顶点间最短路径的算法。该算法名称以创始人之一、1978 年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特弗洛伊德命名弗洛伊德算法(Floyd)计算图中各个顶点之间的最短路…

新应用——信息化财务管理,一站式满足多个需求

财务管理应用是企业为了适应当下社会环境提出的一种将财务管理进行信息化管理的方法&#xff0c;与传统财务管理模式不同&#xff0c;将各类业务数据编制为电子数据&#xff0c;便于财务人员查找数据内容&#xff0c;可以更高效的开展工作。百数应用中心的财务管理应用涵盖了项…

机器学习笔记之深度信念网络(二)模型构建思想(RBM叠加结构)

机器学习笔记之深度信念网络——模型构建思想引言回顾&#xff1a;深度信念网络的结构表示解析RBM隐变量的先验概率通过模型学习隐变量的先验概率引言 上一节介绍了深度信念网络的模型表示&#xff0c;本节将介绍深度信念网络的模型构建思想——受限玻尔兹曼机叠加结构的基本逻…

Flutter多分支打包持续化集成

一、使用效果演示 1.1、选择参数打包 以下为参数使用说明。 packingType枚举 android、ios android ios android&ios (新功能&#xff1a;并行打包)备注&#xff1a; android、ios&#xff1a;串行打包&#xff0c;即先打一个再打一个 android&ios&#xff1a;为并行…

与香港财政司司长同台,欧科云链在这场峰会上都说了啥?

今天&#xff0c;POWER 2023香港Web3创新者峰会在中国香港如期召开&#xff0c;香港特别行政区政府财政司司长陈茂波、财经事务及库务局副局长陈浩濂、全国政协委员、立法会议员吴杰庄等港府要员出席峰会。 作为本场峰会的受邀企业&#xff0c;欧科云链控股(01499.HK)公司执行董…

Kernel Pwn基础教程之 Double Fetch

一、前言 Double Fetch是一种条件竞争类型的漏洞&#xff0c;其主要形成的原因是由于用户态与内核态之间的数据在进行交互时存在时间差&#xff0c;我们在先前的学习中有了解到内核在从用户态中获取数据时会使用函数copy_from_user&#xff0c;而如果要拷贝的数据过于复杂的话…

人工智能-正则表达式

目录1、正则表达式概述2、re模块3、匹配单个字符4、匹配多个字符5、匹配开头和结尾6、匹配分组7、总结1、正则表达式概述 在实际开发过程中经常会需要查找某些复杂字符串的格式 正则表达式&#xff1a;记录文本规则的代码 正则表达式特点&#xff1a; 语法令人头疼&#xff…

立创eda专业版学习笔记(4)(隐藏铺铜)

这里的隐藏有两个意思&#xff0c;一个是铺铜过后把铺铜的填充区域隐藏&#xff0c;方便看图&#xff0c;另外一个是隐藏铺铜的轮廓&#xff0c;方便后续改进。 第一种隐藏&#xff0c;隐藏铺铜的填充区域&#xff08;成片的图块&#xff09;&#xff0c;但是保留轮廓线 这是全…

联想LJ2655DN激光打印机清零方法

联想LJ2655DN激光打印机是市面上常见的打印机,为了节约成本,我们一般使用都是代用硒鼓来代替原装硒鼓,但是发现更换完硒鼓以后还是不能打印甚至有的机器能够打印但是打印速度会变慢或很慢,这个时候这就需要我们对打印机进行清零复位操作了,此款机器因用户更换的硒鼓类型不…

C++ 模板进阶

目录 1. 非类型模板参数 2. 模板的特化 2.1 概念 2.2 函数模板特化 2.3 类模板特化 2.3.1 全特化 2.3.2 偏特化 2.3.3 类模板特化应用示例 3. 模板总结 1. 非类型模板参数 我们在C语言中使用数组的时候可以定义静态数组&#xff0c;但是有个缺陷就是编译器在对越界检查…