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

Linux基础-shell的简单实现

个人主页:C++忠实粉丝
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C++忠实粉丝 原创

Linux基础-shell的简单实现

收录于专栏[Linux学习]
本专栏旨在分享学习Linux的一点学习笔记,欢迎大家在评论区交流讨论💌

目录

1, 全局变量和常量定义

2. 环境信息获取

2.1 GetUserName

2.2 GetHostName

2.3 GetPwd

2.4 LastDir

3. 命令行提示符

3.1 MakeCommandLine

3.2  PrintCommandLine

4, 命令输入处理

4.1 GetCommandLine

4.2 ParseCommandLine

5. 命令调试

5.1 debug

6. 命令执行

6.1 ExecuteCommand

子进程执行命令:

等待子进程结束:

处理子进程的返回状态: 

7. 环境变量管理

7.1 AddEnv

 7.2 InitEnv

8. 内建命令处理

8.1 CheckAndExeBuiltCommand

8.1.1 cd命令

8.1.2 export命令

8.1.3 evn命令

8.1.4 echo命令 

8.2 为什么使用内建命令 

9. 主函数

10. 效果展示:


1, 全局变量和常量定义

功能 : 定义常量和全局变量,包括命令行参数、环境变量、当前工作目录、和最近的命令执行状态代码。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>using namespace std;const int basesize = 1024;
const int argvnum = 64;
const int envnum = 64;//全局的命令行参数
char *gragv[argvnum];
int gargc = 0;//全局变量
int lastcode = 0;//我的系统的环境变量
char *genv[envnum];//全局的当前shell工作路径
char pwd[basesize];
char pwdenv[basesize];

basesize: 定义了缓冲区的基础大小,用于存储用户输入的命令和路径。

argvnum: 定义最大命令行参数的数量。

envnum: 定义最大环境变量的数量。

gargv: 存储解析后的命令行参数的数组。

gargc: 表示当前解析出的参数数量。

lastcode: 保存最近执行命令的退出状态。

genv: 存储环境变量的数组。

pwd 和 pwdenv: 存储当前工作目录和环境变量PWD的缓冲区。

2. 环境信息获取

功能 : 获取当前用户、主机名和当前工作目录的信息,返回相应的字符串。

2.1 GetUserName

GetUserName: 获取当前用户的用户名,使用getenv从环境变量中获取,若未获取到,则返回"None"。 

string GetUserName()
{string name = getenv("USER");return name.empty() ? "None" : name;
}

2.2 GetHostName

GetHostName: 获取主机名,类似于获取用户名的方式。 

string GetHostName()
{string hostname = getenv("HOSTNAME");return hostname.empty() ? "None" : hostname;
}

2.3 GetPwd

GetPwd: 获取当前工作目录,使用getcwd函数获取并更新环境变量PWD。如果获取失败,返回"None"。

string GetPwd()
{if (nullptr == getcwd(pwd, sizeof(pwd)))return "None";snprintf(pwdenv, sizeof(pwdenv), "PWD=%s", pwd);putenv(pwdenv);return pwd;
}

补充知识:

snprintf 是一个安全的字符串格式化函数,用于将格式化的数据写入字符串。

pwdenv 是另一个字符数组,用于存储更新后的环境变量字符串。

这里,"PWD=%s" 是格式化字符串,%s 被当前工作目录的值(即 pwd 中的值)替换。最终结果类似于 PWD=/home/user(假设当前工作目录是 /home/user)。

putenv 是一个函数,用于设置环境变量。

通过调用 putenv(pwdenv),将之前构造的环境变量字符串 PWD=/path/to/current/dir 添加到进程的环境中。

注意,使用 putenv 要确保 pwdenv 的内容在后续使用中依然有效,因为 putenv 不会复制传入的字符串。

2.4 LastDir

LastDir: 从当前路径中提取最后一个目录名称,方便在命令行提示符中显示。 

