C语言——常用字符串库函数的介绍

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

文章目录

常用字符串库函数介绍

以下函数的使用均需要包含头文件<string.h>

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

1.1关于字符串简介

在C语言中对字符串的处理是十分频繁的。但是C语言本身是没有字符串类型的通常字符串被存放在字符数组常量字符串中。唯一标识字符串的结束标志是**‘\0’**字符。

补充常量字符串通常存放在内存中的文字常量区内常量字符串的内容不可以被修改。

1.2:strlen库函数

1.2.1strlen函数的功能

strlen函数是用来获取’\0’字符前字符的个数即求字符串的长度。

1.2.2strlen函数的参数和返回类型

size_t strlen(const char* str);

通过查阅文档可知该函数的参数为 const char* str。即一个const修饰字符指针变量该字符指针变量的指向内容不可以被修改。该函数返回值为size_t类型。也就是无符号整型即unsigned int类型。

1.2.3strlen函数使用注意事项

注意事项
1、字符串以’\0’作为结束标识参数指向的字符串必须以’\0’作为结束标识。
2、返回值size_t为无符号整数

1.2.4strlen的使用

下面我通过一个简单的例子使用库函数strlen求一个字符串的长度。

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

int main()
{
	//创建一个字符数组str1
	char str1[] = "abcde";
	//创建一个字符指针pc
	//pc指向常量字符串xyz首字符的地址	
	char* pc = "xyz";
	//创建临时变量存放strlen函数的返回值
	size_t ret1 = strlen(str1);
	size_t ret2 = strlen(pc);
	//打印返回值验证结果
	printf("%u\n" ,ret1);
	printf("%u\n", ret2);
	return 0;
}

在这里插入图片描述

根据之前对于函数章节的学习也可以通过函数的链式访问来进行对于strlen函数的使用代码例子如下。

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

int main()
{
	//创建一个字符数组str1
	char str1[] = "abcde";
	//创建一个字符指针pc
	//pc指向常量字符串xyz首字符的地址	
	char* pc = "xyz";
	//通过函数链式访问打印返回值验证结果
	printf("%u\n" ,strlen(str1));
	printf("%u\n", strlen(pc));

	return 0;
}

在这里插入图片描述

补充打印无符号整数的占位符为%u当前在作者所使用的vs2019中x86环境下%d格式打印编译器并不会警告但是这不意味着%d打印格式就是没有问题的。从语法角度来看%u打印格式才是正确合理的。

1.2.5模拟实现strlen函数

方法一计数器方法

实现思路创建一个临时变量来记录’\0’字符前的字符个数。通过while循环来进行解引用后的字符判断只要解引用访问的字符不是’\0’就让指针向后移动同时计数器+1。
在这里插入图片描述

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

size_t my_strlen(const char* str)
{
	//断言判断指针有效性
	assert(str != NULL);
	//创建临时变量count记录字符串的长度
	size_t count = 0;
	//当*str == '\0'时结束循环
	//'\0'的ASCII值为0
	//在C语言中0为假非0为真
	while(*str)
	{
		count++;
		str++;
	}
	return count;
}

int main()
{
	char str1[] = "abcd";
	printf("%u\n",my_strlen(str1));
	return 0;
}

在这里插入图片描述

方法二指针运算

实现思路创建一个临时指针变量存放字符串的起始地址然后循环遍历字符串内容当指针解引用访问后得到的字符为’\0’循环停止。通过指针减去指针得到指针间的元素个数从而得到字符串的长度。
在这里插入图片描述

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

size_t my_strlen(const char* str)
{
	//断言判断指针有效性
	assert(str);
	//const修饰sta使左右类型匹配
	const char* sta = str;
	
	while (*str)
	{
		str++;
	}
	//指针-指针返回'\0'前元素个数
	return str - sta;
}

int main()
{
	char* pc = "abcdef";
	size_t ret = my_strlen(pc);
	printf("%u\n",ret);
	return 0;
}

在这里插入图片描述

方法三递归

实现思路将字符串结束标志’\0’作为递归终止条件判断str指针解引用访问的字符内容当str指针解引用访问内容不为’\0’,递推使返回值+1并且调用函数体自身参数为str指针+1。当*str == ‘\0’递推终止进行回归返回字符串长度。
在这里插入图片描述

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

