C语言——详解字符函数和字符串函数(上)

news2024/9/23 1:28:41

目录

一、strlen的使用和模拟实现

1.strlen()函数的介绍

2.strlen()函数的具体使用

3.strlen函数的注意事项

4.strlen函数的模拟实现

二、strcpy的使用和模拟实现

1.strcpy()函数的介绍

2.strcpy()函数的具体使用

3.strcpy()函数的注意事项

4.strcpy函数的模拟实现

三、strcat 的使用和模拟实现 

1.strcat()函数的介绍

2.strcat函数的具体使用

3.strcat函数的注意事项

4.strcat函数的模拟实现

四、strcmp的使用和模拟实现

1.strcmp()函数的介绍

2.strcmp()函数的具体使用

3.strcmp函数的注意事项

4.strcmp函数的模拟实现


一、strlen的使用和模拟实现

1.strlen()函数的介绍

strlen:计算的是字符串str的长度,从字符的首地址开始遍历,以 '\0' 为结束标志,然后将计算的长度返回,计算的长度并不包含'\0'。下面是库中的strlen()函数:

size_t  strlen (const char* str);

  1. 函数的参数为------const char* str:字符指针
  2. 返回值的类型------size_t:无符号整数(即:unsigned int)

前提知识:

  • const关键字:是用来定义常量的,若一个变量被const关键字修饰时,那么这个变量的值就不可以被改变。故:这里的 * str 的值是不能被修改的。
  • size_t数据类型:表示C中任何对象所能达到的最大长度,它是无符号整数。

1.使用const关键字:这里只是计算字符串的长度,用const修饰,避免将原字符串修改掉。

2.使用size_t数据类型:这里返回计算的字符串长度,长度最小值为0,不可能为负数。

2.strlen()函数的具体使用

场景一:

#include <stdio.h>
#include <string.h>
int main()
{
	char arr[10] = "abcde";
	int num = strlen(arr);
	printf("数组arr的长度为:%d\n", num);
 
	return 0;
}

输出的结果:

 场景二:

#include <stdio.h>
#include <string.h>
 
int main()
{
	char arr[] = { 'a','b','c','d','e' };
	int num = strlen(arr);
	printf("数组arr的长度:%d\n", num);
 
	return 0;
}

输出的结果:

上述两种场景输出的结果并不相同

为什么会出现这样的结果,我们在用strlen函数时应该注意什么?

3.strlen函数的注意事项

strlen函数:当计算长度时,只有遇到'\0'才会停止计算,同时计算的长度不包含'\0'。

    场景一,arr字符数组中存储的是一个字符串(字符串是以'\0'为结束标志的),那么strlen遍历到字符 'e' 时,再向后遍历,就会遇到'\0',此时strlen停止遍历,返回字符个数:5;

    场景二:字符'a'、'b'、 'c' 、'd' 、'e'五个字符依次存储在arr的字符数组中,并没有存储'\0',所以'e'字符后面存储的内容我们并不知道有什么。而strlen函数只有遇到'\0'时才停止,所以返回的个数是一个随机值。

故:我们使用strlen函数时,应该检查字符数组是否以'\0'为结束标志。

4.strlen函数的模拟实现

方式一:

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

 方式二:

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

  方式三:

int my_strlen(char* s)
{
	assert(str);
	char* p = s;
	while (*p != ‘\0’)
		p++;
	return p - s;
}

补充知识:assert(断言):是一个宏。

assert 的作用是,将括号中的表达式计算出 ,如果其值为假(即为0),那么它会打印出一条出错信息,然后终止程序的运行。这里的assert是防止指针p指向为NULL。

二、strcpy的使用和模拟实现

1.strcpy()函数的介绍

strcpy()函数:是将一个字符串复制到另一块空间地址中 的函数,‘\0’是停止拷贝的终止条件,同时也会将 '\0' 也复制到目标空间。下面是库中的strcpy()函数声明:

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

函数的参数:

char* destination---------目标字符串的首地址
const char* source------源地址:被复制的字符串的首地址,用const修饰,避免修改掉被拷贝的字符串

函数的返回值类型:

char*:返回的是目标字符串的首地址 

2.strcpy()函数的具体使用

场景一:

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

int main()
{
	char arr[10] = "########";
	printf("%s\n", strcpy(arr, "hello"));

	return 0;
}

输出的结果: 

场景二: 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
 
int main()
{
	char arr1[10] = "**********";
	char arr2[10] = "abcd";
	printf("%s\n", strcpy(arr1, arr2));
	return 0;
}

输出结果:

3.strcpy()函数的注意事项

1.源字符必须以 '\0'结束:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
 
int main()
{
	char arr1[10] = "**********";
	char arr2[] = { 'a','b','c','d' };
	printf("%s\n", strcpy(arr1,arr2));
 
	return 0;
}

