当前位置: 首页 > news >正文

赶紧进来看看---详细介绍五种常用字符串库函数 以及对库函数的模拟实现

本文介绍了strlen.strcpy.strcmp.strcat.strstr五大字符串库函数及使用自定义函数模拟实现这五个字符串库函数.学会使用字符串库函数,在处理字符串时会事半功倍…

字符串函数介绍和模拟实现

  • 一.字符串函数介绍
    • 1.strlen计算字符串中字符个数函数
      • ①.strlen库函数的诞生
      • ②.strlen库函数介绍
      • ③strlen库函数使用
      • ④strlen库函数使用注意事项
    • 2.strcpy字符串拷贝函数
      • ①.strcpy库函数的诞生
      • ②.strcpy库函数介绍
      • ③.strcpy函数的使用
      • ④.strcpy库函数使用注意事项
    • 3.strcmp字符串比较函数
      • ①.strcmp库函数的诞生
      • ②.strcmp库函数的介绍
      • ③strcmp库函数的使用
      • ④strcmp库函数使用注意事项
    • 4.strcat字符串追加函数
      • ①.strcat库函数的诞生
      • ②.strcat库函数的介绍
      • ③.strcat库函数的使用
      • ④.strcat库函数的使用注意事项
    • 5.strstr判断是否存在子字符串函数
      • ①.strstr库函数的诞生
      • ②.strstr库函数的介绍
      • ③strstr库函数的使用
      • ④.strstr库函数的使用注意事项
  • 二.字符串函数模拟实现
    • 1.strlen库函数模拟实现
      • ①计数器方式模拟实现strlen
      • ②.指针减指针方式模拟实现strlen
      • ③.用递归方式模拟实现strlen
    • 2.strcpy字符串拷贝函数模拟实现
    • 3.strcmp字符串比较函数模拟实现
    • 4.strcat字符串追加函数模拟实现
    • 5.strstr库函数模拟实现
  • 二.总结

一.字符串函数介绍

使用字符串库函数首先需要包含字符串头文件->#include<string.h>
这篇博客中详细介绍到了函数->库函数和自定义函数

1.strlen计算字符串中字符个数函数

strlen为计数字符串中字符个数的函数
因为字符串是以’\0’结束的,计算的是字符串里’\0’前面所有的字符个数

①.strlen库函数的诞生

C语言中"abc"双引号括起来的字符被当作字符串abc,是由多个字符连接在一起形成一种数据,而在一些场景中如逆置字符串,
我们需要得到字符串中字符的个数,现在abc这个字符肉眼一下可以看出字符个数是3,但是字符个数多的时候无法一下看清,并且字符串字符个数可能根据实际情况发生变化,
如何用一种方法直接实现得到这个字符串里的字符个数因此封装设计了strlen这个库函数

②.strlen库函数介绍

右边是官网库函数strlen的描述->strlen详细信息
在这里插入图片描述

函数返回类型是一个无符号整形(因为字符个数没有负数)
函数形参是字符指针变量,接受的实参是字符串起始第一个字符地址

字符串已经 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包含 ‘\0’ )

③strlen库函数使用

在这里插入图片描述

上面实现的是将字符串赋给一个字符数组,而arr为数组名,单独使用表示的是数组首元素地址即字符a在数组里的地址,使用strlen计算出字符a开始往后的字符个数计算到直到\0为止得出了字符串字符个数为8

④strlen库函数使用注意事项

.strlen使用后返回的是无符号整数
strlen不会修改字符串的内容
strlen计算的字符数组里如果没有\0结束标志会继续往后寻找\0会造成越界访问 直到在内存空间里找到\0后返回\0前所有字符个数,结果就会发生随机值

2.strcpy字符串拷贝函数

strcpy库函数实现将一个字符串拷贝(复制)给另一个字符串常用于在数组里的字符串拷贝

①.strcpy库函数的诞生

当有两个字符数组arr,str存了两个字符串时,
想要str数组里的字符串赋给arr数组时,当我们写出arr=str 是不正确的,因为数组名单独使用表示的是数组首元素地址, 两个地址都是不可更改的,
更不能用这种方法实现拷贝,需要通过数组里面所有字符的地址解引用得到字符然后一一赋值,实现字符串拷贝
,因此封装设计了strcpy库函数

