C语言字符函数和字符串函数(1)

news2024/12/24 9:01:49

大家好,我们又见面了,让大家久等了,我们今天就来学习字符函数和字符串函数。

在这里插入图片描述

在开启今天的学习之前呢,我来解决一下一些小伙伴平时找不到库函数使用的烦恼,因为我们cplusplus.com最新版本不能够查询函数,我们需要去找我们需要使用的函数,所以就很麻烦,我们可以将它切换成老版本就可以进行查询了。
在这里插入图片描述

在这里插入图片描述
我们只要点击这个红色框就能够切换成老版本了。
在这里插入图片描述
然后我们点击红色框输入我们想要知道的函数就可以实现查询了。

1.strlen函数

在这里插入图片描述

我们以前接触过这个函数,这个函数是用来求字符串或字符长度的对吧,求的是‘/0’之前的字符个数。
我们在这里需要注意的是:
字符串已经 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包
含 ‘\0’ )
参数指向的字符串必须要以 ‘\0’ 结束。
注意函数的返回值为size_t,是无符号的( 易错 )
学会strlen函数的模拟实现

那么我们怎么来使用它呢,我们看到代码:

#include <stdio.h>
#include<string.h>
int main()
{
const char*str1 = "abcdef";
const char*str2 = "bbb";
if(strlen(str2)-strlen(str1)>0)
{
printf("str2>str1\n");
}
else
{
printf("srt1>str2\n");
}
return 0;
}

在这里插入图片描述

我们因为str1里面‘\0’前面有六个字符,所以strlen的结果就是6,而str2的结果就只有3,但是我们这里函数的返回类型size_t,也就是无符号数,我们得到的结果是-3,但是我们这里的结果之后也得转化为一个无符号数,就会是一个很大的正数,所以结果就会输出str2>str1。

那么怎么对这个函数模拟实现呢?

#include<stdio.h>
#include<assert.h>
#include<windows.h>
 
int my_strlen(const char *str)
{
	int count = 0;
	assert(str != NULL);//断言,指针为空,打印出错误信息
	while (*str++)//遇到'\0'停止,不算'\0'
	{
		count++;
	}
	return count;
}

int main()
{
	int len=0;
	char *p = "abcdef";
	len=my_strlen(p);
	printf("len=%d\n", len);
	system("pause");
	return 0;
}

在这里插入图片描述

这里我们要注意我们的传过去的*p,因为我们只求它的字符个数,所以我们不用改变它,就给它用const进行保护,我们为了防止空指针,所以要给它进行断言,我们在使用断言的时候,我们要加上头文件#include<assert.h>,因为我们这里是要求它的字符个数,所以我们需要碰到一个字符就给它计数,所以我们要定义一个计数器,并且对它初始化,我们接下来就利用循环结构就行,当我们碰到一个字符就计数,碰到‘\0’的时候得到’\0’,它的Ascall值为0,所以我们碰到‘\0’的时候就为假,就跳出循环了,最后在将结果返回主函数进行打印。

2.strcpy

在这里插入图片描述

源字符串必须以 ‘\0’ 结束。
会将源字符串中的 ‘\0’ 拷贝到目标空间。
目标空间必须足够大,以确保能存放源字符串。
目标空间必须可变。
学会模拟实现。

接下来我们就给它模拟实现以下:

#include<stdio.h>
#include<string.h>
#include<assert.h>