string LastDir()
{string curr = GetPwd();if (curr == "/" || curr == "None")return curr;size_t pos = curr.rfind("/");if (pos == std::string::npos)return curr;return curr.substr(pos + 1);
}

注意 : 这里curr == "/" || curr == "None" 我们都不需要额外处理, 直接返回就行, 因为curr为"/" 表示根目录, 为None时, 我们直接返会空就行 

3. 命令行提示符

功能:生成和打印命令行提示符,包含用户、主机和当前目录信息。 

3.1 MakeCommandLine

MakeCommandLine: 生成当前命令行提示符的字符串格式,包括用户、主机和当前目录。

string MakeCommandLine()
{//[XXX@XXXXX myshell]$ 这里就与普通命令行进行区分char command_line[basesize];snprintf(command_line, basesize, "[%s@%s %s]#", GetUserName().c_str(), GetHostName().c_str(), LastDir().c_str());return command_line;
}

3.2  PrintCommandLine

PrintCommandLine: 打印生成的命令行提示符到标准输出。 

void PrintCommandLine()
{printf("%s", MakeCommandLine().c_str());fflush(stdout);
}

4, 命令输入处理

功能:从标准输入获取用户输入的命令,并解析成命令及其参数。 

4.1 GetCommandLine

GetCommandLine: 从标准输入获取用户的命令行输入,使用fgets读取并处理换行符。

bool GetCommandLine(char command_buffer[], int size)
{//我们认为 : 我们要将用户出入的命令行 -> 当作一个完整的字符串//"ls -a -1 -n"char* result = fgets(command_buffer, size, stdin);if(!result){return false;}command_buffer[strlen(command_buffer) - 1] = 0;if(strlen(command_buffer) == 0) return false;return true;
}

补充知识:

fgets 是一个标准库函数,用于从标准输入(stdin)读取一行字符,最多读取 size - 1 个字符,并将其存储在 command_buffer 中。

fgets 会在读取到换行符 ('\n') 或 EOF(文件结束符)时停止读取,并会在 command_buffer 的末尾自动添加一个空字符 ('\0')。

如果成功读取,result 将指向 command_buffer;如果失败(例如,输入错误或 EOF),result 将为 nullptr。

注意:  strlen(command_buffer) - 1 获取字符串的最后一个字符(换行符)的索引,并将其设为 0,以去掉换行符。

比如:我们输入 ls -a -l -n

fgets 会将缓冲区填充为: command_buffer = "ls -a -l -n\n\0"

经过strlen(command_buffer) - 1处理后 : "ls -a -l -n\0"

4.2 ParseCommandLine

ParseCommandLine: 使用strtok将输入的命令行字符串分割为单独的命令和参数,并存储在gargv数组中。

void ParseCommandLine(char command_buffer[], int len)
{(void)len;memset(gargv, 0, sizeof(gargv));gargc = 0;//"ls -a -l -n"const char *sep = " ";gargv[gargc++] = strtok(command_buffer, sep);//=是刻意写的while((bool)(gargv[gargc++] = strtok(nullptr, sep)));gargc--;
}

补充知识:

 strtok 函数会将 command_buffer 字符串中的第一个分隔符(空格)替换为 \0,并返回指向第一个标记的指针,存储到 gargv 数组中。

strtok(nullptr, sep) 意味着继续解析之前传入的字符串。

注意 (bool) 转换是为了确保表达式的结果为布尔值,这样可以明确表示循环的条件。

5. 命令调试

5.1 debug

功能 : 输出当前命令参数的数量和每个参数的值,以帮助开发和调试。 

void debug()
{printf("argc: %d\n", gargc);for(int i = 0; gargv[i]; i++){printf("argv[%d]: %s\n", i, gargv[i]);}
}

6. 命令执行

6.1 ExecuteCommand

功能:通过fork()和execvpe()创建子进程执行用户命令,并等待其完成。 

