目录
导读:
strcpy strcat和strstr为字符串函数
memcpy和memmove则为内存函数
本文我们将会讲到这些函数的使用以及如何自身模拟实现
每个模拟实现的代码内也配有注释
1.strcpy函数
1.1strcpy函数的作用及基本用法
char * strcpy ( char * destination, const char * source );
strcpy是stringcopy的简写,表示”字符串复制函数“,作用是将source指向的字符串复制到 destination指向的函数中去。
1.2注意:
- 源字符串必须以 '\0' 结束。
- 会将源字符串中的 '\0' 拷贝到目标空间。
- 目标空间必须足够大,以确保能存放源字符串。
- 目标空间必须可变。
1.3模拟实现strcpy 函数
char* my_strcpy(char* dest, const char* src)
{
char* ret = dest;//保存目标空间的起始地址
while ((*dest++ = *src++))
{
;
}
return ret;//返回目标
}
int main()
{
char arr1[100] = { 0 };
char arr2[] = "Hello world!";
my_strcpy(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
2.strcat函数
2.1strcat函数的作用及基本用法
strcat —— 字符串连接函数 一般形式如下:
char * strcat ( char * destination, const char * source );
调用形式strcat(字符数组1,字符数组2),把源字符串连接到目标字符串后面,结果放在目标字符数组中,函数调用后得到一个函数值——目标字符串的地址
2.2注意:
- 源字符串必须以 '\0' 结束。
- 目标空间必须有足够的大,能容纳下源字符串的内容。
- 目标空间必须可修改。
2.3模拟实现 strcat函数
char* my_strcat(char* dest, const char* src)
{
char* ret = dest;//记录目标字符串的起始地址
while (*dest != '\0')//先进入循环,一直到它本身字符内容的后面
{
dest++;
}
while (*dest++ = *src++)//把src解引用赋值给dest,包括'\0'
{
;
}
return ret;//返回目标字符串的起始地址
}
int main()
{
char arr1[100] = "Hello";
char arr2[] = " world!";
my_strcat(arr1, arr2);
printf("%s\n", arr1);
return 0;
}
3.strstr函数
3.1strstr函数的作用及基本用法
strstr函数用于在一个字符串中查找另一个字符串的第一次出现位置,并返回该位置的指针
char * strstr ( const char *str1, const char * str2);
str1是要被搜索的字符串,str2是要搜索的字符串。
如果str2是空字符串则返回str1
如果str2没有在str1中出现则返回NULL。
3.2模拟实现strstr函数
const char* my_strstr(const char* str1, const char* str2)
{
const char* cp;//记录开始匹配的位置
const char* s1;//遍历str1
const char* s2;//遍历str2
if (*str2 == '\0')//如果str2为空,直接返回
{
return str1;
}
cp = str1;//指向str1起始位置
while (*cp)
{
s1 = cp;
s2 = str2;
while (*s1 && *s2 && *s1 == *s2)//*s1 *s2不指向\0,s1 = s2进入循环
{
s1++;//往后加开始遍历
s2++;
}
if (*s2 == '\0')//循环结束后,如果s2为'\0'表面已经找到
{
return cp;
}
cp++;//循环结束后,s2不为'\0'说明还没有找到,cp自加一
}
return NULL;
}
int main()
{
char arr1[] = "abbbcd";
char arr2[] = "bbc";
char* ret = my_strstr(arr1, arr2);
if (ret == NULL)
{
printf("找不到\n");
}
else
{
printf("%s\n",ret);
}
return 0;
}
4.memcpy函数
4.1memcpy函数的作用及基本用法
是将一段内存区域的数据复制到另一个内存区域。它可以用来实现结构体、数组等复杂数据类型的复制。
void * memcpy ( void * destination, const void * source, size_t num );
destination表示目标内存区域的地址,source表示源内存区域的地址,num表示要复制的字节数。
4.2注意:
- 目标内存区域和源内存区域不能重叠,否则结果会不可预料。
- 要复制的字节数num不能超过目标内存区域和源内存区域的有效长度,否则会造成越界访问的错误。
- 该函数从src指向的内存地址开始,向后复制num个字节到destination指向的内存地址开始处
4.3模拟实现 memcpy函数
void* my_memcpy(void* dest, void* src, size_t sz)
{
while (sz--)
{
*(char*)dest = *(char*)src;//由于memcpy函数是以字节为单位进行copy
//int类型为四个字节,所以这里需要强转为char*类型,一个字节一个字节的复制
dest = (char*)dest + 1;//强转类型都是临时的,并不会永远改变类型
src = (char*)src + 1;//所以这里仍需再次强转为char*
}
}
int main()
{
int arr1[10] = { 0 };
int arr2[] = { 0,9,2,6 };
my_memcpy(arr1, arr2, 16);//16个字节,也就是4个int类型
int i = 0;
for (i = 0; i < 4; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
5.memmove函数
5.1memmove函数的作用及基本用法
其作用是在内存区域移动一定数量的字节,并返回指向目标内存区域的指针。
与memcpy函数作用类似
void * memmove ( void * destination, const void * source, size_t num );
destination表示目标内存区域的指针,source表示源内存区域的指针,num表示要移动的字节数。
5.2注意:
- 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
- 如果源空间和目标空间出现重叠,就得使用memmove函数处理。
5.3模拟实现memmove函数
5.3.1注意:
由于在移动中,可能出现前面的值移动到后面,把重叠内存的值给改变
到把重叠内存的内容再往后移动时,该区域原先的值已发生改动
最初值丢失导致与预想的结果不一样,所以这里要区分情况
5.3.2代码实现:
void* my_memmove(void* dest, const void* src, size_t sz)
{
void* ret = dest;//记录目标字符串的起始地址
//如把后面的内存指针移动到前面
//移动轨迹为从前到后,先改变目标内存前面的内容,再依次改变后面的内存
if (dest < src)
{
while (sz--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
//如果把前面的内存区域移动到后面的内存区域
//移动轨迹为从后到前,先改变目标内存后面的内容,再依次改变前面的
else
{
while (sz--)
{
*((char*)dest + sz) = *((char*)src + sz);
}
}
return ret;
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
my_memmove(arr, arr + 1, 16);//从第2个元素开始往后数4个元素,移动到下标为0的内存中
int i = 0;
for (i = 0; i < 9; i++)
{
printf("%d ", arr[i]);
}
return 0;
}