【C语言进阶(6)】字符串函数的使用方法 + 模拟实现

本文详细介绍了C语言中的字符操作函数如分类和转换,以及字符串操作函数如strlen、strcpy、strcat、strcmp、strncpy、strncat、strstr、strtok和strerror,包括它们的功能、参数和用例,以及模拟实现这些标准库函数的方法。
摘要由CSDN通过智能技术生成

本文重点介绍函数

  • 求字符串长度 —— strlen
  • 长度不受限制的字符串函数 —— strcpy、strcat、strcmp
  • 长度受限制的字符串函数 —— strncpy、strncat、strncmp
  • 字符串查找函数 —— strstr、strtok
  • 错误信息报告函数 —— strerror

Ⅰ 字符操作函数

引用头文件

  • <ctype.h>

⒈字符分类函数

函数名函数功能
iscntrl判断是否是控制字符
isspace判断是否是空白字符:空格‘ ’,换页‘\f’,换行’\n’,回车‘\r’,制表符’\t’或者垂直制表符’\v’
sdigit判断是否是十进制数字: 0~9
isxdigit判断是否是十六进制数字:包括所有十进制数字,小写字母 a ~ f,大写字母 A ~ F
islower判断是否是小写字母:a ~ z
isupper判断是否是大写字母 A ~ Z
isalpha判断是否是字母:a ~ z 或 A ~ Z
isalnum判断是否是字母或者数字:a ~ z,A ~ Z,0 ~ 9
ispunct判断是否是标点符号:任何不属于数字或者字母的图形字符(可打印)
isgraph判断是否是任何图形字符
isprint判断是否是任何可打印字符,包括图形字符和空白字符

⒉字符转换函数

函数名函数功能
toupper将小写字母转换成大写字母
tolower将大写字母转换成小写字母

函数用例

int main()
{
	char str[] = "i WANT TO PLAY bLACK mYTH wUKONG!";

	for (int i = 0; i < strlen(str); i++)
	{
		if (islower(str[i]))
		{
			str[i] = toupper(str[i]);
		}
		else if (isupper(str[i]))
		{
			str[i] = tolower(str[i]);
		}
	}

	printf("%s\n", str);

	return 0;
}

在这里插入图片描述

Ⅱ 字符串操作函数

字符串函数相关知识

  • 字符串末尾一定悄悄的藏着一个 ’ \0 '。
  • 字符串函数引用头文件:<string.h>
  • 只能对字符串进行操作,有 ’ \0 ’ 这个限制条件

⒈strlen

求字符串长度

size_t strlen ( const char * str );
  • size_t 是个无符号整形,想打印 strlen 函数的返回值最好使用 %zd 。

函数功能

  • 求字符串长度,返回 ’ \0 ’ 之前出现的所有字符个数。

函数参数

  • 一个字符串的首字符的地址。

函数用例

在这里插入图片描述

⒉strcpy

拷贝字符串

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