②.strcpy库函数介绍

strcpy库函数官网详细介绍->strcpy
在这里插入图片描述

strcpy库函数 有两个形参,第一个是目的地字符指针变量,第二个是源头字符指针变量,表示将源头指向的数组里的字符串拷贝到目的地字符指针指向的数组里
返回类型是目的地数组第一个字符指针,即拷贝到目的地的数组后返回拷贝完后的数组起始地址

③.strcpy函数的使用

在这里插入图片描述

通过两个数组名即数组首元素地址传参调用strcpy函数 实现将第二个数组里的字符串拷贝到第一个数组里,再通过数组名打印拷贝前后的数组内容.

④.strcpy库函数使用注意事项

源字符串必须以 ‘\0’ 结束。
会将源字符串中的 ‘\0’ 拷贝到目标空间。
strcpy会修改第一个字符串的内容
目标空间必须足够大,以确保能存放源字符串。
目标空间必须可变

3.strcmp字符串比较函数

用来比较两个字符串的大小

①.strcmp库函数的诞生

当我们需要比较两个字符串大小时,而字符串需要赋值到数组里或字符指针变量里仅仅用字符指针或者数组名 用==比较时是不正确的,
他们只是代表着字符串起始字符的地址不能用等号,需要通过指针指向字符串每个字符一一比较,实现这种功能最后封装设计了strcmp库函数

②.strcmp库函数的介绍

strcmp库函数官网详细介绍->strcmp
在这里插入图片描述

strcmp实现有两个形参,分别对应着要比较的字符串的起始字符地址
返回类型是一个整形,用来判断两个字符串大小的标准
标准规定:
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字

③strcmp库函数的使用

这里是引用
arr数组和str数组接受了两个字符串 ,通过数组名即各字符串首字符地址传参调用strcmp函数 进行比较两个数组里每个字符的大小,直到\0为止两个字符串都相等则返回0,期间arr有字符大于str则返回大于0的数,反之返回小于0的数,通过if判断得到两个字符串的比较情况

④strcmp库函数使用注意事项

比较两个字符串是每个字符串相对应的字符大小,直到比较到\0后停止或则期间字符大小不同后
strcmp不会更改两个字符串内容
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字

4.strcat字符串追加函数

用于将一个字符串追加到另一个字符串后面,将两个字符串合成一个字符串

①.strcat库函数的诞生

当我们想把两个字符串合在一起形成一个新的字符串,实
现这一功能用普通的赋值表达式是实现不了的,实现相应功能需要很多步骤,
需要先拿到被追加的字符串的\0再这个基础上往后赋上字符串的每个字符
而将这些步骤封装成一个函数,最后为了每次想追加字符串时不用自己再写一个类似函数 ,封装设计成了库函数

②.strcat库函数的介绍

strcat官网详细介绍->strcat

在这里插入图片描述

strcat库函数介绍有两个形参,第一个是目的地表示要被追加的字符串起始字符指针,
第二个参数是源头要追加过去的字符串的起始字符指针
返回的是被追加后的字符串的起始字符指针

③.strcat库函数的使用

在这里插入图片描述

arr数组存放着字符串"abc"但是数组容量是7个字符,因为追加后数组必须得容纳两个字符串所有字符的个数,
str数组存放字符串"def",arr和str数组名即两个字符串首字符地址传参调用strcat函数
实现将str里的字符串放到arr字符串后面,
再通过打印arr得到追加前和追加后的字符串内容发现完成了追加

④.strcat库函数的使用注意事项

源字符串必须以 ‘\0’ 结束。
追加字符串会修改目的地原字符串即后面多了第二个字符串内容
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改。

5.strstr判断是否存在子字符串函数

判断一个字符串里是否存在另一个字符串.

①.strstr库函数的诞生

字符串有各种个样,为了[]判断两个字符串间是否存在子集关系,即第一个字符串里是否完全包含第二个字符串功能.封装设计了strstr库函数

②.strstr库函数的介绍

strstr’库函数官网详细介绍->strstr
在这里插入图片描述

strstr库函数 有两个形参,第一个是被查找的是否存在子集字符串,第二个是子集字符串,即判断在第一个字符串里是否存在第二个字符串
返回类型是一个字符指针,
设计规定:当第一个字符串中存在第二个字符串,则返回第二个字符串在第一个字符串里第一次出现处第二个字符串第一个字符的地址
如果不存在则返回NULL空指针