size_t my_strlen(const char* str)
{
	//断言判断指针有效性
	assert(str);
	if(*str == '\0')
		return 0;
	else
		return 1 + my_strlen(str+1);
}

int main()
{
	char* pc = "abc";
	size_t ret = my_strlen(pc);
	printf("%u\n",ret);
	return 0;
}

在这里插入图片描述

1.3:strcpy库函数

1.3.1strcpy函数功能

将源头字符串的内容拷贝到目标字符串当中包含’\0’字符。

1.3.2strcpy函数的参数和返回类型

char* strcpy(char* destination, const char* source);

该函数的返回类型是char* 类型即字符指针变量返回的目标空间的起始地址。该函数的参数有两个分别是char* destination即字符指针变量该指针变量存放的是目标字符串的字符地址。const char* source const修饰过的字符指针变量该指针变量的所指向的内容不可以被修改。该指针变量存放的是拷贝源字符串的内容的字符地址。

1.3.5strcpy函数的使用注意事项

注意事项
1、源头字符串必须以’\0’结尾若没有’\0’作为结束标志strcpy就不知道什么时候停止拷贝
2、源头字符串的’\0’会被拷贝到目标字符串中。
3、目标字符串的空间必须足够大否则会造成越界访问。
4、目标字符串必须可修改不能被const修饰

1.3.4strcpy函数的使用

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

int main()
{
	char str1[20]={0};
	char str2[] = "abcdef";
	//将str2的内容拷贝到str1中
	strcpy(str1,str2);
	printf("%s\n", str1);
	return 0;
}

在这里插入图片描述

1.3.5模拟实现strcpy函数

实现思路创建指针变量存放目标字符串的起始地址通过循环将源头字符串中的内容赋给目标字符串直到将’\0’赋给目标字符串后循环终止返回目标字符串的地址。

char* my_strcpy(char* dest, const char* src)
{
	//断言判断指针合法性
	assert(dest && src);
	//记录目标地址
	char* ret = dest;
	//当*dest为'\0'时循环结束,拷贝停止
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}

int main()
{
	char str1[20] = { 0 };
	char str2[] = "hello world";
	//将str2的内容拷贝到str1中
	my_strcpy(str1, str2);
	printf("%s\n", str1);
	return 0;
}

在这里插入图片描述

1.4:strcat库函数

1.4.1strcat函数的功能

将源头字符串的内容追加到目标字符串。

1.4.2strcat函数的返回类型和参数

char* strcat(char* destination, const char* source);

这里的返回类型和参数跟strcpy一模一样这里我就不多做赘述。

1.4.3strcat函数的使用注意事项

注意事项
1、源头字符串从目标字符串的’\0’处开始追加。
2、目标字符串的大小必须确保能够放的下源头字符串。
3、源头字符串必须以’\0’结束且会将源头字符串的’\0’拷贝到目标空间中。
4、目标字符串必须可修改未被const修饰

1.4.4strcat函数的使用

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

int main()
{
	char str1[20] = "abc";
	char str2[] = "def";
	//将str2追加到str1中
	strcat(str1,str2);
	printf("%s\n", str1);
	return 0;
}

在这里插入图片描述

1.4.5模拟实现strcat函数

实现思路先创建临时指针变量存放起始位置的地址然后遍历目标字符串直到目标字符串的指向空间内容为’\0’最后追加源字符串到目标字符串中。返回目标字符串的地址。

char* my_strcat(char* dest, const char* src)
{
	assert(dest && src);
	//记录目标字符串起始位置
	char* ret = dest;
	//判断dest指针指向的内容是否为'\0'
	//不为*dest != '\0',指针++
	while (*dest)
	{
		dest++;
	}
	//追加字符串实现过程和字符串拷贝一样
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}

int main()
{
	char str1[20] = "hello ";
	char str2[] = "world";
	//将str2追加到str1中
	my_strcat(str1, str2);
	printf("%s\n", str1);
	return 0;
}

在这里插入图片描述

1.5:strcmp库函数

1.5.1strcmp函数的功能

