(二)字符函数和字符串函数详细讲解和模拟实现(优化)

news2024/10/7 20:29:57

✨✨✨✨✨✨✨✨✨

    • 📗字符串查找函数:
      • 1.strstr函数
      • 2.strtok函数
    • 📔错误信息报告函数:
      • 1.strerror函数
    • 📓内存操作函数
      • 1.memcpy函数
      • 2.memmove函数
      • 3.memset函数
      • 4.memcmp函数
  • ❤️字符函数讲解
    • 📒字符分类函数
    • 📒字符转换函数

📗字符串查找函数:

1.strstr函数

库函数strstr

char * strstr ( const char *str1, const char * str2);
  • 返回一个指向str1中第一次出现的str2的指针,或者如果str2不是str1的一部分,则返回一个空指针。

模拟实现:

char* my_strstr(const char* str1, const char* str2)
{
	assert(*str2&&*str1)
	while (*str1)//查询完毕
	{
	   //记录初始位置
		char* cp1 = str1;
		char* cp2 = str2;
		while (*str1 == *str2)
		{
			str1++;
			str2++;
			//在相等的条件下,str2=='\0';表示查找完成
			if (*str2 == '\0')
			{
				return cp1;
			}
		}
		//返回初始位置
		str1 = cp1;
		str2 = cp2;
		str1++;
	}
	return NULL;
}

2.strtok函数

库函数strtok

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

注意:

  • sep参数是个字符串,定义了用作分隔符的字符集合
  • 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
  • strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
  • strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
  • strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
  • 如果字符串中不存在更多的标记,则返回 NULL 指针。
#include<stdio.h>
#include<string.h>
#include<assert.h>
int main()
{
	char arr1[] = "apple banana.pair";
	char arr2[] = " .";//以空格和.作为分隔符号

	char tem[30] = { 0 };
	strcpy(tem, arr1);//函数会更改原字符串,所以先拷贝,保证不改变源字符串

	char* ret = NULL;
	ret=strtok(tem, arr2);//若存在下一个标记,则返回标记的指针
	printf("%s\n", ret);
	
	ret = strtok(NULL, arr2);
	printf("%s\n", ret);

	ret = strtok(NULL, arr2);
	printf("%s\n", ret);
//这里只是个简单的例子,太过复杂。
	return 0;

}

在这里插入图片描述
优化:

#include<stdio.h>
#include<string.h>
#include<assert.h>
int main()
{
	char arr1[] = "apple banana.pair";
	char arr2[] = " .";

	char tem[30] = { 0 };
	strcpy(tem, arr1);

	char* ret = NULL;
	for (ret = strtok(tem, arr2); ret!=NULL;ret=strtok(NULL,arr2))
	{
		printf("%s\n", ret);
	}

	return 0;

}

📔错误信息报告函数:

1.strerror函数

库函数strerror

char * strerror ( int errnum );

返回错误码,所对应的错误信息。

注意:

/* strerror example : error list */
#include <stdio.h>
#include <string.h>
#include <errno.h>//必须包含的头文件
int main ()
{
  FILE * pFile;
  pFile = fopen ("unexist.ent","r");
  if (pFile == NULL)
    printf ("Error opening file unexist.ent: %s\n",strerror(errno));
    //errno: Last error number
  return 0;
}

在这里插入图片描述


📓内存操作函数

1.memcpy函数

void * memcpy ( void * destination, const void * source, size_t num );
  • 内存函数只是拷贝内存空间的内容,对内存空间内的类型无要求。(相比较strcpy范围更广)
  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
  • 这个函数在遇到 ‘\0’ 的时候并不会停下来。
  • 如果source和destination有任何的重叠,复制的结果都是未定义的。
#include<stdio.h>
#include<string.h>

int main()
{
	int arr1[11] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[11] = { 0 };
	//并不会因为是整形而无法复制;
	memcpy(arr2, arr1, 20);

	return 0;
}

请添加图片描述

  • 模拟实现
