常见字符函数和字符串函数(上)

news2024/9/29 7:55:25

1.  字符分类函数

        字符分类函数是一类用于判断字符是否属于特定的字符类别(如字母、数字、标点符号等)的函数。在C语言中,这些函数通常可以在<ctype.h>头文件中找到,它们对于文本处理和输入验证非常有用。

        这些函数通常返回一个非零值(通常是int类型的1)如果字符c属于被测试的类别,否则返回0。例如,isalpha('A')会返回1,因为’A’是一个大写字母。

        字符分类函数在处理用户输入、验证数据、以及进行文本分析时非常有用。例如,您可能需要检查用户输入的密码是否包含至少一个数字和一个特殊字符,这时就可以使用isdigit和ispunct函数来进行验证。

这些函数使用起来非常类似,就以 islower 函数为例。

1.  int islower(int c);

 islower 函数能够判断参数部分的 c 是否是小写字母。

通过返回值来判断是否是小写字母,如果是小写字母就返回非零的整数,如果不是小写字母,则返回零。

练习:

 试着编写一个函数将给定字符串里的大写字母全部转化为小写,其他字符不变。

提示:

  • 据Ascll表可知,大写字母的Ascll比自身小写字母小32;
  • 并且我们需要判断给定字符串中大写字母都有哪些,这时候就需要isupper函数来帮忙了;
  • 不要忘记包含对应的头文件<ctype.h>。

示例代码如下:

1.  #include<stdio.h>
2.  #include<ctype.h>
3.  #include<assert.h>
4.  void ce_lower(char* s)
5.  {
6.  	assert(*(s+i)!='\0');
7.  	int i = 0;
8.  	char c;
9.  	while (s)
10.  	{
11. 		c = *(s+i);
12. 		if (isupper(c))
13. 		{
14. 			c += 32;
15. 		}
16. 		putchar(c);
17. 		i++;
18. 	}
19. }
20. 
21. int main()
22. {
23. 	char str[] = { "Test String.\n" };
24. 	ce_lower(str);
25. 	return 0;
26. }

2. 字符转换函数

顾名思义,字符转换函数自然就是进行字符转换的,其作用类似于我们上述编写的这个代码。

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

1.  int tolower(int a);//将参数传进去的大写字母转换为小写
2.  int toupper(int b);//将参数传进去的小写字母转换为大写

上面的代码我们依靠Ascll之间的数值关系转换的,而有了之两个函数我们就可以直接使用函数来进行转换了,思路更简单了是不是。

1.  #include<stdio.h>
2.  #include<ctype.h>
3.  #include<assert.h>
4.  void ce_lower(char* s)
5.  {
6.  	assert(s);
7.  	int i = 0;
8.  	char c;
9.  	while (*(s+i)!='\0')
10. 	{
11. 		c = *(s+i);
12. 		if (isupper(c))
13. 		{
14. 			toupper(c);
15. 		}
16. 		putchar(c);
17. 		i++;
18. 	}
19. }
20. 
21. int main()
22. {
23. 	char str[] = { "Test String.\n" };
24. 	ce_lower(str);
25. 	return 0;
26. }

3. strlen 的使用和模拟实现

1.  size_t strlen(const char* str);

以下是strlen函数的几个特点:

  • 字符串以'\0'作为结束标志,strlen函数返回的是在字符串中'\0'前面出现的字符个数(不包含'\0',如果一个字符串在中间位置出现'\0',那么就只计算'\0'前的字符串长度,如果在开头出现,就为零)
  • 参数指向的字符串必须以'\0'结尾,不然函数无法识别要计算到哪里;
  • 注意函数的返回值为size_t,是无符号的(易错);
  • strlen的使用需要包含头文件<string.h>;

strlen函数模拟实现:

第一种:计数器方式

1.  #include<stdio.h>
2.  #include<string.h>
3.  #include<assert.h>
4.  int my_strlen(const char* s)
5.  {
6.  	assert(s);
7.  	int count = 0;
8.  	while (*s)
9.  	{
10. 		s++;
11. 		count++;
12. 	}
13. 	return count;
14. }
15. int main()
16. {
17. 	int ret = my_strlen("abcdef\n");
18. 	printf("%d\n", ret);
19. 	return 0;
20. }

第二种:不能创立临时变量计数器

1.  #include<stdio.h>
2.  #include<assert.h>
3.  int my_strlen(const char* s)
4.  {
5.  	assert(s);
6.  	if (*s == '\0')
7.  	{
8.  		return 0;
9.  	}
10. 	else
11. 	{
12. 		return 1 + my_strlen(++s);
13. 	}
14. }
15. int main()
16. {
17. 	int ret = my_strlen("abcdef\n");
17. 	printf("%d\n", ret);
19. 	return 0;
20. }

第三种:指针-指针的方式