char* my_strcpy(char* dest, const char* src)
{
	char* ret = dest;
	assert(dest && src);

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

int main()
{
	char arr1[20] = { 0 };
	char arr2[] = "abc";

	/*my_strcpy(arr1, arr2);
	printf("%s\n", arr1);*/


	printf("%s\n", my_strcpy(arr1, arr2));
	return 0;
}

在这里插入图片描述

我们这里定义两个字符数组,将这两个数组的地址传到我们自定义的函数my_strcat中,通过两个指针接收,这里我们依然要给它进行断言,因为我们要把第二个数组的元素拷贝到第一个元素当中,所以我们第二个元素是不变的,所以就用const对它进行保护,首先我们用一个循环找到数组的一个末尾,然后再循环将指针str中的内容拷贝到指针dest中,当dest为’/0’时,整个式子的结果为假就跳出循环。再将指针ret储存的数据返回进行打印。

3.strcat

在这里插入图片描述

连接函数
源字符串必须以 ‘\0’ 结束。
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改。
字符串自己给自己追加,如何

char* my_strcat(char* dest, const char* src)
{
	char* ret = dest;
	assert(dest && src);
	//1. 找到目标空间的末尾
	while (*dest != '\0')
	{
		dest++;
	}
	//2. 数据追加
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}

int main()
{
	char arr1[20] = "abc";
	strcat(arr1, arr1);//strncat
	printf("%s\n", arr1);

	return 0;
}

在这里插入图片描述

在这里插入图片描述

在这个函数我们要知道连接函数strcat和拷贝函数strcpy一样,我们要连接的数组是从上一个数组的‘/0’开始,而且第二个数组的‘\0’也会连接到上一个数组作为结束的标志。所以当我们字符串自己给自己追加也会打印出结果。我们在这里也要进行断言,为了防止变成空指针。

4.strcmp

在这里插入图片描述

比较字符串函数:
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字

那么我们怎么去比较两个字符串的大小呢?我们其实是比较两个字符串函数之间对应位置字符的ASCLL值的小,如果前一个相同的话就比较下一个,一直比较下去直到比较出大小为止。
在这里插入图片描述

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;
}

int main()
{
	char arr1[] = "abq";
	char arr2[] = "abc";
	if (my_strcmp(arr1, arr2) > 0)
	{
		printf(">\n");
	}
	else
	{
		printf("<=\n");
	}

	return 0;
}

在这里插入图片描述

我们这里将两个数组的地址传到函数中,我们进入循环中,如果第一个字符的值都相等,如果此时的str1=‘/0’的话,那么str2也为’\0’,所以两个字符串大小相等,如果str1!=0,那么我们就进行下一个字符的比较,最后返回str1-str2到主函数中进行判断和打印结果。

5.strncpy, strncat,strncmp

我们看到这里的三个函数和上面我们刚学的一些函数有些相似,那么我们就以strcpy和strncpy函数为例来讲解。
在这里插入图片描述

我们发现下面这个函数多了一个参数,而且是一个无符号数的参数,那么这个参数具体的作用是什么呢?其实这个参数是进行限制作用的,我们这个拷贝函数,如果给num一个值,那么num就是我们拷贝过去的字符个数。

int main()
{
	char arr1[20] = { 0 };
	char arr2[] = "abcdefghi";
	strncpy(arr1, arr2, 3);
	printf("%s\n", arr1);
	return 0;
}

在这里插入图片描述
因为我们这里传的参数是3,所以我们只拷贝三个字符上去,所以得到的结果是abc。

int main()
{
	char arr1[20] = "abc\0xxxxxxxxxxxxxx";
	char arr2[] = "defghi";
	strncat(arr1, arr2, 10);
	printf("%s\n", arr1);

	return 0;
}

在这里插入图片描述

我们这里用的连接函数是10个字符,所以我们全部都可以连接上去。但是我们要注意拷贝的时候如果我们要拷贝10个字符上去,而我们这个数组少于10个字符的时候后面多的位置就会补充’\0’,而我们的连接函数则不会补充’\0’,这就是这两个函数的区别。另外两个也是类似的,这里就不一一进行讲解了。

6.strstr

在这里插入图片描述
上面这个是c++,而下面这个才是我们C语言的库函数。这个函数的作用呢就是在一个字符串里找到我们出现的字符串。也就是说要从我们str1里面找到str2的字符串。