#include<stdio.h>
#include<assert.h>
char* my_memcpy(void* dest, void* src, size_t num)
//返回char*可根据我们需要更改
{
	assert(dest && src);
	char* ret = dest;
	while (num--)
	{
		*(char*)dest = *(char*)src;
		//void*类型无法直接++;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}
int main()
{
	int arr1[11] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[11] = { 0 };
	
	my_memcpy(arr2, arr1, 20);
	return 0;
}

在这里插入图片描述

代码更改:

memcpy(arr1+3, arr1, 20);

运行结果:

这里是引用

原因:是我们拷贝是先把4,5地址处的值拷贝成了1,2,之后当来源地址到了原本4,5的位置得到的来源拷贝内容就是之前拷贝过来的1,2,因此无法实现;那么有什么办法吗?

有的:
方法一:就是逆向拷贝;我们先拷贝5到8的地址处,再依次拷贝即可;这是一种很实用的方法,我们来简单总结一下;

这里是引用
位置1:此时dest小于src,并且有重叠部分,则此时只能正向复制;
位置2:此时dest大于src,并且有重叠部分,则此时只能逆向复制;(和上述例子相同)
位置3:代表着无重叠部分,正逆序都可以;

方法二:使用memmove函数;

2.memmove函数

void * memmove ( void * destination, const void * source, size_t num );
  • 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理。
    上述的例子我们就可以采用memmove函数实现:
memmove(arr1+3, arr1, 20);//更改一行代码就可以;
  • memmove模拟实现:

我们就借着上面例子的两种方法,直接用memcpy来实现:

int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[11] = { 0 };

	my_memmove(arr1+3, arr1, 20);
	for (int i = 0; i < 10; i++)
		printf("%d ", arr1[i]);
	
	return 0;
}

但实现我们只分两类即可,不管是否重叠,我们将dest>src都用逆序,因为在的有重叠部分只能用逆序,而无重叠部分都可以使用,为了方便我们统一逆序;dest<src也是如此

#include<stdio.h>
#include<assert.h>
char* my_memmove(void* dest, void* src, size_t num)
{
	assert(dest && src);
	char* ret = dest;
	if (dest < src)
	{
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		dest = (char*)dest + num-1;
		src = (char*)src + num-1;
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest -1 ;
			src = (char*)src -1 ;
		}
	}
	return ret;
}

优化一下:

char* my_memmove(void* dest, void* src, size_t num)
{
	assert(dest && src);
	char* ret = dest;
	if (dest < src)
	{
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		while (num--)
		//num--执行后num值变为19,直接可以加,并且这里提供--过程
		{
			*((char*)dest+num) = *((char*)src+num);
			//上述提供--过程,此处不在需要;
		}
	}
	return ret;
}

3.memset函数

void * memset ( void * ptr, int value, size_t num );

将ptr指向的空间内的num个字节的空间设置为你需要的值(value);

4.memcmp函数

int memcmp ( const void * ptr1, const void * ptr2, size_t num );
  • 比较从ptr1和ptr2指针开始的num个字节;
  • 返回值与strcmp相似;

❤️字符函数讲解

(函数头文件<ctype.h> 的链接点入,即可查询下列字符分类函数和字符转换函数)

📒字符分类函数

字符分类函数在判断字符的时候有一定作用:

函数如果符合条件返回真
iscntrl任何控制字符
isspace空白字符:空格‘ ’,换页‘\f’,换行’\n’,回车‘\r’,制表符’\t’或者垂直制表符’\v’
isdigit十进制数字 0~9
isxdigit十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A ~ F
islower小写字母a~z
isupper大写字母A~Z
isalpha字母a ~ z或A ~ Z
isalnum字母或者数字,a ~ z,A ~ Z,0~9
ispunct标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph任何图形字符
isprint任何可打印字符,包括图形字符和空白字符

📒字符转换函数

int tolower( int c );
int toupper( int c );

我们常常遇到把一个字符串中的大写转换为小写,亦或者小写转换为大写,这样的题,这里我们就可以直接使用函数解决了;

#include <stdio.h>
#include <ctype.h>
int main()
{
    int i = 0;
    char str[] = "Test String.\n";
    char c;
    while (str[i])
    {
        c = str[i];
        if (isupper(c)) //用字符函数来做判断条件;
            c = tolower(c);//若为大写转换为小写
        putchar(c);//输出字符c
        i++;
    }
    return 0;
}

当然如果改一下也没有问题:

