【C语言航路】第十站:指针(三)深刻理解指针运算

news2025/1/16 15:04:26

目录

一、深刻理解指针和数组

1.一维数组

2、字符数组

(1)字符变量存放到数组中

(2)字符串存放到字符数组

(3) 字符串存放到一个指针中

3.二维数组

二、指针与数组经典笔试题

1.题1

2.题2

3.题3

4.题4

5.题5

6.题6

7.题7

8.题8

总结


一、深刻理解指针和数组

对于指针和数组,我们必须要要知道的几个核心原则是:

1.sizeof(数组名),数组名代表的是整个数组,计算的是整个数组的大小

2.&数组名,数组名代表的是整个数组。取出的是整个数组的地址

3.除此之外,所有的数组名都是首元素的地址

1.一维数组

#include<stdio.h>
int main()
{
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(a + 0));
	printf("%d\n", sizeof(*a));
	printf("%d\n", sizeof(a + 1));
	printf("%d\n", sizeof(a[1]));
	printf("%d\n", sizeof(&a));
	printf("%d\n", sizeof(*&a));
	printf("%d\n", sizeof(&a + 1));
	printf("%d\n", sizeof(&a[0]));
	printf("%d\n", sizeof(&a[0] + 1));
}

这些题目,我们只需要抓住核心要点,那么攻破它是易如反掌的,为了方便观察,我们将接下放在代码中,解析如下:


    int a[] = { 1,2,3,4 };
    printf("%d\n", sizeof(a));
    //sizeof(数组名),此时数组名代表的是整个数组,计算的是整个数组的大小
    //此时a的类型是int [4]
    //答案是16,单位是字节
    printf("%d\n", sizeof(a + 0));
    //数组名不是单独在sizeof内部,也不是取地址,此时代表的是首元素的地址,加上0还是首元素的地址,计算的是这个地址的大小
    //a+0的类型是int*
    //答案是4/8,单位是字节
    printf("%d\n", sizeof(*a));
    //a代表的是首元素的地址,对首元素的地址解引用,代表的是首元素,计算的是这个首元素的大小
    //*a的类型是int
    //答案是4,单位是字节
    printf("%d\n", sizeof(a + 1));
    //a是首元素地址,加一后代表的是第二个元素的地址
    //a+1的类型是int*
    //答案是4/8,单位是字节
    printf("%d\n", sizeof(a[1]));
    //代表的是第二个元素,计算的是第二个元素的大小
    //a[1]的类型是int,int的字节就是4个字节
    //答案是4,单位是字节
    printf("%d\n", sizeof(&a));
    //代表是整个数组的地址,地址的大小就是4/8
    //从类型的角度分析:&a的类型是int(*)[4],是一个指针变量,也就是4/8个字节
    //答案是4/8,单位是字节
    //但是在vc6.0上这个编译器上这个算出来的是个16,这是一个bug。理论上应该就是4/8
    printf("%d\n", sizeof(*&a));
    //&a,代表的是整个数组的地址,然后解引用这个数组的地址,取出来的是一个数组,也就是16
    //从类型的角度分析:&a的类型是int(*)[4],解引用后就是去掉这颗*,也就是int [4],这个类型的大小就是16
    //答案是16
    printf("%d\n", sizeof(&a + 1));
    //&a,代表的是整个数组的地址,加一就是这个向后偏移一个数组的长度后的地址,指向数组后面的空间
    //虽然这个不属于它的空间,但是它总是一个地址。
    //&a的类型是int(*)[4],加一后还是int(*)[4]的类型
    //答案是4/8
    printf("%d\n", sizeof(&a[0]));
    //&a[0]代表的是首元素的地址
    //类型是int*
    //答案是4/8
    printf("%d\n", sizeof(&a[0] + 1));
    //&a[0]+1代表的是第二个元素的地址
    //类型是int*
    //答案是4/8
 

为了方便我们区别这个4是首元素大小的4还是地址的4,我们将环境改为64位环境,这样如果是指针变量的话,输出的结果就为8

2、字符数组

(1)字符变量存放到数组中

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr + 0));
	printf("%d\n", sizeof(*arr));
	printf("%d\n", sizeof(arr[1]));
	printf("%d\n", sizeof(&arr));
	printf("%d\n", sizeof(&arr + 1));
	printf("%d\n", sizeof(&arr[0] + 1));


	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr + 0));
	printf("%d\n", strlen(*arr));
	printf("%d\n", strlen(arr[1]));
	printf("%d\n", strlen(&arr));
	printf("%d\n", strlen(&arr + 1));
	printf("%d\n", strlen(&arr[0] + 1));

	return 0;
}

