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

自制简易 Shell:像搭建积木小屋一样打造命令交互小天地

目录

准备工作:搭建小屋的材料

打造小屋的 “身份牌” 

接收指令:小屋的 “对讲机” 

 拆解指令:把大任务拆成小积木

执行指令:小屋的 “行动队” 

 特殊指令:小屋的 “特色功能”

小屋的日常运转 

完整代码


啥是 Shell 呢?打个比方,它就像是你和计算机底层系统之间的 “翻译官” 和 “大管家”。你给它下指令,它就能帮你调动计算机的各种资源去完成任务,就像你跟管家说 “我要整理文件”,管家就会去安排人手(计算机资源)帮你搞定

准备工作:搭建小屋的材料

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>#define NUM 1024
#define SIZE 64
#define SEP " "char cwd[1024];
char enval[1024];
int lastcode = 0;

看代码开头,引入了一堆头文件,这就好比搭建积木小屋前得准备好各种工具。<stdio.h>是负责输入输出的,就像小屋的 “门窗”,能让信息进进出出;<stdlib.h>提供了一些通用的工具函数,像是搭建小屋时的 “万能螺丝刀”;<string.h>专门处理字符串,就像给积木贴上好看标签的工具;<unistd.h><sys/types.h><sys/wait.h>则是和系统交互的关键,好比是和外界沟通获取搭建材料的渠道。

后面定义的几个宏和变量也很重要。NUMSIZE就像是规定了积木的大小和数量上限,给我们的小屋搭建划定了一个范围。cwdenvallastcode则像是小屋里的 “储物箱”,用来存放当前工作目录、环境变量相关信息以及上一个命令的退出码。

打造小屋的 “身份牌” 

const char *getUsername()
{const char *name = getenv("USER");if (name)return name;elsereturn "none";
}const char *getHostname()
{const char *hostname = getenv("HOSTNAME");if (hostname)return hostname;elsereturn "none";
}const char *getCwd()
{const char *cwd = getenv("PWD");if (cwd)return cwd;elsereturn "none";
}

这几个函数就像是在给咱们的小屋制作 “身份牌”。getUsername函数去系统环境变量里找 “USER”,就像在小屋里翻翻找找,看看住在这里的人叫啥名字。要是找到了,就把名字亮出来,找不到就说 “none”。getHostnamegetCwd函数也是类似的道理,一个是找计算机的主机名,一个是找当前工作目录,就好比确定小屋在哪个小区(主机),具体门牌号是啥(工作目录)。 

接收指令:小屋的 “对讲机” 

int getUserCommand(char *command, int num)
{printf("[%s@%s %s]# ", getUsername(), getHostname(), getCwd());char *r = fgets(command, num, stdin);if (r == NULL)return -1;command[strlen(command) - 1] = '\0';return strlen(command);
}

getUserCommand函数就像是小屋里的 “对讲机”。它先打印出一个提示符,格式是[用户名@主机名 当前工作目录]# ,就像管家在小屋门口喊 “我准备好接收指令啦!” 然后通过fgets从标准输入(也就是你在键盘上敲的内容)读取用户输入的命令,存到command这个 “小纸条” 里。要是没读取成功,就返回 -1 ,读取成功了就把命令末尾的换行符去掉,整理得干干净净,再返回命令的长度。 

 拆解指令:把大任务拆成小积木

void commandSplit(char *in, char *out[])
{int argc = 0;out[argc++] = strtok(in, SEP);while (out[argc++] = strtok(NULL, SEP));
}

 commandSplit函数干的活,就像是把一大块复杂的积木拆解成一个个小积木。它用strtok函数把用户输入的命令字符串(in),按照SEP(这里是空格)这个分隔符,拆分成一个个单词,然后把这些单词分别放到out这个 “小格子” 数组里。这样,原本一长串的命令,就被整理得井井有条,方便后续处理。

执行指令:小屋的 “行动队” 

int execute(char *argv[])
{pid_t id = fork();if (id < 0){return -1;}else if (id == 0){execvp(argv[0], argv);exit(1);}else{int status = 0;pid_t rid = waitpid(id, &status, 0);if (rid > 0){lastcode = WEXITSTATUS(status);}}return 0;
}