#include <stdio.h>
int main()
{
    int i = 0;
    char str[] = "Test String.\n";
    char c;
    while (str[i])
    {
        c = str[i];
        if (c<=90&&c>=65) //用字符函数来做判断条件;
            c = c+32;//若为大写转换为小写
        putchar(c);//输出字符c
        i++;
    }
    return 0;
}

完结撒花:

  • 大家一起加油,如果这篇文章有帮助到你,不要忘了一键三连哦,你们的支持,是我最大的动力!
  • 也希望明早阿根廷能够熬过半决赛(两名后卫停赛),加油!!!一起冲!!!
    请添加图片描述

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

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

相关文章

Spring Cloud Alibaba整合Sentinel,使用nacos持久化流控规则

一、引入依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifac…

小程序开发有什么快捷、低成本的方法?

2022年1月17日&#xff0c;阿拉丁研究院在《2021 年度小程序互联网发展白皮书》中提到&#xff0c;微信小程序开发者突破 300 万&#xff0c;DAU 超过 4.5 亿&#xff0c;正成为人们生活的 “标配”。 作为用户&#xff0c;我们几乎时时刻刻都享受着互联网带来的便利&#xff…

JMeter5.5入门到实战:HTTP+TCP+响应断言+自定义拓展+返回值获取

前言 众所周知JMeter是业内公认的性能测试工具&#xff0c;功能十分强大且易于拓展&#xff0c;但是入门有一定门槛&#xff0c;需要明白一些基本概念。本文使用了HTTP取样器、TCP取样器、响应断言、JSON提取器等组件&#xff0c;对公司现存的登录流程进行了测试。公司的产品包…

Java中hashmap底层Hash冲突是什么?以及如何解决Hash冲突 【杭州多测师_王sir】【杭州多测师】...

一、hashMap的底层实现hashmap的底层结构在jdk1.7之前是数组链表&#xff0c;但是在jdk1.8以后&#xff0c;其变成了数组链表红黑树&#xff0c;这个操作会加快在链表时候的查询速度。当链表的长度大于8 的时候&#xff0c;链表就会变为红黑树&#xff0c;而当长度小于6的时候&…

培训机构的存在对 IT 行业产生了哪些影响

这个标题我一看&#xff0c;应该就会引发一波口水、键盘要遭罪啦。。。做为从业十余年&#xff0c;培训行业从事也已经快7年了。 在正厚软件从一开始到今天。从讲师到教学和团队的协作、校区运营&#xff0c;从行业小白到对整体机构的运营和团队&#xff0c;有些许经验谈下个人…

测试4年裸辞失业,面试17k的测试岗被按在地上摩擦,结局让我崩溃大哭....

作为IT行业的大热岗位——软件测试&#xff0c;只要你付出了&#xff0c;就会有回报。说它作为IT热门岗位之一是完全不虚的。可能很多人回说软件测试是吃青春饭的&#xff0c;但放眼望去&#xff0c;哪个工作不是这样的呢&#xff1f;会有哪家公司愿意养一些闲人呢&#xff1f;…

FKM规范在非焊接构件中的静强度评估方法介绍(上篇)

导读&#xff1a;FKM &#xff08;《Analytical Strength Assessment of Components in Mechanical Engineering》&#xff09;规范是德国机械工程研究委员会根据机械产品在实际工程中的应用情况&#xff0c;统计出的针对由钢、铸铁及铝材料制成构件的静强度及疲劳强度的评估规…

C++模板(第二版)笔记之第六章:移动语义和 enable_if

文章目录一、完美转发&#xff08;Perfect Forwarding&#xff09;二、特殊成员函数模板&#xff1a;构造函数三、 通过 std::enable_if<>禁用模板四、 使用 enable_if<>1.不能通过使用 enable_if<>来禁用 copy/move 构造函数以及赋值构造函数五、使用 conce…

0124 双指针 Day13

剑指 Offer 21. 调整数组顺序使奇数位于偶数前面 输入一个整数数组&#xff0c;实现一个函数来调整该数组中数字的顺序&#xff0c;使得所有奇数在数组的前半部分&#xff0c;所有偶数在数组的后半部分。 示例&#xff1a; 输入&#xff1a;nums [1,2,3,4] 输出&#xff1a…

net基于asp.net的计算机网络课程题库系统-计算机毕业设计