无论如何,我们的核心要点是不会改变的。我们的解析如下


    char arr[] = { 'a','b','c','d','e','f' };
    printf("%d\n", sizeof(arr));
    //sizeof(数组名),次数数组名代表的是整个数组的地址,计算的是整个数组的大小,这个数组只有6个元素,没有\0
    //arr的类型是char [6]
    //所以答案是6
    printf("%d\n", sizeof(arr + 0));
    //arr代表的是首元素地址,加0后还是首元素地址,计算的是这个地址的大小
    //这个arr+0的类型是char*
    //所以答案为4/8
    printf("%d\n", sizeof(*arr));
    //arr代表的是首元素的地址,解引用后代表的是首元素
    //类型是char
    //所以答案为1
    printf("%d\n", sizeof(arr[1]));
    //arr[1]是数组第二个元素
    //类型是char
    //所以答案为1
    printf("%d\n", sizeof(&arr));
    //&arr代表的是整个数组的地址
    //类型是char(*)[6]
    //所以答案为4/8
    printf("%d\n", sizeof(&arr + 1));
    //&arr是整个数组的地址,加一后是这个数组向后面空间的一个地址。
    //类型是char(*)[6]
    //答案是4/8
    printf("%d\n", sizeof(&arr[0] + 1));
    //&arr[0]+1是第二个元素的地址
    //答案是4/8


    printf("%d\n", strlen(arr));
    //arr是数组名,代表的是首元素的地址,从首元素的地址开始算字符串的长度
    //为了找到\0,但是我们并不知道数组后面多少个内存才是\0
    //所以答案是大于等于6的随机数
    printf("%d\n", strlen(arr + 0));
    //arr+0是首元素的地址,还是不知道\0究竟在哪里
    //所以答案是大于等于6的随机数
    printf("%d\n", strlen(*arr));
    //arr是首元素的地址,解引用后是第一个元素。第一个元素是字符'a'。类型是char
    //字符a的ASCII值是97,97翻译成16进制数是0x00000061也就是这个地址处开始找\0
    //但是0x00000061这个地址并不一定分配空间,我们不能直接随便拿一个地址就计算长度,所以这个代码是错的
    //这个代码必然会导致程序的崩溃。
    printf("%d\n", strlen(arr[1]));
    //arr[1]是第一个元素。第一个元素是字符'a'。
    //字符a的ASCII值是97,97翻译成16进制数是0x00000061也就是这个地址处开始找\0
    //但是0x00000061这个地址并不一定分配空间,我们不能直接随便拿一个地址就计算长度,所以这个代码是错的
    //这个代码必然会导致程序的崩溃
    printf("%d\n", strlen(&arr));
    //&arr,代表的是整个数组的地址,它的类型是char(*)[6]
    //而strlen的形参是const char* 很明显类型不匹配,但是只能说是不合理。程序还是可以运行计算出来结果的
    //结果仍然是大于等于6的随机值
    printf("%d\n", strlen(&arr + 1));
    //&arr,代表的是整个数组的地址,加一后是它跳过这个数组以后后面的那个地址,它的类型是char(*)[6]
    //而strlen的形参是const char* 很明显类型不匹配,但是只能说是不合理。程序还是可以运行计算出来结果的
    //结果是大于等于0的随机值
    printf("%d\n", strlen(&arr[0] + 1));
    //代表的是第二个元素的地址
    //类型是char*
    //计算的结果是大于等于5的随机值
 

 

 但是其实在这里我们可能还会有一个疑问的是

在这段代码中,计算a字符的大小和计算第一个元素的大小不一样。而且如果是c++下,sizeof('a'),计算出来的是1个字节

这是因为c语言标准的问题

(2)字符串存放到字符数组

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "abcdef";

	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr + 0));
	printf("%d\n", sizeof(*arr));
	printf("%d\n", sizeof(arr[1]));
	printf("%d\n", sizeof(&arr));
	printf("%d\n", sizeof(&arr + 1));
	printf("%d\n", sizeof(&arr[0] + 1));

	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr + 0));
	printf("%d\n", strlen(*arr));
	printf("%d\n", strlen(arr[1]));
	printf("%d\n", strlen(&arr));
	printf("%d\n", strlen(&arr + 1));
	printf("%d\n", strlen(&arr[0] + 1));
	return 0;
}

