前言

在C语言的库函数中,有着一些我们可能会经常使用到的字符串函数,它们的头文件都是string.h,为了方便更好的理解并且记忆这些字符串函数,让我们来自己编写这些字符串函数,看看它们到底是怎么运行的

一、求字符串长度(strlen)

1.1strlen函数的使用

我们首先来看一下strlen这个函数的原型

C语言字符串函数_bc

其中Get the length of a string.的意思是返回一个字符串的长的

size_t 可以理解为是函数返回类型, strlen是函数名,const charstring是这个函数的参数,参数的类型是char,加上const是来保护参数不会被修改 

接下来是具体的使用

C语言字符串函数_#include_02

在调用strlen函数的时候,格式为streln(数组名),但是因为strlen函数是有返回值的,因此在上述代码中我们把一个字符串“abcdef",放进字符数组arr中,,利用ret来接收库函数strlen的返回值,最后打印出结果,那么strlen函数要怎么才会停下来呢

其实strlen函数在执行的时候,只要遇到‘\0’就会停下

C语言字符串函数_字符串_03

当我们在d后放一个‘\0’进去,结果是不是立刻就变了

1.2my_strlen的实现

通过对strlen函数的使用,我们知道了该函数有一个返回值,用来返回字符串的长度,函数的参数是char*类型,并且用const来保护参数,以及,strlen函数在遇到'\0'时会停下,了解这些,我们就可以来书写自己的strlen函数了

如下

#include<stdio.h>
#include<string.h>
#include<assert.h>
int my_strlen(const char* arr)
//返回类型为int,用指针来接收参数
{
	assert(arr);
  /*assert也是一个库函数,头文件是#include<assert.h>,他的作用是保证
  我们传过来的参数不为空*/
	int len = 0;//len是我们要返回的字符串长度,初始化为0
	while (*arr++)/*arr初始指向字符串的第一个字符,如果遇到结束符标志
  (\0就相当于是0,0为假,退出循环)则退
  出循环,不是则长度加1,++是后置,因此arr先被使用(即*arr,表示指向位置的
  字符)再++指向第二个字符,以此类推*/
	{
  len++;
	}
	return len;//最后返回字符串长度
}
int main()
{
	char arr[] = "abcd\0ef";
	int ret = strlen(arr);
	printf("%d ", ret);//库函数结果
	int ret1 = my_strlen(arr);
	printf("%d ", ret1);//我们自己编写函数的结果
}

调试结果如下

C语言字符串函数_#include_04

我们可以看到结果是相同的

二、字符串拷贝(strcpy)

2.1strcpy函数的使用

我们首先来看看strcpy函数的原型

C语言字符串函数_bc_05

C语言字符串函数_bc_06

我们可以看到返回类型是char*,有两个参数,我们来看看对这两个参数的解释

Destination string,目标字符串,Null-terminated source string,以\0结束 的源头字符串,也就是说我们要把源头字符串拷贝到目标字符串上,让我们看看该怎么使用

C语言字符串函数_字符串_07

经过调试我们看到arr1里放的是我们的字符串,

C语言字符串函数_#include_08

而arr2则是部分初始化

C语言字符串函数_字符串_09

调用strcpy函数后,我们可以看到arr2拷贝了arr1的全部内容,包括\0,

这样我们是不是就很清楚了,但是在具体使用的过程中,我们还要注意目标数组的空间要足够大,并且它是可变的,而源头字符串是以\0结尾,并且拷贝的时候会拷贝\0,

2.2my_strcpy的实现

有了上面的细节知识,我们直接上代码

#include<string.h>
#include<assert.h>
#include<stdio.h>
char* my_strcpy(char* dest,const char* src)
//保护源头字符串src,目标函数dest必须可变
{
	assert(dest && src);//断言确保非空
	char* ret = dest;//保存目标函数dest第一个字符的位置
	while (*dest++ = *src++)//一开始,各自指向自己的第一个字符
  /*后置++,因此*src先把自己的字符赋值给*dest,然后dest和src分别指向下
  一个字符,一直到 *src把\0赋值给*dest后,表达式为假,跳出循环
	{
  	;
	}
	return ret;//返回指向目标函数第一个字符的指针
}
int main()
{
	char arr1[] = "abcdef";
	char arr2[30] = { 1,2,3,4,5,6,7 };
	strcpy(arr2, arr1);
	my_strcpy(arr2, arr1);
	printf("%s\n", arr2);
}

调试结果如下

C语言字符串函数_#include_10

三、字符串连接(strcat)

3.1strcat的使用

顾名思义,strcat函数就是把一个字符串连接到另一个函数的后面,它其实就相当于从目标函数的\0处开始,将源头字符串的字符依次拷贝给目标字符串,

函数原型

C语言字符串函数_#include_11

参数解释

C语言字符串函数_字符串_12

可以看到两个参数都是以\0结尾的字符串

我们直接来使用

C语言字符串函数_#include_13

C语言字符串函数_字符串_14

C语言字符串函数_字符串_15

我们要arr2连接到arr1后去,经过调试我们可以看到arr2的字符串确实被连接到了arr1后,同样的我们在具体使用的时候,也要注意目标字符串的空间一定要足够大并且可以修改,源头字符串也要以\0结尾

3.2my_strcat的实现

相比字符串拷贝函数,我们多做的仅仅是找到目标函数的\0,然后从\0开始

进行字符串拷贝

#include<string.h>
#include<assert.h>
#include<stdio.h>
char* my_strcat( char* dest, const char* src)
{
	assert(dest && src);
	char* ret = dest;//记录目标字符串第一个字符的位置
	while (*dest)//寻找并指向目标字符串的\0
	{
  dest++;
	}
	while (*dest++ = *src++)//从\0开始拷贝
	{
  ;
	}
	return ret;//返回指向dest第一个字符的指针
}

int main()

{

	char arr1[30] = "hello ";

	char arr2[] = "world";

	/*strcat(arr1, arr2);*/

	my_strcat(arr1, arr2);

	printf("%s\n", arr1);

}

