8.2 数组遍历访问

本节必须掌握的知识点:

        示例三十

        代码分析                               

        汇编解析     

在上一节中介绍了数组相关的概念,而在本节中将介绍数组的使用。

8.2.1 示例三十

       ■访问数组

示例代码三十

●第一步:分析需求,设计程序结构框架。

分析需求:

1.定义一个 int 型数组,其中有 5 个元素组成,5 个元素分别为 1、2、3、4、5。 int arr[5]={1,2,3,4,5};获取 arr 数组中第 2 个元素(从0开始计数)并打印出来。

2.将 arr 数组中第 2 个元素的值修改为 6。然后把改变后的数组遍历一遍,查看数组的元素是否有变化。

设计程序结构框架:顺序结构+循环结构。先输出数组第 2 个元素的值,再修改数组第 2 个元素的值,最后通过一个for循环语句遍历并输出数组。

●第二步:数据定义,定义恰当的数据结构;

定义一个int类型的数组变量int arr[5] = { 1,2,3,4,5 };

●第三步:分析算法。

(略)

●第四步:编写伪代码,即用我们自己的语言来编写程序。

int main(void) {

    定义一个int类型数组int arr[5] = { 1,2,3,4,5 };

    调用printf函数输出第二个数组元素("%d\n",arr[2]);

    修改第二个数组元素的值:arr[2] = 6;

    调用printf函数输出修改后的第二个数组元素("%d\n",arr[2]);

        for (int i = 0; i < 5; i++)

        {

            调用printf函数输出每个数组元素的值:("arr[%d] = %d\n", i, arr[i]);

         }

        system("pause");

        return 0;                                                                                                    

}

●第五步:画流程图,使用Visio、Excel或者其他绘图工具绘制算法流程和逻辑关系图;(略)

●第六步:编写源程序,其实就是将我们的伪代码翻译成计算机语言;

/*

   修改并访问数组元素

*/

#include <stdio.h>

#include <stdlib.h>

int main(void) {

    int arr[5] = { 1,2,3,4,5 }; //定义数组

    printf("%d\n", arr[2]); //打印arr数组中第2个元素

    arr[2] = 6; //修改数组元素

    printf("arr[2] = %d\n", arr[2]);    //输出修改后的

    for (int i = 0; i < 5; i++)

    {

        printf("arr[%d] = %d\n", i, arr[i]);    //遍历数组元素

    }

    system("pause");

    return 0;

}

●输出结果:

arr[2] = 3

arr[2] = 6

arr[0] = 1

arr[1] = 2

arr[2] = 6

arr[3] = 4

arr[4] = 5

请按任意键继续. . .

8.2.2 代码分析

我们可以利用数组名加中括号下标的形式访问数组中的每一个元素。如果要访问第2个数组元素,它的下标为2。如果有n个数组元素,访问最后一个数组元素下标为n-1,切记计算机中从0开始计数,数组下标不能溢出。

如果修改数组元素的值,同样需要使用数组名加中括号下标的形式表示数组元素,比如将 arr 数组中第 2个元素 3 变成 6。arr[2]=6;

我们可以把数组元素看作是一个独立的变量,变量名是变量存储的地址标号,数组元素就是使用数组下标方式命名的变量名。由于数组元素具有相同的数据类型,且连续存储在内存中,数组下标就是数组元素相对于数组起始地址的偏移(隐含比例因子),所以可以通过改变数组下标的方式变量数组元素。

一维数组使用一个for循环结构遍历数组。循环变量i作为数组下标arr[i]。循环变量i取值范围0~4,代表第0个到第4个数组元素。

8.2.3 汇编解析

汇编代码

;C标准库头文件和导入库

include vcIO.inc

.data

arr sdword  1,2,3,4,5

i sdword  0

.const    

szMsg1 db "arr[2] = %d",0dh,0ah,0

szMsg2 db "arr[%d] = %d",0dh,0ah,0

.code     

start:

       mov eax,[arr+2*4] ;输出第2个数组元素

       invoke printf,offset szMsg1,eax

       mov sdword ptr [arr+2*4],6 ;修改第2个数组元素的值为6

       mov eax,[arr+2*4]

       invoke printf,offset szMsg1,eax  

       .while i < 5

              ;数组元素的地址arr+4*i            

              mov ebx,i

              shl ebx,2

              mov eax,sdword ptr [arr+ebx];取数组元素值[arr+4*i]           

              invoke printf,offset szMsg2,i,eax 

              inc sdword ptr i

       .endw

       ;     

       invoke _getch

       ret                       

end start

●输出结果:

arr[2] = 3

arr[2] = 6

arr[0] = 1

arr[1] = 2

arr[2] = 6

arr[3] = 4

arr[4] = 5

      

访问数组元素:

语句:mov eax,[arr+2*4]     ;输出第2个数组元素

       第二个数组元素地址的计算方法:数组首地址arr+数组元素的偏移;

       偏移的计算方法为:数组下标*4,第2个数组元素的下标为2,每个数组元素占4个字节空间,所以第3个数组元素相对于数组起始地址的偏移为arr+4+4=arr+2*4。

       循环遍历数组元素:[arr+4*i]

       遍历数组元素就是计算每个数组元素的地址的过程。循环变量i作为数组下标,取值范围0~4。每个数组元素占用4个字节空间,4作为比例因子*i,再加上数组的起始地址就是每个数组元素的地址。

反汇编代码

           int arr[5] = { 1,2,3,4,5 }; //定义数组

008E1046  mov         dword ptr [arr],1 

008E104D  mov         dword ptr [ebp-14h],2 

008E1054  mov         dword ptr [ebp-10h],3 

008E105B  mov         dword ptr [ebp-0Ch],4 

008E1062  mov         dword ptr [ebp-8],5 

上述代码初始化数组arr,汇编代码将数组arr定义在数据段中,为全局变量。而C语言中,将数组arr定义为局部变量,在main函数中,因此数组存储在函数的堆栈中。数组首地址arr为第0个数组元素的地址arr+0=ebp-18h,以此类推,第1个数组元素的地址为ebp-14h,第2个数组元素地址为ebp-10h,第3个数组元素地址为ebp-0Ch,第4个数组元素地址为ebp-8,分别存入1,2,3,4,5。

    printf("arr[2] = %d\n", arr[2]); //打印arr数组中第2个元素

008E1069  mov         eax,4  ;比例因子,每个数组元素占4个字节内存

    printf("arr[2] = %d\n", arr[2]); //打印arr数组中第2个元素

008E106E  shl         eax,1  ;4*2

008E1070  mov         ecx,dword ptr arr[eax]  ;将第2个数组元素的值存入ecx

008E1074  push        ecx 

008E1075  push        8E3000h 

008E107A  call        printf (08E1100h)  ;输出第二个数组元素的值

008E107F  add         esp,8 

    arr[2] = 6;  //修改数组元素

008E1082  mov         edx,4  ;比例因子,edx为编译器随机分配的寄存器

008E1087  shl         edx,1  ;4*2

008E1089  mov         dword ptr arr[edx],6  ;将6存入第二个数组元素中

    printf("arr[2] = %d\n", arr[2]);   //输出修改后的

008E1091  mov         eax,4 

008E1096  shl         eax,1 

008E1098  mov         ecx,dword ptr arr[eax] 

008E109C  push        ecx 

008E109D  push        8E3010h 

008E10A2  call        printf (08E1100h)  ;输出第二个数组元素的值

008E10A7  add         esp,8 

    for (int i = 0; i < 5; i++);遍历数组元素

008E10AA  mov         dword ptr [ebp-4],0  ;表达式1

008E10B1  jmp         main+7Ch (08E10BCh) 

008E10B3  mov         edx,dword ptr [ebp-4]  ;表达式3

008E10B6  add         edx,1 

008E10B9  mov         dword ptr [ebp-4],edx 

