字符串操作函数&内存操作函数

strlen

size_t strlen ( const char * str );

字符串是以‘\0’作为结束标志,strlen函数范围的是‘\0’之前的字符个数
参数指向的字符串必须要以‘\0’结尾
strlen函数返回值为size_t(无符号的)

strlen函数的模拟实现

计数器:

size_t SimulationStrlen(const char* pa)
{
	int count = 0;
	assert(pa != NULL);
	while (*pa != '\0')
	{
		count++;
		pa++;
	}
	return count;
}

递归:

size_t SimulationStrlen(const char* pa)
{
	assert(pa != NULL);
	if (*pa == '\0')
	{
		return 0;
	}
	return SimulationStrlen(pa + 1) + 1;
}

指针-指针:

size_t SimulationStrlen(const char* pa)
{
	assert(pa != NULL);
	char* pb = pa;
	while (*pb != '\0')
	{
		pb++;
	}
	return pb - pa;
}

strcpy

参数:指向要复制内容的目标数组的指针、源字符串
返回:destination空间的起始地址

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

源字符串必须以‘\0’结束
strcpy会把源字符串中的‘\0’拷贝过去
目标空间必须足够大(足以放下源字符串)
目标空间必须可变
strcpy的返回值类型的设置是为了实现链式访问

printf("%s", SimulationStrcpy(destination,source));

strcpy函数的模拟实现

#include<stdio.h>
#include<string.h>
#include<assert.h>
char *SimulationStrcpy(char* dst, const char* src)
{
	assert(dst != NULL);
	assert(src != NULL);
	//assert(dst && src)
	char* cp = dst;
	while (*cp++ = *src++);
	return dst;
}

strcat

将源字符串的副本追加到目标字符串。目标中终止的空字符将被源的第一个字符覆盖,并且在目标中由两者串联形成的新字符串的末尾包含一个空字符。

返回:destination空间的起始地址

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

源字符串必须以‘\0’结尾
目标空间必须足够大
目标空间必须可修改

strcat函数的模拟实现

char* SimulationStrcat(char* dst, const char* src)
{
	assert(dst && src);
	char* cp = dst;
	while (*cp)
	{
		cp++;
	}
	while (*cp++ = *src++);
	return dst;
}

strcmp

将 C 字符串 str1 与 C 字符串 str2 进行比较。(比较字符的ASCII码值)

返回值表明
<0第一个不匹配的字符在 ptr1 中的值低于 ptr2 中的值
0两个字符串内容相等
>0第一个不匹配的字符在 ptr1 中的值大于 ptr2 中的值
int strcmp ( const char * str1, const char * str2 );

strcmp函数的模拟实现

int SimulationStrcmp(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;
	}
}

长度不受限与长度受限的字符串函数

