• 【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

    #include 
    #include 
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    补充size_t 的特点:

    #include 
    #include 
    
    int main()
    {
    	if (strlen("abc") - strlen("abcdef") > 0)//因为strlen的返回值是无符号数
    		//两个无符号数相减得到的依然是无符号数
    		//相等于即使相减为负数,但是返回值会约束其符号位无效了,从而成为一个很大的数远远大于0
    		printf(">=0\n");
    	else
    		printf("<=0\n");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    1.2、strcpy函数

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

    #include 
    #include 
    
    int main()
    {
    	char arr1[20] = { 0 };
    	char arr2[] = "hello";
    	strcpy(arr1, arr2);
    	printf("%s\n", arr1);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

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

    #include 
    #include 
    
    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

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

    1.3、strcat函数

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

    #include 
    #include 
    int main()
    {
    	char arr1[20] = "abc";
    	char arr2[] = "def";
    	strcat(arr1, arr2);
    	printf("%s\n", arr1);//abc(追加)def
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

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

    1.4、strcmp函数

    功能:字符串比较大小(不是比较长度,而是比较对应位置上的字符大小,即ASCII码值)
    原型:int strcmp( const char *string1, const char *string2 );
    头文件
    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 
    #include 
    int main()
    {
    	char arr1[] = "abcdef";
    	char arr2[] = "abq";
    	int ret = strcmp(arr1, arr2);
    	printf("%d\n", ret);//-1,第一个字符串比第二个字符串小,返回小于零的数值
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

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

    1.5、strncpy函数

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

    #include 
    #include 
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    探讨拷贝长度的影响

    #include 
    #include 
    
    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    1.6、strncat函数

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

    #include 
    #include 
    
    int main()
    {
    	char arr1[20] = "abc";
    	char arr2[] = "defghi";
    	strncat(arr1, arr2, 3);//长度比str2长时,自动补的'\0'.
    	printf("%s\n", arr1);//abc
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

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

    #include 
    #include 
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

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

    #include 
    #include 
    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    1.7、strncmp函数

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

    #include 
    #include 
    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    1.8、strstr函数

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

    #include 
    #include 
    
    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    1.9、strtok函数

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

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

    #include 
    #include 
    
    int main()
    {
    	char arr[] = "abcdef@yeah.net";
    	char* p = "@.";
    	char* s = strtok(arr, p);//将被标记的地方改为'\0',再把'\0'之前的切分出来。
    	printf("%s\n", s);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

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

    #include 
    #include 
    
    int main()
    {
    	char arr[] = "abcdef@yeah.net";
    	char buf[200] = { 0 };
    	strcpy(buf, arr);
    
    	char* p = "@.";
    	char* s = strtok(buf, p);//将被标记的地方改为'\0',再把'\0'之前的切分出来。
    	printf("%s\n", s);
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

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

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

    #include 
    #include 
    
    int main()
    {
    	char arr[] = "abcdef@yeah.net";
    	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;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

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

    #include 
    #include 
    
    int main()
    {
    	char arr[] = "abcdef@yeah.net";
    	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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

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

    1.10、strerror函数

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

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

    #include 
    #include 
    int main()
    {
    	int i = 0;
    	for (i = 0; i < 10; i++)
    	{
    		printf("%d: %s\n", i, strerror(i));
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

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

    #include 
    #include 
    
    int main()
    {
    	FILE* pf = fopen("add.txt", "r");
    	if (pf == NULL)
    	{
    		printf("打开文件失败,原因是:%s\n",strerror(errno));
    		return 1;
    	}
    	else
    	{
    		printf("打开文件成功\n");
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

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

    #include 
    #include 
    
    int main()
    {
    	FILE* pf = fopen("add.txt", "r");
    	if (pf == NULL)
    	{
    		perror("打开文件失败");
    		return 1;
    	}
    	else
    	{
    		printf("打开文件成功\n");
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    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 );
    头文件
    功能:判断字符是否为小写字母,如果为小写,则返回非零的值;如果不是小写,则返回0

    #include 
    #include 
    
    int main()
    {
    	char ch = 'a';
    	if (islower(ch))
    	{
    		printf("是小写\n");
    	}
    	else
    	{
    		printf("不是小写\n");
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2.2、isdigit 和 isxdight函数

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

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

    #include 
    #include 
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2.3、islower 和 isupper函数

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

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

    #include 
    #include 
    
    int main()
    {
    	char ch1 = 'A';
    	char ch2 = 'a';
    	if(islower(ch2))
    		printf("小写字母:%c\n",ch2);
    	if(islower(ch1))
    		printf("大写字母:%c\n",ch1);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    3、字符转换函数

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

    3.1、tolower函数

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

    #include 
    #include 
    
    int main()
    {
    	char arr[] = "TEST String.";
    	char* p = arr;
    	while (*p)
    	{
    		if (isupper(*p))
    		{
    			*p = tolower(*p);
    		}
    		p++;
    	}
    	printf("%s\n", arr);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    3.2、toupper函数

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

    #include 
    #include 
    
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    4、结语

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

  • 相关阅读:
    codery-why蘑菇街商城项目梳理笔记
    uni-app:文本超出部分用省略号表示
    C++ web httpserver
    js学习笔记
    论文阅读-Whisper语音识别(OpenAI)
    2023年中国负极材料分类、产量及市场规模分析[图]
    MYSQL——命令大全
    Kamiya丨Kamiya艾美捷抗FLAG多克隆说明书
    基于冠状病毒群体免疫算法优化概率神经网络PNN的分类预测 - 附代码
    MySQL密码不要用0开头!!!
  • 原文地址:https://blog.csdn.net/m0_69455439/article/details/133209161