【C语言】字符串函数及内存函数的模拟实现和原理

目录

 一、求字符串长度

1.strlen()函数

1.函数功能

2.函数原形

3.模拟实现

二、长度不受限制的字符串操作函数

1.strcpy()函数

1.函数功能

2.函数原形

3.模拟实现

2.strcat()函数

1.函数功能

2.函数原形

3.模拟实现

3.strcmp()函数

1.函数功能

2.函数原形

3.模拟实现

三、长度受限制的字符串操作函数

1.strncpy()函数

1.函数功能

2.函数原型

3.模拟实现

2.strncat()函数

1.函数功能

2.函数原形

3.模拟实现

3.strncmp()函数

1.函数功能

2.函数原形

3.函数模拟

八、字符串查找

1.strstr()函数

1.函数功能

2.函数原形

3.模拟实现

2.strtok()函数

1.函数功能

2.函数原形

3.实现原理

四、错误信息报告

1.strerror()函数

1.函数功能

2.函数原形

3.实现原理

五、内存操作函数

1.memcpy()函数

 1.函数功能

2.函数原形

3.模拟实现

2.memmove()函数

1.函数功能

2.函数原形

3.模拟实现

3.memset()函数

1.函数功能

2.函数原形

3.模拟实现

4.memcmp()函数

1.函数功能

2.函数原形

3.模拟实现


 一、求字符串长度

1.strlen()函数

1.函数功能

    计算字符串长度的函数,返回类型是size_t,即无符号整型。

2.函数原形

   size_t strlen(const char* str);

3.模拟实现

代码:

//模拟实现strlen()函数
unsigned int my_strlen(const char* str)
{
    char* tmp = str;
	int len = 0;
	while (*tmp)
	{
		len++;
		tmp++;
	}
	return len;
}

二、长度不受限制的字符串操作函数

1.strcpy()函数

1.函数功能

    拷贝字符串(包括'\0'),读到'\0'就停止拷贝。

2.函数原形

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

3.模拟实现

代码:

//模拟实现strcpy()函数
//将str2拷贝到str1中
char* my_strcpy(char* str1, const char* str2)
{
	char* tmp = str1;
	while (*str2)
	{
		*str1 = *str2;
		str1++;
		str2++;
	}
	*str1 = '\0';
	return tmp;
}

2.strcat()函数

1.函数功能

    实现字符串的连接。

2.函数原形

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

3.模拟实现

代码:

//模拟实现strcat()函数
char* my_strcat(char* str1, const char* str2)
{
	char* tmp = str1;
	while (*++str1);//循环结束后*str1是'\0'
	while (*str2)
	{
		*str1 = *str2;
		str1++;
		str2++;
	}
    *str1++ = '\0';
	return tmp;
}

3.strcmp()函数

1.函数功能

    比较两个字符串的大小。

    比较的是两个字符串对应字符的ASCII码值,第一个字符串字符大于第二个字符串中对应字符时函数返回大于0的数,小于时返回小于0的数,等于时返回0。

2.函数原形

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

3.模拟实现

代码:

//模拟实现strcmp()函数
int my_strcmp(const char* str1, const char* str2)
{
	while (*str1 == *str2)
	{
		if (*str1 == '\0')
		{
			return 0;
	    }
		str1++;
		str2++;
	}
	return (*str1 - *str2);
}

三、长度受限制的字符串操作函数

1.strncpy()函数

1.函数功能

  拷贝字符串(前n个字符(不包括'\0')),将前n个字符拷贝完成后,将目标空间的第n+1个字符置为'\0',以终止拷贝。

2.函数原型

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

3.模拟实现

代码:

//模拟实现strncpy()函数
char* my_strncpy(char* str1, const char* str2,unsigned int n)
{
	char* tmp = str1;
	while (n)
    {
		*str1 = *str2;
		str1++;
		str2++;
        n--;
	}
	*str1 = '\0';
	return tmp;
}

2.strncat()函数

1.函数功能

    将源字符串的前n个字符连接到目标字符串,其后加'\0'结束字符串。

2.函数原形

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

3.模拟实现

代码:

//模拟实现strncat()函数
char* my_strncat(char* str1, const char* str2,unsigned int n)
{
	char* tmp = str1;
	while (*++str1);
	while (n)
	{
		*str1 = *str2;
		str1++;
		str2++;
        n--;
	}
    *str1++ = '\0';
	return tmp;
}

3.strncmp()函数

1.函数功能

    比较两个字符串的前n个字符。

2.函数原形

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

3.函数模拟

代码:

//模拟实现strcmp()函数
int my_strcmp(const char* str1, const char* str2,unsigned int n)
{
	while (*str1 == *str2 && n)
	{
		if (*str1 == '\0')
		{
			return 0;
		}
		str1++;
		str2++;
        n--;
	}
	return (*str1 - *str2);
}

八、字符串查找

1.strstr()函数

1.函数功能

    找到字符串中的子字符串,并返回第一次出现的子字符串的首地址。

2.函数原形

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

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

3.模拟实现

代码:

//模拟实现strstr()函数
char* my_strstr(char* str1, const char* str2)
{
	char* s1 = str1;
	char* s2 = str2;
	char* p1 = s1;
	char* p2 = s2;
	while (*p1)
	{
		while (*s1 == *s2 && *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
			return p1;
		else
		{
			p1++;
			s1 = p1;
			s2 = p2;
		}
	}
	return NULL;
}

2.strtok()函数

1.函数功能

    截断字符串(按标识符截断)。

2.函数原形

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

3.实现原理

代码:

//strtok()函数的应用
int main()
{
	char arr[] = "http@qq.com";
	char buf[200] = { 0 };
	strcpy(buf, arr);//buf[200]="http@qq.com"
	const char* p = "@.";//标识符
	char* str = NULL;

	for (str=strtok(buf, p); str!=NULL; str=strtok(NULL, p))
	{
		printf("%s\n", str);
	}

	return 0;
}

运行结果:

解释:

    strtok()函数传参的时候,第一个参数为截断字符串的起始地址。第一次传参的时候传所需截断字符串的首地址;从第二次开始,因为第一次截断时strtok() 记住了标识符的下一个字符的地址,所以只需传空指针NULL;如需截断另一个新的字符串,只需将新字符串的地址传给第一个参数即可。

四、错误信息报告

1.strerror()函数

1.函数功能

    获取指向错误消息字符串的指针(把错误码转化为错误信息)。

2.函数原形

char * strerror ( int errnum );

3.实现原理

代码:

#include <stdio.h>
#include <string.h>
#include <errno.h>
//strerror
//把错误码转换成错误信息
int main()
{
    printf("%s\n", strerror(0));
	printf("%s\n", strerror(1));
	printf("%s\n", strerror(2));
	printf("%s\n", strerror(3));
	printf("%s\n", strerror(4));
    printf("%s\n", strerror(5));

    //错误码记录到错误码的变量中
	//errno - C语言提供的全局的错误变量
    printf("%s\n",strerror(errno));
    return 0;
}

运行结果:

五、内存操作函数

1.memcpy()函数

 1.函数功能

   内存拷贝(一般编译器不支持目标空间和被拷贝的部分有重叠),因拷贝内容的类型不确定,故以单个字节为单位进行拷贝,返回目标空间的起始地址。

2.函数原形

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

3.模拟实现

代码:

#include <stdio.h>
#include <assert.h>
//模拟实现memcpy()
//memcpy()函数的功能因编译器而异,大部分编译器不能处理有重叠的情况,此处不予考虑
void* my_memcpy(void* destination, const void* source, unsigned int n)
{
	assert(destination && source);
    //为了代码的可移植性,因为拷贝对象的大小不确定,所以以单个字节为单位拷贝
	char* src = (char*)source;
	char* des = (char*)destination;

	while (n)
	{
		//从前往后拷贝
		*des = *src;
		des++;
		src++;
		n--;
	}

	return destination;//返回目的空间的首地址,方便链式访问	    
}

函数原理:

    void*可以接受任意类型变量的地址,因为变量大小的不确定性,将指针强转为char*(指针类型决定解引用可以访问的空间大小,char*解引用访问一个字节大小的空间),然后一个字节一个字节的拷贝。

2.memmove()函数

1.函数功能

    内存拷贝(与memcpy()函数相似,memmove()函数能处理目标空间和被拷贝空间有重叠的情况)。

2.函数原形

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

3.模拟实现

代码:

#include <stdio.h>
#include <assert.h>
//模拟实现memmove()
void* my_memmove(void* destination,const void* source,unsigned int n)//n为拷贝的字节数
{
	assert(destination && source);
	//为了代码的可移植性,因为拷贝对象的大小不确定,所以以单个字节为单位拷贝
	char* src = (char*)source;
	char* des = (char*)destination;

	if (src < des && src + n - 1 > des)
	{
		des = des + n - 1;
		src = src + n - 1;
		//重叠且source在前:从后往前拷贝
		for (int i = 0;i < n;i++)
		{
			*des = *src;
			des--;
			src--;
		}
	}
	else
	{
		//没有重叠的空间或者重叠但source在后:从前往后拷贝
		for (int i = 0;i < n;i++)
		{
			*des = *src;
			des++;
			src++;
		}
	}
	return destination;//方便链式访问
}

   函数原理:

    处理目标空间和被拷贝空间有重叠的时候有两种情况,第一种,目标空间在前,被拷贝空间在后,从前往后拷贝(与不重叠的情况拷贝顺序相同);第二种,目标空间在后,被拷贝空间在前,从后往前拷贝。

3.memset()函数

1.函数功能

    将目标空间的前num个字节的空间都赋值为value。

2.函数原形

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

3.模拟实现

代码:

//模拟实现memset()函数
void* my_memset(void* ptr, int value, unsigned int n)
{
	char* p = (char*)ptr;
	char tmp = (unsigned char)value;
	while (n)
	{
		*p = tmp;
		p++;
		n--;
	}
	return ptr;
}

int main()
{
	char str[] = "almost every programmer should know memset!";
	my_memset(str, '-', 6);
	puts(str);
	return 0;
}

运行结果:

4.memcmp()函数

1.函数功能

    比较两个内存空间内对应内容的大小,以单个字节为单位进行比较,比较两个指针指向空间前num个字节的内容,与strcmp()函数不同的是,遇到'\0'也不会停止比较。

2.函数原形

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

3.模拟实现

代码:

#include <stdio.h>

//模拟实现memcmp()函数
int my_memcmp(const void* ptr1, const void* ptr2, unsigned int n)
{
	char* p1 = (char*)ptr1;
	char* p2 = (char*)ptr2;

	while (*p1 == *p2)
	{
		if (n == 0)
			return 0;
		else
		{
			p1++;
			p2++;
			n--;
		}
	}
	return *p1 - *p2;
}

int main()
{
	char buffer1[] = "DWgaOtP12df0";
	char buffer2[] = "DWGAOTP12DF0";

	int n;

	n = my_memcmp(buffer1, buffer2, sizeof(buffer1));

	if (n > 0)
		printf("'%s' is greater than '%s'.\n", buffer1, buffer2);
	else if (n < 0)
		printf("'%s' is less than '%s'.\n", buffer1, buffer2);
	else 
		printf("'%s' is the same as '%s'.\n", buffer1, buffer2);

	return 0;
}

运行结果:

这篇文章写到这里就结束啦,看到错误的话烦请指正,谢谢大家!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值