【C语言】字符函数与字符串函数(下)

news2024/9/24 3:29:33

字符函数与字符串函数(下)

文章目录

  • 字符函数与字符串函数(下)
  • 1.strncpy的使用和模拟实现
    • 1.1使用示例:
    • 1.2模拟实现
  • 2.strncat的使用和模拟实现
    • 2.1使用示例:
    • 2.2模拟实现
  • 3.strncmp的使用和模拟实现
    • 3.1使用示例:
    • 3.2模拟实现
  • 4.strstr函数
    • 4.1使用示例:
    • 4.2模拟实现
  • 5.strtok函数
    • 5.1示例;
  • 6.strerror函数
  • 6.1示例:
    • 6.2额外补充


1.strncpy的使用和模拟实现
2.strncat的使用和模拟实现
3.strncmp的使用和模拟实现
4.strstr的使用和模拟实现
5.strset函数
6.strerror函数

在上一篇文章中学习了strcpy,strcat,strcmp,这一篇接着上篇继续介绍

1.strncpy的使用和模拟实现

在这里插入图片描述

strncpy实在strcpy的基础上可以限制拷贝过去字符的个数

函数声明:

char* strncpy(char* destination, char* source, size_t num);

注意事项:

如果源字符串的长度小于num个,则拷贝完源字符串后,在目标后面追加0,直到num个

1.1使用示例:

int main()
{
	char s[20] = { 0 };
	char a[6] = "world";
	strncpy(s, a, 10);
	printf("%s", s);
	return 0;
}

在这里插入图片描述

1.2模拟实现

char* my_strncpy(char* s, char* a, size_t num)
{
	char* m = s;//记录目标空间的初始位置
	int count = 0;
	while (count <= num)
	{
		*s++ = *a++;
		count++;
		
	}
	printf("%s", m);
}
int main()
{
	char s[20] = { 0 };
	char a[15] = "hello world";
	my_strncpy(s, a, 8);
	return 0;
}



2.strncat的使用和模拟实现

在这里插入图片描述
strncat是可以指定在目标空间追加规定个字符,再追加一个’\0’.

注意事项:

如果源字符串的长度小于num的个数,只会将源字符串’\0’之前的内容追加到目标空间

函数声明:

char* strncat(char* destination, char* source, size_t num);

2.1使用示例:

int main()
{
	char s[20] = "hello ";
	char a[10] = "world";
	strncat(s, a, 3);
	printf("%s", s);
	return 0;
}

2.2模拟实现

char* my_strncat(char* s, char* a, size_t num)
{
	char* m = s;
	int count = 1;
	while (*s)
	{
		s++;
	}
	while(count<=num)
	{
		*s++ = *a++;
	
		count++;
	}
	printf("%s", m);
}
int main()
{
	char s[20] = "hello ";
	char a[10] = "world";
	my_strncat(s, a, 3);


	return 0;
}

在这里插入图片描述

3.strncmp的使用和模拟实现

在这里插入图片描述
比较str1和str2的前num个字符,如果相等,就继续向后比较,最多比较num个字符,如果提前找到不同,就提前结束,大的所在字符大于零一个字符;如果num个字符都相等,就返回0;

函数声明:

int strncmp(const char* str1,const char*str2,size_t num);

3.1使用示例:

int main()
{
	char s[10] = "abcdef";
	char a[10] = "abcdeg";
	int ret = strncmp(s, a, 5);
	printf("%d", ret);
	return 0;
}

3.2模拟实现

char* my_strncmp(char* s, char* a, size_t num)
{
	int count = 0;
	while (*s == *a)//注意这里如果是一个等号的话,就相当于把*a的值赋给了*s
	{
		s++;
		a++;
		count++;
		if (*s == '\0' || count==num)
			return 0;
	}
	return *s - *a;
}
int main()
{
	char s[10] = "abcdef";
	char a[10] = "abcdeg";
	int ret=my_strncmp(s, a, 5);
	printf("%d", ret);
	return 0;
}

4.strstr函数

在这里插入图片描述
函数声明:

char* strstr(const char*str1,const char*str2);

在上边的图片中很容易知道该函数的返回值,同时,在strstr函数中,字符串的匹配不包含’\0’,以’\0’作为结束标志。

4.1使用示例:

int main()
{
    char str[30] = "This is a simple string";
    char* pch = 0;//创建一个指针接受strstr的返回值
   
    pch = strstr(str, "simple");
    
    strncpy(pch, "sample", 6);
    printf("%s",str);
    return 0;
}

在这里插入图片描述
到这一点代码都还是很容易理解的

4.2模拟实现

在这里插入图片描述
分析:

