C语言---数组

news2024/10/7 8:24:24

1、一维数组的创建和初始化

1.1、数组的创建

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

数组的创建方式:

type_t arr_name [const_n];

//type_t 是指数组的元素类型
//const_n 是一个常量表达式,用来指定数组的大小。

1.2、数组的初始化

数组的初始化是指,在创建数组的同时给数组的内容一些合理初始值(初始化)。

//不完全初始化,剩余的元素默认初始化位0
int arr1[10] = {1,2,3};

int arr2[] = {1,2,3};

int arr3[5] = {'1','2','3','4','5'};

char arr4[3] = {'a','98','c'};

char arr5[10] = {'a','b','c'};

char arr6[10] = "abcdef";

arr5和arr6存放元素的效果一样,但是有些细节还是不相同的:

arr5:是人为放进去:‘a’,‘b’,‘c’,然后后面补充0。

arr6:是认为放进去:a’,‘b’,‘c’,‘\0’,然后后面补充0。

那为什么说效果一样呢?因为’\0’的ASCII值为0,所以数组里面存放的是’\0’,其实是以它的ASCII值0存放的。

重点是:字符串有’\0’,而字符没有’\0’。

1.3、一维数组的使用

int arr[10] = {0};                 //数组的不完全使用

int sz = sizeof(arr) / sizeof(arr[0]);      //计算数组元素的个数
    
arr[i]       //数组的访问。

总结:

  • 数组是使用下标来访问的,下标是从0开始的。
  • 数组的大小是可以通过计算得到的。

1.4、一维数组在内存中的存储

看代码:

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

输出:

在这里插入图片描述

可以发现:每一个元素地址值相差为4,因为一个int类型的数据占据4个字节。

随着数组下标的增长,元素的地址,也有规律的递增。

得出结论:数组在内存中是来逆序存放的。

1.5、数组的类型

我们知道一个变量是有类型的,比如:

int a = 0;

char u = ‘a’;

那数组有没有类型呢?答案:有!

int arr[10] = {0};

//int [10]就是arr数组的类型,[]里面的10,也是类型的一部分,不能省略。

【补充:】sizeof()和strlen的用法

#include <stdio.h>
#include <string.h>
int main()
{
	char str[] = "hello bit";
	printf("%d %d", sizeof(str), strlen(str));
	return 0;
}

输出:

在这里插入图片描述

分析:

  • sizeof()是一个操作符,是用来计算变量、类型、数组等所占空间大小的。
  • strlen()是一个库函数,是专门求字符串长度的,只能针对字符串,从参数给定的地址向后一直找’\0’或者说统计’\0’之前出现的字符个数。

首先:str数组中存放:h e l l o _ b i t \0

注意str数组中是存放了10个元素的,一定一定要想到’\0’也是个元素,它也是存放在str数组中的,他也算一个元素。

因此str数组中存放了10个元素,又因为全部都是char类型的,所以str数组大小一共10字节。因为sizeof()输出为10。

而strlen()是统计字符串个数的,并且只统计’\0’之前的字符个数。因为’\0’之前有9个元素,所以strlen()输出为9。

在这里插入图片描述

2、二维数组的创建和初始化

2.2、二维数组的创建

//数组创建
int arr[3][4];      //表示这个二维数组是3行4列的,列就是一行放几个元素,像一个表格一样。二维数组本质上就是多行的数组

char arr[3][5];

double arr[2][4];

2.3、二维数组的初始化

//3行4列,前四个元素放在第一行,中间四个元素放在第二行,最后四个元素放在第三行
int arr[3][4] = {1,2,3,4,2,3,4,5,3,4,5,6};


//前四个元素放在第一行,中间四个元素放在第二行,最后两个元素放在第三行然后剩余的两个位置用0补充
int arr[3][4] = {1,2,3,4,2,3,4,5,3,4};


//将1,2元素放在第一行剩余补0,0,将3,4元素放在第二行剩余补0,0,将4,5元素放在第三行剩余补0,0
int arr[3][4] = {{1,2},{3,4},{4,5}};


//只能省略行,不能省略列
int arr[][4] = {{1,2,3,4},{1,2}};

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

2.3、二维数组的使用

行下标是从0开始,列下标也是从0开始,先确定行,在确定列。

#include <stdio.h>
int main()
{
	int arr[3][4] = { 1,2,3,4,2,3,4,5,3,4,5,6 };
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 4; j++)
		{
			printf("%d ", arr[i][j]);  //打印元素
            scanf("%d", &arr[i][j]);   //输入元素
		}
		printf("\n");
	}
	return 0;
}

输出:

在这里插入图片描述

补充:如何把二维数组看作为一维数组

在这里插入图片描述

我们可以把二维数组的每一行看作是一维数组中的元素,然后把arr[0],arr[1],arr[2]看作是每一行的数组名。

2.4、二维数组在内存中的存储

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

输出:

在这里插入图片描述

可以发现其实二维数组和一维数组在空间中存储的形式是一样的,都是连续的空间。

//以存储空间的角度来看,以下是等价的:
int arr[3][4] = { 1,2,3,4,2,3,4,5,3,4,5,6 };  =  int arr[12] = {1,2,3,4,2,3,4,5,3,4,5,6} 

3、数组越界

数组的下标是有范围限制的。

数组的下标规定是从0开始,如果数组有n个元素,最后一个元素的下标就是n-1。

所以数组的下标如果是小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。

C语言本身是不做数组下标的越界检查,编译器也不一定会报错,但是编译器不报错,并不意味着程序就是正确的。

所以程序员写代码时,最好自己做好越界的检查。

4、数组作为函数参数

往往我们写代码的时候,会将数组作为一个参数传给函数,比如:我要实现一个冒泡排序(这里要讲算法思想)函数。

将一个整型数组排序。

4.1、冒泡排序函数的错误设计


5、冒泡排序的核心思想

冒泡排序的核心思想:两个相邻的元素进行比较。

6、数组名

6.1、一维数组的数组名理解

我们通常说数组名就是数组首元素地址

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

输出:

在这里插入图片描述

可以看到地址确实是一样的。

所以得出结论:数组名确实能表示数组首元素的地址。

但是又两个例外:

  • sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节。
  • &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。

除此以上两种情况,其它遇到的数组名都是数组首元素地址。

6.2、二维数组的数组名理解

二维数组的数组名也表示数组首元素地址。

比如:int arr[3][4]; 数组首元素地址表示的是第一行元素的地址。并不是第一行第一个的元素的地址。

7、计算二维数组的行数和列数

#include <stdio.h>
int main()
{
	int arr[3][4] = { 0 };
    //sizeof(arr)表示整个二维数组的大小,sizeof(arr[0])表示二维数组的第一行大小。
	printf("%d\n", sizeof(arr) / sizeof(arr[0]));
    
    //sizeof(arr[0])表示二维数组的第一行大小,sizeof(arr[0][0])表示二维数组的一个元素大小。
	printf("%d\n", sizeof(arr[0]) / sizeof(arr[0][0]));
	return 0;
}

8、三子棋

  • 新建个项目

  • 创建test.c 测试游戏的逻辑

  • 创建game.c 游戏代码的实现

  • game.h 游戏代码的声明(函数的声明、符号定义)

test.c文件

#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
void menu()
{
	printf("*****************************\n");
	printf("******1. 进入游戏 0. 退出****\n");
	printf("*****************************\n");
}

void game()
{
	char ret = 0;
	char board[ROW][COL] = { 0 };
	//初始化棋盘的函数
	InitBoard(board, ROW, COL);

	//打印棋盘
	DisplayBoard(board, ROW, COL);

	//下棋
	while (1)
	{
		//玩家下棋
		PlayerMove(board,ROW,COL);
		//判断输赢
		ret = IsWin(board,ROW,COL);
		if (ret != 'C')
		{
			break;
		}
		DisplayBoard(board, ROW, COL);
		//电脑下棋
		ComputeMove(board,ROW,COL);
		//判断输赢
		ret = IsWin(board, ROW, COL);
		if (ret != 'C')
		{
			break;
		}
		DisplayBoard(board, ROW, COL);
	}
	if (ret == '*')
	{
		printf("玩家赢\n");
		DisplayBoard(board, ROW, COL);
	}
	else if (ret == '#')
	{
		printf("电脑赢\n");
		DisplayBoard(board, ROW, COL);
	}
	else
	{
		printf("平局\n");
		DisplayBoard(board, ROW, COL);
	}
}

int main()
{
	srand((unsigned int)time(NULL));//设置随机数的生成起点
	int input = 0;
	do
	{
		menu();
		printf("请选择>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

game.c文件

#include "game.h"

//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}

第一个版本
//void DisplayBoard(char board[ROW][COL], int row, int col)
//{
//	int i = 0;
//	for (i = 0; i < row; i++)
//	{
//		打印数据
//		printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
//		打印分割信息
//		if (i < row - 1)
//		{
//			printf("---|---|---\n");
//		}
//	}
//}

//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		//打印数据
		for (j = 0; j < col; j++)
		{
			printf(" %c ", board[i][j]);
			if (j < col - 1)
			{
				printf("|");
			}
		}
		printf("\n");
		//打印分割信息
		if (i < row - 1)
		{
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
				{
					printf("|");
				}
			}
			printf("\n");
		}
	}
}

//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("玩家下棋\n");
		printf("请输入坐标:>");
		scanf("%d %d", &x, &y);
		//判断坐标是否合法
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			//判断坐标是否被占用
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else
			{
				printf("坐标被占用,不能下棋,请选择其它位置\n");
			}
		}
		else
		{
			printf("坐标不合法,请重新输入:>\n");
		}
	}
}

//电脑下棋
//找还未下棋的位置随机下棋
void ComputeMove(char board[ROW][COL], int row, int col)
{
	printf("电脑下棋:>\n");
	int x = 0;
	int y = 0;
	while (1)
	{
		x = rand() % row;   //0~2
		y = rand() % col;   //0~2
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}

//平局的函数,返回1表示填满了,返回0表示未填满
int IsFull(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')
			{
				return 0;
			}
		}
	}
	return 1;
}


//判断输赢
char IsWin(char board[ROW][COL], int row, int col)
{
	//判断在行中赢的
	int i = 0;
	for (i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
		{
			return board[i][1];
		}
	}

	//判断在列中赢的
	int j = 0;
	for (j = 0; j < col; j++)
	{
		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')
		{
			return board[1][j];
		}
	}

	//判断对角线赢的
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
	{
		return board[1][1];
	}
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
	{
		return board[1][1];
	}

	//平局:都没赢就需要平局,平局的判断标准就是:以上赢的标准都不符合且九个格子全部填满。
	if (IsFull(board,ROW,COL))
	{
		return 'Q';
	}
	//游戏继续
	return 'C';
}

game.h文件

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define ROW 3
#define COL 3
#include <stdlib.h>
#include <time.h>

//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);

//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);

//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);

//电脑下棋
void ComputeMove(char board[ROW][COL], int row, int col);

//判断输赢,包含四种情况:
//玩家赢-'*'
//电脑赢-'#'
//平局-'Q'
//继续-'C'
char IsWin(char board[ROW][COL], int row, int col);

9、扫雷

在这里插入图片描述

test.c文件

#define _CRT_SECURE_NO_WARNINGS
#include "game.h"

void menu()
{
	printf("*********************************\n");
	printf("*********   1.玩游戏    *********\n");
	printf("*********   0.退  出    *********\n");
	printf("*********************************\n");
}

void game()
{
	//存放布置好雷的信息
	char mine[ROWS][COLS] = { 0 };
	//存放排查出雷的信息
	char show[ROWS][COLS] = { 0 };
	//mine 初始化数组在没有布置雷的时候都是'0'
	InitBoard(mine, ROWS, COLS,'0');
	//show 初始化数组在没有布置雷的时候都是'*'
	InitBoard(show, ROWS, COLS, '*');

	//设置雷
	SetMine(mine, ROW, COL);
	//打印棋盘,这里只需要打印9*9的棋盘,所以参数需要变化
	//DisplayBoard(mine, ROW, COL);
	DisplayBoard(show, ROW, COL);

	//排查雷
	FindMine(mine, show, ROW, COL);

}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 2:
			printf("退出游戏");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

game.c

#include "game.h"

//初始化棋盘为'0'
void InitBoard(char board[ROWS][COLS], int rows, int cols,char set)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = set;
		}
	}
}

//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("-----------------扫雷游戏--------------------\n");
	for (j = 0; j <= col; j++)
	{
		printf("%d ", j);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);    //添加行号
		for (j = 1; j <= col; j++)
		{
			printf("%c ",board[i][j]);
		}
		printf("\n");
	}
	printf("-----------------扫雷游戏--------------------\n");
}

//设置雷
void SetMine(char board[ROWS][COLS], int row, int col)
{
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
}

int get_mine_count(char board[ROWS][COLS],int x,int y)
{
	return (board[x - 1][y] +
		board[x - 1][y] +
		board[x][y - 1] +
		board[x + 1][y - 1] +
		board[x + 1][y] +
		board[x + 1][y + 1] +
		board[x][y + 1] +
		board[x - 1][y + 1] - 8 * '0'); 


}

//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = 0;        //记录非雷的个数
	while (win < row*col-EASY_COUNT)
	{
		printf("请输入要排查的坐标:>");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] != '*')
			{
				printf("该坐标被排查过了,不能重复排查\n");
			}
			else
			{
				if (mine[x][y] == '1')
				{
					printf("很遗憾,你被炸死了\n");
					DisplayBoard(mine, ROW, COL);
					break;
				}
				else        //如果不是雷,需要统计周围有几个雷
				{
					win++;
					int count = get_mine_count(mine, x, y);
					show[x][y] = count + '0';     //数字1转为字符'1'
					DisplayBoard(show, ROW, COL);
				}
			}
		}
		else
		{
			printf("输入非法坐标,请重新输入\n");
		}
	}
	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你,排雷成功了\n");
		DisplayBoard(mine, ROW, COL);
	}
}

game.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ROW 9
#define COL 9

#define ROWS ROW+2
#define COLS COL+2

#define EASY_COUNT 10

void InitBoard(char board[ROWS][COLS], int rows, int cols,char set);

void DisplayBoard(char board[ROWS][COLS], int row, int col);

void SetMine(char board[ROWS][COLS], int row, int col);

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

'1’和1的运算

‘1’ - ‘0’ = 1

原理:'1’的ASCII值为49

​ '0’的ASCII值为48

‘0’ - ‘0’ = 0

原理同上。

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

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

相关文章

国产替代10BASE-T ST7010QNL 应用局域网的以太网变压器/扼流器

Hqst华强盛导读&#xff1a; 华强盛是电子产品国产替代大军中的一员&#xff0c;随着中国电子产业的快速发展&#xff0c;越来越多的电子产品开始出现了国产替代品。这些国产替代品在性能、品质和价格等方面都有了显著的提升&#xff0c;成为了工厂用户的首选。 国产替代10BAS…

DERT(DEtection TRansformer) ONNX直接推理!!

目录 1.前言 2. ONNX模型 (1) backbone使用的是resnet50 (2) Transformer结构 (3)模型输出 3.代码展示(不收费&#xff01;&#xff01;&#xff01;) 4.结果展示 5.源代码地址 1.前言 DETR DETR的全称是DEtection TRansformer&#xff0c;是Facebook提出的基于…

c++实现【典型的旅行商问题(TSP)】实现配送中心最多可以用2辆车对8个客户进行运输配送

假定配送中心最多可以用2辆车对8个客户进行运输配送。每个车辆载重均 为8吨,车辆每次配送的最大行驶距离为50km,配送中心(编号0)与8个客 户之间及8个客户相互之间的距离d; (i, j= 1, 2, ... 8)、8个客户的货物需 求r;(j= 1, 2... 8)如表1所示。要求寻找一条路径, 使得配送总…

Codeforces Div.2 1798B Three Sevens题解

题目&#xff1a; 传送门 B. Three Sevens time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Lottery "Three Sevens" was held for m days. On day i, ni people with the numbers ai,1…

生态系统NPP及碳源、碳汇模拟——土地利用变化、未来气候变化、空间动态模拟

由于全球变暖、大气中温室气体浓度逐年增加等问题的出现&#xff0c;“双碳”行动特别是碳中和已经在世界范围形成广泛影响。碳中和可以从碳排放&#xff08;碳源&#xff09;和碳固定&#xff08;碳汇&#xff09;这两个侧面来理解。陆地生态系统在全球碳循环过程中有着重要作…

手动计算校正年龄、性别后的标准化死亡率 (SMR)

分析队列人群有无死亡人数超额&#xff0c;通常应用标准人群死亡率来校正&#xff0c;即刻观察到中的实际死亡数&#xff08;D&#xff09;与定一个标准的死亡人数&#xff08;E&#xff09;&#xff0c;D与E之比称为死亡比&#xff08;standarized Mortality ratio&#xff0c…

运筹学-单纯形法

一、单纯形法的求解思路 单纯形法求解线性规划的思路&#xff1a;在高斯消去法的基础上&#xff0c;发展为求解变量数大于方程数&#xff0c;并且使目标函数值优化的方法。从线性方程中找到一个个的单纯形&#xff0c;每个单纯形&#xff08;图形的顶点&#xff09;可以得到一组…

支付宝 小程序 抽奖组件 大转盘

介绍 使用支付宝原有的大转盘营销组件进行改造的&#xff0c;由于背景使用的图片&#xff0c;目前只支持 6 个奖品&#xff0c;一般情况下的大转盘都是这个规格。 转盘停止&#xff1a;之前使用的是计算角度来完成的&#xff0c;没有那种缓慢停止的动画。现在加了一个缓慢停止…

Android实现皮肤主题修改

最近在做App内皮肤切换功能&#xff0c;想了很久方案&#xff0c;写了个皮肤更换工具类&#xff0c;适配N皮肤种类。 话不多说&#xff0c;直接捋一下我的设计思路&#xff0c;因为我的App默认为黑色主题&#xff0c;因此在做其他皮肤主题时&#xff0c;我的图片命名方式是直接…

Fastjson核心解析器DefaultJSONParser,解析算法递归下降算法,实例解析json的步骤

先恭喜热火没有在3-0的情况下被凯尔特人翻盘&#xff0c;抢七获胜成功晋级总决赛~ 最近的项目用到了fastjson&#xff0c;因为源码比较容易搞到&#xff0c;所以就拿来简单的了解了一下&#xff0c;json的主要功能就是解析json和生成json字符串&#xff0c;今天主要是从解析jso…

基于vue3.0简单的页面使用

基于vue3.0简单的页面使用 项目效果图项目文件图package.jsonmain.jsApp.vueviews/Tutorial.vueviews/TS.vueviews/Docs.vueviews/Community.vueviews/Blog.vueviews/About.vueutils/create.jsxutils/defineCom.jsutils/DragIcon.jsutils/someName.tsutils/TS.tsstores/client.…

win11任务栏时间改成12时制

需求&#xff1a;默认24小时值&#xff0c;想改成12小时3:49 方法&#xff1a;设置-时间和语言-语言和区域-管理语言设置-格式 将时间格式改成带tt的

2022年长三角高校数学建模竞赛C题隧道的升级改造与设计解题全过程文档及程序

2022年长三角高校数学建模竞赛 C题 隧道的升级改造与设计 原题再现&#xff1a; 某地现存一旧式双洞隧道&#xff0c;现计划将该隧道在旧貌基础上升级改造。在升级改造前&#xff0c;需进行定标与设计。考虑到该隧道洞壁附着特殊涂料&#xff0c;无人机在洞内通信信号较差&am…

网络面试题:什么是 TCP/IP?

目录标题 什么是 TCP/IP?1) 网络接口层:2) 网络层:3) 传输层:4) 应用层: 2.数据包3.网络接口层4.网络层1) IP:2)地址解析协议 ARP3)子网 5 传输层1&#xff09;UDP&#xff1a;2&#xff09;TCP&#xff1a; 6 应用层运行在TCP协议上的协议&#xff1a;运行在UDP协议上的协议&…

