字符串和内存函数(下)

简介: 字符串和内存函数(下)

1.11 memcpy

void * memcpy ( void * destination, const void * source, size_t num );

(1)函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。

(2)这个函数在遇到 '\0' 的时候并不会停下来。

(3)如果source和destination有任何的重叠,复制的结果都是未定义的。如果destination在source的后面,就可能会导致刚改变的destination的内容,又变成了source. 就会导致重复。这种情况建议使用memmove,就不会发生。

代码展示:

1. #include <stdio.h>
2. int main()
3. {
4.  char arr1[] = "sjhjcd";
5.  char arr2[50] = { 0 };
6.  strcpy(arr2, arr1);//拷贝字符串
7. 
8.  int arr3[] = { 1, 2,3,4,5,6,7 };
9.  int arr4[5] = { 0 };
10.   memcpy(arr4, arr3, 20);//这个什么都可以拷贝,不确定拷贝什么
11.   int i = 0;
12.   for (i = 0; i < 5; i++)
13.   {
14.     printf("%d ", arr4[i]);
15.   }
16.   return 0;
17. }

C语言只要求memcpy能拷贝不重叠的的内存空间就足够了,memmove去处理那些重叠的内存空间。但是VS  的memcpy可以处理重叠的内存拷贝,也可以处理不重叠的内存拷贝。

1.12 memmove

void * memmove ( void * destination, const void * source, size_t num );

(1)和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的

(2)如果源空间和目标空间出现重叠,就得使用memmove函数处理。

memmove 也可以处理不重叠的。

1.13 memcmp

int memcmp ( const void * ptr1, const void * ptr2, size_t num );

(1)比较从ptr1和ptr2指针开始的num个字节

(2)返回值如下:

比较的是字节,相等的话,返回0。 比较的是ASCII值。

1.14 memset

代码展示:

1. #include <stdio.h>
2. int main()
3. {
4.  char arr[20] = { 0 };
5.  memset(arr, 'x', 10);
6.  return 0;
7. }

以字节为单位改。

二 库函数的模拟实现

2.1 模拟实现strlen

1 计数器的方法

1. #include <stdio.h>
2. #include <assert.h>
3. int my_strlen(const char* str)
4. {
5.  assert(str);
6.  int count = 0;
7.  while (*str != '\0')
8.  {
9.    count++;
10.     str++;
11.   }
12.   return count;
13. }
14. int main()
15. {
16.   int len = 0;
17.   len = my_strlen("abcdefg");//传递给my _strlen的是字符'a'的地址
18.   printf("%d", len);
19.   return 0;
20. }

\0 的ASCII码值是 0 ,一个表示字符串结束的标志,这是一个转义字符,整体视为一个字符,在内存中的存储为0000 0000

字符在内存中是以ASCII码值对应的二进制的补码存在的(8位)

2.2 模拟实现strcpy

代码展示:

1. #include <stdio.h>
2. #include <assert.h>
3. char* my_strcpy(char* a, const char* b)
4. {
5.  assert(a && b);
6.  char* ret = a;
7.  while (*a++ = *b++)//++的优先级大于*的优先级
8.  {
9.    ;
10.   }
11.   return ret;
12. }
13. 
14. int main()
15. {
16.   char arr1[20] = { 0 };
17.   char arr2[] = "hello";
18.   printf("%s\n", my_strcpy(arr1, arr2));//函数的链式访问
19.   return 0;
20. }

尽量不要返回局部变量的地址(调用的那个函数,里面的局部变量,使用完就可能被销毁了,地址指向的局部变量的值,可能就变了),而不是局部变量。

2.3 模拟实现strcat

代码展示:

1. #include <stdio.h>
2. #include <assert.h>
3. char* my_strcat(char* dest, const char* src)
4. {
5.  char* ret = dest;
6.  assert(dest && src);
7.  while (*dest)
8.  {
9.    dest++;
10.   }
11.   while (*dest++ = *src++)
12.   {
13.     ;
14.   }
15.   return ret;
16. }
17. int main()
18. {
19.   char arr1[30] = "hello";
20.   char arr2[] = "world";
21.   my_strcat(arr1, arr2);
22.   printf("%s\n", arr1);
23.   return 0;
24. }

思路:(1)找到目标空间中的\0   (2)追加字符

everyting——搜索strcat——右击 打开路径

2.4 模拟实现strstr

代码展示:

1. #include <stdio.h>
2. #include <assert.h>
3. char* my_strstr(const char* str1, const char* str2)
4. {
5.  assert(str1 && str2);
6.  if (*str2 == '\0')
7.  {
8.    return (char*)str1;//(const char* 和char*还是不同的)
9.  }
10.   //当第一个字符出现匹配,后续字母中出现不匹配的时候,字符串的地址要回到出现匹配的第一个字符,的下一个字符的地址,
11.   //所以尽可能不要直接用str1和str2,而是间接的使用
12.   const char* s1 = str1;
13.   const char* s2 = str2;
14.   const char* s3 = str1;//遇到匹配的第一个字符前一直在+1
15.   while (*s3)//在这个循环里,s3一直在+1,一直到s3遇到\0 ,while结束
16.   {
17.     s1 = s3;
18.     s2 = str2;
19.     while (*s1 != '\0' && *s2 != '\0' && * s1 == *s2)
20.     {
21.       s1++;
22.       s2++;
23.     }
24.     if (*s2 == '\0')
25.       return (char*)s3;
26.     s3++;
27.   }
28.   return NULL;
29. }
30. int main()
31. {
32.   char arr1[] = "abcdabcd";
33.   char arr2[] = "A";
34.   char* ret = my_strstr(arr1, arr2);
35.   if (ret == NULL)
36.     printf("找不到");
37.   else
38.     printf("%s\n", ret);
39.   return 0;
40. }