函数功能

  • 将 source 指向的字符串(包含 ’ \0 ')复制到 destination 指向的数组中,然后返回 destination 空间的起始地址。
  • 为了避免溢出,destination 指向的数组的大小应该 足够容纳 source 指向的串中得所有内容。

在这里插入图片描述

函数参数

  • source:指向被复制的字符串。
  • destination:指向要在其中复制内容的目标数组。

返回值

  • destination 数组的起始地址。

函数用例

在这里插入图片描述

⒊strcat

连接字符串

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

函数功能

  • 将一个字符串(包含 ’ \0 ')连接到另一个字符串的后面。
  • 要求目标数组里已经包含一个字符串(可以是空串),找到目标字符串的末尾并将源字符串 cv 过去。

函数参数

  • source:要追加的字符串,与目的地的内存不能重叠。
  • destination:指向目标数组的指针,该数组应包含一个字符串,并且足够大以包含连接的结果字符串。

返回值

  • destination 数组的起始地址。

函数用例

在这里插入图片描述

⒋strcmp

比较字符串

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

函数功能

  • 比较两个字符串的是否相同
  • 从第一个字符开始,依次对比两个字符串中每个对应字符的 ASCII 码值的大小。如果第一个字符串的字符的 ASCII 码小于第二个字符串对应字符的 ASCII 码,则返回一个小于 0 的值;如果大于,则返回一个大于 0 的值。

在这里插入图片描述

函数参数

  • str1:指向第一个字符串的起始地址。
  • str2:指向第二个字符串的起始地址。

函数用例

在这里插入图片描述

⒌strncpy

指定拷贝字符数

char * strncpy ( char * destination, const char * source, size_t num );

函数功能

  • 在实现程序复制的时候,应该限制源字符串的长度,确保目标数组在执行完复制后不会发生溢出。
  • 于是就有了 strncpy。在 strcpy 的基础上添加了一个参数,用来指定拷贝的字符个数

函数参数

  • source:指向被复制的字符串。
  • destination:指向要在其中复制内容的目标数组。
  • num:指定从 source 指向的字符串中拷贝 num 个字符到 destination 指向的目标数组中。

函数用例

在这里插入图片描述

⒍strncat

指定连接字符数

char * strncat ( char * destination, const char * source, size_t num );

函数功能

  • 指定从 source 指向的串中连接 num 个字符到 destination 指向的字符串的末尾
  • 与 strncpy 不同的是,strncat 总是在连接后自动追加一个结束符(’ \0 ')

函数用例

在这里插入图片描述

⒎strncmp

指定比较字符数

int strncmp ( const char * str1, const char * str2, size_t num );

函数功能

  • 指定比较两个字符串的前 num 个字符

函数用例

在这里插入图片描述

⒏strstr

找字符串子串

const char * strstr ( const char * str1, const char * str2 );
      char * strstr (       char * str1, const char * str2 );

函数功能

  • 在 str1 指向的字符串中查找是否存在字符串 str2
  • 看看 str1 里面是否包含 str2,如果包含则返回首次出现 str2 字符的起始地址,反之则扔一个空指针回来。

在这里插入图片描述

函数参数

  • str1:指向待查找的字符串。
  • str2:指向被查找的字符串。

函数用例

在这里插入图片描述

⒐strtok

分割字符串

char * strtok ( char * str, const char * delimiters );

函数功能

  • 按照 delimiters 中提供的分割符,将 str 中出现提供的分割符的位置改成 \0,并将 str 这个串在此处结尾。
char str[] = "wwwoBlack_myth_wukong0com";
char* deli = "o_0";

- 按照 deli 提供的字符对 str 进行分割;
- 将 str 中 o_0 这几个字符的位置换成 \0,www\0Black_myth_wukong0com
- 然后返回分隔的位置之前的串的首地址

函数参数

  • str:指向待被分割的字符串。
  • delimiters:用作分割符的字符(可以是一个字符,也可以是一个集合)。

返回值

  • 返回被分解的第一个子字符串的首字符地址。
  • 若无可检索的字符串,则返回 NULL1。

注意事项

  • strtok 函数会改变被操作的字符串,所以在使用 strtok 函数切分的字符串一般都是临时拷贝的内容并且可修改。
  • strtok 的第一个参数不为 NULL 时,函数将找到 str 中第一个分割符,strtok 函数将保存它在字符串中的位置。

在这里插入图片描述

  • strtok 的第一个参数是为 NULL 时,函数将在同一个字符串中被保存的位置开始,查找下一个分割符。

在这里插入图片描述

  • 如果 strtok 函数找不到分割符,则返回 NULL。

函数用例

  • strtok 函数会记录 str 串中出现分割符的位置,不用担心传 NULL 会找不到 str。

在这里插入图片描述

⒑strerror

错误报告函数

char * strerror ( int errnum );

函数功能

  • 返回错误码所对应的错误信息
  • 错误码对应的错误信息不需要去记,C 语言的库函数在执行失败的时候,都会设置错误码。

函数用例

在这里插入图片描述

实际使用

  • 如果在可能发生错误的情况下需要先判断错误信息,这个时候时没有提供错误码的。

  • 此时就需要将错误码先记录在 errno 变量里,直接将 errno 交给 strerror 即可,就不用每次手动输入错误码那么挫了。

  • errno:C 语言设置的一个存放错误码的全局变量。引用头文件:<errno.h>。当出现新的错误码时,会将旧的覆盖掉,始终记录最新的。

在这里插入图片描述

Ⅲ 模拟实现字符串函数

  • 模拟实现字符串函数,就得保证自定义函数的(参数、返回值)同库函数一致

⒈模拟实现 strlen

1. 计数器法

size_t my_strlen(const char* str)
{
	assert(str);
	size_t len = 0;
	
	while (*str++)
	{
		len++;
	}

	return len;
}

2. 递归法

size_t my_strlen(const char* str)
{
	assert(str);

	if (*str != '\0')
	{
		return 1 + my_strlen(str + 1);
	}
	else
	{
		return 0;
	}
}

3. 指针 - 指针法

size_t my_strlen(const char* str)
{
	assert(str);
	char* start = str;
	char* end = start;

	while (*++end != '\0');

	return end - start;
}

⒉模拟实现 strcpy

char* my_strcpy(char* dest, const char* sour)
{
	assert(dest && sour);
	char* start = dest;;		//源头的地址放到目标空间中会导致目标空间的地址被改变,先用 start 保留目标空间的地址

	while (*dest++ = *sour++);	//将 sour 指向的包含 '\0' 的字符串赋给 dest 指向的空间

	return start;				//返回目标空间的起始地址
}

⒊模拟实现 strcat

char* my_strcat(char* dest, const char* sour)
{
	assert(dest && sour);
	char* start = dest;			//记录目标空间的起始地址

	while (*dest)				//找到目标空间的 '\0' 就停止
	{
		dest++;
	}			
	while (*dest++ = *sour++);	//将 sour 指向的串连接过去

	return start;				//返回目标空间的起始地址
}

⒋模拟实现 strcmp

int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);

	while (*str1 == *str2)	//对应字符 ASCII 相等才会往后找不同
	{
		if ('\0' == *str1)	//在对应字符相等的情况下,*st1 = '\0',说明 *str1 和 *str2 都等于 '\0'
		{
			return 0;		//此时两个字符串完全相等
		}

		str1++;
		str2++;
	}

	return *str1 - *str2;	//返回对应字符 ASCII 码的差值
}

代码优化

int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);

	while (*str1++ == *str2++);			//循环结束后 str1 和 str2 分别指向两个不想等字符的后一位

	return *(str1 - 1) - *(str2 - 1);	//重新指向两个不相等的字符然后解引用,用 ASCII 码值做差
}