我们要抓住的核心是,这个跟上面的区别是,这个后面是有一个\0的,是七个元素。其他的就是我们的核心原则了


    char arr[] = "abcdef";
    //需要注意的是这个数组里面其实有七个元素,后面还有一个\0

    printf("%d\n", sizeof(arr));
    //这个计算的是整个数组的大小
    //类型是char [7]
    //计算结果为7
    printf("%d\n", sizeof(arr + 0));
    //代表的是首元素的地址
    //类型是char*
    //计算结果为4/8
    printf("%d\n", sizeof(*arr));
    //代表的是首元素
    //类型是char
    //计算结果为1
    printf("%d\n", sizeof(arr[1]));
    //代表的是首元素
    //类型为char
    //计算结果为1
    printf("%d\n", sizeof(&arr));
    //代表的是整个数组的地址
    //类型是char(*)[7]
    //计算结果为4/8
    printf("%d\n", sizeof(&arr + 1));
    //代表的是整个数组后面的空间的地址
    //类型是char(*)[7]
    //计算结果为4/8
    printf("%d\n", sizeof(&arr[0] + 1));
    //代表的是第二个元素的地址
    //类型是char*
    //计算结果为4/8


    printf("%d\n", strlen(arr));
    //arr代表的是首元素的地址,第七个元素是\0
    //类型是char*
    //所以结果为6
    printf("%d\n", strlen(arr + 0));
    //代表的是首元素的地址,第七个元素是\0
    //类型是char*
    //所以结果为6
    //printf("%d\n", strlen(*arr));
    //代表的是第一个元素
    //类型是char
    //第一个元素是'a',ASCII值是97,97这个地址是0x00000061
    //但是不能随便拿个地址就去计算字节。去访问
    //所以这个代码是错的
    //printf("%d\n", strlen(arr[1]));
    //代表的是第一个元素
    //类型是char
    //第一个元素是'a',ASCII值是97,97这个地址是0x00000061
    //但是不能随便拿个地址就去计算字节。去访问
    //所以这个代码是错的
    printf("%d\n", strlen(&arr));
    //代表的是整个数组的地址
    //类型是char(*)[7]
    //虽然类型不匹配,但也是数组的起始地址,也能用。只是不合理
    //计算结果是6
    printf("%d\n", strlen(&arr + 1));
    //整个数组的地址后面的空间
    //类型是char(*)[7]
    //类型不匹配,但是只是不合理
    //由于不知道后面是如何存储的数据,所以结果为随机值
    printf("%d\n", strlen(&arr[0] + 1));
    //第二个元素的地址
    //类型是char*
    //结果为5
 

(3) 字符串存放到一个指针中

#include<stdio.h>
#include<string.h>
int main()
{
	char* p = "abcdef";

	printf("%d\n", sizeof(p));
	printf("%d\n", sizeof(p + 1));
	printf("%d\n", sizeof(*p));
	printf("%d\n", sizeof(p[0]));
	printf("%d\n", sizeof(&p));
	printf("%d\n", sizeof(&p + 1));
	printf("%d\n", sizeof(&p[0] + 1));

	printf("%d\n", strlen(p));
	printf("%d\n", strlen(p + 1));
	printf("%d\n", strlen(*p));
	printf("%d\n", strlen(p[0]));
	printf("%d\n", strlen(&p));
	printf("%d\n", strlen(&p + 1));
	printf("%d\n", strlen(&p[0] + 1));
	return 0;
}