用于比较两个字符串的大。

1.5.2strcmp函数的返回类型和参数

int strcmp ( const char * str1, const char * str2 );

函数的返回类型为整型函数的参数为两个被const修饰的字符指针变量。

1.5.3strcmp函数的使用注意事项

注意事项
1、两个字符比较其实比较的是两个字符在内存中存储的ASCII码值。
2、当第一个字符串大于第二个字符串时返回一个大于0的整数。
3、当第一个字符串等于第二个字符串时返回一个等于0的整数。
4、当第一个字符串小于第二个字符串时返回一个小于0的整数。

1.5.4strcmp函数的使用

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

int main()
{
	char str1[] = "abc";
	char str2[] = "abc";
	//存放strcmp函数的返回值
	int ret = strcmp(str1, str2);
	if(ret > 0)//根据返回值判断字符串大小
		printf("str1 > str2\n");
	else if(ret < 0)
		printf("str1 < str2\n");
	else
		printf("str1 == str2\n");
	return 0;
}

在这里插入图片描述

1.5.5模拟实现库函数strcmp

实现思路通过解引用操作访问两个指针指向的内容进行比较当两个指针变量解引用访问的值相等则两个指针偏移一个字节继续向后访问若碰到’\0’或者指针解引用访问的值不相等则返回一个整数。
在这里插入图片描述

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

int my_strcmp(const char* str1, const char* str2)
{
	int ret = 0;
	//断言判断指针有效性
	assert(str1 && str2);
	//循环判断两个字符是否相等
	while(*str1 == *str2)
	{
		if(str1 == '\0')
			return 0;
		str1++;
		str2++;
	}
	return *str1 - *str2;
}

int main()
{
	char str1[] = "abc";
	char str2[] = "abd";
	int ret = my_strcmp(str1,str2);
	
	if(ret > 0)//根据返回值判断字符串大小
		printf("str1 > str2\n");
	else if(ret < 0)
		printf("str1 < str2\n");
	else
		printf("str1 == str2\n");
	return 0;
}

在这里插入图片描述

由于不受长度限制的字符串库函数使用起来相对受长度限制的字符串库函数来说比较的不安全所以C语言标准库中也提供了受长度限制的库函数。这里我就举三个常用的例子

1.6strncat库函数

1.6.1strncat函数的功能

追加n个字节的源头字符串到目标字符串后

1.6.2strncat的返回类型和参数

char * strncat ( char * destination, const char * source, size_t num );

函数返回的依旧是目标字符串的起始地址。参数部分额外多了一个参数size_t num即拷贝的字符个数。

1.6.3strncat的使用注意事项

注意事项
1、将源头字符串的起始位置起num个字符的内容追加到目标字符串的’\0’处
2、如果源头字符串的长度小于num那么只追加源头字符串到其’\0’处。

1.6.4strncat的使用

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

int main()
{
	char str1[20] = "abcde";
	char str2[] = "fghijk";
	strncat(str1,str2,3);
	printf("%s\n", str1);
	return 0;
}

在这里插入图片描述

1.6.5模拟实现库函数strncat

实现思路先创建临时指针变量存放起始位置的地址然后遍历目标字符串直到目标字符串的指向空间内容为’\0’最后追加num个字符的源字符串到目标字符串中。返回目标字符串的地址。

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

char* my_strncat(char* dest, const char* src, size_t num)
{
	//记录目标字符串起始位置
	char* ret = dest;
	//断言判断指针有效性
	assert(dest && src);
	//先遍历目标字符串使指针变量dest指向'\0'
	while(*dest)
	{
		dest++;`在这里插入代码片`
	}
	//通过num控制追加的字节数
	while(num--)
	{
		//追加字符串(同拷贝字符串)
		*(dest+num) = *(src+num);
	}
	return ret;
}

int main()
{
	char str1[20] = "abcde";
	char str2[] = "fghijk";
	
	printf("%s\n", my_strncat(str1,str2,4));
	return 0;
}

在这里插入图片描述

1.7strncpy库函数

1.7.1strncpy函数的功能

拷贝num个字符的源头字符串内容到目标字符串中。

1.7.2strncpy函数的返回类型和参数