四、字符串比较(strcmp)

4.1strcmp函数的使用

字符串比较函数比较的不是两个字符串的长度,而是对应位置上字符ASCIL码值的大小

函数原型

C语言字符串函数_bc_16

因为是比较,使以两个字符串都被const保护

C语言字符串函数_#include_17

也就是第一个字符串大于第二个字符串,则返回大于0的数字第一个字符串等于第二个字符串,则返回0 第一个字符串小于第二个字符串,则返回小于0的数字的意思,比较方法就是逐个比较两个字符串对应位置字符的ASCIL的大小

C语言字符串函数_字符串_18

经过字符串比较函数,可以看到结果是arr1小于arr2,为什么呢?

两个字符串第一个字符都相同,然后看各自的下一个字符,也相同,再看第三个字符,arr1是c,arr2是d,c的ASCIL小于d,因此在字符串比较中arr1小于arr2

C语言字符串函数_字符串_19

再来看,虽然两个字符串前四个字符都相同,但第五个字符,arr1是e,而arr2是\0,e的ASCIL更大,所以是greater

4.2my_strcmp的实现

直接上代码

#include<string.h>
#include<assert.h>
#include<stdio.h>
int my_strcmp(const char* arr1, const char* arr2)
{
	while ((*arr1++ == *arr2++) != '\0')
  /*依次判断两个字符串对应字符是否相等且不等于\0*/
	{
 	 ;
	}
	return *arr1 - *arr2;
  //循环出来的时候,代表此时各自对应位置的字符不相同,*arr1-*arr2大于0
  //则arr1更大,反之则更小
}
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abcd";
	int ret=my_strcmp(arr1, arr2);
	if (ret == 0)
	{
  	printf("相同\n");
	}
	else
	{
  	if (ret > 0)
 	 {
  		printf("arr1>arr2\n");
  	}
  	else
  	{
  		printf("arr1<arr2\n");
  	}
	}
}

结果如下

C语言字符串函数_字符串_20

五、字符串字符串(strstr)

5.1strstr函数的使用

该函数的功能是在一个字符串中查找另一个字符串,如果找到,则返回起始地址,找不到则返回空,找到多个,则只返回第一个起始地址

函数原型

C语言字符串函数_bc_21

参数解释

C语言字符串函数_bc_22

上手使用

C语言字符串函数_bc_23

我们在arr1里找arr3,找到了所以返回arr1里arr2起始字符的地址

C语言字符串函数_bc_24

arr1里没有arr2,因此返回为NULL

5.2my_strstr的实现

我们要想实现strstr函数,需要用到三个指针,

第一个指针首先保存查找字符串的首字符(这里的首字符其实是当前指向的位置),第二个指针指向第一个指针的位置,然后依次向后查找等于被查找字符串的第一个字符,第三个指针保存被查找字符串的当前位置

#include<stdio.h>
#include<assert.h>
#include<string.h>
char* my_strstr(const char* arr1, const char* arr2)
{
	char* s1=NULL;
	char* s2=NULL;
	char* cp = (char*)arr1;//保存查找字符串的当前位置
	while (*cp)//依次向后擦查询
	{
  s1 = cp;   //指向查找字符串的当前位置
  s2 = (char*)arr2;//指向被查找字符串的当前位置
  while (*s1 && *s2 && *s1 == *s2)
  //两者都没查询完且对应位置相等,则依次比较下一个位置的字符
  {
  	s1++;
  	s2++;
  }
  if (*s2 == '\0')//s2如果等于\0,表示s2查询完了,并且在s1中找到了s2
  {
  	return cp; //返回s1中s2的起始位置
  }
  cp++;//如果不相等,则下一个比较的位置是当前位置的下一位置
	}
  return NULL;//查询结束后任然没有找到,则返回空
}
int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "bcf";
	char arr3[] = "cde";
	char* p = my_strstr(arr1, arr3);
	if (p)
	{
  printf("find it %s\n", p);
	}
	else
	{
  printf("not find\n");
	}
}

调试结果如下

C语言字符串函数_#include_25

C语言字符串函数_字符串_26