Netty 实现百万级连接服务的难点和优点分析总结

推送服务 还记得一年半前&#xff0c;做的一个项目需要用到 Android 推送服务。和 iOS 不同&#xff0c;Android 生态中没有统一的推送服务。Google 虽然有 Google Cloud Messaging &#xff0c;但是连国外都没统一&#xff0c;更别说国内了&#xff0c;直接被墙。 所以之前在…

Lua学习笔记:C/C++和Lua的相互调用

前言 本篇在讲什么 C/C和Lua的相互调用 本篇适合什么 适合初学Lua的小白 适合需要C/C和lua结合开发的人 本篇需要什么 对Lua语法有简单认知 对C/C语法有简单认知 依赖Lua5.1的环境 依赖VS 2017编辑器 本篇的特色 具有全流程的图文教学 重实践&#xff0c;轻理论&…

云南智慧档案库综合管理系统建设解决方案

一、智慧档案管理系统建设背景 档案作为一种特殊的文献&#xff0c;是人类社会活动的产物&#xff0c;具有特殊的价值&#xff0c;其价值可以概括为现实价值和历史价值。档案是人类留给国家和社会的宝贵财富&#xff0c;它在经济与社会建设中起着重要的作用。档案是反映一个单…

多重共线性的处理方法

回归分析需要考虑多重共线性问题。多重共线性是指自变量之间存在高度相关性&#xff0c;导致回归模型的系数估计不稳定和假设检验不可靠。在实际应用中&#xff0c;许多自变量之间都可能存在一定程度的相关性&#xff0c;如果没有进行控制&#xff0c;就会导致多重共线性问题的…

设计模式之美-实战二:如何对接口鉴权这样一个功能开发做面向对象分析?

面向对象的三个环节&#xff1a;面向对象分析&#xff08;OOA&#xff09;、面向对象设计&#xff08;OOD&#xff09;、面向对象编程&#xff08;OOP&#xff09;。只知道OOA、OOD、OOP只能说有一个宏观了解&#xff0c;我们更重要的还是要知道“如何做”&#xff0c;也就是&a…

【快应用】多语言适配案例

【关键词】 多语言&#xff0c;$t 【问题背景】 快应用平台的能力会覆盖多个国家地区&#xff0c;平台支持多语言的能力后&#xff0c;可以让一个快应同时支持多个语言版本的切换&#xff0c;开发者无需开发多个不同语言的源码项目&#xff0c;避免给项目维护带来困难。使用系…