函数的模拟实现
通过本次对库函数的模拟实现,提升了代码能力的同时也加深了对这些库函数的理解,为今后的学习过程中的快捷使用打下了基础 |
📘模拟实现strlen
💦cplusplus中strlen是这样的
#include<assert.h>
#include<stdio.h>
size_t my_strlen(const char* str)
{
assert(str);
const char* start = str;
const char* end = str;
while (*end != '\0')
{
end++;
}
return end - start;
}
int main()
{
char arr[] = "abcdef";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
💦运行结果:
💡strlen遇到’\0’停止,如果字符数组中没有’\0’,运行程序后最后的值就是一个随机值,在使用时要注意’0’这个特殊的元素
📘模拟实现strcpy
💦cplusplus中strcpy是这样的
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{
assert(dest);
assert(src);
char* ret = dest;
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr1[20] = "abc";
char arr2[] = "hello bit";
printf("%s\n", my_strcpy(arr1, arr2));
return 0;
}
💦运行结果:
💡在这个函数中我们没有动态开辟内存,所以在将arr2复制到arr1里面去的时候要注意arr1的大小要大于arr2,虽然我们看到例子中也能正常拷贝,但是还是要尽量避免这样的错误
💡同样如果arr1中是一个常量字符串的话,也不能进行正常拷贝,p 的确指向其地址,但该地址存在于在进程的 text 段,text 段除了保存常量还保存可执行代码,因此是不允许可写权限的,而是只允许可读、可执行权限。
📘模拟实现strncpy
💦cplusplus中strncpy是这样的
#define _CRT_SECURE_NO_WARNINGS
#include<assert.h>
#include<stdio.h>
char* strncpy(char* destination, const char* source, size_t num)
{
assert(destination);
assert(source);
char* ret = destination;
while (num--)
{
*destination++ = *source++;
}
return ret;
}
int main()
{
char str1[] = "abcdefghi";
char str2[] = "xxxx";
printf("%s", strncpy(str1, str2, 2));
return 0;
}
运行结果:
📘模拟实现strcmp
💦cplusplus中strcmp是这样的
#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* s1, const char* s2)
{
assert(s1 && s2);
while (*s1 == *s2)
{
if (*s1 == '\0')
{
return 0;
}
s1++;
s2++;
}
return *s1 - *s2;
}
int main()
{
char arr1[] = "abc";
char arr2[] = "abc";
int ret = my_strcmp(arr1, arr2);
if (ret < 0)
printf("arr1<arr2\n");
else if(ret>0)
printf("arr1>arr2\n");
else
printf("arr1==arr2\n");
printf("%d\n", ret);
return 0;
}
💦运行结果:
📘模拟实现strcat
💦cplusplus中strcat是这样的
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
char* my_strcat(char* dest, const char*src)
{
//1.找目标空间中的\0
char* cur = dest;
while (*cur)
{
cur++;
}
//2.拷贝源头数据到\0之后的空间
while (*cur++ = *src++)
{
;
}
return dest;
}
int main()
{
char arr1[20] = "hello ";
char arr2[] = "world!";
printf("%s\n", my_strcat(arr1, arr2));
return 0;
}
💦运行结果:
💡这个与strlen相似,要求arr1中要有’\0’,同时也要满足arr1的大小比arr2大
📘模拟实现strncat
💦cplusplus中strncat是这样的
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
char* strncat(char* destination, const char* source, size_t num)
{
char* cur = destination;
while (*cur)
{
cur++;
}
while (num--)
{
*cur++ = *source++;
}
*cur = '\0';
return destination;
}
int main()
{
char str1[20] = "hello ";
char str2[] = "world !!!";
printf("%s", strncat(str1, str2, 7));
return 0;
}
运行结果:
📘模拟实现strstr
💦cplusplus中strstr是这样的
1、暴力求解
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
char* my_strstr(const char* str1, const char* str2)
{
const char* s1 = str1;
const char* s2 = str2;
const char* p = str1;
if (*str2 == '\0')
{
return (char*)str1;
}
while (*p)
{
s1 = p;
s2 = str2;
while (*s1!='\0' && *s2!='\0' && (*s1 == *s2))
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return (char*)p;//找到了
}
p++;
}
return NULL;//找不到子串
}
int main()
{
char arr1[] = "abcdefabcdef";
char arr2[] = "cdq";
char* p = my_strstr(arr1, arr2);
if (p == NULL)
{
printf("不存在\n");
}
else
{
printf("%s\n", p);
}
return 0;
}
💦运行结果:
2、KMP算法
📘模拟实现memset
💦cplusplus中memset是这样的
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
void* my_memset(void* ptr, int value, size_t num)
{
void* p = ptr;
assert(ptr);
while (num--)
{
*(char*)ptr = value;
ptr = (char*)ptr + 1;
}
return p;
}
int main()
{
char arr1[] = "1234568";
my_memset(arr1, 'a', 4);
printf("%s", arr1);
return 0;
}
💦运行结果:
💡特别注意size_t num指的是从起始地址开始的字节数,在对非字符数组使用这个函数的时候要特别注意
📘模拟实现memcpy
memcpy只需要实现不重叠的拷贝就可以了 - 60分,但在vs测试中我们发现可以达到 100分
💦cplusplus中memcpy是这样的
#define _CRT_SECURE_NO_WARNINGS
#include <assert.h>
#include<stdio.h>
void* my_memcpy(void* dest, void* src, size_t num)
{
void* ret = dest;
assert(dest);
assert(src);
while(num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[10] = { 0 };
my_memcpy(arr2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
💦运行结果:
💡memcpy可以说是strcpy的进阶版了,可以用于各种类型的数据的拷贝,注意事项与strcpy相似
📘模拟实现memmove
memmove是需要实现重叠内存的拷贝的(100)
💦cplusplus中memmove是这样的
💡memmove可以说是memcpy的进阶版了,可以用于各种类型的数据的拷贝,同时还可以实现重叠内存的一个拷贝,注意事项与strcpy相似
#define _CRT_SECURE_NO_WARNINGS
#include<assert.h>
#include<stdio.h>
void* my_memmove(void* dest, void* src, size_t num)
{
void* ret = dest;
assert(dest);
assert(src);
if (dest < src)//1 前->后
{
while (num--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else //2 3 后->前
{
while (num--)
{
*((char*)dest + num) = *((char*)src + num);
}
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr1+2, arr1, 20);
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
💦运行结果:
📘模拟实现qsort
💦cplusplus中qsort是这样的
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
//qsort 可以排序任意类型的数据
//void qsort(void* base, //待排序数据的起始地址
// size_t num, //待排序数据的元素个数
// size_t size, //待排序数据元素的大小(单位是字节)
// int (*cmp)(const void*, const void*) //比较2个元素大小的函数指针
// );
//
void print(float arr[], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%lf ", arr[i]);
}
printf("\n");
}
int cmp_int(const void* e1, const void* e2)
{
return (*(int*)e1 - *(int*)e2);
}
void Swap(char* buf1, char* buf2, int width)
{
int i = 0;
for (i = 0; i < width; i++)
{
char tmp = *buf1;
*buf1 = *buf2;
*buf2 = tmp;
buf1++;
buf2++;
}
}
void my_qsort(void* base, int sz, int width, int (*cmp)(const void* e1, const void* e2))
{
int i = 0;
for (i = 0; i < sz - 1; i++)
{
int j = 0;
for (j = 0; j < sz - 1 - i; j++)
{
if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)
{
Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
}
}
}
}
//测试qsort函数排序整型数据
void test1()
{
int arr[] = { 2,1,3,7,5,9,6,8,0,4 };
int sz = sizeof(arr) / sizeof(arr[0]);
my_qsort(arr, sz, sizeof(arr[0]), cmp_int);
print(arr, sz);
}
//测试qsort函数排序浮点型数据
void test2()
{
float arr[] = { 2.0f,1.0f,3.0f,7.0f,5.0f,9.0f,6.0f,8.0f,4.0f };
int sz = sizeof(arr) / sizeof(arr[0]);
my_qsort(arr, sz, sizeof(arr[0]), cmp_int);
print(arr, sz);
}
struct Stu
{
char name[20];
int age;
};
int cmp_stu_by_name(const void* e1, const void* e2)
{
return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}
int cmp_stu_by_age(const void* e1, const void* e2)
{
return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
//测试qsort排序结构体数据
void test3()
{
struct Stu s[] = { {"zhangsan", 20}, {"lisi", 55}, {"wangwu", 40} };
int sz = sizeof(s) / sizeof(s[0]);
my_qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
my_qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);
}
int main()
{
test1();
test2();
test3();
return 0;
}
💦运行结果: