字符函数与字符串函数(上)

news2024/11/17 15:50:42

个人主页(找往期文章包括但不限于本期文章中不懂的知识点):我要学编程(ಥ_ಥ)-CSDN博客

 

目录

strlen的使用与模拟实现

函数原型:

strlen的使用 

strlen的模拟使用 

strcpy的使用与模拟实现

函数原型:

strcpy的使用 

strcpy的模拟实现: 

strcat的使用与模拟实现 

函数原型:

strcat的使用 

strcat的模拟实现 

strcmp的使用与模拟实现 

函数原型:

strcmp的使用 

strcmp的模拟实现


strlen的使用与模拟实现

函数原型:

size_t strlen ( const char * str );//求字符串的长度

• 字符串以 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。

• 参数指向的字符串必须要以 '\0' 结束。

• 注意函数的返回值为size_t,是无符号的

• strlen的使用需要包含头文件 <string.h>

• 学会strlen函数的模拟实现 

strlen的使用 

#include <stdio.h>
#include <string.h>
int main()
{
	char ch[] = "abcdef";//有'\0'结尾
	size_t ret = strlen(ch);
	printf("%zd\n", ret);
	return 0;
}

#include <stdio.h>
#include <string.h>
int main()
{
	char ch[] = { 'a','b','c' };//没有以'\0'结尾
	size_t ret = strlen(ch);
	printf("%zd\n", ret);
	return 0;
}

strlen的模拟使用 

方法1(计数器的方式):

#include <stdio.h>
#include <assert.h>//断言包含的头文件
size_t my_strlen(const char* str)
{
	size_t count = 0;
	assert(str);//不等于空指针程序正常运行
	while (*str)//当不等于'\0'时,进入
	{
		count++;
		str++;
	}
	return count;
}

int main()
{
	char arr[] = "abcdef";
	size_t ret = my_strlen(arr);
	printf("%zd\n", ret);
	return 0;
}

方法2(指针-指针的方式) :

#include <stdio.h>
#include <assert.h>
size_t my_strlen(const char* str)
{
	assert(str);
	const char* str2 = str;//记录起始位置
	while (*str)
	{
		str++;
	}
	return str - str2;//末地址-起始地址就是两者之间的元素个数
}

int main()
{
	char arr[] = "abcdef";
	size_t ret = my_strlen(arr);
	printf("%zd\n", ret);
	return 0;
}

方法3(递归的方式):

#include <stdio.h>
#include <assert.h>
size_t my_strlen(const char* str)
{
	assert(str);
	if (*str == '\0')
	{
		return 0;//当为'\0'时,就返回
	}
	return 1 + my_strlen(++str);
}

int main()
{
	char arr[] = "abcdef";
	size_t ret = my_strlen(arr);
	printf("%zd\n", ret);
	return 0;
}

递归存在一个限制条件,并且随着递归的深入越来越接近这个限制条件。这个限制条件应该是比较容易想到的, 就是等于'\0'的时候,写法和求n的阶乘类似。

strcpy的使用与模拟实现

函数原型:

char* strcpy(char * destination, const char * source );//字符串的拷贝

source是被拷贝字符串,即源字符串;destination是把字符串拷贝到这里,即目标字符串。其返回类型是char*,返回的是一个地址:目标字符串的起始地址。

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

• 会将源字符串中的 '\0' 拷贝到目标空间。

• 目标空间必须足够大,以确保能存放源字符串。

• 目标空间必须可修改。(当目标空间有时,也是从源头开始拷贝,这也就导致了一个问题,目标空间原来的字符串被覆盖了。)

• 学会模拟实现。

strcpy的使用 

#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[20] = { 0 };//当目标空间不足时,也会完全拷贝,但是会报错
	char arr2[] = "abcdef";
	strcpy(arr1, arr2);
	printf("%s\n", arr1);
	printf("%s\n", arr2);
	return 0;
}

因此源字符串也是要以'\0'结尾,因为这样才能知道拷贝的具体内容。

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

如果要把 edf 搞到 abc 的后面需要用到另外一个函数strcat 。

上面这个就是目标空间不足时(会导致越界访问),报错界面。 

strcpy的模拟实现: 

