库函数->处理字符和字符串的库函数的介绍和实现

一.求字符串长度:

strlen

size_t strlen ( const char * str);//括号当中传入首元素地址

1.从字符串首元素开始,遇到“\0”就停止,每经过一位就+1,即返回的是\0以前字符的个数。
2.返回值是无符号整形size_t,不可能是负数。
3.参数指向的字符串必须是以\0为结束的。
4.strlen函数的模拟实现。

例1:简单计算字符串长度


int main()
{
	size_t len = strlen("abcdef");
	printf("%u\n",len);//打印size_t类型的返回值用%u。
	
	char arr[] = "abcdef";
	printf("%u\n",strlen(arr));
	return 0;
}

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

例2:强化了解返回值是无符号整形

在这里插入图片描述

解析:当不知道返回值是无符号整型的时候,会认为括号的值小于0,打印heheh.无符号整型都是正数,所以打印hahah.
如果整的想要利用strlen计算,打印heheh的目的,那么将返回值类型强制转换为int类型。如下:
在这里插入图片描述

例3:参数指向字符串要以\0为结束
在这里插入图片描述

解析:由于声明的arr当中未表明\0的位置,所以strlen会继续读取接下来的字符,直到找到\0,所以出现在的是一个随机值。

例4:函数的模拟实现

int my_strlen( const char *arr)
{
	int count = 0;
	while (*arr++ != NULL)
	{
		count++;
	}
	return count;
}
int main()
{
	char arr[] = "abcdef";
	int ret=my_strlen(arr);
	printf("%d\n",ret);
	return 0;
}

在这里插入图片描述

二.长度不受限制的字符串函数:

strcpy

注意:在某些编译器中可能会报错,所以要加上:#define _CRT_SECURE_NO_WARNINGS

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

1.返回值是char类型,(目标字符串,需要复制的字符串)。使用时需要引用string.h文件。
2.会以\0作为结束的标志,所以原字符串必须含有\0作为结束的标志。
3.会将原字符串中的\0拷贝到目标空间。
4.目标空间要足够大,才能容纳原字符串。
5.目标空间要可改变。
6.strcpy的模拟实现。
*

例1:函数的简单实用
在这里插入图片描述
例2:会将原字符串中的\0也打印
通过调试当中的监视,我们可以看到\0的拷贝。
在这里插入图片描述
例3:函数的模拟实现:

char* my_strcpy(char* dest,const char* src)//返回一个char*类型的指针,通过指针找到改变的字符串
{
	char* ret = dest;//在后续进行当中指针大小发生改变,但是返回时我们只需要开头的指针
	while(*dest++ = *src++)
	{
		;
	}
	return ret;
}
int main()
{
	char arr1[] = "xxxxxxxxxxxxxx";
	char arr2[] = "abcdef";
	char* ret=my_strcpy(arr1,arr2);
	printf("%s\n",ret);
}

在这里插入图片描述

strcat

说明: 函数用于追加,连接字符串。

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

1.源字符串必须以 ‘\0’ 结束。
2.目标空间必须有足够的大,能容纳下源字符串的内容。
3.目标空间必须可修改

例1:函数练习使用:

int main()
{
	//注意这里要开辟好足够的空间
	char arr1[20] = "abc";
	strcat(arr1,"def");
	printf("%s\n",arr1);
	return 0;
}

在这里插入图片描述

例2:arr1后面没有\0,导致无法停止出错。
在这里插入图片描述

函数的模拟实现:
模拟实现:

#include<assert.h>
char *my_strcat(char *dest, const char*src) 
{ 
 char *ret = dest; 
 assert(dest != NULL); 
 assert(src != NULL); 
 //找到目标字符串的末尾\0的位置,让源字符串开头替换\0
 while(*dest) 
 { 
 dest++; 
 } 
 while((*dest++ = *src++)) 
 { 
 ; 
 } 
 return ret; 
}

strcmp

比较字符串,比较的是字符串的内容,不是长度。一对字符一对字符进行比较。

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

返回类型是int,整形。