这里的代码会出错,'\0'是停止拷贝的终止条件,arr2字符数组所在的内存空间后面存储的内容并不知道,不遇到 '\0' 拷贝就不会停止,这就会导致越界访问,程序就会出现问题。 

2.目标空间必须足够大,以确保能放源字符串

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
 
int main()
{
	char arr1[5] = "*****";
	char arr2[] = "hello world";
	printf("%s\n", strcpy(arr1,arr2));
 
	return 0;
}

这里虽然拷贝成功并将结果输出了,但程序却崩溃了。目标空间太小,不足以放置拷贝的源字符串,会造成溢出的情况 

3.目标空间必须可变

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
 
int main()
{
	char* str1 = "hello world";
	char str2[10] = "*********";
	printf("%s\n", strcpy(str1,str2));
 
	return 0;
}

这里的程序也出现了错误。str1指向的是常量字符串,是不可以被修改掉的,目标空间必须是可以被修改的,因为要将拷贝的字符串放在目标空间中。而源字符串可以是能够修改的,也可以是不能修改的,因为strcpy函数的第二个参数已经用const关键字修饰了,保证了拷贝过程中不会被修改。 

4.strcpy函数的模拟实现
char *my_strcpy(char *dest, const char*src)
{ 
 char *ret = dest;
 assert(dest != NULL);
 assert(src != NULL);
 
 while((*dest++ = *src++))
 {
    ;
 }
 return ret;
}

三、strcat 的使用和模拟实现 

1.strcat()函数的介绍

strcat的函数原型的声明为:

char*strcat(char* strDestination, const char* strSource);

其返回值为char*,需要传入两个参数

strcat函数可以将一个字符串追加到另外一个字符串的后面

2.strcat函数的具体使用

比如在“hello”后面追加一段“world”就可以用strcat函数来实现

#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[30] = "hello ";
	char arr2[] = "world";
	strcat(arr1, arr2);
	printf("%s\n", arr1);//追加字符串
    return 0;
}

 打印结果:

3.strcat函数的注意事项

• 源字符串必须以 '\0' 结束。

• 目标字符串中也得有 \0 ,否则没办法知道追加从哪里开始。

• 目标空间必须有足够的大,能容纳下源字符串的内容。

• 目标空间必须可修改。

• 字符串自己给自己追加,如何?

自己给自己追加

char* my_strcat(char* dest, const char* src)
{
	char* ret = dest;
	assert(dest && src);
	//1. 找到目标空间的\0
	while (*dest)
	{
		dest++;
	}
	//2. 拷贝
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}

int main()
{
	char arr1[20] = "hello ";
	my_strcat(arr1, arr1);
	printf("%s\n", arr1);
	return 0;
}

这样会一直追加下去,并且会造成访问越界。

4.strcat函数的模拟实现
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的使用和模拟实现

1.strcmp()函数的介绍

strcmp函数是C语言中的字符串比较函数,用于比较两个字符串的大小。

函数原型:

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

  • 该函数接受两个参数,分别为要比较的两个字符串的指针。
  • 返回值为整形,表示两个字符串的大小关系。

• 标准规定:

     ◦ 第⼀个字符串大于第⼆个字符串,则返回大于0的数字

     ◦ 第⼀个字符串等于第⼆个字符串,则返回0

     ◦ 第⼀个字符串小于第⼆个字符串,则返回小于0的数字

     ◦ 那么如何判断两个字符串? 比较两个字符串中对应位置上字符ASCII码值的大小。

2.strcmp()函数的具体使用

strcmp函数的比较规则是按照字典序进行比较,即逐个字符比较。具体的比较过程如下:

  1. 若两个字符相等,则继续比较下一个字符。
  2. 若两个字符不相等,则返回它们的ASCII码差值(ASCII码值大的字符串大)。
#include <stdio.h>
#include <string.h>
 
int main()
{
	char str1[] = "appple";
	char str2[] = "banana";
 
	int ret = strcmp(str1, str2);
	if (ret == 0)
		printf("str1和str2相等\n");
	else if (ret > 0)
		printf("str1大于str2\n");
	else
		printf("str1小于str2\n");
		
	return 0;
}

 

3.strcmp函数的注意事项

1、字符串的比较是按照字典序进行的,因此大小写字母的比较结果不同。

2、在比较字符串时,需要确保字符串以'\0'结尾,否则可能会导致比较结果不正确。

例如这个代码:

#include <stdio.h>
#include <string.h>
 
