字符和字符串库函数的介绍与模拟实现

目录

前言

一、函数介绍与模拟实现

1.1 strlen

1.2 strcpy

 1.3 strcat

 1.4 strcmp

1.5 strncpy

 1.6 strncat

1.7 strncmp

1.8 strstr

1.9 strtok

1.10 strerror

二、 内存操作函数的介绍与模拟实现

2.1 memcpy

 2.2 memmove

2.3 memcmp

2.4 memset


前言

本篇文章介绍字符函数与字符串函数,以及模拟实现其中的功能。

C语言当中本身是没有字符串类型的,字符串通常放在常量字符串或者字符数组中,字符串常量适用于对其不做修改的字符串函数。


一、函数介绍与模拟实现

1.1 strlen

size_t   strlen ( const char * str );

参数指向的字符串以  '\0'  结束,strlen函数返回字符串中  '\0'  前的字符个数,其返回值类型是无符号的size_t

以下是对strlen函数的模拟实现

size_t my_strlen(const char* str)
{
	size_t count = 0;
	while (*str++ != '\0')
	{
		count++;
	}
	return count;
}

int main()
{
	char arr[] = "hello strlen";
	size_t sz= my_strlen(arr);
	printf("%d", sz);

	return 0;
}

1.2 strcpy

char* strcpy ( char * destination , const char * source );
//目标字符串可变,源字符串不可变

源字符串source必须以 '\0' 结束,会将源字符串中的 '\0' 拷贝到目标空间,目标空间必须足够大来存放源字符串

通过arr2数组数据监视,strcpy函数将 '\0' 拷贝到目标字符串中。

以下是对strcpy的模拟实现

char* my_strcpy(char* dest, const char* src)
{
	char* ret = dest;
	while (*dest++ = *src++)
	{

	}
	return ret;
}


int main()
{
	char arr1[] = "hello world";
	char arr2[20] =  "xxxxxxxxxxxxxxxxxxxx";
	my_strcpy(arr2, arr1);
	printf(arr2);
}

对arr2空间监视发现模拟实现了strcpy的功能

 1.3 strcat

char * strcat ( char * destination , const char * source );
strcat函数是将源字符串追加到目标字符串后。
源字符串必须以 '\0' 结束。 目标空间必须有足够的大,能容纳下源字符串的内容。字符串不能给自己追加

以下是模拟实现strcat函数

char* my_strcat(char* dest, char* src)
{
	char* ret = dest;
	while (*dest)
	{
		dest++;
	}
	while (*dest++ = *src++)
	{

	}
	return ret;
}

int main()
{
	char arr1[] = "hello world";
	char arr2[20] =  "xxxxx";
	my_strcat(arr2, arr1);
	printf(arr2);
}

对arr2监视,发现成功实现追加

 1.4 strcmp

int strcmp ( const char * str1 , const char * str2 );
第一个字符串大于第二个字符串,则返回大于 0 的数字
第一个字符串等于第二个字符串,则返回 0
第一个字符串小于第二个字符串,则返回小于 0 的数字

下面是对strcmp的模拟实现

int  my_strcmp(const char* str1, const char* str2)
{
	int ret = 0;
	while (!(ret = (*(unsigned char*)str1 - *(unsigned char*)str2)) && *str1)
	{
		str1++;
		str2++;
	}
	if (ret < 0)
	{
		return -1;
	}
	else if (ret > 0)
	{
		return 1;
	}
	return 0;
}

int main()
{
	char arr1[] = "hello world";
	char arr2[] = "hello world";
	int ret=my_strcmp(arr1, arr2);
	printf("%d", ret);
	return 0;
}

1.5 strncpy

char * strncpy ( char * destination , const char * source , size_t num );
拷贝 num 个字符从源字符串到目标空间。
如果源字符串的长度小于 num ,则拷贝完源字符串之后,在目标的后边追加 0 ,直到 num 个。
以下是对strncpy的模拟实现
char* my_strncpy(char* dest, char* sour, size_t num)
{
	char ret = dest;
	while (num)
	{
		if (*dest++ = *sour++)
		{
			num--;
		}
		else
		{
			*dest ++= '\0';
			num--;
		}
	}
	return ret;
}

