【C语言学习笔记---字符串函数】

C语言字符串函数

前言:
通过C语言指针进阶的知识,接下来继续学习关于C语言哪些实用的函数呢?

/知识点汇总/
字符串函数分类
1.求字符串长度:strlen
2.长度不受限制的字符串函数:strcpy、strcat、strcmp
3.长度受限制的字符串函数:strncpy、strncat、strncmp
4.字符串查找函数:strstr、strtok
5.错误信息报告函数:strerroe、perror
6.字符分类函数:
iscntrl – 任何控制字符
isspace – 空白字符:‘空格’,换页’\f’,回车’\n’,制表符’\t’.
isdigit — 十进制数字0~9
isxdigit – 十六进制数字 ,包括十进制数字,小写字母af,大写字母AF
islower — 小写字母a~z
isupper — 大写字母A~Z
isalpha – 字母az或AZ
isalnum – 字母或数字 ,az,AZ,0~9
ispunct – 标点符号,任何不属于数字或者字母的图形字符
isgraph – 任何图形字符
7.字符转换函数:
int tolower (int c); — 大写转小写字母
int toupper (int c); — 小写转大写字母
(这里把1~6的函数归纳到字符串函数里讲解)

1、字符串函数

1.1、strlen函数

库函数:用来求字符串长度的库函数,本质上统计的是字符串中’\0’之前的字符个数
原型:size_t strlen( const char *string );
头文件:#include <string.h>

#include <stdio.h>
#include <string.h>
int main()
{
    
    
	size_t len1 = strlen("abcdef");
	//等价,其中传参传递的首元素地址
	const char* str = "abcdef";
	size_t len2 = strlen(str);
	
	printf("%d\n", len1);//6
	printf("%d\n", len2);//6

	//另外得注意,字符串本身就放置了'\0'的情况
	size_t len1 = strlen("abc\0def");
	const char* str = "abc\0def";
	size_t len2 = strlen(str);

	printf("%d\n", len1);//3
	printf("%d\n", len2);//3
	return 0;
}

补充size_t 的特点:

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

int main()
{
    
    
	if (strlen("abc") - strlen("abcdef") > 0)//因为strlen的返回值是无符号数
		//两个无符号数相减得到的依然是无符号数
		//相等于即使相减为负数,但是返回值会约束其符号位无效了,从而成为一个很大的数远远大于0
		printf(">=0\n");
	else
		printf("<=0\n");
	return 0;
}

1.2、strcpy函数

功能:完成字符串的拷贝,将原目标字符串地址拷贝到目标字符串地址。
原型:char *strcpy( char *strDestination, const char *strSource );
头文件:#include <string.h>

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

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

使用strcpy几个注意事项
1.源字符串必须以’\0’结束(因为会包括’\0’一起拷贝过去)
2.会将源字符串中的’\0’拷贝到目标空间
3.目标空间必须足够大,确保能存放源字符串
4.目标空间必须可变(不能是常量)
5.学会模拟实现,才能更好掌握

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