1.  #include<stdio.h>
2.  #include<assert.h>
3.  int my_strlen(const char* s)
4.  {
5.  	assert(s);
6.  	char* cut = s;
7.  	while (*s)
8.  	{
9.  		s++;
10. 	}
11. 	return s - cut;
12. }
13. int main()
14. {
15. 	int ret = my_strlen("abcdef\n");
16. 	printf("%d\n", ret);
17. 	return 0;
18. }

以上三种都是有可能是strlen函数的内部实现方法,但也仅仅是有可能,具体其内部方法实现到底是怎样,这我们就不得而知了。并且与其原来函数不同的是,我们定义的函数其返回类型都为int类型,而原函数返回类型为size_t,当然这个我们自己就可以进行修改,再次提出这个点,无非就是因为它很容易被人忘记。

4. strcpy函数的使用和模拟实现

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

首先,我们先要知道这个函数是干嘛的?

答:拷贝一个字符串到另一个字符串里。

我们仔细观察这个函数形参可知,第一个形参命名为destination,意为目标,目的地,可见是要拷贝进的那个字符串,而第二个source,意为来源,可见是要被拷贝的那个字符串。从而我们可知这个函数的功能是要把第二个形参代表的字符串拷贝到第一个形参代表的字符串。好了,虽然功能已明确,但还有以下几点我们需要注意一下。

  • 源字符串必须以 '\0' 结束;
  • 会将源字符串中的 '\0' 拷贝到目标空间;
  • 目标空间必须足够大,以确保能存放源字符串;
  • 目标空间必须可修改;

注:源字符串指的是来源字符串,也就是上述所讲的第二个字符串。

1.  #include<stdio.h>
2.  #include<string.h>
3.  int main()
4.  {
5.  	char str1[20] = "Hello world!";
6.  	char str2[20] = { 0 };
7.  	strcpy(str2, str1);
8.  	printf("%s\n", str2);
9.  	return 0;
10. }

strcpy函数的模拟实现:

1.  #include<stdio.h>
2.  #include<assert.h>
3.  char* my_strcpy(char* dest, const char* src)
4.  {
5.  	char* ret = dest;
6.  	assert(dest && src);
7.  	while (*src)
8.  	{
9.  		*dest++ = *src++;
10. 	}
11.     *dest=*src;
12. 	return ret;
13. }

这个是较为麻烦一点的实现方法,其实这个代码还可以简化一点,如下:

1.  #include<stdio.h>
2.  #include<assert.h>
3.  char* my_strcpy(char* dest, const char* src)
4.  {
5.  	char* ret = dest;
6.  	assert(dest && src);
7.  	while (*dest++ = *src++)
8.  	{
9.  		;
10. 	}
11. 	return ret;
12. }

如果说这两个代码有什么会让人有点看不懂的地方,只有可能在while循环那一块,既然如此,我们就来分析一下这一块。

首先,我们需要清楚一点:* 的优先级并没有 ++ 高,并且是后置加加,这样就使得第一次赋值时还是原始值,成功将第一个字符拷贝过去;

其次,应该就是第二个代码中直接将*dest++ = *src++作为条件,这样实现的效果其实和第一个没啥区别,表达式中的值即为while循环条件值,当最后src指向的为'\0'时,恰好为空,实现拷贝;

5. strcat 的使用和模拟实现

此函数主要用于追加字符串,也就是将一个字符串追加到另一个字符串末尾。

那么它要如何使用呢?想要使用它,我们需要先来了解一下它的一些特点

  • 源字符串必须以 '\0' 结束;
  • 目标字符串中也要有 '\0' ,否则没法知道从哪里开始追加;
  • 目标空间需要足够大,能容下源字符串的内容;
  • 目标空间必须可修改;
1.  #include<stdio.h>
2.  #include<string.h>
3.  int main()
4.  {
5.  	char str1[20] = "Hello ";
6.  	char str2[] = "world";
7.  	strcat(str1, str2);
8.  	printf("%s\n", str1);
9.  	return 0;
10. }

 模拟实现strcat函数:

1.  #include<stdio.h>
2.  #include<assert.h>
3.  char* my_strcat(char* dest, const char* src)
4.  {
5.  	char* ret = dest;
6.  	assert(dest && src);
7.  	while (*dest)
8.  	{
9.  		dest++;
10.  	}
11. 	while ((*dest++ = *src++))
12. 	{
13. 		;
14. 	}
15. 	return ret;
16.  }
17. int main()
18. {
19. 	char str1[20] = "Hello ";
20. 	char str2[] = "world";
21. 	char*s=my_strcat(str1, str2);
22. 	printf("%s\n", str1);
23. 	return 0;
24. }

思考:如果我们将字符串自己追加会发生什么呢?

 官方函数:

 自己写的函数:

可见使用官方函数可以成功,但这是根据编译器不同效果也不一样,这是在Vs上可以,但在其他编译器就不一定可以了。 自己写的函数并没有成功,调试可知是陷入了死循环,src指向的内容一直在给dest指向的空间,就以图中字符串为例,起始src指向H,当\0被H替代后,然后其后空间又分别被ello代替,然后此时src又指向H,反反复复,直到空间溢出,退出程序。再次表明了我们模拟实现的仅仅只是他的实现猜想。

6. strcmp的使用和模拟实现

之前我们已经知道了如何用程序来比较两个整型的大小,但面对字符串之间的比较,我们则是束手无策,但现如今,有了strxmp函数来帮忙,它主要通过比较字符的Ascll值来进行判断.

还和上述函数一样,我们学习使用它之前,先来看一看它的一些规定

  • 第一个字符串大于第二个字符串,则返回大于0的数字;
  • 第一个字符串等于第二个字符串,则返回0;
  • 第一个字符串小于第二个字符串,则返回小于0的数字;
1.  #include<stdio.h>
2.  #include<string.h>
3.  int main()
4.  {
5.  	char str1[] = "abcdefg";
6.  	char str2[] = "abcdrfg";
7.  	int ret = strcmp(str1, str2);
8.  	printf("%d\n", ret);
9.  	return 0;
10. }

模拟实现strcmp函数: 

1.  #include<stdio.h>
2.  #include<assert.h>
3.  int my_strcmp(const char* str1, const char* str2)
4.  {
5.  	assert(str1 && str2);
6.  	while (*str1 == *str2)
7.  	{
8.  		if (*str1 == '\0')
9.  		{
10. 			return 0;
11. 		}
12. 		str1++;
13. 		str2++;
14. 	}
15. 	return *str1 - *str2;
16. }
17. int main()
18. {
19. 	char str1[] = "abcdefg";
20. 	char str2[] = "abcdrfg";
21. 	int ret = my_strcmp(str1, str2);
22. 	printf("%d\n", ret);
23. 	return 0;
24. }

模拟函数实现的结果是判断两个字符串第一个不相等的字符的Ascll值之差,更为详细一点。

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

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

相关文章

Windows系统镜像下载

目前官网还可以下载的系统有Win10和Win11&#xff0c;Win7因为已经停止维护&#xff0c;所以只能到第三方镜像站下载&#xff0c;下面将具体展示下载方法。 Win7 下载地址&#xff1a;MSDN, 我告诉你 - 做一个安静的工具站 在操作系统中找到Windows 7&#xff0c;在右侧选择…

Python | Leetcode Python题解之第445题两数相加II

题目&#xff1a; 题解&#xff1a; class Solution:def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:if head is None or head.next is None:return headnew_head self.reverseList(head.next)head.next.next head # 把下一个节点指向自己head…

魔都千丝冥缘——软件终端架构思维———未来之窗行业应用跨平台架构

一、创生-魔都千丝冥缘 在那神秘而复杂的数字世界里&#xff0c;软件的舞台上正上演着一场精彩的剧目。当面对终端单页面中如蛛网般交织的复杂业务逻辑&#xff0c;我们如同在迷雾中摸索前行。多个表单承载着各自的使命&#xff0c;却又有着相同字段的微妙关联&#xff0c;而内…

【C++前缀和 动态规划 贪心】813. 最大平均值和的分组|1936

本文涉及的基础知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 C动态规划 贪心(决策包容性) LeetCode813. 最大平均值和的分组 给定数组 nums 和一个整数 k 。我们将给定的数组 nums 分成 最多 k 个非空子数组&#xff0c;且数组内…

【电商搜索】现代工业级电商搜索技术-Facebook语义搜索技术QueSearch

【电商搜索】现代工业级电商搜索技术-Facebook语义搜索技术Que2Search 目录 文章目录 【电商搜索】现代工业级电商搜索技术-Facebook语义搜索技术Que2Search目录0. 论文信息1. 研究背景&#xff1a;2. 技术背景和发展历史&#xff1a;3. 算法建模3.1 模型架构3.1.1 双塔与分类 …

物流货运托运发货单二联三联打印软件定制 佳易王物流单管理系统操作教程

一、前言 物流货运托运发货单二联三联打印软件定制 佳易王物流单管理系统操作教程 1、软件为绿色免安装版&#xff0c;解压即可使用&#xff0c;已经内置数据库&#xff0c;不需再安装。 2、软件下载可以到本文章最后点击官网卡片下。 二、软件程序教程 1、如图&#xff0c;…

C++入门(2)--引用

6.引用 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同一块内存空间。 类型& 引用变量名(对象名) 引用实体&#xff1b; //引用 //类型& 引用变量名(对象名) 引…

基于php的幸运舞蹈课程工作室管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