③strstr库函数的使用

在这里插入图片描述

arr存放"abcabc",str数组存放"bc",显然字符串bc是字符串abcabc子集
并且arr数组里字符串有两个bc,但是最后通过打印返回的指针发现得到的是第一个字符串里 第一个ac字符串的a地址 ,输出了bcabc

④.strstr库函数的使用注意事项

strstr库函数使用不会改变两个字符串的字符
存在子集关系返回字符串里第一个字符串内第一个与第二个字符串相等的字符串首字符地址
不存在则返回空指针NULL

二.字符串函数模拟实现

根据字符串函数相对应的功能,模拟实现功能相似的自定义函数…

1.strlen库函数模拟实现

①计数器方式模拟实现strlen

在这里插入图片描述

使用count作为计数器的方式 存储字符串里的字符个数最后返回
my_strlen实现了和strlen一样的功能

②.指针减指针方式模拟实现strlen

在这里插入图片描述

采用两个指针相减得到期间的元素个数 即字符串的字符个数

③.用递归方式模拟实现strlen

在这里插入图片描述

采用递归,层层每次加1调用自身指针加1直到arr为\0时开始返回将期间加的1累计起来最后得到字符串的字符个数返回

2.strcpy字符串拷贝函数模拟实现

在这里插入图片描述

在表达式里 实现的将当前str指向的字符 赋给arr指向的空间
然后两个指针都指向下一个空间然后 表示为真进入循环 ,
当最后str指向的是\0赋值给arr指向的空间后表达式为假结束循环,完成了字符串拷贝
最后返回被拷贝的字符串起始地址

3.strcmp字符串比较函数模拟实现

#define _CRT_SECURE_NO_WARNINGS
#include<assert.h>
#include<stdio.h>
int my_strcmp(const char* arr, const char* str)
{
	assert(arr != NULL && str != NULL);   //避免两个指针为空指针
	while (*arr != '\0' && *arr==*str) //当满足 arr指向的空间里的字符不是'\0'同时 arr指向的字符等于str指向的字符时进入循环
	{
		arr++;    //两个指针同时指向后一个字符
		str++;
	}
	if (*arr == *str)   //当while循环结束此时就得出了两个字符串最后的结果 要么相等,要么arr>str 要么arr<str用多分支判断大于返回1小于-1等于返回0
	{
		return 0;
	}
	else if (*arr > *str)
	{
		return 1;
	}
	else
	{
		return -1;
	}
	
}
int main()
{
	char arr[] = "abcde";
	char str[] = "abcde";
	int num = my_strcmp(arr, str);
	if (num == 0)
	{
		printf("arr==str相等\n");
	}
	else if (num > 0)
	{
		printf("arr>str\n");
	}
	else
	{
		printf("arr<str\n");
	}
	return 0;
}

在这里插入图片描述

4.strcat字符串追加函数模拟实现

在这里插入图片描述

先找到 arr数组字符串\0位置 再将str字符串从\0位置开始覆盖 最后arr数组里为两个字符串合并后的新字符串,完成字符串追加

5.strstr库函数模拟实现

#include<stdio.h>
#include<assert.h>
char* my_strstr(const char* arr, const char* str)   // 用const 修饰表示 指针指向的字符不能被修改
{
	assert(arr != NULL && str != NULL);   //断言防止 arr  和str为NULL
	
	char *arr1 = arr;                  //用arr1 str1指针进行移动 使指向的字符进行比较 arr和str记录起始比较位置
	char* str1 = str;                 //记录开始比较的字符位置
	if (*str1 == '\0')         //当str1即起始字符指针指向的字符为\0表示str是空字符串 空集也是arr的子集此时返回arr起始地址
	{
		return arr;
	}
	while (1)   
	{
		while (*arr1 != *str1)  // 使arr1指针指向的字符和str1指针指向的字符相等 
		{
			arr1++;
		}
		arr = arr1;    //arr记录开始比较的起始地址
		while (*arr1 == *str1 && *str1 != '\0')   //  当arr1和str1指向的空间不等 或者 str1指向了\0结束循环
		{
			arr1++;
			str1++;
		}
		if (*str1 == '\0')                 //多分支先判断 str1指向的空间是否为\0 如果是则说明str1前面的所有字符都和arr1里的字符比较了且相等 此时返回arr
		{
			return arr;
		}
		else if (*arr == '\0')         //上分支不成立 看这个分支 当arr1指向的是\0说明 str1还有字符没比完,此时不用继续比较了,arr1字符串里已经不存在str1字符串了
		{
			return NULL;
		}
		else                      //如果是两者不相等 则利用arr  和str 还原开始比较前的位置  arr1从arr+1处继续开始比较
		{
			arr1 = arr + 1;
			str1 = str;
		}
	}
	
}


