C语言-字符串操作函数和内存操作函数介绍及模拟实现

strlen

strlen介绍

size_t strlen ( const char * str );

strlen函数返回的是在字符串中'\0'前面出现的字符个数,不包括'\0'
参数所指向的字符串必须以'\0'结束

strlen的模拟实现

size_t my_strlen(const char* string)
{
	assert(string);
	size_t count = 0;
	while (*string)
	{
		count++;
		string++;
	}
	return count;
}
int main()
{
	char arr1[] = "qwertyu";
	printf("%d\n", my_strlen(arr1));
	return 0;
}

在这里插入图片描述

strcpy

strcpy介绍

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

源字符串必须以'\0'结束。会改变从目的字符串的第一个地址里的内容,直至copy完源字符串的内容,会将源字符串的'\0'拷贝到目标空间。目标空间必须足够大,以确保能存放源字符串。

strcpy的模拟实现

char* my_strcpy(char* destination,const char* source)
{
	char* ret = destination;
	assert(destination&&source);
	//while (*source)
	//{
	//	*destination = *source;
	//	destination++;
	//	source++;
	//}
	//*destination = '\0';
	while (*destination++ = *source++)
	{
		;
	}
	return ret;
 
 
}
int main()
{
	char arr1[20] = "hello ";
	char arr2[] = "world"; 
	my_strcpy(arr1,arr2);
	//strcpy(arr1,arr2);
	return 0;
}

在这里插入图片描述

strncpy

strncpy介绍

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

拷贝num个字符从源字符串到目标空间。
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后面追加0,直至num个。
值得注意的是,strncpy在copy结束的时候仍然是以目标字符串的'\0'作为字符串的结束标志。

strncpy的模拟实现

char* my_strncpy(char* destination,const char* resource ,size_t n)
{
	assert(destination&&resource);
	char* start = destination;
	while (n--)
	{
		*destination = *resource;
		destination++;
		resource++;
	}
	return start;

}
int main()
{
	char arr1[] = "xxxxxxxxxxxxx";
	my_strncpy(arr1,"abcde",10);
	printf("%s\n",arr1);
	return 0;
}

在这里插入图片描述

strcat

strcat介绍

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

在目的字符串的'\0'处,开始追加源字符串的内容,源字符串的首字符会占据掉目的字符串的'\0'所在的空间。同时也会将源字符串中的'\0'追加过去。

strcat的模拟实现

char* my_strcat(char* destination,const char* source)
{
	assert(destination&&source);
	char* ret = destination;
	while (*destination)
	{
		destination++;
	}
	//while (*source)
	//{
	//	*destination = *source;
	//	destination++;
	//	source++;
	//}
	while (*destination++ = *source++)
	{
		;
	}
	return ret;
}
int main()
{
	char arr1[30] = "hello ";
	char arr2[] = "world";
	my_strcat(arr1, arr2);
	return 0;
}

在这里插入图片描述

strncat

strncat介绍

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

可指定追加的字符数量。它的首字符会占据目标字符串'\0' 的位置,同时它会在追加的末尾加上一个'\0',使得目标空间最后还是一个字符串。

strncat的模拟实现

char* my_strncat(char* string1,const char* string2,size_t n)
{
	assert(string1&&string2);
	char* start = string1;
	//在目的地址的后面追加指定个数的字符后,再追加一个\0
	while (*string1)
	{
		string1++;
	}
	while (n--)
	{
		*string1 = *string2;
		string1++;
		string2++;
	}

	*string1 = '\0';
	return string1;
}
int main()
{
	char arr1[20] = "xxxxx";
	my_strncat(arr1,"abcd",3);
	printf("%s\n",arr1);
	return 0;
}

在这里插入图片描述

strcmp

strcmp介绍

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

比较两个字符串,实际为比较两个字符串中对应位置字符的ASSII码值的大小。
若第一个字符串大于第二个字符串,则返回大于0的数字
若第一个字符串小于第二个字符串,则返回小于0的数字
若第一个字符串等于第二个字符串,则返回0

strcmp的模拟实现