execute函数就是小屋里的 “行动队”。它先用fork函数创建一个子进程,就像是派出一个分身去干活。要是创建失败(id < 0 ),就返回 -1 表示任务失败。要是分身(子进程,id == 0 )创建成功,就通过execvp函数去执行用户输入的命令,要是执行出问题了,就用exit(1)结束子进程。而原来的进程(父进程)则通过waitpid函数等着分身回来报告情况,要是等回来了(rid > 0 ),就把分身的退出码存到lastcode里,就像记录下这次行动的结果。 

 特殊指令:小屋的 “特色功能”

void cd(const char *path)
{chdir(path);char tmp[1024];getcwd(tmp, sizeof(tmp));sprintf(cwd, "PWD=%s", tmp);putenv(cwd);
}int doBuildin(char *argv[])
{if (strcmp(argv[0], "cd") == 0){char *path = NULL;if (argv[1] == NULL)path = ".";elsepath = argv[1];cd(path);return 1;}else if (strcmp(argv[0], "export") == 0){if (argv[1] == NULL)return 1;strcpy(enval, argv[1]);putenv(enval); return 1;}else if (strcmp(argv[0], "echo") == 0){char *val = argv[1] + 1;if (strcmp(val, "?") == 0){printf("%d\n", lastcode);lastcode = 0;}else{printf("%s\n", getenv(val));}return 1;}else if (0){}return 0;
}

这里定义的cddoBuildin函数,给小屋增添了一些 “特色功能”。cd函数就像小屋的 “搬家工具”,它能改变当前工作目录,然后更新环境变量里的PWD,就像你给小屋换了个地方,还得把新地址告诉大家。

doBuildin函数则像是一个 “功能调度员”,它判断用户输入的是不是像cdexportecho这种内置命令。要是cd命令,就调用cd函数去切换目录;要是export命令,就把相关环境变量设置好;要是echo命令,根据不同情况,要么打印上一个命令的退出码,要么打印指定环境变量的值。这些内置命令让小屋能实现一些特殊的、常用的功能,就像给小屋装上了一些好用的小机关。

小屋的日常运转 

