目录

1.strcpy(字符串拷贝函数)

1.1函数介绍

1.2函数使用示范 

1.3函数模拟实现 

2.strcat(字符串追加函数) 

 2.1函数介绍

 2.2函数使用示范:

2.3函数模拟实现 :

 2.4思考:字符串可以自己给自己追加吗?

 3.strcmp(字符串比较函数)

3.1函数介绍

3.2函数使用示范 

3.3函数模拟实现 

分割: 

4.strncpy(字符串拷贝函数,可以指定拷贝的字符数目) 

 4.1函数介绍

4.2函数使用示范 

5.strncat(字符串追加函数可以指定追加的字符数目) 

5.1函数介绍

5.2函数使用示范 

6.strncmp(字符串比较函数,可以限定比较的字符数)

6.1函数介绍 

6.2函数的实现 

7.strstr(字符串中找子字符串函数:图解实现)

7.1函数介绍

7.2函数演示使用

7.3函数模拟实现 

8.strtok函数(实现字符分割的函数) 

8.1函数介绍

8.2函数的使用举例 

9.strerror(打印错误信息函数) 

9.1函数介绍

9.2函数实现例子 

10.字符分类函数 

11.字符转换函数 

*10、11两种函数搭配实例 

12结语 


1.strcpy(字符串拷贝函数)

1.1函数介绍

 

函数头文件:string.h

函数参数:① char * destination:拷贝目的空间的地址

                  ②const char * source:源字符串的地址

返回值类型:char*

返回值:返回目的字符串的地址也就是考到到某个地方,这个某个地方的地址。

函数功能:将源字符串直到\0以前的所有内容拷贝到目的空间,包括\0.

源字符串必须以 '\0' 结束。
会将源字符串中的 '\0' 拷贝到目标空间。
目标空间必须足够大,以确保能存放源字符串。
目标空间必须可变

1.2函数使用示范 

int main()
{
	char arr1[20] = { 0 };
	char arr2[] = "hello world";
	char arr3[6] = { 'a','b','c','d','e','f' };
	strcpy(arr1, arr2);
	printf("%s\n", arr1);
	strcpy(arr1, arr3);
	printf("%s\n", arr1);
	char arr4[6] = { 'a','b','c','d','e','\0' };
	
	strcpy(arr1, arr4);
	printf("%s\n", arr1);
	return 0;
}

1.3函数模拟实现 

实现思想:

将目的空间的起始地址保存后,因为后续返回的是目的空间的地址。利用指针遍历将源字符串的内容赋值给目的空间,直到源字符串的指针解引用得到\0. 

参数部分:由于传递的是字符串的地址,所以用char* 类型的指针接收,对于源字符串来说,只是遍历但是不用修改其值,可以用const来修饰。接下来我们看实现

char* my_strcpy(char* dest, const char* src)

{
	char* ret = dest;
	//保存目的空间的地址,后续返回的是目的空间的地址
	//对于判断条件来说,要对指针解引用要保证指针的有效性,所以这里我们要断言一下
	assert(dest != NULL);
	assert(src != NULL);

	while (*src != '\0')
	{
		*dest = *src;
		src++;
		dest++;
	}
*dest = *src;//\0
return ret;

}

int main()
{
	char arr1[20] = "hello world";
	char arr2[] = "xxxxx";
	my_strcpy(arr1, arr2);
printf(“%s\n”,arr1);

	return 0;
}

正是因为我们拷贝的时候将\0也拷贝进入了字符串1,所以1打印的时候只打印了前五个元素,但是内存里面是这样的

当然我们的循环遍历部分也可以改造得简单一些:

	while (*dest++ = *src++)
	{
		;
	}

补充:

 返回值写成char* 是为了实现链式访问 比如:printf("%s\n",my_strcpy(arr1,arr2);
 因为返回的是目的空间首元素的地址

2.strcat(字符串追加函数) 

 2.1函数介绍

函数头文件:string.h

函数参数:① char * destination:追加目的空间的地址

                  ②const char * source:源字符串的地址

返回值类型:char*

返回值:返回目的字符串的地址也就是考到到某个地方,这个某个地方的地址。

函数功能:将源字符串直到\0以前的所有内容追加到目的空间,包括\0.

源字符串必须以 '\0' 结束。
会将源字符串中的 '\0' 追加到目标空间。
目标空间必须足够大,以确保能存放源字符串。
目标空间必须可变

 2.2函数使用示范:

引入例子:现在有目标空间里有hello,但是空间大,希望追加一个world,追加在后面
工作原理:找到目标地址的\0,然后追加
源和目标都有\0,都可修改,然后,目标空间要走足够大

int main()
{
	char arr1[20] = "hello";
	char  arr2[] = "world";
	strcat(arr1, arr2);
	

	printf("%s\n", arr1);
	return 0;
}

2.3函数模拟实现 :

实现思想:先利用目标空间首元素这个指针来找到目标空间字符串中的\0,然后从这个地址开始将源字符串通过指针遍历放到目的空间中,直到找到源字符串的\0. 

参数部分:由于传递的是字符串的地址,所以用char* 类型的指针接收,对于源字符串来说,只是遍历但是不用修改其值,可以用const来修饰。接下来我们看实现

char * my_strcat(char* dest, const char* src)
{
	//断言
	assert(dest);
	assert(src);//等于空指针就是0,为假就报错了
	char* ret = dest;
	//1.首先找目标空间中的\0
	while (*dest)
	{
		dest++;
	}
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}
//
int main()
{
	char arr1[20] = "hello";
	char  arr2[] = "world";
	//strcat(arr1, arr2);
	my_strcat(arr1, arr2);

	printf("%s\n", arr1);
	return 0;
}

 实现效果:

 2.4思考:字符串可以自己给自己追加吗?

分析:当我们自己给自己追加的时候,字符串首元素的地址即是目的地址也是源地址,等目的地址找到\0, 此时开始追加,第一步就将h赋值给了\0的地址空间,让后des++,src++,依次赋值e,l,l....,最后我们发现\0就消失了,整个程序就陷入了死循环,当指针增加超过了这个数组的空间就越界了。

 3.strcmp(字符串比较函数)

3.1函数介绍

函数头文件:string.h

函数参数:①const char * str1:字符串1的地址

                  ②,const char * str2:字符串2的地址

返回值类型:int

返回值:第一个字符串小于第二个字符串就返回一个<0的数

                第一个字符串等于第二个字符串就返回0

                第一个字符串大于第二个字符串就返回一个>0的数

函数功能:

 将 C字符串 str1 与 C字符串 str2 进行比较。从传递的地址处开始比较每个字符串的第一个字符(比较的是字符的ACSII码值)。如果它们彼此相等,则继续以下对,直到字符不同或同时达到\0字符。

3.2函数使用示范 

int main()
{
	int ret = strcmp("abq", "abq");
	printf("%d\n", ret);
	return 0;
}

3.3函数模拟实现 

思想:通过两个指针循环遍历比较对应字符的acsii码值。

参数部分由于只做比较,不修改值所以可以用const修饰

int my_strcmp(const char* str1, const char* str2)
{
	while (*str1 == *str2)
		
	{
		if (*str1 == '\0')
			return 0;
		str1++;
		str2++;

	}
	if (*str1 > *str2)
	{
		return 1;
	}
	else
		return -1;
}
int main()
{
	int ret = my_strcmp("abq", "abq");
	printf("%d\n", ret);
	return 0;
}

分割: 

前面三个函数都是长度不受限制的字符串函数,只关心\0的位置,就是直接拷贝或者追加默认到结尾。
下面介绍长度受限制的字符串函数,唯一的区别就是可以控制拷贝的字符串长度,可以控制追加和比较的字符串的长度。这里做出介绍,不模拟实现,大家可以根据前三个函数和参数介绍进行使用与练习。

4.strncpy(字符串拷贝函数,可以指定拷贝的字符数目) 

 4.1函数介绍

函数头文件:string.h

函数参数:① char * destination:拷贝目的空间的地址

                  ②const char * source:源字符串的地址

                  ③num:无符号整型,表示要拷贝num个字符从源字符串到目标空间

返回值类型:char*

返回值:返回目的字符串的地址也就是考到到某个地方,这个某个地方的地址。

函数功能:将源字符串中前num个字符拷贝到目的空间,但是不会在拷贝完后补充\0
目标空间必须足够大,以确保能存放源字符串。目标空间必须可变

如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。

4.2函数使用示范 

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

看一下拷贝后的内存空间:

5.strncat(字符串追加函数可以指定追加的字符数目) 

5.1函数介绍

函数头文件:string.h

函数参数:① char * destination:追加目的空间的地址

                  ②const char * source:源字符串的地址

                  ③要追加的字符个数

返回值类型:char*

返回值:返回目的字符串的地址也就是考到到某个地方,这个某个地方的地址。

函数功能:将的前 num 个字符附加到目标,以及\0字符。只把要求的串的内容追加完成就行,追加完成会在后面补上\0.

5.2函数使用示范 

int main()
{
	char str1[20];
	char str2[20];
	strcpy(str1, "To be ");
	strcpy(str2, "orcd");
	strncat(str1, str2, 6);
	puts(str1);
	return 0;
}

6.strncmp(字符串比较函数,可以限定比较的字符数)

6.1函数介绍 

函数头文件:string.h

函数参数:①const char * str1:字符串1的地址

                  ②,const char * str2:字符串2的地址

                  ③无符号整型num,表示要比较的前num个字符

返回值类型:int

返回值:第一个字符串小于第二个字符串就返回一个<0的数

                第一个字符串等于第二个字符串就返回0

                第一个字符串大于第二个字符串就返回一个>0的数

函数功能:

 将 C字符串 str1 与 C字符串 str2 进行比较。从传递的地址处开始比较每个字符串的第一个字符(比较的是字符的ACSII码值)。如果它们彼此相等,则继续以下对,直到字符不同或者第num个字符比较完

6.2函数的实现 

int main ()
{
  char str[][5] = { "R2D2" , "C3PO" , "R2A6" };
  int n;
  puts ("Looking for R2 astromech droids...");
  for (n=0 ; n<3 ; n++)
    if (strncmp (str[n],"R2xx",2) == 0)
    {
      printf ("found %s\n",str[n]);
    }
  return 0;
}

7.strstr(字符串中找子字符串函数:图解实现)

7.1函数介绍

函数头文件:string.h

函数参数:① str1:目标字符串的地址

                  ②str2:被查找的字符串的地址

                

返回值类型:char*

返回值:返回指向 str1 中 str2 第一次出现的指针

函数功能:

查找子字符串

返回指向 str1 中 str2 第一次出现的指针,如果 str2 不是 str1 的一部分,则返回 null 指针。
匹配过程不包括终止 null 字符,但到此为止。

7.2函数演示使用

此示例在 str 中搜索“simple”子字符串,并将该词替换为“sample”。

输出:


This is a sample string
int main ()
{
  char str[] ="This is a simple string";
  char * pch;
  pch = strstr (str,"simple");
  if (pch != NULL)
    strncpy (pch,"sample",6);
  puts (str);
  return 0;
}

7.3函数模拟实现 

 函数实现思想:

char* my_strstr(const char* str1, const char* str2)
{
	char* cp = (char*)str1;//用来记录从目标字符串开始匹配的位置
	char* s1 = cp;//用来在目标字符串中从开始匹配的位置进行匹配
	char* s2 = (char*)str2;//用来配合目标字符串之中的查找
	if (*str2 =='\0')
	{
		return  (char* )str1;
	}
	while (*cp)//循环条件为当开始匹配的位置不为空指针,为空说明目标字符串已经遍历到了末尾了
	{
		//开始进行从匹配起始位置进行一个字一个字符的检查
		s1 = cp;//将起始位置赋值给s1,用来进行遍历匹配
		s2 = (char* )str2;
		while (*(char*)s1 && *(char*)s2 && *(char*)s1 == *(char*)s2)//
		{
			(char*)s1++;
			(char*)s2++;
			//当地址加加的时候,有可能目标地址来到末尾或者源字符串来到末尾,二者都应该结束循环,不进入循环
			//
		}
		if (*(char*)s2 == '\0')
		{
			return cp;//循环结束,只有源字符串遍历到最后一位找到了,返回目标字符串的起始匹配地址

		}
		cp++;//当循环结束没有找到,那就将起始匹配地址+!
	}
	return NULL;//当目标字符串遍历完了都没有匹配成功,那就找不到返回空指针
}
int main()
{
	char arr1[] = "abbbcdef ";
	char arr2[] = "bbc";
	char* ret = my_strstr(arr1, arr2);
	if (ret != NULL)
	{
		printf("%s\n", ret);

	}
	else
	{
		printf("找不到\n");
	}

	return 0;

}

8.strtok函数(实现字符分割的函数) 

8.1函数介绍

sep参数是个字符串,定义了用作分隔符的字符集合第一个参数指定一个字符串,它包含了0,个或者多个由sep字符串中一个或者多个分隔符分割的标记。
strtok函数找到str中的下一个标记,并将其用\0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
如果strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
如果字符串中不存在更多的标记,则返回 NULL 指针


 

8.2函数的使用举例 

int main()
{
	char arr[] = "ouybnji@jdkdm.com";
	char copy[20];
	strcpy(copy, arr);
	char sep[] = { "@." };
	char* ret = NULL;
	for (ret = strtok(copy, sep); ret != NULL; ret = strtok(NULL, sep))
	{
		printf("%s\n", ret);
	}
	return 0;
}

由于strtok函数会改变原字符串的内容,所以将字符串拷贝进copy数组里面,sep作为字符参数传入,把copy中的字符串以这两个字符进行分割,不管分隔符的顺序。第一次传参传入的1是copy数组的地址,函数找到分割符@将@改为\0,返回ouybnji的地址,第二次传参第一个函数即是空指针,函数里面保存的是j的地址,从这个地址去寻找分割符号,找到.,进行分割,返回j的地址,第三次传参传入空指针,函数里面保存了c的地址,找到\0没有找到分割符号返回null.

 

9.strerror(打印错误信息函数) 

9.1函数介绍

 库函数执行的时候会发生错误,会将错误码放在errnum这个变量中,errno是C语言提供的全局变量,错误信息表示的错误

函数:返回错误码,所对应的错误信息,返回来错误信息首字符的地址。

9.2函数实现例子 

10.字符分类函数 

这类函数很简单,控制字符属于什么关系,比如大写字符,小写字符,数字字符,如果判断为真就返回一个非0的值,如果判断为假函数就返回0.

这类函数的头文件包含为:ctype.h

我们来看一个:

函数:

检查字符是否为大写字母

检查参数 c 是否为大写字母。

返回值:如果 c 确实是大写的字母,则与零不同的值(即 true)。否则为零(即 false)。

函数有:

 函数 如果他的参数符合下列条件就返回真
iscntrl                任何控制字符
isspace                空白字符:空格‘ ’,换页‘\f’,换行'\n',回车‘\r’,制表符'\t'或者垂直制表符'\v'
isdigit                十进制数字 0~9
isxdigit                十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A~F
islower                小写字母a~z
isupper                大写字母A~Z
isalpha                字母a~z或A~Z
isalnum                字母或者数字,a~z,A~Z,0~9
ispunct                标点符号,任何不属于数字或者字母的图形字符(可打印)
isgraph                任何图形字符
isprint                   任何可打印字符,包括图形字符和空白字符

11.字符转换函数 

int tolower ( int c );
int toupper ( int c )

函数功能:

将大写字母转换为小写字母

如果 c 是大写字母并且具有小写等效字母,则将 c 转换为小写等效字母。如果无法进行此类转换,则返回的值为 c 不变。

函数:将小写字母转换为大写字母

如果 c 是小写字母并且具有大写等效字母,则将 c 转换为大写等效字母。如果无法进行此类转换,则返回的值为 c 不变。

*10、11两种函数搭配实例 

int main()
{
	char arr[20] = { 0 };
		gets(arr);//这里使用gets函数获取字符串空格也可以直接读
		char* p = arr;
		while (*p)
		{
			if (isupper(*p))
			{
				*p = tolower(*p);
			}
			p++;
		}
		printf("%s\n", arr);
	return 0;
}

12.结语 

以上就是本期的所有内容,知识含量蛮多,大家可以配合解释和原码运行理解。创作不易,大家如果觉得还可以的话,欢迎大家三连,有问题的地方欢迎大家指正,一起交流学习,一起成长,我是nicn,正在c++方向前行的新手,感谢大家的关注与喜欢。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