2.5 模拟实现strcmp

代码展示:

1. #include <stdio.h>
2. #include <assert.h>
3. int my_strcmp(const char* str1, const char* str2)
4. {
5.  assert(str1 && str2);
6.  while (*str1 == *str2)
7.  {
8.    if (*str1 == '\0')
9.    {
10.       return 0;
11.     }
12.     str1++;
13.     str2++;
14.   }
15.   if (*str1 > *str2)
16.     return 1;
17.   else
18.     return -1;
19. }
20. int main()
21. {
22.   char arr1[] = "abc";
23.   char arr2[] = "abcd";
24.   int ret = my_strcmp(arr1, arr2);
25.   printf("%d", ret);
26.   return 0;
27. }

"abcd"  和"abc"比较,是1     因为,第一个字符串是d的ASCII,后一个字符串是'\0'的ascii,所以是1.

2.6 模拟实现memcpy

代码展示:

 

1. #include <stdio.h>
2. #include <assert.h>
3. void* my_memcpy(void* dest, const void* src, size_t num)
4. {
5.  void* ret = dest;
6.  assert(dest && src);
7.  while (num--)//后置--,先试用,后--;
8.  {
9.    *(char*)dest = *(char*)src;
10.     dest = (char*)dest + 1;
11.     src = (char*)src + 1;
12.   }
13.   return ret;
14. }
15. int main()
16. {
17.   int arr3[] = { 1, 2,3,4,5,6,7, 8, 9, 10 };
18.   int arr4[5] = { 0 };
19.   my_memcpy(arr4, arr3, 20);
20.   int i = 0;
21.   for (i = 0; i < 5; i++)
22.   {
23.     printf("%d ", arr4[i]);
24.   }
25.   return 0;
26. }

知识点:

(1)void* 不能进行加减,所以转换成char *进行加减。

2.7 模拟实现memmove

代码展示:

1. #include <stdio.h>
2. #include <assert.h>
3. void* my_memmove(void* dest, const void* src, size_t num)//能不创建空间就不创建空间
4. {
5.  void* ret = dest;
6.  assert(dest && src);
7.  if (dest < src)
8.  {
9.    while (num--)
10.     {
11.       *(char*)dest = *(char*)src;
12.       dest = (char*)dest + 1;
13.       src = (char*)src + 1;
14.     }
15.   }
16.   else
17.   {
18.     while (num--)
19.     {
20.       *((char*)dest + num) = *((char*)src+num);
21.     }
22.   }
23.   return ret;
24. }
25. #include <stdio.h>
26. int main()
27. {
28.   int arr3[] = { 1, 2,3,4,5,6,7, 8, 9, 10 };
29.   my_memmove(arr3+1, arr3, 20);
30.   int i = 0;
31.   for (i = 0; i < 10; i++)
32.   {
33.     printf("%d ", arr3[i]);
34.   }
35.   return 0;
36. }


相关文章
|
1月前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
34 3
|
10天前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
32 6
|
28天前
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
1月前
|
存储 程序员 编译器
C语言——动态内存管理与内存操作函数
C语言——动态内存管理与内存操作函数
|
1月前
|
编译器 C语言 C++
详解C/C++动态内存函数(malloc、free、calloc、realloc)
详解C/C++动态内存函数(malloc、free、calloc、realloc)
158 1
|
1月前
|
程序员 C语言
C语言内存函数精讲
C语言内存函数精讲
|
24天前
|
存储 C语言
【c语言】字符串函数和内存函数
本文介绍了C语言中常用的字符串函数和内存函数,包括`strlen`、`strcpy`、`strcat`、`strcmp`、`strstr`、`strncpy`、`strncat`、`strncmp`、`strtok`、`memcpy`、`memmove`和`memset`等函数的使用方法及模拟实现。文章详细讲解了每个函数的功能、参数、返回值,并提供了具体的代码示例,帮助读者更好地理解和掌握这些函数的应用。
20 0
|
1月前
|
C语言 C++
c语言回顾-内存操作函数
c语言回顾-内存操作函数
40 0
|
1月前
|
存储 C语言 C++
来不及哀悼了,接下来上场的是C语言内存函数memcpy,memmove,memset,memcmp
本文详细介绍了C语言中的四个内存操作函数:memcpy用于无重叠复制,memmove处理重叠内存,memset用于填充特定值,memcmp用于内存区域比较。通过实例展示了它们的用法和注意事项。
66 0
|
1月前
一刻也没有为它哀悼~接下来登场的是动态内存分配的malloc与realloc以及free函数
一刻也没有为它哀悼~接下来登场的是动态内存分配的malloc与realloc以及free函数
65 0