【C语言】字符串函数和内存操作函数介绍、模拟实现

目录

求字符串长度

strlen函数

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

strcpy  字符串复制函数

strcat  字符串追加函数

strcmp 字符串比较函数

长度受限制的字符串函数

strncpy 字符串复制函数

strncat 字符串追加函数

strncmp 字符串比较函数

字符串查找函数 

strstr

 strtok

 错误信息报告

 strerror  错误信息报告函数

perror  错误信息打印函数

内存操作函数

memcpy 内存复制函数

memmove  内存移动函数

memset 初始化内存函数

memcmp 内存比较函数



  • 求字符串长度

  • strlen函数

size_t strlen ( const char * str );

strlen函数返回类型是size_t,size_t其实就是无符号整形   

1.字符串以'\0'作为结束标志,strlen函数返回的是在字符串中'\0'前面出现的字符个数(不包括'\0')。 

2.参数指向的字符串必须要以'\0'结束。

例:

 3.模拟实现strlen

//创建临时变量方式
int my_strlen(const char*str)
{
    assert(str!=NULL);//保证指针的有效性,使用时记得引用<assert.h>头文件
    int count=0;
    while(*str)//当*str不为'\0'的时候进入循环
    {
        count++;
        str++;
    }
    return count++;
}

//递归的方式
int my_strlen(const char*str)
{
    if(*str=='\0')
        return 0;
     else
        return 1+my_strlen(str+1);
}

//指针减指针的方式
int my_strlen(const char*str)
{
    char*p=str;//把起始地址赋值给p,让p进行while循环
    while(*p!='\0')
    {
        p++;
    }
    return p-str;
}
  • 长度不受限制的字符串函数

  • strcpy  字符串复制函数

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

1.源字符串(source指针指向的字符串)必须以'\0'结束 

2.strcpy函数将source指针指向的字符串(包括'\0')复制到dest指定的位置。复制或追加字符串时不执行溢出检查。如果源字符串和目标字符串重叠,则strcpy的行为未定义。所以目标空间必须足够大,确保能放入源字符串。

例:

 3.模拟实现strcpy

char* my_strcpy(char* dest,const char* src)
{
    char* ret=dest;//把目的地地址存起来,以防下面计算时变化找不到原来地址
    assert(dest&&src);//保证指针的有效性,使用时记得引用<assert.h>头文件

    //while (*src != '\0')
    //{
    //	*dest = *src;
    //	dest++;
    //	src++;
    //}
    //*dest = *src;//拷贝'\0'
    

    while((*dest++ = *src++))//上面和这里的实现是一样的
    {
         ;   
    }

    return ret;
}

 --------------------------------------------------------------------------------------------------------------------------------

  • strcat  字符串追加函数

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

1.目标空间可修改且必须足够大,能容纳下源字符串内容,源字符串(source指针指向的字符串)必须以'\0'结束

2.strcat函数将source追加到dest,并用空字符终止结果字符串。source的第一个字符覆盖dest的终止空字符(即'\0')。追加字符串时不执行溢出检查。如果源字符串和目标字符串重叠,则strcat的行为未定义。

例:

 3.模拟实现strcat

char* my_strcat(char* dest, const char*src)
{
	char*ret = dest;//把目的地地址存起来,以防下面计算时变化找不到原来地址
	assert(dest&&src);//保证指针的有效性,使用时记得引用<assert.h>头文件
	while (*dest)//先找到目的地的'\0'
	{
		dest++;
	}
	while ((*dest++ = *src++))//追加过去
	{
		;
	}
	return ret;
}

 --------------------------------------------------------------------------------------------------------------------------------

  • strcmp 字符串比较函数

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

strcmp函数不是比较字符串长度,是比较字符串字符的ASCII值,并返回一个值,指示它们之间的关系。

标准规定:

第一个字符串大于第二个字符串,则返回大于0的数字;

第一个字符串等于第二个字符串,则返回0;

第一个字符串小于第二个字符串,则返回小于0的数字;

例:

 模拟实现strcmp:

int my_strcmp(const char*str1, const char*str2)
{

	assert(str1&&str2);
	while (*str1 == *str2)
	{
		if (*str1 == '\0')
			return 0;
		str1++;
		str2++;
	}
	return *str1 - *str2;//str1大于或者小于str2的时候返回他们的差值
}

———————————————————————————————————————————

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

  • strncpy 字符串复制函数

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

strncpy函数将source的初始计数字符复制到dest并返回dest。如果num小于或等于source的长度,则不会自动将空字符('\0')追加到复制的字符串中。如果num大于source的长度,则目标字符串将补0,补足num个。如果源字符串和目标字符串重叠,则strncpy的行为未定义。

例:

模拟实现strncpy:

#include <stdio.h>
char* my_strncpy(char*dest,const char*source,size_t num)
{
	char *ret = dest;

	while (num && (*dest++ = *source++))//复制   
		num--;

	if (num)  //用零填充
	while (--num)
		*dest++ = '\0';

	return ret;
}

  -------------------------------------------------------------------------------------------------------------------------------

  • strncat 字符串追加函数

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

strncat函数将source的初始字加上终止的null字符追加到dest终止空字符。如果在追加计数字符之前,source中出现空字符,strncat将追加source中的所有字符,直至空字符。如果num大于source的长度,则使用source的长度代替num(不足目标长度时不会补0)。结果字符串以空字符结尾。如果复制发生在重叠的字符串之间,则行为未定义。例:

 模拟实现strncat:

#include<stdio.h>
char* my_strncat(char* dest,const char* source,size_t num)
{
	char *ret = dest;

	while (*dest++)
	{
		;
	}
	dest--;
	while (num--)
	{
		if (!(*dest++ = *source++))
			return ret;
	}
	*dest = '\0';
	return ret;
}

 -------------------------------------------------------------------------------------------------------------------------------

  • strncmp 字符串比较函数

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

strncmp函数按ASCII比较str1和str2中的num个字符,并返回一个值,该值指示子字符串之间的关系。strncmp是_strnicmp的一个区分大小写的版本。

标准规定:

第一个字符串大于第二个字符串,则返回大于0的数字;

第一个字符串等于第二个字符串,则返回0;

第一个字符串小于第二个字符串,则返回小于0的数字;

例:

 模拟实现strncmp:

int my_strncmp(const char* str1, const char* str2, size_t num)
{
	assert(str1&&str2);//保证指针的有效性,使用时记得引用<assert.h>头文件
	while (num > 0)
	{
		if (*str1 > *str2)
		{
			return *str1-*str2;//str1大于或者小于str2的时候返回他们的差值
		}
		else if (*str1 < *str2)
		{
			return *str1 - *str2;//str1大于或者小于str2的时候返回他们的差值
		}
		else if (*str1 == *str2)
		{
			str1++;
			str2++;
			num--;
		}
		else
		{
			str1++;
			str2++;
			num--;
		}
	}
	return 0;
}

———————————————————————————————————————————

  • 字符串查找函数 

  • strstr

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

str2为要查找的字符串,str1为查找目的地,找到了就返回指向str1中第一个出现的str2的指针,如果str不是str1的一部分,则返回空指针。匹配过程不包括终止的空字符,但会在此停止。

例:

模拟实现strstr:

char* my_strstr(const char*str1, const char*str2)
{
	assert(str1&&str2);
	char* cp = (char*)str1;
	char* substr = (char*)str2;
	char* s1 = NULL;
	if (*str2 == '\0')
		return NULL;
	while (*cp)
	{
		s1 = cp;
		substr = str2;
		while (*s1&&*substr && (*s1 == *substr))
		{
			s1++;
			substr++;
		}
		if (*substr == '\0')
			return cp;
		cp++;
	}

}

------------------------------------------------------------------------------------------------------------------------------- 

  •  strtok

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

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

例:

  •  错误信息报告

  •  strerror  错误信息报告函数

char * strerror ( int errnum );

这个函数是把错误码转换成错误信息,每个数字都有自己的错误信息,strerror可以帮我们把信息翻译出来,使用时记得包含<errno.h>

例:

  • perror  错误信息打印函数

void perror ( const char * str );

这个函数首先把错误码转化为错误信息然后打印错误信息(包含了自定义信息)如图:

———————————————————————————————————————————

  • 内存操作函数

  • memcpy 内存复制函数

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

将num个字节从源指向的位置直接复制到目标指向的内存块。该函数不检查源中是否有任何终止的空字符,它总是精确复制num字节。为避免溢出,目标和源参数指向的数组大小应至少为num字节,且不应重叠(对于重叠的内存块,memmove是一种更安全的方法)

模拟实现:

void* my_memcpy(void* dest, const void* src, size_t num)
{

	assert(dest&&src);
	void* ret = dest;
	while (num--)
	{
		*(char*)dest = *(char*)src;//转化为char*比较方便
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}
  • memmove  内存移动函数

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

将num个字节从源指向的位置复制到目标指向的内存块。复制就像使用了中间缓冲区一样进行,允许目标和源重叠。该函数不检查源中是否有任何终止的空字符-它总是精确复制num字节。为避免溢出,目标和源参数所指向的数组的大小应至少为num字节。

模拟实现:

void * memmove(void * dst, const void * src, size_t count)
{
	void * ret = dst;
	​
	if (dst <= src || (char *)dst >= ((char *)src + count)) {
	
		while (count--) {
			*(char *)dst = *(char *)src;
			dst = (char *)dst + 1;
			src = (char *)src + 1;
		}
	}
	else {
		
		dst = (char *)dst + count - 1;
		src = (char *)src + count - 1;
		​
		while (count--) {
			*(char *)dst = *(char *)src;
			dst = (char *)dst - 1;
			src = (char *)src - 1;
		}
	}
	​
		return ret;
}

  • memset 初始化内存函数

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

将ptr指向的内存块的首个num字节设置为value。memset() 函数常用于内存空间初始化。
如:
char str[100];
memset(str,0,100);

模拟实现:

void*my_memset(void*str, int val, size_t num)
{
    assert(str);
    void*p = str;
    while (num--)
    {
        *(int*)str = val;
        str = (int*)str + 1;
    }
    return p;
}

  • memcmp 内存比较函数

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

将ptr1指向的内存块的第一个num字节与ptr2指向的第一个num字节进行比较,如果它们都匹配,则返回零;如果不匹配,则返回一个不同于零的值,ptr1<ptr2返回小于0的值,反之返回大于0的值。
注意,与strcmp不同,函数在找到空字符后不会停止比较。

模拟实现:

int my_memcmp(const void*ptr1,const void*ptr2, size_t num)
{
	assert(ptr1);//记得使用assert头文件
	assert(ptr2);
	while (num--)
	{
		if (*(char*)ptr1 == *(char*)ptr2)
		{
			ptr1 = (char*)ptr1 + 1;
			ptr2 = (char*)ptr2 + 1;
		}
		else
		{
			if (*(char*)ptr1 > *(char*)ptr2)
			{
				return 1;
			}
			else
			{
				return -1;
			}
		}
	}
	return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值