项目介绍 计算机网络课程题库系统是针对目前计算机网络课程试题的实际需求,从实际工作出发,对过去的计算机网络课程试题平台存在的问题进行分析,完善用户的使用体会。采用计算机系统来管理信息,取代人工管理模式,查询便利,信息准确率高,节省了开支,提高了工作的效率。 本系统结…

操作系统_线程安全问题

文章目录1.线程安全问题举例2.为什么会有线程安全问题3.如何解决线程安全问题1.从原子性入手解决线程安全问题2.synchronized的使用方法3.java标准库中的线程安全类4.死锁问题举例2.死锁的必要条件1.线程安全问题举例 看代码: class Count {int i 0;public void add(){i;} }…

Sklearn机器学习与Plotly可视化强强联合

在学习sklearn(机器学习)过程中&#xff0c;模型原理可谓是枯燥无味&#xff0c;加上大多数模型训练过程也是不可见的&#xff0c;这使得很多小伙伴们望而却步&#xff0c;当然也有很多学者试图通过各种方式以可视化模型学习及预测过程&#xff0c;但大多数是复杂且不美观的。 …

Windows后台运行并启动Frpc客户端界面

Windows后台运行并启动Frpc客户端界面 frp搭建内网穿透可以看我另外一篇 1.frps服务端配置 [common] bind_port 3000 vhost_http_port 4000 vhost_https_port 5000authentication_method token authenticate_new_work_conns true token 5ae9394f-32d8-4a58-b6ed-e9f36…

【微服务技术05】Ribbon负载均衡

【微服务技术05】Ribbon负载均衡 案例代码&#xff1a;https://gitee.com/pikachu2333/spring-cloud-hexuan 之前配置好了eureka注册中心&#xff0c;使用RestTemplate调用地址为&#xff1a;http://eureka-user-service/user/1&#xff0c;配置了LoadBalanced负载均衡注解 但…

使用RTP包荷载AAC码流数据

目录 一. 前言 二. RTP协议介绍 三. AAC介绍 1. AAC格式 2. ADTS 四. RTP与AAC的结合 五. 代码实战 六. 效果展示 一. 前言 音视频通话中我们通常使用 RTP 协议包荷载音视频码率数据&#xff0c;例如麦克风采集输入数据后编码成帧&#xff0c;再将帧数据放入 RTP 协议包…

B站:以SLO为核心的可用性观测与质量运营

UGeek大咖说是优维科技为技术爱好者研讨云原生技术演进趋势而创办的系列活动&#xff0c;邀请一线互联网大厂的核心骨干主讲&#xff0c;分享原厂实践。本年度主题为可观测&#xff0c;我们希望通过一场场有趣、有料、有深度的活动&#xff0c;让运维圈的小伙伴聚集在一起&…

Java知识点--反射(上)

Java知识点--反射&#xff08;上&#xff09;&#x1f356;一、为什么需要反射1️⃣在特定情境中传统方法的不足2️⃣为了不修改原码引出反射&#x1f357;二、反射机制1️⃣Java反射机制2️⃣Java 反射机制原理示意图3️⃣Java 反射机制可以完成4️⃣反射相关的主要类5️⃣反射…

java计算机毕业设计ssm在线学习资源管理系统t4ko5(附源码、数据库)

java计算机毕业设计ssm在线学习资源管理系统t4ko5&#xff08;附源码、数据库&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#…

2023最新SSM计算机毕业设计选题大全(附源码+LW)之java丹徒高级中学校车预约9poqj

大四计算机专业的同学们即将面临大学4年的最后一次考验--毕业设计。通过完成毕业设计来对过去4年的大学学习生活做一个总结&#xff0c;也是检验我们学习成果的一种方式&#xff0c;毕业设计作品也是我们将来面试找工作的一个敲门砖。 选题前先看看自己掌握哪些技术点、擅长哪…

Denoising Diffusion Probabilistic Models

目录概要前向过程nice property逆向过程参数推导简化参考资料概要 Denoising Diffusion Probabilistic Model(DDPM)是一个生成模型&#xff0c;给定一个目标分布&#xff0c;学习模型以便可以从目标分布中采样。 使用马尔科夫链建模。输入是噪声&#xff0c;通过神经网络逐步去…