C语言字符串库函数的详解和模拟实现第二弹(字符串查找基础)

目录

一. 前言

二. 查找一个字符

2.1 库函数strchr

2.1.1 strchr的函数原型及实现的功能

2.1.2 strchr的使用方法演示

2.1.3 strchr的模拟实现

2.2 库函数strrchr

2.2.1 strrchr的函数原型及可以实现的功能

2.2.2 strrchr的使用方法演示

 2.2.3 strrchr的模拟实现

三.  查找任何几个字符

3.1 strpbrk函数

3.1.1 strpbrk的函数原型和实现的功能

3.1.2 strpbrk函数使用方法的演示

3.1.3 strpbrk的模拟实现

四. 查找一个子字符串

4.1 strstr函数

4.1.1 strstr的函数原型及实现的功能

4.1.2 strstr函数的使用方法演示

4.1.3 strstr函数的模拟实现

五. 查找一个字符串的前缀 

5.1 strspn函数

5.1.1 strspn的函数原型及实现的功能

5.1.2 strspn函数的使用方法演示

5.1.3 strspn函数的模拟实现

5.2 strcspn函数

5.2.1 strcpn的函数原型及实现的功能

5.2.2 strcspn的使用方法演示

5.2.3 strcspn函数的模拟实现

六. 查找字符串中的标记

6.1 strtok函数

6.1.1 strtok的函数实现的功能及函数原型

6.1.2 strtok的使用方法演示

6.1.3 strtok函数的模拟实现


一. 前言

C语言在标准库中提供了标准的字符串操作函数,可用于查找字符串中的字符、子字符串等。这给程序员提供了很大的便利,并且有利于提高程序的可移植性。本文对C语言标准库中提供的常见字符串查找相关函数进行了解读,并进行了模拟实现。

二. 查找一个字符

2.1 库函数strchr

2.1.1 strchr的函数原型及实现的功能

函数原型:char *strchr( const char *string, int c );

函数功能:在字符串string中查找一个字符c,并返回指向第一次出现c的位置的指针,如果字符串string中没有字符c,那么就返回空指针NULL。

函数参数:

  • string:被查找的字符串
  • c:想要在字符串中查找的字符,这里c采用int型是因为字符本质上是其对应的ASCII码值,字符型变量也属于整型家族。int型变量长度为4字节,char型为1字节,因此使用int型变量接受char型变量完全没有问题。

使用库函数strchr要引用头文件

2.1.2 strchr的使用方法演示

代码段2.1在字符串 arr1[ ] = "abcdeccf"中查找第一次出现字符'c'的位置,程序运行的结果:cdeccf

代码段2.1:

#include
#include
int main()
{
	char arr1[] = "abcdeccf";
	char* ret = strchr(arr1, 'c');
	printf("%s\n", ret); //cdeccf
	return 0;
}

2.1.3 strchr的模拟实现

strchr的模拟实现代码:

char* my_strchr(const char* str, int c)
{
	assert(str); //指针有效性检验
	while (*str != '\0')
	{
		if (c == *str)  //查找到c就返回c的位置
		{
			return str;
		}
		str++;
	}
	return NULL; //找不到c就返回NULL
}

2.2 库函数strrchr

2.2.1 strrchr的函数原型及可以实现的功能

函数原型:char *strrchr( const char *string, int c );

函数功能:在字符串string中查找字符c最后一次出现的位置

函数参数:

  • string:被查找的字符串
  • c:期望在string中查找的字符

函数的返回值:若在string中查找到c,则返回c最后一次出现的位置,若没有查找到c,就返回空指针NULL。

2.2.2 strrchr的使用方法演示

代码段2.2实现的功能是在字符串arr1[]="abcdeccf"中查找字符c最后一次出现的位置,程序运行的结果为:cf

代码段2.2:

int main()
{
	char arr1[] = "abcdeccf";
	char* ret = strrchr(arr1, 'c');
	printf("%s\n", ret); //cf
	return 0;
}

 2.2.3 strrchr的模拟实现

模拟实现代码:

char* my_strrchr(const char* str, int c)
{
	assert(str);
	char* ret = NULL; //初始化返回值为NULL
	while (*str != '\0')
	{
		if (c == *str)  //在str中遇到c就将其位置暂时存入ret
		{
			ret = str;
		}
		str++;
	}
	return ret;
}

三.  查找任何几个字符

3.1 strpbrk函数

3.1.1 strpbrk的函数原型和实现的功能