对于这个题,我们还是那三个要点,还需要注意的是,p指向的是a,存放的是a的地址


    char* p = "abcdef";
    //要注意的是,这个p存放的是a的地址
    printf("%d\n", sizeof(p));
    //p是一个指针,计算p的大小
    //答案是4/8
    printf("%d\n", sizeof(p + 1));
    //p+1是指向b的地址
    //答案是4/8
    printf("%d\n", sizeof(*p));
    //p是指向a的,p存放的是a的地址,*p的结果就是a这个字符
    //类型是char
    //计算结果为1
    printf("%d\n", sizeof(p[0]));
    //p是指向a的,p存放的是a的地址,*p的结果就是a这个字符
    //类型是char
    //计算结果为1
    printf("%d\n", sizeof(&p));
    //p是一个指针变量,它的地址是一个二级指针
    //还是一个指针,类型为char**
    //答案为4/8
    printf("%d\n", sizeof(&p + 1));
    //&p是一个二级指针,+1后就是指向p变量后面的一个空间
    //但是本质还是一个二级指针,类型为char**
    //答案为4/8
    printf("%d\n", sizeof(&p[0] + 1));
    //这个指向的是b这个字符,还是一个指针变量char*
    //答案为4/8


    printf("%d\n", strlen(p));
    //p是一个指针,存放着a的地址
    //所以计算结果为6
    printf("%d\n", strlen(p + 1));
    //p+1指向的是b这个字符
    //所以计算结果为5
    //printf("%d\n", strlen(*p));
    //p指向的是'a',它的ASCII值是97,地址是0x00000061
    //不能直接访问这个地址,所以这个代码是错误的
    //printf("%d\n", strlen(p[0]));
    //p指向的是'a',它的ASCII值是97,地址是0x00000061
    //不能直接访问这个地址,所以这个代码是错误的
    printf("%d\n", strlen(&p));
    //p是一个指针,&p是一个二级指针,类型是char**,指针的类型不一样
    //
    printf("%d\n", strlen(&p + 1));
    //p是一个指针,&p是一个二级指针,类型是char**,指针的类型不一样
    printf("%d\n", strlen(&p[0] + 1));
    //指向的是b这个字符
    //答案是5

这个这个使用的是32位环境

3.二维数组

#include<stdio.h>
int main()
{
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(a[0][0]));
	printf("%d\n", sizeof(a[0]));
	printf("%d\n", sizeof(a[0] + 1));
	printf("%d\n", sizeof(*(a[0] + 1)));
	printf("%d\n", sizeof(a + 1));
	printf("%d\n", sizeof(*(a + 1)));
	printf("%d\n", sizeof(&a[0] + 1));
	printf("%d\n", sizeof(*(&a[0] + 1)));
	printf("%d\n", sizeof(*a));
	printf("%d\n", sizeof(a[3]));
}

要时刻注意,我们的核心要点是不会改变的,但是二维数组有一个不同之处是,二维数组的数组名确实是首元素地址,但是二维数组的首元素是第一行这个数组。所以它的数组名是第一行的地址


    int a[3][4] = { 0 };
    printf("%d\n", sizeof(a));
    //这里的a代表的是整个数组,所以计算出来的是4*3*4
    //类型是int [3][4]
    //答案是48
    printf("%d\n", sizeof(a[0][0]));
    //a[0][0]是第一行第一列的元素,计算的是首元素的大小
    //类型是int
    //答案是4
    printf("%d\n", sizeof(a[0]));
    //a是数组名,代表的是首元素的地址,首元素是整个第一行数组。
    //a[0]可以视作*(a+0),也就是对第一行的地址解引用
    //得到的是第一行数组,而这个第一行数组又可以看作是一个一维数组的数组名
    //sizeof(数组名),此时这个一维数组的数组名代表的是整个数组
    //类型是int[4]
    //答案是16
    printf("%d\n", sizeof(a[0] + 1));
    //a[0]是第一行数组,是一个一维数组
    //而这个一维数组中,它就相当于一个一维数组的数组名
    //代表的是首元素的地址,加一后就是第二个元素的地址
    //类型是int*
    //答案是4/8
    printf("%d\n", sizeof(*(a[0] + 1)));
    //a[0]+1是第一行第二个元素的地址
    //解引用后就是第一行第二个元素
    //类型是int
    //答案是4
    printf("%d\n", sizeof(a + 1));
    //a是数组名,是第一行数组的地址,加一后就是第二行数组的地址
    //类型是int(*)[4]
    //答案是4/8
    printf("%d\n", sizeof(*(a + 1)));
    //对第二行的数组解引用,得到的是第二行一维数组的数组名
    //sizeof括号里面直接就是一个一维数组的数组名,代表的是整个一维数组
    //类型是int[4]
    //答案是16
    printf("%d\n", sizeof(&a[0] + 1));
    //&a[0]是第一行数组的地址,加一后就是第二行数组的地址
    //类型是int(*)[4]
    //答案是4/8
    printf("%d\n", sizeof(*(&a[0] + 1)));
    //&a[0]+1是第二行的地址
    //解引用后就是第二行的整个数组,代表的是第二行的数组名
    //类型是int[4]
    //答案是16
    printf("%d\n", sizeof(*a));
    //a的第一行数组的地址,解引用后就是第一行数组
    //类型是int[4]
    //答案是16
    printf("%d\n", sizeof(a[3]));
    //a[3]是第四行的整个数组
    //类型是int[4]
    //答案是16
 

 

 

