字符串函数

目录

一:strlen --- 求字符串长度

1.简介

 2.注意

 3.模拟实现

 二:strcpy --- 字符串拷贝

 1.简介

  2.注意

3.模拟实现

 三:strcat --- 字符串追加

 1.简介

2.注意

3.模拟实现

 四:strcmp --- 字符串比较

1.简介

2.注意

3.模拟实现

 五:strncpy --- 将指定长度的字符串复制到字符数组中

1.简介

2.注意

3.模拟实现

六:strncat --- 在末尾追加指定大小的字符串

1.简介

2.注意

3.模拟实现

七:strncmp --- 指定大小,字符串比较

1.简介

2.注意

3.模拟实现

八:strstr --- 判断字串

 1.简介

2.模拟实现

九:strtok --- 分解字符串为一组字符串

1.简介

2.注意

3.示例

 十:strerror --- 对应错误信息

 1.简介

2.注意


一:strlen --- 求字符串长度

1.简介

 2.注意

<1>:字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包 含 '\0' )。

 <2>:参数指向的字符串必须要以 '\0' 结束。

 <3>:注意函数的返回值为size_t,是无符号的。

 判断下述代码的输出结果:

#include<stdio.h>
int main()
{
	if (strlen("abc") - strlen("abcde"))
	{
		printf(">\n");
	}
	else
	{
		printf("<=\n");
	}
	return 0;
}

 

 解:

strlen("abc") 的值为3

strlen("abcde")的值为5

strlen函数的返回值为size_t,是无符号的

3 - 5 = -2 (无符号数) 会转化为一个很大的正数,所以输出结果为 > 

 3.模拟实现

1.计数器

2.递归

3.指针 - 指针

//模拟实现 strlen 函数
#include<stdio.h>

//计数器
int my_strlen1(char* arr)
{
	int count = 0;//计数器
	while (*arr != '\0')
	{
		arr++;
		count++;
	}
	return count;
}

//递归
int my_strlen2(char* p)
{
	if (*p != '\0')
	{
		return 1 + my_strlen2(p + 1);
	}
	else
	{
		return 0;
	}
}

//指针 - 指针
int my_strlen3(char* pa)
{
	char* ret = pa;//保存pa的初始位置
	while (*pa != '\0')
	{
		pa++;
	}
	return pa - ret;
}

int main()
{
	char arr[] = "abcdefgh";
	//计数器
	int ret1 = my_strlen1(arr);
	//递归
	int ret2 = my_strlen2(arr);
	//指针 - 指针
	int ret3 = my_strlen3(arr);

	printf("%d\n", ret1);
	printf("%d\n", ret2);
	printf("%d\n", ret3);
	return 0;
}

 二:strcpy --- 字符串拷贝

 1.简介

char *strcpy( char *strDestination, const char *strSource );

//                               目标空间                源字符串

把源字符串拷贝到目标空间中去

  2.注意

<1>:源字符串必须以 '\0' 结束。

 

<2>:会将源字符串中的 '\0' 拷贝到目标空间。 

 <3>:目标空间必须足够大,以确保能存放源字符串。

需要拷贝 abc ,但是只给了 2 个空间,会引发异常。

 <4>:目标空间必须可变。

常量字符串不可以被修改。

3.模拟实现