长度不受限的字符串函数= { s t r c m p s t r c p y s t r c a t \left\{\begin{matrix} strcmp & & \\ strcpy & & \\ strcat & & \end{matrix}\right. strcmpstrcpystrcat
长度受限的字符串函数= { s t r n c m p s t r n c p y s t r n c a t \left\{\begin{matrix} strncmp & & \\ strncpy & & \\ strncat & & \end{matrix}\right. strncmpstrncpystrncat

strncpy

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

拷贝nun个字符从源字符串到目标空间
如果源字符串的长度小于num,则拷贝完后,追加0(直到目标空间中字符长度等于num)

strncpy函数的模拟实现

#include<assert.h>
char* SimulationStrncpy(char* destination, const char* source, size_t num)
{
	assert(destination && source);
	char* ret = destination;
	while (num)
	{
		*destination = *source;
		destination++;
		source++;
		num--;
	}
	return ret;
}

strncmp

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

比较到出现字符不一样或者一个字符串结束或者num个字符比较完

strncmp的模拟实现

#include<assert.h>
int SimulationStrcmp(const char* pa, const char* pb, size_t num)
{
	assert(pa && pb);
	for (int i = 0; i < num; i++)
	{
		if (*pa == *pb)
		{
			pa++;
			pb++;
			continue;
		}
		else
		{
			return *pa - *pb;
		}
	}
}

strncat

char* SimulationStrncat(char* destination, const char* source, int num)
{
	assert(destination && source);
	char *ret = destination;
	while (*ret)
	{
		ret++;
	}
	while (num)
	{
		*ret = *source;
		num--;
		ret++;
		source++;
	}
	return destination;
}

strstr

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

判断str2是否为str1的子串
如果是,返回指向 str1 中第一次出现的 str2 的指针;如果 str2 不是 str1 的一部分,则返回空指针。

strstr函数的模拟实现

char* SimulationStrstr(const char* p1, const char* p2)
{
	assert(p1 && p2);//断言这俩指针不是空指针
	const char* s1 = p1;
	const char* s2 = p2;
	const char* cur = p1;
	while (*cur)
	{
		s1 = cur;
		s2 = p2;
		while ((*s1 != 0) && (*s2 != 0) && (*s1 == *s2))
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return (char*)cur;
		}
		if (*s1 == '\0')
		{
			return NULL;
		}
		cur++;
	}
	return NULL;
}

strtok

使用需引用头文件<string.h>

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

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

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "you@are#so$graceful%elegant^and&charming*tonight";
	const char *sep = "@#$%^&*";
	char buf[100] = { 0 };
	strcpy(buf, arr);
	char* str = NULL;
	for (str = strtok(buf, sep); str != NULL; str = strtok(NULL, sep))
	{
		printf("%s ", str);
	}
	return 0;
}

strerror

char * strerror ( int errnum );

返回错误码所对应的错误信息

#include<stdio.h>
#include<string.h>
#include<limits.h>
#include<errno.h>
#include<stdlib.h>//使用perror所需引用
int main()
{
	printf("%s\n", strerror(0));
	printf("%s\n", strerror(1));
	printf("%s\n", strerror(2));
	printf("%s\n", strerror(3));
	printf("\n");
	int* p = (int*)malloc(INT_MAX);//向堆区申请内存,申请成功返回元素地址;不成功返回空指针
	if (p == NULL)//申请不成功
	{
		printf("%s\n", strerror(errno));//全局变量error:错误码
		perror("malloc");
		return 1;
	}
	return 0;
}

在这里插入图片描述

字符分类函数

表格如果参数符合下列条件就返回真
iscntrl任何控制字符
isspace空白字符:“空格”、“换页\f”、换行“\n”、回车“\r”、制表符“\t”、垂直制表符“\v”
isdigit十进制0~9
isxdighit十六进制数字,包括所有十进制数字,小写字母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任何可打印字符,包括图形字符和空白字符
字符转换:tolower(int c)、toupper(int c)

memcpy

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

memcoy函数从source的位置开始向后复制num个字节的数据到destination的内存位置
遇到‘\0’并不会停下来
如果source和destination有任何的重叠,复制的结果都是未定义的

memcpy函数的模拟实现

void* SimulationMemcpy(void* destination, const void* source, size_t num)
{
	assert(destination && source);
	void* ret = destination;
	while (num--)
	{
		*(char*)destination = *(char*)source;
		destination = (char*)destination + 1;
		source = (char*)source + 1;
	}
	return ret;
}
int main()
{
	int arr1[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int arr2[5] = { 0 };
	SimulationMemcpy(arr2, arr1, 20);
	for (int i = 0; i < 5; i++)
	{
		printf("%d", arr2[i]);
	}
	return 0;
}

memmove

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

memmove函数处理的源内存块和目标内存块是可以重叠的

如果destination在source之前,则从前向后拷
如果destination在source + num之前、在source之后,则从后向前拷
如果没有重叠,从后向前拷还是从前向后拷就无所谓啦
在这里插入图片描述

memmove函数的模拟实现

void* SimulationMemmove(void* destination, void* source, size_t num)
{
	void* ret = destination;
	if (destination > source && destination < (char*)source + num)
	{
		while (num--)
		{
			*(char*)destination = *(char*)source;
			destination = (char*)destination + 1;
			source = (char*)source + 1;
		}
	}
	else
	{
		while (num--)
		{
			*((char*)destination + num) = *((char*)source + num);
		}
	}
	return ret;
}

memcmp

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

比较从prt1、prt2指针开始的num个字节

memset–内存设置

memset是以字节为单位来初始化单元的

void *memset(void *dest, int c, size_t count);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值