C/C++字符串函数功能介绍与模拟实现

  在日常代码编写中,我们往往都是基于已经开发好的编译器及平台进行代码的编译与功能的实现,而编译器所自带的库函数可以在我们编写过程中起到很好的辅助作用,通过使用这些库函数可以直接实现代码所需要的一部分功能,从而大大提升我们的编写效率,节约代码的编写时间。而不同种类的库函数有着不同的功能与应用场景,例如最常用的scanf(输入)、printf(打印)、sizeof(计算字节长度)等等...而本文主要围绕库函数一些好用又易懂的字符/字符串函数进行叙述和介绍。

目录

一、字符函数和字符串函数

 1.1strlen

1.2strcpy

1.3strcat

1.4 strcmp

1.5strncpy

1.6strncmp

1.7strncat

1.8strstr

1.9strtok

1.10strerror


一、字符函数和字符串函数

  不管是日常练习还是在实际场景应用中,字符串以及字符数组都是我们最常接触到的,接下来将会罗列出一些高效便捷的库函数,帮助大家在日常代码编写中节省时间,提高效率。

 1.1strlen

   库函数: size_t strlen ( const char * str );

  strlen应该都不陌生,功能也很单一,它是真对字符串/字符数组求长度的。

  在使用时应了解以下几点:

  1.字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包

'\0' )。 
  2.参数指向的字符串必须要以'/0'结束。
  3.注意函数的返回值为 size_t ,是 无符号 的。(易错)
  4.头文件#include<stdio.h>
  在使用时我们应该重点注意第3点,strlen虽然是求字符串长度的,但是返回类型是无符号数,而
而这一点在代码编写时最容易发生以下情况:
 
#include <stdio.h>
#include <string.h>
int main()
{
	if (strlen("abc")-strlen("abcdef")>0)
	{
		printf("大于\n");
	}
	else
	{
		printf("小于\n");
	}

	return 0;
}

  按照惯性思维,我们经过计算,一定可以得出打印的是小于,但当我们编译运行完成后得到的是如下的结果。

   原因是,strlen的返回值是无符号数,也就是unsigned,无符号就没有负数的概念,让两个strlen直接相减得到的也是一个无符号数,所以直接拿返回值相减永远不会小于0。如果真的想要达到比较的效果,可以将返回值强制类型转换成int型进行加减操作。

下面就是strlen的模拟实现:

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

size_t my_strlen(const char* str)
{
	int count = 0;
	while (*str!='\0')
	{
		count++;
		str++;
	}
	return count;
}
int main()
{
	size_t sz = my_strlen("abc");
	printf("%d\n",sz);
	return 0;
}

1.2strcpy

  库函数:char* strcpy(char* destination,const char* source);

  这个函数就是拷贝函数,前一个参数表示要拷贝的目的地,后一个参数表示需要拷贝的内容,特点如下:

  1. 源字符串必须以 '\0' 结束。

  2.会将源字符串中的'\0'拷贝到目标空间。

  3.目标空间必须足够大,以确保能存放源字符串。

  4.目标空间必须可变

  演示:

#include <stdio.h>

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

	return 0;
}

  

 模拟实现:

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

char* my_strcpy(char* dest, const char* src)
{
	char* ret = dest;
	assert(dest != NULL);//加上断言,指针不能为空指针
	assert(src != NULL);
	while (*src!='\0')
	{
		*dest = *src;
		dest++;
		src++;
	}
	*dest = *src;

	return ret;//最后返回的是起始位置的地址
}
int main()
{
	char arr1[20] = "xxxxxxxxxxxxx";
	char arr2[] = "hello world";
	my_strcpy(arr1, arr2);
	printf("%s\n",arr1);

	return 0;
}

1.3strcat

  库函数: char * strcat ( char * destination, const char * source );
  Appends a copy of the source string to the destination string. The terminating null character
in destination is overwritten by the first character of source, and a null-character is included
at the end of the new string formed by the concatenation of both in destination.
  标准规定:
  1.字符串连接,把两个字符串连接到一起。
 
  2.源字符串必须以 '\0' 结束。
  
  3.目标空间必须有足够的大,能容纳下源字符串的内容。
 
  4.目标空间必须可修改。
  5.字符串不能自己给自己追加。
char* my_strcat(char* dest, const char* src)
{
	assert(dest && src);
	assert(src);
	char* ret = dest;
	while (*dest)
	{
		dest++;
	}
	while (*dest++ = *src++)
	{
		;
	}
}
int main()
{
	char arr1[20] = "hello";
	char arr2[] = "world";
	my_strcat(arr1, arr2);
	printf("%s\n",arr1);
	return 0;
}

1.4 strcmp

  库函数:int strcmp ( const char * str1, const char * str2 );
   This function starts comparing the first character of each string. If they are equal to each
other, it continues with the following pairs until the characters differ or until a terminating
null-character is reached.
  标准规定:
  
  1.第一个字符串大于第二个字符串,则返回大于 0 的数字
  2. 第一个字符串等于第二个字符串,则返回 0
  3. 第一个字符串小于第二个字符串,则返回小于 0 的数字
  注:两个字符串比较是一个一个字符进行比较,比如对abcd和abq进行比较,前两个ab都是一样
的,第三个字符c和q,q的ASCLL码值是大于c的,所以此时返回的结果是小于零的数字。

  模拟实现:
#include <stdio.h>
#include <string.h>

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;//这是VS环境下,其他编译器返回的可能是其他大于零或者小于零的数
}
int main()
{
	int ret = my_strcmp("abq", "abq");

	return 0;
}

1.5strncpy

库函数:char * strncpy ( char * destination, const char * source, size_t num );

Copies the first num characters of source to destination. If the end of the source C string
(which is signaled by a null-character) is found before num characters have been copied,
destination is padded with zeros until a total of num characters have been written to it.

标准规定:

1.拷贝num个字符从源字符串到目标空间。

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

完成。

  在传参时我们要注意有三个参数,源字符串地址,目标空间,要拷贝的字符串个数。

  此函数在strcat基础上进行拷贝次数限定,在strcat基础上根据num控制循环次数即可,代码就不

  不再进行单独的模拟实现。

1.6strncmp

库函数:int strncmp ( const char * str1, const char * str2, size_t num );

标准规定:

比较到有一个字符不一样或者其中一个字符串结束或全部比较完。与strncpy一样,在strcmp基础

上增加了长度限制。而它们也叫做长度受限制的字符串函数。相比于不受限的strcmp和strcpy,它

们相对来说更安全,功能也齐全。

1.7strncat

库函数:char * strncat ( char * destination, const char * source, size_t num );

Appends the first num characters of source to destination, plus a terminating null-character.
If the length of the C string in source is less than num, only the content up to the terminating
null-character is copied.
标准规定:
1.字符串拼接,也叫字符串追加,与上面两个带n的函数一样,限制追加的个数。
2.与上面的拷贝有所区别,当num规定的追加数大于实际source所含字符的个数时,不会在source
后面补多余的\0,而是把source的字符追加完成后直接在后面加一个\0

1.8strstr

库函数:char * strstr ( const char *str1, const char * str2);

Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of
str1.
标准规定:
1.在str1中找str2第一次出现的位置,如果找不到返回NULL空指针。

模拟实现:

char* my_strstr(char* str1, char* str2)
{
	char* cp = str1;
	char* s1 = cp;
	char* s2 = str2;
	while (*cp)
	{
		s1 = cp;
		s2 = str2;
		while (*s1 && *s2 && *s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return cp;
		}
		cp++;
	}
	return NULL;
}

   因为查找时,是从str1第一位开始往后开始查找str2,必须将str2中的所有元素都对的上才算查找成功,所以当条件不符合时就需要跳到str1的下一位继续从后开始查找,所以str1需要2个指针才能完成,第一个指针cp记录开始查找的位置,第二个s1指针从此处加加往后遍历与str2一一比较,如果不符合就返回cp所在的位置,cp指针++后继续从下一位往后查找。str2只需要一个指针s2,每次从str2的第一位开始与s1一起++并比较,不符合时直接重置返回str2的位置也就是字符串的第一位。如此往复,当随着s2不断++,说明++之前的字符都和s1++过的字符一样,直到s1或s2其中一个找到了\0,也就是字符串的结尾,此时查找结束。此时存在三种情况:1.s1为\0但s2不为\0       2.s1不为\0但s2为\0      3.都为\0    此时如果是2、3情况的话说明s2中的字符已经全部找完了,那么就返回cp的地址。如果是第一种情况,说明没找到,返回NULL。

1.9strtok

库函数:char * strtok ( char * str, const char * sep );

标准规定:

1.sep参数是个字符串,定义了用作分隔符的字符集合。

2.第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标

记。
3.strtok函数找到str中的下一个标记,并用\0结尾,返回一个指向这个标记的指针。 (注: strtok函数会改变被操作的字符串,所以在使用 strtok 函数切分的字符串一般都是临时拷贝的内容 并且可修改。)
4. strtok 函数的第一个参数不为 NULL ,函数将找到 str 中第一个标记, strtok 函数将保存它在字符串
中的位置。
5. strtok 函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标
记。
6.如果字符串中不存在更多的标记,则返回 NULL 指针。
int main()
{
	char arr[] = "Boch@studio.niubi666";
	char copy[30];
	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;
}

 这个函数相比于之前的几个库函数,显得更加“智能”,也更奇葩。通俗来讲,将一个带有特殊字符的字符串传给它的第一个参数,将它内部所包含的特殊字符另外组成一个字符串传给它的第二个参数,然后它的功能就是在第一个字符串中找到第二个字符串中包含的特殊字符的位置,然后把那个特殊字符改成\0,然后返回\0之前的字符串的第一个字符的指针。第二次再次调用strtok时,第一个参数只需要传一个NULL它就会接着上次查找到的字符串中那个特殊字符所在的位置也就是被改成\0的地方接着往后查,再次查到特殊字符时再吧它改成\0,然后返回\0之前的字符串的第一个字符的指针。直到它再也找不到特殊字符。所以此函数自带指针记录功能。当然,此函数平时用的比较少,这里只做了解即可。

1.10strerror

库函数:char * strerror ( int errnum );

标准贵定:

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

  这个函数对我们代码的编译或许没有太大的作用,但却对我们调试代码和查找bug有着巨大的帮助。

  如果库函数在执行的时候发生了错误,编译器会将一个错误码存放到errno中(errno是C语言提供的一个全局变量用来存放错误码)。每个数字1 2 3 4...都对应不同的错误信息,0表示没有错误。比如经常在网上看到的404,它对应的信息就是“访问的网址不存在”。

  而参数errnum就是错误码,只要strerror接收到一个错误码,就会把错误码所对应的错误信息,以字符串的形式提供出来。返回错误码所对应字符串的起始位置。

 现在,尝试打印一下从0到9所对应的错误信息。

 注意:如果你写的程序存在多个错误,下一个错误的错误编码就会覆盖掉errno中存放的上一个错误的编码,所以及时使用strerror检查很重要。

  以上就是我们日常代码编写中比较常见,实用性比较高的一些库函数,我们通过对其参数、返回值、模拟实现的研究增强了对库函数的理解和认知,而熟练掌握库函数的使用会大大减少我们的工作量,提高代码运行效率的同时也增强了代码的可读性,使其更加凝练更加简介。

  本章内容就到此结束了,每一篇文章都是博主的精心打磨,耐心编排。更多好文关注博主CSDN。一键三连不迷路。

  

  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C+五条

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值