比较两个字符串是否相同,逐个字符进行比较,根据字符的ASCII码值进行比较。
标准规定:
1.第一个字符串大于第二个字符串,则返回大于0的数字
2.第一个字符串等于第二个字符串,则返回0
3.第一个字符串小于第二个字符串,则返回小于0的数字
4.遇到\0就停止,不相同判断出大小之后就停止,不管出没出大小结果。

例1:函数的简单应用
在这里插入图片描述

例2:函数的实现(1)

int my_strcmp(const char* arr1, const char* arr2)
{
	while (*arr1 != '\0' && *arr2 != '\0')
	{
		if (*arr1 > *arr2)
		{
			return 1;
		}
		else if (*arr1 < *arr2)
		{
			return -1;
		}
		else
		{
			arr1++;
			arr2++;
		}
	}

	//验证两个字符串是否一样长,前面都相同的情况下,谁长谁大
	if (*arr1 != '\0')
		return 1;
	if (*arr2 != '\0')
		return -2;
	else 
	    return 0;//如果循环结束并且仍未分出大小,并且二者一样长,说明两个字符串相同
}
int main()
{
	char arr1[]="abcdefd";
	char arr2[]= "abcde";
	int ret= my_strcmp(arr1,arr2);
	printf("%d\n",ret);
	return 0;
}

结果如下:
在这里插入图片描述
函数实现(2)

int my_strcmp (const char * src, const char * dst) 
{ 
 int ret = 0 ; 
 assert(src != NULL); 
 assert(dest != NULL); 
 while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst) 
 ++src, ++dst; 
 if ( ret < 0 ) 
 ret = -1 ; 
 else if ( ret > 0 ) 
 ret = 1 ; 
 return( ret ); 
}

函数的实现(3)

int my_strcmp(const char*str1,const char *str2)
{
	while (*str1 == *str2)
	{
		if (*str1 == '\0')
			return 0;
		str1++;
		str2++;
	}
	return *str1 - *str2;
}
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abcq";
	int ret=my_strcmp(arr1,arr2);
	if (ret > 0)
	{
		printf("arr1>arr2");
	}
	else if (ret < 0)
	{
		printf("arr1<arr2");
	}
	else
		printf("arr1=arr2");
	return 0;
}

三 长度受限制的字符串函数介绍:

strncpy

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

1.拷贝num个字符从源字符串到目标空间。
2.如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
3.最后的是需要拷贝的字符个数.相对来说更安全一点,就会考虑到目标函数的大小问题容纳问题。

例1:函数的简单应用
在这里插入图片描述
例2:如果填写的字符串个数超过本身字符串个数,他会自动用\0来进行拷贝替换,如图所示:
在这里插入图片描述

strncat

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

例1:字符串追加限定个数:

int main()
{
	//为了方便观看连接的时候是否会替换原字符串的\0,以及是否会将源头字符串的\0拷贝进去
	char arr1[20] = "abc\0xxxxx";
	char arr2[] = "defg";
	strncat(arr1,arr2,3);
	return 0;
}

在这里插入图片描述

注意:当追加字符串的个数大于字符串本身具有的个数时,只会到本身拥有的字符串个数到\0就停止,如图所示:

在这里插入图片描述

strncmp

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

例1:简单应用:
在这里插入图片描述

四 字符串查找:

strstr

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

1.应用:在一个字符串当中查找是否存在另一个字符串,
2.原理:查找第一个所需要查找的字符串,就会返回这样字符串第一个的地址。
如果找不到字符串就会返回空指针。

例1:应用简介如下

在这里插入图片描述
例2:函数的实现:

#include<assert.h>
char* my_strstr(const char* str1,const char* str2)
{
	assert(str1&&str2);
	char* s1;
	char* s2;
	char* cp=str1;
	//如果所要查找的字符串是一个空指针,直接返回cp地址
	if (*str2 == '\0')
		return cp;
	while (*cp)
	{
		s1 = cp;
		s2 = str2;
		while (*s1 == *s2 && *s1 != '\0' && *s2 != '\0')
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return cp;
		}
		cp++;
	}
	//找不到
	return NULL;
}
int main()
{
	char arr1[] = "i am a good student,hehe student";
	char arr2[] = "student";
	char *ret= my_strstr(arr1,arr2);
	if (ret == NULL)
	{
		printf("找不到");
	}
	else
		printf("%s\n",ret);
	return 0;
}

