常用字符函数和字符串函数详解

     目录

本章重点

一、strlen函数

二、strcpy函数

三、strcat函数

四、strcmp函数

五、strncat函数

六、strncpy函数

七、strncmp函数

八、strstr函数

九、memcpy函数

十、memmove函数


本章重点

本文重点介绍字符和字符串的库函数得使用和注意事项

深度解析库函数,并实现相关的库函数


一、strlen函数

函数原型

size_t strlen ( const char * str );

函数介绍

  • strlen函数是用于计算字符串长度的
  • 字符串以"\0"作为结束标志,此函数就是计算"\0"之前的字符个数
  • 返回值为 size_t size_t原型为 typedef unsigned int size_t 是无符号整型的重命名,因为strlen函数是计算字符串长度,不可能为负数
  • 参数用const char*  的指针接收,const为不可修改增加了函数的安全性

函数模拟实现

下述展示三种strlen函数的模拟实现,三种不同的思路

方法一:计算头尾指针的距离从而得到字符串的长度

size_t my_strlen(const char* arr)
{
	assert(arr != NULL);//断言函数,用于判断函数是否为空
	const char* ret = arr;//将字符数组首地址赋值给ret指针变量
	while (*ret)//当ret解引用不为\0时循环继续
	{
		ret++;//指针向后偏移
	}
	return ret - arr;//计算出指针的偏移量从而得到字符串的长度
}

方法二 :利用一个标记,当数组内容不为\0时标记加一,从而得到字符串长度

size_t my_strlen1(const char* arr)
{
	assert(arr != NULL);
	int sum = 0;
	while (*arr)
	{
		arr++;
		sum++;
	}
	return sum;
}

方法三: 递归实现,当数组内容不为\0时递归调用

size_t my_strlen2(const char* arr)
{
	assert(arr != NULL);
	if (*arr)
		return 1 + my_strlen2(arr+1);
	else
		return 0;
}


二、strcpy函数

函数原型

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

函数介绍

  • strcpy是实现字符串拷贝的函数
  • destination是目标数组,source是用于拷贝的数组,即将source数组中的内容拷贝到destination中
  • source字符串必须以 '\0' 结束。
  • 会将source字符串中的 '\0' 拷贝到目标空间。
  • destination空间必须足够大,以确保能存放source字符串。
  • destination空间必须可变。

函数模拟实现

char* my_strcpy(char* destination, const char* source)
{
	assert(destination && source);
	char* ret = destination;//用一个字符指针记录des数组的起始地址
	while (*destination = *source)//当source内容为\0时循环结束
	{
		destination++;
		source++;
	}
	return ret;//返回des起始地址
}


三、strcat函数

函数原型

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

函数介绍

  • strcat是字符串追加函数
  • 将source的内容追加到destination中
  • source字符串必须以 '\0' 结束。
  • destination空间必须有足够的大,能容纳下源字符串的内容。
  • destination空间必须可修改。

函数模拟实现

char* my_strcat(char* arr1, const char* arr2)
{
	assert(arr1 && arr2);
	char* ret = arr1;//使用一个字符指针记录目标数组的首地址
	while (*arr1)//当目标函数内容为\0时,开始追加
	{
		arr1++;
	}
	while (*arr1 = *arr2)//开始追加字符串
	{
		arr1++;
		arr2++;
	}
	return ret;
}


四、strcmp函数

函数原型

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

函数介绍

  • strcmp函数时比较两个字符串的大小
  • 第一个字符串大于第二个字符串,则返回大于0的数字
  • 第一个字符串等于第二个字符串,则返回0
  • 第一个字符串小于第二个字符串,则返回小于0的数字

函数模拟实现

int my_strcmp(const char* arr1, const char* arr2)
{
	assert(arr1 && arr2);
	while (*arr1 == *arr2)//通过ascll码值依次比较每个字符的大小
	{
//当字符数组内容为\0时还没有比较出大小则表示两字符串相等
		if (*arr1 == '\0')
			return 0;//相等则返回0
		arr1++;
		arr2++;
	}
	return *arr1 - *arr2;//不相同等返回差值
}


五、strncat函数

函数原型

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

函数介绍

  • 只是在原有的strcat的基础上增加了一个size_t num
  • 表示只追加num个字符

函数模拟实现

