深度剖析字符(串)函数

1、字符串函数介绍

strlen() //求字符串长度
//长度不受限制的字符串函数
strcpy() 
strcat() 
strcmp() 
//长度受限制的字符串函数
strncpy() 
strncat() 
strncmp() 
//字符串查找
strstr() 
strtok() 
//错误信息报告
strerror() 
//字符操作

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

2、库函数介绍及模拟实现

2.1 strlen

所需头文件:#include<string.h>。
解释:string length:字符串长度
作用:求字符串长度,统计的是字符串中**‘\0’*之前出现的字符个数。
原型:size_t strlen (const char
str);
size_t 本质是unsigned int 无符号整型(在vs编辑器中被定义为无符号整型)。

strlen()函数使用:

#include<stdio.h>
#include<string.h>

int main()
{
	char arr[] = "abcdef";
	printf("%d\n",strlen(arr));
	return 0;
}

模拟实现strlen函数
思路:
在这里插入图片描述
代码:

#include<stdio.h>
#include<assert.h>

size_t my_strlen(const char* str)
{
	assert(str);
	const char* start = str;
	const char* end = str;
	while(*end != '\0')
	{
		end++;
	}
	return end - start;
}

int main()
{
	char arr[] = "abcdef";
	int len = my_strlen(arr);
	printf("%d\n",len);
	return 0;
}
  • const权限问题:提升指针所指空间数据的健壮性。
  • 字符串以’\0’作为结束标志,strlen函数返回的是在字符串中’\0’前面出现的字符个数(不包含’\0’)。
  • 参数指向的字符串必须要以’\0’结束。
  • 函数的返回值为size_t,是无符号的。
  • 一个汉字占两个字符。

2.2 strcpy

所需头文件:#include<string.h>。
原型:char * strcpy (char * destination, const char * source);
作用:字符串拷贝
参数(传参)描述:目的地(destination)和源头(source),将源头拷贝到目的地。

strcpy函数使用:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[10] = {0};
	const char* p = "abcdef";
	strcpy(arr,p);
	printf("%s\n",arr);
	return 0;
}

模拟实现strcpy函数
思路:
在这里插入图片描述
代码:

#include<stdio.h>
#include<assert.h>

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

int main()
{
	char arr1[20] = "abc";
	char arr2[] = "hello world";
	printf("%s\n",my_strcpy(arr1,arr2));
	return 0;
}
  • 源字符串必须以‘\0’结束。
  • 会将源字符串中的’\0’拷贝到目标空间。
  • 目标空间必须足够大,以确保能存放源字符串(避免发生内存空间越界)。
  • 常量字符串不可修改(目标空间应当是可修改的)。

2.3 strcat

所需头文件:#include<string.h>。
原型:char * strcat( char * destination, const char * source);
作用:字符串追加
参数(传参)描述:目的地(destination)和源头(source),将源头(数据)追加到目的地数据后方。

strcat函数使用:

#include<stdio.h>
#include<string.h>

int main()
{
	char arr1[20] = "hello ";
	char arr2[] = "world";
	strcat(arr1,arr2);
	printf("%s\n",arr1);
	return 0;
}

模拟实现strcat函数
思路:
在这里插入图片描述
代码:

#include<stdio.h>

char* my_strcat(char* dest,const char* src)
{
	char* cur = dest;
	while(*cur)
	{
		cur++;
	}
	while(*cur++ = *src++)
	{
		;
	}
	return dest;
}

int main()
{
	char arr1[20] = "hello ";
	char arr2[] = "world";
	printf("%s\n",my_strcat(arr1,arr2));
	return 0;
}
  • 从’目的地里的\0’开始进行追加,结束于源字符串的’\0’ 源字符串必须以’\0’结束。
  • 目标空间必须能够容纳下源字符串的内容。
  • 目标空间必须可修改。
  • 无法完成自己给自己追加的操作(单一字符串的结束标志’\0’已经被覆盖)。

2.4 strcmp

所需头文件:#include<string.h>。
作用:字符串比较(比较对应位置上字符的的大小而非长度)。
原型:int strcmp ( const char * str1, const char * str2);

strcmp函数使用:

#include<stdio.h>
#include<string.h>

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abg";
	
	int ret = strcmp(arr1,arr2);
	if(ret < 0)
		printf("arr1<arr2\n");
	else if(ret>0)
		printf("arr1>arr2\n");
	else
		printf("arr1==arr2");
	printf("%d\n",ret);
	return 0; 
}

模拟实现strcmp函数
思路:
在这里插入图片描述
代码:

#include<stdio.h>
#include<assert.h>

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

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abg";
	
	int ret = my_strcmp(arr1,arr2);
	if(ret < 0)
		printf("arr1<arr2\n");
	else if(ret>0)
		printf("arr1>arr2\n");
	else
		printf("arr1==arr2");
	printf("%d\n",ret);
	return 0; 
}

标准规定:

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

2.5 strncpy

所需头文件:#include<string.h>。
原型:char * strncpy ( char * destination, const char * source, size_t num);
作用:有限字符个数的字符串拷贝

strncpy函数使用:

#include<stdio.h>
#include<string.h>

int main()
{
	char arr1[20] = "abcdef";
	char arr2[] = "xxxxx";
	strncpy(arr1,arr2,3);
	printf("%s\n",arr1);
	return 0;
}
  • 从源字符串拷贝num个字符到目标空间。
  • 如果源字符串的长度小于num,拷贝完源字符串后,在目标的后边追加0,直到num个。

