【C语言】字符串库函数的解读和模拟实现第一弹(strlen、strcpy、strcat、strcmp、strncpy、strncat 及 strncmp)

目录

一. strlen函数

1.1 strlen函数实现的功能及函数原型

1.1.1 strlen函数实现的功能

1.1.2 strlen的函数原型

1.1.3 strlen实现功能的更进一步解读

1.2 strlen函数的使用方法演示

1.3 strlen函数的三种模拟实现方法

1.3.1 通过计数的方法模拟实现strlen函数

 1.3.2 通过递归的方法模拟实现strlen函数

1.3.3 使用指针相减的方法来模拟实现strlen函数 

二. strcpy函数

2.1 strcpy函数实现的功能及函数原型

2.1.1 strcpy函数实现的功能 

2.1.2 strcpy函数的函数原型

2.2 strcpy函数的使用方法演示

2.3 strcpy的模拟实现

三. strcat函数

3.1 strcat函数实现的功能及函数原型

3.1.1 strcat函数实现的功能

3.1.2 strcat函数的函数原型

3.2 strcat函数的使用方法演示

3.3 strcat函数的模拟实现

四. strcmp函数

4.1 strcmp函数的功能及函数原型

4.1.1 strcmp函数实现的功能

4.1.2 strcmp函数的函数原型 

4.2 strcmp函数的使用方法演示

4.3 strcmp函数的模拟实现

五. strncpy函数

5.1 strncpy函数的功能及函数原型

5.1.1 strncpy函数的功能

 5.1.2  strncpy的函数原型

5.2 strncpy函数的使用方法演示

5.3 strncpy函数的模拟实现

六. strncat函数

6.1 strncat函数的功能和函数原型

6.1.1 strncat函数实现的功能

 6.1.2 strncat的函数原型

6.2 strncat函数的使用方法演示

6.3 strncat函数的模拟实现 

七. strncmp函数

7.1 strncmp函数的功能和函数原型

7.1.1 strncmp函数的功能

7.1.2 strncmp函数的原型

7.2 strncmp的使用方法演示

7.3 strncmp函数的模拟实现


一. strlen函数

1.1 strlen函数实现的功能及函数原型

1.1.1 strlen函数实现的功能

strlen函数统计某个字符串的有效字符数(不包含末尾的'\0')。

1.1.2 strlen的函数原型

查阅MSDN,strlen的函数原型为:size_t strlen( const char *string );

  • 该函数有一个输入参数,为字符串的名称(字符串首个字符元素的地址)
  • 该函数的返回值类型为size_t,即无符号整型,表示字符串中的有效字符数
  • 使用该函数需要引用头文件<string.h>

1.1.3 strlen实现功能的更进一步解读

许多初学者看到strlen函数,可能会认为strlen函数接受的参数只能是表示首元素地址的字符串名称,其实不是。传入的参数可以是任何一个地址(指针变量),strlen函数在求解字符串有效字符数时,以传入的地址为起始点向后查询字符串终止标识符'\0',在查找到'\0'之前共有几个内存空间的内容不是'\0'字符串的有效字符数就是几。strlen的功能图解如图1.1所示。

图1.1  strlen的功能图解

1.2 strlen函数的使用方法演示

下段代码中定义了字符串arr[]="abcdef",分别将arr和arr+1作为参数传入strlen函数进行计算,得到的结果分别为6和5。

#include<stdio.h>
int main()
{
	char arr[] = "abcdef";
	size_t len1 = strlen(arr);
	size_t len2 = strlen(arr + 1);
	printf("len1=%u  len2=%u\n", len1, len2);  //打印len1=6  len2=5
	return 0;
}

1.3 strlen函数的三种模拟实现方法

1.3.1 通过计数的方法模拟实现strlen函数

每在内存中查找到一个不是'\0'的字符,就进行count++操作,遇到'\0'就终止计数。

代码演示:

size_t my_strlen(const char* str)
{
	assert(str); //传入指针的有效性检验
	size_t count = 0;
	while (*str++ != '\0')
	{
		count++;
	}
	return count;
}

 1.3.2 通过递归的方法模拟实现strlen函数

代码演示:

