字符串,字符,内存函数介绍

发布于:2022-12-18 ⋅ 阅读:(466) ⋅ 点赞:(0)

一,strlen

在这里插入图片描述
1,strlen函数是计算字符串长度的函数
2,他的返回值类型是size_t也就是unsigned int 类型

int main()
{
	char arr1[] = "hello";
	char arr2[] = "hello world";

	if (strlen(arr1) - strlen(arr2)>0)
	{
		printf(">\n");
	}
	else
	{
		printf("<\n");
	}
	return 0;
}

我们第一眼看到这个函数的时候大概率以为输出的结果是小于号,实则不然,这就是因为strlen函数的返回值是unsigned int类型,上面两个数相减结果是-6,他的补码是
11111111111111111111111111111010
但这是无符号类型的整数,其实这是一个非常大的数字。
3,模拟实现

size_t my_strlen(const char* str)
{
	char* start = str;
	while (*str)
	{
		str++;
	}
	return str - start;
}

二,strcpy

在这里插入图片描述
1,字符串拷贝函数,将源头字符串的内容拷贝到目标字符串中
2,目标字符串要有足够大的空间
3,字符串在拷贝的过程中,‘\0’,也进行了拷贝
在这里插入图片描述
在这里插入图片描述

4,源头字符串中必须有’\0’
在这里插入图片描述
在这里插入图片描述
可以看到拷贝发生了错误。

5,目标空间可以被修改
6,模拟实现

char* my_strcpy(char* dest, const char* src)
{
	char* ret = dest;
	assert(dest && src);
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}

三,strcat

在这里插入图片描述