2.6 strncat

所需头文件:#include<string.h>。
原型:char * strcat ( char * destination, const char * source,size_t num);
作用:有限字符个数的字符串追加

strncat函数使用:

#include<stdio.h>
#include<string.h>

int main()
{
	char arr1[20] = "abcdef";
	char arr2[] = "xyz";
	strncat(arr1,arr2);
	printf("%s\n",arr1);
	return 0;
}
  • 无论追加几个字符都应加’\0’作为结束标志。
  • 可以自己给自己追加(限制字符个数)。

2.7 strncmp

所需头文件:#include<string.h>。
原型: int strncmp ( const char * str1, const char * str2,size_t num);
作用:有限字符个数的字符串比较(比较对应位置上字符的的大小而非长度)。

strncmp函数使用:

#include<stdio.h>

int main()
{
	int ret = strncmp("abcdef","abc",4);
	printf("%d\n",ret);
}
  • 比较到出现两个字符不一样或者一个字符串结束或者num个字符全部比完。

2.8 strstr

所需头文件:#include<string.h>。
原型:char * strstr ( const char * str1, const char * str2);;
作用:在一个字符串中找另一个字符串是否存在。若存在,返回字串第一次出现的地址;不存在,返回NULL。

strstr函数使用:

#include<stdio.h>

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "bcd";
	char * p =strstr(arr1,arr2);
	if(p=NULL)
	{
		printf("不存在\n");
	} 
	else
	{
		printf("%s\n",p);
	}
	return 0;
}

模拟实现strstr函数
思路:
在这里插入图片描述
代码:

#include<stdio.h>

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

int main()
{
	char arr1[] = "abcdefabcdef";
	char arr2[] = "cde";
	char * p = my_strstr(arr1,arr2);
	if(p==NULL)
	{
		printf("不存在\n");
	} 
	else
	{
		printf("%s\n",p);
	}
	return 0;
}

2.9 strtok

所需头文件:#include<string.h>。
原型:char * strtok ( char * str, const char *sep );
作用:以分割符作为划分线切将字符串进行切割。
参数:sep参数是个字符串,定义了用作分隔符的字符集合;str参数指定一个字符串,包含了0个或多个由sep字符串中一个或多个分隔符分割的标记。
在传NULL值时,strtok函数会使用记忆(保存)功能,获取对应地址。
strtok函数找到str中的下一个标记,并将其用’\0’结尾,返回一个指向这个标记的指针。

strtok函数使用:

#include<stdio.h>

int main()
{
	char arr[] = "abcdef@123.com"
	char buf[200] = {0};//由于strtok函数在使用中会修改源字符串,所以在使用时尽量修改拷贝后的内容(视情况而定)
	strcpy(buf,arr);
	const char* p = "@.";
	char* str = NULL;
	for(str=strtok(buf,p);str!=NULL;str=strtok(NULL,p))
	{
		printf("%d",str);
	}
	return 0;
}

2.10 strerror

所需头文件:#include<errno.h>。
原型:char * strerror ( int errnum );
作用:把错误码转换成错误信息。
调用库函数出错时,就会把错误码记录到errno变量里。errno是C语言提供的全局的错误变量
perror函数原型:void perror ( const char * str);
perror可以看作printf加上strerror后的结果。 perror打印的依然是errno变量中的错误码对应的错误信息。

strerror函数使用:

#include<stdio.h>
#include<error.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;
}
#include<stdio.h>
#include<errno.h>

int main()
{
	FILE* pf = fopen("test.txt","r");
	if(pf == NULL)
	{
		perror("fopen自定义命名");
		return 1;
	}
	fclose(pf);
	pf = NULL;
	return 0;
}

3、字符分类函数

//字符分类
//任何控制字符
iscntrl()
//空白字符:空格' ',换页'\f',换行'\n',回车'\r',制表符'\t'或者垂直制表符'
'\v'
isspace()
//十进制数字0-9
isdigit()
//十六进制数字,包括所有十进制数字,小写字母a-f,大写字母A-F
isxdigit()
//小写字母a-z
islower()
//大写字母A-Z
isupper()
//字母a-z或A-Z
isalpha()
//字母或者数字,a-z,A-Z,0-9
isalnum()
//标点符号,任何不属于数字或者字母的图形字符(可打印)
ipunct()
//任何图形字符
isgraph()
//任何可打印字符,包括图形字符和空白字符
isprint()
//字符转换
//大写字母转小写
tolower()
//小写字母转大写
toupper()

3.1部分函数具体使用:

#include<stdio.h>
#include<ctype.h>

int main()
{
	char ch = "a";
	//非对应输出字符打印0
	int ret = isdigit(ch);
	int ret1 = isxdigit(ch);
	int ret3 = islower(ch);
	printf("%d",ret);//输出ASCII码值
	return 0;
}
#include<stdio.h>
#include<ctype.h>

int main()
{
	char arr[] = "Are you ok?";
	char* p = arr;
	while(*p){
		if(islower(*p)){
			*p = toupper(*p);
		}
		p++;
	}
	printf("%s\n",arr);
	return 0;
}
  • ch本身不会改变,改变的是它的返回值。

总结:熟练掌握库函数,可以统一代码,省略大量冗余代码,编写代码时很方便。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

捌音

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值