函数原型:char *strpbrk( const char *string, const char *strCharSet );

函数功能:在字符串string中查找第一次出现strCharSet字符串中任何一个字符的位置。

函数参数:string是被查找的字符串,strCharSet为期望在string中查找的字符的集合

函数返回值:若在string中查找到了strCharSet中任意一个字符,则返回指向第一次出现这个字符的位置的指针,若找不到这样的一个字符,则返回空指针NULL。

3.1.2 strpbrk函数使用方法的演示

代码段3在arr1中寻找第一次出现group字符串中任意一个元素的位置,程序运行的结果为:deccf

代码段3.1: 

int main()
{
	char arr1[] = "abcdeccf";
	char group[] = "dhj"; 
	char* ret = strpbrk(arr1, group);
	printf("%s\n", ret); //deccf
	return 0;
}

3.1.3 strpbrk的模拟实现

模拟实现代码:

char* my_strpbrk(const char* str, const char* group)
{
	assert(str && group);  //指针有效性检验
	while (*str != '\0')
	{
		//调用库函数strchr,再group中查找*str,若不返回NULL,则找到了这样一个字符
		if (strchr(group, *str) != NULL)
		{
			return str;
		}
		str++;
	}
	return NULL; //找不到,返回空指针
}

四. 查找一个子字符串

4.1 strstr函数

4.1.1 strstr的函数原型及实现的功能

函数原型:char *strstr( const char *s1, const char *s2);

函数功能及返回值:在s1中查找整个s2第一次出现的起始位置,并返回一个指向该位置的指针,如果s2没有出现在s1的任何地方,函数将返回一个NULL指针。如果第二个参数是一个空字符串,就返回s1。

4.1.2 strstr函数的使用方法演示

代码段4.1在字符串arr1[]="abcdecdf"中查找"cd"第一次出现的位置,程序的运行结果为:cdecdf

代码段4.1:

int main()
{
	char arr1[] = "abcdecdf";
	char arr2[] = "cd"; 
	char* ret = strstr(arr1, arr2);
	printf("%s\n", ret); //cdecdf
	return 0;
}

4.1.3 strstr函数的模拟实现

模拟实现代码:

char* my_strstr(const char* str1, const char* str2)
{
	assert(str1); //指针有效性检验
	if (str2 == NULL) //str2是空字符串就返回str1的位置
	{
		return str1;
	}
	size_t len2 = strlen(str2); //求arr2中含有几个有效字符
	while (*str1 != '\0')
	{
		//比较str1和str2的前len2个字符是否相同
		//如果相同,返回此时str1的位置
		if (strncmp(str1, str2, len2) == 0)
		{
			return str1;
		}
		str1++;
	}
	return NULL;
}

五. 查找一个字符串的前缀 

5.1 strspn函数

5.1.1 strspn的函数原型及实现的功能

函数原型:size_t strspn( const char *str, const char *group );

函数功能:group字符串指定一个或多个字符。strspn返回str起始部分匹配group中任意字符的字符数。例如,arr1[] = "1234.56@abcf",arr2[] = "12389",字符串arr1中的第1、第2、第3个字符可以在arr2中找到,arr1中第4个字符无法在arr2中找到,因此,strspn(arr1,arr2)的返回值为3。

5.1.2 strspn函数的使用方法演示

在代码段5.1中定义了三个字符串,分别为:arr1[] = "12.34.56@abcf"、arr2[] = "123456"、arr3[] = ".123456",先后执行语句strspn(arr1,arr2)和strspn(arr1,arr3),arr1的前2个字符可以在arr2中找到匹配,arr1中前8个字符可以在arr3中找的匹配。因此,程序中ret1=2,ret2=8。

代码段5.1:

#include
#include
int main()
{
	char arr1[] = "12.34.56@abcf";
	char arr2[] = "123456";
	char arr3[] = ".123456";
	size_t ret1 = strspn(arr1, arr2);
	printf("%u\n", ret1);   //2
	size_t ret2 = strspn(arr1, arr3);  //8
	printf("%u\n", ret2);
	return 0;
}

5.1.3 strspn函数的模拟实现

模拟实现代码:

size_t my_strspn(const char* str, const char* group)
{
	assert(str && group);  //指针有效性检验
	size_t count = 0; //str其实位置与group中任意字符匹配的字符数
	while (strchr(group, *str) != NULL)
	{
		//在group中查找*str,若不返回NULL,则表示*str这个字符可以与group中其中之一匹配
		//匹配成功就进行count++操作
		count++;
		str++;
	}
	return count;
}

