[C/C++]C语言中字符相关的库函数的模拟实现

本文主要介绍处理字符和字符串的库函数的功能及模拟实现。

1.对库函数按照功能可分为以下几类:

                     (1)求字符串长度:strlen;

                     (2)长度不受限制的字符串函数:strcpy、strcat、strcmp;

                     (3)长度受限制的字符串函数:strncpy、strncat、strncmp;

                     (4)字符串查找:strstr、strtok;

                     (5)字符操作:iscntrl、isspace、isdigit、isxdigit、islower、isupper、isalpha、isalnum、ispunct、isgraph、isprint;

                     (6)内存操作函数:memcpy、memmove、memset、memcmp;

2.功能介绍及模拟实现

                     C语言中对字符和字符串的处理比较麻烦的,而且C语言没有字符串类型,所以字符串通常放在常量字符串中或者字符数组中。

                     字符串常量适用于那些对它不做修改的字符串函数。

                      (1)strlen函数介绍及模拟实现

                          介绍:用来计算字符串的长度,字符串已经'\0' 作为结束标志,strlen函数返回的是在字符串中'\0' 前面出现的字符个数(不包含'\0' )。参数指向的字符串必须要以'\0' 结束。返回值为size_t,是无符号的。

size_t strlen ( const char * str );

                        模拟实现:

                           方法一:计数器方式

int my_strlen(const char* str)
{
	char* s = (char*)str;
	int i = 0;
	while (*s)
	{
		s++;
		i++;
	}
	return i;
}

                           方法二:不创建临时变量计数器

int my_strlen(const char * str)
{
    if(*str == '\0')
        return 0;
    else
        return 1+my_strlen(str+1);
}

                           方法三:指针的方式

int my_strlen(char *s)
{
    char *p = s;
    while(*p != ‘\0’ )
        p++;
    return p-s;
}

 

                      (2)strcpy函数介绍及模拟实现

                          介绍:strcpy可以将以'\0'结束的字符串复制到另一个地址中,返回值的类型为char*,源字符串必须以'\0' 结束,会将源字符串中的'\0' 拷贝到目标空间,目标空间必须足够大,以确保能存放源字符串,目标空间必须可变。

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

                        模拟实现:需要注意参数顺序,函数的功能,停止条件,通过assert断言保证地址有效性,const修饰源地址指针。

char* my_strcpy(const char * s1,const char* s2)
{
	assert(s1 != NULL);
	assert(s2 != NULL);
	char* p1 = (char*)s1;
	char* p2 = (char*)s2;
	while (*p1 = *p2)
	{
		p1++;
		p2++;
	}
	return *s1;
}

 

                      (3)strcat函数介绍及模拟实现

                          介绍:把src所指向的字符串(包括“\0”)复制到dest所指向的字符串后面(删除*dest原来末尾的“\0”),源字符串必须以'\0' 结束,目标空间必须有足够的大,能容纳下源字符串的内容,目标空间必须可修改。

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

                        模拟实现:

char* my_strcat(char * dest,const char * s2)
{
	char* p2 = (char*)s2;
	char* dest1 = (char*)dest;
	while (*dest1)
	{
		dest1++;
	}
	while (*dest1 = *p2)
	{
		dest1++;
		p2++;
	}
}

                      (4)strcmp函数介绍及模拟实现

                          介绍:判断两个字符串的大小,第一个字符串大于第二个字符串,则返回大于0的数字;

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

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

                        模拟实现:

int my_strcmp(const char* s1, const char* s2)
{
	while (((unsigned char*)s1 - (unsigned char*)s2) && *s2)
	{
		s1++;
		s2++;
	}
	return (unsigned char*)s1 - (unsigned char*)s2;
}

                      (5)strncpy函数介绍及模拟实现

                          介绍:与strcpy相似,区别是拷贝num个字符从源字符串到目标空间。如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。

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

                        模拟实现:

char* my_strncpy(char* dest, const char* src, int num)
{
	char* ret = src;
	for(int i= 0;i<num;i++)
	{
		if (*ret)
		{
			dest[i] = ret[i];
		}
		else
		{
			dest[i] = 0;
		}
	}
	return dest;
}

                      (6)strncat函数介绍及模拟实现

                          介绍:与strcat相似,区别是操作num个字符。

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

                        模拟实现:

char* my_strncat(const char* dest, const char * src, int num)
{
	char* ret = dest;
	char* p2 = src;
	while (*ret)
	{
		ret++;
	}
	while (num--)
	{
		if (*p2)
		{
			*ret = *p2;
			p2++;
			ret++;
		}
		else
		{
			*ret = 0;
			ret++;
		}
	}
	return dest;
}

                      (7)strncmp函数介绍及模拟实现

                          介绍:与strcmp相似,区别是操作num个字符。模拟实现也相似,不再赘述。

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

                      (8)strstr函数介绍及模拟实现

                          介绍:返回字符串中首次出现子串的地址。

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

                        模拟实现:也可以通过KMP算法实现

char *my_strstr(const char* str1, const char* str2 )
{
    assert(str1);
    assert(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++;
    }
}

                      (9)strtok函数介绍及模拟实现

                          介绍:strtok()用来将字符串分割成一个个片段,第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。strtok函数找到str中的下一个标记,并将其用\0 结尾,返回一个指向这个标记的指针。                                            strtok函数的第一个参数不为NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。strtok函数的第一个参数为NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。如果字符串中不存在更多的                                      标记,则返回NULL 指针。

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

                      (10)strerror函数介绍及模拟实现

                          介绍:返回错误码,所对应的错误信息。必须包含的头文件<errno.h>.

char * strerror ( int errnum );

                      (11)字符分类函数

                          包括:

                                  iscntrl :任何控制字符;
                                  isspace :空白字符:空格‘ ’,换页‘\f’,换行'\n',回车‘\r’,制表符'\t'或者垂直制表符'\v';
                                  isdigit :十进制数字 0~9;
                                  isxdigit :十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A~F;
                                  islower :小写字母a~z;
                                  isupper: 大写字母A~Z;
                                  isalpha:字母a~z或A~Z;
                                  isalnum:字母或者数字,a~z,A~Z,0~9;
                                  ispunct: 标点符号,任何不属于数字或者字母的图形字符(可打印);
                                  isgraph: 任何图形字符;
                                  isprint: 任何可打印字符,包括图形字符和空白字符;

                      (12)memcpy函数介绍及模拟实现

                          介绍:与strcpy的区别是,可操作非char型指针,函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。这个函数在遇到'\0' 的时候并不会停下来。如果source和destination有任何的重叠,复制的结果都是未                                        定义的。

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

                        模拟实现:dest 和src转移强制类型转化为char(一个字节)才可以进行操纵,void不能操作;

void* my_memcpy(void* dest, void* src, int num)
{
	assert(dest);
	assert(src);
	void* ret = dest;
	while (num--)		//num个字节
	{
		*(char * )dest = *(char *)src;			//转移强制类型转化为char(一个字节)才可以进行操纵,void不能操作;
		((char*)dest)++;						//必须加括号,分清楚优先级。
		((char*) src)++;
	}
	return ret;
}

                      (13)memcmp函数介绍及模拟实现

                          介绍:比较从ptr1和ptr2指针开始的num个字节的大小;实现方式与strcmp相似,不再赘述。

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

 

                      (14)memmove函数介绍及模拟实现

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

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

                        模拟实现:当dest 处于 src之后。应当从后向前复制,可避免不能重叠的问题,反之从前向后,这就可以对重叠内存块进行复制

void* my_memmove(void* dest, void* src, int num)
{
	assert(dest);
	assert(src);
	void* ret = dest;
	if (dest > src)			//当dest 处于 src之后。应当从后向前复制,可避免不能重叠的问题,反之从前向后
	{
		while (num--)		//num个字节,直接加上,即使最后段
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	else
	{
		while (num--)		//num个字节
		{
			*(char*)dest = *(char*)src;
			((char*)dest)++;
			((char*)src) ++;
		}
	}

	return ret;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值