江河入海,知识涌动,这是我参与江海计划的第3篇。
<一>字符串函数
1.strstr
1.1 strstr的介绍
1.2 strstr的模拟实现
2.strerror
2.1 strerror的介绍
2.2 strerror的模拟实现
<二>内存函数
3.memcpy
2.1 memcpy的介绍
2.2 memcpy的模拟实现
4.memmove
2.1 memmove的介绍
2.2 memmove的模拟实现
5.memset
5.1 memset的介绍和注意事项
5.2 memset的使用
6.memcmp
5.1 memcmp的介绍和注意事项
5.2 memcmp的使用
c语言中还有很多库函数,等待着大家学习!
<一>字符串函数
1.strstr
1.1 strstr的介绍
Returns a pointer to the first occurrence of str2 in str1, or a null pointer if str2 is not part of str1.
(函数返回字符串str2在字符串str1第一次出现的位置,简单点说就是:返回地址。)
The matching process does not include the terminating null-characters, but it stops there.
(字符串的比配不包含'\0',以字符\0作为结束的标志.
1.2 strstr的模拟实现
strstr的模拟实现
#include<assert.h>
const char* my_strstr(const char* str1,const char* str2)
{
assert(str1 && str2);
const char* s1 = NULL;
const char* s2 = NULL;
const char* cur = str1;
if (*str2 == '\0')
return NULL;
while (*cur != '\0')
{
s1 = cur;
s2 = str2;
while (*s1 && *s2 && *s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0')
return cur;
cur++;
}
}
int main()
{
char str1[20] = "abbbcdefgd";
char str2[20] = "bbcde";
const char* p = my_strstr(str1, str2);
if (p != NULL)
{
printf("%s\n", p);
}
else
{
printf("不存在\n");
}
}
1.3运行结果
2.strerror
2.1 strerror的介绍
strerror函数可以把参数部分错误码对应的错误信息的字符串地址返回.
每个不同的C语言标准库或系统的实现中规定错误码,一般是在errno.h这个头文件中说明。C语言程序启动时都会使用一个全局变量errno来记录程序的错误码,程序启动时errno为0,表示没有错误,当我们在使用标准库函数发生某种错误,将会转化为对应的错误码,错误码难理解,所以没一个错误码都有对应的信息,strerror函数可以将对应的错误信息字符串的地址返回。
2.2 strerror的使用例子
#include<string.h>
int main()
{
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d: %s\n",i ,strerror(i));
}
return 0;
}
2.3运行结果
上面可以看到0表示无错误,其他的表示不同的错误信息。
<二>内存函数
3.memcpy
2.1 memcpy的介绍
.函数memcpy从source的位置开始从后复制num个字节的数据到destination的指定位置上。
.这个函数在遇到'\0'的时候不会停止下来。
.如果destinnation和source有任何的重叠,复制的结果不会如我们所愿。
注意:size_t num;---------->num为字节的个数,不是元素的个数。
char类型占一个字节,int占四个字节,double占八个字节。。。。。。。
2.2 memcpy的模拟实现
#include<assert.h>
void* my_memcpy(void* destination, const void* source, size_t num)
{
char* ret = destination;
assert(destination && source);
while (num--)
{
(*(char*)destination) = (*(char*)source);
destination=(char*)destination+1;//(*(char*)source)++报错,强制转换是临时的,本质还是void*
source = (char*)source + 1;
}
return ret;
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int arr2[20] = { 0 };
void* r=my_memcpy(arr2, arr, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ",arr2[i]);
}
return 0;
}
3.3运行结果
对第三点的补充认知
问题:假如我们想从3~7改为1,2,3,4,5,
即改变后的arr[10]={1,2,1,2,3,4,5,8,9,10}
我们可能会这样写代码:
void* my_memcpy(void* destination, const void* source, size_t num)
{
char* ret = destination;
assert(destination && source);
while (num--)
{
(*(char*)destination) = (*(char*)source);
destination=(char*)destination+1;//(*(char*)source)++报错,强制转换是临时的,本质还是void*
source = (char*)source + 1;
}
return ret;
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
void* r=my_memcpy(arr+2, arr, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ",arr[i]);
}
return 0;
}
运行结果:
4.memmove
2.1 memmove的介绍
memmove函数具有memcpy的特点,具有唯一特性就是:memmove可以对重叠的部分进行拷贝。
.如果destination和source具有重叠的部分,切还要进行拷贝就得使用memmove函数。
2.2 memmove的模拟实现
void* my_memmove(void* destination, const void* source, size_t num)
{
char* ret = destination;
assert(destination && source);
if (destination < source)
{
while (num--)
{
(char*)destination = (char*)source;
destination = (char*)destination + 1;
source = (char*)source + 1;
}
}
else
{
while (num--)
{
*((char*)destination+num) = *((char*)source+num);
}
}
return ret;
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
void* r=my_memmove(arr + 2, arr, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
5.memset
5.1 memset的介绍和注意事项
memset用来设置内存的,将内存中的值以字节为单位设置想要设置成的内容。
5.2 memset的使用
5.2.1对int类型的使用
#include<string.h>
int main()
{
int a[20] = {1,2,3,4,5,6,7,8,9,10};
memset(a, 2, 5);
for(int i=0;i<10;i++)
printf("%d\n", a);
return 0;
}
修改前:
修改后:
运行结果:
十六进制(02020202)等价于十进制(33686018)
5.2.2对char的使用
内存展示:
修改前:
修改后:
可以看到是对一个字节单位进行修改的。
6.memcmp
5.1 memcmp的介绍和注意事项
. 比较ptr1和ptr2指针指向的位置开始,向后的num个字节.
. 返回值如下
5.2 memcmp的使用
C语言还有很多库函数等待着大家学习,go,go,go!