C语言-详解内存函数

在这里插入图片描述

文章目录

  • 1.memcpy使用和模拟实现
    • 1.1 memcpy函数的使用规则
    • 1.2 memcpy函数的使用
    • 1.2 模拟实现memcpy函数
  • 2.memmove 函数的使用和模拟实现
    • 2.1 memmove 函数使用规则
    • 2.2 memmove函数的使用
    • 2.3 模拟实现memmove函数
      • 2.3.1 从后往前移
      • 2.3.2 从前往后移
    • 2.4 算法实现
      • 2.4.1 从前往后移算法实现
      • 2.4.2 从后往前移的算法实现
      • 2.4.3 最终代码展示及效果
  • 3.memset 函数的使用
    • 3.1 memset 函数的使用规则
    • 3.2 memset函数的使用
    • 3.3 使用memset函数需要注意的地方
  • 4.memcmp 函数的使用
    • 4.1 memcpy 函数的使用规则
    • 4.2 memcmp函数的使用
  • 5.总结

1.memcpy使用和模拟实现

1.1 memcpy函数的使用规则

它的函数原型如下:

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

具体的函数介绍如下:
在这里插入图片描述

好,相信同学们看了这个函数,应该是能够简单了解函数中各个参数的用法。
下面我们来总结一下:

  • 函数memcpysource的位置开始向后复制num个字节的数据到destination指向的内存位置。
  • 这个函数在遇到'\0'的时候并不会停下来。
  • 如果sourcedestintation有任何的重叠,复制的结果都是未定义的。

1.2 memcpy函数的使用

好,当我们讲了memcpy函数使用规则后,来看一下memcpy函数该怎么使用吧~
在这里插入图片描述
代码如下:

#include <stdio.h>
#include <string.h>
int main() {int arr[] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[20] = { 0 };memcpy(arr2, arr,20);//这里的arr2是目标位置,arr是起始位置,20指的是复制的字节个数,int类型占4个字节, 那这里的20就相当于5个int类型的元素。//也就是说将arr数组中5个元素拷到arr2数组中,arr2是数组首元素的地址,也就是说当执行完这个语句,arr2数组前5个元素存的是arr1数组前5个元素的值for (int i = 0; i < sizeof(arr2) / sizeof(arr2[0]); i++)//sizeof(arr2)/sizeof(arr2[0]),本质上就是用arr2数组所占的总大小/arr2数组中一个元素所占的大小,得出的是arr2它数组元素个数{printf("%d ", arr2[i]);}return 0;
}

代码分析: 这里我们用mencpy函数主要是将arr1数组中前5个元素拷到arr2起始地址处。
也就是说这里用memcpy函数进行拷贝的话,到时会将arr2数组中前5个元素给覆盖掉。
如图:
在这里插入图片描述
相信同学们看了这个图以及上面的代码注释,是能够理解那个代码逻辑的。

VS运行效果:
在这里插入图片描述
通过观察: 我们发现运行结果确实是符合我们预期的,跟我们分析得是一模一样的。

1.2 模拟实现memcpy函数

好,刚刚我们讲了memcpy函数的使用,那如何模拟实现一个memcpy函数呢?
这里想必同学们有点无从下手,没事,博主这里画个图,说不定大家很快就明白了~
如图:
在这里插入图片描述
从图中: 假设我们想要把arr中前5个元素拷到arr2数组中第7到第11个元素的位置,我们该怎么做呢?
在讲解这个之前,我们先看一下int类型和char类型在VS编译器中各占几个字节?
如图:
在这里插入图片描述
从运行结果来看: 我们可以看出int是占4个字节,char是占1个字节。
有同学可能要问了,知道这个有什么用呢?
如图:
在这里插入图片描述
从图中: 我们看出memcpy第三个参数就是所要拷贝的字节个数,这时我们之前讲的intchar所占的大小就发挥作用了。
因为我们到时要在模拟实现的my_memcpy函数内部中,要把数组中int*的元素强转为char*的元素,通过所要传的字节数,用一个while循环,对里面的字节数进行交换。
这里想必同学们会有疑问?为什么要转换为char*的元素进行交换,而不转换为其他类型的元素进行字节数的交换呢?
这是因为: char*类型每解引用一次,访问的是一个字节的内存空间
如果说我们把目标地址dst和起始地址src转换为其他类型。如:short*int*,那么在进行字节的拷贝时可能会跳过一些字节,这会导致拷贝结果不正确。
因此我们要将它强制转换为char*,这样就可以保证我们可以正确地访问和拷贝内存中的每个字节。