bool ExecuteCommand()
{//让子进程进行执行pid_t id = fork();if(id < 0) return false;if(id == 0){//子进程//1. 执行命令execvpe(gargv[0], gargv, genv);//2. 退出exit(1);}int status = 0;pid_t rid = waitpid(id, &status, 0);if(rid > 0){if(WIFEXITED(status)){lastcode = WEXITSTATUS(status);}else{lastcode = 100;}return true;}return false;
}

子进程执行命令:

execvpe(gargv[0], gargv, genv);execvpe 用于执行指定的命令。它会用新的程序替换当前进程(子进程)。参数说明:

gargv[0]:命令的名称(通常是命令的路径)。

gargv:一个字符串数组,包含传递给命令的参数。

genv:一个字符串数组,包含环境变量。

如果 execvpe 成功,当前进程(子进程)将被新的程序替换,之后的代码将不会执行。

如果 execvpe 失败(例如命令未找到),子进程将执行 exit(1),返回状态 1,以指示错误。

等待子进程结束:

int status = 0;:用于存储子进程的退出状态。

waitpid(id, &status, 0):在父进程中调用,等待指定的子进程(由 id 指定)结束。结果存储在 status 变量中。

返回值 rid:如果成功,返回已结束子进程的 PID;如果失败,返回 -1。

处理子进程的返回状态: 

if(rid > 0):确认 waitpid 调用成功,rid 应该是大于 0 的子进程 PID。

WIFEXITED(status):这个宏检查子进程是否正常退出(通过 exit() 或 return 语句)。

WEXITSTATUS(status):如果子进程正常退出,获取其返回状态并将其存储在 lastcode 中。

如果子进程未正常退出(例如由于信号导致的终止),则将 lastcode 设置为 100,这通常用于指示异常情况。

return true;:表示成功执行命令并处理了其退出状态。

7. 环境变量管理

功能:动态分配内存,将新的环境变量添加到genv数组中。

7.1 AddEnv

void AddEnv(const char* item)
{int index = 0;while(genv[index]){index++;}genv[index] = (char*)malloc(strlen(item) + 1);strncpy(genv[index], item, strlen(item) + 1);genv[++index] = nullptr;
}

功能 : 添加环境变量:该函数接受一个字符串 item 作为参数,并将其添加到 genv 环境变量数组中。

逐行分析

int index = 0;:初始化索引为 0,用于遍历 genv 数组。

while(genv[index]):遍历 genv 数组,直到找到第一个空指针,表示可以插入新环境变量的位置。

genv[index] = (char*)malloc(strlen(item) + 1);:

为新的环境变量分配内存。malloc 分配的内存大小为 item 字符串的长度加 1(为字符串结束符 \0 留出空间)。

strncpy(genv[index], item, strlen(item) + 1);:

将 item 的内容复制到 genv[index] 中。使用 strncpy 复制到长度 strlen(item) + 1,确保包含字符串结束符。

genv[++index] = nullptr;:

在数组中下一个位置设置为 nullptr,标志着环境变量的结束。

 7.2 InitEnv

void InitEnv()
{extern char **environ;int index = 0;while(environ[index]){genv[index] = (char*)malloc(strlen(environ[index] + 1));strncpy(genv[index], environ[index], strlen(environ[index] + 1));index++;}genv[index] = nullptr;
}

功能 : 初始化环境变量:该函数从系统环境变量中读取所有环境变量并将其存储在 genv 数组中。

逐行分析

extern char **environ;:声明外部变量 environ,这是一个指向环境变量字符串数组的指针

int index = 0;:初始化索引为 0,用于遍历 environ。

while(environ[index]):遍历 environ 数组,直到找到第一个空指针,表示所有环境变量都已读取。

genv[index] = (char*)malloc(strlen(environ[index]) + 1);:

为每个环境变量分配内存。这里 strlen(environ[index]) 计算字符串的长度,并加 1 来包含 \0 结束符。

strncpy(genv[index], environ[index], strlen(environ[index] + 1));:

将 environ[index] 的内容复制到 genv[index] 中。这里同样存在一个错误,应该是 strncpy(genv[index], environ[index], strlen(environ[index]) + 1);。