#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* p1, const char* p2)
//源字符串不发生变化
{
	assert(p1 && p2);
	char* ret = p1;
	/*while (*p2 != '\0')
	{
		*p1 = *p2;
		p1++;
		p2++;
	}
	*p1 = *p2;*/
	while (*p1++ = *p2++)
	{
		;
	}
	return ret;
	//返回的是目标空间的起始地址
}
int main()
{
	char arr1[10] = "abcdxxxxxx";
	char arr2[] = "qwerty";

	my_strcpy(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

 

 三:strcat --- 字符串追加

 1.简介

char *strcat( char *strDestination, const char *strSource );

//                        目标字符串                     源字符串

把源字符串追加在目标字符串的末尾

2.注意

<1>:源字符串必须以 '\0' 结束。

 

 

由上述可知,字符串追加时从 目标字符串的'\0' 开始追加 ,覆盖 '\0' , 后续追加。

 字符串追加时,以源字符串的 '\0' 作为结尾。

<2>:目标空间必须有足够的大,能容纳下源字符串的内容。

 

<3>:目标空间必须可修改。

 <4>:strcat 不可以自己追加自己。

 '\0' 会被覆盖掉

3.模拟实现

#include<stdio.h>
#include<assert.h>
char* my_strcat(char* p1, const char* p2)
{
	char* ret = p1;
	assert(p1 && p2);
	//找目标空间中的第一个 '\0'
	while (*p1 != '\0')
	{
		p1++;
	}
	//拷贝
	while (*p1++ = *p2++)
	{
		;
	}
	return ret;
}
int main()
{
	char arr1[20] = "Hello ";
	char arr2[] = "World";
	my_strcat(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

 四:strcmp --- 字符串比较

1.简介

比较两个字符串的内容,不能使用等号,要使用 strcmp 函数。

int strcmp( const char *string1, const char *string2 );

对应的字符进行比较(ASCII码值)

2.注意

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

a b c d e

a b c q

         d < q  ---- 返回一个小于0的数字

3.模拟实现

//模拟实现 strcmp
#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* p1, const char* p2)
//字符串进行比较时,不会发生变化,可加上 const 更加安全稳固
{
	assert(p1 && p2);
	while (*p1 == *p2)//当两个相等时,位于 while 循环内
	{
		if (*p1 == '\0')
		{
			return 0;
		}
		p1++;
		p2++;
	}
	/*if (*p1 > *p2)
	{
		return 1;
	}
	else
	{
		return -1;
	}*/
	return *p1 - *p2;//等价于,上述 if else
}
int main()
{
	char arr1[] = "abcde";
	char arr2[] = "abcq";

	int ret = my_strcmp(arr1, arr2);
	printf("%d\n", ret);
	return 0;
}

 

 五:strncpy --- 将指定长度的字符串复制到字符数组中

1.简介

将指定字节的源字符串拷贝到目标字符串中

char *strncpy( char *strDest, const char *strSource, size_t count );

//                       目标字符串               源字符串                   字节

2.注意

<1>:拷贝num个字符从源字符串到目标空间。

 

 

 <2>:如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。

例下:arr2 有4个,但拷贝了7个

 

3.模拟实现

//模拟实现
#include<stdio.h>
#include<assert.h>
char* my_strncpy(char* p1, const char* p2, size_t count)
{
	assert(p1 && p2);
	char* ret = p1;
	/*while (count--)
	{
		*p1++ = *p2++;
	}
	*/
	while (count && (*p1++ = *p2++))//拷贝字符串
	{
		count--;
	}
	if (count)//当 count 大于 p2 的长度时,将补充 '\0'
	{
		while (--count)
		{
			*p1++ = '\0';
		}
	}
	return ret;
}
int main()
{ 
	char arr1[] = "abcd";
	char arr2[] = "qwer";
	my_strncpy(arr1, arr2, 1);
	printf("%s\n", arr1);
	return 0;
}

 

六:strncat --- 在末尾追加指定大小的字符串

1.简介

char *strncat( char *strDest, const char *strSource, size_t count );

2.注意

<1>:拷贝num个字符从源字符串到目标空间。

 

<2>:如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个

 

 

3.模拟实现

//模拟实现
#include<stdio.h>
#include<assert.h>
char* my_strncat(char* p1, const char* p2, size_t count)
{
	char* ret = p1;
	assert(p1 && p2);
	while (*p1 != '\0')
	{
		p1++;
	}
	while (count && (*p1++ = *p2++) != '\0')
	{
		count--;
	}	
	*p1 = '\0';//字符串追加需要加上一个 '\0'
	return ret;
}
int main()
{
	char arr1[10] = "abcd";
	char arr2[] = "efgh";
	my_strncat(arr1, arr2, 2);
	printf("%s\n", arr1);
	return 0;
}

七:strncmp --- 指定大小,字符串比较

1.简介

int strncmp( const char *string1, const char *string2, size_t count );

2.注意

比较到出现另个字符不一样或者一个字符串结束或者num个字符全部比较完。

 

3.模拟实现

//模拟实现
#include<stdio.h>
#include<assert.h>
int my_strncmp(const char* p1, const char* p2, size_t count)
//给定字符串长度进行比较时,不会发生改变
{
	assert(p1 && p2);
	while (count-- && (*p1 == *p2) &&(*p1 !='\0') &&(*p2 != '\0'))
	{
		p1++;
		p2++;
		if (count == 0)
		{
			return 0;
		}
	}
	if (*p1 > *p2)
	{
		return 1;
	}
	else
	{
		return -1;
	}
}
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abcb";
	char arr3[] = "bac";

	int ret1 = my_strncmp(arr1, arr2, 3);
	int ret2 = my_strncmp(arr1, arr2, 4);
	int ret3 = my_strncmp(arr1, arr3, 2);

	printf("%d\n", ret1);
	printf("%d\n", ret2);
	printf("%d\n", ret3);
	return 0;
}

 

八:strstr --- 判断字串

 1.简介

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

strstr(arr1,arr2)判断字符串 arr2 是否为 arr1 的字串
// 若是,则函数返回 str1 字符串从 arr2 第一次出现的位置开始到 str1 结尾的字符串
// 若不是,返回 NULL --- 空指针

2.模拟实现

//模拟实现
#include<stdio.h>
#include<assert.h>
char* my_strstr(const char* p1, const char* p2)
{
	assert(p1 && p2);
	char* s1 = p1;
	char* s2 = p2;
	char* ret = p1;//返回的是找到的起始地址
    //char* ret = (char*)p1;//更稳固
	while (*ret != '\0')
	{
		s1 = ret;
		s2 = p2;
     //s2 = (char*)p2;//同上述 ret
		while ((*s1 != '\0') && (*s2 != '\0') && (*s1 == *s2))
	//  当 s1 / s2 为 \0 时,表示可以停下来        两者相等
		{
			s1++;
			s2++;
		}
		//*s1 != *s2 时,若 *s2 == '\0',说明,arr2 已经被查找完毕
		if (*s2 == '\0')
		{
			return ret;
		}
		ret++;//如果 s1 和 s2 不相等 
	}
	return NULL;
}
int main()
{
	char arr1[] = "abcdefg";
	char arr2[] = "def";
	
	char* ret = my_strstr(arr1, arr2);
	if (ret == NULL)
	{
		printf("找不到\n");
	}
	else
	{
		printf("%s\n", ret);
	}
	return 0;
}

 

九:strtok --- 分解字符串为一组字符串

1.简介

char * strtok ( char * str, const char * sep );
//                       字符串       分隔符的集合
//"Hello ?World !Hi"
// ? ! ---- 分割符
//"192.168.121"
// . --- 分割符

2.注意

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

3.示例

 

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "Hello ?World !Hi";
	char arr[20] = { 0 };//为了保留源数据
	strcpy(arr, arr1);//将 arr1 的数据保留到 arr 中去
	const char* ret = "!?";
	//const --- 限制 ret ,不可被修改

	printf("%s\n", strtok(arr, ret));
	printf("%s\n", strtok(NULL, ret));
	printf("%s\n", strtok(NULL, ret));

	return 0;
}

 

 进行优化 --- 后续可以直接添加,不需要增补代码。

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "Hello ?World !Hi?asd";
	char arr[40] = { 0 };//为了保留源数据
	strcpy(arr, arr1);//将 arr1 的数据保留到 arr 中去
	const char* ret = "!?";
	char* str = NULL;

	for (str = strtok(arr, ret); str != NULL; str = strtok(NULL, ret))
	{
		printf("%s\n", str);
	}
	return 0;
}

 十:strerror --- 对应错误信息

 1.简介

2.注意

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

 

 C语言的库函数在调用失败的时候,会将一个错误码存放在:errno 的变量中

当我们想知道调用库函数的时候发生了什么错误信息,就可以将 errno 中的错误码翻译成错误信息。

errno 的头文件为 #include<errno.h>

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值