好,当我们分析成这样,我们也能画个图把它的思路给分析出来~
如下:
在这里插入图片描述

好,同学们可以看一下博主总结的思路,自己尝试动手写一下这个模拟实现memcpy函数的代码出来。
如果真的写不出来,也没关系,看一下博主是怎么写这个代码的,模仿一下博主的写法。

代码如下:

#include <stdio.h>
#include <assert.h>void* my_memcpy(void* px, void* py, size_t count)//px是指向目标地址,而py指针指向源地址,这里的count可以理解为交换的字节数有多少
{assert(px && py);//用asser判断px和py指针是否为空void* ret = px;//这里用指针变量接收px目标位置的地址while (count--)//通过所要交换的字节数,从而确立循环的次数{*(char*)px = *(char*)py;//将源地址py指向的字节值赋给目标地址px 指向的字节(char*)px = (char*)px + 1;//px 指针向后移动一个字节(char*)py=(char*)py+1;//py 指针向后移动一个字节}return ret;//将指针变量ret的地址返回去
}int main() {int arr[] = {10,9,8,7,6,5,4,3,2,1 };int arr2[20] = { 0 };//针对内存块进行拷贝my_memcpy(arr2+6, arr, 5 * sizeof(int));//这里的arr2+6是目标位置,也就是说跳过6个元素。arr是源位置, 5 * sizeof(int)指的是5个数组元素for (int j = 0; j < sizeof(arr2) / sizeof(arr2[0]); j++)//本质上就是用arr2数组所占的总大小/arr2数组中一个元素所占的大小,得出的是arr2它数组元素个数{printf("%d ", arr2[j]);}printf("\n");return 0;
}

好,相信同学们看了这个代码以及注释,是能够理解这个代码逻辑的。
在这里插入图片描述

VS运行效果:
在这里插入图片描述

从运行结果来看: 我们发现VS编译器的运行结果是符合我们的预期的,也就是说它把arr2数组中的第七个~第十一个元素全都替换为arr数组中前五个元素。

好,这个memcpy函数我们就讲到这里,希望同学们可以理解,同学们要多多实践才行哦~

2.memmove 函数的使用和模拟实现

2.1 memmove 函数使用规则

它的函数原型如下:

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

具体的函数介绍如下:
在这里插入图片描述

我们这里就做一个小小地总结吧:

  • memmove函数和memcpy的差别就是memmove函数处理的源内存块目标内存块是可以重叠的。
  • 如果源空间目标空间出现重叠,就得使用memmove函数。

2.2 memmove函数的使用

我们这里直接上代码吧~
代码如下:

#include <stdio.h>
#include <string.h>
int main() {int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };memmove(arr1 + 2, arr1, 5 * sizeof(int));//目标地址是arr1跳过两个元素的位置,起始地址是arr1首元素的地址,5*sizeof(int)指的是5个整型数组中的元素for (int i = 0; i < sizeof(arr1) / sizeof(arr1[0]); i++)//这里本质上就是用arr1数组所占的总大小/arr1数组中一个元素所占的大小,得出的是arr1它数组元素个数 {printf("%d ", arr1[i]);}printf("\n");return 0;
}

VS运行效果:
在这里插入图片描述
通过运行结果:我们可以看出VS的运行结果是符合我们预期的。

我们这里也简单地给大家画了一个图
如下:
在这里插入图片描述
从图中: 我们把蓝色框住的部分替换为1-5的数值,那有同学可能会问了?
这个memmove函数具体是怎么移动的,它是怎么做到不覆盖其他元素呢?
别急,等下博主讲memmove函数模拟实现的时候会给你细细道来。

2.3 模拟实现memmove函数

好,接下来给大家详细讲一下模拟memmove函数的思路~