index++;:增加索引,以便处理下一个环境变量。

genv[index] = nullptr;:在数组最后设置 nullptr,表示环境变量的结束

8. 内建命令处理

8.1 CheckAndExeBuiltCommand

bool CheckAndExeBuiltCommand()
{if(strcmp(gargv[0], "cd") == 0){//内建命令if(gargc == 2){chdir(gargv[1]);lastcode = 0;}else{lastcode = 1;}return true;}else if(strcmp(gargv[0], "export") == 0){//export也是内建命令if(gargc == 2){AddEnv(gargv[1]);lastcode = 0;}else{lastcode = 2;}return true;}else if(strcmp(gargv[0], "env") == 0){for(int i = 0; genv[i]; i++){printf("%d\n", genv[i]);}lastcode = 0;return true;}else if(strcmp(gargv[0], "echo") == 0){if(gargc == 2){//echo $?//echo $PATH//echo helloif(gargv[1][0] == '$'){if(gargv[1][1] == '?'){printf("%d\n", lastcode);lastcode = 0;}else{printf("%s\n", gargv[1]);lastcode = 0;}}else{lastcode = 3;}return true;}return false;}
}

8.1.1 cd命令

功能:用于更改当前工作目录。

逻辑:

检查参数个数 gargc 是否等于 2(即命令和目录)。

如果参数正确,调用 chdir 函数改变目录,并将 lastcode 设置为 0,表示成功。

如果参数不正确,将 lastcode 设置为 1,表示错误。

chdir() : 将调用进程的当前工作目录更改为path中指定的目录 

8.1.2 export命令

功能:用于设置或导出环境变量。

逻辑:

同样检查参数个数 gargc 是否为 2。

如果正确,调用 AddEnv 函数添加环境变量,并将 lastcode 设置为 0。

如果参数不正确,设置 lastcode 为 2。

8.1.3 evn命令

功能:列出所有环境变量。

逻辑:

遍历 genv 数组,打印每个环境变量。

将 lastcode 设置为 0。

8.1.4 echo命令 

功能:输出字符串或变量。

逻辑:

检查参数个数是否为 2。

如果是,检查 gargv[1] 的第一个字符是否为 $:

如果是 $?,输出 lastcode 的值。

如果是其他以 $ 开头的字符串,直接输出这个字符串(假设它是环境变量)。

如果没有 $,则将 lastcode 设置为 3。

如果参数个数不正确,返回 false。

8.2 为什么使用内建命令 

快速响应:内建命令通常直接在 shell 进程内执行,无需创建新的进程,减少了上下文切换的开销。这使得内建命令的执行速度更快。

基本功能:内建命令提供了一些与 shell 紧密相关的基本功能,如改变目录(cd)、设置环境变量(export)、获取当前环境(env)等,这些操作通常与 shell 的状态直接相关。

环境影响:某些内建命令(如 cd)会影响 shell 的状态(例如当前工作目录),如果用外部程序实现,改变的状态不会反映到 shell 中。

简化用户操作:用户可以直接使用内建命令而无需担心路径问题。例如,cd 命令只需要提供目标路径,而不必寻找相应的外部可执行文件。

状态保持:内建命令如 echo 和 export 能够直接访问 shell 的状态和环境变量,而不需要通过外部程序来管理,这样可以更好地处理如 $?(上一个命令的退出状态)这样的特殊情况。

9. 主函数

 功能:主程序循环,负责显示提示符、获取用户命令、解析命令、检查内建命令,并执行命令。

int main()
{InitEnv();char command_buffer[basesize];while(true){//1. 命令行提示符PrintCommandLine();//command_buffer -> output//2. 获取用户命令if(!GetCommandLine(command_buffer, basesize)){continue;}//3. 解析命令ParseCommandLine(command_buffer, strlen(command_buffer));if(CheckAndExeBuiltCommand()){continue;}4. 执行命令ExecuteCommand();}return 0;
}

10. 效果展示:

相关文章:

Linux基础-shell的简单实现

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 Linux基础-shell的简单实现 收录于专栏[Linux学习] 本专栏旨在分享学习Linux的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 1, 全局变…...

Tomcat日志文件详解及catalina.out日志清理方法

目录 前言1. Tomcat日志文件详解1.1 catalina.out1.2 localhost_access_log1.3 catalina.<date>.log1.4 host-manager.<date>.log 和 manager.<date>.log1.5 localhost.<date>.log 2. catalina.out文件管理与清理方法2.1 为什么不能直接删除catalina.o…...

react 中的hooks中的useState

(1). State Hook让函数组件也可以有state状态, 并进行状态数据的读写操作 (2). 语法: const [xxx, setXxx] React.useState(initValue) (3). useState()说明:参数: 第一次初始化指定的值在内部作缓存返回值: 包含2个元素的数组, 第1个为内部当前状态值, 第2个为更新状态值的…...

STM32学习笔记---DMA

目录 一、什么是DMA 1、DMA是什么 2、DMA的工作流程 3、DMA控制器与外设控制器 二、如何配置DMA 1、DMA框图 2、功能说明 2.1 通道选择 2.2 仲裁器 2.3 源、目标和传输模式 2.4 指针递增 2.5 循环模式 2.6 DMA流控制器和外设流控制器 3、程序设计 三、具体使用DMA…...

Cesium 实战 - 自定义纹理材质 - 立体墙(旋转材质)

Cesium 实战 - 自定义纹理材质 - 立体墙(旋转材质) 核心代码完整代码在线示例Cesium 给实体对象(Entity)提供了很多实用的样式,基本满足普通项目需求; 但是作为 WebGL 引擎,肯定不够丰富,尤其是动态效果样式。 对于实体对象(Entity),可以通过自定义材质,实现各种…...

进程间关系与守护进程

一、进程组 1.1、什么是进程组 提到进程的概念&#xff0c; 其实每一个进程除了有一个进程 ID(PID)之外 还属于一 个进程组。进程组是一个或者多个进程的集合&#xff0c; 一个进程组可以包含多个进程。 每一 个进程组也有一个唯一的进程组 ID(PGID)&#xff0c; 并且这个 PG…...

金山翻译接口逆向

网址&#xff08;加密后&#xff09;&#xff1a;aHR0cHM6Ly93d3cuaWNpYmEuY29tL3RyYW5zbGF0ZQ 文章目录 抓包sign值结果加密 逆向sign值第一步第二步1.2.3. 解密content第一步1.2.3. 抓包 F12 -> 翻译框输入spider -> 点击Fetch/XHR -> 找到接口 index.php? 开头的…...

unified-runtime编译与验证

unified-runtime编译与验证 一.创建容器二.编译unified-runtime三.生成一个cuda ptx kernel四.API测试 unified-runtime编译与验证 一.创建容器 docker run --gpus all --shm-size32g -ti \-e NVIDIA_VISIBLE_DEVICESall --privileged --nethost \--rm -it \-v $PWD:/home \-…...

【Python】最详细--基础语法

Python是一种强大且易于学习的编程语言&#xff0c;广泛用于各种应用程序的开发&#xff0c;如web开发、数据科学、人工智能等。以下是一些Python的基础知识&#xff1a; 1. Python的注释 Python的注释用于在代码中添加说明&#xff0c;以提高代码的可读性。注释在代码执行时…...

二叉树基础:什么样的二叉树适合用数组来存储?

二叉树基础:什么样的二叉树适合用数组来存储? 在计算机科学中,二叉树是一种非常重要的数据结构。它具有许多应用,如搜索、排序、表达式解析等。在存储二叉树时,我们可以使用多种方法,其中一种是使用数组。但是,并不是所有的二叉树都适合用数组来存储。那么,什么样的二…...

iTOP-RK3568开发板独立NPU通过算法加特应用到以下的场景

iTOP-3568开发板采用瑞芯微RK3568处理器&#xff0c;内部集成了四核64位Cortex-A55处理器。主频高达2.0Ghz&#xff0c;RK809动态调频。集成了双核心架构GPU&#xff0c;ARM G52 2EE、支持OpenGLES1.1/2.0/3.2、OpenCL2.0、Vulkan1.1、内嵌高性能2D加速硬件。 内置独立NPU,算力…...

Java基于SpringBoot微信小程序的跳蚤市场系统设计与实现(lw+数据库+讲解等)

项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而不是配置文件。Spring Boot 通过自动化配置和约…...

【分布式微服务云原生】《Redis 的高效之道:线程模型、IO 模型与 Reactor 模型全解析》

标题&#xff1a;《分布式缓存Redis 的高效之道&#xff1a;线程模型、IO 模型与 Reactor 模型全解析》 摘要&#xff1a;本文深入探讨分布式缓存 Redis 的 I线程模型、IO 模型以及 Reactor 模型。详细介绍了 Redis 在不同版本中的线程变化、IO 模型的特点和工作流程&#xff…...

科研类型PPT的制作技巧

目录 科研类型PPT的制作技巧 荣誉: 首页:ppt开头结尾 小标题 重点标记:加粗红色下划线 使用三线表 图片,文本排版 一、明确目的与受众分析 二、基础设计原则 三、内容组织与呈现 四、绘图与模型制作 五、其他注意事项 科研类型PPT的制作技巧 荣誉: 首页:ppt开…...

rom定制系列------小米6x_MIUI14_安卓13刷机包修改写入以及功能定制 界面预览

在接待一些定制化系统中。有很多工作室或者一些特殊行业的友友需要在已有固件基础上简略修改其中的功能。方便使用。例如usb调试默认开启。usb安装设置以及usb安装与内置删减一些app的定制服务。今天给友友预览其中小米6X此款机型定制相关的一些界面与功能演示。 定制机型以及…...

线性代数基础02

目录 1.向量 1.1向量的定义 1.2向量的运算 1.2.1向量加法 1.2.2向量数乘 1.2.3向量点积 1.3矩阵的特征值和特征向量 1.4向量的模 1.4.1向量的模的定义 1.4.2向量的模的几何解释 1.4.3向量的模的性质 1.5向量的内积 1.5.1向量的内积的定义 1.5.2向量的内积的几何解…...

「4.4」祖孙询问

「4.4」祖孙询问 题目描述 已知一棵 n 个节点的有根树。有 m 个询问&#xff0c;每个询问给出了一对节点的编号 x 和 y&#xff0c;询问 x 与 y 的祖孙关系。 输入格式 输入第一行包括一个整数 n 表示节点个数&#xff1b; 接下来 n 行每行一对整数对 a 和 b 表示 a 和 b 之…...

Datawhale 组队学习 文生图 Prompt攻防 task03随笔

这期我们从不同角度切入探讨赛题的进阶思路 思路1&#xff1a;对比不同大模型 首先我们可以选择尝试不同的大模型&#xff0c;使用更复杂的大模型可以提高文本改写的质量和效果。随着模型大小的增加&#xff0c;其表示能力也随之增强&#xff0c;能够捕捉更细微的语言特征和语…...

游戏投屏软件有哪些?分享这10款比较好用的!

说到投屏&#xff0c;这个事情我还是比较有发言权的&#xff01; 一般手机下载个APP&#xff0c;然后就可以通过WiFi、蓝牙或者USB进行连接投屏啦&#xff0c;下面是国内比较主流的一些游戏投屏软件&#xff0c;可以根据他们的优缺点进行选择哦&#xff01; 01.幕连 国内首款…...

[Unity Demo]从零开始制作空洞骑士Hollow Knight第十六集(下篇):制作小BOSS龙牙哥

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、制作小BOSS龙牙哥 1.导入素材制作动画2.制作两种攻击行为3.制作从惊醒到转身到走路or跑步行为总结 前言 hello大家好久没见&#xff0c;之所以隔了一天时间…...

顺序表算法题【不一样的解法!】

本章概述 算法题1算法题2算法题3彩蛋时刻&#xff01;&#xff01;&#xff01; 算法题1 力扣&#xff1a;移除元素 我们先来看这个题目的要求描述&#xff1a; 把与val相同数值的元素移除掉&#xff0c;忽略元素的相对位置变化&#xff0c;然后返回剩下与val值不同的元素个数…...

VuePress的基本常识

今天大概了解了一下Vuepress&#xff0c;感觉很棒&#xff0c;看着极其简单&#xff0c;自己也想做一个&#xff0c;后续我大概率也会做一个用Vuepress为基础做的博客网站&#xff0c;很酷~ 哈哈哈&#xff0c;下面是我今天学习Vuepress的一些内容&#xff0c;简单分享下&#…...

深入解析Vue2与Vue3的区别与Vue3的提升

Vue.js作为一款流行的前端框架&#xff0c;自发布以来&#xff0c;凭借其简洁的语法、灵活的组件化和高效的性能&#xff0c;赢得了众多开发者的喜爱。随着Vue3的发布&#xff0c;许多新特性和新功能也应运而生。那么&#xff0c;Vue2与Vue3究竟有哪些区别呢&#xff1f;Vue3又…...

认识python数据分析

Python作为一种高效、灵活且易于学习的编程语言&#xff0c;在数据分析领域展现出了强大的应用潜力。 从数据清洗、预处理到复杂的统计分析、可视化及机器学习模型的构建&#xff0c;Python提供了丰富的库和框架&#xff0c;极大地简化了数据分析的流程&#xff0c;提高了工作…...

以太网交换安全:MAC地址漂移与检测(实验:二层环路+网络攻击)

一、什么是MAC地址漂移&#xff1f; MAC地址漂移是指网络中设备的MAC地址在运行过程中发生变化的现象。 MAC地址是用于唯一标识网络中的设备。 MAC地址漂移是指交换机上一个VLAN内有两个端口学习到同一个MAC地址&#xff0c;后学习到的MAC地址表项覆盖原MAC地址表项的现象。…...

NeRF三维重建—神经辐射场Neural Radiance Field(二)体渲染相关

NeRF三维重建—神经辐射场Neural Radiance Field&#xff08;二&#xff09;体渲染相关 粒子采集部分 粒子采集的部分我们可以理解为&#xff0c;在已知粒子的情况下&#xff0c;对图片进行渲染的一个正向的过程。 空间坐标(x,y,z&#xff09;发射的光线通过相机模型成为图片上…...

软件测试工程师:如何写出好的测试用例?

软件测试用例(Test Case)是软件测试过程中的一种详细文档或描述&#xff0c;用于描述在特定条件下&#xff0c;对软件系统或组件进行测试的步骤、输入数据、预期输出和预期行为。编写高质量的测试用例是确保软件质量的关键步骤之一。以下是一些编写优秀测试用例的建议&#xff…...

「图::连通」详解并查集并实现对应的功能 / 手撕数据结构(C++)

目录 概述 成员变量 创建销毁 根节点访问 路径压缩 启发式合并 复杂度 Code 概述 并查集&#xff0c;故名思议&#xff0c;能合并、能查询的集合,在图的连通性问题和许多算法优化上着广泛的使用。 这是一个什么数据结构呢&#xff1f; 一般来讲&#xff0c;并查集是…...

基于PSO粒子群优化的CNN-GRU-SAM网络时间序列回归预测算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) PSO优化过程&#xff1a; PSO优化前后&#xff0c;模型训练对比&#xff1a; 数据预测对比&#xff1a; 误差回归对比&a…...

PyTorch 的 DataLoader 类介绍

DataLoader 类 功能与作用 PyTorch 是一个流行的开源机器学习库&#xff0c;它提供了一个名为 DataLoader 的类&#xff0c;用于加载数据集并将其封装成一个可迭代的对象。DataLoader 可以自动地将数据集划分为多个批次&#xff0c;并在训练过程中迭代地返回这些批次。是用于加…...