很明显,看图首先我们先创建了一个指针变量m来记录str1的初始位置,方便后边找到他和使用他
然后我们想找到str1中是否含有str2,那就要一个一个字符进行对比,如果是str1=‘abcdef’,str2=‘bcde’,那很容易找到

复杂一点的情况就是出现如图所示的情况,当我们对比一半的时候发现出现不一样了

那怎末解决呢?
确定一个对比的起点,从这个起点开始一一比较,不符合,向后走,再以后一个字符作为比较的起点

因此我们又创建了两个指针变量,e1 和e2,首先以e1为起点,从e2开始一点点比较,出现不符合时,e1向后移一位,作为起点,e2重新开始与以e1+1为起点的字符串开始一一比较

char* my_strstr(const char* a, const char* b)
{
	char* m = a;
	char* e1;//记录a开始比较的位置
	char* e2;//记录b开机比较的位置
	if (!*b)
		return a;//排除掉b是空指针的情况,如果是空指针返回a
	while (*m)
	{
		e1 = m;//一个一个位置开始比较
		e2 = b;
		while (*e1 && *e2 && *e1 == *e2)//确保*e1和*e2都不为空
		{
			e1++;
			e2++;
		}
		if (*e2 == '\0')//说明找到了str2最后的位置,此时的m的位置就是str2首次出现的位置
			return m;
		m++;//当出现不同,并且也没有走到str2的最后时,说明此时的起点不对,向后移一位在开始一个一个比较
	}
	return (NULL);//当m一直向后走寻找新的起点,一直都没找到时返回空指针
}
int main()
{
	char a[20] = "aaabcdef";
	char b[10] = "aabcdd";
	char* pch=my_strstr(a, b);
	if (pch != (NULL))
		printf("有");
	else
		printf("无");

	return 0;
}

在这里插入图片描述
上边给的代码例子就是当我们以第二个a为起点的时候,找到最后发现不同的情况

5.strtok函数

在这里插入图片描述
函数声明;

char*strtok(char* str,const char* sep);

上面图片的解释可能不太好理解,再来解析一下这个函数的用法
sep这个参数它指向了一个字符串,定义了一个用作分隔符的字符集合

str指定一个字符串,它包含了0个或多个sep中一个或多个分隔符分割的标志

strtok找到str中的下一个标记,并将其用’\0\结尾,返回一个指向这个标记的指针
需要注意的是,strtok函数会改变str字符串的内容,所以被分割的字符串通常是临时拷贝的,且可以修改的

strtok的第一个参数不是空指针时,函数将找到str中的第一个标记,并保存他在字符串中的位置

strtokd的第一个参数是空指针时,函数在同一字符串被保存的位置开始,找下一个标记

如果不再存在更多的标记,返回空指针

5.1示例;

int main()
{
	char s[100] = "123.4.56";
	char* sep = ".";
	char* str = NULL;
	for (str = strtok(s, sep); str != NULL; str = strtok(NULL, sep))//初始化先找到第一个标记,调整部分是第一个参数是空指针,就在标记的地方继续找下一个标记
		//条件是str不是空指针,因为如果找不到下一个标记,就会返回空指针
	{
		printf("%s\n", str);//输出123
		//4
		//56
	}
	return 0;
}

在看一个,理解一下

int main()
{
	char s[100] = "_this,a simple thing";
	char* pch;
	printf("Splitting string\"%s\"into tokens\n", s);//先把字符串s 加进来输出
	pch = strtok(s, "_, ");//先找到第一个标记,这里设置的间隔标记有三个分别是- ,和空格注意'\0'不能做分隔符,读到'\0'字符串就结束了
	while (pch != NULL)
	{
		printf("%s\n", pch);//输出this  a sample thing
		pch = strtok(NULL, "_, ");//从上一次标记开始向后找到下一个标记
	}
	return 0;
}

理解完上边的例子,下边这个就很容易理解了

int main()
{
	char s[20] = "hello,wor\0ld";
	char* pch;
	for (pch = strtok(s, ",\0"); pch != NULL; pch = strtok(NULL, ",\0"))
	{
		printf("%s", pch);//输出hellowor
	}
	return 0;
}

6.strerror函数

char* strerror(int errnum);

strerror函数可以把参数部分错误码对应的错误信息的字符串地址返回来

注意:

1.不同的系统和c语言标准库都规定了一些错误码,一般是放在<errno.h>这个头文件
2.C语言使用一个全局变量errno来记录程序的当前错误,程序启动时errno为0;表示没有错误
3.当使用标准库函数发生错误时,就会将对应的错误码放在errno中,strerror函数就可以把错误对应的错误信息字符串的地址返回

6.1示例:

#include<errno.h>
int main()
{
	//printf(strerror(errno));
	int i = 0;
	for (i = 0; i <= 10; i++)
	{
		printf("%s\n", strerror(i));//展示出可能出现的错误的原因
	}
	return 0;
}