size_t my_strlen(const char* str)
{
	assert(str); 
	if (*str != '\0')
	{
		//*str != '\0'时就将下一个地址传入my_strlen递归调用
		return 1 + my_strlen(str + 1);
	}
	else
	{
		return 0;
	}
}

1.3.3 使用指针相减的方法来模拟实现strlen函数 

两指针相减的结果是两个指针指向的内存位置之间存储的元素的个数。因此,只需确定存储'\0'的内存的地址,与首元素地址相减,就得到了字符串的有效字符数。

size_t my_strlen(const char* str)
{
	assert(str); 
	char* start = str;
	while (*str != '\0') //获取存储'\0'的内存地址
	{
		str++;
	}
	return str - start;
}

二. strcpy函数

2.1 strcpy函数实现的功能及函数原型

2.1.1 strcpy函数实现的功能 

将源字符串的内容复制到目标字符串,包括源字符串末尾的'\0'也会被复制到目标字符串。

注意:目标字符串一定要有足够的空间来容纳源字符串,否则将出现不可预料的结果。

2.1.2 strcpy函数的函数原型

查阅MSDN,strcpy的函数原型为:

char *strcpy( char *strDestination, const char *strSource );

函数有两个输入参数:

  1. strDestination,目标字符串空间,用于容纳复制后的源字符串。
  2. strSource,源字符串。

函数的返回值类型为char*,返回目标字符串首元素的地址。

2.2 strcpy函数的使用方法演示

代码段1定义了两个字符串:arr1[10]="xxxxxxxxx",arr2[10]="abcd",以arr2为源字符串,arr1为目标字符串,将arr2的内容复制到arr1中去,打印arr1,结果为abcd。

代码段1:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[10] = "xxxxxxxxx";
	char arr2[10] = "abcd";
	strcpy(arr1, arr2);
	printf("arr1 = %s\n", arr1); //arr1 = abcd
	return 0;
}

由代码段2,若arr1的空间不足以容纳arr2,程序发生崩溃。运行结果如图2.1所示

代码段2:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[10] = "xxxxxxxx";
	char arr2[15] = "abcdefghiklmn";
	strcpy(arr1, arr2);
	printf("arr1 = %s\n", arr1);
	return 0;
}
图2.1  代码段2的运行结果

2.3 strcpy的模拟实现

代码演示:

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

char* my_strcpy(char* str1, const char* str2)
{
	assert(str1 && str2);
	char* ret = str1;
	while (*str1++ = *str2++)
	{
		;
	}
	return ret;
}

三. strcat函数

3.1 strcat函数实现的功能及函数原型

3.1.1 strcat函数实现的功能

将源字符串追加到目标字符串的尾部,包括'\0'。图3.1为strcat函数的功能图解。

图3.1  strcat函数的功能图解

注意:必须确保源字符串留有足够的空间容纳目标字符串,否则会出现不可预料的结果

3.1.2 strcat函数的函数原型

查阅MSDN,strcat的函数原型为:

char *strcat( char *strDestination, const char *strSource );

strcat函数有两个输入参数:

  1. strDestination,目标字符串首元素地址
  2. strSourc,源字符串首元素地址

函数的返回值类型为字符指针(char*),返回值为目标字符串首元素地址。

3.2 strcat函数的使用方法演示

下段代码定义了两个字符串:arr1[20] = "xxxxxx",arr2[10] = "abc"。将arr1作为目标字符串、arr2作为源字符串传入函数strcat,并打印arr1字符串,结果为:xxxxxxabc

代码演示:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[20] = "xxxxxx";
	char arr2[15] = "abc";
	strcat(arr1, arr2);
	printf("arr1 = %s\n", arr1); //arr1 = xxxxxxabc
	return 0;
}

3.3 strcat函数的模拟实现

首先获取目标空间字符串中第一次出现'\0'的地址,然后将源字符串的数组依次复制到目标字符串最后一个有效字符后面,当发现源字符串中有'\0'时,停止复制。

模拟实现strcat函数的代码:

char* my_strcat(char* dest, const char* src)
{
	char* ret = dest; //返回值
	while (*dest != '\0')
	{
		dest++; //查找目标字符串第一次出现'\0'的位置
	}
	while (*dest++ = *src++) //复制到'\0'终止
	{
		;
	}
	return ret;
}

四. strcmp函数

