C语言字符函数与字符串函数:编织文字的舞会之梦(上)

news2024/9/21 0:44:43

欢迎来到白刘的领域   Miracle_86.-CSDN博客

系列专栏  C语言知识

先赞后看,已成习惯

   创作不易,多多支持!

 在编程的过程中,我们经常要处理字符以及字符串,为了方便操作这些字符和字符串,C语言标准库中提供了一系列库函数,接下来我们就一起来学习这些函数,帮助字符和字符串完成它们的舞会之梦。

目录

一、字符分类函数

二、字符转换函数

三、strlen函数的使用以及模拟实现

方法1

方法2

方法3

四、strcpy函数的使用以及模拟实现

五、strcat函数的使用以及模拟实现

六、strcmp函数的使用以及模拟实现


一、字符分类函数

在C语言中,有一系列函数是专门用来做字符分类的,也就是一个字符是属于什么类型的字符。这些函数都包含在一个头文件:<ctype.h>。

其实上述的函数的使用方法都是非常类似的,所以我们就仅拿其中一个来举例说明。

int islower(int c);

islower函数可以判断一个字符是不是小写字母。

通过返回值来说明是否为小写字母,如果是则返回非0的整数,如果不是则返回0。

我们来举例练习一下:

//写⼀个代码,将字符串中的⼩写字⺟转⼤写,其他字符不变。
#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 (islower(c))
			c -= 32;
		putchar(c);
		i++;
	}
	return 0;
}

因为'A'的ASCII码值是65,'a'的ASCII码值为97,97-65=32,故转换仅需减32即可。

来看运行结果:

二、字符转换函数

C语言中提供了两个字符转换函数:

int tolower(int c); //将参数传进去的⼤写字⺟转⼩写 
int toupper(int c); //将参数传进去的⼩写字⺟转⼤写

刚刚的代码我们是将字符-32来完成效果,这回我们有了字符转换函数,就可以之间上函数了。

#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 (islower(c))
			c = toupper(c);
		putchar(c);
		i++;
	}
	return 0;
}

 运行结果是一样的:

三、strlen函数的使用以及模拟实现

我们先来看看strlen函数的原型:

size_t strlen(const char* str);

str我们很熟悉了,是string(字符串)的缩写,len其实是length的意思,所以这个函数大概我就能知道字面意思,它是用来求字符串长度的。

我们知道字符串是以'\0'结尾的,而strlen函数返回的就是在字符串在'\0'之前出现的字符的个数(不包含'\0')。

这里要注意几个点:

1.参数指向的字符串必须是以'\0'结尾。

2.参数的返回值是size_t类型的,是无符号的(易错)。

3.strlen函数是需要头文件的,它的头文件是<string.h>。

那了解完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;
}

接下来看模拟实现:

方法1

//计数器⽅式
int my_strlen(const char* str)
{
	int count = 0;
	assert(str);
	while (*str)
	{
		count++;
		str++;
	}
	return count;
}

法1创建了个临时变量来计数,还使用了指针运算,由于'\0'为假,指针指到它时,也就意味着字符串结束,循环也就结束。我们还用到了assert断言,严谨一些,养成良好的习惯。

方法2

//不能创建临时变量计数器
int my_strlen(const char* str)
{
	assert(str);
	if (*str == '\0')
		return 0;
	else
		return 1 + my_strlen(str + 1);
}

法2中我们使用了递归,由于每次我们都是+1,所以很容易想到使用递归来完成代码的实现。这里不会递归的兄弟们,传送门放在下面了:

C语言中的套娃——函数递归_俄罗斯套娃可以用递归实现吗-CSDN博客

方法3

//指针-指针的⽅式
int my_strlen(char* s)
{
	assert(s);
	char* p = s;
	while (*p != '\0')
		p++;
	return p - s;
}

 这种方法也使用了指针运算,可见指针运算有多好用:

灵魂指针,教给(一)-CSDN博客

这篇文章详细地讲述了指针的运算。

首先由于传进来的是字符串的首元素地址,然后我们再创建一个指针来移动,最后指针指向字符串末尾,首尾相减,便能知晓中间长度,也就是字符串的长度。

四、strcpy函数的使用以及模拟实现

char* strcpy(char* destination, const char* source);

首先我们认识两个单词:destination n.目的地,source n.源头。

然后我们再来拆分一下strcpy的字面意思,str还是字符串,cpy其实是copy的意思,那我们可以知道了,strcpy是用来拷贝字符串的。

这里说明几点细节:

1.原理:将 source 指向的 C 字符串复制到destination指向的数组中,包括终止 null 字符(并在该点停止)

2.源字符串必须以'\0'结尾。

3.目标空间必须足够大,确保能放下源字符串。

4.目标空间必须是可修改的。

接下来我们来看它的使用:

#include <stdio.h>
#include <string.h>
int main()
{
	char src[40];
	char dest[40];
	strcpy(src, "Hello World");
	strcpy(dest, src);
	printf("最终的目标字符串:%s\n", dest);
	return 0;
}

 来看运行结果:

接下来我们来学习strcpy的模拟实现:

我们可以用两个指针分别指向目的地和源头,然后通过赋值即可完成拷贝。

//1.参数顺序
//2.函数的功能,停⽌条件
//3.assert
//4.const修饰指针
//5.函数返回值
//6.题⽬出⾃《⾼质量C/C++编程》书籍最后的试题部分
#include <stdio.h>
char* my_strcpy(char* dest, const char* src)
{
	char* ret = dest;
	assert(dest != NULL);
	assert(src != NULL);
	
	while (*src != '\0')
	 {
		*dest = *src;
		dest++;
		src++;
	 }
	*dest = *src; //拷贝'\0'
	return ret;
 }

 上述代码已经可以完成效果了,但是我们还可以有更巧妙的代码:

#include<stdio.h>
char* my_strcpy(char* dest, const char* src)
{
	char* ret = dest;
	assert(dest != NULL);
	assert(src != NULL);
	
	while ((*dest++ = *src++))
	 {
		;
	 }
	return ret;
 }

虽然++的优先级比*高,但是是后置++,先操作后++,所以先解引用,完成赋值后再++,最后到'\0',退出循环,是不是很巧妙。

五、strcat函数的使用以及模拟实现

char *strcat(char *dest, const char *src)

老规矩还是字面分析,str字符串,这个cat可不是小猫的那个cat,而是catenate的缩写,意思是连成一串。

1.原理:将源字符串的副本追加到目标字符串。终止 null 字符在 destination 中被 source 的第一个字符覆盖,并包含一个 null 字符在由两者在目的地的串联形成的新字符串的末尾。

2.源字符串必须以'\0'结尾。

3.目标字符串也需要有'\0',否则不知道从哪开始追加。

4.目标空间足够大。

5.目标空间可修改。

#include <stdio.h>
#include <string.h>
int main()
{
	char src[50];
	char dest[50];
	strcpy(src, "World");
	strcpy(dest, "Hello ");
	strcat(dest, src);
	printf("最终的目标字符串:%s", dest);
	return 0;
}

 运行结果:

之后我们学习strcat的模拟,这个其实很简单,刚刚我们学到了strcpy的模拟,那这个无非就是先找到destination中的'\0'再copy,代码如下:

#include<stdio.h>
#include<assert.h>
char* my_strcat(char* dest, const char* src)
{
	char* ret = dest;
	assert(dest != NULL);
	assert(src != NULL);
	while (*dest)
	{
		dest++;
	}
	while ((*dest++ = *src++))
	{
		;
	}
	return ret;
}

六、strcmp函数的使用以及模拟实现

int strcmp(const char *str1, const char *str2)

cmp是compare的缩写,是比较,顾名思义strcmp是比较字符串的。

1.原理:此函数开始比较每个字符串的第一个字符。如果它们等于彼此,它继续往下比较,直到字符不同或终止达到 null-character。

2.返回值:

  • 如果返回值小于 0,则表示 str1 小于 str2。
  • 如果返回值大于 0,则表示 str1 大于 str2。
  • 如果返回值等于 0,则表示 str1 等于 str2。 

3.比较的是两个字符的ASCII码值的大小。

#include <stdio.h>
#include <string.h>
 