二、指针与数组经典笔试题

1.题1

int main()
{
	int a[5] = { 1, 2, 3, 4, 5 };
	int* ptr = (int*)(&a + 1);
	printf("%d,%d", *(a + 1), *(ptr - 1));
	return 0;
}

这段代码我们画图来分析

最终答案是2和5

 

2.题2

struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{
	printf("%p\n", p + 0x1);
	printf("%p\n", (unsigned long)p + 0x1);
	printf("%p\n", (unsigned int*)p + 0x1);
	return 0;
}

p是一个指针变量,是一个结构体指针。它指向的是这个结构体,这个p的值为0x00100000

首先是对结构体加一,跳过整个结构体的字节
结果为0x00100014

然后是将结构体指针强制类型转化为unsigned long类型,这样其实就转化为了普通的正数相加
结果为0x00100001

最后是将这个结构体指针变为了unsigned int* ,是一个指针变量,所指向的数据是unsigned int类型的,是四个字节,所以指针加一就是加四个字节的长度
结果为0x00100004

 

3.题3

#include<stdio.h>
int main()
{

	int a[4] = { 1, 2, 3, 4 };
	int* ptr1 = (int*)(&a + 1);
	int* ptr2 = (int*)((int)a + 1);
	printf("%x,%x", ptr1[-1], *ptr2);
	return 0;
}

 

 

4.题4

#include <stdio.h>
int main()
{
	int a[3][2] = { (0, 1), (2, 3), (4, 5) };
	int* p;
	p = a[0];
	printf("%d", p[0]);
	return 0;
}

 

5.题5

#include<stdio.h>
int main()
{
	int a[5][5];
	int(*p)[4];
	p = a;
	printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
	return 0;
}

 

 

6.题6

int main()
{
	int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int* ptr1 = (int*)(&aa + 1);
	int* ptr2 = (int*)(*(aa + 1));
	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
	return 0;
}

 

 

7.题7

#include <stdio.h>
int main()
{
	char* a[] = { "work","at","alibaba" };
	char** pa = a;
	pa++;
	printf("%s\n", *pa);
	return 0;
}

 

 

8.题8

#include<stdio.h>
int main()
{
	char* c[] = { "ENTER","NEW","POINT","FIRST" };
	char** cp[] = { c + 3,c + 2,c + 1,c };
	char*** cpp = cp;
	printf("%s\n", **++cpp);
	printf("%s\n", *-- * ++cpp + 3);
	printf("%s\n", *cpp[-2] + 3);
	printf("%s\n", cpp[-1][-1] + 1);
	return 0;
}

这道题比较复杂,我们先画出他们的指针指向分布,如下图所示

有了这个指向分布我们才能继续往下做

首先是**++cpp,对于这个式子,我们要搞清楚优先级,++的优先级比较高,所以先执行++,执行以后,指针的图解变为下图所示

然后我们第一次解引用,找到了cp[1],cp[1]的内容是c+2。c+2所指向的内容是c[2],我们对c[2]再度解引用,得到的是POINT。

然后我们第二次打印的式子中。还有一个前置++,所以我们还需要改变指向,如下图所示

 

接下来是解引用现在的cpp,得到的是cp[2],cp[2]也就是c+1,但是此时我们又要对cp[2]进行前置--操作,所以c+1,就要变成了c。所以指向就要发生改变改变后的结果如下图所示

接下来又要对这个进行解引用,得到的是c[0],而c[0]是一个字符指针,存放着E的地址,接下来又要+3,得到的是第四个元素E的地址。所以最终的打印结果为ER

 接下来的第三个打印,我们此时的指向图如下图所示