4.1 strcmp函数的功能及函数原型

4.1.1 strcmp函数实现的功能

strcmp函数是字符串大小比较函数,通过返回值的大小可以获取两个字符串的大小

两个字符串的大小关系是如何定义的?

假设arr1[ ] = "12abf",arr2[ ] = "12dbf"

先比较两个字符串的首字符,一样,再比较第二个字符,一样,将两个字符串的每个字符依次进行比较,直到遇到不一样的字符,比较两字符串首个不一样的字符的ASCII码值,来确定两个字符串的大小关系。若arr1和arr2有效字符数相同,且所有字符均相同,则arr1与arr2相等。

注意:两个字符串之间比较大小不能使用==,如果使用==对两个字符串进行比较,那么实际上是比较两个字符串首元素的地址,而地址的比较没有任何意义。

4.1.2 strcmp函数的函数原型 

查阅MSDN,strcmp的函数原型为:

int strcmp( const char *string1, const char *string2 );

函数有两个输入参数,即两个用于比较的字符串。

函数返回值为int类型,返回值的正负表示两个字符串的大小:

  • 若返回值 <0 :则string1 < string2
  • 若返回值 >0:则string1 > string2
  • 若返回值<0:则string1 = string2

4.2 strcmp函数的使用方法演示

下面程序中定义了两个字符串:arr1[]="abcd"、arr2[]="abdd"。arr1和arr2的前两个字符相同,arr1的第三个字符的ASCII码值小于arr2的第三个字符,因此arr1<arr2。调用函数strcmp(arr1,arr2)的返回值<0,程序打印<。

代码演示:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "abcd";
	char arr2[] = "abdd";
	int ret = strcmp(arr1, arr2); //arr1 < arr2
	if (ret < 0)
	{
		printf("<\n");
	}
	else if (ret > 0)
	{
		printf(">\n");
	}
	else
	{
		printf("=\n");
	}
	return 0;
}

4.3 strcmp函数的模拟实现

模拟实现strcmp函数的代码:

int my_strcmp(const char* str1, const char* str2)
{
	while (*str1 == *str2)
	{
		if (*str1 == '\0') //检查到末尾依旧相同,两字符串相等
		{
			return 0; //两字符串相等返回0
		}
		str1++; //下一个字符地址
		str2++;
	}
	return *str1 - *str2; //返回值为首次不相同的字符串相减
}

五. strncpy函数

5.1 strncpy函数的功能及函数原型

5.1.1 strncpy函数的功能

 将源字符串的前n个字符复制到目标字符串前n个字符的位置。通俗的说,就是把目标字符串的前n个字符元素替换为目标字符串的前n个元素。

对于strncpy函数的具体实现,分为两种情况来讨论:

  1. 当源字符串的有效字符数目大于或等于要求复制的字符数目n时,将源字符串的前n个字符复制到目标字符串前n个字符的位置,目标字符串第n个字符往后的内容不发生改变。图5.1为这种情况下strncpy函数实现的图解。
  2. 当源字符串的有效字符数目小于要求复制的字符数目n时,先将源字符串的有效字符复制到目标字符串,然后看源字符串有效字符数比要求复制的字符数少了几个,少几个就在相应目标字符串的位置补几个'\0'字符。图5.2为这种情况下strncpy函数实现的图解。
图5.1  当源字符串的有效字符数目大于或等于要求复制的字符数目n时strncpy实现的图解

图5.2  当源字符串的有效字符数目小于要求复制的字符数目n时strncpy实现的图解

 5.1.2  strncpy的函数原型

查阅MSDN,strncpy的函数原型为:

char *strncpy( char *strDest, const char *strSource, size_t count );

函数有三个输入参数:

  1. strDest,目标字符串
  2. strSource,源字符串
  3. count,要复制的字符数目

函数的返回值类型为字符型指针(char*),返回目标字符串首元素的地址。

5.2 strncpy函数的使用方法演示

  • 源字符串的有效字符数目大于或等于要求复制的字符数目的情况

在代码段5.2.1中,定义两个字符串:arr1[15]="##########"和arr2[ ]="abcedf",执行指令strncpy(arr1,arr2,3),将arr2中的前三个字符复制到arr1中去,并打印arr1。