int main()
{
	char str1[] = "hello";
	char str2[] = "hello";
 
	str1[5] = '!';
	int ret = strcmp(str1, str2);
	if (ret == 0)
		printf("str1和str2相等\n");
	else if (ret > 0)
		printf("str1大于str2\n");
	else
		printf("str1小于str2\n");
 
	return 0;
}

 结果如下:

那为什么会这样呢?

分析如下

在这段代码中,我们将str1字符串的结尾标识符'\0'改成了'!',运行代码后,输出结果为"str1大于str2"。这是因为str1字符串没有以'\0'结尾,所以strcmp函数会继续比较下去,直到遇到str2字符串的结尾标识符'\0'。由于str1字符串比str2字符串长,所以str1被认为是大于str2。

4.strcmp函数的模拟实现
#include <stdio.h>
#include <string.h>
#include <assert.h>
 
int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);
	while (*str1 == *str2)
	{
		if (*str1 == '\0')
			return 0;//相等
		str1++;
		str2++;
	}
	if (*str1 > *str2)
		return 1;//大于
	else
		return -1;//小于
}
 
int main()
{
	char str1[] = "appple";
	char str2[] = "banana";
 
	int ret = my_strcmp(str1, str2);
	if (ret == 0)
		printf("str1和str2相等\n");
	else if (ret > 0)
		printf("str1大于str2\n");
	else
		printf("str1小于str2\n");
		
	return 0;
}

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

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

相关文章

【MySQL自身的性能优化】InnoDB 的 Buffer Pool

这里写目录标题 一、引入缓存的重要性二、InnoDB 的 Buffer Pool1. Buffer Pool 内部组成2. free 链表管理空闲页3. flush 链表管理脏页4. LRU 链表提高缓存命中那咱需要咋地解决预读问题呢&#xff1f;那咱需要咋地解决 Buffer Pool 污染问题呢&#xff1f; 5. 脏页什么时候被…

Spring Cloud可视化智慧工地大数据云平台源码(人、机、料、法、环五大维度)

智慧工地平台是依托物联网、互联网、AI、可视化建立的大数据管理平台&#xff0c;是一种全新的管理模式&#xff0c;能够实现劳务管理、安全施工、绿色施工的智能化和互联网化。围绕施工现场管理的人、机、料、法、环五大维度&#xff0c;以及施工过程管理的进度、质量、安全三…

鸿蒙harmony--数据库sqlite详解

今天是1月20号星期六&#xff0c;早安&#xff0c;岁末大寒至&#xff0c;静后春归来。愿他乡故人&#xff0c;漂泊有归宿&#xff0c;前程有奔赴&#xff0c;愿人间不寒&#xff0c;温暖常伴&#xff0c;诸事顺利&#xff0c;喜乐长安。 目录 一&#xff0c;定义 二&#xff…

Python seaborn库的边框设置(Seaborn篇-02)

Python seaborn库的边框设置(Seaborn篇-02)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔…

Swin版VMamba来了!精度再度提升,VMamba-S达成83.5%,超越Swin-S,已开源!

本文首发&#xff1a;AIWalker 就在昨日&#xff0c;华科王兴刚团队公开了Mamba在ViT的入局Vim&#xff0c;取得了更高精度、更快速度、更低显存占用。相关信息可参考&#xff1a; 入局CV&#xff0c;Mamba再显神威&#xff01;华科王兴刚团队首次将Mamba引入ViT&#xff0c;更…

钡铼 楼宇暖通网关之 BACnet网关在空气源热泵智能控制系统中的应用介绍

前言 在刚刚过去的2023年&#xff0c;空气源热泵市场依然火爆&#xff0c;全线市场销量递增&#xff0c;各种新品层出不穷&#xff0c;市场认可度持续攀升&#xff0c;在整个采暖市场&#xff0c;空气源热泵已然成为当红明星。 热泵组管道比较复杂&#xff0c;传感器分布比较分…

vue2 使用pdf.js 实现pdf预览,并可复制文本

需求&#xff1a;pdf预览&#xff0c;并且可以选中pdf的内容进行复制。 在ruoyi的vue前端项目中用到&#xff0c;参考了网上不少文章&#xff0c;因为大部分没给具体的pdf.js版本&#xff0c;导致运行过程中报各种api 错误&#xff0c;经过尝试以下版本可用&#xff0c…

Linux中的新建用户、切换用户

目录 一、Linux系统中有哪些用户 二、新建普通用户 三、root账号与普通账号的切换 一、Linux系统中有哪些用户 1.root 超级管理员&#xff08;不受权限约束&#xff09; 2.其他用户 普通用户&#xff08;受到权限约束&#xff09; 二、新建普通用户 创建新用户 sudo user…

HarmonyOS鸿蒙学习基础篇 - 项目目录和文件介绍