根据前面的函数原型我们就可以开始来来模拟实现strcpy函数了。首先得想出思路:是将源字符串的字符赋值给目标空间,然后指向两者地址的指针往后走,直至遇到源字符串的'\0'就可以停止了。

#include <stdio.h>
#include <assert.h>
char* my_strcpy(char* str1, const char* str2)
{
	assert(str1 && str2);//限制不为空指针
	char* p = str1;
	while (*str2)//当还没有遇到'\0'时,就继续拷贝
	{
		*str1 = *str2;
		str1++;
		str2++;
	}
	//因为我们要返回目标空间的初始地址,就得记录一下初始地址
	return p;
}

int main()
{
	char arr1[20] = { 0 };
	char arr2[] = "abcdef";
	char* ret = my_strcpy(arr1, arr2);
	my_strcpy(arr1, arr2);
	printf("%s\n", ret);//ret接收的时arr1的初始地址,也就是首元素的地址
	printf("%s\n", arr1);//数组名是首元素的地址,因此这两个打印的结果是相同的
	return 0;
}

当然这个模拟实现strcpy的部分还可以简化一些。

#include <stdio.h>
#include <assert.h>
char* my_strcpy(char* str1, const char* str2)
{
	assert(str1 && str2);//限制不为空指针
	char* p = str1;
	//这个可以根据优先级来理解:++(后置)> * > = ,由于是后置++,所以是先使用str1与str2
	//即*str1 与 *str2,再++,最后再赋值
	while(*str1++ = *str2++)
	{
		;
	}
	//因为我们要返回目标空间的初始地址,就得记录一下初始地址
	return p;
}

int main()
{
	char arr1[20] = { 0 };
	char arr2[] = "abcdef";
	char* ret = my_strcpy(arr1, arr2);
	my_strcpy(arr1, arr2);
	printf("%s\n", ret);
	printf("%s\n", arr1);
	return 0;
}

strcat的使用与模拟实现 

函数原型:

char * strcat ( char * destination, const char * source );//字符串的拼接(追加)

这些函数参数也是和strcpy一样的意义,source是要拼接的字符串,destination是被拼接的字符串。其返回的是char*,是目标空间的起始地址 

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

• 目标字符串中也得有 '\0' ,否则没办法知道追加从哪里开始(在追加的时候会把这个'\0',给覆盖掉)。

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

• 目标空间必须可修改。

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

strcat的使用 

#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[20] = "hello ";//当这个空间不足时,虽然依然会完全追加,但是会报错
	char arr2[] = "world";
	char* p = strcat(arr1, arr2);
	printf("%s\n", p);
	return 0;
}

当目标空间不足时,报错界面与上面的一样,也是越界访问导致的。

strcat的模拟实现 

#include <stdio.h>
#include <assert.h>
char* my_strcat(char* str1, const char* str2)
{
	assert(str1 && str2);//控制不是空指针
	char* p = str1;
	//我们得先找到目标字符串的'\0',再在'\0'后追加
	while (*str1)
	{
		str1++;
	}
	//当跳出这个while循环就代表我们已经找到这个'\0'的地址了,接下来开始追加
	while (*str2)//这个也可以和上面那个strcpy一样简化
	{
		*str1 = *str2;
		str1++;
		str2++;
	}
	*str1 = *str2;//因为while循环里没有把'\0'追加到目标字符串
	return p;
}

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

strcmp的使用与模拟实现 

函数原型:

int strcmp ( const char * str1, const char * str2 );//字符串的比较

str1与str2就是我们想要比较的字符串。其返回类型是 int  ,当str1 > str2时,返回大于0的数;当str1 == str2时,返回等于0的数;当str1 < str2时,返回0。比较两个字符串中对应位置上字符ASCII码值的大小。 而在比较时,是一个字符一个字符的比较。

例如:我们比较 abc 与 abq时,是 a 与 a 比较,当它们相等时,就比较下一个,会一直比较到两个字符不相等(当出现了字符不相等的时候,比较也就结束了。即使后面还有也不再比较),或者全部比较完。就像上面那个例子,当我们比较到 c 与 q 时,c < q,就会返回一个小于0的数字。(注意会比较到'\0'才停止

strcmp的使用 

#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abc";
	int ret = strcmp(arr1, arr2);
	printf("%d\n", ret);
	return 0;
}