int main ()
{
   char str1[15];
   char str2[15];
   int ret;
 
 
   strcpy(str1, "abcdef");
   strcpy(str2, "ABCDEF");
 
   ret = strcmp(str1, str2);
 
   if(ret < 0)
   {
      printf("str1 小于 str2");
   }
   else if(ret > 0) 
   {
      printf("str1 大于 str2");
   }
   else 
   {
      printf("str1 等于 str2");
   }
   
   return(0);
}

 strcmp的模拟实现,这个其实很简单,直接上代码:

int my_strcmp(const char* str1, const char* str2)
{
	int ret = 0;
	assert(str1 != NULL);
	assert(str2 != NULL);
	while (*str1 == *str2)
	{
		if (*str1 == '\0')
			return 0;
		str1++;
		str2++;
	}
	return *str1 - *str2;
}

未完待续...... 

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

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

相关文章

jmx_prometheus_javaagent-0.19.0.jar+Prometheus+Grafana 监控Tongweb嵌入式(by lqw)

文章目录 1.思路2.部署准备3.应用jar包修改配置和导入tw嵌入式的依赖&#xff08;参考&#xff09;4.Prometheus部署5.Prometheus配置6.安装和配置Grafana 1.思路 Tongweb嵌入式最终是把依赖打入到java应用&#xff08;也就是jar包里&#xff09;&#xff0c;然后启动jar包进行…

TinTin Web3 Bounty 挑战杯开启,Sui 向你发出挑战邀请

以下文章来源于TinTinLand &#xff0c;作者TinTinLand。 2024 年开年最火的是什么&#xff1f; 对 Web3 来说&#xff0c;Bounty 任务应该是普通人获得行业“一杯羹”的重要捷径&#xff01; 通过深入学习各类 Web3 技术&#xff0c;凭借实战锻炼开发创新项目&#xff0c;就…

Linux学习:git补充与调试工具gdb

目录 1. git版本控制器&#xff08;续&#xff09;1.1 git本地仓库结构1.2 git实现版本控制与多人协作的方式1.3 git相关指令&#xff0c;多分支模型与.gitignore文件 2. gdb调试工具2.1 企业项目开发流程简述与调试的必要性2.2 bug的调试思路方法与调式工具的使用 1. git版本控…

ResNet目标检测算法实现交通灯分类

红绿灯识别方案&#xff1a;https://zhuanlan.zhihu.com/p/674791906 目录 一、制作数据集二、ResNet算法三、pytorch转onnx文件四、onnx推理测试五、onnx转mnn 一、制作数据集 1、数据集划分 将红绿灯数据集大文件夹中不同类别的小文件夹中的图片按照9&#xff1a;1进行划分…

小程序绕过 sign 签名

之前看到了一篇文章【小程序绕过sign签名思路】之前在做小程序渗透时也遇到了这种情况&#xff0c;但是直接放弃测试了&#xff0c;发现这种思路后&#xff0c;又遇到了这种情况&#xff0c;记录下过程。 并没有漏洞分享&#xff0c;仅仅是把小程序也分享出来&#xff0c;方便…

Idea 不能创建JDK1.8的spring boot项目

由于https://start.springboot.io/ 不支持JDK1.8&#xff0c;那么我们需要换idea的springboot创建源&#xff0c;需要换成 https://start.aliyun.com&#xff0c;这也是网上大部分教程说的&#xff0c;但是我这边会报这样的错误&#xff1a; Initialization failed for https:…

Go --- Go语言垃圾处理

概念 垃圾回收&#xff08;GC-Garbage Collection&#xff09;暂停程序业务逻辑SWT&#xff08;stop the world&#xff09;程序根节点&#xff1a;程序中被直接或间接引用的对象集合&#xff0c;能通过他们找出所有可以被访问到的对象&#xff0c;所以Go程序的根节点通常包括…

小程序跨端组件库 Mpx-cube-ui 开源:助力高效业务开发与主题定制

Mpx-cube-ui 是一款基于 Mpx 小程序框架的移动端基础组件库&#xff0c;一份源码可以跨端输出所有小程序平台及 Web&#xff0c;同时具备良好的拓展能力和可定制化的能力来帮助你快速构建 Mpx 应用项目。 Mpx-cube-ui 提供了灵活配置的主题定制能力&#xff0c;在组件设计开发阶…

GB28181 —— 5、C++编写GB28181设备端,完成将USB摄像头视频实时转发至GB28181服务并可播放(附源码)