vue_basic├── hvigor //存储购置信息的文件&#xff0c;主要用于发布打包 ├── idea //开发工具相关配置可忽略 ├── AppScope //工程目录 全局公共资源存放路径 │ └── resources │ │ └── base │ │ │ └── element //常亮存放 │ │ …

2023年中国互联网测试开发大会(MTSC2023上海站):核心内容与学习收获(附大会核心PPT下载)

在当今快速发展的互联网时代&#xff0c;软件质量与用户体验的保障离不开测试开发工程师的辛勤付出。本次峰会正是在这样的背景下应运而生&#xff0c;旨在汇聚业界精英&#xff0c;共同探讨测试开发的最新技术与实践。本文将深入剖析大会的核心内容&#xff0c;以及参与者从中…

零日漏洞:威胁与应对

一、引言 随着信息技术的迅猛发展&#xff0c;网络安全问题日益凸显。其中&#xff0c;零日漏洞已成为当今网络安全领域最受关注的问题之一。本文将深入探讨零日漏洞的威胁、产生原因以及应对策略&#xff0c;以期提高人们对这一问题的认识和防范意识。 二、零日漏洞的威胁 …

elementUI+el-upload 上传、下载、删除文件以及文件展示列表自定义为表格展示

Upload 上传组件的使用 官方文档链接使用el-upload组件上传文件 具体参数说明&#xff0c;如何实现上传、下载、删除等功能获取文件列表进行file-list格式匹配代码 文件展示列表自定义为表格展示 使用的具体参数说明文件大小展示问题&#xff08;KB/MB&#xff09;文件下载代码…

Ubuntu中查看IP地址的常用命令及使用方法

在Ubuntu操作系统中&#xff0c;了解和查看IP地址是进行网络配置、故障排除以及连接其他设备的重要一步。 以下是几个常用的命令来查看IP地址&#xff1a; 一、ifconfig命令 输入ifconfig 输出如图所示&#xff0c;即为ip地址 如若提示没有ifconfig命令&#xff0c;则可以使用…

node.js(expree.js )模拟手机验证码功能及登录功能

dbconfig.js const mysql require(mysql) module.exports {// 数据库配置config: {host: localhost, // 连接地址port: 3306, //端口号user: root, //用户名password: wei630229, //密码database: exapp2, //数据库名}, // 连接数据库&#xff0c;使用mysql的连接池连接方式…

力扣36. 有效的数独

模拟 思路&#xff1a; 使用三个哈希表来存储数字个数 row[r][val] 用于存储第 r 行 val 1 的个数&#xff1b;column[c][val] 用于存储第 c 列 val 1 的个数&#xff1b; subboxes[i][j][val] 用于存储第 i 行、第 j 列个小九宫格 val 1 的个数&#xff0c;其中&#xff1…

原生微信小程AR序实现模型动画播放只播放一次,且停留在最后一秒

1.效果展示 0868d9b9f56517a9a07dfc180cddecb2 2.微信小程序AR是2023年初发布&#xff0c;还有很多问提&#xff08;比如glb模型不能直接播放最后一帧&#xff1b;AR识别不了金属、玻璃材质的模型等…有问题解决了的小伙伴记得告诉我一声&#xff09; 微信官方文档地址 3.代码…

HashMap 的底层实现#JDK1.8 之前

最近很多同学问我有没有java学习资料&#xff0c;我根据我从小白到架构师多年的学习经验整理出来了一份50W字面试解析文档、简历模板、学习路线图、java必看学习书籍 、 需要的小伙伴 可以关注我公众号&#xff1a;“ Tom聊架构 ”&#xff0c; 回复暗号&#xff1a;“ 578”即…

递归、搜索与回溯算法(专题一:递归)

往期文章&#xff08;希望小伙伴们在看这篇文章之前&#xff0c;看一下往期文章&#xff09; &#xff08;1&#xff09;递归、搜索与回溯算法&#xff08;专题零&#xff1a;解释回溯算法中涉及到的名词&#xff09;【回溯算法入门必看】-CSDN博客 接下来我会用几道题&#…

【开源】基于JAVA语言的教学资源共享平台

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 课程档案模块2.3 课程资源模块2.4 课程作业模块2.5 课程评价模块 三、系统设计3.1 用例设计3.2 类图设计3.3 数据库设计3.3.1 课程档案表3.3.2 课程资源表3.3.3 课程作业表3.3.4 课程评价表 四、系统展…

WebSocket协议、与HTTP对比

WebSocket 也可前往本人的个人网站进行阅读 WebSocket 和 HTTP WebSocket和HTTP协议一样&#xff0c;都是基于TCP协议实现的应用层协议。 HTTP协议通常是单边通信&#xff0c;主要用于传输静态文档、请求-响应通信&#xff0c;适用于Web浏览器加载网页、API调用等。然而Web…