#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abq";
	int ret = strcmp(arr1, arr2);//q>c,也就是arr1<arr2,输出一个小于0的数
	printf("%d\n", ret);
	return 0;
}

有细心的小伙伴可能会发现,这个arr1大于arr2,输出的是一个数字1。其实这个还是和编译器有关的,我这个是VS2022,大于0,输出的就是1;小于0,就是输出-1。 

strcmp的模拟实现

#include <stdio.h>
#include <assert.h>
int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);
	while (*str1 == *str2)
	{
		//本来是*str1 == *str2 == '\0',但因为*str1 == *str2,所以就简写
		if (*str1 == '\0')
		{
			return 0;
		}
		str1++;
		str2++;
	}
	//如果要和编译器一样的话,就可以写成:
	/*if (*str1 - *str2 > 0)
	{
		return 1;
	}
	else if (*str1 - *str2 < 0)
	{
		return -1;
	}*/
	return *str1 - *str2;//返回两者不相等的情况
}
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abq";
	int ret = my_strcmp(arr1, arr2);
	printf("%d\n", ret);
	return 0;
}

上面这一系列函数是长度没有限制的。例如:在拷贝时,我们没有限制拷贝几个字符;在追加时,没有限制追加几个字符;在比较时,没有比较几个字符。但是如果我们想要限制长度,怎么实现呢?C语言库还给出了长度限制的一系列函数,这类函数就让我们下期一起来学习吧!。

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

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

相关文章

【冲击蓝桥篇】动态规划(上):真题实战+思路解析

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《数据结构与算法&#xff1a;初学者入门指南》&#x1f4d8;&am…

普中51单片机学习(EEPROM)

EEPROM IIC串行总线的组成及工作原理 I2C总线的数据传送 数据位的有效性规定 I2C总线进行数据传送时&#xff0c;时钟信号为高电平期间&#xff0c;数据线上的数据必须保持稳定&#xff0c;只有在时钟线上的信号为低电平期间&#xff0c;数据线上的高电平或低电平状态才允许…

【Java 基础】Java 数组、方法极致精讲

《Java 零基础入门到精通》专栏持续更新中。通过本专栏你将学习到 Java 从入门到进阶再到实战的全套完整内容,所有内容均将集中于此专栏。无论是初学者还是有经验的开发人员,都可从本专栏获益。 订阅专栏后添加我微信或者进交流群,进群可找我领取 前端/Java/大数据/Python/低…

从0到1使用C++实现一个模拟器-1-【实现最简CPU】

文章目录 uint64_tstdstd::arrayCPU和CU类构造函数size_tstatic_caststd::ifstreamriscv64-unknown-elf-objcopy -O binary add-addi add-addi.binriscv64-unknown-elf-gcc -Wl,-Ttext0x0 -nostdlib -o add-addi add-addi.s-wlstd::hex std::setw() std::setfill()各自的用法he…

upload-Labs靶场“1-5”关通关教程

君衍. 一、环境搭建二、第一关 前端JS检测后缀1、源码分析2、禁用浏览器JS上传3、burp抓包修改 三、第二关 MIME头验证1、源码分析2、burp抓包绕过 四、第三关 PHP3绕过1、源码分析2、PHP3绕过 五、第四关 .htaccess重写绕过1、源码分析2、.htaccess复写 六、第五关 黑名单大小…

Qt槽函数不响应的原因总结

Qt专栏&#xff1a;http://t.csdnimg.cn/LE2Lx 目录 1.问题 2.原因 2.1.没有继承QObject&#xff0c;声明Q_OBJECT宏 2.2.信号槽参数不匹配 2.3.信号函数未声明为 signals 2.4.访问权限 2.5.注意connect的位置&#xff0c;信号在创建信号槽连接前使用&#xff0c;则无法…

C#使用iText7将多个PDF文档合并为单个文档

使用HtmlAgilityPack抓取并分析网页内容&#xff0c;然后再调用PuppeteerSharp将网页生成PDF文件&#xff0c;最终的成果如下图所示&#xff0c;得到将近120个pdf文档。能看&#xff0c;但是不方便&#xff0c;需要逐个打开文档才能看到所需的内容&#xff0c;最好能将这些文档…

java 企业培训管理系统Myeclipse开发mysql数据库web结构jsp编程计算机网页项目