我们先使用cpp[-2],这个得到的是cp[0],也就是c+3的地址, 也就是c[3]的地址,然后解引用,得到的是c[3],然后加3,得到的是S的地址,然后打印,最终打印出来的是ST

 接下来我们的操作是,cpp[-1][-1],第一次的-1解引用找到的是cp[1],cp[1]指向的是c+2,也就是c[2],然后再次使用[-1],得到的结果是c[1],c[1]存放的是N的地址,然后我们+1,得到的是E的地址,最终打印出来的就是EW

 


总结

本节讲解了指针和数组的经典笔试面试题,一定要记住那几个原则,以不变应万变

如果对你有帮助,不要忘记点赞加收藏哦!!!

想获得更多优质内容,一定要关注我哦!!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MCU-51:单片机之红外遥控(外部中断)

目录一、红外遥控简介二、硬件电路三、基本发送与接收四、NEC码五、代码演示5.1 红外遥控5.2 红外遥控电机调速注意&#xff1a;一定要看一、红外遥控简介 红外发射装置 也就是通常我们说的红外遥控器是由键盘电路、红外编码电路、电源电路和红外发射电路组成。红外发射电路的…

爬虫逆向之字体反爬(一)、镀金的天空-字体反爬-1

题目地址&#xff1a;http://www.glidedsky.com/level/crawler-font-puzzle-1 写一下之前处理过的几个字体反爬实战&#xff0c;也是很常见的一种反爬类型&#xff0c;这是第一篇 先来看一下题目 源码拿到的数字&#xff0c;和实际显示在网页的数字&#xff0c;明显不一样的 …

相见恨晚的 IDEA 使用技巧,能让你的代码飞起来

Live Templates 是什么&#xff0c;听上去感觉挺玄乎的。有的同学用过之后觉得简直太好用了&#xff0c;不能说大大提高了开发效率吧&#xff0c;至少也是小小的提高一下&#xff0c;节省了很多敲重复代码的时间。有的同学用过之后说&#xff1a;没什么用&#xff0c;奇技淫巧罢…

C语言_程序环境和预处理

目录 1. 程序的翻译环境 2. 程序的执行环境 3. C语言程序的翻译链接 4. 预编译过程详解 4.1 预定义符号介绍 4.1.1 __FILE__ //进行编译的源文件 4.1.2 __LINE__//文件当前的行号 4.1.3 __DATE__//文件被编译的日期 4.1.4 __TIME__//文件被编译的时间 4.1.5 __STDC__…

基于python的学生信息管理系统

《学生信息管理系统》程序使用说明在IDLE中运行《学生信息管理系统》即可进入如图1所示的系统主界面。在该界面中可以选择要使用功能对应的菜单进行不同的操作。在选择功能菜单时&#xff0c;有两种方法&#xff0c;一种是输入1&#xff0c;另一种是按下键盘上的↑或↓方向键进…

【Javascript】高阶函数,JSON,forEach,map,filter,reduce函数

❤️ Author&#xff1a; 老九 ☕️ 个人博客&#xff1a;老九的CSDN博客 &#x1f64f; 个人名言&#xff1a;不可控之事 乐观面对 &#x1f60d; 系列专栏&#xff1a; 文章目录高阶函数箭头函数apply函数JSONfilter函数map函数总结reduce函数find/findIndex函数every/some函…

线缆行业单绞机控制算法(详细图解)

在了解单绞机之前需要大家对收放卷以及排线控制有一定的了解,不清楚的可以参看下面几篇博客,这里不再赘述,受水平和能力所限,文中难免出现错误和不足之处,诚恳的欢迎大家批评和指正。 收放卷行业开环闭环控制算法 PLC张力控制(开环闭环算法分析)_RXXW_Dor的博客-CSDN博…

知识难懂到什么程度

爱因斯坦相对论&#xff0c;诺贝尔评委会都看不懂&#xff0c;到底说的是什么1905年&#xff0c;爱因斯坦发布狭义相对论&#xff1b;1916年&#xff0c;发布广义相对论&#xff1b;2年后&#xff0c;英国的汤姆逊教授通过实验验证了广义相对论的正确&#xff0c;同时也把爱因期…

容器适配器中stack queue priority_queue的介绍及模拟实现

文章目录容器适配器的概念deque的介绍及底层结构stack的介绍 stack的模拟实现 queue的介绍 queue的模拟实现 priority_queue的介绍 priority_queue的模拟实现 容器适配器的概念 适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验…

