字符函数和字符串函数

字符函数

1.字符分类函数

需要包含头文件ctype.h**ctype.h**

在这里插入图片描述

不使用字符函数写的程序

在这里插入图片描述
利用字符函数写的程序

2.字符转换函数

int tolower ( int c ); //将参数传进去的⼤写字⺟转⼩写  
int toupper ( int c ); //将参数传进去的⼩写字⺟转⼤写 

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

字符串函数

1.strlen的使用和模拟实现

字符串以 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前⾯出现的字符个数(不包含 ‘\0’ )
• 参数指向的字符串必须要以 ‘\0’ 结束。
• 注意函数的返回值为size_t,是⽆符号的( 易错 )
• strlen的使⽤需要包含头⽂件
• 学会strlen函数的模拟实现**

在这里插入图片描述
返回类型是无符号的
在这里插入图片描述
运行结果错误,应该是<=

在这里插入图片描述
强制类型转换就OK了

模拟实现——计数器、递归

1.计数器
在这里插入图片描述

2.递归
在这里插入图片描述

在这里插入图片描述
如果不等于\0,说明字符串长度至少为1

所以这样递归

在每一次递归调用中,都会检查当前字符是否是结束符,如果不是,则继续递归调用直到找到结束符

通过递归调用,函数可以顺序地遍历字符串中的每个字符,直到找到结束符为止,从而计算出字符串的长度

2.strcpy的使用和模拟实现——字符串拷贝

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

在这里插入图片描述

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "hello word";
	//字符串拷贝到arr2
	char arr2[20] = { 0 };
	strcpy(arr2,arr1);
	printf("%s", arr2);
	return 0;
}

在这里插入图片描述
在这里插入图片描述
这个警告代码要放到第一行才行

验证\0是否被拷贝过去
在这里插入图片描述

%s遇到\0不会继续打印,遇到\0就停下,所以后面的几个x没有打印

更严谨一点的版本

#include<string.h>
#include<stdio.h>
void my_strcpy(char* dest, const char* src)
{
	assert(src != NULL);
	assert(dest!= NULL);

	//拷贝\0前面的内容
	while (*src!='\0') {
		*dest = *src;
		dest++;
		src++;
	}
	*dest = *src;//拷贝\0
}
int main()
{
	char arr1[] = "hello word";
		char arr2[20] = {"xxxxxxxxxxxx"};
		my_strcpy(arr2,arr1);
		printf("%s", arr2);
	
	return 0;
}

更好的写法

#include<string.h>
#include<assert.h>
#include<stdio.h>
char* my_strcpy(char* dest, const char* src)
{
	assert(src != NULL);
	assert(dest!= NULL);
	char*ret=dest;//把dest的值存起来
	//拷贝\0前面的内容
	while (*dest++ = *src++)//拷贝给dest,字符h,一直到\0, 既拷贝了又判断了,到\0的ASCII是0,就停止循环
	{
		;
	}
	return ret;
}
int main()
{
	char arr1[] = "hello word";
		char arr2[20] = {"xxxxxxxxxxxx"};
		my_strcpy(arr2,arr1);
		printf("%s", arr2);
	
	return 0;
}

3.strcat的使用和模拟实现——用来连接字符串

char*strcat (char*dest,const char*src)

在这里插入图片描述

要保证目标空间足够大,也就是上面arr1的空间足够大,连接过去有空间

如何模拟实现——my_strcat

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<assert.h>
//返回的是目标空间的起始地址
char* my_strcat(char*dest,const char*src)
{
	//assert(dest!=NULL);
	//assert(src!=NULL);//空指针为0
	assert(dest && src);
	char* ret=dest;//后面dest一直在自增,存放一下原来的dest
	//1.找到目标空间的\0 遍历数组1,找到杠零
	while (*dest != '\0')
	{
		dest++;
	}//2.找到后拷贝
	while (*dest++ = *src++)//拷贝进去,一直向后
	{
		;//需要有语句,但什么都不用干,空语句
	}
	return  ret;

}
int main()
{
	char arr1[20] = "hello ";//我想让他打印出hello world
	//连接字符串
	char arr2[] = "world";
	char*s=my_strcat(arr1, arr2);//2连接到1,打印1
	printf("%s\n", arr1);
	printf("%s\n", s);
	return 0;
}

运行结果:
在这里插入图片描述

在这里插入图片描述

能自己连接自己吗?——不可以\0会被掩盖导致死循环

my_strcat(arr1,arr1);//写法错误,会死循环

4.strcmp的使用和模拟实现———比较两个字符串的内容

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

在这里插入图片描述
两个字符内容相等,返回0
大于,返回>0;小于,返回<0

在这里插入图片描述
模拟实现代码

#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 arr1[] = "abq";
	char arr2[] = "abcdef";
	int ret =my_strcmp(arr1, arr2);
	printf("%d\n", ret);
	return 0;
}

在这里插入图片描述
介绍完前三个,现在来介绍后三个

1.strncpy的使用和模拟实现

char*strncpy (char*dest,const char*src,size_t num)

strncpy比strcpy多了一个参数num

num表示拷贝几个——限制长度

num——src里最多要拷贝几个

在这里插入图片描述

1拷贝到2里面3个字符

在这里插入图片描述

在这里插入图片描述

arr1只有6个字符,我下面要求给我拷贝过去8个,非常重视num,不够后面2个就用\0代替

2.strncat——追加num个字符

char*strncat(char*dest,const char*src,size_t num)

一样也是多了一个num

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
strncat追加过后会添加\0,保证追加完之后还是个字符串
这点就和strncpy不同,strncpy在num足够的情况下不会追加\0的,num太大了,拷贝的个数不够才会追加\0

在这里插入图片描述
如果num太大,字符个数不够用,strncat会追加\0来代替吗?——不会

strncat不够重视num不会补\0

我们这里就是做些简单的比较,对于num的取值没有那么随意

比如

int main()
{
	char arr1[] = "abcdef";
	char arr2[20] ="xx\0";
	int len = strlen(arr1);
	strncat(arr2, arr1,len );
	printf("%s", arr2);
	return 0;
}

我们对于num的取值,一般是这样计算的(要拷贝的字符的长度)

3.strncmp——最多比较num个字符

也是多了一个参数

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

最多比较num个,比如前三个就能比较出来,就不会向后比较了

模拟实现

//模拟实现
#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 arr1[] = "abq";
	char arr2[] = "abcdef";
	int ret =my_strcmp(arr1, arr2);
	printf("%d\n", ret);
	return 0;
}

在使用VS2022是有时会提醒XXX不够安全,需要在第一行加上#define _CRT_SUCURE_NO_WARNINGS,一定是在第一行加上

4.strstr——在一个字符串中查找另一个字符串

char*strstr (const char*str1,const char*str2)//返回的是字符串2在字符串1第一次出现的位置

在str1中找str2

如果str2压根没出现,就返回空指针

几种输出结果:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
模拟实现
在这里插入图片描述

5.strtok函数

strtok

在这里插入图片描述
重点是分隔符,把分隔符所分割的字符串,提取出来

写一个字符串:zpengwei@qq.com

sep:分隔符的字节集合——“@ .”,这俩就是分隔符

在这里插入图片描述
strtok就是找到分隔符后,把分隔符改为\0,并返回z(开头)的地址,所以他会改变被操作的字符串

在这里插入图片描述
根据这个函数的参数描述

我们可以得到

所给的字符串里,有几个分隔符,就会变成几个空指针

每找到一个分隔符就设为空,然后返回最开始的地址

下一次再用strtok函数,找到空指针,接着向后分割字符串

在这里插入图片描述
在这里插入图片描述
这个函数使用的条件还是挺苛刻的

字符串里有几个分隔符,就要用几次strtok函数

上面的这种写法太繁杂,因为你不知道这个字符串会有几个分隔符,总不能一个一个数吧

优化写法——比较巧妙

在这里插入图片描述
用的比较少,条件比较苛刻

strerror函数

在这里插入图片描述

当需要把错误码翻译成错误信息时可以用这个函数

错误码存放在errno.h的头文件里

在这里插入图片描述
在这里插入图片描述
直接拖到VS里打开就好

在这里插入图片描述
字符串函数别忘了包含头文件

在这里插入图片描述
因为我们这个项目里根本没有这个文件,所以一定会失败

失败原因(错误码):没有这个文件或文件夹

哪里有错误,他就会有错误码,打印出来就知道大概是什么错误了

perror函数

在这里插入图片描述
perror相当于封装了strerror函数,用起来更方便

随便给perror一个字符串

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值