文章目录
前言
函数的使用,会大大方便我们对代码的抒写,但想要对代码的合理利用,我们必须知道代码实现的逻辑和原理。所以仿写库函数,对于理解是最高效的。
提示:以下是本篇文章正文内容,下面案例可供参考
一、strstr是什么库函数
知识点:strstr 是判断字符串的子串,合理的利用,我们能通过strstr去求左旋字符串和右旋字符串。
函数的调用
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = { "abcdef" };
char arr2[] = { "bcde" };
char* ret = strstr(arr1, arr2);
if (ret == NULL)
{
printf("不存在子串!\n");
}
else
{
printf("%s\n", ret);
}
return 0;
}
仿写库函数
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
char* my_strstr(const char* str1, const char* str2)
{
assert(str1 && str2);
const char* s1 = str1;
const char* s2 = str2;
const char* p1 = str1;
//如果str2 == '\0',直接返回str1;
if (str2 == '\0')
{
return str1;//不存在子串
}
while (*p1)
{
s1 = p1;
s2 = str2;
while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return p1;//找到子串
}
p1++;
}
return NULL;//不存在子串
}
int main()
{
char arr1[] = { "abcdefg" };
char arr2[] = { "bcde" };
char* ret = my_strstr(arr1, arr2);
if (ret == NULL)
{
printf("不存在子串!\n");
}
else
{
printf("%s\n", ret);
}
return 0;
}
二、strtok字符串的分隔符
strtok 第一次传str的指针是被分隔字符串的初始位置的地址,以后传的指针是NULL。
char * strtok(char * str, const char * sep);
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = { "liufu@xiaobite.com" };
char arr2[] = { "@." };//这个是分隔符的字符串集合
char* ret = NULL;
for (ret = strtok(arr1, arr2); ret != NULL; ret = strtok(NULL, arr2))
{
printf("%s\n", ret);
}
return 0;
}
三, strerror错误信息打印的库函数
//当C语言的库函数在执行过程中,发生了错误,就会把对应 的错误码,赋值到errno中
char * str = strerror(errno);
四, 对于整形数组,浮点型数组,结构体数组
对于上述这些数组,也有内存拷贝,内存比较,内存设置的库函数
memcpy 内存拷贝
memcpy 是由:memery 和 copy 组成的,对于C语言来说:memcpy 只处理不重叠的内存拷贝(两块独立的内存空间)
函数调用
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
int arr1[] = { 1,2,3,4,5,6,7 };
int arr2[7] = { 0 };
memcpy(arr2, arr1, sizeof(arr1));//sizeof(arr1),这个参数是size_t size,单位是字节
int i = 0;
for (i = 0; i < 7; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
仿写函数
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{
assert(dest && src);
void* ret = dest;
char* s1 = (char*)dest;
char* s2 = (char*)src;
while (num--)
{
*s1 = *s2;
s1++;
s2++;
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7 };
int arr2[7] = { 0 };
void * ret = my_memcpy(arr2, arr1, sizeof(arr1));//sizeof(arr1),这个参数是size_t size,单位是字节
int i = 0;
for (i = 0; i < 7; i++)
{
printf("%d ", arr2[i]);
}
return 0;
}
memmove 函数
memmove 函数处理的是重叠内存的拷贝
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
int main()
{
//把23456 拷贝到34567当中去
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr + 2, arr + 1, 20);//20个btye
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
仿写库函数
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<assert.h>
void* my_memmove(void* dest, const void* src, size_t num)
{
assert(dest && src);
void* ret = dest;
char* s1 = (char*)dest;
char* s2 = (char*)src;
if (dest > src)//后面——》前面
{
s1 += num - 1;
s2 += num - 1;
while (num--)
{
*s1 = *s2;
s1--;
s2--;
}
}
else
{
//前面——》后面
while (num--)
{
*s1 = *s2;
s1++;
s2++;
}
}
return ret;
}
int main()
{
//把23456 拷贝到34567当中去
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
void * ret = my_memmove(arr + 2, arr + 1, 20);//20个btye
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
memcmp 和 memset
memset 是内存比较,它必须是按照实参的类型去比较,比如int类型,就要int类型比,结构体类型就要结构体类型比,不能转换类型。
memset 是内存设置,也可以说是内存初始化。
int arr[10] = {0};
memset(arr1,1,10);//arr1是数组初始位置,从这个位置开始,把10 int 类型的内存赋值为1.
总结
字符串和内存处理的库函数就先讲解到这里,对于库函数,我认为,要想使用的好,那就要熟悉它的逻辑和原理,更要多用。