字符串函数及其模拟实现

strlen

函数介绍

函数介绍:
字符串以’\0’作为结束标志,strlen函数返回的是在字符串中’\0’前面出现的字符个数(不包含’\0’)。
参数指向的字符串必须要以’\0’ 结束。
注意函数的返回值为size_t,是无符号的

模拟实现

计数方式:

int my_strlen(const char* str)//const修饰且在*左边,保证指向的内容不被改变
{
	int count = 0;
	assert(str);
	while (*str)
	{
		count++;
		str++;
	}
	return count;
}

不创建变量方式(递归方式)

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

指针 - 指针方式

int my_strlen(char* s)
{
	assert(str);
	char* p = s;
	while (*p != '\0')
		p++;
	return p - s;
}

strcpy

函数介绍

char* strcpy(char * destination, const char * source )
实现字符串拷贝,左参数是目标字符串的首地址,右参数是源字符串的首地址。
注意:
源字符串必须以‘ \0 ’ 结束。
strcpy会将源字符串的‘ \0 ’拷贝到目标空间中。
目标空间足够大,以确保能存放源字符串。
目标空间必须可变。

如果目标空间不够大,那么就会造成非法写入,然后报错。
拷贝的方法就是从源字符串的第一个字符开始一直到‘ \0 ’,如果源字符串的末尾没有以0结尾,就会一直读取,一直到0,这样就会非法访问。

模拟实现

方式1

void my_strcpy(char* str, const char* src)
{
	assert(str && src);
	while (*src)
	{
		*str = *src;
		str++;
		src++;
	}
	*str = *src;
}

方式2,将方式1中while循环里面简化、

void my_strcpy(char* str, const char* src)
{
	assert(str && src);
	while (*str++ = *src++);
}

后置++,先使用再进行加操作,就算加了括号也是先使用再进行加操作。返回当前值,就是一直到str等于0的时候才停止循环。

方式3,增加返回值

char* my_strcpy(char* str, const char* src)
{
	char* ret = str;
	assert(str && src);
	while (*str++ = *src++);
	return ret;
}

strcat

函数介绍

char * strcat ( char * destination, const char * source )
字符串追加函数,在目标字符串后面追加源字符串,目标字符串的最后一个‘ \0 ’,被源字符串的第一个字符占据,追加完成以后会再新增一个‘ \0 ’。
注意:
源字符串必须以‘ \0 ’结束
目标字符串中也得有‘ \0 ’,否则没办法知道追加从哪里开始。
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改。

模拟实现

char* my_strcat(char* str, const char* src)
{
	char* ret = str;
	assert(str);
	assert(src);
	/*while (*str++ != '\0');在str等于0后要退出判断条件,此时会再进行一次加操作,后置加加不会因为要退出循环就不执行。
	str--;*/
	while (*str != '\0')
	{
		str++;
	}
	while (*str++ = *src++);
	return ret;
}

我们自己写的函数是无法自己给自己追加的,因为‘ \0 ’,被覆盖了,永远都不会遇到‘ \0 ’。但是库函数strcat可以 ,但是尽量不要这样使用,可以使用strncat来给自己追加。

strcmp

函数介绍

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

比较规则是按照字典序比较的,如果是大小写的话就按照ASCII码值比较。ASCII码值大,那么字符串中的字符就大。如果一个字符串结束,另一个字符串就和‘ \0 ’,比较,此时就是‘ \0 ’小。

模拟实现

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

strncpy

函数介绍

char * strncpy ( char * destination, const char * source, size_t num )
前两个参数和strcpy是一个意思,第三个参数是要拷贝的数量
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
如果字符串大于num,就拷贝num个,不补‘ \0 ’。

模拟实现

char* my_strncpy(char* str, const char* src, int num)
{
	char* ret = str;
	assert(str&& src);
	while (*str = *src)
	{
		str++;
		src++;
		num--;
		if (num == 0)
			break;
	}
	while (num)
	{
		*str = '\0';
		str++;
		num--;
	}
	return ret;
}

strncat

函数介绍

char * strncat ( char * destination, const char * source, size_t num )
指定在目标字符串后面追加多少个。
追加后补‘ \0 ’。
如果源字符串不够长,有多少个追加多少个。

模拟实现

char* my_strcat(char* str, const char* src, int num)
{
	char* ret = str;
	assert(str);
	assert(src);
	while (*str != '\0')
	{
		str++;
	}
	while (*str++ = *src++)
	{
		num--;
		if (num == 0)
		{
			*str = '\0';
			break;
		}
	}
	return ret;
}

strncmp

函数介绍

int strncmp ( const char * str1, const char * str2, size_t num )
比较前n个字符,返回值与strcmp相同。

模拟实现

int my_strncmp(const char* str, const char* src, int num)
{
	assert(str && src);
	while (*str == *src)
	{
		num--;
		if (*str == '\0' || num <= 0)
			return 0;
		str++;
		src++;
	}
	return *str - *src;
}

strtok

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

int main()
{
	char arr[] = "zhangsan@qq.com.cn";
	char temp = { 0 };
	temp = strcpy(temp, arr);
	char* sep = ".@";
	char* str = NULL;
	for (str = strtok(arr, temp); str != NULL; str = strtok(NULL, temp))
	{
		printf("%s\n", str);
	}
	return 0;
}

strstr

函数介绍

const char * strstr ( const char * str1, const char * str2 )
在字符串中找字串,在str1中找str2
返回str2字符串在str1中第一次出现的第一个字符的地址,找不到就返回NULL。

模拟实现

char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	const char* cp = str1;
	const char* s1 = NULL;
	const char* s2 = NULL;
	if (*str2 == '\0')//如果字符串是空
		return str1;
	while (*cp)
	{
		s1 = cp;
		s2 = str2;
		while (*s1 == *s2 && *s2 && *s1)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
			return cp;
		cp++;
	}
	return NULL;
}

strerror

strerror函数可以把参数部分错误码对应的错误信息的字符串地址返回来。
使用strerror需要包含<string.h>

在C语言库函数中设计一些错误码,当我们库函数在调用的过程中发生了各种错误,要记录下来,这时候记录的就是错误码。
在这里插入图片描述

当库函数调用失败的时候会将错误码记录到errno这个变量当中,如过要使用这个变量需要引用<errno.h>这个头文件。
errno是一个C语言的全局变量。

比如我们打开一个文件,不存在那么打开失败,就会把失败的错误码存在errno里面

int main()
{
	FILE* pf = fopen("add.txt", "r");
	if (pf == NULL)
	{
		printf("打开文件失败,原因:%s\n", strerror(errno));
		return 1;
	}
	else
	{
		printf("打开文件成功\n");
	}
	return 0;
}

在这里插入图片描述

perror

perror直接打印错误码所对应的信息,并且会打印参数,然后加一个冒号一个空格。
相当于printf和strerror(errno)的一个组合功能。

int main()
{
	FILE* pf = fopen("add.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	else
	{
		printf("打开文件成功\n");
	}
	return 0;
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值