char* my_strncat(char* arr1, const char* arr2, size_t num)
{
	assert(arr1 && arr2);
	char* ret = arr1;
	while (*arr1)
	{
		arr1++;
	}
	while (num--)//只追加num个字符
	{
		*arr1 = *arr2;
		arr1++;
		arr2++;
	}
	return ret;
}

六、strncpy函数

函数原型

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

函数介绍

  • 在原有strncpy上增加了一个size_t num
  • 表示只复制num个字符

函数模拟实现

char* my_strncpy(char* arr1, const char* arr2, size_t num)
{
	assert(arr1 && arr2);
	char* ret = arr1;
	while (num--)//控制复制的字符数
	{
		*arr1 = *arr2;
		arr1++;
		arr2++;
	}
	return ret;
}

七、strncmp函数

函数原型

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

函数介绍

  • 字符串比较函数,只比较num个字符
  • 相较于strcmp只多了一个num

函数模拟实现

int my_strncmp(const char* arr1, const char* arr2 ,size_t num)
{
	assert(arr1 && arr2);
	while (num--)
	{
		if (*arr1 == *arr2)//字符相等时指针后移
		{
			arr1++;
			arr2++;
		}
		else
		{
			return *arr1 - *arr2;//只要有不相等时就返回两个字符的差
		}
	}
	return 0;//循环结束任然相等返回0
}

八、strstr函数

函数原型

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

函数介绍

  • strstr函数是在str1字符串中查找str2字符串是否为str1的子串

函数模拟实现

char* my_strstr(const char* arr1, const char* arr2)
{
	const char* s1 = arr1;//利用s1指针记录被查询数组的地址
	const char* s2 = arr2;//s2记录查询数组的地址
	const char* p = arr1;//p指针为被查询数组的偏移量
	while (*s1)
	{
		s1 = p;//从arr1第一个字符开始对比,不是字串就偏移一位
		s2 = arr2;
		while (*s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')//如果查询的数组为\0了那就证明arr2是arr1的子串
		{
			return p;
		}
		p++;
	}
	return NULL;
}

九、memcpy函数

函数原型

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

函数介绍

  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
  • 这个函数在遇到 '\0' 的时候并不会停下来。
  • 如果source和destination有任何的重叠,复制的结果都是未定义的
  • 可以传任意参数,不局限于字符数组
  • 这里的num是字节数,例如传整型数组,一个整型是4字节,10个整型num的值为40

函数模拟实现

void* my_memcpy(void* arr1, const void* arr2,size_t num)
{
	void* ret = arr1;
	assert(arr1 && arr2);
	while (num--)//num为字节数,这样就保证了能够一个字节一个字节的交换
	{
		*(char*)arr1 = *(char*)arr2;//将传过来的地址强制类型转换为字符型
         //一个字节一个字节的复制
		arr1 = (char*)arr1 + 1;//强转为char*型这样指针偏移量就为1
		arr2 = (char*)arr2 + 1;
	}
	return ret;
}

十、memmove函数

函数原型

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

函数介绍

  • 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理

函数模拟实现

重叠情况一:当source指针在destination指针后面时,直接数字从前向后复制移动即可

 

重叠情况2:当source指针在destination指针前面时,直接数字从后向前复制移动即可

void* my_memmove(void* arr1, const void* arr2, size_t num)
{
    void* ret = arr1;
    assert(arr1 && arr2);
    if (arr1 <= arr2)//当目标函数指针在源函数左边时
    {
        while (num--)//从左向右复制
        {
            *(char*)arr1 = *(char*)arr2;
            arr1 = (char*)arr1 + 1;
            arr2 = (char*)arr2 + 1;
        }
    }
    else//目标函数在源函数右边时
    {
        while (num--)//从右向左依次复制
        {
            *((char*)arr1 + num) = *((char*)arr2 + num);
        }
    }
    return ret;
}


 总结

万丈高楼平地起,没有基础就没有后面的高楼,即使这些库函数并没有什么很难的算法,但是也是需要我们去学习的

这里总结了10个常用库函数的使用以及使用的注意事项,同时也给出了这些库函数的模拟实现

这里肯定还是存在问题的,希望看到的诸君不吝赐教!

猜你喜欢

转载自blog.csdn.net/x2656271356/article/details/128680681#comments_24893034