【C语言】库函数实现及其模拟

⚡Hello~这里是傾城49⚡

🐏不定期更新知识干货~🐏

🌈点个关注不迷路~🌈

文章目录

前言

Strlen

strlen实现

strlen模拟实现

方法一

方法二

方法三

Strcpy

strcpy实现

strcpy模拟实现

Strcat

strcat实现

strcat模拟实现

Strcmp

strcmp实现

strcmp模拟实现

Strncpy

strncpy实现

Strncat

strncat实现

Strncmp

strncmp实现

字符串查找

Strstr

strstr实现

strstr模拟实现

Strtok

strtok实现

Strerror

strerror实现

Memcpy

memcpy实现

memcpy模拟实现

Memmove

memmove实现

memmove模拟实现

Memcmp

memcmp实现

Memset

memset实现

总结




前言

C语言中部分的库函数实现及其模拟。


Strlen

size_t strlen ( const char * str )

  • 字符串以'\0'作为结束标志,strlen函数返回的是在字符串中'\0'前面出现的字符个数(不包含'\0')
  • 函数的返回值为size_t,是无符号的。

strlen实现

#include <stdio.h>
#include <string.h>
int main()
{
    const char* str1 = "abcdef";
	int ret = strlen(str1);
	printf("%d", ret);//6
    return 0;
}

strlen模拟实现

主要的代码:

方法一

//计数方法
int my_strlen(const char * str)
{
     int count = 0;
     while(*str)
     {
          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(char *s)
{
   char *p = s;
   while(*p != ‘\0’ )
    {
       p++;
    }
   return p-s;
}

Strcpy

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

  • 源字符串必须以'\0'结束
  • 源字符串中的'\0'也会拷贝到目标空间。
  • 目标空间必须可变、必须足够大,确保能存放源字符串。

strcpy实现

#include <stdio.h>
int main()
{
	char str1[10];
	char str2[] = "abcdef";
	strcpy(str1, str2);
	printf("%s", str1);//abcdef
	return 0;
}

strcpy模拟实现

主要的代码:

char *my_strcpy(char *dest, const char*src)
{ 
    char *ret = dest;
    assert(dest != NULL);
    assert(src != NULL);
    while((*dest++ = *src++))
    {
     ;
    }
    return ret;
}

Strcat

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

  • 源字符串必须以'\0'结束
  • 目标空间必须可修改、必须足够大,能容纳下源字符串的内容。

strcat实现

#include <stdio.h>
int main()
{
	char arr[20] = "I'm a ";
	strcat(arr, "student");
	printf("%s", arr);
	return 0;
}

3897b5bc5e7e4c678d8dda539d5ce9ee.png

strcat模拟实现

主要的代码:

char *my_strcat(char *dest, const char*src)
{
    char *ret = dest;
    assert(dest != NULL);
    assert(src != NULL);
    while(*dest)
    {
        dest++;
    }
    while((*dest++ = *src++))
    {
        ;
    }
    return ret;
}

Strcmp

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

ae6f928a46464845a88622e61f701981.png


strcmp实现

#include <stdio.h>
int main()
{
	char arr1[20] = "abcde";
	char arr2[20] = "abq";
	int ret = strcmp(arr1, arr2);
	printf("%d", ret);//返回小于0的数字
	return 0;
}

strcmp模拟实现

主要的代码:

int my_strcmp (const char * src, const char * dst)
{
    assert(src && dst);
    while(*src == *dst)
    {
        if(*src == '\0')
            return 0;
        src++;
        dst++;
    }
    return *src - *dst;
}

Strncpy

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

  • 拷贝num个字符从源字符串到目标空间。
  • 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后面追加0直到num个

strncpy实现

#include <stdio.h>
int main()
{
	char arr1[20] = "xxxxxxxxxx";
	char arr2[20] = "abqssd";
	strncpy(arr1, arr2, 3);
	printf("%s", arr1);
	return 0;
}

c24f49f2651a497b82579536513ad092.png


Strncat

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


strncat实现

#include <stdio.h>
int main()
{
	char arr1[20] = "abcd";
	strncat(arr1, "efgh", 3);
	printf("%s", arr1);
	return 0;
}
30168cb3d5b24e8d8fdd7622f949f854.png


Strncmp

int strncmp ( const char * str1, const char * str2, size_t cum )

ae6f928a46464845a88622e61f701981.png


strncmp实现

#include <stdio.h>
int main()
{
	char* p1 = "abcd";
	char* p2 = "abcqe";
	int ret = strncmp(p1, p2, 4);
	printf("%d", ret);//返回小于0的数字
	return 0;
}

字符串查找

Strstr

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

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

  • 返回一个指针,这个指针是str2在str1中第一次出现的位置
  • 如果str2不是str1的子集,则返回空指针

strstr实现

#include <stdio.h>
int main()
{
	char arr1[] = "abcbbcde";
	char arr2[] = "bbc";
	char* ret = strstr(arr1, arr2);
	if (ret == NULL)
	{
		printf("找不到\n");
	}
	else
	{
		printf("%s\n", ret);
	}
	return 0;
}

1bf3fc3ec25d41ab8712c7eae4e64bce.png

strstr模拟实现

主要的代码:

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

    return NULL;
}

Strtok

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

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

strtok实现

#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[] = "blog.csdn.net/m0_74173089?type=blog";
	char* p = "./?_=";
	char buf[50] = { 0 };
	strcpy(buf, arr1);
	char* ret = strtok(buf, p);
	printf("%s\n", ret);
	return 0;
}