int main()
{
	char arr1[20] = "hello ";
	char arr2[] = "world";
	strcat(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

在这里插入图片描述

1,这是一个字符串链接函数
2,目标空间足够大
3,目标空间可以被修改
4,目标字符串中与源头字符串中都含有’\0’
(1)若源头字符串中不含有’\0’,会与strcpy函数源头字符串不含结束标志结果一致
(2)函数的连接点是目标字符串中’\0’的位置
在这里插入图片描述
在这里插入图片描述
5,与strcpy函数相同结束标志’\0’也进行了拷贝
6,能否实现自己给自己连接呢?答案是否定的(你可以想一下这是为什么?)
7,模拟实现

char* my_strcat(char* dest, const char* src)
{
	assert(dest && src);
	char* ret = dest;
	while (*dest)
	{
		dest++;
	}
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}

四,strcmp

在这里插入图片描述
1,字符串比较函数,一个字节一个字节的比较字符串的ascall码,若str1大于str2则返回大于0 的值,相反返回小于0的值,否则返回0.

int main()
{
	char arr1[] = "abce";
	char arr2[] = "abcd";
	int ret = strcmp(arr1, arr2);
	printf("%d\n", ret);
	return 0;
}

在这里插入图片描述
2,两个字符串中必须含有’\0’,
在这里插入图片描述
如图,两个字符串明明相等,却返回-1.并且还造成了越界访问。
3,模拟实现

int my_strcmp(const char* arr1, const char* arr2)
{
	assert(arr1 && arr2);
	while (*arr1 == *arr2)
	{
		if (*arr1 == '\0')
			return 0;
		arr1++;
		arr2++;
	}
	return *arr1 - *arr2;
}

五,strncpy

在这里插入图片描述

int main()
{
	char arr1[20] = "hello world";
	char arr2[] = "xxxxxx";
	strncpy(arr1, arr2, 5);
	printf("%5s\n", arr1);
	return 0;
}

在这里插入图片描述

1,有长度限制的字符串拷贝函数
2,目标空间足够大

3,模拟实现

char* my_strcpy(char* arr1, const char* arr2, size_t num)
{
	assert(arr1 && arr2);
	char* ret = arr1;
	while (num&&*arr2)
	{
		*arr1 = *arr2;
		arr1++;
		arr2++;
		num--;
	}
	while (num--)
	{
		*arr1 = '\0';
		arr1++;
	}
	return ret;
}

六,strncat

在这里插入图片描述
这个函数就可以实现自己给自己追加了

int main()
{
	char arr1[30] = "hello world ";
	strncat(arr1, arr1,11);
	printf("%s\n", arr1);
	return 0;
}

在这里插入图片描述

1,有长度限制的字符串追加函数
2,目标空间足够大
3,在追加num个字符之后,还会追加上一个’\0’
在这里插入图片描述
在这里插入图片描述
4,模拟实现

char* my_strncat(char* dest, const char* src, size_t num)
{
	assert(dest && src);
	char* ret =dest;
	while (*dest)
	{
		dest++;
	}
	while (num-- && *src != '\0')
	{
		*dest = *src;
		dest++;
		src++;
	}
	if (*src == '\0')
	{
		*dest = *src;
		return ret;
	}
	else
	{
		*dest = '\0';
	}
	return ret;
}

七,strncmp

在这里插入图片描述

1,有长度限制的字符串比较函数
2,相比较几个,就比较几个
在这里插入图片描述

八,strstr

在这里插入图片描述
1,字符串查找函数
2,在主串中查找子串,返回字串在主串中的地址,若在主串中找到多次字串那么返回第一次找到的地址。
在这里插入图片描述
3,模拟实现

char* my_strstr(const char* arr1, const char* arr2)
{
	assert(arr1 && arr2);
	char* p = arr1;
	char* s1 = p;
	char* s2 = arr2;
	while (*p)
	{
		s1 = p;
		while (*s2&&*s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
			return p;
		p++;
	}
	return NULL;

}

但这是一种暴力求解方法,如果追求更高的效率,可以看后期的KMP算法。

九,strtok

在这里插入图片描述
1,sep参数是个字符串,定义了用作分隔符的字符集合
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记
2,函数会将分隔符位置改成’\0’(真的会把字符串改变,所以通常先拷贝一下源字符串)
3,此函数具有记忆功能,如果一个字符串需要分隔多次,只需第一次传入字符串地址
后面传空指针为参数即可。
4,函数返回值为指向分割后的字符串的指针。
在这里插入图片描述
在这里插入图片描述

十,strerror

在这里插入图片描述
这是一个将错误码,转化成错误信息的函数。
在这里插入图片描述

十一,perror

perror=strerror+printf
在这里插入图片描述

十二,字符函数

在这里插入图片描述
这里有很多函数,我们介绍几个
例如,将小写字母全部转化成大写字母的代码。

int main()
{
	char arr[] = "Hello world";
	char* pc = arr;
	while (*pc)
	{
		if (islower(*pc))
		{
			*pc = toupper(*pc);
		}
		pc++;
	}
	printf("%s\n", arr);
	return 0;
}

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

十三,memcpy

在这里插入图片描述
1,这个函数会将 num个字节的内容 从source中拷贝到 destination中。
在这里插入图片描述
2,模拟实现

void* my_memcpy(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	void* ret = dest;
	while (num--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}

十四,memmove

在这里插入图片描述
1,与memcpy大致相同,和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
在这里插入图片描述
2,模拟实现

void* my_memmove(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	void* ret = dest;
	if (dest < src)
	{
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		while (num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	return ret;
}

十五,memcmp

在这里插入图片描述
1,比较从ptr1呵ptr2开始的num个字节的内容
2,返回值与上述的strcmp相同
在这里插入图片描述
3,模拟实现

int my_memcmp(const void* ptr1, const void* ptr2, size_t num)
{
	assert(ptr1 && ptr2);
	while (num--)
	{
		if (*(char*)ptr1 == *(char*)ptr2)
		{
			ptr1 = (char*)ptr1 + 1;
			ptr2 = (char*)ptr2 + 1;
		}
		else
		{
			return *(char*)ptr1 - *(char*)ptr2;
		}
	}
}
本文含有隐藏内容,请 开通VIP 后查看