目录
1.模拟实现strlen
我们都知道这个函数是用来记录‘\0’之前字符的个数的(不包含‘\0’)。那么我们将如何实现呢?
接下来,博主将以三种方式模拟实现strlen函数。
方式1:常规遍历,当*str == 0时便自动会停下来
//计数器方式
int my_strlen(const char* str)
{
int count = 0;
while (*str)
{
count++;
str++;
}
return count;
}
int main()
{
char* arr[] = { "abcdefg" };
int ret = my_strlen(arr);
printf("%d", ret);
return 0;
}
方式2:利用函数递归实现
//不能创建临时变量计数器
int my_strlen(const char* str)
{
if (*str == '\0')
return 0;
else
return 1 + my_strlen(str + 1);
}
int main()
{
char* arr[] = { "abcdefg" };
int ret = my_strlen(arr);
printf("%d", ret);
return 0;
}
方式3:原理:指针-指针会得到两个指针之间的字符个数
//指针-指针的方式
int my_strlen(char* s)
{
char* p = s;
while (*p != '\0')
p++;
return p - s;
}
int main()
{
char* arr[] = { "abcdefg" };
int ret = my_strlen(arr);
printf("%d", ret);
return 0;
}
2.模拟实现strcpy
这个函数会将源数据拷贝到目标数据中。
//1.参数顺序
//2.函数的功能,停止条件
//3.assert
//4.const修饰指针
//5.函数返回值
//6.题目出自《高质量C/C++编程》书籍最后的试题部分
char *my_strcpy(char *dest, const char*src)
{
char *ret = dest;
assert(dest != NULL);
assert(src != NULL);
while((*dest++ = *src++))
{
;
}
return ret;
}
int main()
{
char arr1[1000] = { "abcdefg" };
char arr2[] = { "aaaa" };
char* ret = my_strcpy(arr1, arr2);
printf("%s", ret);
return 0;
}
char * strcpy(char * destination, const char * source)
所以我们模拟时候,参数是先放目标字符串,再放源字符串。
而我们的停止条件,当*dest++ = *src++; dest 和 src只要有一方为'\0'那么就停止了
assert的作用就是判断dest 和 src是否为空指针的,他的头文件为 #include<assert.h>
至于const,则是为了防止src这个源字符串被修改,我们要改的只是dest。
至于函数返回值ret,我们可以看到他是一个指针,他返回的是目标空间的起始地址。
!注意:这个函数会把源字符串中的'\0'拷贝到目标文件
3.模拟实现strcat
这个函数是将源字符串拷贝到目标字符串的后面。实现代码如下:
#include<stdio.h>
#include<assert.h>
char* my_strcat(char* dest, const char* src)
{
char* ret = dest;
assert(dest != NULL);
assert(src != NULL);
while (*dest)
{
dest++;
}
while ((*dest++ = *src++))
{
;
}
return ret;
}
int main()
{
char arr1[1000] = { "abcdef" };
char arr2[] = { "aaaaa" };
char* ret = my_strcat(arr1, arr2);
printf("%s", ret);
return 0;
}
原理:就是先把目标字符串给遍历到‘\0’的位置,然后再把源字符串一一拷贝进去。
!注意:这里需要先把目标字符串的起始位置拷贝下来,因为strcat函数返回的是目标空间的起始位置。
4.模拟实现strstr
这个函数是在目标字符串中找源字符串第一次出现的位置。找到位置,就返回第一次出现的位置,找不到就返回NULL。
#include<stdio.h>
char* my_strstr(const char* str1, const char* str2)
{
const char* s1;//遍历str1指向的字符串
const char* s2;//遍历str2指向的字符串
const char* cp;//记录str1遍历的起始位置
cp = str1;
while (*cp)
{
s1 = cp;
s2 = str2;
while (*s1 && *s2 && *s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0')
return cp;
cp++;
}
return NULL;
}
int main()
{
char arr1[] = "abbaabababadefg";
char arr2[] = "bababa";
char * ret = my_strstr(arr1, arr2);
if (ret == NULL)
printf("找不到");
else
printf("%s", ret);
return 0;
}
这里最好不要动str1和str2,让cp去记录str1的起始位置,s1和s2分别代替str1和str2去遍历字符串。当*s1 == *s2时,就进入循环,让s1++和s2++,如果*s2 == 0,就说明找到了,这时候就可以返回cp;当*s1 不等于 *s2时,那就让cp++,然后再进行判断是*s1是否等于*s2;当cp指向str1的末尾,也就是'\0'时,那么就说明找不到了,这个时候返回NULL即可。当然这里还要考虑s1和s2是否为空的情况,在while循环中,已经体现了这点。
5.模拟实现strcmp
strcmp函数是string compare(字符串比较)的缩写,用于比较两个字符串并根据比较结果返回整数。
int my_strcmp(const char* p, const char* s)
{
assert(p && s);
while (*p++ == *s++)
{
;
}
if (*p == 0)
return 0;
if (*p > *s)
return 1;
else
return -1;
}
int main()
{
char arr1[] = "abcde";
char arr2[] = "abcc";
int ret = my_strcmp(arr1, arr2);
printf("%d", ret);
return 0;
}
由于我们只是对两个字符串进行比较,不改变其内容,所以我们首先可以加上const修饰,其次我们应该对他们进行assert判断,防止空指针的情况,接着便是通过while循环把两者相同的字符遍历过去,到他们字符不相同的地方,然后进行比较即可。
6.模拟实现memcpy
#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* src, size_t sz)
{
void* ret = dest;
assert(dest && src);
while (sz--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
int main()
{
int arr1[100] = { 0 };
int arr2[] = { 1,2,3,4,5 };
my_memcpy(arr1, arr2, 20);
return 0;
}
需要注意的点就是这里把dest和src强制转化成(char*)类型,是为了方便比较,一个字节一个字节比较,方便不同类型的数据进行比较。
7.模拟实现memmove
void* my_memove(void* des, const void* src,size_t sz)
{
void* ret = des;
assert(des && src);
if(des < src)
{
//从前到后
int i = 0;
for(i = 0; i < sz; i++)
{
*(char*)des = *(char*)src;
des = (char*)des + 1;
src = (char*)src + 1;
}
}
else
//从后到前
while(sz--)
{
*(char*)des + sz = *(char*)src + sz;
}
return ret;
}
int main()
{
int arr[] = {1,2,3,4,5,6,7,8,9,10};
my_memove(arr,arr+2,20);
int i = 0;
for(i = 0; i < 10; i++)
{
printf("%d",arr[i]);
}
return 0;
}
为了防止数据提前丢失,导致结果错误,这里需要注意就是,当dest < src时,我们应该采用从前到后的方式,当dest > src时,我们应该采用从后到前的方式。
举个例子:
这里dest 是 arr, src 是 arr+2,我们可以发现dest在src的前面,所以dest < src的,我们需要从前往后,如果从后往前,7换到5,6换到4,这个时候的5就不是原来的5了,已经给前面换成7了。