程序运行的结果为:arr1 = abc#######

代码段5.2.1:

int main()
{
	char arr1[15] = "##########";
	char arr2[] = "abcdef";
	char* ret = strncpy(arr1, arr2, 3);
	printf("arr1 = %s\n", arr1); //arr1 = abc#######
	return 0;
}
  •  源字符串的有效字符数目小于要求复制的字符数目的情况

在代码段5.2.2中,定义两个字符串:arr1[15]="##########"和arr2[ ]="abc",执行指令strncpy(arr1,arr2,5),将arr2中的前5个字符复制到arr1中去,并打印arr1。

程序运行结果为:arr1 = abc

代码段5.2.2:

int main()
{
	char arr1[15] = "##########";
	char arr2[] = "abc";
	char* ret = strncpy(arr1, arr2, 5);
	printf("arr1 = %s\n", arr1); //arr1 = abc
	return 0;
}

进入调试,打开监视窗口,观察执行完strncpy(arr1,arr2,5)指令后arr1的变化情况,可以看到,arr1的前三个元素变为了'a'、'b'、'c',第四和第五个元素均变为了'\0'、'\0'。执行完strncpy(arr1,arr2,5)后的监视窗口如图5.3所示。

图5.3 执行完strncpy(arr1,arr2,5)后的监视窗口情况

5.3 strncpy函数的模拟实现

 strncpy模拟实现的代码:

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

char* my_strncpy(char* str1, const char* str2, size_t n)
{
	char* ret = str1;
	while ((*str2 != '\0') && n) //复制n个字符串到str1,遇*str2='\0'终止复制
	{
		*str1 = *str2;
		str1++;
		str2++;
		n--;
	}

	if (n > 0) 
	{
		//str2中有效字符数小于n时arr1后方补'\0'
		while (n--)
		{
			*str1++ = '\0';
		}
	}
	return ret;
}

六. strncat函数

6.1 strncat函数的功能和函数原型

6.1.1 strncat函数实现的功能

strnact函数为限制长度的字符串追加函数,将源字符串的前n个字符追加到目标字符串的后方。注意:要确保目标字符串留有足够的空间容纳源字符串,否则程序将产生不可预料的结果。

分两种情况来讨论:

  1. 当源字符串有效字符数目小于或等于要求追加的字符数n时,直接将源字符串的前n个字符追加到目标字符串的后面。图解可参考图6.1。
  2. 当源字符串有效字符数目小于要求复制的字符数时,则在源字符串中遇到了一个'\0'后就终止追加。图解可参考图6.2。
图6.1 当源字符串有效字符数目小于要求追加的字符数n时strncat的图解
图6.2 当源字符串有效字符数目小于要求追加的字符数n时strncat的图解

 6.1.2 strncat的函数原型

查阅MSDN,strncat的函数原型为:

char *strncat( char *strDest, const char *strSource, size_t count );

该函数有三个输入参数:

  1. strDest,目标字符串(被追加的字符串)
  2. strSource,源字符串
  3. count,要追加的字符串数目

该函数的返回值为目标字符串(strDest)首元素的地址

6.2 strncat函数的使用方法演示

  • 源字符串有效字符数目小于或等于要求追加的字符数时

代码段6.2.1实现的功能为在arr1后方追加arr2的前三个字符,然后打印arr1。

程序运行的结果为:arr1 = ####abc

代码段6.2.1:

int main()
{
	char arr1[15] = "####";
	char arr2[] = "abcdef";
	char* ret = strncat(arr1, arr2, 3);
	printf("arr1 = %s\n", ret); //arr1 = ####abc
	return 0;
}
  • 源字符串有效字符数目大于要求追加的字符数时

代码段6.2.2定义了两个字符串:arr1[15] = "####\0######"和arr2[] = "abc",strncat(arr1, arr2, 5)语句希望将arr2的前5个字符追加到arr1后面(从arr1中第一个\0的位置开始追加),但是arr2仅有三个有效字符,因此,先追加arr2全部的三个有效字符,使得arr1中从原来第一个\0位置处开始的三个字符,依次变为'a'、'b'、'c',然后再'c'后面追加'\0'。

程序运行的结果为:arr1 = ####abc

代码段6.2.2:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[15] = "####\0######";
	char arr2[] = "abc";
	char* ret = strncat(arr1, arr2, 5);
	printf("arr1 = %s\n", ret);  //arr1 = ####abc
	return 0;
}

进入调试界面,打开监视窗口,监视arr1在执行完strncat(arr1, arr2, 5)语句后的变化情况。执行完strncat(arr1, arr2, 5)语句后的监视窗口如图6.3所示。

图6.3  执行完strncat(arr1, arr2, 5)语句后的监视窗口

6.3 strncat函数的模拟实现 

strncat函数模拟实现的代码:

char* my_strncat(char* dest, const char* src, size_t n)
{
	assert(dest && src);  //指针的有效性检查
	char* ret = dest;
	while (*dest != '\0') //查找源字符串第一次出现\0的位置
	{
		dest++;
	}
	while ((*src != '\0') && n)
	{
		//将src的前n个字符(所有有效字符)追加到目标字符串后面
		*dest++ = *src++; 
		n--;
	}
	*dest = '\0';  //追加完成后补'\0'
	return ret;
}

七. strncmp函数

7.1 strncmp函数的功能和函数原型

7.1.1 strncmp函数的功能

strncmp是限制长度的字符串比较函数,将arr1和arr2的前n个字符视为具有n个有效字符的字符串,比较arr1和arr2前n个字符组成的字符串的大小。如果在比较过程中遇到了'\0'字符,则停止比较。

当还没有比较完前n个字符就遇到'\0'时,分两种情况讨论:

  1. 两个字符在比较过程中同时遇到'\0',如定义arr1[]="abc",arr2[]="abc",执行语句strncmp(arr1, arr2, 5),但由于arr1和arr2前三个字符相同,到了第四个字符就遇到了'\0',因此,比较到第四个字符就停止比较,不再比较第五个字符,arr1与arr2相等。
  2. 两个字符在比较过程中其中一个遇到'\0',如定义arr1[]="ab",arr2[]="abcdef",执行语句strncmp(arr1, arr2, 4),比较到第三个字符时arr1就遇到了'\0',arr2的第三个字符为c,'\0'的ASCII码值小于'c'。因此arr1<arr2。

7.1.2 strncmp函数的原型

查阅MSDN,得strncmp的函数原型为:

int strncmp( const char *string1, const char *string2, size_t count );

有三个输入参数:

  • string1和string2:两个用于比较的字符串
  • count:比较的字符数目

函数的返回值为int类型,通过返回值的正负比较大小

  • 若  返回值>0:arr1 > arr2
  • 若  返回值<0:arr1 < arr2
  • 若  返回值=0:arr1 = arr2

7.2 strncmp的使用方法演示

代码段7.2.1定义了字符串arr1[]="abcde"和arr2[]="abce",执行语句strncmp(arr1,arr2,3)和strncmp(arr1,arr2,4),分别比较arr1和arr2前3和前四个字符组成的字符串的大小,arr1和arr2的前三个字符进行比较结果相等,前四个字符进行比较arr1<arr2。

代码运行的结果为:=  <

代码段7.2.1:

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

int main()
{
	char arr1[] = "abcde";
	char arr2[] = "abce";
	int ret = strncmp(arr1, arr2, 3); //比较arr1和arr2的前三个字符,结果为=
	if (ret > 0)
	{
		printf(">  ");
	}
	else if (ret < 0)
	{
		printf("<  ");
	}
	else
	{
		printf("=  ");
	}
	ret = strncmp(arr1, arr2, 4);  //比较arr1和arr2的前四个字符,结果为<
	if (ret > 0)
	{
		printf(">\n");
	}
	else if (ret < 0)
	{
		printf("<\n");
	}
	else
	{
		printf("=\n");
	}
	return 0;
}

7.3 strncmp函数的模拟实现

strncmp函数的模拟实现代码:

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

int my_strncmp(const char* str1, const char* str2, size_t count)
{
	assert(str1 && str2);
	while ((*str1 == *str2) && count)
	{
		if (*str1 == '\0')  //同时遇到'\0',arr1=arr2
		{
			return 0;
		}
		str1++;
		str2++;
		count--;
	}
	if (0 == count)
	{
		return 0;
	}
	else
	{
		return *str1 - *str2;
	}
}

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

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值