2.3.1 从后往前移

首先,还是老样子,我们这里要将目标地址后的5个元素替换为源地址后的5个元素。
如下图:
在这里插入图片描述
那我们该怎么移红色框住的5个元素到蓝色框住的区域中呢?还要避免源字符串src中的5个元素被覆盖。
具体操作如下动图所示:
在这里插入图片描述
从动图中: 大家有没有发现,这里我们采取的是从后往前的方法来移动的。
这里我们是先将数组为5的元素移到数组7的位置中,再把数组为4的元素移到数组6的位置中,以此类推……
这样子移的目的是避免起始地址src的元素被覆盖,如果我们先将数组元素为1移到3的位置中,可能把元素为3的数字给覆盖掉,这显然是不合理的。因为memmove函数是允许源空间目标空间出现重叠的。

2.3.2 从前往后移

还是老样子,我们这里要将目标地址后的5个元素替换为源地址后的5个元素。
如下:
在这里插入图片描述
但是这里大家有没有发现,这里的起始地址src是高过目标地址dest的,因此我们就不能用刚刚的从后往前的方法来移动元素。
我们这里是采用从前往后的方法来移动元素。
具体操作流程如下:
在这里插入图片描述
在这里插入图片描述
从动图中: 我们这里是采用从前往后的方法来移动元素。
同理:我们这样子移动的目的也是为了避免起始地址中数组元素67在移动过程中被覆盖掉。

2.4 算法实现

好,前面我们讲了模拟实现memmmove函数两种移动方法,分别是从前往后移从后往前移的方法。
那具体该如何实现这两种方法的算法呢?下面来看一下。

2.4.1 从前往后移算法实现

这里的从前往后移的算法其实跟我们刚刚写的模拟实现memcpy函数的思路其实是差不多的。
为什么这么说呢?我们来看一下下面这幅图:
在这里插入图片描述
通过此图: 我们发现memmove函数中的第三个参数是size_t,也就是字节个数。
那我们知道参数num的值,那就好办了,我们这里可以分别把src指针和dest转换为char*类型的指针,对其解引用,每解引用一次,两个指针各自向后偏移一个元素,然后根据参数num的个数,来决定所要交换字节的次数
需要注意的是: 这里面我们还要了解一个知识~
也就是对于相同类型的数组,数组元素的地址是按照下标递增的。下标的值越高,数组元素的地址就越高。
那同学们可能会有疑问:直到这个东西有什么用呢?
这是因为我们要在模拟实现memmove函数中,加上个if的判断条件,这里面就是用来判断什么情况下用从前往后移,什么情况下用从后往前移。
那显然: 我们这里的起始地址src是打过目标地址dest的。因此那个代码我们就可以这么写~

代码如下:

	if (dest < src)//从前往后移的代码逻辑{while (nums--) {*(char*)dest = *(char*)src;(char*)dest = (char*)dest + 1;(char*)src = (char*)src + 1;}}else {;//从后往前移的代码逻辑}

2.4.2 从后往前移的算法实现

那么同理:我们看一下从后往前移的算法该怎么实现。
如下:
在这里插入图片描述
同样地,我们这里还是先观察memmmove的字节个数num,这个是关系到我们要交换多少个字节个数。
那么细心的同学可能发现: src指向的是数组首元素的地址,也就是1的地址。而dest指向的是数组第三个元素,也就是3的地址。
那么我们之前就讲过: 要先把起始地址中最后那个元素的字节数与目标地址最后那个元素的字节数进行交换,然后每交换一个字节数,那个字节数num的值就会-1,直到num的值为0,才会停止交换字节数。这样子才不至于说移动的过程中把起始地址中的元素给覆盖掉。
相信同学们看到这里,应该是能够把这个代码给写出来的,大家可以尝试动手写一下~

好,如果同学们写完的话,可以看一下自己写的代码和博主写的代码逻辑是否相同~
代码如下:

if (dest < src)//从前往后移的代码逻辑
{while (nums--) {*(char*)dest = *(char*)src;(char*)dest = (char*)dest + 1;(char*)src = (char*)src + 1;}
}
else {;//从后往前移的代码逻辑while (nums--)//每交换一次字节数,nums的值都会递减;{*((char*)dest + nums) = ((char*)src + nums);}
}

