前言
在C语言的库函数中,有着一些我们可能会经常使用到的字符串函数,它们的头文件都是string.h,为了方便更好的理解并且记忆这些字符串函数,让我们来自己编写这些字符串函数,看看它们到底是怎么运行的
一、求字符串长度(strlen)
1.1strlen函数的使用
我们首先来看一下strlen这个函数的原型
其中Get the length of a string.的意思是返回一个字符串的长的
size_t 可以理解为是函数返回类型, strlen是函数名,const charstring是这个函数的参数,参数的类型是char,加上const是来保护参数不会被修改
接下来是具体的使用
在调用strlen函数的时候,格式为streln(数组名),但是因为strlen函数是有返回值的,因此在上述代码中我们把一个字符串“abcdef",放进字符数组arr中,,利用ret来接收库函数strlen的返回值,最后打印出结果,那么strlen函数要怎么才会停下来呢
其实strlen函数在执行的时候,只要遇到‘\0’就会停下
当我们在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);//我们自己编写函数的结果
}
调试结果如下
我们可以看到结果是相同的
二、字符串拷贝(strcpy)
2.1strcpy函数的使用
我们首先来看看strcpy函数的原型
我们可以看到返回类型是char*,有两个参数,我们来看看对这两个参数的解释
Destination string,目标字符串,Null-terminated source string,以\0结束 的源头字符串,也就是说我们要把源头字符串拷贝到目标字符串上,让我们看看该怎么使用
经过调试我们看到arr1里放的是我们的字符串,
而arr2则是部分初始化
调用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);
}
调试结果如下
三、字符串连接(strcat)
3.1strcat的使用
顾名思义,strcat函数就是把一个字符串连接到另一个函数的后面,它其实就相当于从目标函数的\0处开始,将源头字符串的字符依次拷贝给目标字符串,
函数原型
参数解释
可以看到两个参数都是以\0结尾的字符串
我们直接来使用
我们要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码值的大小
函数原型
因为是比较,使以两个字符串都被const保护
也就是第一个字符串大于第二个字符串,则返回大于0的数字第一个字符串等于第二个字符串,则返回0 第一个字符串小于第二个字符串,则返回小于0的数字的意思,比较方法就是逐个比较两个字符串对应位置字符的ASCIL的大小
经过字符串比较函数,可以看到结果是arr1小于arr2,为什么呢?
两个字符串第一个字符都相同,然后看各自的下一个字符,也相同,再看第三个字符,arr1是c,arr2是d,c的ASCIL小于d,因此在字符串比较中arr1小于arr2
再来看,虽然两个字符串前四个字符都相同,但第五个字符,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");
}
}
}
结果如下
五、字符串字符串(strstr)
5.1strstr函数的使用
该函数的功能是在一个字符串中查找另一个字符串,如果找到,则返回起始地址,找不到则返回空,找到多个,则只返回第一个起始地址
函数原型
参数解释
上手使用
我们在arr1里找arr3,找到了所以返回arr1里arr2起始字符的地址
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");
}
}
调试结果如下