008E10BC  cmp         dword ptr [ebp-4],5 

008E10C0  jge         main+9Dh (08E10DDh)  ;表达式2

    {

        printf("arr[%d] = %d\n", i, arr[i]);   //遍历数组元素

008E10C2  mov         eax,dword ptr [ebp-4]  ;将循环变量i存入eax

008E10C5  mov         ecx,dword ptr arr[eax*4]  ;取数组元素arr[i*4]的值

008E10C9  push        ecx 

008E10CA  mov         edx,dword ptr [ebp-4] 

008E10CD  push        edx 

008E10CE  push        8E3020h 

008E10D3  call        printf (08E1100h)  ;输出数组元素的值

008E10D8  add         esp,0Ch 

    }

008E10DB  jmp         main+73h (08E10B3h;跳转到表达式3

    system("pause");

008E10DD  push        8E3030h 

008E10E2  call        dword ptr [__imp__system (08E2078h)] 

008E10E8  add         esp,4 

    return 0;

       请读者留意注释代码中数组元素地址的计算方法。需要注意的是:在C语言中,数组arr定义在main函数内,作为局部变量存储在堆栈空间,使用栈内基址寄存器ebp计算每个数组元素的偏移地址。

如何获取第i个元素,其实就是获取其数组首部地址,加上相对偏移就可以计算出第i个元素的存储位置。我们定义的是int型变量,所以这些元素都有共同的特点,它们都是4个字节大小,所以只要找到数组的首地址,就可以找到存储第i个元素的位置。

通过数组内存结构图的形式展示:

首地址  

1

2

3

4

5

 

数组元素地址 = 首地址+偏移

第0个元素的地址 = 首地址+0*元素大小;

第1个元素的地址 = 首地址+1*元素大小;

第2个元素的地址 = 首地址+2*元素大小;

第3个元素的地址 = 首地址+3*元素大小;

第4个元素的地址 = 首地址+4*元素大小;

如果有i个元素:

第i个元素的地址 = 首地址+(i-1)*元素大小。

实验五十九:数组间赋值

在VS中新建项目8-2-2.c:

两个数组 arr1、arr2,arr1[6]={1,2,3,4,5,6};将数组 arr1 里的元素复制到数组 arr2中。

谨慎

既然是把一个数组的元素全部复制到另一个数组中,可不可以这样写呢?arr2=arr1;因为数组也是变量,给变量赋值不就是这样写的。如果你有这样的想法,那你就错了。数组名表示的是数组的起始地址,而不是数组的值。

我们来看正确的答案:

/*

   数组间赋值

*/

#include <stdio.h>

#include <stdlib.h>

int main(void) {

    int arr1[6] = { 1,2,3,4,5,6 };

    int arr2[6] = { 0 };

    //循环遍历数组元素并赋值

    for (int i = 0; i < 6; i++)

    {

        arr2[i] = arr1[i];

        printf("arr2[%d] = %d\n", i, arr2[i]);

    }

    system("pause");

    return 0;

}

●输出结果:

arr2[0] = 1

arr2[1] = 2

arr2[2] = 3

arr2[3] = 4

arr2[4] = 5

arr2[5] = 6

请按任意键继续. . .

●代码解析:

    int arr1[6]= {1,2,3,4,5,6};//定义arr1数组,并初始化。

int arr2[6]={0};//定义arr2数组,并将所有数组元素初始化为0。

使用for循环进行遍历数组中的元素。

1.当i = 0时,arr1[0] = 1,并把arr1[0]的元素赋给arr2[0],此时arr2[0]的元素为1;

输出 arr2[0] = 1;

2.当i = 1时,arr1[1] = 2,并把arr1[1]的元素赋给arr2[1],此时arr2[1]的元素为2;

输出 arr2[1] = 2;

    3.当i = 2时,arr1[2] = 3,并把arr1[2]的元素赋给arr2[2],此时arr2[2]的元素为3;

输出 arr2[2] = 3;

4.当i = 3时,arr1[3] = 4,并把arr1[3]的元素赋给arr2[3],此时arr2[3]的元素为4;

输出 arr2[3] = 4;

    5.当i = 4时,arr1[4] = 5,并把arr1[4]的元素赋给arr2[4],此时arr2[4]的元素为5;

输出 arr2[4] = 5;

    6.当i = 5时,arr1[5] = 6,并把arr1[5]的元素赋给arr2[5],此时arr2[5]的元素为6;

输出 arr2[5] = 6;

实验六十:数组元素倒序排序

在VS中新建项目8-2-3.c:

定义int型数组,并输入6个元素,按倒序的方式排序。

arr[0]与arr[5]交换

arr[1]与arr[4]交换

Arr[2]与arr[3]交换

/*

   数组元素倒序排序

*/

#include <stdio.h>

#include <stdlib.h>

int main(void) {

    int arr[6] = { 0 };

    int i;

    for (i = 0; i < 6; i++)

    {

        printf("arr[%d]=", i);

        scanf_s("%d", &arr[i]);//输出6个元素

    }

    for (i = 0; i < 3; i++) //交换

    {

        int temp = arr[i];//临时变量

        arr[i] = arr[5 - i];

        arr[5 - i] = temp;

    }

    printf("倒序:\n");

    for (i = 0; i < 6; i++)//交换后的数组进行输出

    {

        printf("arr[%d]=%d\n", i, arr[i]);

    }

    system("pause");

    return 0;

}

●输出结果:

arr[0]=1

arr[1]=2

arr[2]=3

arr[3]=4

arr[4]=5

arr[5]=6

倒序:

arr[0]=6

arr[1]=5

arr[2]=4

arr[3]=3

arr[4]=2

arr[5]=1

请按任意键继续. . .

●代码分析:

for(i=0;i<3;i++) //交换

    {

        int temp = arr[i];

        arr[i] = arr[5-i];

        arr[5-i] = temp;

    }

    主要分析这段代码:

    1.当i=0时,把arr[0]的元素放入变量temp中,然后把arr[5-0]的值放入arr[0]中,再把变量temp的值赋值给arr[5],此时完成arr[0]与arr[5]的交换。

2.当i=1时,把arr[1]的元素放入变量temp中,然后把arr[4]的值放入arr[1]中,再把变量temp的值赋值给arr[4],此时完成arr[1]与arr[4]的交换。

3.当i=2时,把arr[2]的元素放入变量temp中,然后把arr[3]的值放入arr[2]中,再把变量temp的值赋值给arr[3],此时完成arr[2]与arr[3]的交换。

实验六十一:数组元素的删除

在VS中新建项目8-2-4.c:

怎样实现数组元素的删除呢?

(1)、查找要删除数字的下标;

(2)、从下标开始,后面一个覆盖前面一个元素;

(3)、数组的总长度-1。

 注意

数组是一块连续的内存空间,一旦被定义,是不可以被改变大小的,因为在定义数组时,就已经写入内存中了,大小也被确定了。既然不能改变,那怎么删除呢?这属于障眼法,删除的元素会被它后面的元素覆盖掉,在控制台输出时,看似被删除了,但删除掉的那块内存已经被写入了,已分配的内存空间是不可能被抹掉的。

/*

   数组元素的删除

*/

#include <stdio.h>

#include <stdlib.h>

int main(void) {

    int arr[] = { 25,11,22,44,33 };

    int deleteArr = 0; //删除元素

    int deleteIndex = -1;//删除下标 给一个不可能的初始值,容易判断

    int i;

    int count = 5;

    printf("请输入要删除的元素:");

    scanf_s("%d", &deleteArr);

    for (i = 0; i < count; i++)

    {

        if (deleteArr == arr[i])

        {

            //记录下标

            deleteIndex = i;

            break;//找到后直接跳出循环

        }

    }

    //未找到要删除的数组元素

    if (-1 == deleteIndex)

    {

        printf("没有找到要删除的下标值");

    }

    else

    {

//从下标开始,后面一个覆盖前面一个

        for (i = deleteIndex; i < count - 1; i++)

        {

            arr[i] = arr[i + 1];

        }

        count--;//删除一个元素,其数组长度会减1

    }

    printf("删除后的数组:\n");

    //遍历数组

    for (i = 0; i < count; i++)

    {

        printf("%d   ", arr[i]);

    }

    printf("\n删除后的原数组:\n");

    //遍历数组

    for (i = 0; i < count+1; i++)

    {

        printf("%d   ", arr[i]);

    }

    printf("\n");

    system("pause");

    return 0;

}

●输出结果:

请输入要删除的元素:22

删除后的数组:

25   11   44   33

删除后的原数组:

25   11   44   33   33

请按任意键继续. . .

       ●代码分析:

删除前内存中的数组:

图8-5 删除前内存中的数组

图8-6 删除后内存中的数组

上图很好的诠释数组是一块连续的内存空间,一旦被定义,则是不可以被改变大小的。尽管我们在控制台显示输出的结果中已经没有了被删除的元素22,但是它申请的内存是存在的,后面一个数组元素44覆盖了22,同样再下一个数组元素33覆盖了44,最后一个数组元素33仍然保留在内存中。

实验六十二:插入数组元素

在VS中新建项目8-2-5.c:

/*

   插入数组元素

*/

#include <stdio.h>

#include <stdlib.h>

#define NUM 6

int main(void) {

    int arr[NUM] = {25,11,22,44,33};

    int instetArr = 0;

    int count = 5;

    int i = 0;

    printf("插入前的数组元素:\n");

    for (i; i < NUM; i++)

    {

        printf("%d   ", arr[i]);

    }

    printf("\n输入要插入的元素:");

    scanf_s("%d", &instetArr);

    arr[count++] = instetArr;

    for (i = 0; i < count; i++)

    {

        printf("%d   ", arr[i]);

    }

    printf("\n");

    system("pause");

    return 0;

}    

●输出结果:

插入前的数组元素:

25   11   22   44   33   0

输入要插入的元素:66

25   11   22   44   33   66

请按任意键继续. . .

●代码分析:

       如果要插入一个数组元素,必须保证有相应的内存空间。数组是静态内存分配,在编译器编译时,已经从数组名起始地址分配了固定的内存空间,不可以被改变。上述代码中使用#define宏定义了一个常量值NUM为6。表面初始化数组int arr[NUM] = {25,11,22,44,33};实际是int arr[NUM] = {25,11,22,44,33,0};输出的结果也证明了这一点。

    插入的值66覆盖了数组最后一个元素0。

    如果将66插入到数组的中间位置,将如何实现呢?

arr[NUM] = {25,11,66,22,44,33};

请读者参考8-2-4.c的代码独立完成。

练习

1、输入10名同学的成绩,并按从高到低的形式输出。

2、int arr[5] = {1,2,3,4,5}; 交换第二个元素和第三个元素。

3、int arr[4] = { 1, 2, 3, 4}; 求arr数组中元素的和、乘积。

4、使用数组表示下面的数据:

姓名      工资       工号

张三      10000.11    101

李四      9999.999    102

王五      8999.12     103

小李      12000       104

小王      15000       105

小章      14000.5     106

5、输入5名学生的分数并显示出他们的最高分和最低分。

6、把下面的汇编指令,写出对应的C语言代码。

00401010   push        ebp

00401011   mov         ebp,esp

00401013   sub         esp,64h

00401016   push        ebx

00401017   push        esi

00401018   push        edi

00401019   lea         edi,[ebp-64h]

0040101C   mov         ecx,19h

00401021   mov         eax,0CCCCCCCCh

00401026   rep stos    dword ptr [edi]

00401028   mov         dword ptr [ebp-14h],4Dh

0040102F   mov         dword ptr [ebp-10h],42h

00401036   mov         dword ptr [ebp-0Ch],21h

0040103D   mov         dword ptr [ebp-8],63h

00401044   mov         dword ptr [ebp-4],37h

0040104B   mov         dword ptr [ebp-18h],0

00401052   mov         dword ptr [ebp-1Ch],0FFFFFFFFh

00401059   mov         dword ptr [ebp-24h],5

00401060   push              offset string "\xc7\xeb\xca\xe4\xc8\xeb\xd2\xaa\xc9\xbe\xb3\xfd\xb5\xc4\xd4\xaa\xcb\xd8"

00401065   call        printf (00401320)

0040106A   add         esp,4

0040106D   lea         eax,[ebp-18h]

00401070   push        eax

00401071   push        offset string "%d" (0042505c)

00401076   call        scanf (004012c0)

0040107B   add         esp,8

0040107E   mov         dword ptr [ebp-20h],0

00401085   jmp         main+80h (00401090)

00401087   mov         ecx,dword ptr [ebp-20h]

0040108A   add         ecx,1

0040108D   mov         dword ptr [ebp-20h],ecx

00401090   mov         edx,dword ptr [ebp-20h]

00401093   cmp         edx,dword ptr [ebp-24h]

00401096   jge         main+9Eh (004010ae)

00401098   mov         eax,dword ptr [ebp-20h]

0040109B   mov         ecx,dword ptr [ebp-18h]

0040109E   cmp         ecx,dword ptr [ebp+eax*4-14h]

004010A2   jne         main+9Ch (004010ac)

004010A4   mov         edx,dword ptr [ebp-20h]

004010A7   mov         dword ptr [ebp-1Ch],edx

004010AA   jmp         main+9Eh (004010ae)

004010AC   jmp         main+77h (00401087)

004010AE   cmp         dword ptr [ebp-1Ch],0FFh

004010B2   jne         main+0B3h (004010c3)

004010B4   push        offset string "\xc3\xbb\xd3\xd0\xd5\xd2\xb5\xbd\xd2\xaa\xc9\xbe\xb3\xfd\xb5\xc4\xcf\xc2\

004010B9   call        printf (00401320)

004010BE   add         esp,4

004010C1   jmp         main+0E8h (004010f8)

004010C3   mov         eax,dword ptr [ebp-1Ch]

004010C6   mov         dword ptr [ebp-20h],eax

004010C9   jmp         main+0C4h (004010d4)

004010CB   mov         ecx,dword ptr [ebp-20h]

004010CE   add         ecx,1

004010D1   mov         dword ptr [ebp-20h],ecx

004010D4   mov         edx,dword ptr [ebp-24h]

004010D7   sub         edx,1

004010DA   cmp         dword ptr [ebp-20h],edx

004010DD   jge         main+0DFh (004010ef)

004010DF   mov         eax,dword ptr [ebp-20h]

004010E2   mov         ecx,dword ptr [ebp-20h]

004010E5   mov         edx,dword ptr [ebp+ecx*4-10h]

004010E9   mov         dword ptr [ebp+eax*4-14h],edx

004010ED   jmp         main+0BBh (004010cb)

004010EF   mov         eax,dword ptr [ebp-24h]

004010F2   sub         eax,1

004010F5   mov         dword ptr [ebp-24h],eax

004010F8   push        offset string "\xc9\xbe\xb3\xfd\xba\xf3\xb5\xc4\xbd\xe1\xb9\xfb\xa3\xba\n" (0042502c)

004010FD   call        printf (00401320)

00401102   add         esp,4

00401105   mov         dword ptr [ebp-20h],0

0040110C   jmp         main+107h (00401117)

0040110E   mov         ecx,dword ptr [ebp-20h]

00401111   add         ecx,1

00401114   mov         dword ptr [ebp-20h],ecx

00401117   mov         edx,dword ptr [ebp-20h]

0040111A   cmp         edx,dword ptr [ebp-24h]

0040111D   jge         main+126h (00401136)

0040111F   mov         eax,dword ptr [ebp-20h]

00401122   mov         ecx,dword ptr [ebp+eax*4-14h]

00401126   push        ecx

00401127   push        offset string "%d   " (00425024)

0040112C   call        printf (00401320)

00401131   add         esp,8

00401134   jmp         main+0FEh (0040110e)

00401136   push        offset string "pause" (0042501c)

0040113B   call        system (004011b0)

00401140   add         esp,4

00401143   xor         eax,eax

本文摘自编程达人系列教材《汇编的角度——C语言》。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于C++11实现的手写线程池

在实际的项目中&#xff0c;使用线程池是非常广泛的&#xff0c;所以最近学习了线程池的开发&#xff0c;在此做一个总结。 源码&#xff1a;https://github.com/Cheeron955/Handwriting-threadpool-based-on-C-17 项目介绍 项目分为两个部分&#xff0c;在初版的时候&#x…

STM32——定时器

一、简介 *定时器可以对输入的时钟进行计数&#xff0c;并在计数值达到设定值时触发中断 *16位计数器、预分频器、自动重装寄存器的时基单元&#xff0c;在72MHz计数时钟下可以实现最大59.65s的定时 *不仅具备基本的定时中断功能&#xff0c;而且还包含内外时钟源选择、输入…

ubuntu使用oh my zsh美化终端

ubuntu使用oh my zsh美化终端 文章目录 ubuntu使用oh my zsh美化终端1. 安装zsh和oh my zsh2. 修改zsh主题3. 安装zsh插件4. 将.bashrc移植到.zshrcReference 1. 安装zsh和oh my zsh 首先安装zsh sudo apt install zsh然后查看本地有哪些shell可以使用 cat /etc/shells 将默…

平方回文数-第13届蓝桥杯选拔赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第73讲。 平方回文数&#…

监控云安全的9个方法和措施

如今&#xff0c;很多企业致力于提高云计算安全指标的可见性&#xff0c;这是由于云计算的安全性与本地部署的安全性根本不同&#xff0c;并且随着企业将应用程序、服务和数据移动到新环境&#xff0c;需要不同的实践。检测云的云检测就显得极其重要。 如今&#xff0c;很多企业…

windows tomcat服务注册和卸载

首页解压tomcat压缩包&#xff0c;然后进入tomcat bin目录&#xff0c;在此目录通过cmd进入窗口&#xff0c; 1&#xff1a;tomcat服务注册 执行命令&#xff1a;service.bat install tomcat8.5.100 命令执行成功后&#xff0c;会在注册服务列表出现这个服务&#xff0c;如果…

打造爆款活动:确定目标受众与吸引策略的实战指南

身为一名文案策划经理&#xff0c;我深知在活动策划的海洋中&#xff0c;确定目标受众并设计出能触动他们心弦的策略是何等重要。 通过以下步骤&#xff0c;你可以更准确地确定目标受众&#xff0c;并制定出有效的吸引策略&#xff0c;确保活动的成功&#xff1a; 明确活动目…

Unity【入门】环境搭建、界面基础、工作原理

Unity环境搭建、界面基础、工作原理 Unity环境搭建 文章目录 Unity环境搭建1、Unity引擎概念1、什么是游戏引擎2、游戏引擎对于我们的意义3、如何学习游戏引擎 2、软件下载和安装3、新工程和工程文件夹 Unity界面基础1、Scene场景和Hierarchy层级窗口1、窗口布局2、Hierarchy层…

企业如何实现数据采集分析展示一体化

在当今数字化时代&#xff0c;企业越来越依赖于数据的力量来驱动决策和创新。通过全量实时采集各类数据&#xff0c;并利用智能化工具进行信息处理&#xff0c;企业能够借助大数据分析平台深入挖掘数据背后的价值&#xff0c;从而为企业发展注入新动力。 一、企业痛点 随着数字…

基于单片机智能防触电装置的研究与设计

摘 要 &#xff1a; 针对潮湿天气下配电线路附近易发生触电事故等问题 &#xff0c; 对单片机的控制算法进行了研究 &#xff0c; 设 计 了 一 种 基 于 单片机的野外智能防触电装置。 首先建立了该装置的整体结构框架 &#xff0c; 再分别进行硬件设计和软件流程分析 &#xf…

水电表远程抄表:智能化时代的能源管理新方式

1.行业背景与界定 水电表远程抄表&#xff0c;是随着物联网技术发展&#xff0c;完成的一种新型的能源计量管理方式。主要是通过无线传输技术&#xff0c;如GPRS、NB-IoT、LoRa等&#xff0c;将水电表的信息实时传输到云服务器&#xff0c;进而取代了传统人工当场抄水表。这种…

MySQL 重启之后无法写入数据了?

数据库交接后因 persist_only 级别的参数设置引发的故障分析。 作者&#xff1a;不吃芫荽&#xff0c;爱可生华东交付服务部 DBA 成员&#xff0c;主要负责 MySQL 故障处理及相关技术支持。 爱可生开源社区出品&#xff0c;原创内容未经授权不得随意使用&#xff0c;转载请联系…

冯喜运:5.29市场避险情绪升温,黄金原油小幅收涨

【黄金消息面分析】&#xff1a;周二&#xff08;5月28日&#xff09;美盘时段&#xff0c;由于美元走弱且市场情绪出现负面变化&#xff0c;黄金收复早前跌幅&#xff0c;站上2350美元关口。金价早盘一度走弱&#xff0c;源于美联储降息可能性降低带来压力&#xff0c;投资者在…

HTML+CSS TAB导航栏

效果演示 这段代码实现了一个名为"Tab导航栏"的效果,它是一个基于CSS的导航栏,包含五个选项卡,每个选项卡都有一个带有渐变背景色的滑块,当用户点击选项卡时,滑块会滑动到相应的位置。同时,选中的选项卡会变为白色,未选中的选项卡会变为灰色。 Code <!DOC…

SARscape雷达图像处理软件简介

合成孔径雷达&#xff08;SAR&#xff09;拥有独特的技术魅力和优势&#xff0c;渐成为国际上的研究热点之一&#xff0c;其应用领域越来越广泛。SAR数据可以全天候对研究区域进行量测、分析以及获取目标信息。高级雷达图像处理工具SARscape&#xff0c;能让您轻松将原始SAR数据…

每天写两道(二)LRU缓存、

146.LRU 缓存 . - 力扣&#xff08;LeetCode&#xff09; 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存int get(int key) 如果关键字 key 存在于缓存…

猜猜我是谁游戏

猜谜过程 在TabControl控件中&#xff0c;第一个tab中放了一个PictureBox&#xff0c;里面有一张黑色的图片。 玩家点击显示答案按钮&#xff0c;切换图片。 设计器 private void button1_Click(object sender, EventArgs e){this.pictureBox1.Image Image.FromFile(&qu…

网络渗透day2

Windows登录的明文密码存储过程和密文存储位置 明文密码存储过程&#xff1a; Windows操作系统不会以明文形式存储用户密码。相反&#xff0c;当用户设置或更改密码时&#xff0c;系统会对密码进行哈希处理&#xff0c;然后存储其哈希值。哈希处理的目的是为了提高密码的安全性…

设计模式——职责链(责任链)模式

目录 职责链模式 小俱求实习 结构图 实例 职责链模式优点 职责链模式缺点 使用场景 1.springmvc流程 ​2.mybatis的执行流程 3.spring的过滤器和拦截器 职责链模式 使多个对象都有机会处理请求&#xff0c;从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成…

VM虚拟机共享文件夹fuse: bad mount point `/mnt/hgfs‘: No such file or directory

报错显示挂载点 /mnt/hgfs 不存在&#xff0c;你需要先创建这个目录。可以按照以下步骤进行操作&#xff1a; 创建挂载点目录&#xff1a; sudo mkdir -p /mnt/hgfs 手动挂载共享文件夹&#xff1a; sudo vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other 确保每次启动时自动…