2.4.3 最终代码展示及效果

代码实现:

#include <stdio.h>
#include <assert.h>
void* my_memmove(void* dest, void* src, int nums) {assert(dest && src);void* ret = dest;if (dest < src)//从前往后移的代码逻辑{while (nums--) {*(char*)dest = *(char*)src;(char*)dest = (char*)dest + 1;(char*)src = (char*)src + 1;}}else {;//从后往前移的代码逻辑while (nums--)//每交换一次字节数,nums的值都会递减;{*((char*)dest + nums) = *((char*)src + nums);}}return ret;
}int main() {int arr[] = { 1,2,3,4,5,6,7,8,9,10 };my_memmove(arr+2, arr, 5 * sizeof(int));//起始地址为数组首元素地址,目标地址为数组首元素跳过两个元素的地址,交换的是5个int类型的元素,也就是20个字节的空间for (int i = 0; i < 10; i++) {printf("%d ", arr[i]);}printf("\n");return 0;
}

这里面我们分别演示VS从前往后移从后往前移的运行效果吧~
1.从前往后移运行效果:
在这里插入图片描述
从此图: 可以看出起始地址src是高过目标地址dest,所以这里是把目标地址中的3~5的元素替换为起始地址中的6-8元素。说明是能够达到我们的预期效果的。
2.从前往后移运行效果:
在这里插入图片描述
从此图: 可以看出目标地址dest是高过起始地址src,所以这里本质上是将目标地址3~5的元素替换为起始地址中的1~3的元素,说明这也是达到我们想要的预期效果。

好,这个memmove函数我们就讲到这里,这个函数相对比较复杂,下来同学们要多去实践这个代码。

3.memset 函数的使用

3.1 memset 函数的使用规则

它的函数原型如下:

void *memset (void *ptr,int value,size_t num)

具体的函数介绍如下:
在这里插入图片描述
这里相信同学们看了函数官网的介绍,应该是能够理解memset函数的规则,我们这里就浅浅总结一下吧~
总结: memset函数是用来设置内存的,将内存中的值以字节为单位设置成想要的内容

3.2 memset函数的使用

代码如下:

#include <stdio.h>
#include <string.h>
int main() {char arr[] = "she is my sister!!!";//这里面创建了一个字符数组,里面的字符各占一个字节memset(arr, 'x', 3);//第一个参数是目标地址,第二个参数为填充的内存块,第三个参数为字节数,由于这里第三个字节数为3,因此会把前三个字符元素she替换为'x'printf("%s\n", arr);//这里从数组中的首元素地址开始往后打印字符串,直到遇到\0才停止打印return 0;
}

相信同学们看了这个代码的注释,自己是应该知道怎么使用这个memset函数的。

VS运行效果:
在这里插入图片描述
从图中: 可以看出VS的运行结果是符合我们的预期的。

3.3 使用memset函数需要注意的地方

这里有同学可能会误用memset函数,比如他们可能会把代码写成这样:,运行时出现这种情况
如下:
在这里插入图片描述
他们会有所好奇“为什么打印的不是整数1,而是这么大的数呢?
别急,这里博主给你讲一下它的原理,相信你们很快就懂了~
如图:
在这里插入图片描述
我们通过在vs编译器调试时发现,arr数组中的5个元素全都设置都是以01 01 01 01存储的。
这是因为memset函数是以字节单位来设置的,它是把每个字节都填充为1,而不是说它把一个元素填充为1
我们从vs内存看出它是以十六进制来存储的,因此把这四个01构成一个整数,它就是这么一个值。
具体计算过程如下:
在这里插入图片描述
但是memset函数是可以为任何任意一个数据类型设置内存块来填充的。
那么博主这么讲: 就是想告诉同学们,memset函数是以字节为单位设置的,它会把每个字节填充为memset函数第二个参数那个内存块。所以我们可不敢随意用memset函数把每个元素设置,这是做不到的。

好,相信讲到这里,同学们已经知道memset函数怎么用了,那这个memset函数我们就讲到这里!