⒌模拟实现 strncpy

char* my_strncpy(char* dest, const char* sour, size_t num)
{
	assert(dest && sour);

	int i = 0;

	//strncpy 是不会在末尾自动补 \0 的
	for (i = 0; i < num; i++)
	{
		*(dest + i) = *(sour + i);
	}
	
	return dest;
}

⒍模拟实现 strncat

char* my_strncat(char* dest, const char* sour, size_t num)
{
	assert(dest && sour);
	char* start = dest;

	while (*++dest);				//找到串 1 的 '\0' 的位置

	for (int i = 0; i < num; i++)
	{
		if (!(*dest++ = *sour++))	//两个串任何一个遇到 '\0' 都直接结束函数调用
		{
			return start;
		}
	}
	*dest = '\0';					//在末尾补上一个 '\0'

	return start;
}

⒎模拟实现 strncmp

int my_strncmp(const char* str1, const char* str2, size_t num)
{
	assert(str1 && str2);

	while (*str1++ == *str2++ && --num);	//比较到第 num 个字符循环 num - 1 次即可

	return *(str1 - 1) - *(str2 - 1);		//让两个指针重新指向不相等字符的位置
}

⒏模拟实现 strstr

解题思路

在这里插入图片描述
在这里插入图片描述

结束条件

  • s2 -> ‘\0’:当 s2 指向 \0 时,说明 str2 的全部连续的内容已经在 str1 中找到了,str2 是 str1 的子串,返回 p(str1 首次出现 str2 的地址)即可。
  • p -> ‘\0’:当 p 指向 \0 时说明直到走到 str1 的尽头,s2 都没走到 \0,str1 中没有包含 str2 的子串,返回一个空指针即可。

代码实现

const char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);

	const char* s1 = str1;					//记录str1位置
	const char* s2 = str2;					//记录str2位置
	const char*  p = str1;					//记录起始位置

	while (*p)								//*p 指向 \0 时说明主串已经走到头了
	{
		s1 = p;								//字符不相等时让 s1 指向 p 的位置
		s2 = str2;							//字符不相等时让 s2 回到 str2 的初始位置

		while (*s1 && *s2 && *s1 == *s2)	//字符相等且 s1,s2 都未指向 \0 时比较下一对字符
		{
			s1++;
			s2++;
		}

		if ('\0' == *s2)					//s2 走到 \0 时说明 str2 是 str1 的子串
		{
			return p;						//返回在 str1 中首次出现 str2 的地址
		}

		p++;								//不相等时让 s1 从 p 的下一个位置开始比较
	}

	return NULL;							//都走到这步了说明 str2 肯定不是 str1 的子串
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值