5.2 strcspn函数

5.2.1 strcpn的函数原型及实现的功能

函数原型:size_t strcspn( const char *str, const char *group );

函数功能:strcspn函数的功能与strspn正好相反,它计算字符串str起始部分有几个字符无法与group中任意一个字符匹配。比如,arr1[]="123.456.78.90@abcd",arr2[ ]="@abc",arr1前面的123.456.78.90(共13个字符)与arr2无法匹配,因此,strcspn(arr1,arr2)返回的结果为12。

5.2.2 strcspn的使用方法演示

代码段5.2中定义两个字符串arr1和arr2,指向语句strcspn(arr1, arr2),arr1中的前12个字符无法与arr2中任意一个字符匹配,因此程序运行的结果为13。

#include
#include
int main()
{
	char arr1[] = "123.456.78.90@abcd";
	char arr2[] = "@abc";
	size_t ret = strcspn(arr1, arr2);
	printf("%u\n", ret);   //13
	return 0;
}

5.2.3 strcspn函数的模拟实现

模拟实现代码:

size_t my_strcspn(const char* str, const char* group)
{
	assert(str && group); //指针的有效性检验
	size_t count = 0;
	while (strchr(group, *str) == NULL)
	{
		//调用库函数strchr,在group函数中查找不到*str就返回NULL,执行count++
		count++;
		str++;
	}
	return count;
}

六. 查找字符串中的标记

6.1 strtok函数

6.1.1 strtok的函数实现的功能及函数原型

函数原型:char *strtok( char *strToken, const char *strDelimit );

函数功能:通过查找标识符,将一个字符串分隔开来,并将标识符丢弃,将源字符串标识符的位置替换为'\0'。

函数参数:strDelimit字符串定义了分隔符的集合,strToken包含零个或多个strDelimit字符串中定义的分隔符。函数在strToken查找strDelimit定义的分隔符,并将分隔符替换为\0。

函数的返回值:若在字符串中查找到了标记,就返回被标记的位置,若找不到标记,就返回空指针NULL。

注意:若strtok的第一个参数不是NULL,函数将找到字符串的第一个标记,同时,strtok函数将保存第一个标记在字符串中的位置。若strtok的第一个参数为NULL,则从上一次标记被保存的位置开始查找下一个标记。

6.1.2 strtok的使用方法演示

注意:由于strtok函数会改变原来的字符串,因此,一般将字符串的一份临时拷贝传入到strtok函数中。

在代码段6.1中,定义了字符串arr1[]="123.456.789@abc#def" 和分隔符集合group[]=".@#",程序在arr1中查找分隔符.#@并打印被分隔的每一块,程序的运行结果为:123   456   789   abc   def。

代码段6.1:

#include
#include
int main()
{
	char arr1[] = "123.456.789@abc#def";
	char arr[25] = { 0 };
	strcpy(arr, arr1); //取一份arr1的临时拷贝
	char group[] = ".#@";
	char* ret = arr;
	for (ret = strtok(arr, group); ret != NULL; ret = strtok(NULL, group))
	{
		printf("%s  ", ret); //123  456  789  abc  def
	}
	return 0;
}

警告:由于strtok函数具有记忆功能,因此,在同一循环内不能用strtok函数同时处理两个字符串,不可以循环条件使用strtok函数,循环体内的语句也使用strtok函数。

6.1.3 strtok函数的模拟实现

模拟实现代码: 

char* my_strtok(char* str, const char* group)
{
	static char* remember = NULL; //记忆字符串位置
	char* start = NULL; //定义并初始化开始查询的位置
	if (str == NULL)
	{
		//若第一个参数为NULL,则从上次查找的的分隔符位置开始查询下一个分隔符
		start = ++remember; 
	}
	else
	{
		//若第一个参数不为NULL,则从这个参数指向的位置开始查询
		start = str;
	}
	assert(start); //此时,不再运行start为空指针,要进行指针有效性检验
	size_t leng = strlen(group) + 1; //group的字符数(包含末尾\0)
	char* pos = strpbrk(start, group); //求start后第一次出现分隔符的位置
	if (NULL != pos)
	{
		*pos = '\0';
		remember = pos; //记忆分隔符的下一个内存位置
		return start; //返回开始查找的位置
	}
	else
	{
		return NULL;
	}
}

全文结束,感谢大家的阅读,敬请批评指正。

你可能感兴趣的:(C语言进阶,c语言,开发语言)