清华大佬超全超详细讲解——C++STL看这份教程就够了

2022 年年度编程语言揭榜啦&#xff01;在上个月预想的 C、C、Python 三种候选语言中&#xff0c;C 脱颖而出&#xff0c;成为 TIOBE 2022 年度编程语言的最终获得者&#xff01;新的一波学习热潮要来了。TIOBE 编程语言社区排行榜是编程语言流行趋势的一个指标&#xff0c;每月…

数据分析思维(三)|测试/对比思维

测试/对比思维 1、概念 测试/对比思维可以说在数据分析的工作中随处可见。当我们通过各种手段得到一些结果数据后&#xff0c;如何评价结果的好坏呢&#xff1f;这个时候你可能会想到和标准结果进行比较、和之前的数据进行对照等等方法&#xff0c;这些方法归根结底就是一种测…

ubuntu 安装 Gitkraken 8.1.1 Pro 版本

GitKraken 是一个非常好用的 Git 图形界面客户端, 自 6.5.1 版本以后, GitKraken 对私有仓库不再免费开放使用 本文介绍一个 ubuntu 安装 GitKraken 8.1.1 Pro 版本的方法 环境准备 安装 yarn 测试过 node 18.12.1 版本, 没能升级到 Pro 版, 可能是因为 GitCracken 仓库太久…

springboot+sa-token-quick-login实现快速登录

当你的项目需要一个登录认证功能&#xff0c;这个登录界面可以不华丽、可以烂&#xff0c;但是一定要有&#xff0c;同时你又不想花费太多的时间浪费在登录页面上&#xff0c; 那么你便可以尝试一下Sa-Token-Quick-Login。 1、Sa-Token-Quick-Login Sa-Token-Quick-Login 可以…

5.4、TCP 流量控制(滑动窗口机制)

一般来说&#xff0c;我们总是希望数据传输得更快一些。 但如果发送方把数据发送得过快&#xff0c;接收方就可能来不及接收&#xff0c;这就会造成数据的丢失。 所谓流量控制(flow control)就是让发送方的发送速率不要太快&#xff0c;要让接收方来得及接收\color{red}让发送…

基于微信小程序的个人健康数据管理系统小程序

文末联系获取源码 开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7/8.0 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.3.9 浏览器…

第一章.机器学习的前期准备—jupyter 更换文件路径的方法,jupyter使用方法,训练/验证/测试数据集的概念,学习方式,常见应用

第一章.机器学习的前期准备 1.1 第一章.机器学习的前期准备 1.jupyter软件的安装 说明:可以使用Anaconda软件中的jupyter软件 1).jupyter 更换文件路径的方法&#xff1a; ①.查找电脑中是否存在 jupyter_notebook_config.py 文件&#xff0c;若不存在&#xff0c;通过命令提…

前端最基础面试题:说说JavaScript中如何判断数据类型?

1. 基本数据类型的判定&#xff1a;typeof [变量名] typeof 1 // number typeof string呀 // string typeof true // boolean typeof Symbol(abc) // symbol控制台验证&#xff1a; 2. 引用类型 object 的判断&#xff1a; ① constructor ② instanceof ③ Object.prototy…

Redux与前端表格施展“组合拳”,实现大屏展示应用的交互增强

Redux 是 JavaScript 状态容器&#xff0c;提供可预测化的状态管理。它可以用在 react、angular、vue 等项目中, 但与 react 配合使用更加方便一些。 Redux 原理图如下&#xff0c;可以看到store仓库是Redux的核心&#xff0c;通过维护一个store仓库管理 state。state 是只读的…

JS严格模式(use strict)

javascript语法不够严谨&#xff0c;例如我们在项目中不用关键字去定义了一个变量a&#xff0c;控制台一切正常。b123;console.log(b)但是&#xff0c;如果开启了严格模式呢&#xff1f;"use strict" b123; console.log(b)此时将会报错Uncaught ReferenceError: b is…

开关电源中功率电感均方根电流是如何推导的?来自《开关电源宝典》

3.2.8 功率电感的有效电流参考“1.7.3 功率电感”章节内容&#xff0c;我们知道&#xff0c;功率电感具有温升电流、RMS电流、饱和电流、额定电流等电流参数。在后续“第5章 降压电路的应用方法”应用实例中进行功率电感选型时&#xff0c;需要保证所选电感的额定电流参数大于实…