4.memcmp 函数的使用

4.1 memcpy 函数的使用规则

它的函数原型如下:

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

具体的函数介绍如下:
在这里插入图片描述
相信同学们看了这个函数官网的介绍,应该是知道这个memcmp函数的使用规则的,那我们这里就简单总结一下吧~

  • 比较从ptr1ptr2指针指向的位置开始,向后的num个字节。
  • memcmp函数按照字节顺序比较两个内存块中的字节,并返回一个整数值来表示比较结果。
    具体规则如下:
  • 如果ptr1的对应字节小于ptr2的对应字节,则返回一个负数。
  • 如果ptr1的对应字节等于ptr2的对应字节,则返回0
  • 如果ptr1的对应字节大于ptr2的对应字节,则返回一个正数。

通俗点来讲: 在比较字符串时,ASCII 码值就是内存块中对应字符的值。因此,可以说memcmp 函数实际上是通过比较两个字符串的 ASCII 码值来判断它们的大小关系。

4.2 memcmp函数的使用

我们这里就简单演示一下memcmp函数用法是怎么样,相信同学们看了博主写的这个代码,应该是可以上手的~
代码如下:

#include <stdio.h>
#include <string.h>
int main()
{char buffer1[] = "DWgaOtP12df0";//创建两个字符数组buffer1和buffer2char buffer2[] = "DWGAOTP12DF0";int n = memcmp(buffer1, buffer2, sizeof(buffer1));//比较两个字符串相应字符的Ascll码值。由于buffer1第三个字符的Ascll码值大于buffer2第三个字符的Ascll码值,因此这里返回一个大于0的数字,无需往后比较字符。if (n > 0)//因为buffer1>buffer2,所以会执行这条语句printf("'%s' is greater than '%s'.\n", buffer1, buffer2);//%s是从数组首元素开始往后打印字符串,直到遇到'\0'为止else if (n < 0)printf("'%s' is less than '%s'.\n", buffer1, buffer2);elseprintf("'%s' is the same as '%s'.\n", buffer1, buffer2);return 0;
}

这个函数跟我们之前讲的strcmp函数非常类似,都是比较两个字符数组相应字符的Ascll码值,如果出现对应字符的Ascll码值不相同,无需往后进行比较。

相信同学们看了博主写的代码注释,是可以理解这个代码的。

VS运行效果:
在这里插入图片描述
分析: 由于buffer1数组第三个字符的Ascll码值大于buffer2第三个字符的Ascll码值,因此返回的是大于0的数。因此执行的是if(n>0)的那条语句。那么从VS运行结果来看,它是达到我们的预期效果的。

好,这个memcmp函数我们就讲到这里,希望同学们可以理解!

5.总结

好,讲了这么多,让我们来回顾今天讲了什么吧~

  • 函数memcpy主要功能是从起始位置src复制nums个字节的数据到dest指向的内存位置。
    但是这个函数遇到'\0'的时候,并不会停下来的。
    如图:
    在这里插入图片描述
    分析: 这里我们是把arr2数组中的10字节的元素用memcpy函数拷到arr数组中,那从这个运行结果,我们可以看出这个arr数组已经是越界访问了。因此使用这个memcpy函数要小心一点才行。
    如果起始地址src和目标地址dest有任何的重叠,复制的结果都是未定义的。
  • memmove函数和memcpy函数的功能基本相同,也是遇到'\0'的时候,并不会停下来的。
    唯一不同的是memmove函数处理的源内存和目标内存块是可以重叠的。
    如果说源空间srt和目标空间dest 出现重叠,就得使用memmove函数来处理。
  • memset函数是用来设置内存的,将内存的值以字节设置成想要的内容。
    需要注意的是: memset函数是以字节单位来设置的,所以各位同学们要合理使用memset函数,否则运行时会输出一个让人意想不到的结果嘿嘿!
  • memcmp函数是比较两个字符数组元素对应的Ascll码值,从数组首元素开始往后比较,比较nums个字节。如果出现对应字符的Ascll码值不相同,无需往后进行比较。