#include<stdio.h>
#include<assert.h>
const char* my_strstr(const char* str1, const char* str2)
{
	const char* cp;//记录开始匹配的位置
	const char* s1;//遍历str1指向的字符串
	const char* s2;//遍历str2指向的字符串

	assert(str1 && str2);
	if (*str2 == '\0')
		return str1;

	cp = str1;
	while (*cp)
	{
		s1 = cp;
		s2 = str2;
		while (*s1 && *s2 && *s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
			return cp;

		cp++;
	}
	return NULL;
}

int main()
{
	char arr1[] = "abbbcdef";
	char arr2[] = "bbc";

	const char* ret = my_strstr(arr1, arr2);
	if (ret == NULL)
	{
		printf("找不到\n");
	}
	else
	{
		printf("%s\n", ret);
	}

	return 0;
}

在这里插入图片描述
在这里插入图片描述

在做这个题的时候我们需要用到多个指针,因为我们要两个指针指向刚开始的位置,用另外的指针去移动,在用指针给储存起来,在这里我们的s1和s2指针是用来遍历的,我们先用if语句进行判断,如果我们的str2为’\0’时,就返回str1,因为我们在集合中就已经知道空集合是任意集合的子集,当我们的str2指针为’\0’时,我们才会将str1的指针用cp来接收,然后我们将cp指针和str2指针分别赋给s1和s2指针,前提是cp不能为不能为’\0’,然后我们进入下一个循环,当s1和s2为’\0’和s1与s2相等时,我们就给他们进行下一个字符的比较,如果不相等我们就跳出循环,跳出循环后要对指针s2进行判断,如果我们的s2指针为’\0’的话,我们就返回cp,cp++我们就下一个字符作为第一个字符开始遍历,如果一直到指针cp为’\0’的时候都没有找到,那就返回NULL空指针。

7.strtok

在这里插入图片描述

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

这个函数的作用是用分隔符将我们的一些字符串给分隔开,而我们将分隔符储存到一个指针sep中,当我们需要用到的时候就给它传参就行了。

int main()
{
	char arr[] = "zpengwei@yeah.net";

	char buf[200] = {0};//"zpengwei@yeah.net"
	strcpy(buf, arr);

	char* p = "@.";
	char* s = strtok(buf, p);
	printf("%s\n", s);

	s = strtok(NULL, p);
	printf("%s\n", s);

	s = strtok(NULL, p);
	printf("%s\n", s);

	return 0;
}

在这里插入图片描述

我们将分隔符@和.存入一个指针p中,当我们对字符串进行操作的时候我们就取分隔符前面的字符串,并且将分隔符的位置保存下来,然后我们想要对下面的字符串进行打印的话,就要重复对字符串进行该函数操作,不过这里传参不同,我们传参的第一个位置变成了空指针NULL,而我们的就会从上一次标记的地方开始,找到下一个分隔符,将字符串输出。

8. strerror

在这里插入图片描述

这个函数的作用是返回错误码,所对应的错误信息。

#include<errno.h>
int main()
{
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d: %s\n", i, strerror(i));
	}

	return 0;
}

在这里插入图片描述

在使用这个函数我们会用到全新的头文件,这个我们要记得,然后由于我们这个函数的作用是返回错误码所对应的信息,我们就可以利用循环来查看0到9的错误码所代表的信息。

好了,学到这里大家一定都很累了吧,我们今天的学习就到这里了,我们下次再见,谢谢大家。

在这里插入图片描述

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

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

相关文章

C盘扩容(微PE工具箱)

C盘扩容&#xff08;微PE工具箱&#xff09; 1、关闭Bitlocker2、安装微PE3、以D盘分10G给C盘为例3.1安装后重启会出现两个选项电脑系统和PE系统&#xff0c;选择PE系统3.2调成分区空间3.3检查分盘情况并删除PE系统 1、关闭Bitlocker 2、安装微PE https://www.wepe.com.cn/dow…

2023年招标行业研究报告