int main()
{
	char arr[] = "abcabc";
	char str[] = "bc";
	char* ret = my_strstr(arr, str);
	if (ret == NULL)
	{
		printf("str不是arr的子集\n");
	}
	else
	{
		printf("str是arr的子集:%s", ret);
	}
	return 0;
}

在这里插入图片描述

二.总结

本篇博客中介绍了五种常用的字符串库函数,并对各字符串库函数进行了模拟实现,这几个库函数都是比较常见的,熟悉掌握后在后续使用它们解决遇到的字符串相关的问题能够事半功倍…

在这里插入图片描述

写文不易,给个一键三连支持下吧~

相关文章:

  • 浅谈 python在密码学的应用
  • lammps数据后处理:python绘制应力应变曲线 附程序代码
  • 机器学习模型2——决策树
  • Java.lang.Character类中codePointAt(CharSequence seq, int index)方法具有什么功能呢?
  • docker-compose 安装Harbor
  • 微服务项目:尚融宝(52)(核心业务流程:充值服务(3))
  • python的小作业
  • 2022届计算机毕业论文(设计)学生选题参考合集推荐收藏
  • AI艺术的背后:详解文本生成图像模型【基于GAN】
  • NR 物理层编码 - slide4 循环码Cyclic Code
  • 内网渗透-内网信息收集
  • 新学期、新目标、迎接新的自己
  • 2022年重庆自考如何报名,有哪些条件和要求?
  • 70 QDateTime时间戳转换有误
  • 中科大给师生们发了一封钓鱼邮件 结果3000多人上当了
  • [译] 理解数组在 PHP 内部的实现(给PHP开发者的PHP源码-第四部分)
  • 【162天】黑马程序员27天视频学习笔记【Day02-上】
  • 002-读书笔记-JavaScript高级程序设计 在HTML中使用JavaScript
  • 03Go 类型总结
  • create-react-app做的留言板
  • docker-consul
  • Java 内存分配及垃圾回收机制初探
  • Lsb图片隐写
  • opencv python Meanshift 和 Camshift
  • PermissionScope Swift4 兼容问题
  • SOFAMosn配置模型
  • thinkphp5.1 easywechat4 微信第三方开放平台
  • vue--为什么data属性必须是一个函数
  • 多线程 start 和 run 方法到底有什么区别?
  • 二维平面内的碰撞检测【一】
  • 深入浅出webpack学习(1)--核心概念
  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • Mac 上flink的安装与启动
  • 大数据全解:定义、价值及挑战
  • 数据库巡检项
  • 微龛半导体获数千万Pre-A轮融资,投资方为国中创投 ...
  • 曜石科技宣布获得千万级天使轮投资,全方面布局电竞产业链 ...
  • # 数据结构
  • #Z2294. 打印树的直径
  • (cos^2 X)的定积分,求积分 ∫sin^2(x) dx
  • (day6) 319. 灯泡开关
  • (Java)【深基9.例1】选举学生会
  • (zz)子曾经曰过:先有司,赦小过,举贤才
  • (第61天)多租户架构(CDB/PDB)
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (过滤器)Filter和(监听器)listener
  • (黑马C++)L06 重载与继承
  • (每日持续更新)jdk api之FileFilter基础、应用、实战
  • (十八)三元表达式和列表解析
  • (算法)求1到1亿间的质数或素数
  • (转载)跟我一起学习VIM - The Life Changing Editor
  • .form文件_一篇文章学会文件上传
  • .java 9 找不到符号_java找不到符号
  • .NET 6 在已知拓扑路径的情况下使用 Dijkstra,A*算法搜索最短路径
  • .Net Core 中间件验签