一、源码特点 java 企业培训管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

Vulnhub靶机:basic_pentesting_2

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.4&#xff09; 靶机&#xff1a;basic_pentesting_2&#xff08;10.0.2.7&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://download.vulnhub.c…

未来已来:智慧餐饮点餐系统引领餐饮业的数字化转型

时下&#xff0c;智慧餐饮点餐系统正在引领着餐饮业迈向更高的位置。今天&#xff0c;小编将与大家共同探讨智慧餐饮点餐系统的发展趋势、优势以及对餐饮业的影响。 一、智慧餐饮点餐系统的发展趋势 智慧餐饮点餐系统的出现填补了这一空白&#xff0c;它通过引入数字化技术&a…

基于springboot+vue的医院资源管理系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

IDEA-DeBug理论与实践

文章目录 01_Debug简介和意义02_IDEA中的Debug步骤03_跳转到当前代码执行的行04_步过调试的使用05_步入调试的使用06_强制步入调试的使用07_步出调试的使用08_回退断点调试的使用09_运行到光标处10_计算表达式11_条件断点12_多线程调试 在软件开发中&#xff0c;IDEA&#xff0…

让燃油车再次破防 比亚迪汉唐荣耀双出击

相信很多读者朋友都还记得&#xff0c;就在不久前趣味科技曾经报道&#xff0c;2024龙年伊始比亚迪就打着“电比油低”的旗号&#xff0c;推出了价格仅为7.98万元起的秦PLUS、驱逐舰05荣耀版&#xff0c;向合资燃油车发起了大举进攻。 这两款“7”字头售价的车型上市&#xff0…

<网络安全>《60 概念讲解<第七课 网络模型OSI对应协议>》

1 OSI模型 OSI模型&#xff08;Open Systems Interconnection Model&#xff09;是一个由国际标准化组织&#xff08;ISO&#xff09;提出的概念模型&#xff0c;用于描述和标准化电信或计算系统的通信功能&#xff0c;以实现不同通信系统之间的互操作性。该模型将通信系统划分…

智能驾驶规划控制理论学习-基于采样的规划方法

目录 一、基于采样的规划方法概述 二、概率路图&#xff08;PRM&#xff09; 1、核心思想 2、实现流程 3、算法描述 4、节点连接处理 5、总结 三、快速搜索随机树&#xff08;RRT&#xff09; 1、核心思想 2、实现流程 3、总结 4、改进RRT算法 ①快速搜索随机图&a…

每日一类:QString类深入讲解

QString类是Qt框架中的一个核心组件&#xff0c;设计用于方便、高效地处理Unicode字符串。与标准C中的字符串处理方式相比&#xff0c;QString提供了更为丰富的API&#xff0c;支持国际化&#xff0c;并且内部使用UTF-16编码&#xff0c;能够处理世界上几乎所有的语言文字。 设…

Python图像形态学处理:腐蚀、膨胀、礼帽、黑帽……

文章目录 二值形态学灰度形态学 python图像处理教程&#xff1a;初步&#x1f4f7;插值变换 最基础的形态学操作有四个&#xff0c;分别是腐蚀、膨胀、开计算和闭计算&#xff0c;【scipy.ndimage】分别实现了二值数组和灰度数组的这四种运算。而针对灰度图像&#xff0c;【sc…

android路由表APP,携程Android面试题

大家应该看过很多分享面试成功的经验&#xff0c;但根据幸存者偏差的理论&#xff0c;也许多看看别人面试失败在哪里&#xff0c;对自己才更有帮助。 最近跟一个朋友聊天&#xff0c;他准备了几个月&#xff0c;刚刚参加完字节跳动面试&#xff0c;第二面结束后&#xff0c;嗯&…

(案例贴2) html+css 倒计时器

欢迎大家使用这个计时器噢 老哥直接附代码咯. timer.html <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">&l…

python 小游戏《2048》字符版非图形界面

参考链接&#xff1a; 闲谈2048小游戏和数组的旋转及翻转和转置 目录 2048 一、方阵类 二、随机插入1或2 三、 合并和递增 四、 判断和移动 五、 键盘控制 完整源代码 玩法过程 2048 上回说到2048小游戏中数组的各种旋转、翻转的方法&#xff0c;就是为代码编程作准…