24-9-28-读书笔记(二十)-《契诃夫文集》(四)上([俄] 契诃夫 [译] 汝龙 )

文章目录 《契诃夫文集》&#xff08;四&#xff09;上&#xff08;[俄] 契诃夫 [译] 汝龙 &#xff09;目录阅读笔记记录总结 《契诃夫文集》&#xff08;四&#xff09;上&#xff08;[俄] 契诃夫 [译] 汝龙 &#xff09; 时间过得好快啊&#xff0c;马上又要十月份了&#x…

开源链动2+1模式AI智能名片小程序源码:放大特色,构建独特竞争力

摘要&#xff1a;本文探讨在当今社会背景下&#xff0c;开源链动21模式AI智能名片小程序源码如何通过坚持与众不同来构建独特竞争力。在信息传播便捷但个体易同质化的时代&#xff0c;拥有特色是脱颖而出的关键&#xff0c;而这种模式下的小程序源码具有独特的发展潜力。 一、引…

Golang | Leetcode Golang题解之第443题压缩字符串

题目&#xff1a; 题解&#xff1a; func compress(chars []byte) int {write, left : 0, 0for read, ch : range chars {if read len(chars)-1 || ch ! chars[read1] {chars[write] chwritenum : read - left 1if num > 1 {anchor : writefor ; num > 0; num / 10 {…

bidict:Python 中高效的双向字典库

在 Python 编程中&#xff0c;字典&#xff08;dict&#xff09;是用于存储键值对的强大数据结构&#xff0c;能够快速地根据键查找值。然而&#xff0c;有时我们不仅需要从键查找值&#xff0c;还需要根据值查找键。这种双向查询需求在很多场景中很常见&#xff0c;如映射表、…

openEuler 修改网卡和常用网络配置

简介 1、网卡启用、禁用和查看状态 2、编辑网卡&#xff0c;配置静态Ip 3、删除之前网卡缓存的Ip 4、机器即连接内网&#xff0c;又连接外网 的网卡配置 5、openEuler 修改默认的镜像仓库&#xff08;推荐&#xff09;1、网卡启用、禁用和查看状态 # 查看网络状态 nmcli devi…

muduo网络库介绍

文章目录 MuduoServer常见接口TcpServer类EventLoop类TcpConnection类 服务器搭建Client常见接口TcpClient类 客户端搭建 Muduo Muduo是陈硕大佬开发的,一个基于非阻塞IO和事件驱动的C高并发网络编程库 这是一个基于主从Reactor模型的网络编程库,线程模型是one loop per thre…

K-means聚类分析对比

K-means聚类分析&#xff0c;不同K值聚类对比&#xff0c;该内容是关于K-means聚类分析的&#xff0c;主要探讨了不同K值对聚类结果的影响。K-means聚类是一种常见的数据分析方法&#xff0c;用于将数据集划分为K个不同的类别。在这个过程中&#xff0c;选择合适的K值是非常关键…

VSCode 中配置 C/C++ 环境的步骤

VSCode 中配置 C/C 环境的步骤 1. 安装 VSCode 1、下载位置 https://code.visualstudio.com/Download2、安装 正常操作步骤&#xff0c;同意协议&#xff0c;下一步&#xff0c;点击完成即可 2. 安装 C/C 扩展 打开 VSCode。 点击左侧的扩展图标&#xff08;或使用快捷键…

Linux网络:网络编程套接字

socket 套接字 socket常见API 创建套接字&#xff1a;&#xff08;TCP/UDP&#xff0c;客户端服务器&#xff09; int socket(int domain, int type, int protocol);绑定端口号&#xff1a;&#xff08;TCP/UDP&#xff0c;服务器&#xff09; int listen(int sockfd, int …

Python 算法交易实验89 QTV200日常推进-模式思考

说明 过去几天大A的表现还是比较戏剧化的。 让我想到了&#xff1a; 1 价稳量缩模式。之前很长一段时间都是这种状态&#xff0c;最终还是大爆发了&#xff0c;这个可取。2 周期模式。假设价格是一个周期为T(T可变)的正弦波&#xff0c;所以最终还是回到了几个月前的位置&…

Java 常用运算符简单总结

目录 1. 运算符​编辑 1.1 算术运算符​编辑 1.1.1 除法运算符​编辑 1.1.2 取模&#xff08;取余&#xff09;运算符​编辑 1.1.3 自增/减运算符​编辑​编辑 1.2 关系运算符 1.3 逻辑运算符 1.3.1 逻辑/短路与 1.3.2 逻辑/短路或 1.4 取反操作 1.5 逻辑异或 1.4 …

第三节-类与对象(中)

1.类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类&#xff08;空类大小为1&#xff09;。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成以下6个默认成员函数。 默认成员函数&#xff1a;…