在这里插入图片描述
写一个代码看看他是怎么使用的

int main()
{
	FILE* pFile;//声明了一个指向FILE类型的指针pFile,用于文件操作
	pFile = fopen("unexit.ent", "r");//使用fopen函数尝试以只读模式('r')打开名为unexit.ent的文件,并返回文件的指针赋值给pFile;
	if (pFile == NULL)//判断文件是否为空,若为空打开失败,输出失败的原因
	{
		printf("error opening file unexit.ent:%s\n", strerror(errno));//这个失败的原因是我根本就没有这个文件
	}
	return 0;
}

在这里插入图片描述

6.2额外补充

也可以了解一下perror函数
他相当于一次把打印和调用strerror函数完成了,将直接把错误信息打印出来,并且在他打印完参数后,会打印一个冒号和空格再打印错误信息

int main()
{
	FILE* pFile;
	pFile = fopen("unexit.ent", "r");
	if (pFile == NULL)
	{
		perror("error opening file unexit.ent");//这个失败的原因是我根本就没有这个文件
	}
	return 0;
}

在这里插入图片描述

作者有话说:作者只是一直刚学的小白,以上理解均是作者学习完后对知识的理解,如有错误和不当,感谢指出,如感到有帮助,请留下一个👍

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

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

相关文章

方法汇总 | Pytorch实现常见数据增强(Data Augmentation)【附源码】

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发…

目标检测 | yolov10 原理和介绍

相关系列&#xff1a; 目标检测 | yolov1 原理和介绍 目标检测 | yolov2/yolo9000 原理和介绍 目标检测 | yolov3 原理和介绍 目标检测 | yolov4 原理和介绍 目标检测 | yolov5 原理和介绍 目标检测 | yolov6 原理和介绍 目标检测 | yolov7 原理和介绍 目标检测 | yolov8 原理和…

JS TypeError: Cannot read properties of null (reading ‘getAttribute’) 解决

JS TypeError: Cannot read properties of null (reading ‘getAttribute’) 解决 在JavaScript开发中&#xff0c;TypeError: Cannot read properties of null (reading getAttribute) 是一个常见的错误&#xff0c;它表明你尝试从一个值为null的对象上调用getAttribute方法。…

【AI学习】人工智能的几种主义

无意翻开了杨立昆的《科学之路》&#xff0c;书前有好多人作序&#xff0c;数了一下&#xff0c;八个人的序言&#xff0c;说明&#xff0c;至少有八个人读过这本书。其中黄铁军教授讲到了机器学习的发展历程。 人工智能发展历程中的各种主义&#xff0c;对于外行人大概都是如我…

微信好友恢复,分享4大技巧,快速恢复微信好友

在微信的社交网络中&#xff0c;好友关系的维护至关重要。但有时候&#xff0c;由于误操作或其他原因&#xff0c;我们可能会不小心删除了某些重要联系人。那么&#xff0c;如果想再度找回这些好友&#xff0c;我们应该使用什么方法呢&#xff1f; 别担心&#xff0c;本文将分…

4-1-4 步进电机原理1(电机专项教程)

4-1-4 步进电机原理1&#xff08;电机专项教程&#xff09; 4-1-4 步进电机原理1步进基本工作原理步进电机优点步进电机主要部件步进电机基本原理步进电机分类双极性单极性步进电机 4-1-4 步进电机原理1 如何使用arduino控制步进电机 步进电机从原理和工作方法上都更加复杂一些…

打靶记录13——doubletrouble

靶机&#xff1a; https://www.vulnhub.com/entry/doubletrouble-1,743/ 难度&#xff1a; 中 目标&#xff1a; 取得两台靶机 root 权限 涉及攻击方法&#xff1a; 主机发现端口扫描Web信息收集开源CMS漏洞利用隐写术密码爆破GTFObins提权SQL盲注脏牛提权 学习记录&am…

CSP-CCF 202305-1 重复局面

一、问题描述 【题目背景】 国际象棋在对局时&#xff0c;同一局面连续或间断出现3次或3次以上&#xff0c;可由任意一方提出和棋。 【问题描述】 国际象棋每一个局面可以用大小为 88 的字符数组来表示&#xff0c;其中每一位对应棋盘上的一个格子。六种棋子王、后、车、象、…

STL六大组件

STL&#xff08;Standard Template Library&#xff0c;标准模板库&#xff09;是C标准库的一部分&#xff0c;提供了丰富且高效的数据结构和算法。STL主要由6大组件构成&#xff0c;分别是容器、算法、迭代器、适配器、仿函数和空间配置器。 容器&#xff08;Containers&#…

