C语言常用字符串函数详解

在C语言标准库里面,存在一个对字符串数组进行操作的函数的头文件为string.h。

常用的字符串函数有strlen,strcpy,strcat等等。

了解这些字符串函数是如何实现的可以有助于更好的使用这些字符串函数,并且可以加深对C语言的理解。

strlen

strlen是获得一个字符串的有效长度,注意计算大小时不包括'\0'。

下面是C语言官方所给出的声明和解释:

strlen的返回值是size_t,是一个无符号整型。形参用const修饰*str,防止*str被修改。

strlen的模拟实现

计数法:

size_t my_strlen_1(const char* arr)
{
	assert(arr);//断言,防止空指针
    size_t count=0;
	while (*arr != '\0')
	{
		arr++;
		count++;
	}
	return count;
}

递归法:

size_t my_strlen_2(const char* arr)
{
	
	assert(arr);
    if(*arr=='\0')
        return 0;
	
	return my_strlen2(++arr)+1;
}

两种方法都可以计算出一个字符串的长度

strcpy

strcpy是将字符串拷贝至目标空间内,原字符串必须包含'\0',且目标空间足够存入该字符串。

同样的给出C语言官方所给出的声明和解释:

注意strcpy有返回值,返回值为目标空间的首元素地址。

strcpy的模拟实现

char* mystrcpy(char* des, const char* str)
{
    assert(des&&str);
    char* tmp = des;//先保存一下原地址
	while (*str != '\0')
	{
		*des = *str;
		des++;
		str++;
	}
	*des = '\0';//最后将'\0'也拷贝过去
	return tmp;
}

strcat

strcat是将一个字符串拼接到另一个字符串的后面,要求目标空间足够大。

给出C语言官方所给出的声明和解释:

该函数是将source所指向的字符串拷贝到destination指向的字符串的后面,返回目标空间的首元素地址。

strcat的模拟实现

char* mystrcat(char* des, const char* source)
{
	assert(des&&source);
	char* tmp=des;
	while (*des!= '\0')//先找到目标字符串的'\0'
		des++;
	while (*source!= '\0')//将字符串拷贝值目标函数末尾
	{
		*des= *source;
		des++;
		source++;
	}
	*des= '\0';//将'\0'也给目标字符串
	return tmp;
}

strcmp

strcmp逐位比较两个字符串,如果第一个字符串大于第二个字符串返回大于零的数;如果第一个字符串小于第二个字符串返回小于零的数;如果二者相等则返回0。这个大于小于指的是ASCII码值,也就是逐位比较字符的ASCII码值。

给出C语言官方所给出的声明和解释:

 strcmp的模拟实现

int mystrcmp(const char* str1,const char* str2)
{
	assert(str1&&str2);
	while (1)
	{
		if (*str1 == '\0'&& *str2 == '\0')//如果都到结尾,说明两个子串相等
		{
			return 0;
		}
		else if (*str1 == *str2)//如果相等继续向后判断
		{
			str1++;
			str2++;
		}
		else if (*str1 > *str2)
			return 1;
		else
			return -1;
	}
}

strstr

查找字符串中的子串,返回被查找字符串中子串首元素地址。

给出C语言官方所给出的声明和解释:

从官方的文档中可以看出strstr有两种类型,一种是被const修饰,一种未被const修饰,实现功能一样,只是存在一定的权限问题;在str1里面查找是否存在str2子串,如果没有找到则返回空值。

strstr的模拟实现

const char* mystrstr(const char* str1, const char* str2)
{
	assert(str1&&str2);
	const char*pa = str1;
	const char*pb = str2;

	if (*str1 == '\0')//规定如果查找空字符,返回原字符串
		return str1;

	while (*str1 != '\0')
	{
		while (*pb != '\0'&&*pa != '\0')
		{
			if (*pa == *pb)//逐个比较
			{
				pa++;
				pb++;
			}
			else
				break;
		}

		if (*pb == '\0')
			return arr1;//返回字符串子串首元素地址
		if (*pa == '\0')//避免进行不必要的计算
			return NULL;
		str1++;
		pa = str1;
		pb = str2;
	}
	return NULL;
}

除了上面的常用的字符串函数,string.h里面还包含一些对内存操作的函数,也非常的好用例如memcpy、memmove、memset等等

memcpy

memcpy是将source指向的空间里面的内容按字节拷贝到destination所指向的空间,共拷贝num个字节,并返回目标地址;

给出C语言官方所给出的声明和解释:

这里采用void*指针,说明该指针可以指向任意类型的地址,也就说是说,无论什么类型的元素都可以拷贝,直接访问地址进行拷贝。

memcpy的模拟实现

void* mymemcpy(void* str1, const void* str2, int size)//size字节数
{
	assert(str1&&str2);
	for (int i = 0; i < size; i++)
	{
		*((char*)str1+ i)  = *((char*)str2+ i);
	}
	return str1;
}

这里需要强制类型转换,将任意类型的地址转换成char*,这样每次步进都是一个字节,就可以逐字节拷贝。

memset

memset是对指定内存空间写入num个字节,注意写入的值为int类型,只能写入整型,返回值为void*。

同样给出C语言官方所给出的声明和解释:

这里写入的值虽然是int类型,但是在具体实现的过程中,会存在截断,高24位会截断。

memset的模拟实现

void* mymemset(void* ptr,int val,size_t num)
{
    assert(ptr);
    unsigned char ch = val;//截断,只保留8位无符号类型
    for(size_t i=0;i<num;i++)
    {
        *((char*)ptr+i) = ch;
    }
    return ptr;
}

memcmp、memmove等具体功能可以查看cplusplus.com - The C++ Resources Network

具体的实现方式和上面类似,不在阐述。

评论 12 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:游动-白 设计师:我叫白小胖 返回首页

打赏作者

TangguTae

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

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值