好,讲到这里,相信同学们对C语言的内存函数有了基本的理解,大家看完这篇博客,自己下来要多去实践四个函数。唯有这样大家才能把编程学好的!

**当然如果大家如果觉得博主这篇文章对你学习C语言有帮助的话,可以给博主一键三连吗 **
在这里插入图片描述
** 谢谢大家支持!!! **

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/308283.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用docker制作Android镜像(实操可用)

一、安装包准备 1、准备jdk 下载地址&#xff1a;Java Downloads | Oracle 注意版本&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 参考下面的 对照表&#xff0c;不然后面构建镜像报错&#xff0c;就是版本不对。 我就是因为下载的jdk17&…

边缘计算平台原理、关键功能以及技术优势

1、什么是边缘计算及其工作原理&#xff1f; 边缘计算是一种分布式计算模型&#xff0c;它将数据处理和存储靠近数据源头和最终用户的边缘设备上&#xff0c;从而减少了数据传输和延迟。边缘计算旨在解决云计算模型所面临的问题&#xff0c;例如延迟高、带宽瓶颈和安全性等问题…

虚幻引擎架构自动化及蓝图编辑器高级开发进修班

课程名称&#xff1a;虚幻引擎架构自动化及蓝图编辑器高级开发进修班 课程介绍 大家好 我们即将推出一套课程 自动化系统开发。 自动化技术在项目开发的前中后期都大量运用。如何您是一家游戏公司&#xff0c;做的是网络游戏&#xff0c;是不是经常会遇到程序员打包加部署需…

Energia学习案例

案例一&#xff1a;编写程序&#xff0c;实现每次按下按键&#xff0c;红色LED灯改变状态&#xff08;初始点亮&#xff09;&#xff0c;在窗口监视窗中显示按击次数。[要求用计时器实现按键消抖] #include"Timer.h" //包含计时器头文件volatile int stateHIGH; //灯…

防止邮箱发信泄露服务器IP教程

使用QQ邮箱,网易邮箱,189邮箱,新浪邮箱,139邮箱可能会泄露自己的服务器IP。 泄露原理&#xff1a;服务器通过请求登录SMTP邮箱服务器接口&#xff0c;对指定的收件人发送信息。 建议大家使用商业版的邮箱&#xff0c;比如阿里云邮箱发信等 防止邮件发信漏源主要关注的是确保邮件…

蓝桥杯练习系统(算法训练)ALGO-954 逗志芃的暴走

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 逗志芃是有妹子的现充&#xff0c;但是有时候妹子就是烦恼。因为逗志芃太逗了&#xff0c;所以这段时间妹子对逗志芃发动了…

【Vue + keep-alive】路由缓存

一. 需求 列表页&#xff0c;n 条数据项可打开 n 个标签页&#xff0c;同时1条数据项的查看和编辑共用一个标签页。如下所示&#xff1a; 参考 // 主页面 // 解决因 路由缓存&#xff0c;导致 编辑后跳转到该页面 不能实时更新数据 onActivated(() > {getList() })二. 实现…

JAVA 4

这次我学习了第四次Java课程 Math #include<math.h> 数学运算 Math.main 随机数 double aMath.random(); System.out.println(a);对小数处理 double a 3.6415; System.out.println("Math.floor: " Math.floor(a));//向下最近的整数 System.out.println(&…

wpf下如何实现超低延迟的RTMP或RTSP播放

技术背景 我们在做Windows平台RTMP和RTSP播放模块对接的时候&#xff0c;有开发者需要在wpf下调用&#xff0c;如果要在wpf下使用&#xff0c;只需要参考C#的对接demo即可&#xff0c;唯一不同的是&#xff0c;视频流数据显示的话&#xff0c;要么通过控件模式&#xff0c;要么…

【黑马头条】-day09用户行为-精度丢失-点赞收藏关注

文章目录 1 long类型精度丢失问题1.1 解决1.2 导入jackson序列化工具1.3 自定义注解1.4 原理1.5 测试 2 用户行为要求3 创建微服务behavior3.1 微服务创建3.2 添加启动类3.3 创建bootstrap.yml3.4 在nacos中配置redis3.5 引入redis依赖3.6 更新minio 4 跳过 1 long类型精度丢失…

