string库函数对大家来说一定都不陌生,这是一个我们很经常用到的库函数,用作各种字符串之间的操作,但是我们平常使用到的都是标准库中已经制作并封装好之后的函数,那么这些函数到底是怎么实现的呢?今天我们就来分别实现一下string中的各种函数,让我们对于string标准库中的函数有更加深刻的认识。
1.strlen函数的实现
可以说strlen函数是我们string库函数中最常用到的函数了,起作用就是求字符串的长度。实现这个函数的方法有许多种,今天我们就选择一种最简单的来向大家实现strlen函数。
我们想要实现一个函数第一步要做的就是了解其作用以及传入参数和返回值。这些我们都可以通过上网的方式进行查找。在这里向大家推荐一个特别方便的查找函数的网址:https://legacy.cplusplus.com/
就比如strlen函数:
我们来分析一下上图中的数据 括号中的是我们所传的参数,我们需要向函数中传入一个字符串的指针也就是字符串的首地址,因为我们只计算字符串的长度但是不改变字符串的内容,那么为了保证函数传参的安全性用const来修饰。这个函数的返回值是size_t也就是一个无符号整型。作用就是查找字符串的长度。那么我们就可以根据这些信息来设计函数了。设计效果如下:
#include<stdio.h>
//自定义函数strlen求字符串长度 1.count计数法
//int my_strlen(char* ch, int sz)
//{
// int count = 0;
// char* c = ch;
// while (*c++)
// {
// count++;
// }
// return count;
//}
//自定义函数strlen求字符串长度 2.指针相减法
//int my_strlen(char* ch1, char* ch2)
//{
// return ch2 - ch1;
//}
//自定义函数strlen求字符串长度 3.函数递归法
int my_strlen(char* ch)
{
if (*ch != '\0')
{
return 1 + my_strlen(ch + 1);
}
else
{
return 0;
}
}
int main()
{
char ch[] = "deig";
int sz = sizeof(ch) / sizeof(ch[0]);
char* c = ch;
int ret = my_strlen(c);
printf("%d", ret);
return 0;
}
像我们自己制作的函数中传入指定字符串的首地址就可以得到该字符串的长度。
2.strcmp函数的实现
和上面相同,我们先来了解一下strcmp函数的返回值以及传参情况:
strcmp函数的作用是判断两个字符串是否相等。那么我们需要像函数中所上传的参数就是两个字符数组的首地址了。对于这个函数的返回值我们可能很疑惑,没关系,我们再来通过一张照片来认识一下这个函数的返回值。
由上面我们可以知道,这个函数会将两个字符串中的内容一个一个比较大小,如果一样就比较下一个字符,直到比较结束,如果两个字符串完全一样那么就返回0。如果A字符串的字母大于B字符串中的字母就返回>0的数字。(A字符串为先传的参数)。反之,则返回一个小于0的数字。值得我们注意的是,由于我们这个函数是一个字母一个字母进行比较的,返回结果自然会与第一个不相同的字符相符。例:abczz和abdaa 由于第一个不相同的字符为c和d且c<d那么就会返回一个小于0的数字,即使后面第一个字符串中的字符为zz第二个字符串的字符为aa也是如此。
在知道了这个函数的各部分细节那么我们就可以根据这些细节自己自定义出相对应的函数了。
#include<stdio.h>
#include<string.h>
//strcmp的应用
//int main()
//{
// char ch1[] = "abodef";
// char ch2[] = "abodef";
// int ret= strcmp(ch1, ch2);
// if (ret == 0)
// {
// printf("相等\n");
// }
// else if (ret >0)
// {
// printf("ch1>ch2");
// }
// else
// {
// printf("ch1<ch2");
// }
//
// return 0;
//}
//模拟实现my_strcmp函数
int my_strcmp(char* ch1, char* ch2)
{
char* tmp1 = ch1;
char* tmp2 = ch2;
while ((*tmp1 == *tmp2)&&(*tmp1!='\0')) //在使用括号内置++时可能会出现下一个字符判断错误的情况,为了避免这种情况,尽量
{ //将++放到大括号里面进行
tmp1++;
tmp2++;
}
return *tmp1 - *tmp2;
}
int main()
{
char ch1[] = "aboaef";
char ch2[] = "abodef";
int ret = my_strcmp(ch1, ch2);
if (ret == 0)
{
printf("相等\n");
}
else if (ret > 0)
{
printf("ch1>ch2");
}
else
{
printf("ch1<ch2");
}
return 0;
}
上面就是我们自己 所创造的strcmp函数,是不是效果跟库函数中的函数一摸一样呢?
3.strcpy函数的实现
同样的我们先来了解一下函数的详情:
strcpy函数的作用是将一个字符数组中的内容复制到另外一个字符数中之中。如图就是将source中的值复制到destination当中。由于我们想要的结果是只改变destination数组中值而不希望改变source数组中的值,那么我们会用const来修饰并保护source指针。我们这个函数在将source中的值全部复制到destination终止后会将destination的首地址作为返回值返回出去。我们同样的可以利用字符指针进行接收,或者直接利用%s进行字符串的打印。函数的实现如下:
#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* ch1,const char* ch2)
{
assert(ch1 && ch2);
char* ret = ch1;
while (*ch1++ = *ch2++)
{
;
}
return ret;
}
int main()
{
char ch1[20] = "abcdef";
char ch2[20]="hello";
my_strcpy(ch1, ch2);
printf("%s", ch1);
return 0;
}
效果如上,我们将数组1的之进行打印可以发现,我们数组中的内容已经改变为我们数组二中的内容了。
4.strcat函数的实现
那么我们长话短说,直接来认识这个函数。
我们可以发现这个函数和我们的strcpy函数很相似,无论是参数还是返回值都是一模一样的。那我们先来认识一下这个函数的作用,我们这个函数是将两个字符串连接起来,也就是将source的内容连接到destination的后面然后再返回destination的首地址。我们可以通过这个首地址进行打印等操作。 那么我们接下来直接看代码:
#include<stdio.h>
#include<string.h>
//strcat的使用
//int main()
//{
// char ch1[20] = "abc";
// char ch2[] = "defg";
// char*c=strcat(ch1, ch2);
// printf("%s", c);
// return 0;
//}
//strcat的模拟
char* my_strcat(char* ch1,const char* ch2)
{
char* tmp1 = ch1;
//找到'\0'
while (*ch1)
{
*ch1++;
}
//对ch1进行赋值
while (*ch1++ = *ch2++)
{
;
}
return tmp1;
}
int main()
{
char ch1[20] = "abc";
char ch2[] = "1234";
printf("%s", my_strcat(ch1, ch2));
return 0;
}
上面就是我们strcat函数的实现。
5.strstr函数的实现
strstr函数是string函数中比较难的一个函数,那么我们就将其作为我们本次博客的最后一个自定义函数来实现一下其内容。
就像上面我们看到的一样,我们这个函数的参数也是两个指针,但是起作用却大大不同。strstr函数的作用就是判断str2字符串是否为str1字符串的子集,如果是,那么就返回str2在str1中的首字母的地址,如果str2不是str1的子集的话就返回空指针NULL。这个函数在大项目的实现之中可能用到的比较多,接下来,我们就来实际操作实现一下这个函数。
#include<stdio.h>
#include<string.h>
//strstr函数的使用
//int main()
//{
// char ch1[] = "abcdefgh";
// char ch2[] = "defg";
// printf("%s", strstr(ch1, ch2));
// return 0;
//}
//自定义函数 my_strstr对字符串子集的查找
//char* my_strstr(char* h1, char* h2)
//{
// char* c = h2;
// int flag = 0;
// while ((*h1 != *h2)&&*h1!='\0')
// {
// h1++;
// }
// char* ret = h1;
// while ((*h1 == *h2)&&*h2!='\0')
// {
// ++h1;
// ++h2;
// }
// if(*h2=='\0')
// {
// return ret;
// }
// else if(*h1=='\0')
// {
// return NULL;
// }
// else
// {
// return my_strstr(++ret, c);
// }
//}
char* my_strstr(const char* ch1, const char* ch2)
{
const char* s1 = NULL;
const char* s2 = NULL;
const char* sp = ch1;
if (*ch2 == '\0')
{
return (char*)ch1;
}
while (*sp)
{
s1 = sp;
s2 = ch2;
while (*s1 && *s2 &&(*s1 == *s2))
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return (char*)sp;
}
sp++;
}
return NULL;
}
int main()
{
char ch1[] = "abbbcefgh";
char ch2[] = "def";
char ch3[] = "bcef";
char ch4[] = "cef";
printf("%s\n", my_strstr(ch1, ch2));
printf("%s\n", my_strstr(ch1, ch3));
printf("%s\n", my_strstr(ch1, ch4));
printf("%s", my_strstr(ch1, ""));
return 0;
}
上述我们采用了两种方法进行strstr函数的模拟,第一种偏向于部分功能逐步的实现,第二种比较整体,结构更加严谨。
此上就是我们本次博客的全部内容,感谢您的观看,祝您天天开心。