//模拟实现strlen
//strlen->计算字符串的元素个数,碰到'\0'结束
//方法一:计数器法
#include<assert.h>
int My_strlen(const char* arr)
{
//断言,确保指针的安全性
assert(arr);
int count = 0;
//strlen计算'\0'之前的元素个数
while (*arr != '\0')
{
//++寻找下一个元素
arr++;
count++;
}
return count;
}
int main()
{
char arr[] = "abcdef";
int ret = My_strlen(arr);
printf("%d\n", ret);
return 0;
}
//方法二:递归法
int My_strlen(const char* arr)
{
//断言,确保指针的安全性
assert(arr);
if (*arr++)
{
return 1 + My_strlen(arr);
}
return 0;
}
int main()
{
char arr[] = "abcdef";
int ret = My_strlen(arr);
printf("%d\n", ret);
return 0;
}
//方法三:指针法
//指针-指针 = 元素个数
int My_strlen(const char* arr)
{
//断言,确保指针的安全性
assert(arr);
//首元素地址
char* ret = arr;
//得到'\0'的地址
while (*arr != '\0')
{
arr++;
}
return arr - ret;
}
int main()
{
char arr[] = "abcdef";
int ret = My_strlen(arr);
printf("%d\n", ret);
return 0;
}
//模拟实现strcpy
//strcpy->字符串拷贝函数
//函数构成:char* strcpy(char* 目标空间,const char* 源头(要拷贝的值))
//将源头字符串包括'\0'传值到目标空间内,以'\0'为结束标志
//注意:目标空间的空间要大于源头空间
#include<assert.h>
char* My_strcpy(char* arr2, const char* arr1)
{
//断言,防止arr2或arr1为空指针
assert(arr2 && arr1);
//因为最后要返回目标空间(arr2)的首元素地址,我们先将arr2首元素地址存储起来
char* ret = arr2;
//将arr1的值依次传给arr2,当最后将'\0'传给arr2后
//判断条件为0,跳出循环
while (*arr2++ = *arr1++)
{
;
}
return ret;
}
int main()
{
char arr1[] = "abcdef";
char arr2[10] = "cdef";
My_strcpy(arr2, arr1);
printf("%s\n", arr2);
return 0;
}
#include<stdio.h>
//strcmp模拟实现
//strcmp比较原则为:元素一对一进行比较:
//大于返回>0
//小于返回>0
//当全部元素包括'\0'都相等时,返回0
#include<assert.h>
int My_strcmp(const char* arr1, const char* arr2)
{
//断言,确保指针可用性
assert(arr1 && arr2);
while (*arr1 == *arr2)
{
//当arr1与arr2的元素全部相等
if (*arr1 == '\0')
{
return 0;
}
arr1++;
arr2++;
}
if (*arr1 > *arr2)
{
return *arr1 - *arr2;
}
else
{
return *arr1 - *arr2;
}
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abcdef";
int ret = My_strcmp(arr1, arr2);
printf("%d\n", ret);
return 0;
}
//模拟实现strcar
//strcar连接字符串函数
//构造:char* strcar(char*连接目标,const char*需连接的字符串)
//寻找目标字符串的'\0',将需要连接的字符串的首地址放到'\0'处依次往后(包括需连接的字符串的'\0')
//直到遇到'\0'结束
#include<assert.h>
char* My_strcar(char* arr1,const char* arr2)
{
//断言,确保指针安全性
assert(arr1 && arr2);
char* ret = arr1;
while (*arr1)
{
arr1++;
}
while ((*arr1++ = *arr2++))
{
;
}
return ret;
}
int main()
{
char arr1[20] = "abcdef";
char arr2[] = "ghi";
My_strcar(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
//模拟实现strstr
//strstr函数->arr1,arr2寻找arr1中arr2的字符串
//最后返回arr1中的arr2的字符串首元素往后的字符
//找到第一次出现的字符,并返回后面的字符
char* My_strstr(const char* arr1, const char* arr2)
{
//定义两个指针用于操作arr1,arr2
char* s1 = NULL;
char* s2 = NULL;
//将arr1的地址存到cp指针内,用于最后寻找相同的元素和最后返回值
char* cp = (char*)arr1;
//循环,当*cp为'\0'时,表示arr1里找不到arr2的字符串
while (*cp)
{
s1 = cp;
s2 = (char*)arr2;
//当*s1、*s2有为'\0'时
//跳出循环
//条件成立arr1与arr2的元素均++
while (*s1 && *s2 && *s1 == *s2)
{
s1++;
s2++;
}
//当*s2为'\0'时,表示已经寻找到
if (*s1 == '\0')
{
return cp;
}
cp++;
}
return NULL;
}
int main()
{
char arr1[] = "abbcdef";
char arr2[] = "bcd";
char* ret = My_strstr(arr1, arr2);
if (NULL == ret)
{
printf("NULL\n");
}
printf("%s\n", ret);
return 0;
}
//模拟实现memcpy
//我们学习过strcpy字符串拷贝库函数
//当我们想拷贝不同类型元素时,我们可以使用memcpy函数
//void* memcpy(void* 目标空间,const void* 源头, size_t 拷贝元素字节个数)
//我们可以通过字节个数来决定我们要拷贝多少个元素到目标空间
// 最后返回拷贝完后目标空间的首元素地址
//遇到'\0'结束
//注意:目标空间要比源头数组空间大
#include<assert.h>
void* My_memcpy(void* arr2, const void* arr1, size_t sz)
{
assert(arr2 && arr1);
//保存arr2的首元素地址,便于之后返回
void* p = arr2;
//我们将arr2与arr1强转为char*有两个理由:
//1.void*指针不能进行*和++、--操作
//2.char*++、--跳过一个字节,而sz为我们要拷贝的字节个数
//无论什么类型,我们可以一个一个字节的拷贝,这样适用于任何类型的拷贝
while (sz--)
{
*((char*)arr2) = *((char*)arr1);
arr2 = (char*)arr2 + 1;
arr1 = (char*)arr1 + 1;
}
return p;
}
int main()
{
float arr1[] = { 1.0f,2.0f,3.0f,4.0f,5.0f,6.0f };
float arr2[10] = { 0.0f };
My_memcpy(arr2, arr1, 20);
int sz = sizeof(arr2) / sizeof(arr2[0]);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%.1f ", arr2[i]);
}
return 0;
}
当我们想将源头元素拷贝到源头数组里呢?memcpy可行吗?
我们发现好像并不行,由此我们引出memmove函数
接下来我们就模拟实现一下memmove函数
//模拟实现memmove
//memmove函数与memcpy基本相同
//可以说memmove函数包含了memcpy的功能
#include<assert.h>
void* My_memmove(void* arr2, const void* arr1, size_t sz)
{
assert(arr2 && arr1);
//保存arr2的首元素地址,便于之后返回
void* p = arr2;
//分情况,如果arr1在arr2的右边
//因为地址是由低到高变化的
if (arr2 < arr1)
{
//从前->后交换
while (sz--)
{
*((char*)arr2) = *((char*)arr1);
arr2 = (char*)arr2 + 1;
arr1 = (char*)arr1 + 1;
}
}
//arr1在arr2的左边时
//或者arr1和arr2元素不重叠
else
{
while (sz--)
{
//从后->前交换
//arr2+sz(字节个数),sz--后 == 字节个数-1
//访问到arr2的最后一个元素空间
//arr1也一样的道理
*((char*)arr2 + sz) = *((char*)arr1 + sz);
}
}
return p;
}
int main()
{
float arr1[] = { 1.0f,2.0f,3.0f,4.0f,5.0f,6.0f };
//float arr2[10] = { 0.0f };
//My_memcpy(arr1+2, arr1, 12);
My_memmove(arr1 + 2, arr1, 12);
int sz = sizeof(arr1) / sizeof(arr1[0]);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%.1f ", arr1[i]);
}
return 0;
}
原理图: