当前位置: 首页 > news >正文

C语言数组全面解析:从初学到精通

数组

    • 1. 前言
    • 2. 一维数组的创建和初始化
    • 3. 一维数组的使用
    • 4. 一维数组在内存中的存储
    • 5. 二维数组的创建和初始化
    • 6. 二维数组的使用
    • 7. 二维数组在内存中的存储
    • 8. 数组越界
    • 9. 数组作为函数参数
    • 10. 综合练习
      • 10.1 用函数初始化,逆置,打印整型数组
      • 10.2 交换两个整型数组
      • 10.3 三子棋
      • 10.4 扫雷

在这里插入图片描述

1. 前言

大家好,我是努力学习游泳的鱼。今天我们来学习数组。
在这里插入图片描述
数组分为一维数组和二维数组,我们需要学习它们如何创建和初始化,如何使用,如何在内存中存储。话不多说,让我们开始对数组的学习吧。

2. 一维数组的创建和初始化

数组是一组相同类型元素的集合。

一维数组的创建格式如下:
数组的元素类型 数组名[常量表达式];
int arr[100]; // 表示数组能存放100个int类型的数据
我们使用大括号来初始化数组。
完全初始化:对数组的所有元素都进行初始化。大括号里初始化的元素个数和数组最多存放的元素个数相同。
int arr[10] = {1,2,3,4,5,6,7,8,9,10}; // 完全初始化:数组最多存放10个元素,大括号内初始化了10个元素
不完全初始化:只初始化数组的部分元素,剩下的被初始化成0
int arr[100] = {0}; // 不完全初始化:第一个元素被手动初始化成0,剩下的元素默认被初始化为0
如果对数组初始化,数组大小可以省略,默认为初始化元素的个数。如下面两种写法效果是相同的。

int arr[5] = {1,2,3,4,5};
int arr[] = {1,2,3,4,5}; // 省略数组大小,默认是5

如果创建数组时不初始化,则数组大小不能省略,此时分为两种情况:

  1. 局部数组里存放的都是随机值。
  2. 全局数组会被默认初始化为0
int arr1[10]; // 默认初始化为0int main()
{int arr2[10]; // 存储的是随机值return 0;
}

对于一个变量,这两种情况也成立。

  1. 当一个局部变量不初始化时,存储的是随机值。
  2. 当一个全局变量或静态变量不手动初始化时,会被默认初始化成0
int a; // 默认初始化为0int main()
{static int b; // 默认初始化为0int c; // 存储的是随机值return 0;
}

本质上,这是存储位置的差异导致的。局部变量是存储在栈区的,栈区上的数据如果不初始化,存储的是随机值。全局变量和静态变量是存储在静态区的,静态区上的数据如果不手动初始化,会被默认初始化为0

C99中引入了变长数组的概念,允许数组的大小用变量来指定,如果编译器不支持C99中的变长数组,那就不能使用。

int n = 10;
int arr[n]; // 变长数组

变长数组不能初始化。

int n = 10;
int arr[n] = {0}; // 不能像这样初始化

3. 一维数组的使用

数组通过下标来访问,数组的下标是0开始的。
[]是下标引用操作符。

比如,int arr[] = {10,20,30,40,50};,10的下标是020的下标是130的下标是240的下标是350的下标是4
那么,arr[3]对应的就是40,如果我们想把40改成400,就这么写:arr[3] = 400;
我们如何计算数组的元素个数呢?很简单,用数组的总大小除以数组一个元素的大小就行了。比如对于arr数组,数组元素个数sz就可以这么算:int sz = sizeof(arr) / sizeof(arr[0]);
假设我们想存储1~100的整数并打印出来,就可以这么写:

#include <stdio.h>int main()
{int arr[100] = { 0 };int sz = sizeof(arr) / sizeof(arr[0]);int i = 0;for (; i < sz; ++i){arr[i] = i + 1;}for (i = 0; i < sz; ++i){printf("%d ", arr[i]);}return 0;
}

4. 一维数组在内存中的存储

一维数组在内存中是连续存放的。
随着数组下标的增长,地址是由低到高变化的。

我们可以写个程序来验证。

#include <stdio.h>int main()
{int arr[10] = { 0 };int sz = sizeof(arr) / sizeof(arr[0]);int i = 0;for (; i < sz; ++i){printf("&arr[%d] = %p\n", i, &arr[i]);}return 0;
}

我们把数组元素的地址按照下标从低到高打印出来。
在这里插入图片描述

我们发现,相邻两个元素之间的地址都差4,这是因为数组在内存中是连续存放的,相邻元素的地址就差一个int,即4个字节。
并且,随着下标的增长,地址是由低到高变化的。

5. 二维数组的创建和初始化

如我们想要创建一个三行五列的二维整型数组,就可以这么写:int arr[3][5];这个数组有三行五列,共15个元素,每个元素是int类型的。
int int int int int
int int int int int
int int int int int
对二维数组进行初始化要使用大括号,初始化时会一行一行放,一行放满后才会放下一行。若是不完全初始化,剩余元素会被默认初始化成0
如:int arr[3][5] = { 1,2,3,4,5,6 };的效果是:
1 2 3 4 5
6 0 0 0 0
0 0 0 0 0
由于二维数组的每一行都可以看作一个一维数组,如果要对每一行分别初始化,可以在大括号里使用大括号。
这么说有点抽象,举个例子:int arr[3][5] = { {1,2}, {3,4}, {5,6} };的效果是:
1 2 0 0 0
3 4 0 0 0
5 6 0 0 0
如果对二维数组初始化,二维数组的行可以省略,但是列不能省略。如果省略二维数组的行,编译器会根据初始化的内容来确定有几行。
如:int arr[][5] = {1,2,3,4,5,6};的效果是:
1 2 3 4 5
6 0 0 0 0
由于两行就够放了,编译器会默认行数为2
再比如:int arr[][5] = { {1,2}, {3,4}, {5,6} };的效果是:
1 2 0 0 0
3 4 0 0 0
5 6 0 0 0
由于3行就够放了,编译器会默认行数为3
如果我们想给数组的所有元素都初始化成0,就可以这么写:
int arr[3][5] = {0};数组的第一个元素被初始化成0,剩下的元素会被默认初始化成0,效果是,数组的全部元素都被初始化成0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0

6. 二维数组的使用

二维数组也是用下标来访问的。和一维数组的区别是,二维数组有两个下标,行标和列标。行标和列标都是从0开始的。比如说,一个35列的数组arr,每个位置的元素的访问方式如下:
arr[0][0] arr[0][1] arr[0][2] arr[0][3] arr[0][4]
arr[1][0] arr[1][1] arr[1][2] arr[1][3] arr[1][4]
arr[2][0] arr[2][1] arr[2][2] arr[2][3] arr[2][4]
如果我们想把这些元素打印出来,可以用一层循环产生行标,另一层循环产生列标。每行打印完后,记得换个行。

#include <stdio.h>int main()
{int arr[3][5] = { {1,2,3,4,5}, {2,3,4,5,6}, {3,4,5,6,7} };int i = 0;for (; i < 3; ++i){int j = 0;for (; j < 5; ++j){printf("%d ", arr[i][j]);}printf("\n");}return 0;
}

当然,二维数组有几行几列也是可以通过代码计算出来的。
计算行数的方法:sizeof(arr) / sizeof(arr[0]);即数组的总大小除以数组第一行元素的大小。
计算列数的方法:sizeof(arr[0]) / sizeof(arr[0][0]);即数组第一行元素的大小除以数组第一行第一列的元素的大小。
上面的代码就可这样改进:

#include <stdio.h>int main()
{int arr[3][5] = { {1,2,3,4,5}, {2,3,4,5,6}, {3,4,5,6,7} };int i = 0;for (; i < sizeof(arr) / sizeof(arr[0]); ++i){int j = 0;for (; j < sizeof(arr[0]) / sizeof(arr[0][0]); ++j){printf("%d ", arr[i][j]);}printf("\n");}return 0;
}

7. 二维数组在内存中的存储

我们用下面的程序把二维数组每个元素的地址打印出来。

#include <stdio.h>int main()
{int arr[3][5] = { 0 };int i = 0;for (; i < sizeof(arr) / sizeof(arr[0]); ++i){int j = 0;for (; j < sizeof(arr[0]) / sizeof(arr[0][0]); ++j){printf("&arr[%d][%d] = %p\n", i, j, &arr[i][j]);}}return 0;
}

在这里插入图片描述
我们发现,每两个元素之间都差4个字节,每当发生换行,如第一行最后一个元素arr[0][4]到第二行第一个元素arr[1][0]也差4个字节。arr是一个整型数组,每两个元素之间差1int类型的大小。这说明:

二维数组在内存中也是连续存放的。
随着下标的增长,地址也是由低到高变化的。

除此之外,我们还可以把二维数组的每个元素理解成一维数组。如:对于三行五列的二维数组arrarr[0]就是这个二维数组的第一个元素,同时arr[0]也是一个有五个元素的一维数组,这五个元素分别是arr[0][0]arr[0][1]arr[0][2]arr[0][3]arr[0][4]

8. 数组越界

数组的下标是有范围限制的。
数组的下标规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1
所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。
C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的,所以程序员写代码时,最好自己做越界的检查。
如下面的程序,当i10时就越界了。

int main()
{int arr[10] = {0};int i = 0;for (; i<=10; ++i){arr[i] = i;}return 0;
}

二维数组的行和列也可能存在越界。

9. 数组作为函数参数

数组名表示什么?看看下面的代码:

#include <stdio.h>int main()
{int arr[10] = { 0 };printf("arr = %p\n", arr);printf("arr + 1 = %p\n", arr + 1);printf("&arr[0] = %p\n", &arr[0]);printf("&arr[0] + 1 = %p\n", &arr[0] + 1);printf("&arr = %p\n", &arr);printf("&arr + 1 = %p\n", &arr + 1);printf("sizeof(arr) = %d\n", sizeof(arr));return 0;
}

运行结果:
在这里插入图片描述
由运行结果可知,数组名(arr)和数组首元素地址(&arr[0])是完全相同的,且+1之后也是完全相同的,都跳过了4个字节(1int)。数组的地址(&arr)和前两者值是相同的,但+1之后跳过了40个字节(即跳过了整个数组),这是因为,如果写arr&arr[0]都表示首元素地址,即第一个整型元素的地址,+1会跳过一个整型;如果写&arr,取出的是整个数组的地址,+1自然也跳过了整个数组。注意:以上所有计算都是十六进制的计算,如所谓的跳过40个字节其实是+0x28,再转换成十进制后得到的40
并且,sizeof(arr)计算的是整个数组的大小,即40

数组名一般表示数组首元素的地址。但是有两个例外:

  1. sizeof(数组名),数组名不是数组首元素的地址,数组名表示整个数组,计算的是整个数组的大小。
  2. &数组名,数组名不是数组首元素的地址,数组名表示整个数组,取出的是整个数组的地址。

题目:写一个函数,对一个整型数组进行冒泡排序。

冒泡排序:对数组中2个相邻的元素进行比较,如果不满足就交换。

比如,一个数组里存放的是
9 8 7 6 5 4 3 2 1 0
我想把它排成升序,也就是左边的数要比右边的数小。
首先比较98,因为98大,不满足升序,就交换。
8 9 7 6 5 4 3 2 1 0
接着比较97,因为97大,不满足升序,就交换。
8 7 9 6 5 4 3 2 1 0
接着比较96,因为96大,不满足升序,就交换。
8 7 6 9 5 4 3 2 1 0
……
这一趟冒泡排序下来,数组就排序成
8 7 6 5 4 3 2 1 0 9
9的位置就正确了。接下来进行下一趟冒泡排序。由于9的位置处在正确的位置上,下一趟冒泡排序就不需要考虑9了,只需排序除了9之外的数字。
首先比较87,因为87大,不满足升序,就交换。
7 8 6 5 4 3 2 1 0 9
接着比较86,因为86大,不满足升序,就交换。
7 6 8 5 4 3 2 1 0 9
……
这一趟冒泡排序下来,数组就排序成
7 6 5 4 3 2 1 0 8 9
8的位置就正确了。
有没有发现,一趟冒泡排序,可以使一个数字的位置正确。那么,假设有10个数字,总共需要几趟冒泡排序呢?答案:10个数字需要9趟冒泡排序。因为一趟冒泡排序搞定一个数字,9趟冒泡排序就搞定9个数字,最后一个数字的位置自然也是正确的。
那么一趟内部又需要多少次比较呢?假设有10个数字,第一趟就需要比较9次,第一趟结束后就搞定了其中一个数字,只需排序剩下9个数字,所以第二趟需要比较8次。由于每趟排序都能够搞定一个数字,每趟排序都会比上一趟少一次比较,这样就知道每一趟需要几次比较了。
有了以上的分析,我们需要写两层循环。外层循环负责控制冒泡排序的趟数,假设数组有sz个元素,就需要排序sz-1趟;内层循环控制一趟内部冒泡排序的比较,第一趟需要sz-1次比较,第二趟需要sz-2次比较,后面每趟都比前一趟少一次比较,如果外层循环的循环变量(假设是i)是从0开始的,那第i趟就需要sz-1-i次比较。
如果一趟比较完后没有发生交换,则数组就已经有序了,就不需要继续排序了。我们可以定义一个flag并初始化为1,假设数组已经有序。如果发生交换,则把flag改成0。如果一趟冒泡排序中没有发生交换,则flag仍然是1,就已经有序了,不需要继续排序了。
数组元素个数怎么知道呢?一定要在数组创建的局部范围内计算数组的元素个数int sz = sizeof(arr) / sizeof(arr[0]);因为如果传参给别的函数后,我们使用数组名传参,由前面的知识可知,数组名表示数组首元素的地址,传递过去的是一个指针,所以sizeof(arr)就是4或者8sizeof(arr) / sizeof(arr[0])这个表达式是无法计算出数组元素个数的。

#include <stdio.h>void bubble_sort(int arr[], int sz)
{int i = 0;for (; i < sz - 1; ++i){// 一趟冒泡排序int flag = 1; // 假设已经有序int j = 0;for (; j < sz - 1 - i; ++j){if (arr[j] > arr[j + 1]){flag = 0;// 交换int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}}if (1 == flag)return;}
}int main()
{int arr[] = { 9,8,7,6,5,4,3,2,1,0 };int sz = sizeof(arr) / sizeof(arr[0]);// 冒泡排序bubble_sort(arr, sz);int i = 0;for (; i < sz; ++i){printf("%d ", arr[i]);}return 0;
}

当然,就一种情况是无法代表所有场景的。我写了个测试代码,在不同场景下测试这个冒泡排序是否正确,供大家参考。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>int test_bubble_sort()
{srand((unsigned int)time(NULL));const int sz = 100; // 数组元素个数int* arr = (int*)malloc(sz * sizeof(int));if (NULL == arr){perror("test_bubblesort::malloc");return 0;}int i = 0;for (; i < 1000; ++i){// 生成随机数组int j = 0;for (; j < sz; ++j){arr[j] = rand();}// 冒泡排序bubble_sort(arr, sz);// 检验排序是否成功for (j = 0; j < sz - 1; ++j){if (arr[j] > arr[j + 1]){free(arr);return 0; // 排序失败}}}free(arr);return 1; // 检验成功
}int main()
{int ret = test_bubble_sort();if (1 == ret)printf("检验成功\n");elseprintf("检验失败\n");return 0;
}

10. 综合练习

10.1 用函数初始化,逆置,打印整型数组

初始化和打印应该相当简单了吧,只需要产生所有的下标,遍历数组,就能够访问整个数组并初始化或打印了。唯一需要注意的是,整型数组无法在函数内部使用sizeof(arr) / sizeof(arr[0])计算元素个数,因为数组作为函数参数传递时,传递的是首元素的地址。
初始化函数(假设初始化为全0):

void init(int arr[], int sz)
{int i = 0;for (; i < sz; ++i){arr[i] = 0;}
}

打印函数:

#include <stdio.h>void print(int arr[], int sz)
{int i = 0;for (; i < sz; ++i){printf("%d ", arr[i]);}printf("\n");
}

接下来讲讲如何逆置。类似字符串的逆置,整型数组的逆置只需交换第一个元素和最后一个元素,再交换第二个元素和倒数第二个元素,接着交换第三个元素和倒数第三个元素……
如果用下标来访问数组,我们需要一个左下标left指向第一个元素,一个右下标right指向最后一个元素,交换后,left向后走,right向前走,当left还在right左边时,说明还有元素可以交换,否则就跳出循环。

void reverse(int arr[], int sz)
{int left = 0;int right = sz - 1;while (left < right){int tmp = arr[left];arr[left] = arr[right];arr[right] = tmp;++left;--right;}
}

10.2 交换两个整型数组

如何交换两个整型数组arr1arr2(假设两个数组一样大)呢?
很简单,只需要遍历两个数组,把对应位置的元素交换就行了!

#include <stdio.h>int main()
{int arr1[] = { 1,3,5,7,9 };int arr2[] = { 2,4,6,8,0 };int i = 0;int sz = sizeof(arr1) / sizeof(arr1[0]);printf("交换前:\n");printf("arr1: ");for (i = 0; i < sz; ++i){printf("%d ", arr1[i]);}printf("\narr2: ");for (i = 0; i < sz; ++i){printf("%d ", arr2[i]);}printf("\n");// 交换arr1和arr2for (i = 0; i < sz; ++i){int tmp = arr1[i];arr1[i] = arr2[i];arr2[i] = tmp;}printf("交换后:\n");printf("arr1: ");for (i = 0; i < sz; ++i){printf("%d ", arr1[i]);}printf("\narr2: ");for (i = 0; i < sz; ++i){printf("%d ", arr2[i]);}printf("\n");return 0;
}

10.3 三子棋

我们可以用已有的知识,实现一个三子棋小游戏。详细讲解戳这里

10.4 扫雷

再来实现一个扫雷小游戏。详细讲解戳这里

相关文章:

C语言数组全面解析:从初学到精通

数组 1. 前言2. 一维数组的创建和初始化3. 一维数组的使用4. 一维数组在内存中的存储5. 二维数组的创建和初始化6. 二维数组的使用7. 二维数组在内存中的存储8. 数组越界9. 数组作为函数参数10. 综合练习10.1 用函数初始化&#xff0c;逆置&#xff0c;打印整型数组10.2 交换两…...

2024-02-28(Kafka,Oozie,Flink)

1.Kafka的数据存储形式 一个主题由多个分区组成 一个分区由多个segment段组成 一个segment段由多个文件组成&#xff08;log&#xff0c;index&#xff08;稀疏索引&#xff09;&#xff0c;timeindex&#xff08;根据时间做的索引&#xff09;&#xff09; 2.读数据的流程 …...

Window下编写的sh文件在Linux/Docker中无法使用

Window下编写的sh文件在Linux/Docker中无法使用 一、sh文件目的1.1 初始状态1.2 目的 二、过程与异常2.1 首先获取标准ubuntu20.04 - 正常2.2 启动ubuntu20.04容器 - 正常2.3 执行windows下写的preInstall文件 - 报错 三、检查和处理3.1 评估异常3.2 处理异常3.3 调整后运行测试…...

第16章-DNS

目录 1. 域名 1.1 产生背景 1.2 概述 1.3 域名的树形层次化结构 2. DNS 2.1 概述 2.2 工作机制 3. DNS查询模式 3.1 递归查询&#xff1a; 3.2 迭代查询&#xff1a; 4. 相关知识点 4.1 集中式DNS 4.2 国内通用DNS 4.3 配置DNS代理 1. 域名 1.1 产生背景 ① IP…...

Leetcoder Day27| 贪心算法part01

语言&#xff1a;Java/Go 理论 贪心的本质是选择每一阶段的局部最优&#xff0c;从而达到全局最优。 什么时候用贪心&#xff1f;可以用局部最优退出全局最优&#xff0c;并且想不到反例到情况 贪心的一般解题步骤 将问题分解为若干个子问题找出适合的贪心策略求解每一个子…...

SpringBoot自动配置中bean的加载控制

&#x1f648;作者简介&#xff1a;练习时长两年半的Java up主 &#x1f649;个人主页&#xff1a;程序员老茶 &#x1f64a; ps:点赞&#x1f44d;是免费的&#xff0c;却可以让写博客的作者开心好久好久&#x1f60e; &#x1f4da;系列专栏&#xff1a;Java全栈&#xff0c;…...

Linux系统运维脚本:根据菜单选择要登录到的Linux主机,方便维护多个linux服务器

目 录 一、要求 二、解决方案 &#xff08;一&#xff09;解决思路 &#xff08;二&#xff09;方案 三、脚本程序实现 &#xff08;一&#xff09;脚本代码和解释 1、定义hosts.txt文件 2、脚本代码 3、代码解释 &#xff08;二&#xff09;脚本验证 1…...

蓝桥杯练习题——二分

1.借教室 思路 1.随着订单的增加&#xff0c;每天可用的教室越来越少&#xff0c;二分查找最后一个教室没有出现负数的订单编号 2.每个订单的操作是 [s, t] 全部减去 d #include<iostream> #include<cstring> using namespace std; const int N 1e6 10; int d[…...

Java面试——Redis

优质博文&#xff1a;IT-BLOG-CN 一、Redis 为什么那么快 【1】完全基于内存&#xff0c;绝大部分请求是纯粹的内存操作&#xff0c;非常快速。数据存在内存中。 【2】数据结构简单&#xff0c;对数据操作也简单&#xff0c;Redis中的数据结构是专门进行设计的。 【3】采用单线…...

信号系统之复数傅立叶变换

1 实数DFT 傅里叶变换系列的所有四个成员&#xff08;DFT、DTFT、傅里叶变换和傅里叶级数&#xff09;都可以用实数或复数进行。由于DSP主要关心的是DFT&#xff0c;所以就以它为例。 可以根据以下方程定义离散傅里叶变换的实数版本&#xff1a; 一个 N 个样本时域信号 被分解…...

Unity - 相机画面为黑白效果

一、 在Hierarchy中创建一个Global Volume,并设置它为局部作用 二、 将场景出现的作用域范围缩小至相机所在位置&#xff0c;将相机包含即可。 三、添加覆盖组件Color Adjustments,并将Saturation直接拉为-100 。 此时&#xff0c;相机拍摄画面为黑白&#xff0c;场景视图中…...

哈啰Java 春招 24届

时长 1h 3. 为什么使用分布式ID&#xff0c;解决了什么问题 4. Leaf算法了解吗&#xff1f;讲一下原理和工作流程以及优缺点 5. 有没有可能导致id重复&#xff1f;该如何解决&#xff1f; 6. 项目中redis是如何运用的&#xff1f; 7. 项目中分布式锁是如何实现的&#xff1f; 8…...

《剑指 Offer》专项突破版 - 面试题 68 : 查找插入位置/ 69 : 山峰数组的顶部(C++ 实现)

目录 面试题 68 : 查找插入位置 面试题 69 : 山峰数组的顶部 面试题 68 : 查找插入位置 题目&#xff1a; 输入一个排序的整数数组 nums 和一个目标指 t&#xff0c;如果数组 nums 中包含 t&#xff0c;则返回 t 在数组中的下标&#xff1b;如果数组 nums 中不包含 t&#…...

赖迪思软件 lattice Diamond

问题1&#xff1a;工程编译好后&#xff0c;git上传&#xff0c;变更分支又切换回来&#xff0c;再次编译有时候失败&#xff0c;所以配置好的管脚变成默认的&#xff0c;生成的IP核变成名变粗&#xff08;顶部文件&#xff0c;管脚配置显示IP核输入输出信号配置&#xff09;。…...

ROS开发基础-Linux基础第四部(开发板设置本地IP)

一 、网线连接设备 使用网线连接jetson NX与机械臂&#xff0c;如下图所示&#xff1a; 二、 修改上位机IPV4 IP ①测试是否可连接。网线连接机械臂之后&#xff0c;在桌面打开终端输入命令“ping 192.168.1.18”,如不可正常通信&#xff0c;可按照下述步骤进行设置。 ②在U…...

TSINGSEE青犀AI智能分析网关V4智慧油田安全生产监管方案

一、方案背景 随着科技的不断发展&#xff0c;视频监控技术在油田行业中得到了广泛应用。为了提高油田生产的安全性和效率&#xff0c;建设一套智能视频监控平台保障安全生产显得尤为重要。本方案采用先进的视频分析技术、物联网技术、云计算技术、大数据和人工智能技术&#…...

C++基于多设计模式下的同步异步日志系统day3

C基于多设计模式下的同步&异步日志系统day3 &#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;C基于多设计模式下的同步&异步日志系统 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&am…...

Cypher语句查询neo4j数据库教程

文章目录 Cypher介绍执行Cypher语句查询总结 Cypher介绍 NodeMatcher和RelationshipMatcher能够表达的匹配条件相对简单&#xff0c;更加复杂的查询还是需要用Cypher语句来表达。 Py2neo本身支持执行Cypher语句的执行&#xff0c;可以将复杂的查询写成Cypher语句&#xff0c;…...

【ESP32 IDF快速入门】点亮第一个LED灯与流水灯

文章目录 前言一、有哪些工作模式&#xff1f;1.1 GPIO的详细介绍1.2 GPIO的内部框图输入模式输出部分 二、GPIO操作函数2.1 GPIO 汇总2.2 GPIO操作函数gpio_config配置引脚reset 引脚函数设置引脚电平选中对应引脚设置引脚的方向 2.3 点亮第一个灯 三、流水灯总结 前言 ESP32…...

再见,Visual Basic——曾经风靡一时的编程语言

2020年3月&#xff0c;微软团队宣布了对Visual Basic&#xff08;VB&#xff09;的“终审判决”&#xff1a;不再进行开发或增加新功能。这意味着曾经风光无限的VB正式退出了历史舞台。 VB是微软推出的首款可视化编程软件&#xff0c;自1991年问世以来&#xff0c;便受到了广大…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹&#xff0c;并新增内容 3.创建package文件夹...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

算法:模拟

1.替换所有的问号 1576. 替换所有的问号 - 力扣&#xff08;LeetCode&#xff09; ​遍历字符串​&#xff1a;通过外层循环逐一检查每个字符。​遇到 ? 时处理​&#xff1a; 内层循环遍历小写字母&#xff08;a 到 z&#xff09;。对每个字母检查是否满足&#xff1a; ​与…...