C进阶——字符串与内存函数

目录

一. 字符串操作函数

求字符串长度 ——strlen

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

字符串拷贝函数——strcpy

字符串连接函数——strcat

字符串比较函数——strcmp

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

 字符串连接函数——strncpy

 字符串拷贝函数——strncat

字符串比较函数——strncmp

字符串查找函数——strstr

二. 内存操作函数

内存拷贝函数

拷贝未重叠内存——memcpy

拷贝重叠内存——memmove

内存比较函数——memcmp

内存设置函数——memset

三. 函数的模拟实现

字符串操作函数的模拟实现

模拟实现strlen

模拟实现strcpy

模拟实现strcat

模拟实现strcmp

模拟实现strstr

内存操作函数的模拟实现

模拟实现memcpy

模拟实现memmove


一. 字符串操作函数

求字符串长度 ——strlen

size_t strlen ( const char * str );

函数功能:

求字符串的长度 

  • 字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。
  • 参数指向的字符串必须要以 '\0' 结束。
  • 注意函数的返回值为size_t,是无符号的( 易错 )

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

字符串拷贝函数——strcpy

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

函数功能: 

 将源字符串拷贝到目标字符串,返回目标字符串首元素的地址。

  • 源字符串必须以 '\0' 结束。
  • 会将源字符串中的 '\0' 拷贝到目标空间。
  • 目标空间必须足够大,以确保能存放源字符串。
  • 目标空间必须可变

字符串连接函数——strcat

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

函数功能: 

将源字符串追加到目标字符串的后面,返回目标字符串首字符的地址 

  • 源字符串必须以 '\0' 结束。
  • 目标空间必须有足够的大,能容纳下源字符串的内容。
  • 目标空间必须可修改

字符串比较函数——strcmp

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

函数功能: 

比较对应位置上字符的ascii码值的大小

标准规定:
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字

注意:

 两个字符串不能直接进行比较,也不能直接进行相加相减运算,因为字符串表示的是首字符的地址。也就是说,如果直接进行比较的话,比的不是字符串的内容,而是地址,所以是错误的。

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

 字符串连接函数——strncpy

char * strncpy ( char * destination, const char * source, size_t num );
  • 拷贝num个字符从源字符串到目标空间。
  • 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。

 字符串拷贝函数——strncat

char * strncat ( char * destination, const char * source, size_t num );
  • 将源字符串的num个字符添加到目标字符串,并加上一个结束的空字符。
  • 如果源字符串长度小于num,则只复制到null字符结束之前的内容。

字符串比较函数——strncmp

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

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

字符串查找函数——strstr

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

返回一个指向str1中首次出现str2的指针,如果str2不是str1的一部分,则返回一个空指针。

二. 内存操作函数

内存拷贝函数

拷贝未重叠内存——memcpy

void * memcpy ( void * destination, const void * source, size_t num );
  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
  • 这个函数在遇到 '\0' 的时候并不会停下来。
  • 如果source和destination有任何的重叠,复制的结果都是未定义的

拷贝重叠内存——memmove

void * memmove ( void * destination, const void * source, size_t num );
  • 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理。

内存比较函数——memcmp

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

比较从ptr1和ptr2指针开始的num个字节

内存设置函数——memset

void * memset ( void * ptr, int value, size_t num );

 函数功能:

以字节为单位设置内存 

举个例子

#include<stdio.h>
#include<string.h>
 
int main()
{
	char arr[20] = { 0 };
	memset(arr, 'x', 10);
	printf("%s\n", arr);
	return 0;
}

可以对整型进行操作,不过因为是对内存进行操作,所以要考虑到大小端字节序的问题

三. 函数的模拟实现

字符串操作函数的模拟实现

模拟实现strlen

在这里介绍三种方法

  1. 计数器的方法
  2. 递归的方法
  3. 指针 - 指针

计数器的方法:

int my_strlen(const char* str)
{
	assert(str);//断言str非空
	int count = 0;
	while (*str++ != '\0')
	{
		count++;
	}
	return count;
}

递归的方法:

int my_strlen(const char* str)
{
	assert(str);//断言str非空
	//找边界
	if (*str == '\0')
	{
		return 0;
	}
	return my_strlen(str + 1) + 1;
}

 这里需要注意的是,str++ 和 str+1 不是一个概念,str++是先使用后++,本题可以写成++str的形式,先++再使用。

指针 - 指针:


int my_strlen(const char* str)
{
	assert(str);
	const char* cur = str;
	while (*cur != '\0')
	{
		cur++;
	}
	return cur - str;

模拟实现strcpy


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

模拟实现strcat


char* my_strcat(char* dest, const char* src)
{
	char* ret = dest;
	assert(dest && src);
	//1、找到目标字符串的\0
	while (*dest)//注意循环条件写成*dest++是错误的,因为会跳过\0,请细品
	{
		dest++;
	}
	//2、拷贝源字符串
	while (*dest++ = *src++)
	{
		;
	}
	return ret;

模拟实现strcmp

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 *str1 - *str2;
		return 1;
	else
		return -1;
}

模拟实现strstr

char* my_strstr(const char* str, const char* substr)
{
	const char* s1 = str;
	const char* s2 = substr;
	const char* cur = str;
 
	assert(str && substr);
	//特殊情况
	if (*substr == '\0')
		return (char*)str;
	while (*cur)
	{
		s1 = cur;
		s2 = substr;
		while (*s1 && *s2 && *s1 == *s2)//注意*s1!='\0&&*s2!='\0
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
			return (char*)cur;
		cur++;
	}
	return NULL;
}

内存操作函数的模拟实现

模拟实现memcpy


void* my_memcpy(void* dest, const void* src, size_t num)
{
	void* ret = dest;//注意返回类型是void*,而不是void,
	assert(dest && src);
	while (num--)//先使用,后--
	{
		*(char*)dest = *(char*)src;//想想为什么强制类型转换成char*,因为只有它最合适
		dest = (char*)dest + 1;//注意直接进行dest++,src++是错误的,因为它是空类型
		src = (char*)src + 1;
	}
	return ret;
}

模拟实现memmove

void* my_memmove(void* dest, const void* src, size_t num)
{
	void* ret = dest;
	assert(dest && src);
	if (dest < src)//从前向后拷贝
	{
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else//从后向前拷贝
	{
		while (num--)//先使用,后--,在循环体中是--后的num
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	return ret;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

theonly_Love

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值