char * strncpy ( char * destination, const char * source, size_t num );

返回类型依旧是目标字符串的起始位置。参数方面前俩个参数不变第三个参数为num个字符的空间。

1.7.3strncpy函数的使用注意事项

注意事项
1、将源头字符串的第一个字符数复制到目标字符串中。如果在复制 num 个字符之前找到源 头字符串的末尾由 ‘\0’ 字符表示则目标将填充0直到总共写入 num 个字符为止。
2、如果源字符串的长度超过 num则不会在目标字符串末尾附加’\0’字符。因此在这种情况下不应将目标字符串视为以’\0’结尾的字符串这样读取它会溢出。
3、目标字符串和源头字符串不得重叠有关重叠时更安全的替代方案请参见 Memmove。

1.7.4strncpy函数的使用

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

int main()
{
	char str1[20] = {0};
	char* pc = "hello world";
	strncpy(str1, pc, 11);
	printf("%s\n", str1);
	return 0;
}

在这里插入图片描述

1.7.5模拟实现库函数strncpy

设计思路创建指针变量存放目标字符串的起始地址通过循环将num个源头字符串中的字符赋给目标字符串当赋完num个字符时循环终止返回目标字符串的地址。

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

char* my_strncpy(char* dest, const char* src, size_t num)
{
	char* ret = dest;
	assert(dest && src);
	//拷贝num个字符
	while (num--)
	{
		//将源头字符串字符拷贝到目标字符串中
		*(dest + num) = *(src + num);
	}
	return ret;
}

int main()
{
	char str1[20] = { 0 };
	char* pc = "hello world";
	printf("%s\n", my_strncpy(str1, pc, 3));
	return 0;
}

在这里插入图片描述

1.8strncmp库函数

1.8.1strncmp函数的功能

比较两个字符串的n个字符的ASCII码值大小

1.8.2strncmp函数的返回类型和参数

int strncmp ( const char * str1, const char * str2, size_t num );

strncmp函数的前两个参数是需要进行比较的两个字符串第三个是比较的字符个数num是几就比较几个字符。

1.8.3strncmp函数的使用注意事项

注意事项
1、比较字符串str1和字符串str2的最多num个字符。
2、这个函数开始比较每个字符串的第一个字符。如果它们彼此相等则继续处理下面的对直到字符不同直到到达一个’\0’字符或直到两个字符串中num字符匹配以先发生的为准。

1.8.4strncmp函数的使用

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

int main()
{
	char str1[] = "abcd";
	char str2[] = "abcq";
	int ret = strncmp(str1, str2, 3);
	printf("%d\n", ret);
	return 0;
}

在这里插入图片描述

1.8.5模拟实现strncmp函数

实现思路通过num来控制循环变量判断两个两个字符串每个字符的内容是否相等循环结束后返回最终两个字符的差。

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

int my_strncmp(const char* str1, const char* str2, size_t num)
{
	assert(str1 && str2);
	//num控制循环次数
	while (num--)
	{
		//比较两个字符
		if (*str1 == *str2)
		{
			str1++;
			str2++;
		}
	}
	return *str1 - *str2;
}

int main()
{
	char str1[] = "abcd";
	char str2[] = "abcq";
	int ret = strncmp(str1, str2, 4);
	printf("%d\n", ret);
	return 0;
}

在这里插入图片描述

1.8strstr库函数

1.8.1strstr函数的功能

查找字符串中的字符串并返回子字符串的起始地址

1.8.2strstr函数的返回类型和参数

const char * strstr ( const char * str1, const char * str2 );
char * strstr (       char * str1, const char * str2 );

返回类型为子字符串的起始地址当子字符串不存在时返回一个空指针。参数str1为被查找的字符串参数str2为需要查找的字符串。

1.8.3strstr函数的使用注意事项

注意事项
strstr函数匹配子字符串的过程是不包含’\0’的但是查找的字符串已是’\0’那么函数便停止查找并返回子字符串起始地址。

1.8.4strstr函数的使用

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

int main()
{
	char str1[] = "abbbcde";
	char str2[] = "bbc";
	printf("%s\n", strstr(str1, str2));
	return 0;
}

在这里插入图片描述

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