第一章 行业概况 1.1 招标定义和分类 招标行业涉及政府、企事业单位通过公开、公平、公正的手段组织采购、工程建设等项目的过程。尽管中国的招标行业发展历程相对较短&#xff0c;但随着市场经济的深入发展和政府采购制度的持续改革&#xff0c;该行业已逐渐崭露头角&#x…

《遇见秋分》公众号排版模板,感受秋天的文艺唯美

秋分,是二十四节气之第十六个节气,秋季第四个节气。秋分这天太阳几乎直射地球赤道,全球各地昼夜等长。秋分&#xff0c;“分”即为“平分”、“半”的意思,除了指昼夜平分外,还有一层意思是平分了秋季。秋分日后,太阳光直射位置南移,北半球昼短夜长&#xff0c;昼夜温差加大,气…

ptmalloc源码分析 - Top chunk的扩容函数sysmalloc实现(09)

目录 一、sysmalloc函数基本分配逻辑 二、强制try_mmap分配方式 三、非主分配区分配的实现 1. 设置老的Top chunk的参数 2. 尝试使用grow_heap函数 3. 尝试使用new_heap函数 4. 尝试使用try_mmap方式 四、主分配区分配的实现 1. 设置Top扩容的size值 2. brk分配成功的…

(25)(25.1) 光学流量传感器的测试和设置

文章目录 25.1.1 测试传感器 25.1.2 校准传感器 25.1.3 测距传感器检查 25.1.4 预解锁检查 25.1.5 首次飞行 25.1.6 第二次飞行 25.1.7 正常操作设置 25.1.8 视频示例&#xff08;Copter-3.4&#xff09; 25.1.9 空中校准 25.1.1 测试传感器 将传感器连接至自动驾驶仪…

面试官:Vue3.0里为什么要用 Proxy API 替代 defineProperty API ?

&#x1f3ac; 岸边的风&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 一、Object.defineProperty 为什么能实现响应式 小结 二、proxy 三、总结 一、Object.defineProperty 定义&am…

vue打印、vue-print-nb插件的基本使用

今天做项目碰到一个打印的需求&#xff0c;只打印一个表格&#xff0c;去网上找了些方法总结一下 打印的方法最常见的就是window.print(),这是浏览器自带的打印方法&#xff0c;方便快捷无需安装插件&#xff0c;但相应的自定义化也差无法打印页面局部&#xff0c;去网上查找资…

薄盒借周杰伦IP卖藏品 车翻在奈雪的茶

在瑞幸联名茅台、喜茶联名FENDI、茶百道联名米哈游后&#xff0c;奈雪的茶搭上了周杰伦。9月14日&#xff0c;在《范特西》专辑发行22周年之际&#xff0c;奈雪的茶推出“范特西音乐宇宙”主题的奶茶与周边。 周杰伦系IP加持&#xff0c;奈雪的茶卖爆了&#xff0c;范特西Styl…

淘宝天猫商品全网搜索接口,关键词搜索商品列表数据接口,淘宝API接口申请指南

淘宝搜索接口是一种提供更便捷的淘宝商品搜索服务的工具。通过该接口&#xff0c;用户可以更加快速地找到自己需要的商品&#xff0c;节省时间和精力。 淘宝关键字搜索接口主要用于以下几个方面的业务应用&#xff1a; 商品搜索。用户可以根据关键字搜索他们想要购买的商品。…

生信学院|09月20日《在线焊件建模——xFrame》

课程主题&#xff1a;在线焊件建模——xFrame 课程时间&#xff1a;2023年09月20日 14:00-14:30 主讲人&#xff1a;武旭 生信科技 售后服务工程师 1、3DEXPERIENCE设计平台介绍 2、xFrame设计工具使用 3、Q&A 请安装腾讯会议客户端或APP&#xff0c;微信扫描海报中的…

【深度学习】clip-interrogator clip docker 容器启动过程