int my_strcmp(const char* string1,const char* string2)
{
	assert(string1&&string2);
	//while (*string1&&*string2)
	//{
	//	if (*string1 > *string2)
	//	{
	//		return 1;
	//	}
	//	else if (*string1 < *string2)
	//	{
	//		return -1;
	//	}
	//	else
	//	{
	//		string1++;
	//		string2++;
	//	}
	//}
	//只有两个字符串完全相等时,才会return 0
	while (*string1==*string2)
	{
		if (*string1=='\0')
		{
			return 0;
		}
		else
		{
			string1++;
			string2++;
		}
	}
	if (*string1>*string2)
	{
		return 1;
	}
	else
	{
		return -1;
	}
	
 
 
}
int main()
{
	char arr1[] = "a";
	char arr2[] = "abc";
	//printf("%d\n", strcmp(arr1, arr2)); 
	printf("%d\n", my_strcmp(arr1, arr2));
	return 0;
}

在这里插入图片描述

strncmp

strncmp介绍

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

比较到出现两个字符不一样或者num个字符全部比较完

strncmp的模拟实现

int my_strncmp(const char* string1, const char* string2, size_t n)
{
	assert(string1 && string2);
	//指定次数n
	while (n--)
	{
		if (*string1 == *string2)
		{
			string1++;
			string2++;
		}
		else if (*string1 > *string2)
		{
			return 1;
		}
		else
		{
			return -1;
		}
	}
	return 0;
}
int main()
{
	char arr1[] = "abczefg";
	char arr2[] = "abckghjk";
	printf("%d\n", my_strncmp(arr1, arr2, 2));
	return 0;
}

在这里插入图片描述

strstr

strstr介绍

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

在str1字符串中查找str2字符串,若有,则返回str2字符串在str1中的地址(是指首字符的地址);若无,则返回空指针

strstr的模拟实现

char* my_strstr(char* string1,char* string2)
{
	assert(string1&&string2);
 
	//首先排除一个特殊的情况
	if (*string2=='\0')
	{
		return string1;
	}
	//考虑一次循环过程,需要两个临时指针s1,s2来随时控制在两个字符串中的位置
	//一个指针cp,来记录在循环过程中指向s1中某个字符的位置
	char* s1 = NULL;
	char* s2 = NULL;
	char* cp = string1;
	while (*cp)
	{
		s1 = cp;
		s2 = string2;
		while (*s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return cp;
		}
		cp++;
	}
	return NULL;
	
}
int main()
{
	char arr1[] = "abcdefgh";
	printf("%s\n", my_strstr(arr1, "fg"));
	return 0;
}

在这里插入图片描述

memcpy

memcpy介绍

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

它从source的位置开始向后复制num个字节的数据到destination的内存位置。
在遇到'\0'的时候不会停下来
如果source和destination有任何的重叠,复制的结果都是未定义的,并不会得到预期想要的效果。

memcpy的模拟实现

void* my_memcpy(void* destination,const void* source,size_t num)
{
	assert(destination&&source);
	void* ret = destination;
	while (num--)
	{
		*(char*)destination = *(char*)source;
		((char*)destination)++;
		((char*)source)++;
	}
	return ret;
}
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[] = {11,22,33,44,55};
	my_memcpy(arr1,arr2,9);
	return 0;
}

在这里插入图片描述

memmove

memmove介绍

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

与strcpy相比,memmove不仅可以对字符串进行操作,还可以对整型,结构体等进行操作;它们的最大差别在于memmove还可以处理源内存块和目标内存块相重合的情况。比如:在同一个数组的内部进行操作。

memmove的模拟实现

void* my_memmove(void* destination,const void* source,size_t num)
{
	assert(destination && source);
	void* ret = destination;
	//向前move和向后move
	if (destination<source)
	{
		//向前move
		while (num--)
		{
			*(char*)destination = *(char*)source;
			((char*)destination)++;
			((char*)source)++;
		}
	}
	else
	{
		//向后move
		while (num--)
		{
			*((char*)destination + num) = *((char*)source + num);
		}
		
	}
	return ret;
}
int main()
{
	int arr1[] = {1,2,3,4,5,6,7,8,9,10};
	my_memmove(arr1+2,arr1,20);
	return 0;
}

在这里插入图片描述

memcmp

memcmp介绍

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

比较从ptr1和ptr2指针开始的num个字节,返回的规则同strcmp

memcmp的模拟实现