int main()
{
	char arr1[] = "helloggh";
	char arr2[] = "world";
	my_strncpy(arr1, arr2, 7);
	return 0;
}

以下是对arr1的监控

 1.6 strncat

char * strncat ( char * destination , const char * source , size_t num );
将源字符串的第一个num字符附加到目标字符串中,再加上一个终止的空字符。如果源字符串中的C字符串的长度小于num,则只复制直到终止的空字符的内容。
以下是对strncat的模拟实现
char* my_strncat(char* dest, char* src, size_t num)
{
	char* ret = dest;
	while (*dest)
	{
		dest++;
	}
	while (num--)
	{
		if (*dest = *src)
		{
			dest++;
			src++;
		}
		else
		{
			break;
		}
	}
	return ret;
}

int main()
{
	char arr1[20] = "hello ";
	char arr2[] = "world";
	my_strncat(arr1, arr2,5);
	printf(arr1);
	return 0;
}

1.7 strncmp

int strncmp ( const char * str1 , const char * str2 , size_t num );
比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。
具体实现与strcmp的模拟实现类似,只需改动while循环条件即可
while (!(ret = (*(unsigned char*)str1 - *(unsigned char*)str2)) && *str1&&num)
	{
		str1++;
		str2++;
		num--;
	}

1.8 strstr

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

返回一个指向str1中第一次出现的str2的指针,或者如果str2不是str1的一部分,则返回一个空指针。

1.9 strtok

char * strtok ( char * str , const char * sep );
sep 参数是个字符串,定义了用作分隔符的字符集合 。
第一个参数指定一个字符串,它包含了 0 个或者多个由 sep 字符串中一个或者多个分隔符分割的标
记。

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

#include <stdio.h>
#include <string.h>
int main()
{
	char str[] = "- This, a sample string.";
	char* pch;
	printf("拆分字符串 \"%s\":\n", str);
	pch = strtok(str, " ,.-");
	while (pch != NULL)
	{
		printf("%s\n", pch);
		pch = strtok(NULL, " ,.-");
	}
	return 0;
}

运行结果为

1.10 strerror

char * strerror ( int errnum );

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

#include <errno.h>              //必须包含的头文件

printf ( "Error opening file unexist.ent: %s\n" , strerror ( errno ));
   //errno: Last error number

二、 内存操作函数的介绍与模拟实现

2.1 memcpy

void * memcpy ( void * destination , const void * source , size_t num );=
函数 memcpy source 的位置开始向后复制 num 个字节的数据到 destination 的内存位置。
这个函数在遇到 '\0' 的时候并不会停下来。
如果 source destination的内存位置 有任何的重叠,复制的结果都是未定义的。
下面是对其的模拟实现

#include<stdio.h>

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

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8 };
	int arr2[10] = { 0 };
	my_memcpy(arr2, arr, 32);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

通过对arr2内存的监控发现对应字节的数据以及被替换

 2.2 memmove

void * memmove ( void * destination , const void * source , size_t num );
memcpy 的差别就是 memmove 函数处理的源内存块和目标内存块是可以重叠的。
如果源空间和目标空间出现重叠,就得使用 memmove 函数处理。

以下是对memmove的模拟实现

void* my_memmove(void* dest, void* src, size_t num)
{
	void* ret = dest;
	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;
}

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr, arr + 2, 16);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

 将从arr+2开始的16个字节的数据,也就是4个整形数据:3,4,5,6复制到从arr开始的位置

预计结果为 3,4,5,6,5,6,7,8,9,10

通过对arr地址内存监控得到成功复制了数据

2.3 memcmp

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

 比较从ptr1ptr2指针开始的num个字节

返回值小于0表示两个内存块中不匹配得第一个字节ptr1的值比ptr2的值低

返回值等于0表示两个内存块内容相等

返回值大于0表示两个内存块中不匹配得第一个字节ptr1的值大于ptr2的值

2.4 memset

void * memset ( void *str, int c, size_t num );

复制字符 c(一个无符号字符)到参数 str 所指向的字符串的前 n 个字符。

用以下代码测试功能

int main()
{
    int arr[10] = { 0 };
    memset(arr, 1, 12);
    return 0;
}

 通过对arr内存监控得

替换了12个字节,也就是3个整形。 

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值