Midjourney进阶-反推与优化提示词(案例实操)

​ Midjourney中提示词是关键&#xff0c;掌握提示词的技巧直接决定了生成作品的质量。 当你看到一张不错的图片&#xff0c;想要让Midjourney生成类似的图片&#xff0c;却不知道如何描述画面撰写提示词&#xff0c;这时候Midjourney的/describe指令&#xff0c;正是帮助你推…

AIoTedge边缘计算平台V1.0版本发布

AIoTedge边缘计算平台V1.0&#xff0c;一款创新的AIoT解决方案&#xff0c;现已正式发布。该产品集成了NodeRED软网关、边缘物联网平台和边缘AI能力&#xff0c;为企业提供强大的边云协同能力。它支持设备管理和泛协议接入&#xff0c;确保不同设备间的无缝连接。AIoTedgeV1.0还…

SQL-事务与并发问题

在数据库管理系统中&#xff0c;事务是一个重要的概念&#xff0c;它确保了一组数据库操作要么全部成功&#xff0c;要么全部失败&#xff0c;从而维护数据的完整性和一致性。随着多个用户同时访问数据库&#xff0c;事务的并发处理变得尤为重要。 1. 事务的定义 事务是指一组…

一文读懂推荐系统

随着互联网的飞速发展&#xff0c;信息过载已经成为了一个普遍的问题。我们每天都要面对大量的内容&#xff0c;却很难找到真正符合自己兴趣和需求的信息。这时&#xff0c;推荐系统应运而生&#xff0c;它能够根据用户的兴趣和行为&#xff0c;智能地推荐相关内容&#xff0c;…

​与辉同行2日破亿,打工就是在浪费生命,真让罗永浩说对了!​

去年东方甄选的小作文事件发生之后 罗永浩就鼓励董宇辉出来单干还发表了惊天言论&#xff0c;“打工就是在浪费生命” 董宇辉接手“与辉同行”公司后&#xff0c;两天直播总销售额就已经超过了1亿元 难道真让罗永浩说对了&#xff0c;打工就是在浪费生命吗&#xff1f; 打工…

20240819解决飞凌的OK3588-C的核心板的适配以太网卡RTL8211F-CG在百兆模式下通过交换机上外网

20240819解决飞凌的OK3588-C的核心板的适配以太网卡RTL8211F-CG在百兆模式下通过交换机上外网 2024/8/19 18:00 缘由&#xff1a;由于自制的飞凌的OK3588-C的核心板的底板对空间要求高/敏感&#xff0c;并且对网速要求不高&#xff0c;百兆即可满足要求。 也就直接使用千兆网卡…

质量体系 | 这些医疗器械质量管理标准/法规有什么区别?

在医疗器械行业中&#xff0c;确保产品质量和安全至关重要&#xff0c;而ISO 9001、ISO 13485、GMP、中国《医疗器械生产质量管理规范》和QS820等标准/法规为行业提供了明确的指导。 ISO9001 ISO9001:2015 Quality management systems-Requirements&#xff08;质量管理体系要…

通过ros2服务来控制程序的启动和关闭

运行handle.py程序&#xff0c;启动服务节点&#xff0c;调用服务节点控制程序的启动和关闭&#xff0c;本例为启动和关闭一个python程序&#xff08;每隔一秒打印hello,world&#xff09;&#xff0c;运行截图如下: 一、创建服务节点 handle.py import rclpy from rclpy.no…

无人机之航拍挑选注意事项

航拍无人机的挑选&#xff0c;主要从安全稳定、航拍画质、云台防抖、图传距离、续航时间等因素来考虑。 一、安全稳定 安全稳定性&#xff0c;是我们选择航拍无人机的首要参考标准。毕竟再好的镜头、再好的外形设计、再好的航拍功能&#xff0c;如果没有安全稳定的飞行&#x…

【若依 - 前后端不分离版】SysCaptchaController 详解:生成与处理验证码

文章目录 一、SysCaptchaController 类概述1. 类的功能2. 主要功能 二、验证码生成流程1. 接口定义2. 代码流程解析2.1. 设置响应头2.2. 生成验证码2.3. 存储验证码2.4. 返回验证码图片 三、处理异常和流关闭1. 异常处理2. 流关闭 四、实际应用中的验证码处理1. 验证码生成和展…

【数模修炼之旅】05 拟合模型 深度解析(教程+代码)

【数模修炼之旅】05 拟合模型 深度解析&#xff08;教程代码&#xff09; 接下来 C君将会用至少30个小节来为大家深度解析数模领域常用的算法&#xff0c;大家可以关注这个专栏&#xff0c;持续学习哦&#xff0c;对于大家的能力提高会有极大的帮助。 1 拟合模型介绍及应用 …