被测试的USB摄像头 效果 源码说明 主要功能模拟设备端&#xff0c;完成注册、注销、心跳等&#xff0c;同时当服务端下发指令播放视频时 设备端实时读取USB摄像头视频并通过OpenCV处理后实时转ps格式后封包rtp进行推送给服务端播放。 源码 /****remark: pes头的封装,里面的具…

ETH Gas 之 Base Fee Priority Fee

前情回顾 ETH网络 之 Gas EIP-1559 EIP-1559 EIP-1559是以太坊改进提案&#xff08;Ethereum Improvement Proposal&#xff09;&#xff0c;旨在改进以太坊的交易费用机制。该提案引入了一种新的交易费用模型&#xff0c;以提高交易费用的可预测性和网络的效率。我们本文各…

敏捷开发最佳实践:学习与改进维度实践案例之会诊式培养敏捷教练

自组织团队能够定期反思并采取针对性行动来提升人效&#xff0c;但2022年的敏捷调研发现&#xff0c;70%的中国企业在学习和改进方面仍停留在团队级。本节实践案例将分享“会诊式培养敏捷教练”的具体做法&#xff0c;突出了敏捷以人为本的学习和改进&#xff0c;强调了通过人员…

​HTTP与HTTPS:网络通信的安全卫士

✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天开心哦&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; ✨✨ 帅哥美女们&#xff0c;我们共同加油&#xff01;一起进步&am…

【SAP-ABAP】CO01保存时错误DBSQL_DUPLICATE_KEY_ERROR

找到该表的主键OBJNR&#xff0c;事务代码SM56中查看当前缓冲到该key的号码段&#xff0c;事务代码SNRO修改对象名称OBJNR编号范围状态。 事务代码SM13查看数据更新记录

音频转换器哪个好?5个角度详细测评~

我们常常会用到音频转换器&#xff0c;比如因为平台和设备对某些格式的不兼容&#xff0c;需要进行格式转换&#xff1b;比如有些音频文件可能过大&#xff0c;需要转换为更高效&#xff1b;压缩格式以节省存储空间或加快传输速度&#xff1b;比如调整音频文件的比特率、采样率…

腾讯云轻量应用服务器CPU型号谁知道?

腾讯云轻量应用服务器CPU型号是什么&#xff1f;轻量服务器处理器主频&#xff1f;腾讯云服务器网txyfwq.com账号下的CPU处理器型号为2.5GHz主频的Intel(R) Xeon(R) Gold 6133 CPU和2.4GHz主频Intel(R) Xeon(R) CPU E5-26xx v4&#xff0c;腾讯云轻量应用服务器不支持指定底层物…

AMPQ和rabbitMQ

RabbitMQ 的 Channel、Connection、Queue 和 Exchange 都是按照 AMQP&#xff08;Advanced Message Queuing Protocol&#xff09;标准实现的。 AMPQ的网络部分 AMQP没有使用HTTP&#xff0c;使用TCP自己实现了应用层协议。 AMQP实现了自己特有的网络帧格式。 一个Connection…

蓝桥杯 2023 省A 更小的数

主要思路&#xff1a; 输入一个长度为n的字符串&#xff0c;用二维数组dp[i][j]来记录子串[i, j]是否需要反转一次才能满足条件。使用动态规划自底向上地填充dp数组。根据问题的要求&#xff0c;需要考虑字符串的子串中字符的大小关系来判断是否需要反转。最后统计满足条件的子…

航空实时监控

1、从Kafka中读取飞机数据&#xff0c;并进行清洗 此步骤在前面的“使用Spark清洗统计业务数据并保存到数据库中”任务阶段应该已经完成。如果没有完成&#xff0c;请参考源代码自行完成。核心类主要有三个&#xff1a;SparkStreamingApplication类、SparkUtil类和MapManager类…

Cache缓存:HTTP缓存策略解析

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

处理器方法的返回值--返回对象Object

处理器方法也可以返回Object对象。这个Object可以是Integer&#xff0c;String&#xff0c;自定义对象&#xff0c; Map&#xff0c;List 等。但返回的对象不是作为逻辑视图出现的&#xff0c;而是作为直接在页面显示的数据出现的。 返回对象&#xff0c;需要使用ResponseBody注…