int main()
{
    
    
	char arr1[20] = "xxxxxxxxxxxxxxx";
	//char arr2[] = "hello";
	//char arr2[] = {'A','B','C'};
	char arr2[] = {
    
     'A','B','C','\0'};
	strcpy(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

小结:所以是由程序员决定目标空间必须足够大,且目标空间必须权限为可写

1.3、strcat函数

功能:将源头的字符串地址追加到目标字符串的地址
原型:char *strcat( char *strDestination, const char *strSource );
头文件:<string.h>
执行步骤
1.找到arr1的末尾’\0’
2.再把arr1的内容追加到arr1后边(arr2的首地址会覆盖,arr1的’\0’实现追加)

#include <stdio.h>
#include <string.h>
int main()
{
    
    
	char arr1[20] = "abc";
	char arr2[] = "def";
	strcat(arr1, arr2);
	printf("%s\n", arr1);//abc(追加)def
	return 0;
}

注意事项
1.目标空间足够大
2.目标空间必须有’\0’(保证能找到目标空间的末尾)
3.源字符串也得有’\0’,拷贝时会一通拷贝过去,从而组成新字符串得结束位标志符
4.自己追加自己时,源指针和目标指针都指向首字符,然后源字符串的’\0’,会被覆盖掉,导致后面追加时,找不到’\0’了。尽管库函数能实现,但是不建议

扫描二维码关注公众号,回复: 16975693 查看本文章

1.4、strcmp函数

功能:字符串比较大小(不是比较长度,而是比较对应位置上的字符大小,即ASCII码值)
原型:int strcmp( const char *string1, const char *string2 );
头文件:<string.h>
Return Value
Value Relationship of string1 to string2
//< 0 string1 less than string2
//0 string1 identical to string2
//> 0 string1 greater than string2
标准规定:比较ASCLL码值
1.第一个字符串大于第二个字符串,则返回大于0的数字
2.第一个字符串等于第二个字符串,则返回0
3.第一个字符串小于第二个字符串,则返回小于0的数字

#include <stdio.h>
#include <string.h>
int main()
{
    
    
	char arr1[] = "abcdef";
	char arr2[] = "abq";
	int ret = strcmp(arr1, arr2);
	printf("%d\n", ret);//-1,第一个字符串比第二个字符串小,返回小于零的数值
	return 0;
}

小结
strlen,strcat,strcmp,strcpy属于长度不受限制的字符串函数;
接着介绍长度受限制字符串函数:strncat,strncmp,strncpy

1.5、strncpy函数

功能:字符串拷贝(可指定长度)
原型:char* strncpy(char* strDest, const char* strSource, size_t count);
头文件:<string.h>

#include <stdio.h>
#include <string.h>
int main()
{
    
    
	char arr1[20] = {
    
     0 };
	char arr2[] = "abcdefghi";
	strncpy(arr1, arr2, 3);
	printf("%s\n", arr1);//abc
	char arr1[20] = "xxxxxxxxxxxxxxx";
	char arr2[] = "abcdefghi";
	strncpy(arr1, arr2, 3);
	printf("%s\n", arr1);//abcxxxxxxxxxx
	return 0;
}

探讨拷贝长度的影响

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

int main()
{
    
    
	char arr1[20] = "xxxxxxxxxxxx";
	char arr2[] = "abc";
	strncpy(arr1, arr2, 6);//长度比str2长时,自动补的'\0'.
	printf("%s\n", arr1);//abc\0\0\0
	return 0;
}

1.6、strncat函数

功能:字符串追加(可指定长度)
原型:char* strncat(char* strDest, const char* strSource, size_t count);
头文件:<string.h>

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

int main()
{
    
    
	char arr1[20] = "abc";
	char arr2[] = "defghi";
	strncat(arr1, arr2, 3);//长度比str2长时,自动补的'\0'.
	printf("%s\n", arr1);//abc
	return 0;
}

探究’\0’的追加情况1:

#include <stdio.h>
#include <string.h>
int main()
{
    
    
	char arr1[20] = "abc\0xxxxxxxxxxx";//字符串中本身具备'\0'时,依然以'\0'开始覆盖,最后补'\0'结束
	char arr2[] = "defghi";
	strncat(arr1, arr2, 3);
	printf("%s\n", arr1);//abcdef\0
	return 0;
}

探究’\0’的追加情况2:

#include <stdio.h>
#include <string.h>
int main()
{
    
    
	char arr1[20] = "abc\0xxxxxxxxxxx";//字符串中本身具备'\0'时,依然以'\0'开始覆盖,最后补'\0'结束
	char arr2[] = "defghi";
	strncat(arr1, arr2, 10);//10长度比str2长时,自动在末尾补'\0'.此函数就不会对超出长度的字符进行操作了
	printf("%s\n", arr1);//abcdef
	return 0;
}

1.7、strncmp函数

功能:字符串大小比较(可指定长度)
原型:int strncmp( const char *string1, const char *string2, size_t count );
头文件:<string.h>

#include <stdio.h>
#include <string.h>
int main()
{
    
    
	char arr1[] = "abcdef";
	char arr2[] = "abcqw";
	//int ret = strncmp(arr1, arr2, 3);
	//printf("%d\n", ret);//0

	int ret = strncmp(arr1, arr2, 4);//比较字符串前4个字符
	printf("%d\n", ret);//-1
	return 0;
}

1.8、strstr函数

功能:在字符串中找字符串(字符串中找子字符串或着段),strstr会返回str1中str2第一次出现的位置,如果str1中没有str2,则返回NULL
原型:const char *strstr( const char *string, const char *strCharSet );
头文件:<string.h>

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

int main()
{
    
    
	char arr1[] = "abcdefghi";
	char arr2[] = "def";
	char* ret = strstr(arr1, arr2);
	if (ret == NULL)
	{
    
    
		printf("找不到\n");
	}
	else
	{
    
    
		printf("%s\n", ret);//defghi
	}
	return 0;
}

1.9、strtok函数

功能:常用于切割字符串
原型:char *strtok( char *strToken, const char *strDelimit );
头文件:<string.h>

注意
strtok函数找到str中的下一个标记,并将其用’\0’,结尾返回一个指向这个标记的指针;
strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。
比如
IP地址:本来是一个无符号的整数,这种整数不方便记忆,所以将这个整数转换成点分十进制的表示方式
[email protected] – 分隔符可以是@或 ’ . ’
192.168.101.23 – 分隔符可以是 ’ . ’

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

int main()
{
    
    
	char arr[] = "[email protected]";
	char* p = "@.";
	char* s = strtok(arr, p);//将被标记的地方改为'\0',再把'\0'之前的切分出来。
	printf("%s\n", s);
	return 0;
}

小结:在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改
如下所示,利用一个新数组保存原数组数据:

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

int main()
{
    
    
	char arr[] = "[email protected]";
	char buf[200] = {
    
     0 };
	strcpy(buf, arr);

	char* p = "@.";
	char* s = strtok(buf, p);//将被标记的地方改为'\0',再把'\0'之前的切分出来。
	printf("%s\n", s);

	return 0;
}

小结
strtok函数的第一个参数为NULL,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
如果字符串中不存在更多的标记,则返回NULL指针。

如下所示,每次调用都会保存上次调用的标记(具备记忆功能),依次类推:

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

int main()
{
    
    
	char arr[] = "[email protected]";
	char buf[200] = {
    
     0 };
	strcpy(buf, arr);

	char* p = "@.";
	char* s = strtok(buf, p);//将被标记的地方改为'\0',再把'\0'之前的切分出来。
	printf("%s\n", s);

	s = strtok(NULL, p);
	printf("%s\n", s);

	s = strtok(NULL, p);
	printf("%s\n", s);
	return 0;
}

为了代码的实用性,以循环的方式依次识别标记,对代码进行优化

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

int main()
{
    
    
	char arr[] = "[email protected]";
	char buf[200] = {
    
     0 };
	strcpy(buf, arr);

	char arr2[] = "192.168.101.23";
	char buf2[200] = {
    
     0 };
	strcpy(buf2, arr2);

	char* p = "@.";
	char* s = NULL;
	for (s = strtok(buf, p); s != NULL; s = strtok(NULL, p))
	{
    
    
		printf("%s\n", s);
	}

	char* p2 = ".";
	for (s = strtok(buf2, p2); s != NULL; s = strtok(NULL, p2))
	{
    
    
		printf("%s\n", s);
	}
	return 0;
}

小结
1.strtok函数找到str中的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针。
2.strtok函数的第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置
3.strtok函数的第一个参数为NULL,函数将在同一个字符串中将被保存的位置开始,查找下一个标记。
4.如果字符串中不存在更多的标记,则返回标记为NULL指针

1.10、strerror函数

功能:是将错误码翻译成错误信息,返回错误信息的字符串的起始地址
原型:char *strerror( int errnum );
头文件:<string.h>

错误码比如常见网页打不开显示:-404-
C语言中使用库函数的时候,如果发生错误,就会将错误码放在errno的变量中,errno是一个全局变量,可以直接使用的

#include <stdio.h>
#include <string.h>
int main()
{
    
    
	int i = 0;
	for (i = 0; i < 10; i++)
	{
    
    
		printf("%d: %s\n", i, strerror(i));
	}
	return 0;
}

strerror函数常用于文件的操作判定
以打开文件的例子展示:
fopen以读的形式打开文件,如果文件存在,打开成功;如果文件不存在,打开失败。

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

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

对比perroe函数
原型:void perror( const char *string );
功能:直接打印错误码,所对应的错误信息(先打印自定义信息:xxx,再直接打印错误原因)
等价:perror == printf + strerror

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

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

2、字符分类函数

字符分类函数:
iscntrl – 任何控制字符
isspace – 空白字符:‘空格’,换页’\f’,回车’\n’,制表符’\t’…
较常用:
isdigit — 十进制数字0~9
isxdigit – 十六进制数字 ,包括十进制数字,小写字母af,大写字母AF
islower — 小写字母a~z
isupper — 大写字母A~Z
isalpha – 字母az或AZ
isalnum – 字母或数字 ,az,AZ,0~9
ispunct – 标点符号,任何不属于数字或者字母的图形字符
isgraph – 任何图形字符

这里以常见的为例

2.1、islower函数

原型:int iswlower( wint_t c );
头文件:<ctype.h>
功能:判断字符是否为小写字母,如果为小写,则返回非零的值;如果不是小写,则返回0

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

int main()
{
    
    
	char ch = 'a';
	if (islower(ch))
	{
    
    
		printf("是小写\n");
	}
	else
	{
    
    
		printf("不是小写\n");
	}
	return 0;
}

2.2、isdigit 和 isxdight函数

原型:int isdigit( int c );
头文件:<ctype.h>
功能:判断字符是否为十进制数字0~9

原型:int isxdigit( int c );
头文件:<ctype.h>
功能:判断字符是否为十六进制数字 ,包括十进制数字,小写字母af,大写字母AF

#include <stdio.h>
#include <ctype.h>
int main()
{
    
    
	//if(ch >= 'a' && ch <= 'z')
	int ret = islower('a');
	printf("%d\n", ret);

	int ret2 = isdigit('5');
	printf("%d\n", ret2);

	int ret3 = isxdigit('c');
	printf("%d\n", ret3);
	return 0;
}

2.3、islower 和 isupper函数

原型:int islower( int c );
头文件:<ctype.h>
功能:判断字符是否为小写字母a~z

原型:int isupper( int c );
头文件:<ctype.h>
功能:判断字符是否为大写字母A~Z

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

int main()
{
    
    
	char ch1 = 'A';
	char ch2 = 'a';
	if(islower(ch2))
		printf("小写字母:%c\n",ch2);
	if(islower(ch1))
		printf("大写字母:%c\n",ch1);
	return 0;
}

3、字符转换函数

C语言只有两个字符转换函数:tolower 、toupper

3.1、tolower函数

原型:int tolower( int c );
头文件:<ctype.h>
功能:将大写字母转换为小写字母

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

int main()
{
    
    
	char arr[] = "TEST String.";
	char* p = arr;
	while (*p)
	{
    
    
		if (isupper(*p))
		{
    
    
			*p = tolower(*p);
		}
		p++;
	}
	printf("%s\n", arr);
	return 0;
}

3.2、toupper函数

原型:int toupper( int c );
头文件:<ctype.h>
功能:将小写字母转换为大写字母

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

int main()
{
    
    
	int ret = tolower('A');
	printf("%c\n", ret);//a

	int ret2 = toupper('a');
	printf("%c\n", ret2);//A

	int ret3 = tolower('A');
	printf("%c\n", ret3);//a
	ret3 = toupper(ret3);
	printf("%c\n", ret3);//A
	return 0;
}

4、结语

熟悉各个函数的使用有利于程序的可读性和效率,此篇笔记有误的地方请多多指教。
半亩方糖一鉴开,天光云影共徘徊。
问渠哪得清如许?为有源头活水来。–朱熹(观书有感)

猜你喜欢

转载自blog.csdn.net/m0_69455439/article/details/133209161