文章目录 dockerfile备忘ENTRYPOINT ["bash", "/app/startProject.sh"]常用docker指令web服务脚本访问接口文件 给一张图片&#xff0c;输出图片描述。 dockerfile备忘 只有从dockerfile制作的镜像才有分层结构&#xff0c;加速传输&#xff0c;故第一步…

Linux内核源码分析 (B.2)深入理解 Linux 物理内存管理

Linux内核源码分析 (B.2)深入理解 Linux 物理内存管理 文章目录 Linux内核源码分析 (B.2)深入理解 Linux 物理内存管理[TOC] 1\. 前文回顾2\. 从 CPU 角度看物理内存模型2.1 FLATMEM 平坦内存模型2.2 DISCONTIGMEM 非连续内存模型2.3 SPARSEMEM 稀疏内存模型2.3.1 物理内存热插…

MySQL常见面试题(一)

&#x1f600;前言 在数据库管理系统中&#xff0c;存储引擎起着核心的角色&#xff0c;它决定了数据管理和存储的方式。MySQL作为一个领先的开源关系型数据库管理系统&#xff0c;提供了多种存储引擎来满足不同的需求和优化不同的应用。除了选择合适的存储引擎&#xff0c;数据…

拉格朗日乘子法思路来源

核心思路:由果索因 一. 直观理解 1. 问题描述 对于如"图1"式(等式约束优化问题, 可行域是边界), 转化成拉格朗日乘子法的思路来源: 图1: 拉格朗日乘子法问题描述图 如"图2",f为曲面.c为平面, 黑色加粗线是f和c的交线.(约束就是限制自变量的变化范围). …

Llama2-Chinese项目:2.1-Atom-7B预训练

虽然Llama2的预训练数据相对于第一代LLaMA扩大了一倍&#xff0c;但是中文预训练数据的比例依然非常少&#xff0c;仅占0.13%&#xff0c;这也导致了原始Llama2的中文能力较弱。为了能够提升模型的中文能力&#xff0c;可以采用微调和预训练两种路径&#xff0c;其中&#xff1…

聚观早报|蔚来汽车首颗自研芯片;中式汉堡正打破“麦门永存”

【聚观365】9月19日消息 蔚来汽车首颗自研芯片 中式汉堡正在打破“麦门永存” 三星Galaxy S24系列入网 特斯拉电动皮卡预订量已超过200万辆 郭明錤称iPhone 15 Pro Max需求强劲 蔚来汽车首颗自研芯片 蔚来汽车正在进行自研芯片布局&#xff0c;蔚来汽车硬件副总裁白剑上个…

慢SQL治理经验总结

在过去两年的工作中&#xff0c;我们团队曾负责大淘宝技术的慢SQL治理工作&#xff0c;作为横向的数据安全治理平台&#xff0c;如何快速准确地发现部门内所有应用的慢SQL&#xff0c;并进行高效的推动治理&#xff0c;同时覆盖多个开发、生产环境&#xff0c;是一个很大的挑战…

机器人掀起“智能热潮”:揭秘中国机器人市场的新风貌

原创 | 文 BFT机器人 中国的机器人市场和自动化形势从未像今年这样令人兴奋。去年&#xff0c;全球超过一半的工业机器人在中国销售。2023年上半年&#xff0c;中国机器人需求趋势仍在继续上升&#xff0c;根据估算&#xff0c;在此期间销售的工业机器人数量约为14.5万台&…

用Python分析文本数据的词频并词云图可视化(文末送书)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

广播风暴的分析和解决方法(STP配置)

目录 1.广播风暴 2.解决方法&#xff1a;配置STP 1.广播风暴 以下图为例 配置交换机LSW1 <Huawei>sys Enter system view, return user view with CtrlZ. [Huawei]sysname LSW1 [LSW1]stp Sep 14 2023 05:35:15-08:00 LSW1 DS/4/DATASYNC_CFGCHANGE:OID 1.3.6.1.4.1.…