int main()
{while (1){char usercommand[NUM];char *argv[SIZE];// 1. 打印提示符&&获取用户命令字符串获取成功int n = getUserCommand(usercommand, sizeof(usercommand));if (n <= 0)continue;// 2. 分割字符串// "ls -a -l" -> "ls" "-a" "-l"commandSplit(usercommand, argv);// 3. check build-in commandn = doBuildin(argv);if (n)continue;// 4. 执行对应的命令execute(argv);}
}

 main函数就是小屋日常运转的 “总导演”。它在一个无限循环里,不断地做这几件事:先通过getUserCommand获取用户输入的命令,要是没获取到有效命令就跳过这次循环;然后用commandSplit把命令拆分开;接着看看是不是内置命令,是的话就用doBuildin处理,处理完了就跳过这次循环;最后要是不是内置命令,就用execute去执行这个命令。

完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>#define NUM 1024
#define SIZE 64
#define SEP " "char cwd[1024];
char enval[1024];
int lastcode = 0;const char *getUsername()
{const char *name = getenv("USER");if (name)return name;elsereturn "none";
}const char *getHostname()
{const char *hostname = getenv("HOSTNAME");if (hostname)return hostname;elsereturn "none";
}const char *getCwd()
{const char *cwd = getenv("PWD");if (cwd)return cwd;elsereturn "none";
}int getUserCommand(char *command, int num)
{printf("[%s@%s %s]# ", getUsername(), getHostname(), getCwd());char *r = fgets(command, num, stdin);if (r == NULL)return -1;command[strlen(command) - 1] = '\0';return strlen(command);
}void commandSplit(char *in, char *out[])
{int argc = 0;out[argc++] = strtok(in, SEP);while (out[argc++] = strtok(NULL, SEP));
}int execute(char *argv[])
{pid_t id = fork();if (id < 0){return -1;}else if (id == 0){execvp(argv[0], argv);exit(1);}else{int status = 0;pid_t rid = waitpid(id, &status, 0);if (rid > 0){lastcode = WEXITSTATUS(status);}}return 0;
}void cd(const char *path)
{chdir(path);char tmp[1024];getcwd(tmp, sizeof(tmp));sprintf(cwd, "PWD=%s", tmp);putenv(cwd);
}int doBuildin(char *argv[])
{if (strcmp(argv[0], "cd") == 0){char *path = NULL;if (argv[1] == NULL)path = ".";elsepath = argv[1];cd(path);return 1;}else if (strcmp(argv[0], "export") == 0){if (argv[1] == NULL)return 1;strcpy(enval, argv[1]);putenv(enval); // ???return 1;}else if (strcmp(argv[0], "echo") == 0){char *val = argv[1] + 1;if (strcmp(val, "?") == 0){printf("%d\n", lastcode);lastcode = 0;}else{printf("%s\n", getenv(val));}return 1;}else if (0){}return 0;
}int main()
{while (1){char usercommand[NUM];char *argv[SIZE];// 1. 打印提示符&&获取用户命令字符串获取成功int n = getUserCommand(usercommand, sizeof(usercommand));if (n <= 0)continue;// 2. 分割字符串// "ls -a -l" -> "ls" "-a" "-l"commandSplit(usercommand, argv);// 3. check build-in commandn = doBuildin(argv);if (n)continue;// 4. 执行对应的命令execute(argv);}
}

通过这段代码,咱们就像是亲手搭建了一个简易的 Shell “积木小屋”,虽然它还很简单,但却有着强大的潜力。希望大家都能从这个小小的 Shell 代码里,感受到编程的乐趣和神奇。

相关文章:

自制简易 Shell:像搭建积木小屋一样打造命令交互小天地

目录 准备工作&#xff1a;搭建小屋的材料 打造小屋的 “身份牌” 接收指令&#xff1a;小屋的 “对讲机” 拆解指令&#xff1a;把大任务拆成小积木 执行指令&#xff1a;小屋的 “行动队” 特殊指令&#xff1a;小屋的 “特色功能” 小屋的日常运转 完整代码 啥是 …...

WEB安全--内网渗透--利用Net-NTLMv2 Hash

一、前言 在前两篇文章中分析了NTLM协议中Net-NTLMv2 Hash的生成、如何捕获Net-NTLMv2 Hash&#xff0c;现在就来探讨一下在内网环境中&#xff0c;如何利用Net-NTLMv2 Hash进行渗透。 二、Net-NTLM Hash的破解 工具&#xff1a;hashcat 原理&#xff1a;利用其内部的字典对…...

MySQL 数据库操作指南:从数据库创建到数据操作

关键词&#xff1a;MySQL&#xff1b;数据库操作&#xff1b;DDL&#xff1b;DML 一、引言 MySQL 作为广泛应用的关系型数据库管理系统&#xff0c;对于开发人员和数据库管理员而言&#xff0c;熟练掌握其操作至关重要。本文章通过一系列 SQL 示例&#xff0c;详细阐述 MySQL…...

从传递函数到PID控制器

在过程控制中&#xff0c;按偏差的比例&#xff08;P&#xff0c;Proportional&#xff09;、积分&#xff08;I&#xff0c;Integral&#xff09;和微分&#xff08;D&#xff0c;Differential&#xff09;进行控制的PID控制器&#xff08;亦称PID调节器&#xff09;是应用最为…...

抓wifi无线空口包之Ubuntu抓包(二)

一、设置网卡信道和频段&#xff0c;并抓包 1、使用iwconfig查看自己机器的无线网卡名称 wangwang-ThinkCentre-M930t-N000:~$ iwconfig lo no wireless extensions. eno1 no wireless extensions. enxc8a3624ab329 no wireless extensions. wlx90de80d1b5b1 IE…...

使用protobuf编译提示无法打开包括文件: ‘absl/log/absl_log.h’: No such file or directory

问题原因 Protobuf 依赖 Abseil&#xff1a; Protobuf 3.20 版本开始依赖 Abseil&#xff0c;但你的系统未正确安装或配置 Abseil。 头文件路径未包含&#xff1a; 编译器找不到 absl/log/absl_log.h&#xff0c;可能是因为 Abseil 未正确安装或未在项目中设置包含路径。 …...

深入浅出Java 锁 | 源码剖析 | 万字解析

目录 硬件内存结构&Java内存模型 硬件内存结构 Java内存模型&#xff08;JMM&#xff09; JMM中三大特性&#xff1a;原子性、有序性、可见性 Java中有哪些锁&#xff1f; Java中锁可以分成悲观锁和乐观锁的实现。 乐观锁和悲观锁的区别&#xff0c;乐观锁一定好嘛&…...

java流程控制12:流程控制练习

流程控制练习 打印三角型 package com.zheng.struct;public class TestDemo {public static void main(String[] args) {//打印三角形 5行for(int i1;i<5;i){for(int j5;j>i;j--){System.out.print(" ");}for(int j1;j<i;j){System.out.print("*&quo…...

JAVA:ByteBuddy 动态字节码操作库的技术指南

1、简述 ByteBuddy 是一个功能强大的 Java 字节码操作库&#xff0c;可以帮助开发者在运行时动态生成和修改类&#xff0c;而无需直接接触复杂的 ASM API。它被广泛应用于框架开发、AOP&#xff08;面向切面编程&#xff09;、代理类生成、性能监控等领域。 2、ByteBuddy 的优…...

C语言学习记录(13)自定义类型:结构体

一、结构体变量的声明、创建和初始化 1.结构体变量的声明 结构体变量我们学操作符的时候就顺带讲了一点了&#xff0c;因为当时讲了结构体成员变量访问操作符.。 结构体变量不像int、float这种内置类型的&#xff0c;一旦创建&#xff0c;系统就知道这是干啥的&#xff0c;结…...

rtthread 软件SPI驱动, 支持mode0~3,MSB,LSB

rtthread的软件模拟SPI用的上层PIN驱动写&#xff0c;由于经过层层封装&#xff0c;时钟频率并不会太高&#xff0c;200MHz的MCU跑不到1MHz的时钟频率。所以最好是在底层就模拟好&#xff0c;给上层用。 头文件 struct io_poSOFT {gpio_type *port;uint16_t pin; }; typedef …...

C++自学笔记——动态创建对象

动态创建对象 1. 什么是动态创建对象&#xff1f; 在学习之前的知识点时&#xff0c;我们知道有静态存储期和自动存储期。 静态存储期的对象在程序的整个生命周期内都存在&#xff0c;全局变量和static修饰的局部变量都属于这一类。自动存储期的对象&#xff0c;这些对象在函…...

35.[前端开发-JavaScript基础]Day12-for循环中变量-华为商城-商品列表-轮播图

for循环中监听函数中打印变量 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"wi…...

详细描述以太坊的gas、gaslimit、gasPrice

目录 一、Gas 是什么? ✅ 简要定义: 🧠 举例理解: 二、Gas Limit 是什么? ✅ 简要定义: 分两种: 举例说明: 三、Gas Price 是什么? ✅ 简要定义: 为什么它重要? 示例: 四、 EIP-1559 后的新机制(伦敦升级) 三个要素: 五、额外技巧(开发实用) 本文…...

【Java】Maven

一、概念 是一个项目管理和构建工具&#xff0c;它基于项目对象模型&#xff08;POM&#xff09;的概念&#xff0c;通过一小段描述信息来管理项目的构建。 二、Maven坐标 <groupId>com.itheima</groupId><artifactId>maven-project01</artifactId>&…...

PageCache

目录 一、PageCache的具体过程 二、具体实现代码 一、PageCache的具体过程 页缓存主要解决的是内存外碎片问题&#xff0c;并且直接和系统调用打交道。 申请过程如下&#xff1a; 当中心缓存中没有内存时,会去页缓存申请一个span结构,要经过下面几步: &#xff08;1&#xf…...

Vue3实战五、面包屑,收缩菜单,高亮暗黑主题切换,全屏功能实现

目录 面包屑&#xff0c;收缩菜单&#xff0c;黑夜白夜样式,全屏功能实现收缩菜单按钮结合pinia功能实现第一步、定义布局配置的数据类型第二步、创建布局状态管理文件第三步、使用布局配置状态第四步、进行展开/收起左侧菜单逻辑第五步、动态切换左侧菜单宽度样式第六步、动态…...

Linux内核设计——(二)进程调度

目录 一、进程调度简介 二、多任务 三、调度器 3.1 I/O消耗型和处理器消耗型进程 3.2 进程优先级 3.3 CFS算法 3.4 实时调度策略 3.5 SCHED_FIFO 3.6 SCHED_RR 3.7 调度器入口 四、上下文切换 4.1 睡眠和唤醒 4.2 need_resched标志 4.3 用户抢占 4.4 内核抢占 一…...

【C++初阶】--- string类模拟实现

1.基础函数 1.1成员函数 成员函数主要是_str、_size、_capacity这三个。npos是size_t 的最大值,用于当作后续成员函数的参数的缺省值。 class string { private:char* _str nullptr;//指向字符串的指针size_t _size 0;//字符串长度size_t _capacity 0;//空间大小static c…...

Pythia 使用说明

Pythia 是一个由非营利研究组织 EleutherAI 开发的开源语言模型套件&#xff0c;专注于透明性和可复现性。它是为了推动自然语言处理&#xff08;NLP&#xff09;领域的开放研究而设计&#xff0c;尤其在模型训练过程和性能分析方面提供了详尽的文档和数据。 Pythia 的核心特点…...

python:获取某路径下所有图片的名称

可以使用 Python 的 os 模块或者 pathlib 模块来获取指定路径下所有图片的名称。以下是使用这两种方法实现的代码示例&#xff1a; 使用 os 模块 import osdef get_image_names_os(path):image_extensions (.jpg, .jpeg, .png, .gif, .bmp)image_names []for root, dirs, f…...

一个开源的 VS Code 大模型聊天插件:Light-at

这篇文章是一个开发杂谈。对于有经验的开发者来说&#xff0c;可能这个项目并不算特别复杂或者高技术&#xff0c;只是对我个人来说算一个里程碑&#xff0c;因此写篇杂谈文章记录一下。也许也能给起步者一些参考。 项目地址&#xff1a;https://github.com/HiMeditator/light-…...

图论学习笔记2

请先阅读图论学习笔记 1。 在这篇文章里&#xff0c;我们将继续以前 tarjan 求解的强连通分量和双连通分量&#xff0c;讲解其缩点相关内容。 也会讲解一些特殊的图&#xff1a;基环树与仙人掌图、最小树形图。 缩点 我们知道&#xff0c;将强连通分量、双连通分量缩点之后…...

蓝桥杯备赛---真题训练之15届省赛产品360度展示

题目 介绍 在电子商务网站中&#xff0c;用户可以通过鼠标或手势交互实现 360 度全方位查看产品&#xff0c;提升用户体验。现在需要你设计一个 Pipeline 管道函数&#xff0c;用于控制 360 度展示产品的动画序列&#xff0c;通过管道连接各个动画步骤&#xff0c;使产品以流畅…...

图论:单源最短路(BF算法+迪杰斯特拉算法+spfa算法)

单源最短路 概念 dijkstra实现&#xff08;解决不了负权值&#xff09; P3371 【模板】单源最短路径&#xff08;弱化版&#xff09; - 洛谷 #include<iostream> #include<vector> #include<cstring> using namespace std;typedef pair<int, int> PII…...

嵌入式学习(35)-TTS语音模块FT-VBM-OS支持ModbusRTU

一、概述 FT-TTS-R-01 &#xff08;下简简“模块”&#xff09;是一款可将串口传入的文本信息转成语音播报的控制器。块”可下接收任意字 符或者汉字&#xff0c;并通过 TTS 语音合成功能&#xff0c;清晰、准确、自然的合成并播放音频。该块”还带有 1 路继电器输出&#xff0…...

【Vue-组件】学习笔记

目录 <<回到导览组件1.项目1.1.Vue Cli1.2.项目目录1.3.运行流程1.4.组件的组成1.5.注意事项 2.组件2.1.组件注册2.2.scoped样式冲突2.3.data是一个函数2.4.props详解2.5.data和prop的区别 3.组件通信3.1.父子通信3.1.1.父传子&#xff08;props&#xff09;3.1.2.子传父…...

Github上一些使用技巧(缩写、Issue的Highlight)自用

1. GIthub中的一些缩写 LGTM ! 最近经常看到一些迷之缩写&#xff0c;感觉挺有意思的&#xff0c;但是有时候看到一些没见过的缩写还是有点懵逼&#xff0c;不过缩写确实也是很方便去review&#xff0c;这里就记录汇总一下&#xff1b;顺便加了一些git的基操单词&#xff08;加…...

【团体程序涉及天梯赛】L1~L2实战反思合集(C++)

实战反思汇总记录 仔细审题&#xff0c;想好再写 L1-104 九宫格 - 团体程序设计天梯赛-练习集 易忽略的错误&#xff1a;开始习惯性地看到n就以为是n*n数组了&#xff0c;实际上应该是9*9的固定大小数组&#xff0c;查了半天没查出来 L1-101 别再来这么多猫娘了&#xff01…...

ubuntu下的node.js的安装

安装 node-v22.14.0-linux-x64.tar.xz 的步骤如下&#xff1a; 1. 下载和解压 如果尚未下载文件&#xff0c;可以通过 wget 下载&#xff08;替换为实际下载链接&#xff09;&#xff1a; wget https://nodejs.org/dist/v22.14.0/node-v22.14.0-linux-x64.tar.xz解压文件&…...

VMware-workstation-full-12.5.2 install OS X 10.11.1(15B42).cdr

手把手虚拟机安装苹果操作系统 VMware_workstation_full_12.5.2 unlocker208 Apple Max OS X(M&#xff09;-CSDN博客 vcpu-0:VERIFY vmcore/vmm/main/physMem_monitor.c:1180 FILE: FileCreateDirectoryRetry: Non-retriable error encountered (C:\ProgramData\VMware): Cann…...

Linux下创建svn库 和 svn安装与操作

1.介绍 SVN是Subversion的简称&#xff0c;是一个开放源代码的版本控制系统&#xff0c;相较于RCS、CVS&#xff0c;它采用了分支管理系统&#xff0c;它的设计目标就是取代CVS。适合中小公司的开发人员不多的项目使用,相比git管理工具更简单. 2.安装svn 2.1 国际惯例 首先看…...

React-04React组件状态(state),构造器初始化state以及数据读取,添加点击事件并更改state状态值

1.React组件状态&#xff08;state&#xff09; 组件可以拥有状态&#xff08;state&#xff09;&#xff0c;它是组件数据的私有部分&#xff0c;可以用来管理动态数据。状态仅适用于类组件&#xff0c;或者使用 React 的 Hook 时可以在函数组件中使用。 注意 组件中render方…...

第3课:MCP协议接口定义与开发实践

MCP协议接口开发实战&#xff1a;从标准化设计到跨语言SDK落地 一、引言&#xff1a;为什么接口标准化是多智能体协作的“刚需” 在多智能体系统中&#xff0c;不同语言开发的智能体、异构服务之间的通信效率往往受制于接口兼容性问题。MCP&#xff08;Model Context Protoco…...

Perl语言的WebAssembly

Perl语言的WebAssembly&#xff1a;将古老的语言带入新世纪 引言 在编程语言发展的历史长河中&#xff0c;Perl作为一门早期广泛使用的脚本语言&#xff0c;以其灵活性和丰富的文本处理能力而闻名。然而&#xff0c;随着互联网和Web技术的迅猛发展&#xff0c;许多开发者开始…...

[ISP] ISP 中的 GTM 与 LTM:原理、算法与与 Gamma 校正的对比详解

在现代图像信号处理&#xff08;ISP&#xff09;流水线中&#xff0c;图像增强是提升视觉质量的核心手段之一。尤其是在高动态范围&#xff08;HDR&#xff09;内容、弱光环境或复杂光照条件下&#xff0c;Tone Mapping&#xff08;色调映射&#xff09;技术的引入成为关键。To…...

健身管理小程序|基于java微信开发健身管理小程序的系统设计与实现(源码+数据库+文档)

健身管理小程序目录 基于微信开发健身管理小程序设计与实现 一、前言 二、系统设计 三、系统功能设计 小程序端&#xff1a; 后台 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码…...

批量将文本合并成单个文件,支持按文件夹合并文本文档

我们的文件夹中有零零碎碎的多个小的文本文件&#xff0c;这对我们存档记录是非常不方便&#xff0c;不友好的。如果我们能够将多个小的文本文件合并成一个完整的大的文本文件&#xff0c;那不管是在共享还是在存档起来都更加的方便。今天给大家介绍一下如何批量将多个文本文件…...

ROS云课三分钟-差动移动机器人巡逻报告如何撰写-中等报告

评语&#xff1a; 成绩中等&#xff08;70/100&#xff09;&#xff0c;具体如下&#xff1a; 1. 摘要部分 问题描述&#xff1a; 内容空洞&#xff1a;摘要过于简短&#xff0c;仅简要概述了研究内容和实现方法&#xff0c;未突出研究的创新点或重要性。缺乏细节&#xff1…...

forms实现推箱子小游戏

说明: forms实现推箱子小游戏 效果图&#xff1a; step0:游戏规则 # 推箱子游戏规则说明## &#x1f3af; 游戏目标 - 通过控制角色移动&#xff0c;将所有**棕色箱子(3)**推到**红色目标点(4)**上 - 当所有箱子都变为**绿色(7)**时&#xff0c;即完成当前关卡 - 完成全部关…...

图的储存+图的遍历

图的存储 邻接矩阵 #include <iostream>#include <cstring>using namespace std;const int N 1010;int n, m;int edges[N][N];int main() {memset(edges, -1, sizeof edges);cin >> n >> m; // 读⼊结点个数以及边的个数 for(int i 1; i < m; i)…...

蓝桥杯—数字接龙(dfs+减枝)

一.题目 二.思路 一看就是迷宫问题的变种&#xff0c;从左上角到达右下角&#xff0c;要解决 1.8个方向的方向向量&#xff0c;用dx&#xff0c;dy数组代表方向向量 2.要按照一个规律的数值串进行搜索0&#xff0c;1&#xff0c;2&#xff0c;k-1&#xff0c;0&#xff0c;1…...

Solidity智能合约漏洞类型与解题思路指南

一、常见漏洞类型与通俗解释 1. 重入攻击(Reentrancy) 🌀 通俗解释:就像你去银行取钱,柜台人员先给你钱,然后再记账。你拿到钱后立即又要求取钱,由于账还没记,柜台又给你一次钱,这样循环下去你就能拿走银行所有的钱。 漏洞原理:合约在更新状态前调用外部合约,允许…...

临床 不等于 医学-《分析模式》漫谈52

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 “Analysis Patterns”的第4章“企业财务观察”有这么一句话&#xff1a; An important point about this model——a reflection of its clinical background 2004&#xff08;机械…...

鸿蒙应用开发中的 Stack 布局模式

在鸿蒙(HarmonyOS)应用开发中&#xff0c;Stack 布局模式是一种非常灵活的布局方式&#xff0c;类似于其他开发框架中的 StackPanel 或 AbsoluteLayout。它允许子组件按照层级关系进行堆叠&#xff0c;后添加的组件会覆盖在先添加的组件之上。开发者可以通过设置组件的位置、大…...

仿modou库one thread one loop式并发服务器

源码&#xff1a;田某super/moduo 目录 SERVER模块&#xff1a; Buffer模块&#xff1a; Socket模块&#xff1a; Channel模块&#xff1a; Connection模块&#xff1a; Acceptor模块&#xff1a; TimerQueue模块&#xff1a; Poller模块&#xff1a; EventLoop模块&a…...

【AI学习】初步了解Gradio

Gradio 是一个开源的 Python 库&#xff0c;专注于快速构建交互式 Web 界面&#xff0c;特别适用于机器学习模型、数据科学项目或任意 Python 函数的演示与部署。它通过极简的代码实现前后端一体化&#xff0c;无需前端开发经验即可创建功能丰富的应用。以下是 Gradio 的核心特…...

C++11QT复习 (十四)

文章目录 Day9 数据结构学习笔记&#xff08;2025.04.01&#xff09;一、C基础快速回顾二、STL&#xff08;标准模板库&#xff09;三、常见容器及其对应的数据结构四、容器操作演示1. 基本容器使用2. 异构类型容器 五、迭代器详解特点示例用户自定义结构体访问成员 六、算法库…...

ThreadCache

目录 一、Freelist 二、ThreadCache 三、哈希桶映射规则 一、Freelist 在之前整体框架介绍的时候&#xff0c;我们曾说过ThreadCache是一个哈希桶的结构。每一个桶都要存同一个大小的对象块&#xff08;即最小块的内存&#xff09;。 那么我们使用FreeList来…...

c++中同步和异步,阻塞和非阻塞原理以及机制

在C中&#xff0c;同步与异步、阻塞与非阻塞是并发编程中的重要概念&#xff0c;它们描述了程序在执行任务时的行为模式。理解这些概念对于设计高效、响应良好的并发程序至关重要。下面我将详细介绍这些概念的原理和机制。 1. 同步与异步 同步&#xff08;Synchronous&#x…...