小红的白色字符串

题目描述 小红拿到了一个字符串&#xff0c;她准备将一些字母变成白色&#xff0c;变成白色的字母看上去就和空格一样&#xff0c;这样字符串就变成了一些单词。 现在小红希望&#xff0c;每个单词都满足以下两种情况中的一种&#xff1a; 1.开头第一个大写&#xff0c;其余为…

01、ArcGIS For JavaScript 4.29对3DTiles数据的支持

综述 Cesium从1.99版本开始支持I3S服务的加载&#xff0c;到目前位置&#xff0c;已经支持I3S的倾斜模型、3D Object模型以及属性查询的支持。Cesium1.115又对I3S标准的Building数据实现了加载支持。而ArcGIS之前一直没有跨越对3DTiles数据的支持&#xff0c;所以在一些开发过…

抖音滑块验证码加密的盐的位置

最近更新后之前很容易找到盐的位置的方法变了&#xff0c;抖音特意把盐隐藏起来了 {"reply": "RJC","models": "yAd8rl","in_modal": "DTn0nD2","in_slide": "ou7H0Ngda","move": …

Vue2(十五):replace属性、编程式路由导航、缓存路由组件、路由组件独有钩子、路由守卫、history与hash

一、router-link的replace属性 1、作用&#xff1a;控制路由跳转时操作浏览器历史记录的模式 2、浏览器的历史记录有两种写入方式&#xff1a;分别为push和replace&#xff0c;push是追加历史记录&#xff0c;replace是替换当前记录。路由跳转时候默认为push 3、如何开启repla…

环信 IM 客户端将适配鸿蒙 HarmonyOS

自华为推出了自主研发操作系统鸿蒙 HarmonyOS 后&#xff0c;国内许多应用软件开始陆续全面兼容和接入鸿蒙操作系统。环信 IM 客户端计划将全面适配统鸿蒙 HarmonyOS &#xff0c;助力开发者快速实现社交娱乐、语聊房、在线教育、智能硬件、社交电商、在线金融、线上医疗等广泛…

基于java+springboot+vue实现的网上购物系统(文末源码+Lw+ppt)23-42

摘 要 随着我国经济的高速发展与人们生活水平的日益提高&#xff0c;人们对生活质量的追求也多种多样。尤其在人们生活节奏不断加快的当下&#xff0c;人们更趋向于足不出户解决生活上的问题&#xff0c;网上购物系统展现了其蓬勃生命力和广阔的前景。与此同时&#xff0c;为…

我与C++的爱恋:类与对象(二)

​ ​ &#x1f525;个人主页&#xff1a;guoguoqiang. &#x1f525;专栏&#xff1a;我与C的爱恋 ​ 本篇着重介绍构造函数和析构函数&#xff0c;剩余内容在下篇解答。 一、类的默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。 任何类在什么都不写时…

GFS部署实验

目录 1、部署环境 ​编辑 2、更改节点名称 3、准备环境 4、磁盘分区&#xff0c;并挂载 5. 做主机映射--/etc/hosts/ 6. 复制脚本文件 7. 执行脚本完成分区 8. 安装客户端软件 1. 安装解压源包 2. 创建gfs 3. 安装 gfs 4. 开启服务 9、 添加节点到存储信任池中 1…

RUM 最佳实践-交互延迟的探索与发现

FID 在互联网高速发展的时代&#xff0c;用户体验已成为企业竞争的关键所在。网页性能作为用户体验的重要组成部分&#xff0c;直接影响着用户的满意度和工作效率。First Input Delay&#xff08;FID&#xff09;作为衡量网页性能的重要指标&#xff0c;越来越受到业界关注。今…

【Linux学习笔记】安卓运行C可执行文件No such file or directory

文章目录 开发环境运行失败现象解决办法方法一&#xff1a;使用静态库方法二&#xff1a;使用动态库创建lib查找依赖库复制需要注意的事情 开发环境 开发板&#xff1a;正点原子RK3568开发板安卓版本&#xff1a;11可执行程序命名&#xff1a;ledApp需加载模块&#xff1a;dts…