1de56f5eba534fd7bfcaf07bb7b4ff7b.png

 

连续打印用到for循环

#include <stdio.h>
#include <string.h>
int main()
{
	char arr1[] = "blog.csdn.net/m0_74173089?type=blog";
	char* p = "./?_=";
	char buf[50] = { 0 };
	strcpy(buf, arr1);
	char* ret = NULL;
	for (ret = strtok(buf, p); ret != NULL;ret = strtok(NULL,p))
	{
		printf("%s\n", ret);
	}
	return 0;
}

afb9b804067143d6a8b4cffd8191d0ff.png


Strerror

char * strerror ( int errnum )

返回错误码,所对应的错误信息。

错误码存在一个变量中,这个变量是errno


strerror实现

#include <stdio.h>
#include <string.h>
int main()
{
	printf("%s\n", strerror(0));
	printf("%s\n", strerror(1));
	printf("%s\n", strerror(2));
	printf("%s\n", strerror(3));
	return 0;
}

05f54106fc164e2386eeed343009e1e0.png

我们以读文件为例

#include <stdio.h>
#include <string.h>
int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;
	}

	fclose(pf);
    pf = NULL;
	return 0;
}

436c569757384fa3ad45e15997178ee2.png

 当我们打开不存在的文件时,就会返回一个错误信息

还有一个函数是perror,它可以直接打印错误信息,在打印错误信息前,会先打印自定义的信息

perror可以理解为printf + strerror

#include <stdio.h>
int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}

	fclose(pf);
    pf = NULL;
	return 0;
}

1f67f539f1bd420bb5c0bae27f6d94a6.png


Memcpy

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

  • 函数memcpy从source的位置开始向后复制num字节的数据到destination的内存位置。
  • 这个函数在遇到'\0'的时候不会停下来
  • 如果source和destination有任何的重叠,复制的结果都是未定义的。

memcpy实现

#include <stdio.h>
#include <string.h>
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };
	memcpy(arr2, arr1+2, 20);
	return 0;
}

84311162cb52461ea498a82d0d5eb04f.png

memcpy模拟实现

主要的代码:

void* my_memcpy(void* dest, const void* src, size_t num)
{
	void* ret = dest;
	assert(dest && src);
	while (num--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
        //++(char*)dest;
        //++(char*)src;
	}
	return ret;
}

Memmove

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

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

memmove实现

#include <stdio.h>
#include <string.h>
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr1, arr1+2, 20);
	return 0;
}

f6da0448df5d435c8d2082e2b0932610.png

memmove模拟实现

主要的代码:

void* my_memmove(void* dest, const void* src, size_t num)
{
	void* ret = dest;
	assert(dest && src);
	if (dest < src)
	{
		//前-->后
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		//后-->前
		while (num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
	return ret;
}

Memcmp

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

  • 比较从ptr1和ptr2指针开始的num个字节

ae6f928a46464845a88622e61f701981.png


memcmp实现

#include <stdio.h>
#include <string.h>
int main()
{
	int arr1[] = { 1,2,3 };
	int arr2[] = { 1,2,5 };
	int ret = memcmp(arr1, arr2, 9);
	printf("%d\n", ret);
	return 0;
}

b0a10b6c18c4464ea518deb04cfa8a47.png


Memset

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

  • 字节为单位来设置内存中的数据。

memset实现

#include <stdio.h>
#include <string.h>
int main()
{
	char arr[] = "hello world";
	memset(arr, 'x', 5);
	printf("%s\n", arr);
	return 0;
}

00ae2461880940e087608ef64d2448b3.png


总结

以上就是部分库函数的实现及其模拟,你的支持就是我更新的动力~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值