int my_memcmp(const void* ptr1,const void* ptr2,size_t num)
{
	assert(ptr1&&ptr2);
	while (num--)
	{
		if ((*(char*)ptr1)> (*(char*)ptr2))
		{
			return 1;
		}
		else if ((*(char*)ptr1) < (*(char*)ptr2))
		{
			return -1;
		}
		else
		{
			((char*)ptr1)++;
			((char*)ptr2)++;
		}
	}
	return 0;
}
int main()
{
	int arr1[] = {1,2,3};
	int arr2[] = {1,2,2};
	printf("%d\n", my_memcmp(arr1, arr2, 8));
}

在这里插入图片描述

其它函数

strtok

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

delimiters参数是一个字符串,定义了用作分隔符的字符集合
str参数指定一个字符串,它包含0个或者多个由delimiters字符串中的一个或者多个分隔符分割的标记。
strtok函数在str中从左至右找到delimiters中的一个符号标记,并将其替换为'\0',返回一个指向以这个'\0'结尾的字符串(strtok将会改变被操作的字符串,所以使用strtok函数切分的字符串一般都是临时拷贝的内容)
strtok函数的第一个参数不为NULL,函数将找到str中出现的第一个标记,并保存它在字符串中的位置
strtok函数的第一个参数为NULL,函数将在上一次字符串中被保存的位置开始,查找下一个标记
如果字符串中不存在更多的标记,将会返回NULL

int main()
{
	char arr[] = "abc@qq.com";
	//char arr[] = "192.168.120.87";
	char sep[] = "@.";
	//记录好位置之后找标记
	char* ret=strtok(arr,sep);
	printf("%s\n",ret);
	ret = strtok(NULL, sep);
	printf("%s\n", ret);
	ret = strtok(NULL, sep);
	printf("%s\n", ret);

	//char* ret = NULL;
	//for (ret=strtok(arr,sep);ret!='\0';ret=strtok(NULL,sep))
	//{
	//	printf("%s\n",ret);
	//}


	return 0;
}

如下,以"@."为分隔符,将字符串拆分为3个部分。
在这里插入图片描述
如下,是一种更为标准的输出格式。

int main()
{
	//char arr[] = "abc@qq.com";
	char arr[] = "192.168.120.87";
	char sep[] = ".";
	//记录好位置之后找标记
	//char* ret=strtok(arr,sep);
	//printf("%s\n",ret);
	//ret = strtok(NULL, sep);
	//printf("%s\n", ret);
	//ret = strtok(NULL, sep);
	//printf("%s\n", ret);

	char* ret = NULL;
	for (ret=strtok(arr,sep);ret!='\0';ret=strtok(NULL,sep))
	{
		printf("%s\n",ret);
	}
	return 0;
}

在这里插入图片描述

strerror

char * strerror ( int errnum )

返回错误码所对应的错误信息
与之相对应的perror会打印出错误信息,并可以自己定义输出格式

举例说明

int main()
{
	printf("%s\n", strerror(0));
	printf("%s\n", strerror(1));
	printf("%s\n", strerror(2));
	printf("%s\n", strerror(3));
	printf("%s\n", strerror(5));
	printf("%s\n",strerror(6));
	return 0;
}

在这里插入图片描述
正确的使用方式

#include <errno.h>
int main()
{
	FILE* ret=fopen("test.txt","r");
	if (ret=='\0')
	{
		//如果有错误,会将错误码存到errno中
		printf("%s\n",strerror(errno));
		//perror("错误信息是:");
	}
	fclose(ret);
	return 0;
}

在这里插入图片描述
perror 的使用:
在这里插入图片描述

字符分类函数和字符转换函数islower,isupper,tolower,toupper

两个例子

int main()
{
	int ret=islower('A');
	printf("%d\n", ret);
	 ret = isupper('A');
	printf("%d\n", ret);
	 ret = tolower('F');
	printf("%c\n", ret);
	 ret = toupper('a');
	printf("%c\n", ret);
	return 0;
}

在这里插入图片描述

int main()
{
	char arr[] = "I Have An Apple";
	//如果是大写就转换为小写,然后输出;否则直接输出
	int i = 0;
	while (arr[i])
	{
		if (isupper(arr[i]))
		{
			//printf("%c",tolower(arr[i]));
			arr[i] = tolower(arr[i]);
		}
		printf("%c",arr[i]);
		i++;
	}
	
	return 0;
}

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值