int main()
{
	char str1[] = "abbbcde";
	char str2[] = "be";
	printf("%s\n", strstr(str1, str2));
	return 0;
}

在这里插入图片描述

1.8.5模拟实现strstr函数

实现思路首先需要两个指针变量s1和s2指向两个字符串的起始地址。再创建一个临时指针变量cp来记录str2在str1中首次出现的位置。当str2传进来是空字符串‘\0’时直接返回str1的起始地址。通过循环来遍历两个字符串。当cp指针指向的内容为’\0’时循环结束内循环判断 *s1 是否与 *s2 相等。若 *s2 == '\0’则返回cp指针即记录str2在str1中首次出现的地址。若循环结束还未匹配则返回NULL即空指针。
在这里插入图片描述

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

const char* my_strstr(const char* str1, const char* str2)
{
	const char* s1 = NULL;
	const char* s2 = NULL;
	const char* cp = str1;

	assert(str1 && str2);

	if (*str2 == '\0')
		return str1;

	//子字符串匹配条件
	while (*cp)
	{
		s1 = cp;
		s2 = str2;
		//只有s1 == s2且都不为'\0'此时匹配是否为子字符串
		while ((*s1 != '\0') && (*s2 != '\0') && (*s1 == *s2))
		{
			s1++;
			s2++;
		}
		//子字符串匹配成功
		if (*s2 == '\0')
			return cp;
		cp++;
	}
	//未查找到子字符串
	return NULL;
}

int main()
{
	const char str1[] = "abbbcde";
	const char str2[] = "bbc";
	const char str3[] = "abbbcde";
	const char str4[] = "be";
	printf("%s\n", my_strstr(str1, str2));
	printf("%s\n", my_strstr(str3, str4));
	return 0;
}

在这里插入图片描述

1.9strtok库函数

1.9.1strtok函数的功能

根据分割符字符串分割指定字符串的内容如给定待分割字符串str1[] = “zhangsan@qq.com”给定分割符字符串str2[] = “@.”。此时调用strtok(str1,str2);函数将会把str1中含有分隔符字符串的位置覆盖成’\0’并返回切割后各个子串首字符的地址。

1.9.2strtok函数的返回类型和参数

char * strtok ( char * str, const char * delimiters );

strtok函数的返回类型是字符指针指针中存放的是分割后各个子串的地址。strtok函数的参数是两个字符指针第一个是用来存放待分割的字符串地址第二个是用来存放分割符的集合地址。

1.9.3strtok函数的使用注意事项

注意事项
1、strtok函数会改变被操作的字符串所以在使用strtok函数切分的字符串一般都是临时拷贝的内容 并且可修改。
2、若strtok函数的第一个参数不为 NULL 函数将找到字符串中第一个标记strtok函数将保存它在字符串中的位置。
3、strtok函数的第一个参数为 NULL 函数将在同一个字符串中被保存的位置开始查找下一个标记。
4、如果字符串中不存在更多的标记则返回 NULL 指针。

1.9.4strtok函数的使用

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

int main()
{ 
	char str1[] = "zhangsan@qq.com";
	char str2[50] = { 0 };
	char del[] = "@.";
	//用于控制循环并存放strtok函数的返回值
	char* ret = NULL;
	strcpy(str2, str1);
	//循环打印分割后的字符串
	for (ret = strtok(str2, del); ret != NULL; ret = strtok(NULL, del))
	{
		printf("%s ",ret);
	}
	printf("\n");
	return 0;
}

在这里插入图片描述

1.10strerror库函数

1.10.1strerror函数的功能

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

1.10.2strerror函数的返回类型和参数

char * strerror ( int errnum );

strerror函数的返回类型是char* 的指针变量该指针变量存放的是所对应的错误信息的首字符地址。函数的参数为错误信息码即errno全局变量。

1.10.3strerror函数的使用注意事项

注意事项
使用errno全局变量需要引相应的头文件<errno.h>。

1.10.4strerror函数的使用

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

int main()
{
	//打开文件
	FILE* pf = fopen("test.text","r");
	if (NULL == pf)
	{
		printf("%s\n",strerror(errno));
		return 1;
	}
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

在这里插入图片描述

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6