strtok

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

1.sep参数是个字符串,定义了用作分隔符的字符集合
2.第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
3.strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改
变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
4.strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
5.strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
6.如果字符串中不存在更多的标记,则返回 NULL 指针。

例1:
在这里插入图片描述

五 错误信息报告:

strerror

strerror: 打印出错误信息
同类另一个->perror: 打印内容+错误信息

char * strerror ( int errnum );

1.函数能够返回c语言内置错误码对应的错误信息。
2.函数返回值是错误码对应的错误信息字符串的首元素地址。
3.必须包含的头文件
#include <stdio.h>
#include <string.h>
#include <errno.h>

简单应用:
在这里插入图片描述

六 内存操作函数

memcpy

void * memcpy ( void * destination, const void * source, size_t num );

1.函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。 2.这个函数在遇到 ‘\0’ 的时候并不会停下来。 3.如果source和destination有任何的重叠,复制的结果都是未定义的 模拟函数实现:

void * memcpy ( void * dst, const void * src, size_t count) 
{ 
 void * ret = dst; 
 assert(dst); 
 assert(src); 
 /* 
 * copy from lower addresses to higher addresses 
 */ 
 while (count--) 
 { 
 *(char *)dst = *(char *)src; 
 dst = (char *)dst + 1; 
 src = (char *)src + 1; 
 } 
 return(ret); 
}
int main()
{
	int arr[10] = {1,2,3,4,5,6,7,8,9,10};
	memcpy(arr,arr+2,16);
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]) - 1; i++)
	{
		printf("%d ",arr[i]);
	}
	return 0;
}

在这里插入图片描述

memmove

说明:实现了字符串重复拷贝,拷贝的地方可以有重叠。

void * memmove ( void * destination, const void * source, size_t num );

1.和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
2.如果源空间和目标空间出现重叠,就得使用memmove函数处理。
3.memmove(所要挪动到的地方,从哪里开始,字节大小)

例子:
在这里插入图片描述

函数实现:

为了避免出现分析memcpy中出现可能的重叠部分更替,思路是如果向后面移动拷贝,就从字符串的后面开始想字符串前面拷贝;如果想字符串前面进项拷贝移动,就从字符串前面开始向后面开始一个个拷贝移动。(具体注意事项在代码中有注释)

void* my_memmove(void* dest,const void*src,size_t count)//无符号整形
{
	assert(dest&&src);
	void* ret = dest;
	if (dest >= src)//说明就是向后的进行,要从后往前进行
	{
		while (count--)
		{
			*((char*)dest + count) = *((char*)src + count);
			//加的count就是原来个数-1了,正好是最后的指针
			//强制类型和转换为char*类型,一个字节一个字节移动。
		}
	}
	if (dest < src)//说明向前进行,所以要先拷贝前面的
	{
		while (count--)
		{
			*(char*)dest=*(char*)src;//将元数据当中一个字节的数据给到前面的一个字节
			dest = (char*)dest + 1;//根据数据在内存当中的存储01 00 00 00 02 00 00 00。一个字节一个字节给
			src = (char*)src + 1;
		}
	}
}

int main()
{
	int arr[10] = {1,2,3,4,5,6,7,8,9,10};
	my_memmove(arr,arr+2,16);
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]) - 1; i++)
	{
		printf("%d ",arr[i]);
	}
	return 0;
}

在这里插入图片描述

memset

用于初始化内存空间为单个内容。

说明:memset(目标空间,初始化内容,每一个单位是字节)

int main()
{
	int arr[] = {1,2,3,4,5};
	memset(arr,0,20);//将内存当中的数组数字都初始化为0
	return 0;
}

初始化之前内存存储:
在这里插入图片描述
全部初始化为0:
在这里插入图片描述

memcmp

int memcmp ( const void * ptr1, const void * ptr2,  size_t num );

1.比较的num是字节大小。
2.返回值类型:
如果ptr1>ptr2,返回1.
如果ptr1<ptr2,返回2.
如果ptr1=ptr2,返回0.

例子:
返回0
在这里插入图片描述

完结,撒花!欢迎各位点赞转发互关哈!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值