{
  "AI/AI大模型应用拆解.md": "> 此笔记记录一些AI工具的应用原理，给自己制作此类工具提供一点思路\n\n**AI老师阅卷批改：**\nOCR文字识别->大语言模型文本处理\n\n**AI视频总结（bilinote）：**\n下载视频->提取音频->音频转文字->大语言模型文本处理\n\n**AI一键解读医学报告：**\nOCR文字识别->大语言模型文本处理\n",
  "AI/AI提示词工程/AI绘画提示词.md": "*by 树萌芽*\n\n**图片风格为2D像素像素化风格，比例 「1:1」  画一个游戏道具，背景是纯黑色，纯黑色**  \n**不带任何文字，没有任何文字，现在我要你画     一个闪闪发光的金黄色金币卡**\n\n\n**图片风格为2D像素风格，比例 「1:1」  画一个游戏元素，风格为2.5D 就是上帝视角，就是正交斜视角那种有立体感，背景是纯黑色，纯黑色    不带任何文字，现在我要你画一个**   \n**一丛茂密的灌木丛  记住一定要3d立体感 只要 灌木丛 只要 灌木丛！**\n\n\n比例 「1:1」图片风格为2D像素风格， 画一个游戏装饰元素，风格为2.5D 就是上帝视角，就是正交斜视角那种有立体感，背景是纯黑色，纯黑色    不带任何文字，现在我要你画一个     占卜测运算命台  相关的装饰可以多一点    记住一定要3d立体感  ",
  "AI/AI提示词工程/大模型驱动应用功能的实现.md": "\n**大模型本身不能直接执行任何任务。它像一个超级大脑，但缺少手和脚。它通过生成“指令”或“代码”，然后由一个“执行环境”来真正驱动任务。**\n\n让我们来分解这个过程：\n\n### 核心原理：工具使用与函数调用\n\n大模型驱动任务的核心能力被称为 **“工具使用”** 或 **“函数调用”** 。你可以把这个过程想象成一个聪明的分析师和一个高效的执行秘书之间的配合：\n\n- **大模型（分析师）：** 负责理解你的自然语言指令、分析意图、制定计划，并决定下一步该调用哪个“工具”（函数）。\n- **执行环境/应用程序（秘书）：** 它拥有真正的“手和脚”。它准备好了各种工具（API、函数），并严格按照分析师的指令去执行。\n\n### 具体工作流程（以“订机票”为例）\n\n假设你对一个集成了大模型的AI助手说：“帮我订一张明天从北京到上海的最便宜的机票。”\n\n这个过程并不是大模型直接去登录航空公司的系统，而是如下步骤：\n\n1.  **意图理解与规划：**\n    - 大模型解析你的指令，识别出关键信息：\n        - **意图：** 订机票\n        - **出发地：** 北京\n        - **目的地：** 上海\n        - **时间：** 明天\n        - **偏好：** 最便宜\n    - 它在内部规划出一个步骤序列：`查询航班 -> 比较价格 -> 填写订单 -> 完成支付`。\n\n2.  **识别可用工具：**\n    - 应用程序（AI助手）已经向大模型“注册”了它可以调用的各种工具函数，比如：\n        - `search_flights(departure, destination, date)`\n        - `compare_prices(flight_list)`\n        - `book_flight(flight_id, passenger_info)`\n        - `process_payment(booking_id, payment_details)`\n\n3.  **生成函数调用：**\n    - 大模型意识到第一步需要查询航班。于是，它不会用自然语言回复你，而是会生成一个**结构化的函数调用请求**，格式通常是JSON：\n      ```json\n      {\n        \"function\": \"search_flights\",\n        \"arguments\": {\n          \"departure\": \"北京\",\n          \"destination\": \"上海\",\n          \"date\": \"2024-06-02\"\n        }\n      }\n      ```\n\n4.  **执行函数：**\n    - 应用程序接收到这个请求后，**在自己的安全环境内**，调用真正的 `search_flights` 函数。这个函数可能连接着航司的API、携程的接口，或者一个内部的航班数据库。\n    - **关键点：** 执行代码、访问网络、操作数据库等危险或实际的操作，都是由应用程序完成的，而不是大模型本身。\n\n5.  **获取结果并继续：**\n    - `search_flights` 函数返回一个结构化的航班列表给应用程序。\n    - 应用程序把这个结果（数据）再次作为上下文提供给大模型。\n    - 大模型看到查询结果后，进行下一步分析，比如调用 `compare_prices` 来筛选出最便宜的选项。\n    - 然后，它可能会生成下一个函数调用，比如 `book_flight`，并提示你提供乘机人信息。\n\n6.  **循环直至完成：**\n    - 这个“模型分析 -> 生成调用 -> 环境执行 -> 返回结果”的循环会一直持续，直到任务完成（比如订单确认号生成）。\n\n### “打开网页”是如何工作的？\n\n这个例子更直观：\n\n1.  你说：“打开百度首页。”\n2.  大模型识别出你的意图是“打开网页”，并且目标网址是“百度首页”。\n3.  它生成一个函数调用，比如 `open_browser(url=\"https://www.baidu.com\")`。\n4.  应用程序（比如你的操作系统 shell 或一个自动化脚本）执行这个函数，启动你的默认浏览器并导航到该网址。\n5.  大模型回复你：“已为您打开百度首页。”\n\n### 为什么大模型“能够”做这些事？它的能力来源是什么？\n\n1.  **代码理解与生成能力：** 大模型在训练时学习了海量的公开代码（如GitHub），因此它非常理解编程逻辑和API的调用方式。它知道 `search_flights` 这个函数需要哪些参数，以及返回的数据大概是什么样子。\n2.  **逻辑推理与规划能力：** 它将复杂的用户请求（“订最便宜的机票”）分解成一系列可执行的、有序的步骤。\n3.  **自然语言到结构化数据的转换能力：** 这是最关键的一步。它能将你模糊的、非结构化的口语指令（“帮我找个便宜的航班”），精确地转换成计算机可以理解的结构化参数（`{“max_price\": 500, \"sort_by\": \"price\"}`）。\n\n### 总结\n\n- **大模型是“策略大脑”，不是“执行手脚”。** 它通过**工具使用（函数调用）** 来驱动任务。\n- **真正的执行者是外部的应用程序或系统**，它提供了安全的执行环境和真实的工具。\n- 大模型的价值在于充当了一个**极其强大的“自然语言到代码/指令”的翻译器和规划器**，让人类可以用最自然的方式与复杂的计算机系统交互。\n\n所以，当你看到一个大模型能“订机票”或“打开网页”时，背后其实是一个精心设计的系统，在这个系统中，大模型扮演着指挥中心的角色，而具体的脏活累活则由它指挥的其他专业模块来完成。",
  "AI/AI提示词工程/开发前后端分离网站提示词.md": "1.取消CORS跨域限制，允许任何链接\n2.前端使用React框架，后端使用python的Flask框架\n3.前端修改在frontend文件夹，后端修改在backend文件夹",
  "AI/Qwen-Code命令行安装使用教程.md": "**Qwen Code** 是一个 CLI 工具，修改自 **Gemini CLI**，针对 Qwen3‑Coder系列的模型增强了解析器和工具支持。\n\n确保已安装 Node.js 20 及以上版本，可以通过以下命令安装：\n\n```bash\ncurl -qL https://www.npmjs.com/install.sh | sh\n```\n\n然后通过 npm 管理器安装 Qwen Code：\n\n```bash\nnpm i -g @qwen-code/qwen-code\n```\n\n> 另一种方式是从源码安装：\n> \n> ```bash\n> git clone https://github.com/QwenLM/qwen-code.git\n> cd qwen-code && npm install && npm install -g\n> ```\n\nQwen Code 支持 OpenAI SDK 调用 LLM，你可以导出以下环境变量，或者简单地将其放在 `.envfile` 中。\n\n```bash\nexport OPENAI_API_KEY=\"your_api_key_here\"\nexport OPENAI_BASE_URL=\"https://dashscope.aliyuncs.com/compatible-mode/v1\"\nexport OPENAI_MODEL=\"qwen3-coder-plus\"\n```\n\n现在，你可以通过简单地输入 **`qwen`** 来享受 Qwen-Code 和 Qwen 带来的编程体验。\n\n### Claude Code\n\n除了 Qwen Code 之外，现在还可以将 Qwen3‑Coder 与 Claude Code 搭配使用。只需在[阿里云百炼](https://bailian.console.aliyun.com/)平台申请 API Key，并安装 Claude Code，即可开始畅享编码体验。\n\n```bash\nnpm install -g @anthropic-ai/claude-code\n```\n\n我们提供了两种接入方式，帮助你无缝地用 Qwen3‑Coder 进行编码。\n\n#### 使用dashscope提供的代理  API\n\n只需要将Anthropic的base url替换成dashscope上提供的endpoint即可。\n\n```bash\nexport ANTHROPIC_BASE_URL=https://dashscope.aliyuncs.com/api/v2/apps/claude-code-proxy\nexport ANTHROPIC_AUTH_TOKEN=your-dashscope-apikey\n```\n\n可选方案 2：使用 claude-code-config 自定义路由\n\n#### Optional 2: 使用 claude-code-config 自定义路由\n\nclaude-code-router 是一个第三方的路由工具，用于为 Claude Code 灵活地切换不同的后端 API。dashScope平台提供了一个简单的扩展包 claude-code-config，可为 claude-code-router 生成包含 dashScope 支持的默认配置。\n\n```bash\nnpm install -g @musistudio/claude-code-router\nnpm install -g @dashscope-js/claude-code-config\n```\n\n生成配置文件和插件目录：\n\n```bash\nccr-dashscope\n```\n\n该命令会自动生成 ccr 所需的配置文件和插件目录。你也可以手动调整 ~/.claude-code-router/config.json 和 ~/.claude-code-router/plugins/ 中的配置。\n\n最后，通过 ccr 开始使用 Claude Code：\n\n```bash\nccr code\n```\n\n至此，你即可通过 ccr 使用 Claude Code 畅享 Qwen3‑Coder 的强大编码能力。祝开发顺利！\n\n### Cline\n\n配置 Qwen3-Coder-480B-A35B-instruct 以使用 cline ‒ 进入 cline 的配置设置 ‒ 选择“OpenAI Compatible”模式 ‒ 在 OpenAI Compatible API tokens处，输入从 Dashscope 获取的密钥 ‒ 勾选“使用自定义基础 URL”，并输入：`https://dashscope.aliyuncs.com/compatible-mode/v1` ‒ 输入模型名称：`qwen3-coder-plus`",
  "AI/Qwen-Code官方文档使用教程.md": "\n---\n\nQwen Code 是一款专为 **Qwen3-Coder** 模型优化的命令行 AI 工作流工具，通过先进的代码理解能力、自动化任务和智能辅助功能，显著提升开发效率。\n\n---\n\n## 🛠 操作步骤\n\n### 1️⃣ 获取阿里云百炼 API Key\n\n1. 登录 **阿里云百炼大模型服务平台**。\n    \n2. 如果页面顶部显示 **image**，说明需要开通服务。\n    \n    - 开通后可领取新人免费额度（30~180天）。\n        \n    - 如果提示 **实名认证**，请先完成认证。\n        \n3. 免费额度详情可在 **新人免费额度页面** 查看。\n    \n4. 获取 **阿里云百炼 API Key**。\n    \n\n---\n\n### 2️⃣ 选择模型\n\nQwen Code 支持 **OpenAI 兼容接口模型**，包括：\n\n- 🌟 **qwen3-coder-plus**（推荐，2025年7月23日起限时优惠）\n    \n- qwen3-coder-480b-a35b-instruct\n    \n- qwen3-coder-flash\n    \n- qwen3-coder-30b-a3b-instruct\n    \n\n---\n\n### 3️⃣ 安装与配置 Qwen Code\n\n#### ✅ Node.js 版本检查\n\n```bash\nnode -v\n```\n\n需 **Node.js 20+**，低于则需重新安装。\n\n#### 📦 安装 Qwen Code\n\n```bash\n# 配置镜像源加速\nnpm config set registry https://registry.npmmirror.com\n\n# 安装 Qwen Code\nnpm install -g @qwen-code/qwen-code@latest\n```\n\n---\n\n### 4️⃣ 启动并配置 Qwen Code\n\n1. 在终端中输入：\n    \n    ```bash\n    qwen\n    ```\n    \n2. 选择认证方式 → **OpenAI**\n    \n3. 填写以下信息：\n    \n\n|配置项|说明|\n|---|---|\n|🔑 API Key|阿里云百炼 API Key|\n|🌐 Base URL|`https://dashscope.aliyuncs.com/compatible-mode/v1`|\n|🤖 Model|推荐 `qwen3-coder-plus`|\n\n👉 若不想每次都输入，请配置 **环境变量**。\n\n---\n\n### 5️⃣ 配置环境变量\n\n在系统中设置：\n\n```bash\nexport OPENAI_API_KEY=你的APIKey\nexport OPENAI_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1\nexport OPENAI_MODEL=qwen3-coder-plus\n```\n\n---\n\n### 6️⃣ 向 Qwen Code 提问\n\n💡 示例问题：\n\n```\n如何用python实现一个二叉搜索树？\n```\n\nQwen Code 会自动创建文件、写入并执行代码。\n\n---\n\n### 7️⃣ 查看 Token 消耗\n\n输入：\n\n```bash\n/stats model\n```\n\n即可查看本次启动后的 **Token 消耗** 与 **API 调用次数**。\n\n---\n\n## 🎁 免费额度\n\n- 阿里云百炼：**每个模型 100 万免费 Token**\n    \n- Qwen Code：**每天 2000 次免费调用**\n    \n\n👉 为避免额外消费，可开启 **免费额度用完即停** 按钮。\n\n---\n\n## 🔧 进阶操作\n\n更多功能请参考：\n\n- 📘 [Qwen Code 文档]\n    \n- 📘 [阿里云百炼代码能力]\n    \n\n---\n\n## ❓ 常见问题 (FAQ)\n\n### ❓ Q：为什么 Token 消耗快？\n\n✅ A：可能多次调用 API。  \n👉 控制方法：\n\n- 精简工作目录（避免在项目根目录运行）。\n    \n- 设置 Token 限额：\n    \n\n```json\n{\n  \"sessionTokenLimit\": 32000\n}\n```\n\n- 使用指令：\n    \n    - `/compress` → 压缩对话历史\n        \n    - `/clear` → 清空历史\n        \n\n---\n\n### ❓ Q：如何切换模型？\n\n- 未配置环境变量：\n    \n    1. `/quit` 退出\n        \n    2. `qwen` 重新启动，手动输入 API Key、Base URL、模型名\n        \n- 已配置环境变量：\n    \n    1. 修改 `OPENAI_MODEL`\n        \n    2. `/quit` → `qwen` 重启\n        \n\n---\n\n### ❓ Q：如何使用每天 2000 次免费额度？\n\n- 输入 `/auth` → 选择 **Qwen Oauth** → 登录 **Qwen Chat**\n    \n- 每天可免费调用 `qwen3-coder-plus` **2000 次**\n    \n- 超过 2000 次 → 切换回 **OpenAI 认证方式**\n    \n\n---\n\n### ❓ Q：为什么报 `401 Incorrect API key provided` 错误？\n\n✅ 检查以下：\n\n- API Key 是否正确\n    \n- 是否有全局环境变量覆盖了配置文件\n    \n\n---",
  "AI/大模型上下文记忆功能的实现.md": "\n**大模型本身不具备记忆功能，并且是无状态的。我们感受到的“记忆”和“上下文”能力，是由使用大模型的应用程序（或框架）提供的。**\n\n### 1. 大模型本身：一个“无状态”的函数\n\n你可以把一个大模型（比如 GPT-4）想象成一个极其复杂、聪明的**数学函数**。\n\n- **无状态：** 这个函数本身不存储任何关于上一次被调用（即上一次对话）的信息。就像你计算 `f(x) = x + 2` 这个函数，你输入 `3`，它输出 `5`。你再次输入 `3`，它还是会输出 `5`。它不会“记得”你上一次输入了什么。大模型在每次被调用时，都只基于**当前这一次的输入**进行计算，然后产生输出。计算完成后，它内部不保存任何这次对话的“状态”。\n- **核心输入：** 大模型最核心的输入就是一个**文本序列**，也就是一个由词汇（Token）组成的字符串。它在这个序列的范围内进行模式识别和文本生成。\n\n### 2. “记忆”从何而来？—— 上下文窗口\n\n既然模型本身无记忆，我们感受到的连贯对话是怎么来的呢？答案是 **“上下文窗口”**。\n\n- **什么是上下文窗口？** 这是模型**单次处理**所能接受的最大文本长度（例如 128K Tokens）。这个窗口不仅包含你**刚刚提出的新问题**，还包含了应用程序**特意塞进去的、之前所有的对话历史**。\n- **工作流程是这样的：**\n  1.  你第一次说：“你好，我叫小明。”\n  2.  应用程序（比如ChatGPT界面）会收到这条消息。它不会只把“你好，我叫小明。”发给模型，而是会组装一个完整的“提示”。这个提示可能看起来像这样（高度简化）：\n        `[系统指令：你是一个友好的助手...] 用户：你好，我叫小明。 助手：`\n  3.  模型收到这个提示，生成回答：“你好小明！很高兴认识你。”\n  4.  **关键一步：** 当你接着问第二个问题：“你还记得我叫什么吗？”时，应用程序会把**迄今为止所有的对话**都组装成一个新的、更长的提示，发给模型：\n        `[系统指令：你是一个友好的助手...] 用户：你好，我叫小明。 助手：你好小明！很高兴认识你。 用户：你还记得我叫什么吗？ 助手：`\n  5.  模型看到这个包含了全部历史的提示，它就能“看到”之前你提到了名字叫“小明”，从而生成正确的回答：“当然记得，你叫小明！”\n\n所以，**模型的“记忆”本质上是“回顾”**。它并没有真正记住，而是每次都被给予了一份完整的“剧本”以供参考。这个剧本就是**上下文窗口**。\n\n### 3. 应用程序的角色：有状态的“对话管理者”\n\n真正“有状态”的，是和你交互的**应用程序或服务**。\n\n- **它负责维护对话历史：** 这个应用（比如ChatGPT网页、API后端服务）有一个数据库或缓存，用来存储你整个会话的所有消息。\n- **它负责组装和修剪提示：** 每次你发送新消息，它都会从存储中取出历史记录，拼接到新消息前面，形成一个完整的提示，再发送给无状态的大模型。当对话很长，超过了模型的上下文窗口限制时，它还需要智能地修剪或总结早期的对话内容，以腾出空间。\n- **它可能管理长期记忆：** 一些更高级的应用（如GPTs、某些AI聊天机器人）可能会提供“长期记忆”或“核心记忆”功能。这通常是应用程序将你认为重要的信息提取出来，存储在独立的向量数据库里。在后续对话中，它会动态地从数据库中检索相关的“记忆”，并将其作为上下文的一部分塞给模型。\n\n### 总结与类比\n\n为了让你更好地理解，我们可以做一个类比：\n\n- **大模型本身：** 像一个**世界顶级的、但患有短期失忆症的厨师**。他厨艺精湛，能根据你给他的所有食材（输入提示）做出一道完美的菜（输出回答）。但做完之后，他就把这次烹饪忘得一干二净。\n- **应用程序：** 像这个厨师的**助手和服务员**。他负责记录每一位顾客（用户）点过的所有菜（对话历史）。当顾客要点新菜时，服务员会把顾客过去的点单记录和新的要求一起交给厨师，这样厨师就能做出符合顾客口味和需求的菜。\n\n**所以，回到你的问题：**\n\n1.  **你觉得这个记忆的功能是大模型提供的能力吗？**\n    - 不完全是。**基础能力**（在给定上下文中理解关联信息）是模型提供的，但**实现记忆的机制**（存储、组装、传递上下文）是由应用程序提供的。两者缺一不可。\n\n2.  **大模型是有状态的吗？**\n    - **大模型本身是无状态的。** 它是一个纯粹的函数。\n    - **但以大模型为核心构建的AI应用或服务是“有状态”的。** 这个状态就是它维护的对话历史、用户偏好等数据。\n\n这种“无状态模型 + 有状态应用”的设计，既保证了模型本身的纯粹和可扩展性（可以同时服务海量用户而状态不冲突），又通过应用程序赋予了它进行连贯、个性化对话的强大能力。",
  "AI/大语言模型的API key.md": "#### deepseek ：\n**调用密钥：**\nsk-832f8e5250464de08a31523c7fd71295\n**调用地址：**\nhttps://api.deepseek.com\n**调用模型：**\ndeepseek-chat  \ndeepseek-reasoner\n\n\n\n阿里云百炼大模型平台：\n通用秘钥：sk-3d9e8e02a3704868b1a7159d52f2643d\n\n\n字节火山方舟模型控制台：\n通用秘钥：fc439240-ed3c-4e65-acaf-3541c66c6ebc\n\n\n#### Kimi ：\n**调用密钥：**\nsk-zdg9NBpTlhOcDDpoWfaBKu0KNDdGv18SipORnL2utawja0bE\n**调用地址：**\nhttps://api.moonshot.cn\n**调用模型：**\nkimi-k2-0905-preview \nkimi-k2-0711-preview\nkimi-k2-turbo-preview 这个非常贵\nkimi-latest-8k  支持图片理解\nkimi-latest-32k\nkimi-latest-128k 这个非常贵\n",
  "AI/大语言模型的API 调用.md": "deepseek api秘钥：\n调用密钥：\nsk-16e24c16ff894771849ee6e15d4fb301\n调用地址：\nhttps://api.deepseek.com\n\n阿里云百炼大模型平台：\n通用秘钥：\nsk-3d9e8e02a3704868b1a7159d52f2643d\n调用地址：\nhttps://dashscope.aliyuncs.com/compatible-mode/v1\n\n字节火山方舟模型控制台：\n通用秘钥：\nfc439240-ed3c-4e65-acaf-3541c66c6ebc\n调用地址：\nhttps://ark.cn-beijing.volces.com/api/v3/chat/completions\n\nkimi API调用：\n调用密钥：\nsk-32M3DYWQdPlftpaGOmIuS7OFKzqCiSutktFPxPqTWn3oFadM\n调用地址：\nhttps://api.moonshot.cn",
  "AI/阿里云百炼平台模型API调用示例.md": "\n### **Python调用示例：**\n```python\nimport os\nfrom openai import OpenAI\n\nclient = OpenAI(\n    api_key=os.getenv(\"DASHSCOPE_API_KEY\"), # 如果您没有配置环境变量，请在此处用您的API Key进行替换\n    base_url=\"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n)\ncompletion = client.chat.completions.create(\n    model=\"qwen3-coder-plus\",\n    messages=[\n        {'role': 'system', 'content': 'You are a helpful assistant.'},\n        {'role': 'user', 'content': '请编写一个Python函数 find_prime_numbers，该函数接受一个整数 n 作为参数，并返回一个包含所有小于 n 的质数（素数）的列表。质数是指仅能被1和其自身整除的正整数，如2, 3, 5, 7等。不要输出非代码的内容。'}],\n    )\nprint(\"=\"*20+\"回复内容\"+\"=\"*20)\nprint(completion.choices[0].message.content)\nprint(\"=\"*20+\"Token消耗\"+\"=\"*20)\nprint(completion.usage)\n```\n**返回结果示例：**\n````plaintext\n====================回复内容====================\n```python\ndef find_prime_numbers(n):\n    if n <= 2:\n        return []\n    \n    primes = []\n    \n    for num in range(2, n):\n        is_prime = True\n        for i in range(2, int(num ** 0.5) + 1):\n            if num % i == 0:\n                is_prime = False\n                break\n        if is_prime:\n            primes.append(num)\n    \n    return primes\n```\n====================Token消耗====================\nCompletionUsage(completion_tokens=95, prompt_tokens=91, total_tokens=186, completion_tokens_details=None, prompt_tokens_details=PromptTokensDetails(audio_tokens=None, cached_tokens=0))\n````\n\n\n\ncurl调用示例：\n```curl\ncurl -X POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions \\\n-H \"Authorization: Bearer $DASHSCOPE_API_KEY\" \\\n-H \"Content-Type: application/json\" \\\n-d '{\n    \"model\": \"qwen3-coder-plus\",\n    \"messages\": [\n        {\n            \"role\": \"system\",\n            \"content\": \"You are a helpful assistant.\"\n        },\n        {\n            \"role\": \"user\", \n            \"content\": \"请编写一个Python函数 find_prime_numbers，该函数接受一个整数 n 作为参数，并返回一个包含所有小于 n 的质数（素数）的列表。质数是指仅能被1和其自身整除的正整数，如2, 3, 5, 7等。不要输出非代码的内容。\"\n        }\n    ]\n}'\n```\n\n\n返回结果示例：\n```json\n{\n    \"choices\": [\n        {\n            \"message\": {\n                \"content\": \"```python\\ndef find_prime_numbers(n):\\n    if n <= 2:\\n        return []\\n    \\n    primes = []\\n    \\n    for num in range(2, n):\\n        is_prime = True\\n        for i in range(2, int(num ** 0.5) + 1):\\n            if num % i == 0:\\n                is_prime = False\\n                break\\n        if is_prime:\\n            primes.append(num)\\n    \\n    return primes\\n```\",\n                \"role\": \"assistant\"\n            },\n            \"finish_reason\": \"stop\",\n            \"index\": 0,\n            \"logprobs\": null\n        }\n    ],\n    \"object\": \"chat.completion\",\n    \"usage\": {\n        \"prompt_tokens\": 91,\n        \"completion_tokens\": 95,\n        \"total_tokens\": 186,\n        \"prompt_tokens_details\": {\n            \"cached_tokens\": 0\n        }\n    },\n    \"created\": 1753192010,\n    \"system_fingerprint\": null,\n    \"model\": \"qwen3-coder-plus\",\n    \"id\": \"chatcmpl-798c99c2-7410-9cc4-8385-6dfd757757fa\"\n}\n```\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
  "Docker/Docker 镜像相关.md": "\n**QQ机器人框架NapCat**\n```shell\n#安装\ndocker run -d \\\n-e NAPCAT_GID=$(id -g) \\\n-e NAPCAT_UID=$(id -u) \\\n-p 4080:3000 \\\n-p 4070:3001 \\\n-p 4060:6099 \\\n--name napcat \\\n--restart=always \\\nmlikiowa/napcat-docker:latest\n\n#固化以下路径，方便掉线时快速重新登录\n#QQ 持久化数据路径：/app/.config/QQ\n#NapCat 配置文件路径: /app/napcat/config\n\n#登录 WebUI 后台地址：http://<宿主机ip>:6099/webui\n```\n\n**网页SSH客户端-EasyNode**\n```shell\n#项目地址：https://github.com/chaos-zhu/easynode\n\n# 1. 创建easynode目录\nmkdir -p /root/easynode && cd /root/easynode\n\n# 2. 下载docker-compose.yml文件\nwget https://git.221022.xyz/https://raw.githubusercontent.com/chaos-zhu/easynode/main/docker-compose.yml\n\n# 3. 启动服务\ndocker-compose up -d\n\ndocker run -d -p 8082:8082 --restart=always -v /root/easynode/db:/easynode/app/db chaoszhu/easynode\n\n### 监控服务\n#安装\n# 使用默认端口22022安装\ncurl -o- https://git.221022.xyz/https://raw.githubusercontent.com/chaos-zhu/easynode/main/client/easynode-client-install.sh | bash\n\n# 使用自定义端口安装, 例如54321\ncurl -o- https://git.221022.xyz/https://raw.githubusercontent.com/chaos-zhu/easynode/main/client/easynode-client-install.sh | bash -s -- 54321\n\n#卸载\ncurl -o- https://git.221022.xyz/https://raw.githubusercontent.com/chaos-zhu/easynode/main/client/easynode-client-uninstall.sh | bash\n\n#查看监控服务状态：systemctl status easynode-client \n#查看监控服务日志: journalctl --follow -u easynode-client \n#查看详细日志：journalctl -xe\n```\n\n**docker加速地址**\n\n![[Screenshot_20250717_225309.jpg]]\n\n\ndocker.1ms.run/\n\ndocker run -d -p 4050:80 --restart=always -v /shumengya/tu:/var/www/html docker.1ms.run/oaooa/pichome\n\n\n\n\n\n\n\n",
  "Docker/Docker命令集合.md": "\ndocker-compose up -d\n\ndocker-compose down\n\ndocker-compose restart\n\ndocker-compose logs -f\n\ndocker-compose ps  \n\ndocker-compose build --no-cache\n\n\n**Docker容器一键更新到最新版镜像（以60s API举例）**\n```bash\n#拉取最新镜像\n\ndocker pull mlikiowa/napcat-docker:latest\ndocker pull couchdb:latest #Obsidian同步的数据库\ndocker pull aceberg/watchyourlan #扫描局域网的工具\n\ndocker pull dpanel/dpanel:latest\n\n\n#停止并删除旧容器\n\ndocker stop napcat\ndocker rm napcat\n\n#兰空图床免费版\ndocker run -d \\\n  --name lsky-pro \\\n  -p 8089:80 \\\n  -v /shumengya/docker/storage/lsky:/var/www/html \\\n  --restart=always \\\n  halcyonazure/lsky-pro:latest\n\n\n\n\n\n\n\n\n#可视化Docker面板\ndocker run -d \\\n  --name dpanel \\\n  -p 8800:8080 \\\n  -v /var/run/docker.sock:/var/run/docker.sock \\\n  -v /shumengya/docker/storage/dpanel:/dpanel/data \\\n  --restart=always \\\n  dpanel/dpanel:latest\n\n\n\n#扫描局域网的工具\ndocker run -d \\\n  --name watch-your-lan \\\n  --restart unless-stopped \\\n  --net=host \\\n  -e TZ=Asia/Shanghai \\\n  -v /shumengya/docker/storage/watchyourlan:/data \\\n  aceberg/watchyourlan\n\n#Obsidian 同步数据库\ndocker run -d \\\n  --name obsidian-couchdb \\\n  -e COUCHDB_USER=shumengya \\\n  -e COUCHDB_PASSWORD='tyh@19900420' \\\n  -p 5984:5984 \\\n  couchdb:latest\n\n\n  \n#napcat QQ机器人\ndocker run -d \\\n  --name napcat \\\n  --restart=always \\\n  -e NAPCAT_GID=$(id -g) \\\n  -e NAPCAT_UID=$(id -u) \\\n  -p 4080:3000 \\\n  -p 4070:3001 \\\n  -p 4060:6099 \\\n  -v /shumengya/docker/storage/napcat/qq:/app/.config/QQ \\\n  -v /shumengya/docker/storage/napcat/config:/app/napcat/config \\\n  mlikiowa/napcat-docker:latest\n\n\n\n\n```\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
  "Docker/Docker镜像快速迁移.md": "\n---\n\n## ✅ 方法一：直接导出容器（container → tar）\n\n如果你运行的是一个 **容器**（而不是镜像），可以直接打包它：\n\n```bash\n# 导出容器\ndocker export <容器ID或名字> -o container.tar\n\n# 在另一台Linux机器上导入\ndocker import container.tar new-image:latest\n```\n\n特点：\n\n- 容器的运行时文件系统会被打包（包含你安装的软件和修改），**但不会包含容器的历史层和环境变量**。\n    \n- 类似于“快照”迁移。\n    \n\n---\n\n## ✅ 方法二：保存镜像（image → tar）\n\n如果你已经把容器做成了一个镜像，建议用 **save/load**：\n\n```bash\n# 在源主机上保存镜像\ndocker save -o myimage.tar myimage:latest\ndocker save -o frpc-1panel.tar snowdreamtech/frpc:0.63.0\n\n# 拷贝到目标主机（比如用 scp）\nscp myimage.tar user@remote:/path/\n\n# 在目标主机导入\ndocker load -i myimage.tar\n```\n\n特点：\n\n- 保留镜像层和构建历史。\n    \n- 推荐这种方式。\n    \n\n---\n\n",
  "Docker/优秀好用的Docker镜像/60sAPI-一款多功能丰富的后端接口集合.md": "\n```bash\n\n#60s api后端\ndocker run -d \\\n  --restart always \\\n  --name 60s \\\n  -p 4399:4399 \\\n  vikiboss/60s:latest\n\n```\n\n```bash\ndocker pull vikiboss/60s:latest \n```\n\n```bash\ndocker stop 60s\ndocker rm 60s\n```",
  "Docker/优秀好用的Docker镜像/FileCodeBox-文件快递柜.md": "\n```bash\ndocker run -d \\\n  --name filecodebox \\\n  --restart=always \\\n  -p 12345:12345 \\\n  -v /shumengya/docker/storage/filecodebox:/app/data \\\n  lanol/filecodebox:beta\n\n```\n\n```bash\n#典型的非关系型数据库（json）\ndocker pull lanol/filecodebox:beta\n```\n\n```\ndocker stop lanol/filecodebox:beta\ndocker rm lanol/filecodebox:beta\n```",
  "Docker/优秀好用的Docker镜像/frp-内网穿透神器.md": "\n```bash\n#启动最新版frp客户端\ndocker run -d \\\n  --name frpc \\\n  --restart=always \\\n  --network host \\\n  -v /shumengya/docker/storage/frpc:/etc/frp \\\n  -e TZ=Asia/Shanghai \\\n  natfrp/frpc:latest \\\n  -c /etc/frp/frpc.toml\n\n#启动最新版frp服务端\ndocker run -d \\\n  --name frps \\\n  --restart=always \\\n  --network host \\\n  -e TZ=Asia/Tokyo \\\n  -v /shumengya/docker/storage/frps:/etc/frp \\\n  snowdreamtech/frps:latest \\\n  -c /etc/frp/frps.toml\n\n\n```\n\n```bash\n\n```\n\n```\n\n```",
  "Docker/优秀好用的Docker镜像/Gitea-私有化仓库部署.md": "\n```bash\n#github/gitlab的本地轻量化部署代替-gitea\ndocker run -d \\\n  --name gitea \\\n  -p 8989:3000 \\\n  -p 8022:22 \\\n  -e USER_UID=1000 \\\n  -e USER_GID=1000 \\\n  -v /shumengya/docker/storage/gitea:/data \\\n  --restart=always \\\n  gitea/gitea:latest\n\n```\n\n```bash\n#典型的非关系型数据库（json）\ndocker pull gitea/gitea:latest\n```\n\n```\ndocker stop gitea/gitea:latest\ndocker rm gitea/gitea:latest\n```",
  "Docker/优秀好用的Docker镜像/kkfileview-文件格式预览大全.md": "\n```bash\n\ndocker run -d \\\n  --name kkfileview \\\n  -p 8289:8012 \\\n  -v /shumengya/docker/storage/kkFileView:/data/file \\\n  --restart unless-stopped \\\n  keking/kkfileview:latest\n\n\n```\n\n```bash\n\n```\n\n```\n\n```",
  "Docker/优秀好用的Docker镜像/MongoDB-数据库.md": "\n```bash\n#MongoDB数据库\ndocker run -d --name mongodb \\\n  -e MONGO_INITDB_ROOT_USERNAME=shumengya \\\n  -e MONGO_INITDB_ROOT_PASSWORD=shumengya520 \\\n  -v /shumengya/docker/storage/mongodb:/data/db \\\n  -p 27017:27017 \\\n  mongo\n```\n\n```bash\n#典型的非关系型数据库（json）\ndocker pull mongo \n```",
  "Docker/优秀好用的Docker镜像/MySQL-数据库.md": "\n```bash\ndocker run -d \\\n--name mysql_latest \\\n-p 3306:3306 \\\n-v /shumengya/docker/storage/mysql:/var/lib/mysql \\\n-e MYSQL_ROOT_PASSWORD=shumengya520 \\\n--memory=4g \\\n--cpus=4 \\\nmysql:latest\n\n\n\n```\n\n```bash\n#典型的非关系型数据库（json）\ndocker pull mysql:latest\n```\n\n```\ndocker stop mysql\ndocker rm mysql\n```",
  "Docker/优秀好用的Docker镜像/NapCat-QQ机器人框架.md": "\n```bash\ndocker run -d \\\n  --name filecodebox \\\n  --restart=always \\\n  -p 12345:12345 \\\n  -v /shumengya/docker/storage/filecodebox:/app/data \\\n  lanol/filecodebox:beta\n\n```\n\n```bash\n#典型的非关系型数据库（json）\ndocker pull lanol/filecodebox:beta\n```\n\n```\ndocker stop lanol/filecodebox:beta\ndocker rm lanol/filecodebox:beta\n```",
  "Docker/优秀好用的Docker镜像/Ntfy-萌芽通知.md": "\n```bash\ndocker run -d \\\n  --name ntfy \\\n  --restart=always \\\n  -e TZ=\"Asia/Shanghai\" \\\n  -e NTFY_BASE_URL=\"https://ntfy.shumengya.top\" \\\n  -e NTFY_CACHE_FILE=\"/var/cache/ntfy/cache.db\" \\\n  -e NTFY_AUTH_FILE=\"/var/lib/ntfy/auth.db\" \\\n  -e NTFY_AUTH_DEFAULT_ACCESS=\"deny-all\" \\\n  -e NTFY_BEHIND_PROXY=\"true\" \\\n  -e NTFY_ATTACHMENT_CACHE_DIR=\"/var/lib/ntfy/attachments\" \\\n  -e NTFY_ENABLE_LOGIN=\"true\" \\\n  -v /shumengya/docker/storage/ntfy/cache:/var/cache/ntfy \\\n  -v /shumengya/docker/storage/ntfy/etc:/etc/ntfy \\\n  -v /shumengya/docker/storage/ntfy/lib:/var/lib/ntfy \\\n  -p 82:80 \\\n  binwiederhier/ntfy:latest \\\n  serve\n\n\n```\n\n```bash\n#典型的非关系型数据库（json）\ndocker pull binwiederhier/ntfy:latest\n```\n\n```\ndocker stop binwiederhier/ntfy:latest\ndocker rm binwiederhier/ntfy:latest\n```",
  "Docker/优秀好用的Docker镜像/Postgres-数据库.md": "\n```bash\n#postgres数据库\ndocker run -d \\\n  --name postgres \\\n  -e POSTGRES_PASSWORD=shumengya520 \\\n  -e POSTGRES_USER=shumengya \\\n  -e POSTGRES_DB=shumengyadb \\\n  -v /shumengya/docker/storage/postgres:/data \\\n  -e PGDATA=/data/pgdata \\\n  -p 5432:5432 \\\n  --restart=always \\\n  postgres:latest\n\n```\n\n```bash\n#典型的非关系型数据库（json）\ndocker pull postgres:latest\n```\n\n```\ndocker stop postgres:latest\ndocker rm postgres:latest\n```",
  "Docker/优秀好用的Docker镜像/Redis-内存数据库.md": "\n```bash\n#Redis数据库\ndocker run -d --name redis-server \\\n  -p 6379:6379 \\\n  -v /shumengya/docker/storage/redis:/data \\\n  redis:latest \\\n  redis-server --requirepass \"shumengya520\" --appendonly yes\n  \ndocker run -d --name redis-server \\\n  -p 6379:6379 \\\n  -v /shumengya/docker/storage/redis:/data \\\n  redis:latest \\\n  redis-server --requirepass \"shumengya520\" --appendonly yes --save 900 1 --save 300 10 --save 60 10000\n```\n\n```bash\n\ndocker pull redis\n```",
  "Docker/优秀好用的Docker镜像/registry-轻量级自建Docker镜像仓库.md": "\n```bash\n\ndocker run -d \\\n  --name registry \\\n  --restart always \\\n  --cpus=\"1\" \\\n  --memory=\"512m\" \\\n  --log-opt max-size=1m \\\n  --log-opt max-file=3 \\\n  -p 5000:5000 \\\n  -v /shumengya/docker/storage/registry:/var/lib/registry \\\n  -e TZ=Asia/Shanghai \\\n  -e REGISTRY_STORAGE_DELETE_ENABLED=true \\\n  registry:3.0.0\n\n```\n\n```bash\n\n```\n\n```\n\n```",
  "Docker/优秀好用的Docker镜像/SurveyKing-强大的问卷调查服务.md": "\n```bash\ndocker run -d \\\n  -p 1991:1991 \\\n  --memory=4g \\\n  --cpus=4 \\\n  surveyking/surveyking\n\n\n```\n\n```bash\n\n```\n\n```\n\n```",
  "Docker/优秀好用的Docker镜像/tailscale-ip-derp.md": "\n```bash\ndocker run -d \\\n--name derper \\\n-p 33445:13477/tcp \\\n-p 3478:3478/udp \\\n-v /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock \\\n-e DERP_ADDR=\":33445\" \\\n-e DERP_VERIFY_CLIENTS=true \\\nghcr.io/yangchuansheng/ip_derper:latest\n\n\n\n```\n\n```bash\n#典型的非关系型数据库（json）\ndocker pull lanol/filecodebox:beta\n```\n\n```\ndocker stop lanol/filecodebox:beta\ndocker rm lanol/filecodebox:beta\n```",
  "Docker/优秀好用的Docker镜像/模板.md": "\n```bash\n\n\n\n```\n\n```bash\n\n```\n\n```\n\n```",
  "Github/Github仓库公共API总结.md": "\n---\n\n## Releases（发行版本）相关接口\n\n- **获取最新发布版本（Latest Release）**  \n    `GET /repos/{owner}/{repo}/releases/latest`  \n    返回最新非预发布、非草稿版的发布详情，包括版本号、发布时间、说明等。([GitHub Docs](https://docs.github.com/en/rest/releases?utm_source=chatgpt.com \"REST API endpoints for releases and release assets\"))\n    \n- **列出所有发布版本（List Releases）**  \n    `GET /repos/{owner}/{repo}/releases`  \n    返回该仓库所有发布版本的列表，不包含未关联发布的普通 Git 标签。([GitHub Docs](https://docs.github.com/en/rest/releases/releases?utm_source=chatgpt.com \"REST API endpoints for releases\"))\n    \n- **通过 Tag 获取指定发布版本（Get a Release by Tag）**  \n    `GET /repos/{owner}/{repo}/releases/tags/{tag}`  \n    根据具体 tag 名称获取对应发布版本的信息。([GitHub Docs](https://docs.github.com/en/rest/releases?utm_source=chatgpt.com \"REST API endpoints for releases and release assets\"))\n    \n- **创建、更新、删除发布版本（Create / Update / Delete Release）**\n    \n    - `POST /repos/{owner}/{repo}/releases` — 创建新的发布版本\n        \n    - `PATCH /repos/{owner}/{repo}/releases/{release_id}` — 更新发布版本\n        \n    - `DELETE /repos/{owner}/{repo}/releases/{release_id}` — 删除发布版本  \n        （这些操作通常需要认证权限。）([GitHub Docs](https://docs.github.com/en/rest/releases?utm_source=chatgpt.com \"REST API endpoints for releases and release assets\"))\n        \n\n---\n\n## Git Tags（标签）相关接口\n\n- **列出仓库的 Git 标签**  \n    `GET /repos/{owner}/{repo}/tags`  \n    返回该仓库所有标签（包括 lightweight 和 annotated）。([Stack Overflow](https://stackoverflow.com/questions/18384873/how-to-list-the-releases-of-a-repository?utm_source=chatgpt.com \"github - How to list the releases of a repository?\"), [GitHub Docs](https://docs.github.com/en/rest/repos/tags?utm_source=chatgpt.com \"REST API endpoints for repository tags\"))\n    \n- **获取标签引用（Tag Reference）**  \n    `GET /repos/{owner}/{repo}/git/refs/tags/{tag_name}`  \n    可获取该标签所对应的对象（TAG_SHA），用于进一步查询。([Stack Overflow](https://stackoverflow.com/questions/72429056/how-to-get-single-tag-information-using-github-api?utm_source=chatgpt.com \"How to get Single tag Information using GitHub Api?\"))\n    \n- **获取 Annotated Tag 对象详情**  \n    `GET /repos/{owner}/{repo}/git/tags/{tag_sha}`  \n    获取标签对象的完整信息，包括 `object.sha` 即对应的 commit SHA、tagger、message 等。([Stack Overflow](https://stackoverflow.com/questions/72429056/how-to-get-single-tag-information-using-github-api?utm_source=chatgpt.com \"How to get Single tag Information using GitHub Api?\"))\n    \n\n---\n\n## Commits（提交）相关接口\n\n- **列出提交记录（List Commits）**  \n    `GET /repos/{owner}/{repo}/commits`  \n    返回最新的提交列表，第一个通常为最新提交。响应中包含 SHA、作者、提交信息、签名验证信息等。([GitHub Docs](https://docs.github.com/en/rest/commits/commits?utm_source=chatgpt.com \"REST API endpoints for commits\"))\n    \n- **获取单个提交详情（Get a Commit）**  \n    `GET /repos/{owner}/{repo}/commits/{commit_sha}`  \n    获取指定提交的详细信息。([GitHub Docs](https://docs.github.com/en/rest/commits?utm_source=chatgpt.com \"REST API endpoints for commits\"))\n    \n- **比较两个提交（Compare Commits）**  \n    `GET /repos/{owner}/{repo}/compare/{base}...{head}`  \n    用于比较两个 commit 或两个 tag 之间的差异。([Stack Overflow](https://stackoverflow.com/questions/61359461/get-all-commits-in-a-git-tag-through-github-api-return-only-the-first-commit?utm_source=chatgpt.com \"get all commits in a Git tag through GitHub API return only ...\"))\n    \n\n---\n\n## 综合流程示例\n\n下面是一个常见逻辑，例如想获取最新发布对应的 commit SHA：\n\n1. 调用 `GET /repos/{owner}/{repo}/releases/latest` 获取最新 release 的 `tag_name`。\n    \n2. 调用 `GET /repos/{owner}/{repo}/git/refs/tags/{tag_name}` 获取 TAG_SHA。\n    \n3. 调用 `GET /repos/{owner}/{repo}/git/tags/{tag_sha}` 获取该标签对象的 commit SHA（object.sha）。\n    \n\n这套流程常用于从发布版本跳转到对应的 Git 提交。([Stack Overflow](https://stackoverflow.com/questions/67040794/how-can-i-get-the-commit-hash-of-the-latest-release-from-github-api?utm_source=chatgpt.com \"How can I get the commit hash of the latest release from ...\"))\n\n---\n\n## 表格总结\n\n|功能需求|接口路径 / 方法|\n|---|---|\n|最新发布版本信息|`GET /repos/{owner}/{repo}/releases/latest`|\n|列出所有发布版本|`GET /repos/{owner}/{repo}/releases`|\n|通过 tag 查询发布|`GET /repos/{owner}/{repo}/releases/tags/{tag}`|\n|获取标签列表|`GET /repos/{owner}/{repo}/tags`|\n|获取标签引用（TAG_SHA）|`GET /repos/{owner}/{repo}/git/refs/tags/{tag_name}`|\n|获取标签对象详情|`GET /repos/{owner}/{repo}/git/tags/{tag_sha}`|\n|列出提交|`GET /repos/{owner}/{repo}/commits`|\n|获取指定 commit 信息|`GET /repos/{owner}/{repo}/commits/{commit_sha}`|\n|比较两个 commit/tag|`GET /repos/{owner}/{repo}/compare/{base}...{head}`|\n\n---\n\n如果你还希望了解更多，如 API 速率限制、认证方式（匿名 vs token）、分页处理（per_page、page 参数）、使用 GraphQL API 实现同类功能，或具体的 JavaScript `fetch` 调用示例，都可以随时继续讨论！",
  "Github/Github获取仓库密钥.md": "这个地方要注意：\n\n你输入 `git push` 时出现\n\n```\nUsername for 'https://github.com': shumengya\nPassword for 'https://shumengya@github.com':\n```\n\n这里的 **Password** 已经不是 GitHub 登录密码了。\n从 2021 年 8 月开始，GitHub **禁用了账户密码推送**，必须用 **Personal Access Token (PAT)** 或 **SSH Key** 来认证。\n\n---\n\n### ✅ 方案一：生成 Personal Access Token（HTTPS 推荐）\n\n1. 登录 GitHub → 右上角头像 → **Settings**\n2. 左侧栏 → **Developer settings** → **Personal access tokens** → **Tokens (classic)**\n3. 点击 **Generate new token (classic)**\n\n   * 勾选 **repo**（访问和推送仓库必须要有）\n   * 设置有效期（比如 90 天或无期限）\n   * 点击生成\n4. 复制生成的 Token（只会显示一次）\n\n之后推送时：\n\n* **Username**：填 GitHub 用户名（`shumengya`）\n* **Password**：填刚生成的 Token\n\n---\n\n### ✅ 方案二：改用 SSH Key（更方便）\n\n1. 本地生成 SSH Key：\n\n   ```bash\n   ssh-keygen -t ed25519 -C \"你的邮箱\"\n   ```\n\n   按回车保存，默认会在 `~/.ssh/id_ed25519` 和 `~/.ssh/id_ed25519.pub`。\n2. 查看公钥：\n\n   ```bash\n   cat ~/.ssh/id_ed25519.pub\n   ```\n3. 复制内容 → GitHub → **Settings → SSH and GPG keys → New SSH key** → 粘贴保存。\n4. 修改仓库地址为 SSH：\n\n   ```bash\n   git remote set-url origin git@github.com:shumengya/你的仓库名.git\n   ```\n5. 之后直接 `git push` 就不用输密码了。\n\n---\n\n👉 建议你选 **SSH Key**，因为用一次就永久生效，不会过期。\n\n要不要我给你写一份 **完整 SSH Key 配置和测试流程**（从生成到验证）？\n\n",
  "Github/Git常用命令.md": "```shell\r\ngit remote add origin <url>\r\ngit remote add origin https://github.com/shumengya6666666/Pixel-plane-wars.git\r\ngit remote add origin git@github.com:shumengya6666666/Pixel-plane-wars.git\r\ngit remote set-url origin git@github.com:shumengya6666666/Pixel-plane-wars.git\r\ngit clone git@github.com:shumengya6666666/Pixel-plane-wars.git\r\ngit remote add origin git@github.com:shumengya6666666/Pixel-Odyssey.git\r\ngit push -u origin main\r\ngit remote add origin git@github.com:shumengya6666666/Sprout-Farm.git\r\ngit remote set-url origin git@github.com:shumengya6666666/Sprout-Farm.git\r\ngit push -u origin master\r\ngit remote add origin git@github.com:shumengya6666666/Pixel-plane-wars.git\r\n```\r\n\r\n",
  "Github/Git提交临时禁用https.md": "在 Git 中临时禁用 HTTPS 证书认证（主要用于解决自签名证书、证书过期或不可信证书导致的连接问题），可以通过修改 Git 的 http.sslVerify 配置实现\n\n### **1. 单次命令临时禁用（推荐）**\n在执行具体 Git 命令（如 clone、pull、push 等）时，通过 -c 参数临时指定禁用 SSL 验证，仅对当前命令生效：\n\n```bash\n# 示例1：克隆仓库时临时禁用\ngit clone -c http.sslVerify=false https://远程仓库地址.git\n# 示例2：拉取代码时临时禁用\ngit pull -c http.sslVerify=false origin 分支名\n# 示例3：推送代码时临时禁用\ngit push -c http.sslVerify=false origin 分支名\n```\n\n### **2. 当前仓库临时禁用（有效期至手动恢复）**\n如果需要在当前仓库中临时禁用（多次操作生效），可修改当前仓库的局部配置：\n\n```bash\n# 进入仓库目录后执行，禁用当前仓库的HTTPS证书验证\ngit config http.sslVerify false\n# 此时执行 pull/push 等操作会跳过证书验证\ngit pull origin 分支名\n```\n\n**使用完毕后务必恢复验证**（避免长期暴露风险）：\n\n```bash\n# 恢复当前仓库的HTTPS证书验证（默认值）\ngit config http.sslVerify true\n```\n\n### **3. 全局临时禁用（不推荐，影响所有仓库）**\n如果需要对所有仓库临时禁用（不建议，风险较高），可修改全局配置：\n\n```bash\n# 全局禁用（所有仓库生效）\ngit config --global http.sslVerify false\n# 恢复全局默认设置\ngit config --global http.sslVerify true\n```\n\n",
  "Github/Linux下使用git探索.md": "**修改全局代理为http1**\n```\ngit config --global http.version HTTP/1.1\n```\n\n**相当于 git fetch + git merge，会把远程最新提交合并到你当前分支。**\n```\ngit pull\n```\n\n**这会把你的本地提交临时“挪开”，先更新远程提交，然后再把你的提交放回去，避免多余的合并记录。**\n```\ngit pull --rebase\n```\n\n**如果只想下载最新提交但不合并**\n```\ngit fetch\n```\n\n**树萌芽GitHub仓库提交代码通用密钥：**\n```\n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\n```\n\n### 1. 添加所有改动\n```\ngit add .\n```\n### 2. 提交，写上提交说明\n```\ngit commit -m \"更新说明\"\n```\n### 3. 推送到远程仓库（假设分支是 main）\n```\ngit push origin main\n```\n\n\n**压缩成一条命令实现：**\n```\ngit add . && git commit -m \"update\" && git push origin main\n```\n\n**或者设置命令别名，比如写进 ~/.bashrc 或 ~/.zshrc：**\n```\nalias gopush='git add . && git commit -m \"update\" && git push origin main'\n```\n\n\n注意：校园网可能会屏蔽梯子，必要时开热点提交\n\n",
  "Github/linux常用git命令.md": "下面给你整理了一份 **Linux 下常用的 Git 命令速查表**，涵盖从初始化到协作的常见操作：\n\n---\n\n## 🔹 基础配置\n\n```bash\ngit config --global user.name \"你的名字\"        # 设置用户名\ngit config --global user.email \"你的邮箱\"      # 设置邮箱\ngit config --global core.editor \"vim\"          # 设置默认编辑器\ngit config --list                              # 查看当前配置 \n```\n\n---\n\n## 🔹 仓库初始化与克隆\n\n```bash\ngit init                      # 初始化一个本地仓库\ngit clone <repo_url>          # 克隆远程仓库\ngit clone <repo_url> myproj   # 克隆并重命名文件夹\n```\n\n---\n\n## 🔹 文件操作\n\n```bash\ngit status          # 查看仓库当前状态\ngit add <file>      # 添加文件到暂存区\ngit add .           # 添加所有修改到暂存区\ngit reset <file>    # 从暂存区撤销已添加的文件\ngit rm <file>       # 删除文件并记录到暂存区\ngit mv old new      # 重命名文件并记录到暂存区\n```\n\n---\n\n## 🔹 提交相关\n\n```bash\ngit commit -m \"说明\"        # 提交暂存区到仓库\ngit commit -am \"说明\"       # 添加修改并提交（跳过 git add）\ngit log                     # 查看提交历史\ngit log --oneline --graph   # 图形化查看分支提交记录\n```\n\n---\n\n## 🔹 分支操作\n\n```bash\ngit branch                  # 查看分支\ngit branch <name>           # 创建分支\ngit checkout <name>         # 切换分支\ngit checkout -b <name>      # 新建并切换分支\ngit merge <name>            # 合并分支到当前分支\ngit branch -d <name>        # 删除分支\n```\n\n---\n\n## 🔹 远程仓库\n\n```bash\ngit remote -v                           # 查看远程仓库地址\ngit remote add origin <url>             # 添加远程仓库\ngit remote remove origin                # 删除远程仓库\ngit push origin master                  # 推送 master 分支到远程\ngit push -u origin <branch>             # 推送并设置默认分支\ngit pull origin master                  # 拉取远程更新并合并\ngit fetch origin                        # 抓取远程分支（不合并）\n```\n\n---\n\n## 🔹 回退与撤销\n\n```bash\ngit checkout -- <file>      # 撤销工作区修改\ngit reset HEAD <file>       # 取消暂存区文件\ngit reset --hard HEAD~1     # 回退到上一个提交\ngit revert <commit_id>      # 撤销指定提交，生成新提交\n```\n\n---\n\n## 🔹 标签管理\n\n```bash\ngit tag                    # 查看标签\ngit tag v1.0               # 打标签\ngit tag -a v1.0 -m \"说明\"  # 创建附注标签\ngit push origin v1.0       # 推送标签到远程\ngit push origin --tags     # 推送所有标签\n```\n\n---\n\n## 🔹 常用技巧\n\n```bash\ngit stash                  # 临时保存修改\ngit stash pop              # 恢复最近一次保存\ngit diff                   # 查看未暂存的修改\ngit diff --cached          # 查看已暂存的修改\n```\n\n---\n\n\n",
  "LeetCode/力扣-两数之和详解.md": "两数之和问题 - 详细运算过程解析\n\n算法思路回顾\n\n使用哈希表（字典）来存储已经遍历过的数字及其索引，对于每个当前数字，计算其与目标值的差值（补数），并检查该补数是否已经在哈希表中存在。\n\n详细运算过程\n\n让我们通过一个具体例子来详细解析算法的执行过程：\n\n示例： nums = [2, 7, 11, 15], target = 9\n\n初始化阶段\n\n```python\nnum_map = {}  # 创建一个空字典用于存储数字和索引的映射\n```\n\n第一次迭代 (i=0, num=2)\n\n1. 计算补数：complement = target - num = 9 - 2 = 7\n2. 检查补数7是否在num_map中：7 in num_map → 结果为False（因为字典为空）\n3. 将当前数字和索引存入字典：num_map[2] = 0\n4. 此时字典状态：{2: 0}\n\n第二次迭代 (i=1, num=7)\n\n1. 计算补数：complement = target - num = 9 - 7 = 2\n2. 检查补数2是否在num_map中：2 in num_map → 结果为True（因为字典中有键2）\n3. 找到匹配，返回结果：[num_map[2], 1] → [0, 1]\n4. 算法结束，返回结果[0, 1]\n\n运算过程可视化\n\n迭代次数 当前索引(i) 当前值(num) 补数(complement) 补数是否在num_map中 num_map更新 操作说明\n1 0 2 7 否 {2:0} 将2和索引0存入字典\n2 1 7 2 是 - 找到匹配，返回[0,1]\n\n关键点解析\n\n1. 补数计算：对于每个数字，计算target - num得到补数，这个补数就是我们需要在之前遍历过的数字中寻找的值。\n2. 哈希表的作用：哈希表用于存储已经遍历过的数字及其索引，这样可以在O(1)时间内检查补数是否存在。\n3. 顺序重要性：算法先检查补数是否存在，然后再将当前数字存入字典，这样可以确保不会使用同一个元素两次。\n4. 时间复杂度：每个元素只被访问一次，哈希表的插入和查找操作平均时间复杂度为O(1)，因此总时间复杂度为O(n)。\n5. 空间复杂度：最坏情况下需要存储所有n个元素，因此空间复杂度为O(n)。\n\n为什么这种方法有效？\n\n这种方法有效的关键在于利用了数学关系：如果a + b = target，那么target - a = b。通过存储已经遍历过的数字，我们可以快速检查当前数字的补数是否已经出现过。\n\n这种方法比暴力解法（双重循环）高效得多，将时间复杂度从O(n²)降低到O(n)，是典型的\"以空间换时间\"策略。\n\n边界情况处理\n\n虽然题目保证有解，但实际应用中可能需要考虑无解的情况。我们的代码在无解时会返回空列表，这是一种合理的处理方式。\n\n这种算法设计简洁高效，是解决两数之和问题的标准方法，被广泛应用于各种编程面试和实际开发中。",
  "LeetCode/力扣1-两数相加问题.md": "两数相加问题\n\n问题描述\n\n给定两个非空链表，表示两个非负整数。每位数字按照逆序方式存储，每个节点存储一位数字。将两个数相加，并以相同形式返回表示和的链表。\n\n假设除了数字0之外，这两个数都不会以0开头。\n\n示例\n\n示例 1：\n\n```\n输入：l1 = [2,4,3], l2 = [5,6,4]\n输出：[7,0,8]\n解释：342 + 465 = 807\n```\n\n示例 2：\n\n```\n输入：l1 = [0], l2 = [0]\n输出：[0]\n```\n\n示例 3：\n\n```\n输入：l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]\n输出：[8,9,9,9,0,0,0,1]\n```\n\n提示\n\n· 每个链表中的节点数在范围 [1, 100] 内\n· 0 <= Node.val <= 9\n· 题目数据保证列表表示的数字不含前导零\n\n方法思路\n\n问题分析\n\n两个链表表示的数字是逆序存储的，即链表的头节点表示个位数，第二个节点表示十位数，以此类推。我们需要模拟加法运算，从低位到高位逐位相加，并处理进位问题。\n\n算法选择\n\n· 使用一个虚拟头节点(dummy node)简化链表操作\n· 同时遍历两个链表，逐位相加并处理进位\n· 如果链表长度不同，较短链表的缺失位视为0\n· 最后如果还有进位，需要额外创建一个节点\n\n算法步骤\n\n1. 初始化虚拟头节点和当前指针\n2. 初始化进位值为0\n3. 同时遍历两个链表，直到两个链表都遍历完且没有进位\n4. 计算当前位的和：两个链表当前节点的值加上进位\n5. 计算新的进位和当前位的值\n6. 创建新节点并连接到结果链表\n7. 移动所有指针到下一个位置\n8. 返回虚拟头节点的下一个节点\n\n复杂度分析\n\n· 时间复杂度：O(max(m, n))，其中m和n分别是两个链表的长度\n· 空间复杂度：O(max(m, n))，结果链表的长度最多为max(m, n) + 1\n\n解决代码\n\n```python\n# Definition for singly-linked list.\nclass ListNode:\n    def __init__(self, val=0, next=None):\n        self.val = val\n        self.next = next\n\nclass Solution:\n    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:\n        \"\"\"\n        将两个逆序存储的数字链表相加，返回结果链表\n        \n        参数:\n        l1: ListNode - 第一个数字链表\n        l2: ListNode - 第二个数字链表\n        \n        返回:\n        ListNode - 相加结果的链表\n        \"\"\"\n        dummy = ListNode(0)  # 虚拟头节点\n        current = dummy      # 当前指针\n        carry = 0            # 进位值\n        \n        # 遍历两个链表，直到两个链表都为空且没有进位\n        while l1 or l2 or carry:\n            # 获取当前节点的值，如果节点为空则为0\n            val1 = l1.val if l1 else 0\n            val2 = l2.val if l2 else 0\n            \n            # 计算当前位的和\n            total = val1 + val2 + carry\n            carry = total // 10  # 计算进位\n            digit = total % 10   # 计算当前位的值\n            \n            # 创建新节点并连接到结果链表\n            current.next = ListNode(digit)\n            current = current.next\n            \n            # 移动到下一个节点\n            if l1:\n                l1 = l1.next\n            if l2:\n                l2 = l2.next\n        \n        return dummy.next  # 返回结果链表的头节点\n```\n\n代码解释\n\n1. 链表节点定义：ListNode类定义了链表节点的结构，包含值val和指向下一个节点的指针next。\n2. 初始化：\n   · 创建虚拟头节点dummy，简化链表操作\n   · 设置当前指针current指向虚拟头节点\n   · 初始化进位carry为0\n3. 循环处理：\n   · 使用while循环遍历两个链表，直到两个链表都遍历完且没有进位\n   · 循环条件l1 or l2 or carry确保处理所有情况\n4. 获取当前值：\n   · 如果链表节点存在，获取其值；否则视为0\n   · 这样可以处理链表长度不同的情况\n5. 计算和与进位：\n   · 计算当前位的总和：val1 + val2 + carry\n   · 计算新的进位：total // 10\n   · 计算当前位的值：total % 10\n6. 创建新节点：\n   · 根据当前位的值创建新节点\n   · 将新节点连接到结果链表\n   · 移动当前指针到新节点\n7. 移动指针：\n   · 如果链表还有节点，移动到下一个节点\n   · 这样可以继续处理后续位\n8. 返回结果：\n   · 返回虚拟头节点的下一个节点，即结果链表的头节点\n   · 虚拟头节点简化了链表操作，避免处理空链表的情况\n\n示例验证\n\n以示例1为例：l1 = [2,4,3] (表示342)，l2 = [5,6,4] (表示465)\n\n1. 个位：2 + 5 = 7，进位0 → 结果个位7\n2. 十位：4 + 6 = 10，进位1 → 结果十位0\n3. 百位：3 + 4 + 1 = 8，进位0 → 结果百位8\n\n最终结果为[7,0,8] (表示807)，符合预期。\n\n这种方法高效地处理了链表相加的问题，考虑了所有边界情况，包括链表长度不同和最后有进位的情况。",
  "LeetCode/力扣2-两数之和.md": "两数之和问题\n\n问题描述\n\n给定一个整数数组 nums 和一个整数目标值 target，请你在该数组中找出和为目标值 target 的那两个整数，并返回它们的数组下标。\n\n你可以假设每种输入只会对应一个答案，并且你不能使用两次相同的元素。你可以按任意顺序返回答案。\n\n示例 1：\n\n```\n输入：nums = [2,7,11,15], target = 9\n输出：[0,1]\n解释：因为 nums[0] + nums[1] == 9，返回 [0, 1]。\n```\n\n示例 2：\n\n```\n输入：nums = [3,2,4], target = 6\n输出：[1,2]\n```\n\n示例 3：\n\n```\n输入：nums = [3,3], target = 6\n输出：[0,1]\n```\n\n提示：\n\n· 2 <= nums.length <= 10^4\n· -10^9 <= nums[i] <= 10^9\n· -10^9 <= target <= 10^9\n· 只会存在一个有效答案\n\n方法思路\n\n1. 问题分析\n\n我们需要在数组中找到两个不同的元素，它们的和等于目标值。由于数组可能很大，暴力解法（双重循环）的时间复杂度为O(n²)，效率太低。\n\n2. 算法选择\n\n使用哈希表来存储每个元素及其索引，这样可以在O(1)时间内检查目标值与当前元素的差值是否存在于哈希表中。\n\n3. 算法步骤\n\n1. 初始化一个空哈希表（字典）\n2. 遍历数组中的每个元素及其索引\n3. 对于每个元素，计算目标值与当前元素的差值（补数）\n4. 检查该差值是否已存在于哈希表中\n5. 如果存在，返回当前索引和差值的索引\n6. 如果不存在，将当前元素及其索引存入哈希表\n\n4. 复杂度分析\n\n· 时间复杂度：O(n)，只需遍历数组一次\n· 空间复杂度：O(n)，用于存储哈希表\n\n解决代码\n\n```python\ndef twoSum(nums, target):\n    \"\"\"\n    在给定数组中找出和为目标值的两个整数的索引\n    \n    参数:\n    nums: List[int] - 整数数组\n    target: int - 目标值\n    \n    返回:\n    List[int] - 两个整数的索引列表\n    \"\"\"\n    num_map = {}  # 创建空字典存储数字和索引的映射\n    for i, num in enumerate(nums):  # 遍历数组，获取索引和数值\n        complement = target - num  # 计算补数\n        if complement in num_map:  # 检查补数是否在字典中\n            return [num_map[complement], i]  # 如果在，返回两个索引\n        num_map[num] = i  # 如果不在，将当前数字和索引存入字典\n    return []  # 如果没有找到，返回空列表（但题目保证有解，所以不会执行到这里）\n    \n#最简单方法\nclass Solution:\n    def twoSum(self, nums: List[int], target: int) -> List[int]:\n       n=len(nums)\n       for i in range(n):\n           for j in range(i+1,n):\n               if nums[i]+nums[j]==target:\n                   return[i,j]\n       return[]\n           \n```\n\n代码解释\n\n1. 初始化哈希表：num_map 用于存储元素值到索引的映射\n2. 遍历数组：使用 enumerate 函数同时获取元素的索引 i 和数值 num\n3. 计算补数：对于每个 num，计算 complement = target - num\n4. 检查补数是否存在：如果补数存在于哈希表中，说明找到了两个数，返回它们的索引\n5. 存储当前元素：如果补数不存在，将当前元素及其索引存入哈希表，以便后续查找\n6. 返回结果：如果遍历结束仍未找到，返回空列表（但题目保证有解，所以不会执行到此）\n\n",
  "Linux/ADB/ADB常用命令.md": "\n\n### 1. **基本命令**\n\n- **连接设备**\n    ```bash\n    adb devices\n    ```\n    \n    列出连接的设备，显示设备ID和状态。\n    \n- **启动ADB服务器**\n    ```bash\n    adb start-server\n    ```\n    \n    启动ADB服务。\n    \n- **停止ADB服务器**\n    ```bash\n    adb kill-server\n    ```\n    \n    停止ADB服务。\n    \n\n### 2. **设备管理**\n\n- **查看设备信息**\n    ```bash\n    adb shell getprop\n    ```\n    \n    获取设备的各种信息（如型号、Android版本等）。\n    \n- **重启设备**\n    ```bash\n    adb reboot\n    ```\n    \n    重新启动设备。\n    \n- **重启到bootloader**\n    ```bash\n    adb reboot bootloader\n    ```\n    \n    将设备重启到bootloader模式（用于解锁、刷机等）。\n    \n- **进入恢复模式**\n    ```bash\n    adb reboot recovery\n    ```\n    \n    重新启动设备并进入恢复模式。\n    \n\n### 3. **文件传输**\n\n- **从设备拷贝文件到电脑**\n    ```bash\n    adb pull <设备路径> <本地路径>\n    ```\n    \n    例如：\n    \n    ```bash\n    adb pull /sdcard/test.txt ./test.txt\n    ```\n    \n- **从电脑拷贝文件到设备**\n    ```bash\n    adb push <本地路径> <设备路径>\n    ```\n    \n    例如：\n    \n    ```bash\n    adb push test.txt /sdcard/\n    ```\n    \n\n### 4. **执行命令**\n\n- **进入设备的Shell**\n    ```bash\n    adb shell\n    ```\n    \n    进入设备的命令行界面，可以执行Linux命令。\n    \n- **执行单个命令**\n    ```bash\n    adb shell <命令>\n    ```\n    \n    例如，查看设备的文件系统：\n    \n    ```bash\n    adb shell ls /sdcard/\n    ```\n    \n\n### 5. **应用管理**\n\n- **安装应用**\n    ```bash\n    adb install <apk文件路径>\n    ```\n    \n    例如：\n    \n    ```bash\n    adb install app.apk\n    ```\n    \n- **卸载应用**\n    ```bash\n    adb uninstall <包名>\n    ```\n    \n    例如：\n    \n    ```bash\n    adb uninstall com.example.app\n    ```\n    \n- **列出所有已安装的应用**\n    ```bash\n    adb shell pm list packages\n    ```\n    \n- **清除应用数据**\n    ```bash\n    adb shell pm clear <包名>\n    ```\n    \n    例如：\n    \n    ```bash\n    adb shell pm clear com.example.app\n    ```\n    \n\n### 6. **日志与调试**\n\n- **查看日志输出**\n    ```bash\n    adb logcat\n    ```\n    \n    实时显示设备的日志输出，常用于调试。\n    \n- **过滤日志**\n    ```bash\n    adb logcat <标签>:<等级>\n    ```\n    \n    例如：\n    \n    ```bash\n    adb logcat *:E\n    ```\n    \n    显示所有错误级别（Error）及以上的日志。\n    \n- **查看设备的进程**\n    ```bash\n    adb shell ps\n    ```\n    \n\n### 7. **屏幕截图与录屏**\n\n- **截取屏幕截图**\n    \n    ```bash\n    adb shell screencap /sdcard/screenshot.png\n    ```\n    \n    将截图保存到设备存储中。\n    \n- **录制屏幕视频**\n    ```bash\n    adb shell screenrecord /sdcard/demo.mp4\n    ```\n    \n\n### 8. **开发与调试**\n\n- **开启开发者选项与USB调试**  \n    需要在设备的设置里开启开发者选项，并启用USB调试。\n    \n- **远程调试**\n    ```bash\n    adb tcpip 5555\n    ```\n    \n    让设备进入无线调试模式（通过IP连接设备）。\n    \n- **连接到指定IP设备**\n    ```bash\n    adb connect <设备IP>:5555\n    ```\n    \n\n### 9. **设备状态与操作**\n\n- **查看设备状态**\n    ```bash\n    adb devices -l\n    ```\n    \n- **查看设备的存储**\n    ```bash\n    adb shell df\n    ```\n    \n- **获取设备电池状态**\n    ```bash\n    adb shell dumpsys battery\n    ```\n    \n\n### 10. **其他常用命令**\n\n- **获取设备信息（硬件、系统信息）**\n    ```bash\n    adb shell dumpsys\n    ```\n    \n- **查看设备的CPU使用情况**\n    ```bash\n    adb shell top\n    ```\n    \n",
  "Linux/ADB/某安卓板子不知名初始化脚本.md": "adb push busybox /tmp\nadb shell\ncd /tmp\nchmod 777 *\n./busybox ifconfig wlan0 up\n\n人总是孤独的，不要去搞过于偏门的东西，大学时间很有限，不要花太多时间在一些虚无缥缈的东西上\n",
  "Linux/busybox v1.36命令简介.md": "以下是针对 **BusyBox** 中每条命令的简要说明：\n\n1. **[**：测试表达式的真假。\n2. **[[**：增强版的条件测试命令。\n3. **acpid**：管理系统的 ACPI 事件。\n4. **adjtimex**：调整系统时间。\n5. **ar**：创建、修改、提取归档文件。\n6. **arch**：显示机器架构类型。\n7. **arp**：显示或修改 ARP 缓存。\n8. **arping**：向网络发送 ARP 请求。\n9. **ascii**：显示 ASCII 表。\n10. **ash**：一个轻量级的 shell。\n11. **awk**：强大的文本处理工具。\n12. **base32**：以 Base32 编码格式进行数据转换。\n13. **base64**：以 Base64 编码格式进行数据转换。\n14. **basename**：从路径中提取文件名。\n15. **bbconfig**：配置 BusyBox。\n16. **beep**：产生蜂鸣声。\n17. **blkdiscard**：丢弃磁盘块。\n18. **blkid**：显示块设备的标识。\n19. **blockdev**：对块设备进行操作。\n20. **brctl**：管理网桥接口。\n21. **bunzip2**：解压 `.bz2` 格式文件。\n22. **bzcat**：查看 `.bz2` 格式文件内容。\n23. **bzip2**：压缩文件为 `.bz2` 格式。\n24. **cal**：显示日历。\n25. **cat**：连接文件并显示内容。\n26. **chat**：发送控制字符以进行调制解调器通信。\n27. **chattr**：改变文件的属性。\n28. **chcon**：改变文件的 SELinux 上下文。\n29. **chgrp**：改变文件的组。\n30. **chmod**：改变文件的权限。\n31. **chown**：改变文件的拥有者。\n32. **chroot**：改变根目录。\n33. **chrt**：操作进程的调度策略。\n34. **chvt**：切换虚拟终端。\n35. **cksum**：计算文件的校验和。\n36. **clear**：清除终端屏幕。\n37. **cmp**：比较两个文件。\n38. **comm**：比较两个已排序文件的内容。\n39. **conspy**：查看控制台的输出。\n40. **cp**：复制文件。\n41. **cpio**：创建、解压 cpio 格式归档。\n42. **crc32**：计算 CRC32 校验和。\n43. **crond**：周期性执行任务的守护进程。\n44. **crontab**：编辑 cron 表。\n45. **cttyhack**：改变控制终端。\n46. **cut**：按列剪切文本。\n47. **date**：显示或设置系统日期和时间。\n48. **dc**：计算器程序。\n49. **dd**：转换和复制文件。\n50. **deallocvt**：释放虚拟终端。\n51. **depmod**：生成内核模块依赖关系。\n52. **devmem**：访问物理内存。\n53. **df**：显示文件系统的磁盘空间使用情况。\n54. **dhcprelay**：转发 DHCP 请求。\n55. **diff**：比较文件的不同之处。\n56. **dirname**：获取路径的目录部分。\n57. **dmesg**：显示内核的消息缓冲区内容。\n58. **dnsd**：轻量级 DNS 服务器。\n59. **dnsdomainname**：显示域名。\n60. **dos2unix**：转换 DOS 格式文本为 Unix 格式。\n61. **du**：显示磁盘使用情况。\n62. **dumpkmap**：转储键盘映射。\n63. **dumpleases**：显示 DHCP 租约。\n64. **echo**：显示一行文本。\n65. **ed**：文本编辑器。\n66. **egrep**：扩展正则表达式的 grep 命令。\n67. **eject**：弹出光盘。\n68. **env**：显示或设置环境变量。\n69. **ether-wake**：发送 Wake-on-LAN 魔术包。\n70. **expand**：将制表符转换为空格。\n71. **expr**：计算表达式的值。\n72. **factor**：因数分解。\n73. **fakeidentd**：模拟 identd 服务。\n74. **false**：返回失败状态。\n75. **fatattr**：显示或修改 FAT 文件系统的属性。\n76. **fbset**：设置帧缓冲设备的参数。\n77. **fbsplash**：管理帧缓冲启动画面。\n78. **fdflush**：刷新文件描述符。\n79. **fdformat**：格式化软盘。\n80. **fdisk**：管理磁盘分区。 \n81. **fgconsole**：切换到指定的虚拟终端。\n82. **fgrep**：固定字符串搜索工具。\n83. **find**：搜索文件。\n84. **findfs**：查找文件系统。\n85. **flash_eraseall**：擦除闪存设备。\n86. **flash_lock**：锁定闪存设备。\n87. **flash_unlock**：解锁闪存设备。\n88. **flock**：对文件进行锁定。\n89. **fold**：折叠文本行。\n90. **free**：显示内存使用情况。\n91. **freeramdisk**：释放 RAM 磁盘。\n92. **fsck**：检查文件系统的完整性。\n93. **fsck.minix**：检查 Minix 文件系统。\n94. **fsfreeze**：冻结文件系统以进行备份。\n95. **fstrim**：修剪未使用的磁盘空间。\n96. **fsync**：强制磁盘同步。\n97. **ftpd**：启动 FTP 服务器。\n98. **ftpget**：下载文件通过 FTP。\n99. **ftpput**：上传文件通过 FTP。\n100. **fuser**：显示正在使用某个文件的进程。\n101. **getenforce**：显示 SELinux 的状态。\n102. **getopt**：解析命令行选项。\n103. **grep**：搜索文本中的模式。\n104. **groups**：显示用户所属的组。\n105. **gunzip**：解压 `.gz` 文件。\n106. **gzip**：压缩文件为 `.gz` 格式。\n107. **hd**：显示硬盘的分区信息。\n108. **hdparm**：设置硬盘参数。\n109. **head**：显示文件的开头部分。\n110. **hexdump**：以十六进制格式显示文件内容。\n111. **hexedit**：编辑十六进制文件。\n112. **hostname**：显示或设置主机名。\n113. **httpd**：启动 HTTP 服务器。\n114. **hush**：一个小型 shell。\n115. **hwclock**：访问硬件时钟。\n116. **id**：显示用户和组信息。\n117. **ifconfig**：配置网络接口。\n118. **ifdown**：关闭网络接口。\n119. **ifenslave**：配置链路聚合。\n120. **ifplugd**：监控网络接口的连接状态。\n121. **ifup**：启用网络接口。\n122. **inetd**：启动网络服务守护进程。\n123. **inotifyd**：启动文件系统事件监控。\n124. **insmod**：加载内核模块。\n125. **install**：复制文件并设置权限。\n126. **ionice**：设置进程的 I/O 优先级。\n127. **iostat**：显示 CPU 和 I/O 统计信息。\n128. **ip**：配置网络接口和路由。\n129. **ipaddr**：显示或设置 IP 地址。\n130. **ipcalc**：计算和显示 IP 地址信息。\n131. **ipcrm**：删除共享内存、消息队列、信号量。\n132. **ipcs**：显示进程间通信的状态。\n133. **iplink**：管理网络接口的状态。\n134. **ipneigh**：显示邻居表。\n135. **iproute**：管理路由表。\n136. **iprule**：显示或管理路由规则。\n137. **iptunnel**：配置 IP 隧道。\n138. **kbd_mode**：设置键盘模式。\n139. **kill**：终止进程。\n140. **killall**：终止指定名称的所有进程。\n141. **killall5**：终止所有进程。\n142. **klogd**：内核日志守护进程。\n143. **less**：分页显示文件内容。\n144. **link**：创建硬链接。\n145. **ln**：创建硬链接或符号链接。\n146. **loadfont**：加载字体。\n147. **loadkmap**：加载键盘映射。\n148. **logread**：显示日志文件内容。\n149. **losetup**：管理环回设备。\n150. **ls**：列出目录内容。\n\n\n151. **lsattr**：显示文件的属性。\n152. **lsmod**：显示加载的内核模块。\n153. **lsof**：列出打开的文件。\n154. **lspci**：显示所有 PCI 设备。\n155. **lsscsi**：显示 SCSI 设备信息。\n156. **lsusb**：列出 USB 设备。\n157. **lzcat**：解压 `.lz` 文件并显示内容。\n158. **lzma**：压缩文件为 `.lzma` 格式。\n159. **lzop**：快速的文件压缩工具。\n160. **lzopcat**：查看 `.lzo` 格式文件内容。\n161. **makedevs**：创建设备节点。\n162. **makemime**：生成 MIME 类型文件。\n163. **man**：查看手册页（如果有）。\n164. **md5sum**：计算文件的 MD5 校验和。\n165. **mesg**：控制终端消息的接收。\n166. **microcom**：串行通信工具。\n167. **mim**：提取文件的 MIME 类型。\n168. **mkdir**：创建目录。\n169. **mkdosfs**：创建 FAT 文件系统。\n170. **mke2fs**：创建 ext2 文件系统。\n171. **mkfifo**：创建命名管道。\n172. **mkfs.ext2**：创建 ext2 文件系统。\n173. **mkfs.minix**：创建 Minix 文件系统。\n174. **mkfs.reiser**：创建 Reiser 文件系统。\n175. **mkfs.vfat**：创建 VFAT 文件系统。\n176. **mknod**：创建块设备或字符设备文件。\n177. **mkswap**：创建交换分区。\n178. **mktemp**：创建临时文件。\n179. **modinfo**：显示内核模块的信息。\n180. **modprobe**：加载或卸载内核模块。\n181. **more**：分页显示文件内容。\n182. **mount**：挂载文件系统。\n183. **mountpoint**：检查是否为挂载点。\n184. **mpstat**：显示 CPU 使用统计信息。\n185. **mv**：移动或重命名文件。\n186. **nameif**：根据 MAC 地址设置网络接口名称。\n187. **nanddump**：转储 NAND 闪存的内容。\n188. **nandwrite**：将数据写入 NAND 闪存。\n189. **nbd-client**：连接到网络块设备。\n190. **nc**：Netcat 工具，用于读写网络连接。\n191. **netstat**：显示网络连接状态。\n192. **nice**：调整进程的优先级。\n193. **nl**：显示带有行号的文件内容。\n194. **nmeter**：网络带宽监控工具。\n195. **nohup**：在后台运行命令并忽略挂起信号。\n196. **nologin**：禁止用户登录。\n197. **nsenter**：进入其他命名空间。\n198. **nslookup**：查询 DNS 信息。\n199. **nuke**：终止所有与特定进程相关的网络连接。\n200. **od**：以不同格式显示文件内容（如十六进制）。\n201. **openvt**：在指定的虚拟终端上运行命令。\n202. **partprobe**：通知操作系统重新读取分区表。\n203. **paste**：合并多个文件按列显示。\n204. **patch**：应用补丁文件。\n205. **pgrep**：查找匹配指定模式的进程。\n206. **pidof**：查找指定进程的 PID。\n207. **ping**：向网络主机发送 ICMP 请求。\n208. **ping6**：向网络主机发送 ICMPv6 请求。\n209. **pipe_progress**：显示管道中的数据传输进度。\n210. **pivot_root**：更改文件系统根目录。\n211. **pkill**：根据进程名终止进程。\n212. **pmap**：显示进程的内存映射。\n213. **popmaildir**：从邮件目录中获取邮件。\n214. **poweroff**：关闭计算机。\n215. **powertop**：用于优化电源管理的工具。\n216. **printenv**：显示所有环境变量。\n217. **printf**：格式化并输出文本。\n218. **ps**：显示当前进程信息。\n219. **pscan**：扫描当前进程的状态。\n220. **pstree**：以树形结构显示进程。\n221. **pwd**：显示当前工作目录。\n222. **pwdx**：显示指定进程的工作目录。\n223. **raidautorun**：自动启动 RAID 配置。\n224. **rdate**：同步时间。\n225. **rdev**：显示或设置设备的特殊属性。\n226. **readlink**：显示符号链接的目标。\n227. **readprofile**：读取并显示应用的性能配置。\n228. **realpath**：返回文件的绝对路径。\n229. **reboot**：重启系统。\n230. **reformime**：转换 MIME 格式。\n231. **renice**：改变进程的优先级。\n232. **reset**：重置终端。\n233. **resize**：调整终端大小。\n234. **resume**：恢复挂起的进程。\n235. **rev**：反转每行文本。\n236. **rfkill**：管理无线设备的开关。\n237. **rm**：删除文件。\n238. **rmdir**：删除空目录。\n239. **rmmod**：卸载内核模块。\n240. **route**：显示或修改路由表。\n241. **rtcwake**：设置系统的 RTC 来定时唤醒。\n242. **run-init**：运行初始化程序。\n243. **run-parts**：按顺序运行目录中的脚本。\n244. **runcon**：设置进程的 SELinux 上下文。\n245. **rx**：接收串口数据。\n246. **script**：记录终端会话。\n247. **scriptreplay**：重放记录的终端会话。\n248. **sed**：流编辑器，用于处理文本数据。\n249. **seedrng**：种子随机数生成器。\n250. **selinuxenabled**：检查 SELinux 是否启用。\n251. **sendmail**：发送电子邮件。\n252. **seq**：生成一个数字序列。\n253. **sestatus**：显示 SELinux 状态。\n254. **setconsole**：设置控制台的终端类型。\n255. **setenforce**：启用或禁用 SELinux 强制模式。\n256. **setfattr**：设置文件的扩展属性。\n257. **setfont**：设置终端的字体。\n258. **setkeycodes**：设置键盘扫描码到键值的映射。\n259. **setlogcons**：设置日志控制台。\n260. **setpriv**：设置进程的特权级别。\n261. **setserial**：设置串口设备的参数。\n262. **setsid**：创建新的会话并运行命令。\n263. **setuidgid**：设置进程的用户和组标识。\n264. **sh**：启动一个新的 shell。\n265. **sha1sum**：计算文件的 SHA-1 校验和。\n266. **sha256sum**：计算文件的 SHA-256 校验和。\n267. **sha3sum**：计算文件的 SHA-3 校验和。\n268. **sha512sum**：计算文件的 SHA-512 校验和。\n269. **showkey**：显示键盘输入的键值。\n270. **shred**：擦除文件，防止数据恢复。\n271. **shuf**：随机排列输入行。\n272. **slattach**：设置串行连接。\n273. **sleep**：暂停一段时间。\n274. **smemcap**：设置进程内存使用限制。\n275. **sort**：按行排序文本文件。\n276. **split**：将文件分割成多个小文件。\n277. **ssl_client**：通过 SSL 连接远程主机。\n278. **start-stop-daemon**：启动或停止后台守护进程。\n279. **stat**：显示文件或文件系统的状态。\n280. **strings**：显示文件中的可打印字符串。\n281. **stty**：设置终端行属性。\n282. **sum**：计算文件的校验和。\n283. **svc**：启动、停止或重启服务。\n284. **svok**：检查服务的状态。\n285. **swapoff**：禁用交换空间。\n286. **swapon**：启用交换空间。\n287. **switch_root**：切换到新的根文件系统。\n288. **sync**：同步文件系统。\n289. **sysctl**：显示或设置内核参数。\n290. **syslogd**：启动系统日志守护进程。\n291. **tac**：反向显示文件内容。\n292. **tail**：显示文件的最后部分。\n293. **tar**：创建和解压 tar 归档。\n\n294. **tc**：配置网络流量控制。\n295. **tcpsvd**：TCP 服务守护进程。\n296. **tee**：将输入内容输出到多个文件。\n297. **telnet**：远程登录到另一个计算机。\n298. **telnetd**：启动 Telnet 服务器。\n299. **test**：检查条件的真假。\n300. **tftp**：简易的文件传输协议客户端。\n301. **tftpd**：TFTP 服务器。\n302. **time**：测量命令执行时间。\n303. **timeout**：设置命令的超时时间。\n304. **top**：显示系统进程信息。\n305. **touch**：创建空文件或更新文件的时间戳。\n306. **tr**：替换或删除字符。\n307. **traceroute**：追踪数据包在网络中的路由。\n308. **traceroute6**：追踪 IPv6 数据包的路由。\n309. **tree**：以树形结构显示目录内容。\n310. **true**：始终返回成功状态。\n311. **truncate**：截断文件到指定长度。\n312. **ts**：为每行添加时间戳。\n313. **tsort**：排序文件中的时间戳。\n314. **tty**：显示终端设备名称。\n315. **ttysize**：显示终端的大小。\n316. **tunctl**：管理 TUN/TAP 网络设备。\n317. **tune2fs**：调整 ext2/ext3/ext4 文件系统的参数。\n318. **ubiattach**：附加 UBI 设备。\n319. **ubidetach**：分离 UBI 设备。\n320. **ubimkvol**：创建 UBI 卷。\n321. **ubirename**：重命名 UBI 卷。\n322. **ubirmvol**：删除 UBI 卷。\n323. **ubirsvol**：恢复 UBI 卷。\n324. **ubiupdatevol**：更新 UBI 卷的数据。\n325. **udhcpc**：DHCP 客户端，用于获取网络配置信息。\n326. **udhcpc6**：DHCPv6 客户端。\n327. **udhcpd**：DHCP 服务器。\n328. **udpsvd**：UDP 服务守护进程。\n329. **uevent**：显示系统的 udev 事件。\n330. **umount**：卸载文件系统。\n331. **uname**：显示系统信息。\n332. **uncompress**：解压 `.Z` 格式文件。\n333. **unexpand**：将空格转换为制表符。\n334. **uniq**：删除重复的行。\n335. **unix2dos**：转换 Unix 格式文本为 DOS 格式。\n336. **unlink**：删除文件。\n337. **unlzma**：解压 `.lzma` 格式文件。\n338. **unlzop**：解压 `.lzo` 格式文件。\n339. **unshare**：在新命名空间中运行命令。\n340. **unxz**：解压 `.xz` 格式文件。\n341. **unzip**：解压 `.zip` 文件。\n342. **uptime**：显示系统的运行时间和负载。\n343. **usleep**：暂停指定的微秒数。\n344. **uudecode**：解码 `.uu` 格式文件。\n345. **uuencode**：编码文件为 `.uu` 格式。\n346. **vconfig**：管理 VLAN 网络接口。\n347. **vi**：文本编辑器。\n348. **volname**：显示文件系统的卷标。\n349. **watch**：定期执行并显示命令输出。\n350. **watchdog**：监控系统状态并在需要时重启。\n351. **wc**：计算文件的行数、字数和字符数。\n352. **wget**：下载文件。\n353. **which**：显示可执行文件的路径。\n354. **whoami**：显示当前用户的用户名。\n355. **whois**：查询域名注册信息。\n356. **xargs**：将标准输入转换为命令行参数。\n357. **xxd**：创建十六进制转储。\n358. **xz**：压缩文件为 `.xz` 格式。\n359. **xzcat**：查看 `.xz` 格式文件内容。\n360. **yes**：输出指定字符串，通常用来测试管道。\n361. **zcat**：查看 `.gz` 格式文件内容。\n362. **zcip**：配置 ZCIP 地址。\n\n这些命令覆盖了文件操作、系统管理、网络配置、进程管理等多个方面，是 BusyBox 在资源受限环境中为用户提供常用功能的集合。\n",
  "Linux/busybox玩法总结.md": "### 一句命令启动busybox的简单http服务器\n\n```shell\nbusybox httpd -f -p 端口 -h 目录\n```\n\n### 查看端口占用情况\n\n- `-t`：显示 TCP 连接\n- `-u`：显示 UDP 连接\n- `-l`：只显示正在监听的端口\n- `-n`：显示数字形式的地址和端口号，而不进行域名解析\n\n```shell\nbusybox netstat -tuln\n```\n\n### 启动busybox的ftp服务器\n\n```shell\nbusybox ftp -d 目录 -p 端口\nbusybox ftp -d 目录 #默认占用21端口\n\nsudo mkdir -p 目录\nsudo chmod 755 目录\n\n```\n\n### 启动 `busybox` 的 Telnet 服务器\n\n```\nbusybox telnetd -l /bin/login\nbusybox telnetd -p 2323 -l /bin/login\n\n```\n\n",
  "Linux/crontab的使用.md": "`crontab` 是一个用于在 Unix 和类 Unix 系统（如 Linux）中设置定时任务的工具。它允许用户根据指定的时间间隔安排脚本或命令的执行。\n> 目前我用来代替 systemctl的服务\n\n### 基本概念\n`crontab` 的配置文件由一系列行组成，每行代表一个定时任务，其基本格式如下：\n```plaintext\n* * * * * command\n```\n这五个 `*` 分别代表分钟（0 - 59）、小时（0 - 23）、日期（1 - 31）、月份（1 - 12）和星期（0 - 7，其中 0 和 7 都代表星期日），`command` 是要执行的命令或脚本。\n\n### 使用步骤\n\n#### 1. 编辑 `crontab` 文件\n可以使用以下命令编辑当前用户的 `crontab` 文件：\n```bash\ncrontab -e\n```\n首次使用时，系统会提示选择一个文本编辑器，选择你熟悉的编辑器（如 `nano` 或 `vim`）即可。\n\n#### 2. 添加定时任务\n在打开的 `crontab` 文件中添加定时任务，下面是一些具体的示例：\n\n##### 示例 1：每分钟执行一次命令\n```plaintext\n* * * * * /usr/bin/echo \"This is a test\" >> /tmp/test.log\n```\n这个任务会每分钟执行一次，将 `\"This is a test\"` 追加到 `/tmp/test.log` 文件中。\n\n##### 示例 2：每小时的第 30 分钟执行一次命令\n```plaintext\n30 * * * * /usr/bin/backup_script.sh\n```\n这个任务会在每小时的第 30 分钟执行 `/usr/bin/backup_script.sh` 脚本。\n\n##### 示例 3：每天凌晨 2 点执行一次命令\n```plaintext\n0 2 * * * /usr/bin/daily_cleanup.sh\n```\n这个任务会在每天凌晨 2 点执行 `/usr/bin/daily_cleanup.sh` 脚本。\n\n##### 示例 4：每月 1 号的 3 点 15 分执行一次命令\n```plaintext\n15 3 1 * * /usr/bin/monthly_report.sh\n```\n这个任务会在每月 1 号的 3 点 15 分执行 `/usr/bin/monthly_report.sh` 脚本。\n\n##### 示例 5：每周日的 18 点执行一次命令\n```plaintext\n0 18 * * 0 /usr/bin/weekly_backup.sh\n```\n这个任务会在每周日的 18 点执行 `/usr/bin/weekly_backup.sh` 脚本。\n\n##### 示例 6：指定时间范围执行命令\n```plaintext\n0 9-17 * * 1-5 /usr/bin/workday_check.sh\n```\n这个任务会在周一至周五的 9 点到 17 点之间，每小时的整点执行 `/usr/bin/workday_check.sh` 脚本。\n\n##### 示例 7：每隔一段时间执行命令\n```plaintext\n*/15 * * * * /usr/bin/check_status.sh\n```\n这个任务会每隔 15 分钟执行一次 `/usr/bin/check_status.sh` 脚本。\n\n#### 3. 保存并退出\n编辑完成后，保存并退出文本编辑器。如果使用 `nano` 编辑器，按 `Ctrl + X`，然后按 `Y` 确认保存，最后按 `Enter` 键退出。如果使用 `vim` 编辑器，按 `Esc` 键，输入 `:wq` 并按 `Enter` 键保存并退出。\n\n#### 4. 查看 `crontab` 文件内容\n可以使用以下命令查看当前用户的 `crontab` 文件内容：\n```bash\ncrontab -l\n```\n\n#### 5. 删除 `crontab` 文件\n如果需要删除当前用户的所有定时任务，可以使用以下命令：\n```bash\ncrontab -r\n```\n\n### 注意事项\n- **环境变量**：`crontab` 任务在执行时使用的环境变量可能与用户登录时不同。如果脚本依赖特定的环境变量，需要在脚本中明确设置。\n- **日志记录**：建议将定时任务的输出重定向到日志文件，以便后续排查问题。\n- **权限问题**：确保执行的命令或脚本具有足够的权限。\n",
  "Linux/Debian 12安装MySQL教程.md": "\n---\n\n## 🧩 一、卸载旧版本（如果你之前装过 5.7 或 MariaDB）\n\n为了避免冲突，建议先清理旧包：\n\n```bash\nsudo systemctl stop mysql || true\nsudo apt remove --purge -y mysql-server mysql-client mysql-common mariadb-server mariadb-client mariadb-common\nsudo apt autoremove --purge -y\nsudo rm -rf /var/lib/mysql /etc/mysql\n```\n\n---\n\n## ⚙️ 二、添加官方 MySQL APT 仓库\n\n### 1️⃣ 下载并安装配置包\n\n```bash\nwget https://dev.mysql.com/get/mysql-apt-config_0.8.36-1_all.deb\nsudo dpkg -i mysql-apt-config_0.8.36-1_all.deb\n```\n\n安装时会弹出交互菜单，请仔细选择：\n\n- **MySQL Server & Cluster → mysql-8.4-lts**\n    \n- 其他（如 Tools、Connector 等）可保持默认。\n    \n\n然后退出（选择 “OK” 保存配置）。\n\n---\n\n## ⚙️ 三、更新并安装 MySQL 8.4 LTS\n\n```bash\nsudo apt update\nsudo apt install -y mysql-server\n```\n\n这个命令会自动安装最新的 MySQL 8.4（LTS 版），包含 `mysql-community-server` 和相关依赖。\n\n---\n\n## 🔍 四、验证安装\n\n```bash\nmysql --version\n```\n\n你应看到类似输出：\n\n```\nmysql  Ver 8.4.2 for Linux on x86_64 (MySQL Community Server - GPL)\n```\n\n---\n\n## 🧠 五、启动与开机自启\n\n```bash\nsudo systemctl enable mysql\nsudo systemctl start mysql\nsudo systemctl status mysql\n```\n\n如果输出里状态是 `active (running)` ✅，说明服务正常运行。\n\n---\n\n## 🔐 六、安全配置\n\n执行官方安全脚本：\n\n```bash\nsudo mysql_secure_installation\n```\n\n它会引导你：\n\n- 设置 root 密码\n    \n- 移除匿名用户\n    \n- 禁止 root 远程登录（可选）\n    \n- 删除 test 数据库\n    \n- 重载权限表\n    \n\n建议全部选择“是（Y）”。\n\n---\n\n## 🧭 七、登录测试\n\n```bash\nmysql -u root -p\n```\n\n输入刚刚设置的密码，进入后执行：\n\n```sql\nSELECT VERSION();\n```\n\n输出应为：\n\n```\n+-----------+\n| VERSION() |\n+-----------+\n| 8.4.x     |\n+-----------+\n```\n\n---\n\n## 🧰 八、（可选）修改 MySQL 配置文件\n\n主配置路径：\n\n```\n/etc/mysql/mysql.conf.d/mysqld.cnf\n```\n\n如果你想修改端口、字符集等：\n\n```bash\nsudo nano /etc/mysql/mysql.conf.d/mysqld.cnf\n```\n\n推荐添加以下配置以支持中文与 emoji：\n\n```ini\n[mysqld]\ncharacter-set-server = utf8mb4\ncollation-server = utf8mb4_unicode_ci\n\n[client]\ndefault-character-set = utf8mb4\n```\n\n然后重启服务：\n\n```bash\nsudo systemctl restart mysql\n```\n\n---\n\n## 🧱 九、测试端口与启动情况\n\n```bash\nss -tunlp | grep mysql\n```\n\n输出类似：\n\n```\ntcp   LISTEN  0  80  127.0.0.1:3306  *:*  users:((\"mysqld\",pid=xxxx,fd=xxx))\n```\n\n说明 MySQL 已在 3306 端口监听。\n\n---\n\n## 🚀 十、总结\n\n|项目|状态|\n|---|---|\n|系统|Debian 12 (Bookworm) ✅|\n|MySQL 版本|8.4 LTS ✅|\n|官方支持|完全兼容|\n|安装难度|简单（无依赖冲突）|\n|推荐用途|长期开发 / 生产环境|\n\n---\n",
  "Linux/Debian 12安装PostgresDB教程.md": "下面给出在 PostgreSQL （PostgreSQL）在 Debian 12 (Bookworm) 上安装及基本配置的**一步步教程**\n\n---\n\n## 前置条件\n\n1. 已有一台 Debian 12 系统（可以是物理机、VM、或者云上实例）。\n    \n2. 使用拥有 `sudo` 权限的用户登录。\n    \n3. 网络可访问外部软件源。\n    \n\n---\n\n## 安装过程\n\n### 1. 更新系统软件包\n\n```bash\nsudo apt update\nsudo apt upgrade -y\n```\n\n这是一个好习惯，确保系统软件包为最新。\n\n### 2. 安装 PostgreSQL\n\n有两种方式：使用 Debian 默认仓库或使用官方 PostgreSQL 仓库。\n\n#### 方法 A：使用 Debian 默认仓库\n\n```bash\nsudo apt install -y postgresql postgresql-contrib\n```\n\n这会安装 PostgreSQL 及一些附加工具。\n安装后，服务一般会自动启动。可用 `sudo systemctl status postgresql` 查看。\n\n#### 方法 B：使用 PostgreSQL 官方 PGDG 仓库（推荐如果你想安装特定版本）\n\n1. 安装 `postgresql-common`（生成脚本等）：\n    \n    ```bash\n    sudo apt install -y postgresql-common\n    ```\n    \n\n    \n2. 运行脚本将 PGDG 仓库添加到系统：\n    \n    ```bash\n    sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh\n    ```\n    \n    或者手动：导入签名密钥、创建 `/etc/apt/sources.list.d/pgdg.list`。\n    \n3. 更新软件包列表：\n    \n    ```bash\n    sudo apt update\n    ```\n    \n4. 安装你想的版本，比如：\n    \n    ```bash\n    sudo apt install -y postgresql-18\n    ```\n    \n    （版本号根据仓库显示为止）\n    \n\n---\n\n### 3. 检查服务状态 & 设置开机启动\n\n```bash\nsudo systemctl status postgresql\nsudo systemctl enable postgresql\n```\n\n确认服务已运行并且开机启动。\n\n---\n\n### 4. 切换用户、设置 postgres 用户密码\n\n安装完成后，系统默认创建一个系统用户 `postgres`，以及 PostgreSQL 内部用户 `postgres`。你可以切换并为它设密码：\n\n```bash\nsudo -i -u postgres\npsql\n\\password postgres\n\\q\nexit\n```\n\n这样为超级用户设置了密码。\n\n---\n\n### 5. 创建数据库和用户（基本操作）\n\n切换为 `postgres` 用户后，在 psql 中执行：\n\n```sql\nCREATE DATABASE mydb;\nCREATE USER myuser WITH PASSWORD 'strongpassword';\nGRANT ALL PRIVILEGES ON DATABASE mydb TO myuser;\n```\n\n然后退出 `\\q`。\n你可以用以下方式连接：\n\n```bash\npsql -d mydb -U myuser -h localhost\n```\n\n---\n\n### 6. 配置远程访问（如果你希望其他机器也能访问数据库）\n\n默认 PostgreSQL 只监听本地 localhost。若要允许远程连接，需要两步：\n\n1. 编辑 `postgresql.conf`，修改 listen_addresses ：\n    \n    ```bash\n    sudo nano /etc/postgresql/12/main/postgresql.conf\n    # 找到\n    listen_addresses = 'localhost'\n    # 改为\n    listen_addresses = '*'\n    ```\n    \n    然后保存。\n    \n2. 编辑 `pg_hba.conf`，允许特定 IP 或网段连接：\n    \n    ```bash\n    sudo nano /etc/postgresql/12/main/pg_hba.conf\n    # 添加一行，例如：\n    host    all    all    192.168.100.0/24    md5\n    ```\n    \n    然后重启服务：\n    \n    ```bash\n    sudo systemctl restart postgresql\n    ```\n    \n\n> **警告**：允许远程访问时要注意安全（防火墙、强密码、只限可信IP）。\n\n---\n\n### 7. （可选）安装 pgAdmin4 图形管理工具\n\n如果你更倾向图形界面管理数据库，可以考虑安装 pgAdmin 4。 ([HowtoForge](https://www.howtoforge.com/how-to-install-postgresql-and-pgadmin-tool-on-debian-12/?utm_source=chatgpt.com \"How to Install PostgreSQL and pgAdmin Tool on Debian 12\"))  \n大致步骤：添加 pgAdmin 仓库、安装 `pgadmin4-web`、运行配置脚本、然后通过浏览器访问管理界面。\n\n---\n\n### 8. 卸载或清理（如果需要）\n\n如果你想移除 PostgreSQL，建议使用 `purge` 而不仅仅 `remove`，以清理配置文件。有人经验如下：\n\n> “使用 apt purge —purge … 然后 rm -rf 残余目录” ([Reddit](https://www.reddit.com/r/debian/comments/16cn3zx/how_to_properly_install_postgresql_remove_it_and/?utm_source=chatgpt.com \"how to properly install postgresql, remove it, and install it again?\"))  \n> 但在你的场景里（你打算长期使用 PostgreSQL），通常不需要卸载。\n\n\n---\n",
  "Linux/Debian12卸载宝塔面板命令.md": "在 **Debian 12** 上彻底卸载 **宝塔面板（BT Panel）**，包括其服务、目录和残留配置文件，可以按以下步骤执行。\n\n---\n\n### 🧹 一键卸载命令（官方脚本）\n\n宝塔官方提供了卸载脚本，最安全的做法是：\n\n```bash\nbt uninstall\n```\n\n如果命令不存在，可用下面的方式：\n\n```bash\nbash /www/server/panel/install/uninstall.sh\n```\n\n---\n\n### 🧨 手动彻底清理残留（推荐完整执行以下步骤）\n\n如果你想**完全删除所有宝塔相关文件与服务**，执行以下命令（逐条复制）：\n\n```bash\n# 1. 停止宝塔服务\n/etc/init.d/bt stop || systemctl stop bt\n\n# 2. 删除宝塔主目录\nrm -rf /www\n\n# 3. 删除宝塔执行脚本及命令链接\nrm -f /usr/bin/bt\nrm -f /etc/init.d/bt\n\n# 4. 删除启动服务项\nsystemctl disable bt --now 2>/dev/null\n\n# 5. 删除宝塔日志和缓存\nrm -rf /tmp/*bt*\nrm -rf /var/log/bt*\nrm -rf /var/lib/btpanel\n\n# 6. 删除宝塔安装脚本可能残留的位置\nrm -rf /root/.bt_backup\nrm -rf /root/bt.*\nrm -rf /root/panel\nrm -rf /root/.ssh_bt\n\n# 7. 删除 Nginx、MySQL、PHP 等由宝塔安装的服务（如需要）\n# ⚠️ 若系统中其它服务依赖这些组件，请谨慎执行！\napt purge -y nginx* mysql* mariadb* php* pure-ftpd* redis* memcached* mongod* vsftpd*\napt autoremove -y\napt clean\n```\n\n---\n\n### 🧾 可选清理（防止端口和用户残留）\n\n```bash\n# 删除宝塔可能创建的用户\nuserdel -r www 2>/dev/null\n\n# 清理面板端口防火墙规则（默认为 8888）\nufw delete allow 8888 2>/dev/null || iptables -D INPUT -p tcp --dport 8888 -j ACCEPT 2>/dev/null\n```\n\n---\n\n### ✅ 验证是否卸载干净\n\n执行以下命令检查：\n\n```bash\nps aux | grep bt\nls /www\nls /usr/bin/bt\n```\n\n若无输出或显示“无此文件或目录”，说明已彻底卸载。\n\n---\n",
  "Linux/Debian12安装MongoDB教程.md": "在 **Debian 12 (Bookworm)** 上安装 MongoDB 的正确方式是使用 **MongoDB 官方仓库**（推荐）或 **APT 默认仓库**（版本较旧）。下面给出详细步骤（推荐安装 **MongoDB 7.0** 最新稳定版）。\n\n---\n\n## 🧩 一、使用 MongoDB 官方仓库安装（推荐）\n\n### 1️⃣ 导入 MongoDB 公钥\n\n```bash\nsudo apt-get install -y curl gnupg\ncurl -fsSL https://pgp.mongodb.com/server-7.0.asc | \\\n  sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor\n```\n\n---\n\n### 2️⃣ 添加 MongoDB 官方 APT 源\n\n```bash\necho \"deb [ signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] \\\nhttps://repo.mongodb.org/apt/debian bookworm/mongodb-org/7.0 main\" | \\\nsudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list\n```\n\n---\n\n### 3️⃣ 更新软件源并安装 MongoDB\n\n```bash\nsudo apt-get update\nsudo apt-get install -y mongodb-org\n```\n\n---\n\n### 4️⃣ 启动并设置开机自启\n\n```bash\nsudo systemctl start mongod\nsudo systemctl enable mongod\n```\n\n---\n\n### 5️⃣ 查看运行状态\n\n```bash\nsudo systemctl status mongod\n```\n\n如果显示 `active (running)`，说明安装成功。\n\n---\n\n### 6️⃣ 进入 Mongo Shell（测试）\n\n```bash\nmongosh\n```\n\n退出：\n\n```bash\nexit\n```\n\n---\n\n## 🧩 二、（可选）如果想卸载 MongoDB\n\n```bash\n# 1️⃣ 停止服务\nsudo systemctl stop mongod 2>/dev/null || true\nsudo systemctl disable mongod 2>/dev/null || true\n\n# 2️⃣ 卸载所有相关包\nsudo apt-get purge -y mongodb-org* mongodb* mongosh*\n\n# 3️⃣ 删除残留的数据和日志目录\nsudo rm -rf /var/lib/mongo\nsudo rm -rf /var/lib/mongodb\nsudo rm -rf /var/log/mongodb\nsudo rm -rf /tmp/mongodb-*\n\n# 4️⃣ 删除配置文件和 systemd 服务文件\nsudo rm -f /etc/mongod.conf\nsudo rm -rf /etc/mongodb.conf\nsudo rm -f /lib/systemd/system/mongod.service\nsudo rm -f /etc/systemd/system/mongod.service\n\n# 5️⃣ 删除 apt 源文件\nsudo rm -f /etc/apt/sources.list.d/mongodb-org-*.list\n\n# 6️⃣ 清理包缓存\nsudo apt-get autoremove -y\nsudo apt-get autoclean -y\n\n\n# 1️⃣ 导入官方 GPG 密钥\ncurl -fsSL https://pgp.mongodb.com/server-7.0.asc | \\\n  sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor\n\n# 2️⃣ 添加官方源\necho \"deb [signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg] \\\nhttps://repo.mongodb.org/apt/debian bookworm/mongodb-org/7.0 main\" | \\\n  sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list\n\n# 3️⃣ 更新包并安装\nsudo apt-get update\nsudo apt-get install -y mongodb-org\n\n# 4️⃣ 启动并设置开机自启\nsudo systemctl enable mongod\nsudo systemctl start mongod\nsudo systemctl status mongod\n\n```\n\n---\n\n## ✅ 验证版本\n\n```bash\nmongod --version\n```\n\n---\n",
  "Linux/Debian12安装Redis教程.md": "\n---\n\n## ① 卸载当前 Debian 仓库版本\n\n执行以下命令以删除 Redis 及其依赖，并清理旧配置／服务残留：\n\n```bash\nsudo systemctl stop redis-server.service\nsudo systemctl disable redis-server.service\n\nsudo apt remove --purge -y redis-server redis-tools\n# 可选清理相关包\nsudo apt autoremove -y\n\n# 删除可能的配置和数据目录（如果你数据可以丢弃或已备份）：\nsudo rm -rf /etc/redis\nsudo rm -rf /var/lib/redis\nsudo rm -rf /var/log/redis\n```\n\n这样可以确保旧版本几乎完全被移除。\n\n---\n\n## ② 添加官方 Redis 仓库 & 安装最新版\n\n从官方文档添加仓库并安装最新版。根据官方说明： ([Redis](https://redis.io/docs/latest/operate/oss_and_stack/install/archive/install-redis/install-redis-on-linux/?utm_source=chatgpt.com \"Install Redis on Linux | Docs\"))\n\n```bash\nsudo apt update\n\n# 安装必要工具\nsudo apt install -y lsb-release curl gpg\n\n# 添加官方 GPG key\ncurl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg\nsudo chmod 644 /usr/share/keyrings/redis-archive-keyring.gpg\n\n# 添加 Redis 官方仓库\necho \"deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main\" | sudo tee /etc/apt/sources.list.d/redis.list\n\n# 更新仓库索引\nsudo apt update\n\n# 安装 Redis 最新版本（官方名称可能是 “redis” 或 “redis-server”，看包名）\nsudo apt install -y redis\n```\n\n安装完成后，启动服务并设为开机启动：\n\n```bash\nsudo systemctl enable redis-server\nsudo systemctl start redis-server\n```\n\n验证安装：\n\n```bash\nredis-server --version\nredis-cli ping # 应返回 PONG\n```\n\n---\n\n## ③ 注意事项 &提示\n\n- 由于你之前遇到过 “`/usr/bin/redis-server -> redis-check-rdb`” 的链接问题，这次用官方仓库安装后，务必检查 `which redis-server`、`ls -l /usr/bin/redis-server`，确认 `redis-server` 是正确的守护进程可执行体。\n    \n- 配置文件可能变化，最好检查 `/etc/redis/redis.conf` 中 `supervised systemd` 或 `daemonize no`、`bind` 等项是否与你的环境相符。\n    \n- 若你的服务端（你开发的游戏服务端）使用 Redis 作为缓存或消息队列，建议备份关键配置或数据，以避免在卸载过程中丢失。\n    \n- 安装后再次测试服务状态：\n    \n    ```bash\n    sudo systemctl status redis-server\n    ```\n    \n    确认 “Active: active (running)”。\n    \n- 安全建议：设置强密码、开启绑定本地（或限制访问）、配置持久化策略等。\n    \n\n---\n",
  "Linux/docker,LXC,qemu,k8s,chroot等的特点.md": "\n以下从技术定义、核心原理、特点、区别及相互关系等方面，详细解析 **LXC、Docker、chroot、虚拟机、QEMU、K8s** 的概念及关联：\n\n\n### **一、核心技术定义与原理**\n#### 1. **chroot**\n- **本质**：Linux 系统调用，用于修改进程的“根目录”（`/`），创建一个隔离的文件系统视图。\n- **原理**：通过 `chroot` 命令，指定一个新的根目录，进程只能访问该目录下的文件（类似“伪根”），但不隔离 CPU、内存、网络等资源。\n- **特点**：\n  - 最轻量的隔离，仅文件系统隔离，无资源限制。\n  - 进程仍共享宿主机内核、进程空间、网络栈等。\n  - 非完整容器，常用于调试、环境隔离（如构建跨平台程序）。\n\n#### 2. **LXC（Linux Containers）**\n- **本质**：基于 Linux 内核特性（`namespace` 命名空间 + `cgroups` 资源控制）的操作系统级容器。\n- **原理**：\n  - `namespace`：隔离进程、网络、文件系统、用户等资源（如 `PID namespace` 使容器内进程号独立）。\n  - `cgroups`：限制容器的 CPU、内存、磁盘 I/O 资源使用。\n- **特点**：\n  - 共享宿主机内核，启动快（秒级），资源占用低。\n  - 提供接近虚拟机的隔离性，但轻量高效。\n  - 需要手动配置，侧重系统级隔离（如运行完整的 Linux 发行版）。\n\n#### 3. **Docker**\n- **本质**：基于容器技术的应用打包与部署平台，核心是容器运行时（`runc`，基于 Open Container Initiative 标准）。\n- **原理**：\n  - 继承 LXC 的 `namespace` 和 `cgroups`，但更上层，封装了镜像（`Image`）、容器（`Container`）、仓库（`Registry`）流程。\n  - 通过镜像分层技术（UnionFS）实现快速打包，通过 `Docker Engine` 管理容器生命周期。\n- **特点**：\n  - 聚焦“应用容器化”，强调“一次构建，到处运行”。\n  - 比 LXC 更易用（标准化 API、自动化部署），适合微服务、CI/CD。\n  - 镜像生态丰富（Docker Hub），但隔离性略弱于 LXC（共享内核，依赖宿主机内核版本）。\n\n#### 4. **虚拟机（Virtual Machine, VM）**\n- **本质**：通过虚拟化技术模拟完整硬件环境，运行独立操作系统。\n- **分类与原理**：\n  - **全虚拟化**（如 VMware Workstation）：Hypervisor 完全模拟硬件，Guest OS 无需修改。\n  - **半虚拟化**（如 Xen）：Guest OS 知道自己运行在虚拟机中，通过 Hypercall 与 Hypervisor 交互。\n  - **硬件辅助虚拟化**（如 Intel VT-x）：CPU 直接支持虚拟化，提升性能。\n- **特点**：\n  - 隔离性最强（独立内核、硬件资源），支持不同操作系统（如 Windows 跑在 Linux 宿主机上）。\n  - 资源开销大（需模拟硬件，启动慢，内存/CPU 占用高）。\n  - 适合需要完整 OS 环境的场景（如测试不同系统、遗留应用迁移）。\n\n#### 5. **QEMU**\n- **本质**：开源的通用模拟器和虚拟机监视器（Virtual Machine Monitor, VMM）。\n- **原理**：\n  - 单独使用时，通过软件模拟目标硬件（如在 x86 上运行 ARM 程序），性能较低。\n  - 与 **KVM**（Kernel-based Virtual Machine，Linux 内核模块）结合时，利用硬件虚拟化技术（如 VT-x），成为高效的虚拟机引擎（QEMU-KVM）。\n- **特点**：\n  - 跨平台兼容性强，支持多种架构（x86、ARM、RISC-V 等）。\n  - 是虚拟机技术的具体实现之一，常作为 KVM 的用户空间工具。\n\n#### 6. **K8s（Kubernetes）**\n- **本质**：容器编排平台，用于自动化部署、扩展和管理容器化应用。\n- **核心功能**：\n  - 调度容器到节点（Node），支持负载均衡、服务发现。\n  - 处理容器的生命周期（重启、扩缩容、滚动更新）。\n  - 提供资源配额、健康检查、故障恢复等机制。\n- **特点**：\n  - 不绑定特定容器运行时（支持 Docker、containerd、runc 等）。\n  - 解决“大规模容器集群管理”问题，适合微服务架构、云原生应用。\n\n\n### **二、核心区别对比**\n| **维度**         | **chroot**       | **LXC/Docker（容器）** | **虚拟机（含 QEMU-KVM）** | **K8s**                |\n|-------------------|------------------|------------------------|---------------------------|------------------------|\n| **隔离级别**      | 文件系统隔离     | 操作系统级隔离（内核共享） | 硬件级隔离（独立内核）    | 编排管理层（不涉及底层隔离） |\n| **资源共享**      | 完全共享         | 共享宿主机内核         | 独立内核，硬件资源模拟    | 管理多个容器/节点的资源 |\n| **启动时间**      | 瞬间             | 秒级                   | 分钟级（需启动 Guest OS） | 不涉及启动，管理已有容器 |\n| **资源开销**      | 极低             | 低（仅用户空间隔离）   | 高（硬件模拟 + 完整 OS）  | 额外控制平面开销       |\n| **支持的 OS**     | 同宿主机内核     | 同宿主机内核           | 任意 OS（如 Windows/Linux） | 不限制，管理容器化应用 |\n| **核心目标**      | 文件系统隔离     | 轻量应用隔离/部署      | 完整 OS 环境模拟          | 容器集群管理           |\n| **典型用途**      | 环境调试         | 应用打包、轻量部署     | 多系统测试、遗留应用兼容  | 大规模容器调度、微服务 |\n\n\n### **三、相互关系**\n#### 1. **技术栈分层**\n```\n应用层（K8s）\n├─ 容器运行时（Docker/LXC/containerd）\n│  ├─ 内核特性（namespace/cgroups）\n│  └─ chroot（基础文件系统隔离）\n└─ 虚拟化层（虚拟机/QEMU-KVM）\n   └─ 硬件（CPU/内存/存储，支持 VT-x 等虚拟化技术）\n```\n\n#### 2. **具体关联**\n- **chroot 与容器**：  \n  chroot 是容器实现文件系统隔离的基础（如 Docker 镜像的根文件系统通过 chroot 挂载），但容器在此之上增加了 `namespace` 和 `cgroups` 实现完整隔离。\n\n- **LXC 与 Docker**：  \n  Docker 早期基于 LXC 开发，后转向自有运行时（`libcontainer`，现 `runc`），二者同属容器技术，但定位不同：  \n  - LXC 偏向“系统级容器”（运行完整 Linux 发行版，如 Ubuntu 容器）；  \n  - Docker 偏向“应用级容器”（打包单个应用及其依赖，如 Node.js 服务）。\n\n- **虚拟机与 QEMU**：  \n  QEMU 是虚拟机的一种实现方式，单独使用时模拟硬件（慢），与 KVM 结合时利用硬件虚拟化（高效），属于虚拟机技术的底层引擎之一（类似 VirtualBox、VMware 的技术定位）。\n\n- **K8s 与容器/虚拟机**：  \n  - K8s 主要管理容器（如 Docker 容器），但也可通过虚拟机节点（Node）部署（每个 Node 可以是物理机或虚拟机）。  \n  - 容器运行在宿主机（物理机或虚拟机）上，K8s 不关心底层是物理机还是虚拟机，只调度容器到节点。\n\n\n### **四、应用场景总结**\n- **chroot**：简单文件系统隔离（如构建跨版本软件、修复系统）。  \n- **Docker/LXC**：轻量应用部署（微服务、Web 服务），追求资源效率和快速启动。  \n- **虚拟机/QEMU-KVM**：需要完整 OS 隔离（如运行 Windows 应用、多租户隔离、硬件兼容性测试）。  \n- **K8s**：大规模容器集群管理（微服务架构、弹性扩缩容、高可用部署）。\n\n\n### **五、核心总结**\n- **隔离性**：虚拟机（强隔离，独立内核）> 容器（共享内核，OS 级隔离）> chroot（仅文件系统）。  \n- **效率**：chroot/容器（高效）> 虚拟机（低效，因硬件模拟）。  \n- **关系**：  \n  - 容器技术（LXC/Docker）基于内核特性（namespace/cgroups），chroot 是其文件系统隔离的基础。  \n  - 虚拟机（如 QEMU-KVM）通过硬件虚拟化实现强隔离，与容器形成互补（容器适合同一 OS 下的应用隔离，虚拟机适合跨 OS 隔离）。  \n  - K8s 是容器的“上层管理工具”，不依赖特定容器运行时，聚焦集群调度与自动化。\n\n理解这些技术的核心是明确其“隔离目标”和“资源模型”：容器追求轻量高效，虚拟机追求强隔离，K8s 解决规模化管理问题，而 chroot 是最基础的工具。根据需求选择合适的技术（如部署单个应用用 Docker，多 OS 环境用虚拟机，大规模集群用 K8s 编排容器）。",
  "Linux/Linux zip 命令总结.md": "\n1. 打包单个文件：\n\n```\nzip 压缩包名称.zip 要打包的文件\n```\n\n2. 打包多个文件：\n\n```\nzip 压缩包名称.zip 文件1 文件2 文件3\n```\n\n3. 打包整个目录（包括子目录）：\n\n```\nzip -r 压缩包名称.zip 要打包的目录\n```\n\n4. 打包目录并排除某些文件：\n\n```\nzip -r 压缩包名称.zip 要打包的目录 -x 要排除的文件或目录\n```\n\n5. 带密码打包：\n\n```\nzip -r -e 压缩包名称.zip 要打包的目录\n```\n\n执行后会提示你输入密码\n\n例如，要打包当前目录下的documents文件夹为backup.zip，可以使用：\n\n```\nzip -r backup.zip documents\n```\n\n如果系统中没有zip命令，可以先安装：\n\n- Debian/Ubuntu: sudo apt install zip\n",
  "Linux/Linux一些奇奇怪怪的命令.md": "打开终端tmoe面板：\ncurl -LO https://gitee.com/mo2/linux/raw/2/2.awk\nawk -f 2.awk\n\nubuntu和deepin系统安装宝塔面板：\nwget -O install.sh https://download.bt.cn/install/install_lts.sh && sudo bash install.sh ed8484bec\n\n重启宝塔面板：\nbt restart\n\n开启宝塔面板：\nbt default\n\n安装和运行casaos轻量nas系统：\ncurl -fsSL https://get.casaos.io | sudo bash\n\n安装和运行1panel面板：\ncurl -sSL https://resource.fit2cloud.com/1panel/package/quick_start.sh -o quick_start.sh && sudo bash quick_start.sh\n\n连接ssh示例\n\nssh root@192.168.25.151 -p 6003",
  "Linux/Linux下的scp命令总结.md": "Linux scp 命令总结\n用途：安全复制文件/目录到本地或远程主机（基于 SSH 协议）。\n \n基本语法\n \nscp [选项] 源文件 目标路径\n \n \n常用选项\n \n选项 说明 \n -r  递归复制目录及子目录 \n -P <port>  指定 SSH 端口（注意大写 P） \n -i <identity_file>  使用指定的私钥文件认证 \n -C  压缩传输数据 \n -p  保留文件属性（时间戳、权限等） \n -v  显示详细传输过程 \n \n典型示例\n \n1. 本地文件 → 远程主机\n \nscp local_file.txt user@remote_host:/path/to/remote_dir/\n \n2. 远程文件 → 本地\n \nscp user@remote_host:/path/to/remote_file.txt ~/local_dir/\n \n3. 复制目录（需加  -r ）\n \nscp -r local_dir/ user@remote_host:/path/to/remote_dir/\n \n4. 远程主机间复制（通过本地中转）\n \nscp user1@host1:/file.txt user2@host2:/path/\n \n5. 指定端口（如非默认 22 端口）\n \nscp -P 2222 local_file.txt user@remote_host:/remote_path/\n \n6. 使用私钥认证\n \nscp -i ~/.ssh/id_rsa local_file.txt user@remote_host:/remote_path/\n \n \n注意事项\n \n- 远程路径需以  user@host:  开头。\n- 目标路径不存在时会自动创建（目录需  -r ）。\n- 若提示权限问题，检查私钥文件权限（需  chmod 600 ）。",
  "Linux/Linux不同格式解压命令.md": "在 Linux 中解压不同格式的压缩文件，可使用以下命令：\n \n1. tar.gz 文件\n \ntar -xzf filename.tar.gz\n \n \n- 说明：\n x  表示解压， z  调用 gzip 解压， f  指定文件名。\n \n2. tar.zst 文件\n \ntar --zstd -xf filename.tar.zst\n \n \n- 说明：\n --zstd  明确使用 zstd 解压， x  解压， f  指定文件名。需确保系统已安装  zstd  工具。\n \n3. tar.xz 文件\n \ntar -xJf filename.tar.xz\n \n \n- 说明：\n J  调用 xz 解压， x  解压， f  指定文件名。\n \n补充：若需解压时显示详细过程，可添加  -v  参数（如  tar -xvzf filename.tar.gz ）。",
  "Linux/Linux后台运行程序.md": "在 Linux 系统中，让服务一直保持在后台运行有多种方法，下面为你详细介绍：\r\n\r\n### 1. 使用 `&` 符号\r\n在命令后面加上 `&` 符号可以让命令在后台运行。\r\n\r\n#### 示例\r\n```bash\r\npython my_script.py &\r\n```\r\n上述命令会让 `my_script.py` 脚本在后台运行。\r\n\r\n#### 注意事项\r\n- 这种方式虽然简单，但当你关闭当前终端会话时，该进程可能会收到 `SIGHUP` 信号而终止。\r\n- 你可以使用 `jobs` 命令查看当前终端中后台运行的作业，使用 `fg` 命令将后台作业调回到前台。\r\n\r\n### 2. 使用 `nohup` 命令\r\n`nohup` 命令可以让程序忽略 `SIGHUP` 信号，从而在你关闭终端后继续运行。\r\n\r\n#### 示例\r\n```bash\r\nnohup python my_script.py > output.log 2>&1 &\r\n```\r\n- `nohup`：用于忽略 `SIGHUP` 信号。\r\n- `> output.log`：将标准输出重定向到 `output.log` 文件。\r\n- `2>&1`：将标准错误输出也重定向到标准输出，即同样写入 `output.log` 文件。\r\n- `&`：让命令在后台运行。\r\n\r\n#### 查看运行状态\r\n使用 `ps` 命令可以查看进程是否还在运行：\r\n```bash\r\nps -ef | grep my_script.py\r\n```\r\n\r\n### 3. 使用 `screen` 工具\r\n`screen` 是一个全屏窗口管理器，它可以创建多个虚拟终端会话，即使你断开连接，会话中的进程仍然会继续运行。\r\n\r\n#### 安装 `screen`\r\n在 Debian 或 Ubuntu 系统上：\r\n```bash\r\nsudo apt-get install screen\r\n```\r\n在 CentOS 或 RHEL 系统上：\r\n```bash\r\nsudo yum install screen\r\n```\r\n\r\n#### 使用步骤\r\n1. 启动一个新的 `screen` 会话：\r\n```bash\r\nscreen\r\n```\r\n2. 在 `screen` 会话中运行你的命令，例如：\r\n```bash\r\npython my_script.py\r\n```\r\n3. 按下 `Ctrl + A` 然后再按下 `D` 组合键，将当前 `screen` 会话分离，此时会话会在后台继续运行。\r\n4. 如果你想重新连接到该会话，可以使用以下命令：\r\n```bash\r\nscreen -r\r\n```\r\n\r\n### 4. 使用 `tmux` 工具\r\n`tmux` 也是一个类似 `screen` 的终端复用工具，功能更强大。\r\n\r\n#### 安装 `tmux`\r\n在 Debian 或 Ubuntu 系统上：\r\n```bash\r\nsudo apt-get install tmux\r\n```\r\n在 CentOS 或 RHEL 系统上：\r\n```bash\r\nsudo yum install tmux\r\n```\r\n\r\n#### 使用步骤\r\n1. 启动一个新的 `tmux` 会话：\r\n```bash\r\ntmux new -s mysession\r\n```\r\n这里的 `mysession` 是会话的名称，你可以自定义。\r\n2. 在 `tmux` 会话中运行你的命令，例如：\r\n```bash\r\npython my_script.py\r\n```\r\n3. 按下 `Ctrl + B` 然后再按下 `D` 组合键，将当前 `tmux` 会话分离。\r\n4. 如果你想重新连接到该会话，可以使用以下命令：\r\n```bash\r\ntmux attach -t mysession\r\n```\r\n\r\n### 5. 使用系统服务管理工具（如 `systemd`）\r\n对于需要长期稳定运行的服务，推荐使用系统服务管理工具，如 `systemd`（大多数现代 Linux 发行版都使用 `systemd`）。\r\n\r\n#### 创建服务文件\r\n创建一个新的服务文件，例如 `/etc/systemd/system/my_script.service`：\r\n```ini\r\n[Unit]\r\nDescription=My Python Script Service\r\nAfter=network.target\r\n\r\n[Service]\r\nExecStart=/usr/bin/python /path/to/my_script.py\r\nWorkingDirectory=/path/to/working/directory\r\nRestart=always\r\nUser=your_username\r\n\r\n[Install]\r\nWantedBy=multi-user.target\r\n```\r\n- `Description`：服务的描述信息。\r\n- `After`：指定服务在网络服务启动后再启动。\r\n- `ExecStart`：指定要执行的命令。\r\n- `WorkingDirectory`：指定工作目录。\r\n- `Restart`：设置为 `always` 表示服务崩溃或停止后会自动重启。\r\n- `User`：指定运行服务的用户。\r\n\r\n#### 启动和管理服务\r\n```bash\r\n# 重新加载 systemd 管理器配置\r\nsudo systemctl daemon-reload\r\n# 启动服务\r\nsudo systemctl start my_script.service\r\n# 设置服务开机自启\r\nsudo systemctl enable my_script.service\r\n# 查看服务状态\r\nsudo systemctl status my_script.service\r\n```",
  "Linux/Linux命令风格解析.md": "在Linux命令行中，选项的不同书写形式反映了三种主流风格的设计逻辑，以下是结合历史背景与实际应用场景的深度解析：\n\n### 一、Unix/Posix风格：简洁至上的单字符范式\n这是最古老的选项体系，诞生于Unix电传打字机时代。其核心特征是：\n- **符号标识**：必须以单个短横线`-`开头，如`ls -a`\n- **组合规则**：无参数的选项可自由拼接，如`ls -alh`等价于`ls -a -l -h`\n- **参数绑定**：带参数的选项需紧跟值，如`-w50`或`-w 50`均可\n- **历史局限**：受限于26个字母的容量，复杂工具需依赖组合（如`find -type f -exec`）\n\n典型场景：文件操作（`ls`、`cp`）、权限管理（`chmod`）等基础命令。这种风格的高效性在处理批量文件时尤为突出，例如`rm -rf`的组合操作。\n\n### 二、BSD风格：去符号化的实用主义\nBSD操作系统对Unix传统的突破体现在：\n- **无符号标识**：直接使用字母组合，如`ps aux`\n- **灵活组合**：多个选项可连写且无需分隔符，如`tar zxf archive.tar.gz`\n- **参数兼容**：带参数的选项可空格分隔或直接拼接，如`ps Uroot`与`ps U root`等效\n\n这种设计源于BSD对用户体验的优化，例如`ps aux`的组合能直观展示进程全貌。但需注意，并非所有BSD风格选项都能随意组合，如`ps fx`中的`f`和`x`分别控制显示格式和非终端进程，顺序调换可能影响输出。\n\n### 三、GNU风格：可读性优先的长选项\nGNU项目为解决单字符选项的语义模糊问题，引入了：\n- **双横线标识**：以`--`开头的完整单词，如`gzip --help`\n- **参数传递**：支持`--sort=time`或`--sort time`两种格式\n- **缩写机制**：唯一前缀即可生效，如`--cre`可替代`--create`\n- **功能扩展**：突破字母限制，如`wget --user-agent`可自定义请求头\n\n这种风格在复杂工具（如`git`、`docker`）中广泛应用，例如`git commit --amend`比`-a`更清晰。GNU工具通常同时支持长/短选项，如`ls --all`与`-a`等效。\n\n### 四、混合使用的注意事项\n1. **解析优先级**：旧风格选项需置于最前，如`tar cvf --exclude=*.tmp`中`cvf`为传统选项，`--exclude`为GNU选项\n2. **命令特异性**：并非所有命令都支持混合风格，例如`ps`可接受`ps -ef`（Unix风格）和`ps aux`（BSD风格），但`ps -aux`会被解析为混合模式\n3. **参数歧义**：当选项与文件名冲突时，可用`--`终止选项解析，如`rm -- -file`可强制删除名为`-file`的文件\n\n### 五、典型命令的风格对比\n| 命令       | Unix风格          | BSD风格         | GNU风格          |\n|------------|-------------------|-----------------|------------------|\n| 解压缩     | `tar -zxf file`   | `tar zxf file`  | `tar --gzip --extract --file=file` |\n| 进程查看   | `ps -ef`          | `ps aux`        | `ps --forest`    |\n| 显示帮助   | `ls -h`           | `ls h`（无效）  | `ls --help`      |\n\n### 六、历史演变与实践建议\n- **工具适配**：GNU工具普遍兼容多种风格，而BSD衍生工具（如`freebsd`的`ps`）可能仅支持特定格式\n- **学习路径**：新手建议从GNU长选项入手（如`--help`），逐步掌握短选项组合\n- **文档依赖**：使用`man`或`--help`查看具体命令的选项说明，例如`tar --help`会列出所有支持的风格\n\n理解这些风格差异，不仅能更高效地使用命令行，还能深入体会不同开发社区的设计哲学。例如，GNU的长选项体现了自由软件运动对可读性的追求，而BSD的简洁风格则延续了Unix“做一件事并做好”的理念。在实际应用中，可根据场景灵活选择：快速操作时用短选项，复杂配置时用长选项，疑难问题则结合`--help`与`man`手册。\n",
  "Linux/Linux复制文件命令.md": "在 Linux 中，可以使用 `cp` 命令将某个路径的文件复制到另一个位置。命令格式如下：\r\n\r\n```bash\r\ncp 源文件路径 目标路径\r\n```\r\n\r\n### 示例\r\n假设要将 `/home/user/file.txt` 复制到 `/home/user/documents/`，命令如下：\r\n\r\n```bash\r\ncp /home/user/file.txt /home/user/documents/\r\n```\r\n\r\n### 选项\r\n- **`-r`**：复制目录及其内容。\r\n- **`-i`**：覆盖前提示确认。\r\n- **`-v`**：显示复制进度。\r\n\r\n### 示例\r\n1. **复制目录**：\r\n   ```bash\r\n   cp -r /home/user/folder /home/user/documents/\r\n   ```\r\n\r\n2. **覆盖前提示**：\r\n   ```bash\r\n   cp -i /home/user/file.txt /home/user/documents/\r\n   ```\r\n\r\n3. **显示进度**：\r\n   ```bash\r\n   cp -v /home/user/file.txt /home/user/documents/\r\n   ```\r\n\r\n### 总结\r\n`cp` 命令用于复制文件或目录，常用选项包括 `-r`、`-i` 和 `-v`。",
  "Linux/Linux安装ollama.md": "apt install tur-repo\napt install ollama\nollama serve\n重新开启个会话\n安装各种开源模型\n",
  "Linux/Linux常用软件包安装.md": "```bash\nsudo apt install docker-compose -y\n```",
  "Linux/Linux查看无线网口.md": "在Debian系统中，可以通过以下几种方法查看使用的无线网卡的名称：\r\n\r\n### 使用命令行工具`ifconfig`\r\n1. 打开终端，输入命令`ifconfig -a`。\r\n2. 该命令会列出系统中所有的网络接口，包括有线网卡、无线网卡等。通常无线网卡的名称会以`wlan`开头，如`wlan0`、`wlan1`等。你可以根据网卡的相关信息（如MAC地址、IP地址等）来确定具体使用的无线网卡。\r\n\r\n### 使用`iwconfig`命令\r\n1. 在终端中输入`iwconfig`。\r\n2. 此命令主要用于配置无线网卡，它会显示出系统中的无线接口信息，包括无线网卡的名称、频率、信号强度等。通过识别无线网卡的相关参数，能找到正在使用的无线网卡名称。\r\n\r\n### 查看`/sys/class/net/`目录\r\n1. 打开终端，输入命令`ls /sys/class/net/`。\r\n2. 该目录下列出了系统中所有的网络设备接口文件，无线网卡的名称通常也以`wlan`开头，通过查看该目录可以找到无线网卡的名称。\r\n\r\n### 使用`nmcli`命令\r\n1. 确保`NetworkManager`服务已安装并运行，然后在终端中输入`nmcli device status`。\r\n2. 该命令会显示系统中网络设备的状态信息，包括设备名称、设备类型、状态等。在设备类型为`wifi`的行中，可以找到无线网卡的名称。",
  "Linux/Linux的Proc目录解析.md": " `/proc` 在 Linux 中是一个 **伪文件系统 (procfs)**，它不是存储在磁盘上的真实文件，而是内核在内存中动态生成的接口，主要用于提供 **内核、进程和系统状态** 的信息。几乎所有的监控工具（如 `top`、`htop`、`ps`、`free`、`uptime`、`vmstat`、`iostat`）都是通过读取 `/proc` 下的文件获取数据的。\n \n---\n\n# 🗂 **/proc 能查看的信息汇总**\n\n## 1. **进程相关信息**\n\n每个正在运行的进程在 `/proc` 下都会有一个以 **PID** 命名的目录，例如 `/proc/1234/`。里面的内容主要是该进程的状态：\n\n- `/proc/[pid]/cmdline` → 启动命令行参数\n    \n- `/proc/[pid]/cwd` → 当前工作目录 (符号链接)\n    \n- `/proc/[pid]/exe` → 可执行文件路径 (符号链接)\n    \n- `/proc/[pid]/environ` → 环境变量\n    \n- `/proc/[pid]/fd/` → 打开的文件描述符\n    \n- `/proc/[pid]/maps` → 内存映射情况\n    \n- `/proc/[pid]/stat` → 进程状态、运行时间、优先级等\n    \n- `/proc/[pid]/status` → 可读性较好的进程状态信息\n    \n- `/proc/[pid]/task/` → 线程信息（子目录为线程 ID）\n    \n\n---\n\n## 2. **CPU 相关信息**\n\n- `/proc/cpuinfo` → CPU 型号、核心数、主频、缓存大小、虚拟化支持等\n    \n- `/proc/stat` → CPU 使用率、上下文切换、中断次数等\n    \n- `/proc/interrupts` → 中断统计\n    \n- `/proc/softirqs` → 软中断统计\n    \n\n---\n\n## 3. **内存信息**\n\n- `/proc/meminfo` → 总内存、可用内存、缓存、swap 等\n    \n- `/proc/kcore` → 内核内存映射（类似物理内存的转储）\n    \n- `/proc/vmallocinfo` → 内核虚拟内存使用情况\n    \n- `/proc/slabinfo` → 内核对象缓存（slab 分配器）\n    \n\n---\n\n## 4. **系统信息**\n\n- `/proc/version` → 内核版本信息\n    \n- `/proc/uptime` → 系统运行时间和空闲时间\n    \n- `/proc/loadavg` → 系统平均负载\n    \n- `/proc/cmdline` → 内核启动参数\n    \n- `/proc/modules` → 已加载的内核模块\n    \n- `/proc/filesystems` → 支持的文件系统类型\n    \n- `/proc/mounts` → 当前挂载的文件系统（和 `mount` 命令一致）\n    \n- `/proc/partitions` → 磁盘分区信息\n    \n- `/proc/devices` → 已注册的设备\n    \n- `/proc/ioports` → I/O 端口使用情况\n    \n- `/proc/iomem` → 内存映射的 I/O 信息\n    \n- `/proc/diskstats` → 磁盘 I/O 统计\n    \n- `/proc/locks` → 当前内核中的文件锁\n    \n\n---\n\n## 5. **网络信息**\n\n在 `/proc/net/` 目录下：\n\n- `/proc/net/dev` → 网络接口的流量统计（类似 `ifconfig`、`ip -s link`）\n    \n- `/proc/net/tcp`、`/proc/net/udp` → TCP/UDP 连接信息（类似 `ss`、`netstat`）\n    \n- `/proc/net/unix` → UNIX 套接字信息\n    \n- `/proc/net/route` → 路由表\n    \n- `/proc/net/arp` → ARP 缓存表\n    \n- `/proc/net/snmp` → 网络协议统计信息（ICMP、TCP、UDP）\n    \n\n---\n\n## 6. **内核配置与参数**\n\n- `/proc/sys/` → 内核参数（可读可写，可通过 `sysctl` 修改），例如：\n    \n    - `/proc/sys/net/ipv4/ip_forward` → 是否启用 IPv4 转发\n        \n    - `/proc/sys/kernel/hostname` → 主机名\n        \n    - `/proc/sys/kernel/pid_max` → 最大进程号\n        \n    - `/proc/sys/vm/swappiness` → 内存换出策略\n        \n\n---\n\n## 7. **其他有用的文件**\n\n- `/proc/self/` → 当前进程（即访问 `/proc` 的进程本身）的信息\n    \n- `/proc/kmsg` → 内核日志（类似 `dmesg`）\n    \n- `/proc/sched_debug` → 调度器的调试信息\n    \n- `/proc/zoneinfo` → 内存区域信息\n    \n- `/proc/swap` → swap 使用情况\n    \n\n---\n\n# 📊 **总结**\n\n通过 `/proc`，你可以获取：\n\n1. **进程级别** → PID、内存、CPU、线程、文件描述符\n    \n2. **系统级别** → CPU、内存、负载、启动参数、模块、文件系统\n    \n3. **硬件级别** → 设备、中断、I/O 端口、内存映射\n    \n4. **网络级别** → 接口流量、TCP/UDP 连接、路由、ARP\n    \n5. **内核级别** → 内核参数、调度、日志、虚拟内存\n    \n\n---\n",
  "Linux/Linux软件包存放地址.md": "在 Linux 系统中，安装的软件包通常会放置在以下几个目录中，具体路径取决于软件包的类型和安装方式。\r\n\r\n### 1. **二进制文件（可执行文件）**\r\n   - **`/usr/bin/`**：大多数用户安装的软件的二进制文件都会安装在此目录下。这些是常见的应用程序和命令（例如 `ls`, `cp`, `git` 等）。\r\n   - **`/bin/`**：存放一些最基本的系统命令，这些命令在系统的任何时候都需要可用，通常在恢复模式下也能使用。\r\n   - **`/usr/local/bin/`**：用户自己安装的软件（通常是通过源代码编译安装的软件）会放在这个目录下。它优先级高于 `/usr/bin/`，因此用户安装的命令会覆盖系统自带的软件。\r\n   - **`/sbin/` 和 `/usr/sbin/`**：这些目录通常存放的是系统管理工具，需要管理员权限来使用。比如 `ifconfig`, `mount` 等。\r\n\r\n### 2. **库文件**\r\n   - **`/lib/`**：包含了系统启动和运行时所必需的共享库（例如 C 库）。\r\n   - **`/usr/lib/`**：用于存放大多数安装的软件包的共享库，支持应用程序的运行。\r\n   - **`/usr/local/lib/`**：与 `/usr/local/bin/` 类似，这是存放用户手动安装的程序和库的地方。\r\n\r\n### 3. **配置文件**\r\n   - **`/etc/`**：这是系统和应用程序的全局配置文件所在的目录。几乎所有的配置文件都可以在这里找到。例如 `/etc/passwd` 存放用户信息，`/etc/ssh/sshd_config` 存放 SSH 配置等。\r\n   - **`/usr/local/etc/`**：对于用户自己安装的软件包，它的配置文件一般会放在此目录下。\r\n\r\n### 4. **文档和帮助文件**\r\n   - **`/usr/share/`**：存放共享的数据文件，包括应用程序的文档、帮助文件、图标等。例如 `/usr/share/doc/` 目录存放着已安装软件包的文档和许可证。\r\n   - **`/usr/local/share/`**：用户自己安装的软件的共享数据文件通常存放在此目录。\r\n\r\n### 5. **临时文件**\r\n   - **`/tmp/`**：这个目录用于存放临时文件，系统或应用程序运行时会使用这个目录来存放临时数据。通常，`/tmp/` 目录中的文件会在系统重启后被删除。\r\n   - **`/var/tmp/`**：类似于 `/tmp/`，但 `/var/tmp/` 中的文件不会在系统重启时被清除，适用于需要较长时间存储的临时文件。\r\n\r\n### 6. **日志文件**\r\n   - **`/var/log/`**：存放系统和应用程序的日志文件。比如 `/var/log/syslog` 记录了系统日志，`/var/log/auth.log` 记录了认证相关的日志等。\r\n\r\n### 7. **其他相关目录**\r\n   - **`/opt/`**：这个目录通常用于存放大型的第三方软件包，特别是那些由供应商提供的独立应用程序（例如 Google Chrome 或 Oracle Java）通常会安装在这个目录。\r\n   - **`/home/`**：每个用户的个人目录会在 `/home/` 目录下（例如 `/home/user/`），其中可能包含用户安装的软件或自定义的程序。\r\n\r\n### 总结\r\n- **二进制文件**：`/bin/`、`/usr/bin/`、`/usr/local/bin/`\r\n- **库文件**：`/lib/`、`/usr/lib/`、`/usr/local/lib/`\r\n- **配置文件**：`/etc/`、`/usr/local/etc/`\r\n- **共享数据文件**：`/usr/share/`、`/usr/local/share/`\r\n- **日志文件**：`/var/log/`\r\n- **临时文件**：`/tmp/`、`/var/tmp/`\r\n- **软件包**：`/opt/`（大型第三方应用）\r\n",
  "Linux/QQ机器人napcat命令.md": "输入 xvfb-run -a qq --no-sandbox 命令启动。 \n保持后台运行 请输入 screen -dmS napcat bash -c \"xvfb-run -a qq --no-sandbox\"  \n后台快速登录 请输入 screen -dmS napcat bash -c \"xvfb-run -a qq --no-sandbox -q QQ号码\"  \nNapcat安装位置 /opt/QQ/resources/app/app_launcher/napcat \nWEBUI_TOKEN 请自行查看/opt/QQ/resources/app/app_launcher/napcat/config/webui.json文件获取 \n注意, 您可以随时使用 screen -r napcat 来进入后台进程并使用 ctrl + a + d 离开(离开不会关闭后台进程)。 \n停止后台运行 \n\n screen -S napcat -X quit ",
  "Linux/screen常用指令.md": "## `screen`命令简介\n\n`screen` 是一个窗口管理器，允许用户在一个单一的终端窗口中运行多个会话。它特别适用于需要长时间运行的进程，因为即使网络连接断开，进程也会继续运行。\n\n## 常用命令\n\n### 启动和使用\n\n- **启动一个新的screen会话**\n  ```bash\n  screen\n  ```\n  或者为会话命名：\n  ```bash\n  screen -S session_name\n  ```\n\n- **列出所有screen会话**\n  ```bash\n  screen -ls\n  ```\n\n- **重新连接到一个已存在的screen会话**\n  ```bash\n  screen -r session_name\n  ```\n\n- **分离当前会话（让会话在后台继续运行）**\n  按下 `Ctrl + A` 然后按 `D`。\n\n- **终止一个screen会话**\n  在会话中按下 `Ctrl + D` 或者输入 `exit`。\n\n### 会话管理\n\n- **强制连接到一个会话**\n  如果有多个会话在运行，使用：\n  ```bash\n  screen -r -d session_name\n  ```\n  这将断开该会话的其他连接并连接到它。\n\n- **多窗口管理**\n  - 创建新窗口：`Ctrl + A` 然后 `C`\n  - 切换窗口：`Ctrl + A` 然后 `N`（下一个），`Ctrl + A` 然后 `P`（上一个）\n  - 列出所有窗口：`Ctrl + A` 然后 `\"`（双引号）\n\n### 会话命名\n\n- **重命名当前窗口**\n  按下 `Ctrl + A` 然后 `A`，输入新的名称。\n\n## 配置文件\n\n- **自定义screen**\n  可以通过编辑 `~/.screenrc` 文件进行配置。例如：\n  ```bash\n  # 开启多窗口状态栏\n  hardstatus on\n  hardstatus alwayslastline\n  hardstatus string \"%{= kG}%-Lw%{= BW}%50>%n%f* %t%{-}%+Lw%<\"\n  ```\n\n## 提示\n\n- 使用 `screen` 可以有效防止因网络不稳定导致的会话中断。\n- 熟练掌握快捷键可以大大提高效率。\n- 对于需要长期运行的任务，如编译或数据处理，`screen` 是一个非常有用的工具。\n\n",
  "Linux/ssh切换root登录通用方法.md": "1. 给root新建密码：sudo passwd root\n2. 配置权限文件:sudo nano /etc/ssh/sshd_config \n3. 光标移动到：permitrootlogin no 把no 改为yes ctrl+o（写入文本）回车  ctrl+x（退出） \n4. 重启服务器：sudo reboot\n5. 重启ssh服务：sudo service sshd restart\n6. 用命令切换root账号：su -（或者sudo su -）",
  "Linux/SSH服务端配置.md": "配置 SSH 服务端（`sshd_config`）是确保服务器安全性和功能性的关键步骤。以下是基于您提供的默认配置文件的详细配置指南，包括关键选项的解释和安全建议。\n\n### 1. 基本配置\n\n#### 端口设置\n默认情况下，SSH 使用端口 22。为了提高安全性，您可以更改为其他端口。\n\n```bash\nPort 22\n```\n\n**建议**：修改为非标准端口（如 `Port 2222`）可以减少被自动扫描攻击的风险。\n\n```bash\nPort 2222\n```\n\n#### 监听地址\n默认配置监听所有 IPv4 地址。\n\n```bash\nListenAddress 0.0.0.0\n#ListenAddress ::\n```\n\n**建议**：如果服务器有多个网络接口，您可以指定特定的 IP 地址来监听。例如，仅监听内部网络：\n\n```bash\nListenAddress 192.168.1.100\n```\n\n### 2. 主机密钥\n\n主机密钥用于验证服务器的身份。确保这些密钥存在并且安全。\n\n```bash\n#HostKey /etc/ssh/ssh_host_rsa_key\n#HostKey /etc/ssh/ssh_host_ecdsa_key\n#HostKey /etc/ssh/ssh_host_ed25519_key\n```\n\n**建议**：取消注释需要的密钥类型，确保至少启用一种强加密算法（如 Ed25519）。\n\n```bash\nHostKey /etc/ssh/ssh_host_ed25519_key\n```\n\n### 3. 身份验证\n\n#### 禁止 root 登录\n出于安全考虑，建议禁止 root 用户通过 SSH 登录。\n\n```bash\n#PermitRootLogin prohibit-password\n```\n\n**建议**：将其设置为 `no` 或 `prohibit-password`，推荐使用密钥认证。\n\n```bash\nPermitRootLogin no\n```\n\n#### 密码认证\n启用或禁用密码认证。为了更高的安全性，建议使用密钥认证并禁用密码认证。\n\n```bash\n#PasswordAuthentication yes\nPasswordAuthentication no\n```\n\n#### 公钥认证\n确保启用公钥认证，并配置 `AuthorizedKeysFile`。\n\n```bash\nPubkeyAuthentication yes\nAuthorizedKeysFile .ssh/authorized_keys\n```\n\n**建议**：保持默认配置，确保每个用户的 `~/.ssh/authorized_keys` 文件中包含正确的公钥。\n\n#### 键盘交互认证\n如果只使用密钥认证，禁用键盘交互认证。\n\n```bash\nKbdInteractiveAuthentication no\n```\n\n### 4. 使用 PAM\n\nPAM（可插拔认证模块）用于增强认证机制。\n\n```bash\nUsePAM yes\n```\n\n**建议**：保持启用，但确保其他认证方法（如密码认证）根据需要进行配置。\n\n### 5. 限制用户和组\n\n通过 `AllowUsers` 或 `AllowGroups` 限制可以通过 SSH 登录的用户或组。\n\n```bash\n# Allow only specific users\n#AllowUsers user1 user2\n\n# Allow only specific groups\n#AllowGroups sshusers\n```\n\n**建议**：根据需要取消注释并配置，限制访问范围。\n\n```bash\nAllowUsers alice bob\n```\n\n### 6. 其他安全设置\n\n#### 禁用空密码登录\n\n```bash\n#PermitEmptyPasswords no\nPermitEmptyPasswords no\n```\n\n**确保**：禁止使用空密码登录。\n\n#### 启用防火墙和限制连接数\n\n配置防火墙（如 `ufw` 或 `iptables`）仅允许必要的端口和 IP 地址访问。同时，可以设置 `MaxAuthTries` 和 `MaxSessions` 来限制尝试次数和并发会话数。\n\n```bash\nMaxAuthTries 3\nMaxSessions 2\n```\n\n### 7. 日志和监控\n\n设置合适的日志级别以监控 SSH 活动。\n\n```bash\nLogLevel VERBOSE\n```\n\n**建议**：根据需要设置日志级别，如 `INFO` 或 `VERBOSE`，并定期检查日志文件（通常位于 `/var/log/auth.log` 或 `/var/log/secure`）。\n\n### 8. 重启 SSH 服务\n\n在完成配置后，重新启动 SSH 服务以应用更改。\n\n```bash\nsudo systemctl restart sshd\n```\n\n**检查配置是否正确**：\n\n在重新启动之前，最好检查配置文件是否有语法错误：\n\n```bash\nsudo sshd -t\n```\n\n如果没有输出，说明配置语法正确。否则，按照错误提示进行修正。\n\n### 9. 其他推荐配置\n\n- **启用双因素认证（2FA）**：增加登录的安全性。\n- **限制 SSH 登录时间**：通过 `sshd_config` 或使用其他工具限制用户的登录时间。\n- **使用 Fail2Ban**：防止暴力破解攻击，通过监控日志文件并动态更新防火墙规则。\n\n### 示例优化后的 `sshd_config`\n\n以下是根据上述建议优化后的配置示例：\n\n```bash\nPort 2222\nListenAddress 0.0.0.0\nHostKey /etc/ssh/ssh_host_ed25519_key\n\nPubkeyAuthentication yes\nAuthorizedKeysFile .ssh/authorized_keys\n\nPermitRootLogin no\nPasswordAuthentication no\nKbdInteractiveAuthentication no\n\nUsePAM yes\n\nAllowUsers alice bob\n\nLogLevel VERBOSE\n\nMaxAuthTries 3\nMaxSessions 2\n\nAcceptEnv LANG LC_*\n\nSubsystem\tsftp\t/usr/lib/openssh/sftp-server\n```\n\n",
  "Linux/systemctl命令详细总结.md": "\n### Linux `systemctl` 命令常用用法总结\n\n\n#### **一、服务管理（核心功能）**\n`systemctl` 主要用于管理系统服务（`.service` 文件），支持启动、停止、重启、查看状态、设置开机启动等操作。\n\n##### 1. 服务状态操作\n| 操作                | 命令                                  | 说明                                                                 |\n|---------------------|---------------------------------------|----------------------------------------------------------------------|\n| 启动服务            | `systemctl start <服务名>`            | 启动指定服务（仅临时生效，重启后不保留）                             |\n| 停止服务            | `systemctl stop <服务名>`             | 停止指定服务                                                         |\n| 重启服务            | `systemctl restart <服务名>`          | 重启服务（若服务未运行则启动）                                         |\n| 重新加载配置        | `systemctl reload <服务名>`           | 重新加载服务配置文件（不重启服务，适用于支持此功能的服务，如 Nginx） |\n| 平滑重启（优雅重启）| `systemctl try-restart <服务名>`      | 仅在服务运行时重启，避免报错                                         |\n\n##### 2. 服务状态查询\n| 操作                | 命令                                  | 说明                                                                 |\n|---------------------|---------------------------------------|----------------------------------------------------------------------|\n| 查看状态            | `systemctl status <服务名>`           | 显示服务运行状态、日志及依赖关系（按 `Q` 退出）                     |\n| 简洁状态            | `systemctl is-active <服务名>`        | 仅显示服务是否激活（active/running）                                |\n| 查看是否启用开机启动| `systemctl is-enabled <服务名>`       | 显示服务是否设置为开机启动（enabled/disabled）                      |\n| 列出所有服务        | `systemctl list-units --type=service` | 列出所有运行中的服务                                                |\n| 列出所有服务（含未激活）| `systemctl list-units --type=service --all` | 显示所有服务，包括未激活的（状态为 inactive/failed 等）          |\n| 列出失败的服务      | `systemctl --failed --type=service`   | 查看启动失败的服务                                                   |\n\n##### 3. 开机启动管理\n| 操作            | 命令                              | 说明                         |\n| ------------- | ------------------------------- | -------------------------- |\n| 启用开机启动        | `systemctl enable <服务名>`        | 设置服务开机自动启动（永久生效，关联到默认运行目标） |\n| 禁用开机启动        | `systemctl disable <服务名>`       | 取消服务开机启动                   |\n| 临时启用（仅本次启动）   | `systemctl enable --now <服务名>`  | 立即启动服务并设置开机启动              |\n| 临时禁用（停止并取消启动） | `systemctl disable --now <服务名>` | 立即停止服务并取消开机启动              |\n\n##### 4. 服务依赖与依赖关系\n| 操作                | 命令                                  | 说明                                                                 |\n|---------------------|---------------------------------------|----------------------------------------------------------------------|\n| 查看依赖关系        | `systemctl list-dependencies <服务名>` | 显示服务的依赖项（依赖它的服务 + 它依赖的服务）                     |\n| 查看直接依赖        | `systemctl list-dependencies --reverse <服务名>` | 仅显示依赖该服务的其他服务                                       |\n\n\n#### **二、系统状态与控制**\n##### 1. 系统基本状态\n| 操作                | 命令                                  | 说明                                                                 |\n|---------------------|---------------------------------------|----------------------------------------------------------------------|\n| 查看系统运行时间    | `systemctl uptime`                    | 显示系统已运行时间（类似 `uptime` 命令）                            |\n| 查看启动耗时        | `systemctl time`                      | 显示系统启动总耗时及各阶段（内核、用户空间、服务）耗时              |\n| 查看登录会话        | `systemctl list-sessions`             | 列出当前登录的用户会话                                               |\n\n##### 2. 电源管理（需管理员权限）\n| 操作                | 命令                                  | 说明                                                                 |\n|---------------------|---------------------------------------|----------------------------------------------------------------------|\n| 关机                | `systemctl poweroff`                  | 立即关机                                                             |\n| 重启                | `systemctl reboot`                    | 立即重启                                                             |\n| 休眠（挂起到硬盘）  | `systemctl hibernate`                 | 系统进入休眠状态                                                     |\n| 睡眠（挂起到内存）  | `systemctl suspend`                   | 系统进入睡眠状态（低功耗，断电数据丢失）                             |\n| 混合休眠            | `systemctl hybrid-sleep`              | 同时休眠到内存和硬盘，结合两者优势                                 |\n| 取消挂起/休眠      | `systemctl wakeup`                    | 唤醒系统（需配合定时器使用）                                         |\n\n##### 3. 运行目标（替代传统运行级别）\n| 操作                | 命令                                  | 说明                                                                 |\n|---------------------|---------------------------------------|----------------------------------------------------------------------|\n| 查看当前目标        | `systemctl get-default`               | 显示默认运行目标（如 `graphical.target` 对应图形界面）              |\n| 切换目标            | `systemctl isolate <目标名>`           | 切换到指定目标（如 `multi-user.target` 为无图形多用户模式）         |\n| 设置默认目标        | `systemctl set-default <目标名>`       | 设置开机默认目标（需管理员权限）                                     |\n\n**常用目标对应关系**：  \n- `graphical.target`：图形界面（对应传统运行级别 5）  \n- `multi-user.target`：无图形多用户模式（对应级别 3）  \n- `rescue.target`：单用户救援模式（对应级别 1）  \n- `emergency.target`：紧急模式（无文件系统挂载，仅基本命令）  \n\n\n#### **三、定时器管理（systemd.timer）**\n`systemctl` 可管理定时任务（替代传统 `cron`），需配合 `.timer` 文件使用。\n\n| 操作                | 命令                                  | 说明                                                                 |\n|---------------------|---------------------------------------|----------------------------------------------------------------------|\n| 列出所有定时器      | `systemctl list-timers`               | 显示激活的定时器及其下一次触发时间                                   |\n| 查看定时器状态      | `systemctl status <定时器名>`         | 显示定时器详细状态及日志                                             |\n| 启用/禁用定时器     | `systemctl enable/disable <定时器名>`  | 控制定时器是否开机启动                                               |\n| 立即触发定时器任务  | `systemctl start <定时器名>`          | 强制立即执行定时器关联的服务                                         |\n\n\n#### **四、资源控制与限制（高级功能）**\n可对服务设置 CPU、内存、IO 等资源限制（需在服务文件中配置，或临时生效）。\n\n| 操作                | 命令                                  | 说明                                                                 |\n|---------------------|---------------------------------------|----------------------------------------------------------------------|\n| 设置 CPU 核心限制   | `systemctl set-property <服务名> CPUAffinity=0,1` | 限制服务仅运行在 CPU 0 和 1 核心                     |\n| 设置内存上限        | `systemctl set-property <服务名> MemoryMax=1G` | 限制服务最大内存使用量为 1GB                                       |\n| 恢复默认资源配置    | `systemctl unset-property <服务名> CPUAffinity MemoryMax` | 清除已设置的资源限制                                             |\n\n\n#### **五、日志相关（结合 journalctl）**\n| 操作                | 命令                                  | 说明                                                                 |\n|---------------------|---------------------------------------|----------------------------------------------------------------------|\n| 查看服务日志        | `systemctl status <服务名> -l`        | 显示服务状态并附带日志（`-l` 展开完整日志）                         |\n| 实时监控日志        | `journalctl -u <服务名> -f`           | 实时追踪服务日志（需结合 `journalctl` 命令）                         |\n| 查看历史日志        | `journalctl -u <服务名> --since \"2025-05-01\"` | 查看指定时间后的服务日志                               |\n\n\n#### **六、常用选项与技巧**\n- **通配符匹配**：  \n  可使用通配符管理同类服务，例如：  \n  ```bash\n  systemctl start nginx*.service  # 启动所有以 nginx 开头的服务\n  systemctl stop *.timer          # 停止所有定时器服务\n  ```\n\n- **强制操作**：  \n  `--force` 用于强制停止/重启服务（可能终止进程）：  \n  ```bash\n  systemctl --force stop <服务名>\n  ```\n\n- **临时生效（不修改配置）**：  \n  使用 `--now` 可立即执行操作并关联开机启动（或取消）：  \n  ```bash\n  systemctl enable --now <服务名>  # 启动并启用开机启动\n  systemctl disable --now <服务名> # 停止并禁用开机启动\n  ```\n\n- **查看帮助**：  \n  ```bash\n  systemctl --help                 # 查看全局帮助\n  systemctl help <子命令>          # 查看子命令详细用法（如 systemctl help start）\n  ```\n\n\n#### **七、示例场景**\n1. **管理 Nginx 服务**：  \n   ```bash\n   systemctl start nginx       # 启动 Nginx\n   systemctl enable nginx      # 设置开机启动\n   systemctl status nginx      # 查看运行状态\n   systemctl reload nginx      # 重新加载配置\n   ```\n\n2. **系统关机与重启**：  \n   ```bash\n   systemctl reboot            # 立即重启\n   systemctl poweroff          # 立即关机\n   systemctl suspend           # 进入睡眠\n   ```\n\n3. **设置默认运行目标**：  \n   ```bash\n   systemctl set-default multi-user.target  # 设为无图形多用户模式\n   systemctl isolate rescue.target         # 进入单用户救援模式\n   ```\n\n\n### 总结\n`systemctl` 是 systemd 生态的核心工具，覆盖服务管理、系统控制、定时任务、资源限制等功能。熟练掌握其常用命令可高效管理 Linux 系统服务与状态，替代传统 SysVinit 的 `service`、`chkconfig` 等工具。建议结合 `journalctl` 分析服务日志，通过服务文件（`/etc/systemd/system/`）自定义复杂配置。`systemctl` 是 Linux 系统中用于控制 `systemd` 系统和服务管理器的命令。以下是 `systemctl` 命令的一些常用用法总结：\n\n### 1. 服务管理\n#### 启动服务\n```bash\nsystemctl start <服务名>\n```\n例如，启动 `httpd` 服务：\n```bash\nsystemctl start httpd\n```\n\n#### 停止服务\n```bash\nsystemctl stop <服务名>\n```\n例如，停止 `httpd` 服务：\n```bash\nsystemctl stop httpd\n```\n\n#### 重启服务\n```bash\nsystemctl restart <服务名>\n```\n例如，重启 `httpd` 服务：\n```bash\nsystemctl restart httpd\n```\n\n#### 重新加载服务配置\n```bash\nsystemctl reload <服务名>\n```\n例如，重新加载 `nginx` 服务配置：\n```bash\nsystemctl reload nginx\n```\n\n#### 查看服务状态\n```bash\nsystemctl status <服务名>\n```\n例如，查看 `httpd` 服务状态：\n```bash\nsystemctl status httpd\n```\n\n### 2. 服务的开机自启管理\n#### 设置服务开机自启\n```bash\nsystemctl enable <服务名>\n```\n例如，设置 `httpd` 服务开机自启：\n```bash\nsystemctl enable httpd\n```\n\n#### 禁止服务开机自启\n```bash\nsystemctl disable <服务名>\n```\n例如，禁止 `httpd` 服务开机自启：\n```bash\nsystemctl disable httpd\n```\n\n#### 查看服务是否开机自启\n```bash\nsystemctl is-enabled <服务名>\n```\n例如，查看 `httpd` 服务是否开机自启：\n```bash\nsystemctl is-enabled httpd\n```\n\n### 3. 系统管理\n#### 重启系统\n```bash\nsystemctl reboot\n```\n\n#### 关机\n```bash\nsystemctl poweroff\n```\n\n#### 挂起系统\n```bash\nsystemctl suspend\n```\n\n#### 休眠系统\n```bash\nsystemctl hibernate\n```\n\n#### 混合休眠（挂起并休眠）\n```bash\nsystemctl hybrid-sleep\n```\n\n### 4. 查看系统状态\n#### 查看系统当前运行级别\n```bash\nsystemctl get-default\n```\n\n#### 设置系统默认运行级别\n```bash\nsystemctl set-default <目标运行级别>\n```\n例如，设置系统默认运行级别为多用户模式：\n```bash\nsystemctl set-default multi-user.target\n```\n\n### 5. 查看服务列表\n#### 查看所有已激活的服务\n```bash\nsystemctl list-units --type=service --state=active\n```\n\n#### 查看所有服务（包括未激活的）\n```bash\nsystemctl list-units --type=service --all\n```\n\n",
  "Linux/Termux/service-frpc.md": "```bash\nbash -lc '\nset -e\nmkdir -p \"$PREFIX/var/service/frpc/log\"\nln -sf \"$PREFIX/share/termux-services/svlogger\" \\\n  \"$PREFIX/var/service/frpc/log/run\"\n\ncat > \"$PREFIX/var/service/frpc/run\" <<'\"'\"'EOF'\"'\"'\n#!/data/data/com.termux/files/usr/bin/sh\nexec 2>&1\ncd \"$HOME/frpc\"\nexec frpc -c \"$HOME/frpc/frpc.toml\"\nEOF\n\nchmod +x \"$PREFIX/var/service/frpc/run\" \\\n         \"$PREFIX/var/service/frpc/log/run\"\n\necho \"✅ frpc service 已创建\"\necho \"👉 启动：sv up frpc\"\necho \"👉 状态：sv status frpc\"\necho \"👉 日志：tail -n 200 $PREFIX/var/log/sv/frpc/current\"\n'\n```",
  "Linux/Termux/service-openlist.md": "```shell\nbash -lc '\nset -e\n\n# 1) 准备 service 目录 + log 目录\nmkdir -p \"$PREFIX/var/service/openlist/log\"\n\n# 2) 绑定官方 logger\nln -sf \"$PREFIX/share/termux-services/svlogger\" \\\n  \"$PREFIX/var/service/openlist/log/run\"\n\n# 3) 写 run 脚本（沿用你现有的 ~/data 数据目录）\ncat > \"$PREFIX/var/service/openlist/run\" <<'\"'\"'EOF'\"'\"'\n#!/data/data/com.termux/files/usr/bin/sh\nexec 2>&1\ncd \"$HOME\"\nexec openlist server --data \"$HOME/data\"\nEOF\n\nchmod +x \"$PREFIX/var/service/openlist/run\" \\\n         \"$PREFIX/var/service/openlist/log/run\"\n\necho \"✅ openlist service 已创建\"\necho \"👉 现在可用：sv up openlist\"\necho \"👉 查看状态：sv status openlist\"\necho \"👉 查看日志：tail -n 200 $PREFIX/var/log/sv/openlist/current\"\n'\n```\n\n```bash\nsv up openlist\nsv status openlist\n# 想让 Termux 每次打开就自动拉起：\nsv-enable openlist\n```",
  "Linux/Termux/shell2http举例.md": "`shell2http` 的灵活性和轻量级特性让它能玩出许多有趣的花样！以下是一些创意使用案例，涵盖实用场景和趣味玩法：\n\n---\n\n### **一、智能家居 & 自动化**\n1. **远程控制智能插座**  \n   ```bash\n   shell2http -basic-auth=\"admin:密码\" POST:/灯控 'curl -X POST http://智能插座IP/开关 -d \"state=on\"'\n   ```\n   - 用途：用手机浏览器一键开关灯，配合 Siri 快捷指令还能语音控制。\n\n2. **树莓派摄像头拍照**  \n   ```bash\n   shell2http /拍照 'raspistill -o /tmp/snapshot.jpg && base64 /tmp/snapshot.jpg'\n   ```\n   - 用途：远程拍照并返回 Base64 图片，可嵌入网页实时查看。\n\n3. **温湿度监控**  \n   ```bash\n   shell2http /温湿度 'python3 读取传感器脚本.py'\n   ```\n   - 用途：连接 DHT11/DHT22 传感器，通过 HTTP 返回 JSON 格式温湿度数据。\n\n---\n\n### **二、实用工具**\n4. **临时文件共享**  \n   ```bash\n   shell2http -form /upload 'mv $filepath_file1 ./共享文件夹/$filename_file1 && echo 上传成功'\n   ```\n   - 用途：在局域网内快速共享文件，上传后生成直链供他人下载。\n\n5. **二维码生成器**  \n   ```bash\n   shell2http /qrcode \"qrencode -t ANSIUTF8 '$v_text'\"\n   ```\n   - 用法：访问 `http://IP:8080/qrcode?text=HelloWorld`，终端直接显示二维码。\n\n6. **DDNS 动态域名更新**  \n   ```bash\n   shell2http /update_ddns 'curl \"https://ddns服务商API?ip=$(curl ifconfig.me)\"'\n   ```\n   - 用途：外网触发更新 DDNS 记录，解决家庭宽带 IP 变化问题。\n\n---\n\n### **三、趣味玩法**\n7. **语音播报远程控制**  \n   ```bash\n   shell2http POST:/说话 'echo \"$v_text\" | espeak -v zh'  # Linux 文本转语音\n   ```\n   - 用途：用手机输入文字，让电脑念出来（比如捉弄同事）。\n\n8. **在线抽奖/随机选择**  \n   ```bash\n   shell2http /抽奖 'shuf -n1 名单.txt'\n   ```\n   - 用途：年会时打开网页点击按钮，大屏幕显示中奖者。\n\n9. **生成梗图**  \n   ```bash\n   shell2http -form /生成表情包 'convert 模板.jpg -pointsize 30 -fill white -annotate +100+200 \"$v_text\" -' \n   ```\n   - 用途：上传文字生成表情包，可集成到微信群机器人。\n\n---\n\n### **四、开发调试**\n10. **模拟慢速 API**  \n    ```bash\n    shell2http /slow 'sleep ${v_time:-5} && echo 响应完成'\n    ```\n    - 用途：测试前端 Loading 效果，访问 `/slow?time=10` 模拟 10 秒延迟。\n\n11. **Mock 测试接口**  \n    ```bash\n    shell2http /api/user 'echo \"{\\\"name\\\":\\\"张三\\\",\\\"age\\\":$(shuf -i 20-60 -n1)}\"'\n    ```\n    - 用途：快速生成随机 JSON 数据，替代未完成的真实接口。\n\n12. **代理请求记录器**  \n    ```bash\n    shell2http -cgi /proxy 'echo \"URL: $REQUEST_URI\" >> log.txt; curl -s \"$v_url\"'\n    ```\n    - 用途：记录所有经过的请求参数，调试第三方回调。\n\n---\n\n### **五、系统管理**\n13. **服务器监控面板**  \n    ```bash\n    shell2http /cpu \"top -bn1 | grep 'Cpu(s)'\" /内存 \"free -h\" /磁盘 \"df -h\"\n    ```\n    - 用途：手机浏览器快速查看服务器状态。\n\n14. **远程重启服务**  \n    ```bash\n    shell2http -500 POST:/reboot_nginx 'systemctl restart nginx && echo 成功'\n    ```\n    - 用途：内网安全重启服务（务必设置 Basic 认证！）。\n\n15. **日志实时查看**  \n    ```bash\n    shell2http /tail_log 'tail -n20 /var/log/syslog'\n    ```\n    - 用途：快速检查日志，无需 SSH 登录。\n\n---\n\n### **注意事项**\n- **安全第一**：暴露在公网时务必启用 `-basic-auth` 和 HTTPS。\n- **权限控制**：敏感操作（如重启服务）建议结合 IP 白名单。\n- **临时用途**：适合原型设计或内部工具，不建议替代专业 API 网关。\n\n这些案例只需简单修改即可运行，试试用 `shell2http` 把你身边的硬件和脚本变成「物联网设备」吧！",
  "Linux/Termux/shell2HTTP软件简单总结.md": "以下是 `shell2http` 项目的详细中文总结：\n\n---\n\n### **项目概述**\n`shell2http` 是一个用 Go 编写的轻量级 HTTP 服务器，核心功能是通过 HTTP 请求触发执行预定义的 Shell 命令，并将结果返回给客户端。它适用于开发调试、原型设计、远程控制等场景，支持快速将 Shell 脚本暴露为 HTTP 接口。\n\n---\n\n### **核心功能**\n1. **简单易用**  \n   - 通过命令行参数直接绑定 URL 路径与 Shell 命令，例如：  \n     ```shell\n     shell2http /date \"date\" /ps \"ps aux\"\n     ```\n   - 支持 GET、POST 等多种 HTTP 方法（通过 `METHOD:/path` 语法指定）。\n\n2. **请求处理模式**  \n   - **普通模式**：直接执行命令，返回标准输出（stdout）。\n   - **表单模式（`-form`）**：解析查询参数和上传文件，生成环境变量供脚本使用：\n     - `$v_参数名`：来自 URL 查询参数的值（如 `?id=123` → `$v_id`）。\n     - `$filepath_字段名`：上传文件的临时路径。\n     - `$filename_字段名`：上传文件的原始文件名。\n   - **CGI 模式（`-cgi`）**：模拟 CGI 环境，设置 HTTP 请求相关环境变量，处理请求体数据。\n\n3. **安全与认证**  \n   - **Basic 认证**：通过 `-basic-auth` 设置用户名密码，支持多用户。\n   - **SSL/TLS**：使用 `-cert` 和 `-key` 选项启动 HTTPS 服务器。\n   - **表单字段过滤**：通过 `-form-check` 限制参数名格式（如仅允许数字）。\n\n4. **高级特性**  \n   - **缓存**：`-cache=N` 缓存命令输出 N 秒。\n   - **超时控制**：`-timeout` 设置命令执行超时时间。\n   - **错误处理**：`-500` 在命令非零退出时返回 500 错误；`-show-errors` 显示错误输出。\n   - **环境变量**：支持导出特定或全部环境变量（`-export-vars`/`-export-all-vars`）。\n\n5. **日志与调试**  \n   - 自定义日志文件（`-log`）、禁用时间戳（`-no-log-timestamp`）。\n\n---\n\n### **安装方式**\n1. **MacOS**  \n   ```shell\n   brew install msoap/tools/shell2http\n   ```\n2. **Docker**  \n   ```shell\n   docker pull msoap/shell2http\n   docker run -p 8080:8080 msoap/shell2http /date \"date\"\n   ```\n   - 使用 `--init` 防止僵尸进程。\n\n3. **Snap（Linux）**  \n   ```shell\n   sudo snap install shell2http\n   ```\n   - 注意沙箱环境可能导致路径问题。\n\n4. **源码编译**  \n   ```shell\n   go install github.com/msoap/shell2http@latest\n   ```\n\n5. **预编译二进制**  \n   从 [GitHub Releases](https://github.com/msoap/shell2http/releases) 下载（支持 Windows、Linux、MacOS、树莓派）。\n\n---\n\n### **使用示例**\n1. **基础命令**  \n   ```shell\n   shell2http /top \"top -l 1 | head -10\" /date \"date\"\n   ```\n   - 访问 `http://localhost:8080/date` 返回当前时间。\n\n2. **环境变量**  \n   ```shell\n   shell2http -export-vars=GOPATH /gopath 'echo $GOPATH'\n   ```\n\n3. **表单处理**  \n   ```shell\n   shell2http -form /upload 'cp $filepath_file1 ./uploads/$filename_file1'\n   ```\n   - 上传文件并保存到 `uploads` 目录。\n\n4. **CGI 模式**  \n   ```shell\n   shell2http -cgi /cgi-script './script.sh'\n   ```\n   - 脚本可读取请求头、请求体，设置响应头。\n\n5. **HTTPS 服务器**  \n   ```shell\n   shell2http -cert=cert.pem -key=key.pem /date \"date\"\n   ```\n   - 生成自签名证书：  \n     ```shell\n     go run $(go env GOROOT)/src/crypto/tls/generate_cert.go -host localhost\n     ```\n\n---\n\n### **应用场景**\n- **系统监控**：暴露 `top`、`ps`、`df` 等命令的 HTTP 接口。\n- **文件操作**：上传/下载文件、目录列表。\n- **远程控制**：调节音量、控制媒体播放器（如 MacOS 的 Vox.app）。\n- **API 模拟**：返回静态 JSON 或动态生成数据。\n- **调试工具**：模拟慢速响应、记录请求日志。\n\n---\n\n### **相关工具**\n- **shell2telegram**：将 Shell 命令绑定到 Telegram 机器人。\n- **websocketd**：将 STDIN/STDOUT 程序转换为 WebSocket 服务。\n- **devd**：本地开发的轻量级 HTTP 守护进程。\n\n---\n\n### **注意事项**\n- **安全性**：避免在生产环境暴露敏感命令，使用防火墙和认证机制。\n- **性能**：默认多线程处理请求，可通过 `-one-thread` 限制为单线程。\n- **路径问题**：Docker 或 Snap 环境需注意命令的可访问性。\n\n通过灵活配置，`shell2http` 可快速搭建功能丰富的 HTTP 服务，适合开发者和运维人员简化工作流程。",
  "Linux/Termux/Termux-api用法总结/弹窗.md": "`termux-toast` 命令用于在 Android 设备上显示一个短暂的消息（Toast）。这个消息会在屏幕上弹出，并在几秒钟后自动消失。它的基本用法如下：\n\n### 基本用法\n\n```bash\ntermux-toast [选项] <消息文本>\n```\n\n### 常用选项\n\n- `-s` 或 `--short`：使用短时间显示消息（默认选项）。\n- `-l` 或 `--long`：使用较长时间显示消息。\n- `-g` 或 `--gravity`：设置消息显示的位置。可选值为 `top`、`middle` 和 `bottom`（默认是 `bottom`）。\n- `-b` 或 `--background`：设置背景颜色，使用十六进制颜色代码。\n- `-c` 或 `--color`：设置文本颜色，使用十六进制颜色代码.\n\n### 示例\n\n1. **显示一个默认的短消息**：\n\n   ```bash\n   termux-toast \"Hello, World!\"\n   ```\n\n3. **在屏幕顶部显示消息**：\n\n   ```bash\n   termux-toast -g top \"This message is at the top.\"\n   ```\n\n4. **设置背景和文本颜色**：\n\n   ```bash\n   termux-toast -b \"#FF0000\" -c \"#FFFFFF\" \"Red background with white text.\"\n   ```\n\n这些命令可以在脚本中使用，以便在某些事件发生时通知用户。请注意，由于 Toast 本质上是短暂的通知类型，它们不适合显示需要用户交互或长时间关注的重要信息。",
  "Linux/Termux/Termux-api用法总结/录音.md": "当然！以下是一些使用 `termux-microphone-record` 命令的示例，展示了如何利用不同的参数来满足不同的录音需求：\n\n1. **使用默认设置开始录音**：\n   ```bash\n   termux-microphone-record -d\n   ```\n   这将使用默认设置开始录音，并保存到默认文件。\n\n2. **录制到指定文件**：\n   ```bash\n   termux-microphone-record -f /sdcard/my_recording.wav\n   ```\n   这会将录音保存到 `/sdcard/my_recording.wav` 文件中。\n\n3. **限制录音时间为 30 秒**：\n   ```bash\n   termux-microphone-record -f /sdcard/my_recording.wav -l 30\n   ```\n   这将录制 30 秒的音频，并保存到指定文件。\n\n4. **使用特定编码器（例如 AAC）录音**：\n   ```bash\n   termux-microphone-record -f /sdcard/my_recording.aac -e aac\n   ```\n   这会使用 AAC 编码器进行录音。\n\n5. **指定比特率为 128 kbps**：\n   ```bash\n   termux-microphone-record -f /sdcard/my_recording.wav -b 128\n   ```\n   这将以 128 kbps 的比特率进行录音。\n\n6. **使用特定采样率（例如 44100 Hz）录音**：\n   ```bash\n   termux-microphone-record -f /sdcard/my_recording.wav -r 44100\n   ```\n   这会以 44100 Hz 的采样率录音。\n\n7. **使用双声道录音**：\n   ```bash\n   termux-microphone-record -f /sdcard/my_recording.wav -c 2\n   ```\n   这会以双声道（立体声）进行录音。\n\n8. **获取当前录音的信息**：\n   ```bash\n   termux-microphone-record -i\n   ```\n   这将显示有关当前录音的详细信息。\n\n9. **停止当前录音**：\n   ```bash\n   termux-microphone-record -q\n   ```\n   这会停止当前正在进行的录音。\n\n这些示例展示了如何使用 `termux-microphone-record` 的不同参数来调整录音的输出。你可以根据需要组合这些参数来实现更复杂的录音配置。",
  "Linux/Termux/Termux-api用法总结/所有支持的api.md": "Termux API 是一个提供设备功能访问的工具，允许在 Termux 环境中通过命令行接口访问 Android 设备的各种硬件和系统功能。以下是这些 Termux API 的简单介绍：\n\n1. **termux-api-start/stop**：启动或停止 Termux API 服务。\n2. **termux-audio-info**：获取设备的音频信息。\n3. **termux-battery-status**：获取设备的电池状态信息。\n4. **termux-brightness**：设置或获取屏幕亮度。\n5. **termux-call-log**：访问设备的通话记录。\n6. **termux-camera-info**：获取设备相机信息。\n7. **termux-camera-photo**：使用设备相机拍照。\n8. **termux-clipboard-get/set**：获取或设置设备的剪贴板内容。\n9. **termux-contact-list**：获取设备的联系人列表。\n10. **termux-dialog**：显示对话框。\n11. **termux-download**：下载文件。\n12. **termux-fingerprint**：使用指纹传感器进行身份验证。\n13. **termux-infrared-frequencies/transmit**：获取红外频率信息或发送红外信号。\n14. **termux-job-scheduler**：安排一个任务在特定时间运行。\n15. **termux-keystore**：访问或管理密钥存储。\n16. **termux-location**：获取设备的地理位置信息。\n17. **termux-media-player**：播放媒体文件。\n18. **termux-media-scan**：扫描媒体文件。\n19. **termux-microphone-record**：录制音频。\n20. **termux-nfc**：访问 NFC 功能。\n21. **termux-notification/channel/list/remove**：管理通知，包括创建、列出和移除通知。\n22. **termux-saf-create/dirs/ls/managedir/mkdir/read/rm/stat/write**：通过 Storage Access Framework (SAF) 访问和管理文件系统。\n23. **termux-sensor**：访问设备的传感器数据。\n24. **termux-share**：共享文件或文本。\n25. **termux-sms-inbox/list/send**：访问和管理短信，包括查看收件箱和发送短信。\n26. **termux-speech-to-text**：将语音转换为文本。\n27. **termux-storage-get**：从设备存储中获取文件。\n28. **termux-telephony-call/cellinfo/deviceinfo**：拨打电话或获取设备的电话信息。\n29. **termux-toast**：显示一个短暂的消息。\n30. **termux-torch**：控制设备的手电筒。\n31. **termux-tts-engines/speak**：获取 TTS 引擎信息或合成语音。\n32. **termux-usb**：访问 USB 设备。\n33. **termux-vibrate**：控制设备的振动。\n34. **termux-volume**：获取或设置音量。\n35. **termux-wallpaper**：设置设备的壁纸。\n36. **termux-wifi-connectioninfo/enable/scaninfo**：管理 Wi-Fi 连接，获取连接信息或扫描 Wi-Fi 网络。\n\n这些 API 提供了丰富的功能，可以让用户通过脚本自动化许多任务或访问设备的硬件功能。",
  "Linux/Termux/Termux-api用法总结/闪光灯.md": "`termux-torch` 命令用于控制 Android 设备的手电筒（通常是相机闪光灯）。可以通过此命令打开或关闭手电筒。它的基本用法如下：\n\n### 基本用法\n\n```bash\ntermux-torch <状态>\n```\n\n### 参数\n\n- `<状态>`：指定手电筒的状态，可以是 `on` 或 `off`。\n  - `on`：打开手电筒。\n  - `off`：关闭手电筒。\n\n### 示例\n\n1. **打开手电筒**：\n\n   ```bash\n   termux-torch on\n   ```\n\n2. **关闭手电筒**：\n\n   ```bash\n   termux-torch off\n   ```\n\n这些命令可以在脚本中使用，以便在特定情况下自动打开或关闭手电筒，比如在黑暗环境中需要光源时。使用这些命令时，请确保授予 Termux 应用程序相应的权限，以便访问设备的相机闪光灯功能。",
  "Linux/Termux/Termux-SSH相关.md": "Termux更改终端密码:\n```\npasswd\n```\n重启SSH服务\n```\npkill sshd \nsshd\n```\n查看本机IP\n```\nifconfig\n```\n生成SSH主机密钥\n```\nssh-keygen -A\n```\n更新Termux包\n```\npkg update && pkg upgrade\n```\nTermux退出chroot容器\n```\nexit\n```\nTermux安装软件\n```\npkg install \n```\n查看终端用户名\n```\nwhoami\n```\n\n\n\n",
  "Linux/Termux/Termux常用命令.md": "\n**termux-setup-storage** \n挂载外部储存目录\n\n**termux-wake-lock**\n获取唤醒锁（免杀后台）\n\n**termux-battery-status**\n查看设备电池状态",
  "Linux/Termux/Termux常用软件包.md": "**termux-services** \n持久化后台服务，类似于systemctl\n\n**openlist**\n网页云盘\n\n**frp**\n内网穿透工具",
  "Linux/Termux/termux的pkg命令总结.md": "pkg  是用于管理 apt 软件包的工具，用法为  pkg [--check-mirror] command [arguments] ， --check-mirror  强制重新检查镜像可用性。其命令包括：\n \n autoclean ：从 apt 缓存中删除所有过时软件包。\n \n clean ：从 apt 缓存中删除所有软件包。\n \n files <packages> ：显示指定软件包安装的所有文件。\n \n install <packages> ：安装指定软件包。\n \n list-all ：列出仓库中所有可用软件包。\n \n list-installed ：列出已安装的软件包。\n \n reinstall <packages> ：以最新版本重新安装指定已安装软件包。\n \n search <query> ：按名称或描述等查询搜索软件包。\n \n show <packages> ：显示软件包基本元数据，如依赖项。\n \n uninstall <packages> ：卸载指定软件包，保留配置文件。\n \n upgrade ：将所有已安装软件包升级到最新版本。\n \n update ：从配置的仓库更新 apt 数据库。",
  "Linux/Termux/Termux问题小总结.md": "\n#### 使用termux-setup-storage无法访问外部储存\n>在报告问题前，请务必在 Android `14` 上运行 `pkg install termux-am`。\n>\n>存储权限的授予方式如下。\n>\n>- Android `< 11`： `Android Settings` -> `Apps` -> `Termux` -> `Permissions` -> `Storage`\n>- Android `>= 11`： `Android 设置`  ->  `应用`  -> `Termux` ->  `权限`  ->  `文件和媒体`  ->  `允许管理所有文件`\n>- Android `>= 13`： `Android Settings` -> `Apps` -> （`Advanced` ->）  `特殊应用访问`  ->  `所有文件访问`  -> `Termux`\n>\n>如果使用 GitHub 动作构建，运行 `test -d \"$HOME/storage\" || termux-am broadcast --user 0 --es com.termux.app.reload_style storage -a com.termux.app.reload_style com.termux > /dev/null` 应该可以。\n>\n>至于 `termux-setup-storage` 不工作，运行命令后，请发送或发送邮件给我 `adb logcat -d > logcat.txt` 输出。\n\n\n",
  "Linux/ubuntu设置root登陆.md": "在 Ubuntu GNOME 22.04 中，默认情况下是禁用 root 用户的登录，以提高系统安全性。如果你需要启用 root 用户并允许其通过图形界面登录，可以按照以下步骤操作：\n\n### 1. 启用 Root 用户\n\nUbuntu 默认情况下禁用了 root 用户账户，因此我们需要为 root 设置密码才能启用它。\n\n1. 打开终端，使用以下命令设置 root 用户密码：\n\n   ```bash\n   sudo passwd root\n   ```\n\n   然后根据提示输入并确认 root 用户密码。\n\n### 2. 允许 Root 用户登录图形界面\n\nUbuntu 默认不允许 root 用户直接登录 GNOME 图形界面。如果你希望启用 root 登录图形界面，需要修改 GDM（GNOME Display Manager）的配置文件。\n\n1. 编辑 GDM 配置文件：\n\n   ```bash\n   sudo nano /etc/gdm3/custom.conf\n   ```\n\n2. 找到 `[security]` 部分，并确保以下行没有被注释掉（没有 `#`）：\n\n   ```plaintext\n   AllowRoot=true\n   ```\n\n3. 保存并退出（按 `Ctrl + O` 保存，`Ctrl + X` 退出）。\n\n### 3. 重启 GDM\n\n配置更改后，重启 GDM 或重新启动计算机以使更改生效。你可以使用以下命令重启 GDM：\n\n```bash\nsudo systemctl restart gdm3\n```\n\n### 4. 使用 root 登录\n\n现在，你应该能够在登录屏幕选择 root 用户进行登录了。只需要输入你为 root 设置的密码即可。\n\n### 5. 注意安全\n\n启用 root 用户图形界面登录可能会增加系统的安全风险，因为 root 用户具有系统的完全控制权限。为了保护系统的安全性，建议仅在必要时启用 root 登录，并使用强密码以及定期检查系统的安全性。\n\n如果你不需要 root 图形界面登录，建议使用 `sudo` 命令来执行管理员操作，这样可以减少潜在的安全风险。\n\n",
  "Linux/Windows文件一键上传到Linux.md": "\n**萌芽农场**\n```powershell\nscp -r D:\\Godot\\Godot项目\\比较完成的作品\\萌芽农场\\Server\\* root@192.168.31.233:/shumengya/docker/mengyafarmserver/\n\nscp -r D:\\Godot\\Godot项目\\比较完成的作品\\萌芽农场\\Server\\* root@192.168.1.233:/shumengya/docker/mengyafarmserver/\n```\n\n一个人的服务器（我的世界基岩版1.1.xPocketMine服务器）\n```powershell\nscp -r C:\\Users\\BigTang\\Desktop\\一个人的服务器\\* root@192.168.31.233:/shumengya/docker/OnePersonServer/\n```",
  "Linux/wlan0简单介绍.md": "### 1. 网络接口类型及其作用\n- **lo（回环接口）**:\n  - 用于系统内部通信，IP地址通常为 `127.0.0.1`，子网掩码为 `255.0.0.0`。\n  - 主要用于本地测试，如运行本地服务器（如HTTPD）时，只能在本机访问。\n\n- **eth0（以太网接口）**:\n  - 代表第一块物理网卡，`HWaddr` 表示网卡的MAC地址，`inet addr` 表示IP地址。\n  - 支持IPv4和IPv6，通常用于有线网络连接。\n  - 可以通过 `ifconfig` 查看网卡的接收和发送数据包的情况。\n\n- **br0（网桥接口）**:\n  - 用于在链路层连接多个网络接口（如eth0），实现帧的转发。\n  - 常用于虚拟化环境中，连接多个虚拟网络接口。\n\n- **wlan0（无线接口）**:\n  - 代表无线网卡，类似于eth0，但用于无线网络连接。\n  - 需要驱动程序支持，配置方式与以太网接口类似。\n\n### 2. `ifconfig` 命令的常见操作\nWindows命令为：ipconfig\n\n- **启动/关闭网卡**:\n  - `ifconfig eth0 up`：启动网卡。\n  - `ifconfig eth0 down`：关闭网卡。\n\n- **配置/删除IPv6地址**:\n  - `ifconfig eth0 add <IPv6地址>`：为网卡添加IPv6地址。\n  - `ifconfig eth0 del <IPv6地址>`：删除网卡的IPv6地址。\n\n- **修改MAC地址**:\n  - `ifconfig eth0 hw ether <MAC地址>`：修改网卡的MAC地址。\n\n- **修改IP地址**:\n  - `ifconfig eth0 <IP地址>`：修改网卡的IP地址。\n  - `ifconfig eth0 <IP地址> netmask <子网掩码>`：修改IP地址并设置子网掩码。\n  - `ifconfig eth0 <IP地址> netmask <子网掩码> broadcast <广播地址>`：同时设置IP地址、子网掩码和广播地址。\n\n- **设置最大传输单元（MTU）**:\n  - `ifconfig eth0 mtu <字节数>`：设置网卡的最大传输单元大小。\n\n### 3. 注意事项\n- 使用 `ifconfig` 命令时，尤其是在远程服务器上操作时，需谨慎关闭网卡，否则可能导致无法远程连接。\n- 虚拟网卡和物理网卡的区别在于虚拟网卡由系统或应用程序创建，不依赖于物理硬件。\n\n这篇文章详细介绍了 `ifconfig` 命令的使用方法以及常见网络接口的配置和功能，适合需要管理和调试网络接口的用户参考。",
  "Linux/全局执行某个sh脚本，该放在Linux哪个目录.md": "要使得某个 `.sh` 脚本能够在系统中全局执行，你可以将该脚本放在 **系统的 `PATH` 路径中**，使其在任何地方都能被执行。常见的目录有：\n\n### 1. **`/usr/local/bin/`**\n这是推荐的目录，因为它是用来放置系统管理员手动安装或编译的软件及脚本的。脚本放在这个目录中，可以确保它对所有用户可用，并且不会与系统自带的命令冲突。\n\n步骤：\n1. 将你的 `.sh` 脚本复制到 `/usr/local/bin/` 目录下。\n   \n   ```bash\n   sudo cp your_script.sh /usr/local/bin/\n   ```\n\n2. 赋予脚本执行权限：\n\n   ```bash\n   sudo chmod +x /usr/local/bin/your_script.sh\n   ```\n\n3. 确保脚本能被执行，可以通过命令行直接调用（例如 `your_script.sh`），无需指定路径。\n\n### 2. **`/usr/bin/`**\n这个目录通常用于系统范围内的二进制文件，和 `/usr/local/bin/` 类似。但是，建议将自定义脚本放在 `/usr/local/bin/` 目录下，因为 `/usr/bin/` 通常用于通过包管理器安装的系统级命令。\n\n步骤：\n1. 将脚本复制到 `/usr/bin/` 目录：\n\n   ```bash\n   sudo cp your_script.sh /usr/bin/\n   ```\n\n2. 赋予执行权限：\n\n   ```bash\n   sudo chmod +x /usr/bin/your_script.sh\n   ```\n\n### 3. **`/bin/`**（不推荐）\n`/bin/` 目录通常用于存放系统核心命令和工具，普通用户通常不建议将自定义脚本放在这个目录中，除非它们确实是系统必需的命令。通常会将脚本放置在 `/usr/local/bin/` 或 `/usr/bin/` 中。\n\n### 4. **用户特定的目录（例如 `/home/username/bin/`）**\n如果你只想为某个特定用户设置全局脚本，而不是所有用户可以访问的脚本，你可以将脚本放在该用户的 `~/bin/` 目录下（如果该目录不存在，可以自己创建）。确保将 `~/bin/` 添加到用户的 `PATH` 环境变量中。\n\n步骤：\n1. 创建 `~/bin/` 目录（如果没有的话）：\n\n   ```bash\n   mkdir -p ~/bin\n   ```\n\n2. 将脚本复制到 `~/bin/` 目录：\n\n   ```bash\n   cp your_script.sh ~/bin/\n   ```\n\n3. 赋予执行权限：\n\n   ```bash\n   chmod +x ~/bin/your_script.sh\n   ```\n\n4. 编辑 `~/.bashrc` 或 `~/.profile`，将 `~/bin/` 添加到 `PATH`：\n\n   ```bash\n   export PATH=$PATH:~/bin\n   ```\n\n5. 使 `~/.bashrc` 变更生效：\n\n   ```bash\n   source ~/.bashrc\n   ```\n\n### 总结\n- **最推荐的目录：** `/usr/local/bin/`，适用于系统范围内的自定义脚本。\n- **其他可选目录：** `/usr/bin/`（不推荐），如果需要放系统级命令可以选择该目录。\n- **特定用户的脚本：** 用户自己的 `~/bin/` 目录。\n",
  "Linux/手动配置alist.md": "```shell\n# 解压下载的文件，得到可执行文件：\ntar -zxvf alist-xxxx.tar.gz\n# 授予程序执行权限：\nchmod +x alist\n# 运行程序\n./alist server\n\n# 获得管理员信息 以下两个不同版本，新版本也有随机生成和手动设置\n# 低于v3.25.0版本\n./alist admin\n\n# 高于v3.25.0版本\n# 随机生成一个密码\n./alist admin random\n# 手动设置一个密码 `NEW_PASSWORD`是指你需要设置的密码\n./alist admin set NEW_PASSWORD\n\n```\n\n\n\n使用任意方式编辑 `/usr/lib/systemd/system/alist.service` 并添加如下内容，其中 path_alist 为 AList 所在的路径\n\n```shell\n[Unit]\nDescription=alist\nAfter=network.target\n \n[Service]\nType=simple\nWorkingDirectory=path_alist\nExecStart=path_alist/alist server\nRestart=on-failure\n \n[Install]\nWantedBy=multi-user.target\n\n```\n\n然后，执行 systemctl daemon-reload 重载配置，现在你可以使用这些命令来管理程序：\n**• 启动: systemctl start alist**\n**• 关闭: systemctl stop alist**\n**• 配置开机自启: systemctl enable alist**\n**• 取消开机自启: systemctl disable alist**\n**• 状态: systemctl status alist**\n**• 重启: systemctl restart alist**",
  "Linux/把Ubuntu镜像源切换到阿里云.md": "要将 Ubuntu 22.04 (AMD64) 的软件源更换为阿里云的镜像源，可以按照以下步骤操作：\n\n### 1. 备份当前的源列表\n\n在更改源之前，先备份原有的 `sources.list` 文件：\n\n```bash\nsudo cp /etc/apt/sources.list /etc/apt/sources.list.bak\n```\n\n### 2. 修改 `sources.list` 文件\n\n打开 `/etc/apt/sources.list` 文件，编辑并替换为阿里云的源地址：\n\n```bash\nsudo nano /etc/apt/sources.list\n```\n\n将文件内容替换为以下内容（适用于 Ubuntu 22.04）：\n\n```plaintext\n# 阿里云 Ubuntu 22.04 镜像源\ndeb http://mirrors.aliyun.com/ubuntu/ jammy main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ jammy main restricted universe multiverse\n\ndeb http://mirrors.aliyun.com/ubuntu/ jammy-updates main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ jammy-updates main restricted universe multiverse\n\ndeb http://mirrors.aliyun.com/ubuntu/ jammy-backports main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ jammy-backports main restricted universe multiverse\n\ndeb http://mirrors.aliyun.com/ubuntu/ jammy-security main restricted universe multiverse\ndeb-src http://mirrors.aliyun.com/ubuntu/ jammy-security main restricted universe multiverse\n```\n\n### 3. 更新软件包列表\n\n替换源后，更新 apt 包索引：\n\n```bash\nsudo apt update\n```\n\n### 4. 升级已安装的软件包\n\n为了确保一切顺利运行，你可以运行以下命令来升级现有的软件包：\n\n```bash\nsudo apt upgrade\n```\n\n\n",
  "Linux/构建最小Linux系统.md": "以下是手动构建一个极简Linux系统（约10MB）的完整步骤，包含内核和基础用户空间：\r\n\r\n### 1. 准备环境（Ubuntu/Debian示例）\r\n```bash\r\nsudo apt install -y build-essential libncurses-dev bison flex qemu-system-x86\r\nmkdir tiny_linux &amp;&amp; cd tiny_linux\r\n```\r\n\r\n### 2. 编译定制化内核（5MB）\r\n```bash\r\n# 下载最新稳定版内核\r\nwget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.9.8.tar.xz\r\ntar xf linux-6.9.8.tar.xz &amp;&amp; cd linux-6.9.8\r\n\r\n# 最小化配置\r\nmake defconfig\r\nmake menuconfig  # 手动调整以下选项：\r\n#   General setup\r\n#     [ ] Configure standard kernel features (expert users)\r\n#   Device Drivers\r\n#     [*] Block devices &gt; RAM block device support (16MB)\r\n#     [*]   Network device support &gt; Ethernet driver support &gt; Intel(R) PRO/1000\r\n#   File systems\r\n#     [*] Ext2\r\n#     [ ] Btrfs\r\n#     [ ] XFS\r\n#   [*] Enable loadable module support  # 禁用\r\n\r\n# 编译内核\r\nmake -j$(nproc) bzImage\r\n```\r\n\r\n### 3. 创建最小根文件系统（5MB）\r\n```bash\r\ncd ..\r\nmkdir rootfs &amp;&amp; cd rootfs\r\n\r\n# 使用BusyBox构建基础工具\r\nwget https://busybox.net/downloads/busybox-1.36.1.tar.bz2\r\ntar xf busybox-1.36.1.tar.bz2 &amp;&amp; cd busybox-1.36.1\r\nmake defconfig\r\nmake menuconfig  # 选择静态编译：\r\n# Settings -&gt; Build Options -&gt; [*] Build static binary\r\n\r\nmake -j$(nproc) &amp;&amp; make install\r\ncd _install\r\n\r\n# 创建必要目录\r\nmkdir -p proc sys dev etc/init.d\r\n\r\n# 创建启动脚本\r\ncat &gt; etc/init.d/rcS &lt;&lt;EOF\r\n#!/bin/sh\r\nmount -t proc none /proc\r\nmount -t sysfs none /sys\r\n/sbin/mdev -s\r\nEOF\r\nchmod +x etc/init.d/rcS\r\n\r\n# 创建文件系统镜像\r\ndd if=/dev/zero of=rootfs.img bs=1M count=16\r\nmkfs.ext2 -F rootfs.img\r\nsudo mount -o loop rootfs.img /mnt\r\nsudo cp -r ./* /mnt\r\nsudo umount /mnt\r\n```\r\n\r\n### 4. 使用QEMU启动测试\r\n```bash\r\nqemu-system-x86_64 \\\r\n    -kernel ../linux-6.9.8/arch/x86/boot/bzImage \\\r\n    -hda rootfs.img \\\r\n    -append &quot;root=/dev/ram0 console=ttyS0&quot; \\\r\n    -nographic\r\n```\r\n\r\n### 5. 可选优化（缩减体积）\r\n```bash\r\n# 使用UPX压缩可执行文件\r\nsudo apt install upx\r\nfind . -type f -executable | xargs upx --best\r\n\r\n# 移除调试符号\r\nstrip --strip-all busybox\r\n\r\n# 使用musl libc替代glibc\r\nwget https://musl.libc.org/releases/musl-1.2.4.tar.gz\r\ntar xzf musl-1.2.4.tar.gz &amp;&amp; cd musl-1.2.4\r\n./configure --prefix=/usr/local/musl &amp;&amp; make &amp;&amp; sudo make install\r\n```\r\n\r\n### 6. 构建结果\r\n```\r\n├── linux-6.9.8\r\n│   └── arch/x86/boot/bzImage    # 内核文件\r\n├── rootfs\r\n│   ├── bin                      # 基础命令\r\n│   ├── rootfs.img               # 根文件系统镜像\r\n│   └── etc                      # 配置文件\r\n```\r\n\r\n### 替代方案：使用Buildroot快速构建\r\n```bash\r\ngit clone https://github.com/buildroot/buildroot\r\ncd buildroot\r\nmake menuconfig  # 选择：\r\n# Target options -&gt; Target Architecture = x86_64\r\n# System configuration -&gt; Root filesystem overlay = ../rootfs\r\n# Kernel -&gt; Linux Kernel = 6.9.8\r\nmake -j$(nrep)\r\n```\r\n\r\n### 系统特性对比\r\n\r\n| 组件         | 手动构建 | Buildroot构建 |\r\n| ------------ | -------- | ------------- |\r\n| 启动时间     | &lt;1s   | &lt;1.5s      |\r\n| 内存占用     | 8MB      | 12MB          |\r\n| 可执行文件数 | 12个     | 25个          |\r\n| 支持网络     | 否       | 是            |\r\n| 支持动态库   | 否       | 可选          |\r\n\r\n建议从手动构建开始学习原理，实际项目使用Buildroot可节省90%时间。后续可添加OpenSSH（+1.2MB）或Web服务器（+0.8MB）等组件扩展功能。",
  "Linux/树萌芽常用Linux命令集合.md": "tar.gz文件解压：\ntar -zxvf 文件名\n\nlinux 重命名文件/文件夹:\nmv 原文件名 新文件名\n\n注意：/etc/systemd/system/  这里放置systemctl服务\n\n重新加载systemctl服务：\nsystemctl daemon-reload\n\nsystemctl start 服务名\nsystemctl stop 服务名\nsystemctl enable 服务名\nsystemctl status 服务名\n",
  "Linux/树萌芽的局域网中网IP分配.md": "# IP分段：192.168.31.1-192.168.31.255\n\n## -------------------------------\n\n## 10 20 30 40 50 60 70\n\n##  66 99 88 11 22 33 44 55\n\n## 110 120 119 \n\n## 111 222\n\n## 233\n\n## -------------------------------\n\n## x86电脑系列\n\n#### Windows11\n\n#### Linux Mint\n\n#### 树萌芽NAS（大萌芽）：233\n\n\n\n## 安卓手机系列\n\n####  红萌芽盘 ：222\n\n#### 黑萌芽盘 ：111\n\n#### 小萌芽盘： \n\n\n\n#### vivo平板\n\n#### OPPO手机\n\n\n\n## 随身WiFi系列\n\n#### UFI1003  \n\n#### UZ801\n\n#### UZ901\n\n#### UFI100C 目前有9个\n\n### IP：11 - 99\n\n\n\n####  \n\n####  \n\n####  \n\n####  \n\n\n\n",
  "Linux/编译alist.md": "以下是编译 Alist 前后端的详细步骤：\r\n\r\n---\r\n\r\n### **1. 准备工作**\r\n#### 环境要求：\r\n- **Go 1.16+** (后端依赖)\r\n- **Node.js 14+** (前端依赖)\r\n- **Git** (代码管理)\r\n- **Yarn** 或 **npm** (前端包管理)\r\n\r\n#### 安装依赖：\r\n```bash\r\n# 安装 Go (以 Linux 为例)\r\nwget https://golang.org/dl/go1.20.linux-amd64.tar.gz\r\nsudo tar -C /usr/local -xzf go1.20.linux-amd64.tar.gz\r\nexport PATH=$PATH:/usr/local/go/bin\r\n\r\n# 安装 Node.js (推荐使用 nvm)\r\ncurl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash\r\nnvm install 16\r\nnvm use 16\r\n\r\n# 安装 Yarn\r\nnpm install -g yarn\r\n```\r\n\r\n---\r\n\r\n### **2. 后端编译**\r\n#### 获取源码：\r\n```bash\r\ngit clone https://github.com/alist-org/alist.git\r\ncd alist\r\n```\r\n\r\n#### 安装依赖并编译：\r\n```bash\r\n# 进入后端目录\r\ncd alist\r\n\r\n# 下载 Go 依赖\r\ngo mod download\r\n\r\n# 编译（默认生成当前系统的可执行文件）\r\ngo build -o alist main.go\r\n\r\n# 交叉编译（示例：编译 Linux AMD64）\r\nCGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o alist-linux-amd64 main.go\r\n```\r\n\r\n编译完成后，会在当前目录生成可执行文件 `alist`（或指定名称）。\r\n\r\n---\r\n\r\n### **3. 前端编译**\r\n#### 进入前端目录：\r\n```bash\r\ncd ../web # 假设源码根目录为 alist/\r\n```\r\n\r\n#### 安装依赖并构建：\r\n```bash\r\nyarn install        # 或使用 npm install\r\nyarn build          # 或使用 npm run build\r\n```\r\n\r\n构建完成后，静态文件会生成在 `dist` 目录中。\r\n\r\n---\r\n\r\n### **4. 整合前后端**\r\n将前端构建的静态文件复制到后端目录的 `public` 文件夹中：\r\n```bash\r\n# 创建 public 目录（如果不存在）\r\nmkdir -p ../alist/public\r\n\r\n# 复制前端文件\r\ncp -r dist/* ../alist/public/\r\n```\r\n\r\n---\r\n\r\n### **5. 运行 Alist**\r\n```bash\r\n# 进入后端目录\r\ncd ../alist\r\n\r\n# 赋予执行权限（Linux/macOS）\r\nchmod +x alist\r\n\r\n# 启动服务\r\n./alist server\r\n```\r\n\r\n默认访问地址：`http://localhost:5244`\r\n\r\n---\r\n\r\n### **6. 高级配置**\r\n1. **修改配置文件**  \r\n   首次运行后会在程序目录生成 `data/config.json`，可按需修改端口、存储驱动等。\r\n\r\n2. **自定义前端变量**  \r\n   在 `web/.env` 文件中修改环境变量（如 API 地址）：\r\n   ```env\r\n   VITE_API_URL=http://your-domain.com:5244\r\n   ```\r\n\r\n3. **Docker 编译（可选）**  \r\n   Alist 官方提供 Docker 镜像，也可自行构建：\r\n   ```bash\r\n   docker build -t alist .\r\n   ```\r\n\r\n---\r\n\r\n### **常见问题**\r\n1. **依赖安装失败**  \r\n   - 检查网络是否通畅（尤其是 Go 依赖可能需要代理）。\r\n   - 确保 Node.js 和 Go 版本符合要求。\r\n\r\n2. **前端构建报错**  \r\n   - 清理缓存：`yarn cache clean` 或 `rm -rf node_modules`。\r\n   - 检查 `web/package.json` 中的依赖版本是否冲突。\r\n\r\n3. **启动后无法访问**  \r\n   - 检查防火墙是否开放端口（默认 `5244`）。\r\n   - 确认 `config.json` 中 `address` 设置为 `0.0.0.0`（允许外部访问）。\r\n\r\n---\r\n\r\n通过以上步骤，你可以成功编译并运行 Alist 的完整服务。如需更多定制化配置，建议参考 [Alist 官方文档](https://alist.nn.ci/)。",
  "Linux/编译busybox步骤.md": "```shell\r\npkg update && pkg upgrade\r\npkg install git make clang\r\napt install gcc\r\nexport CC=clang\r\napt install build-essential\r\npkg install ncurses-dev\r\ngit clone https://git.busybox.net/busybox\r\ncd busybox\r\nmake menuconfig\r\n#make -j$(nproc) \r\nmake -j4\r\nmake install\r\n\r\n\r\n```\r\n\r\n```shell\r\n#可选创建符号链接\r\nPREFIX=$HOME/.local\r\nmkdir -p $PREFIX/bin\r\nfor applet in $(./busybox --list); do\r\n    ln -s $PREFIX/bin/busybox $PREFIX/bin/$applet\r\ndone\r\n\r\n```\r\n\r\n",
  "Linux/随身WiFi/随身WiFi一些记录.md": "export TERM=linux\n",
  "Minecraft/Minecraft命名彩蛋.md": "在 Minecraft Java 版（以及很多情况下 Bedrock 版也适用）里，给生物使用命名牌（Name Tag）命名时，有几种**彩蛋效果**（Easter Eggs）可以触发。以下是主要已知的几种：\n\n| 名称                         | 生物                           | 效果                                           | 备注                                             |\n| -------------------------- | ---------------------------- | -------------------------------------------- | ---------------------------------------------- |\n| **“Dinnerbone” 或 “Grumm”** | 任何可命名的生物（除某些Boss如末影龙）        | 生物会“倒立”——模型翻转，看起来在头朝下走路                      | 这是对开发者 Nathan Adams（昵称 Dinnerbone）和 Grumm 的致敬。 |\n| **“jeb_”**（注意结尾的下划线）       | 羊（Sheep）                     | 羊的羊毛会不断在所有颜色之间切换，形成“彩虹羊”效果                   | 虽然羊毛颜色看上去在变，但剪下或杀掉后掉落的仍然是原始颜色的羊毛               |\n| **“Toast”**                | 兔子（Rabbit）                   | 命名为 “Toast” 的兔子会变成黑白皮肤（纪念性皮肤）                | 背后故事是某玩家丢失了一只叫 Toast 的兔子，开发者为其添加了这一皮肤。         |\n| **“Johnny”**               | 复仇者（Vindicator）或在某版本中 Zoglin | 命名为 “Johnny” 的复仇者会变得对几乎所有生物（包括动物／敌对／中立）都敌对攻击 | 这是对电影 The Shining 中 “Here’s Johnny” 场景的致敬。     |\n|                            |                              |                                              |                                                |\n",
  "Minecraft/Minecraft常用命令.md": "***/kill @e[type=mutant:mskeleton_bones]*** \n清除掉突变骷髅模组的骷髅骨头实体\n\n***/kill @e[type=item]*** \n清除所有掉落物\n\n***/gamerule mobGriefing true*** \n设置生物破坏开启或者禁用 （禁用后村民不会繁殖，雪傀儡不会产雪）\n\n***/gamerule keepInventory true***\n设置玩家死亡不掉落",
  "Obsidion/Obsidion美化.md": "```json\n{\n  \"Appearance-light@@theme-light-style-select\": \"theme-light-background-adapt\",\n  \"Appearance-light@@mod-left-split-background-select-light\": \"mod-left-split-background-CSS-light\",\n  \"Appearance-light@@background-mod-left-CSS-light\": \"radial-gradient(100% 50% at 100% 50%, rgba(90, 109, 237, 0.1) 0%, rgba(255, 255, 255, 0) 100%)\",\n  \"Appearance-light@@background-mod-left-CSS-backdrop-filter-light\": \"blur(0px)\",\n  \"Appearance-light@@mod-right-split-background-select-light\": \"mod-right-split-background-CSS-light\",\n  \"Appearance-light@@background-mod-right-CSS-light\": \"radial-gradient(100% 50% at 0% 50%, rgba(90, 109, 237, 0.1) 0%, rgba(255, 255, 255, 0) 100%)\",\n  \"Appearance-light@@background-mod-right-CSS-backdrop-filter-light\": \"blur(0px)\",\n  \"Appearance-light@@mod-root-split-background-select-light\": \"mod-root-split-background-CSS-light\",\n  \"Appearance-light@@background-mod-root-CSS-light\": \"transparent\",\n  \"Appearance-light@@background-mod-root-CSS-backdrop-filter-light\": \"blur(0px)\",\n  \"Appearance-light@@background-underlying-select-light\": \"background-underlying-CSS-light\",\n  \"Appearance-light@@background-underlying-CSS-light\": \"linear-gradient(168.44deg, #D7DAEA 1.62%, #F2F2F8 95.72%)\",\n  \"Appearance-light@@background-underlying-CSS-blend-mode-light\": \"normal\",\n  \"Appearance-light@@card-border-radius-light\": \"0px\",\n  \"Appearance-light@@card-shadow-light\": \"none\",\n  \"Appearance-light@@background-activated-tab-header-light\": \"radial-gradient(50% 150% at 50% 150%, #F8F9FF 0%, rgba(97, 54, 144, 0) 100%)\",\n  \"Appearance-light@@shadow-activated-tab-header-light\": \"none\",\n  \"Appearance-light@@indicator-remove-light\": true,\n  \"Appearance-light@@Active-states-file-explorer-select-light\": \"activated-file-tab-style-light\",\n  \"Appearance-light@@workspace-divider-transparent-light\": true,\n  \"Components@@CTA-BTN-enable\": true,\n  \"Components@@file-names-untrim\": true,\n  \"Components@@folder-font-bold\": true,\n  \"Components@@colorful-folder\": true,\n  \"Components@@file-icon-remove\": false,\n  \"Components@@outline-enhanced\": true,\n  \"Components@@new-tab-btn-select\": \"new-tab-btn-default\",\n  \"Components@@immersive-canvas\": true,\n  \"Components@@scrollbar-hide\": true,\n  \"Appearance-light@@card-layout-open-light\": true,\n  \"Appearance-light@@accent-color-override-light\": false,\n  \"Appearance-light@@card-highlight-light\": true,\n  \"Editor@@line-hover-indicator\": true,\n  \"Editor@@focus-indicator-codeblock-line-number\": true,\n  \"Editor@@focus-indicator-list-level\": true,\n  \"Editor@@editor-grid-background-pattren\": true,\n  \"Editor@@inline-title-divider-remove\": true,\n  \"Editor@@h1-divider-on\": true,\n  \"Editor@@h2-divider-on\": true,\n  \"Editor@@h3-divider-on\": true,\n  \"Editor@@h4-divider-on\": true,\n  \"Editor@@h5-divider-on\": true,\n  \"Editor@@h6-divider-on\": true,\n  \"Editor@@text-align-justify\": true,\n  \"Editor@@bold-color@@light\": \"#4781EC\",\n  \"Editor@@italic-color@@light\": \"#FF4BFE\",\n  \"Editor@@img-center-align\": true,\n  \"Mobile@@drawer-phone-full-width\": true,\n  \"Mobile@@card-layout-pad-open\": true,\n  \"Plugin@@colorful-checkbox\": true\n}\n```",
  "内网穿透/frp客户端配置.md": "\n```toml\n#=============================================================================\n#===================================基础设置===================================\n#=============================================================================\n\nserverAddr = \"47.108.90.0\"\nserverPort = 7000\n\nauth.method = \"token\"\nauth.token = \"smy\"\n\nwebServer.addr = \"0.0.0.0\"\nwebServer.port = 7400\nwebServer.user = \"shumengya\"\nwebServer.password = \"tyh@19900420\"\nwebServer.pprofEnable = false\n\n#下面两个二选一\ntransport.protocol = \"kcp\"\n#transport.protocol = \"quic\"\n\n# 日志配置\nlog.to = \"console\"\nlog.level = \"info\"\n\n\n#=============================================================================\n#===================================Http服务===================================\n#=============================================================================\n\n# 萌芽盘-openlist\n[[proxies]]\nname = \"openlist\"\ntype = \"http\"\nlocalIP = \"127.0.0.1\"\nlocalPort = 5244\ncustomDomains = [\"openlist.shumengya.top\",\"pan.shumengya.top\"] \n\n\n#大萌芽1panel面板-1panel\n[[proxies]]\nname = \"1panel\"\ntype = \"http\"\nlocalIP = \"127.0.0.1\"\nlocalPort = 19132\ncustomDomains = [\"1panel.shumengya.top\"] \n\n\n#Obsidian笔记同步-couchdb\n[[proxies]]\nname = \"couchdb\"\ntype = \"http\"\nlocalIP = \"127.0.0.1\"\nlocalPort = 5984\ncustomDomains = [\"note.shumengya.top\"] \n\n#大萌芽frp客户端-frpc\n[[proxies]]\nname = \"frpc\"\ntype = \"http\"\nlocalIP = \"127.0.0.1\"\nlocalPort = 7400\ncustomDomains = [\"frpc.shumengya.top\"] \n\n#萌芽文件快传-filecodebox\n[[proxies]]\nname = \"filecodebox\"\ntype = \"http\"\nlocalIP = \"127.0.0.1\"\nlocalPort = 12345\ncustomDomains = [\"file.shumengya.top\",\"send.shumengya.top\"] \n\n#萌芽图床-lsky-pro\n[[proxies]]\nname = \"lsky-pro\"\ntype = \"http\"\nlocalIP = \"127.0.0.1\"\nlocalPort = 8089\ncustomDomains = [\"image.shumengya.top\",\"img.shumengya.top\"] \n\n#在线代码编辑器-codeserver\n[[proxies]]\nname = \"codeserver\"\ntype = \"http\"\nlocalIP = \"127.0.0.1\"\nlocalPort = 8888\ncustomDomains = [\"code.shumengya.top\"] \n\n#60sAPI接口集合-60sapi\n[[proxies]]\nname = \"60s-API\"\ntype = \"http\"\nlocalIP = \"127.0.0.1\"\nlocalPort = 4399\ncustomDomains = [\"60s.api.shumengya.top\"] \n\n#社交媒体视频ai总结-bilinote\n[[proxies]]\nname = \"bilinote\"\ntype = \"http\"\nlocalIP = \"127.0.0.1\"\nlocalPort = 3015\ncustomDomains = [\"bilinote.shumengya.top\"] \n\n#萌芽git仓库-gitea\n[[proxies]]\nname = \"gitea\"\ntype = \"http\"\nlocalIP = \"127.0.0.1\"\nlocalPort = 8989\ncustomDomains = [\"repo.shumengya.top\"] \n\n#Docker可视化面板-DPanel\n[[proxies]]\nname = \"dpanel\"\ntype = \"http\"\nlocalIP = \"127.0.0.1\"\nlocalPort = 8800\ncustomDomains = [\"dpanel.shumengya.top\"] \n\n#萌芽通知-ntfy\n[[proxies]]\nname = \"ntfy\"\ntype = \"http\"\nlocalIP = \"127.0.0.1\"\nlocalPort = 82\ncustomDomains = [\"ntfy.shumengya.top\"] \n\n#萌芽大内网管理后台-openwrt\n[[proxies]]\nname = \"openwrt\"\ntype = \"http\"\nlocalIP = \"192.168.1.1\"\nlocalPort = 80\ncustomDomains = [\"openwrt.shumengya.top\"] \n\n#=========================================================================\n#===================================TCP服务=================================\n#=========================================================================\n\n#萌芽农场远程控制台\n[[proxies]]\nname = \"mengyafarm-config\"\ntype = \"tcp\"\nlocalIP = \"127.0.0.1\"\nlocalPort = 7071\nremotePort = 6060\n\n#mysql数据库\n[[proxies]]\nname = \"mysql\"\ntype = \"tcp\"\nlocalIP = \"127.0.0.1\"\nlocalPort = 3306\nremotePort = 3307  # frps 上的映射端口\n\n#MongoDB数据库\n[[proxies]]\nname = \"mongodb\"\ntype = \"tcp\"\nlocalIP = \"127.0.0.1\"\nlocalPort = 27017\nremotePort = 27018\n\n#Postgres数据库\n[[proxies]]\nname = \"postgres\"\ntype = \"tcp\"\nlocalIP = \"127.0.0.1\"\nlocalPort = 5432\nremotePort = 5433\n\n#大萌芽-Debian11 SSH连接\n[[proxies]]\nname = \"bigmengya-ssh\"\ntype = \"tcp\"\nlocalIP = \"127.0.0.1\"\nlocalPort = 22\nremotePort = 9022\n\n#Redis数据库\n[[proxies]]\nname = \"redis\"\ntype = \"tcp\"\nlocalIP = \"127.0.0.1\"\nlocalPort = 6379\nremotePort = 6380\n\n\n#=========================================================================\n#===================================UDP服务=================================\n#=========================================================================\n\n```\n",
  "内网穿透/frp服务端配置.md": "\n```toml\n# frp服务端配置 - 作为nginx后端服务\n# 与nginx配合使用，提供HTTPS支持\n\nbindAddr = \"0.0.0.0\"\nbindPort = 7000\n\n#下面两个二选一\nkcpBindPort = 7000    # KCP 监听的 UDP 端口（可与 bindPort 相同）\n#quicBindPort = 7000    # QUIC 使用的 UDP 端口（与 bindPort 可相同）\n\n[auth]\nauth.method = \"token\"  \nauth.token = \"smy\"   \n\n# HTTP配置 - 作为后端服务（nginx代理）\nvhostHTTPPort = 8080  # nginx代理到此端口\n\n# 日志配置\nlog.to = \"console\"\nlog.level = \"info\"\n\n# 管理界面\n[webServer]\nwebServer.addr = \"0.0.0.0\"\nwebServer.port = 7500\nwebServer.user = \"shumengya\"\nwebServer.password = \"tyh@19900420\" \n\n[transport]\ntcpMux = true   # 如要关闭 tcp 多路复用（默认启用）\nmaxPoolCount = 10  # 服务端允许的最大连接池数量\ntls.force = false  # 不强制客户端必须 TLS（除非你要强制安全）\n```\n\n",
  "内网穿透/Frp的kcp和quic的区别和特点.md": "\n---\n\n## 基础：QUIC 与 KCP 本身的区别（协议层面）\n\n要理解 FRP 下这两种模式的差别，首先必须认识 QUIC 与 KCP 两种协议在 UDP 之上的设计差异。下面从几个维度来对比。\n\n|维度|KCP|QUIC|\n|---|---|---|\n|协议定位 / 设计目标|一个可靠的 UDP 层协议（“可靠 UDP + ARQ + 拥塞控制 + 重传策略”），强调低延迟、对弱网络适应性较好。 ([腾讯云](https://cloud.tencent.com/developer/article/1964393?utm_source=chatgpt.com \"KCP协议：从TCP到UDP家族QUIC/KCP/ENET-腾讯云开发 ...\"))|更现代的传输层协议，最初由 Google 设计，后来演化成为 HTTP/3 的底层传输（即：QUIC + TLS + 多路复用）的一部分。它在 UDP 之上集成了连接管理、多路复用、拥塞控制、0-RTT、TLS 加密等机制。 ([CSDN博客](https://blog.csdn.net/qq_36541069/article/details/132143729?utm_source=chatgpt.com \"所得杂记：KCP，QUIC，MQTT - CSDN博客\"))|\n|连接建立 / 握手延迟|KCP 在使用上一般是比较“轻”的握手（因为只是建立会话 ID 等），延迟比较低|QUIC 支持 0-RTT、较快握手（因为集成 TLS）等机制，从连接建立角度更有优势|\n|多路复用 / 多流支持|传统 KCP 是面向“单流”（一个会话对应一个流式数据）。要实现真正的多路复用，需要在上层自己设计；否则每条独立连接就是一个 KCP 实例|QUIC 原生支持多流（multiple streams）和流内优先级，能在一个连接上同时承载多个逻辑数据流，减少队头阻塞（Head-of-line blocking）的问题|\n|拥塞控制 / 拥塞算法|KCP 自己有拥塞控制与窗口机制，也可以调节参数去“弱化”拥塞控制以换取低延迟。 ([腾讯云](https://cloud.tencent.com/developer/article/1964393?utm_source=chatgpt.com \"KCP协议：从TCP到UDP家族QUIC/KCP/ENET-腾讯云开发 ...\"))|QUIC 的拥塞控制受到现代研究和 TCP 的启发，有较为成熟的拥塞控制与流量控制算法；它也能动态适应网络变化|\n|丢包 / 重传机制|KCP 使用选择性重传 (Selective Retransmission)、快速重传、延迟 ACK 调节等策略来减少重传滞后和延迟惩罚。 ([腾讯云](https://cloud.tencent.com/developer/article/1964393?utm_source=chatgpt.com \"KCP协议：从TCP到UDP家族QUIC/KCP/ENET-腾讯云开发 ...\"))|QUIC 也具备细粒度的 ACK / 重传机制，有更复杂的 ACK / 确认策略，集成了更现代的重传算法|\n|加密 / 安全|KCP 本身通常是“裸协议”或可选加密（上层或 FRP 在其上做加密）|QUIC 本身设计是**加密为默认**（TLS 集成在协议里），所有控制面与数据面都加密，更能防止中间人干扰、流量识别等问题|\n|开销 / 资源占用|相对轻量；因为协议栈简单，控制开销、头部开销较低|更复杂，协议处理开销更大（比如加密、握手、流管理、ACK 处理等）|\n|在极端场景 / 性能瓶颈下表现|在高延迟 + 大包 / 大数据量 + 丢包环境下，KCP 性能可能下降。比如有测试指出在**高延迟 + 发送超过 MTU 的数据**时，KCP 的延迟会显著恶化。 ([GitHub](https://github.com/xtaci/kcp-go/issues/204?utm_source=chatgpt.com \"对比TCP/QUIC/KCP的测试结果 · Issue #204 · xtaci/kcp-go - GitHub\"))|在这些情况下，QUIC 的设计通常更稳健一些，更能处理大流量、多个流、多并发场景|\n\n从这些对比来看，QUIC 在协议设计上更“现代”、更全面、更关注安全性与多路复用，而 KCP 更加轻量、灵活，适合对实时性、低延迟要求比较高的场景。\n\n不过，协议设计优劣并不是绝对的，具体在 FRP 的应用场景下，还要考虑实现、参数调优、网络环境等因素。\n\n---\n\n## 在 FRP 中：QUIC 模式 vs KCP 模式的区别与表现\n\nFRP 支持将底层通信协议从默认的 TCP / HTTPTransport 切换成 KCP 或 QUIC（即 `transport.protocol = \"kcp\"` 或 `\"quic\"`）模式。官方文档里对此有说明。 ([gofrp.org](https://gofrp.org/en/docs/features/common/network/network/?utm_source=chatgpt.com \"Communication Security and Optimization | frp\"))\n\n下面是两种模式在 FRP 中常见的差别、优缺点、使用注意。\n\n### 优点 / 劣势对比\n\n|特性 / 维度|FRP + KCP 模式|FRP + QUIC 模式|\n|---|---|---|\n|延迟表现 / 实时响应|通常优于 TCP，尤其在丢包 / 抖动较大、网络不稳定的环境下。很多用户用 KCP 模式来加速远程桌面、SSH 等。 ([CSDN博客](https://blog.csdn.net/MENGHUANBEIKE/article/details/100793876?utm_source=chatgpt.com \"利用frp内网穿透kcp模式做跳板，加速流畅访问远程桌面3389\"))|在连接建立、短连接场景以及多流场景中，QUIC 有优势；也能在某些网络被封、被干扰的情况下更抗阻断性（因为包头更难识别）|\n|抗网络干扰 / 被封锁风险|KCP 尽管在 UDP 上传输，但协议本身特征可能比较容易被识别；在被运营商主动干扰 UDP 流量的环境中可能被限速或封锁|QUIC 本身带加密和混淆特性，更难被中间设备识别，某些用户用 QUIC 模式来规避“被运营商阻断 FRP TCP 连接”的情况。比如有一篇博客指出，TCP 模式在某些校园网或被 ISP 限制时连接失败，而改用 QUIC 协议就能恢复连接。 ([ZRHan's Blog](https://blog.zrhan.top/2024/07/14/%E7%94%A8quic%E5%8D%8F%E8%AE%AE%E8%A7%A3%E5%86%B3frp%E8%A2%AB%E8%BF%90%E8%90%A5%E5%95%86%E9%98%BB%E6%96%AD%E7%9A%84%E9%97%AE%E9%A2%98/?utm_source=chatgpt.com \"用quic协议解决frp被运营商阻断的问题 - ZRHan's Blog\"))|\n|带宽开销 / 效率|KCP 为了追求低延迟，会在一定程度上牺牲一些带宽效率（可能会有额外重传、冗余、控制包开销等） ([gofrp.org](https://gofrp.org/en/docs/features/common/network/network/?utm_source=chatgpt.com \"Communication Security and Optimization \\| frp\"))|QUIC 在设计上对带宽利用率考虑较多，控制与重传机制更复杂，会在多流、大连接场景下更高效|\n|多代理 / 多连接 / 并发|KCP 模式下，如果你在一个 FRP 实例下跑很多代理 / 多条连接，每条连接都是一条 KCP，会有一定管理开销|QUIC 的多流 / 多路复用设计可以在一个连接上承载多个代理或多个数据流，更理想地减少连接数和开销|\n|实现稳定性 / Bug 风险|KCP 在 FRP 中被使用较久、成熟度较高，用户社区案例较多，参数调优经验丰富|QUIC 是相对较新、更复杂的模式，在 FRP 中可能还存在一些 bug 或限制；例如，有 issue 提到 “无法单独运行在 QUIC 模式” 的问题——无论是否配置 bind_port 字段，frps 总会监听 TCP 端口（这个 issue 在 FRP 的 issue 列表里被关闭为“不计划修复”）([GitHub](https://github.com/fatedier/frp/issues/3225?utm_source=chatgpt.com \"无法单独运行在quic模式 · Issue #3225 · fatedier/frp · GitHub\"))|\n|参数调优空间 / 灵活性|KCP 的很多参数（MTU、窗口、nodelay、重传策略等）都可以调，灵活性高；但需要手动调优以适应网络环境|QUIC 的很多机制是在协议内部做的（如流控、拥塞控制、加密层），对用户的参数调控空间可能较少（或复杂）|\n|适用场景|需要低延迟或在弱网络环境里工作的服务（如 SSH、RDP、交互式服务）|多流服务、HTTP(s) 代理、长连接传输、多代理复用、抗干扰场合等可能更适合|\n\n综合来看：如果你现在主要是用 FRP 来做一些 SSH、远程桌面、交互性强的服务，或者网络环境不稳定／丢包率高，KCP 模式可能是更稳定、可控的选择。而如果你需要让 FRP 在更复杂的网络环境下更具抗封锁性、更现代化、更高效，QUIC 模式是一个很有吸引力的选项。\n\n### 在 FRP 上使用时的注意与限制\n\n- 要让 QUIC / KCP 模式生效，你需要在 frps 和 frpc 两边都正确配置对应的端口（`quicBindPort` / `kcpBindPort` 等）与 `transport.protocol = \"quic\"` 或 `\"kcp\"`。否则默认仍用 TCP。 ([格态随记](https://blog.gotab.cn/archives/RvdYvu2g?utm_source=chatgpt.com \"Frp：服务端 frps.toml 和 frpc.toml 客户端配置文件详解\"))\n    \n- 防火墙 / UDP 端口必须开放 — 因为 KCP / QUIC 都是在 UDP 上运行的，无法简单依赖 TCP。\n    \n- 参数调优很关键：KCP 有很多参数（如 `nodelay`、`interval`、窗口大小、重传策略等）需要根据网络环境调整，否则可能效果不好或发生延迟爆炸。\n    \n- QUIC 模式在 FRP 中可能还不够成熟 / 存在一些边界 bug。例如前面提到的 “无法单独运行在 QUIC 模式” 问题就是一个。 ([GitHub](https://github.com/fatedier/frp/issues/3225?utm_source=chatgpt.com \"无法单独运行在quic模式 · Issue #3225 · fatedier/frp · GitHub\"))\n    \n- 在高带宽 / 长距离 /大流量场景下，KCP 模式可能表现不如预期，因为协议本身在大包 / 高延迟 + 数据量大时延迟会膨胀。实测中有用户发现，在延迟较高 + 发送大于 MTU 的数据场景下，QUIC 表现优于 KCP。 ([GitHub](https://github.com/xtaci/kcp-go/issues/204?utm_source=chatgpt.com \"对比TCP/QUIC/KCP的测试结果 · Issue #204 · xtaci/kcp-go - GitHub\"))\n    \n- 加密开销：如果你还在 FRP 上启用 TLS / 加密，QUIC 本身就有加密，叠加可能有额外开销；KCP 则通常是裸或可选加密，开销可能较低。\n    \n\n---\n\n## 总结 & 建议\n\n- **优势倾向**  \n     - 若你更注重“稳定 + 可控 + 低延迟 + 在弱网环境下表现好”，KCP 是一个比较稳妥的选择（尤其已有成熟经验）  \n     - 若你更希望未来扩展性强、支持多流、抗干扰 / 抗封锁能力更好、连接更现代化，QUIC 是更有前景的选择\n    \n- **实用建议**  \n     1. 在你的网络环境下做对比测试：部署一个用 KCP，一个用 QUIC，测一下延迟、丢包率、吞吐量、稳定性，哪一个更符合你的场景就用哪个。  \n     2. 若你目前已有稳定的 KCP 环境且能满足需求，不必急于切换；只有在遇到 TCP 被封锁 / 性能瓶颈 / 抗干扰需求时，再考虑 QUIC。  \n     3. 在启用 QUIC（或 KCP）模式时，务必留一个“回退”方案（例如保留 TCP 模式），以防 QUIC 模式在某些网络环境下连接失败 / 不稳定。  \n     4. 多关注 FRP 的版本更新、issue 列表，特别是关于 QUIC 模式的 bug 或兼容性问题。\n    \n",
  "内网穿透/Frp设置同一端口不同域名访问.md": "\n---\n\n## 1) frps（公网服务器）配置\n\n编辑 `frps.toml`，让 frps 监听一个 HTTP CONNECT 复用端口（你希望是 8022 就设 8022）：\n\n```toml\nbindPort = 7000\n\n# 关键：tcpmux 复用入口端口\ntcpmuxHTTPConnectPort = 8022\n```\n\n重启 frps\n这个 8022 **不是直接 SSH 端口**，而是“HTTP CONNECT 复用入口”\n\n---\n\n## 2) 两台内网主机的 frpc 配置\n\n### 主机 A（big.smy.top）\n\n`frpc.toml`：\n\n```toml\nserverAddr = \"你的公网IP\"\nserverPort = 7000\n\n[[proxies]]\nname = \"ssh_big\"\ntype = \"tcpmux\"\nmultiplexer = \"httpconnect\"\ncustomDomains = [\"big.smy.top\"]\nlocalIP = \"127.0.0.1\"\nlocalPort = 22\n```\n\n### 主机 B（small.smy.top）\n\n`frpc.toml`：\n\n```toml\nserverAddr = \"你的公网IP\"\nserverPort = 7000\n\n[[proxies]]\nname = \"ssh_small\"\ntype = \"tcpmux\"\nmultiplexer = \"httpconnect\"\ncustomDomains = [\"small.smy.top\"]\nlocalIP = \"127.0.0.1\"\nlocalPort = 22\n```\n\n`customDomains` 就是用来区分路由的域名键\n\n---\n\n## 3) DNS 解析\n\n把\n\n- `big.smy.top`\n- `small.smy.top`\n    \n\n都 **A 记录解析到同一台公网 frps 的 IP**。\n\n---\n\n## 4) 连接方式\n\n因为 tcpmux 依赖 **HTTP CONNECT** 来告诉 frps 目标域名，所以你不能这样直连：\n\n```bash\nssh big.smy.top -p 8022   # ❌ 这样 frps 不知道该转给谁\n```\n\n要用 ProxyCommand（官方示例用 socat）：\n\n```bash\nssh -o 'ProxyCommand=socat - PROXY:公网IP:%h:%p,proxyport=8022' test@big.smy.top\nssh -o 'ProxyCommand=socat - PROXY:公网IP:%h:%p,proxyport=8022' test@small.smy.top\n```\n\nfrps 会根据 `%h`（也就是 big / small 域名）分流到对应主机\n\n---\n\n## 5) 更舒服的用法：写到你的 `~/.ssh/config`\n\n```sshconfig\nHost big\n    HostName big.smy.top\n    User test\n    ProxyCommand socat - PROXY:公网IP:%h:%p,proxyport=8022\n\nHost small\n    HostName small.smy.top\n    User test\n    ProxyCommand socat - PROXY:公网IP:%h:%p,proxyport=8022\n```\n\n以后直接：\n\n```bash\nssh big\nssh small\n```\n\n---\n\n因为 SSH 本身无法携带“我要去哪个域名后端”的信息给 frps\ntcpmux 是目前 frp 官方唯一的“同端口分流 SSH”方案\n\n---\n",
  "内网穿透/Tailscale/Tailscale客户端常用命令.md": "### tailscale 命令\n\n- **up**  \n    连接到 Tailscale，如有需要会进行登录\n- **down**  \n    从 Tailscale 断开连接\n- **set**  \n    修改指定的偏好设置\n- **login**  \n    登录到 Tailscale 账号\n- **logout**  \n    从 Tailscale 断开并使当前节点密钥失效\n- **switch**  \n    切换到另一个 Tailscale 账号\n- **configure**  \n    配置主机以启用更多 Tailscale 功能\n- **syspolicy**  \n    诊断 MDM（移动设备管理）与系统策略配置\n- **netcheck**  \n    显示本地网络状况的分析\n- **ip**  \n    显示 Tailscale 的 IP 地址\n- **dns**  \n    诊断内部 DNS 转发器\n- **status**  \n    显示 tailscaled 及其连接的状态\n- **metrics**  \n    显示 Tailscale 的指标数据\n- **ping**  \n    在 Tailscale 层对主机执行 Ping，并显示路由情况\n- **nc**  \n    连接到主机的某个端口，并连接到标准输入/输出（类似 netcat）\n- **ssh**  \n    通过 Tailscale SSH 到一台 Tailscale 机器\n- **funnel**  \n    将内容或本地服务器公开到互联网\n- **serve**  \n    在你的 tailnet（ Tailscale 网络）中提供内容或本地服务\n- **version**  \n    显示 Tailscale 版本\n- **web**  \n    运行一个用于控制 Tailscale 的 Web 服务器\n- **file**  \n    发送或接收文件\n- **bugreport**  \n    输出用于诊断问题的可分享标识符\n- **cert**  \n    获取 TLS 证书\n- **lock**  \n    管理 tailnet lock（网络锁）\n- **licenses**  \n    获取开源许可证信息\n- **exit-node**  \n    显示你的 tailnet 中配置为出口节点的机器\n- **update**  \n    将 Tailscale 更新到最新或其他版本\n- **whois**  \n    显示与某个 Tailscale IP（v4 或 v6）对应的机器和用户\n- **drive**  \n    与你的 tailnet 共享目录\n- **completion**  \n    生成 shell 自动补全脚本\n    \n",
  "内网穿透/Tailscale/搭建derp和headscale避坑与指南.md": "derp（Docker安装）：\n\n```bash\n#Docker容器一键化启动\n#默认开启tcp端口33445 udp端口3478\ndocker run --restart always \\\n  --name derper1 \\\n  -p 33445:33445 \\\n  -p 3478:3478/udp \\\n  -v /shumengya/ssl/derp1/:/app/certs \\\n  -e DERP_CERT_MODE=manual \\\n  -e DERP_ADDR=:33445 \\\n  -e DERP_DOMAIN=derp1.shumengya.top \\\n  -e DERP_CERT_FILE=/app/certs/derp1.shumengya.top.crt \\\n  -e DERP_KEY_FILE=/app/certs/derp1.shumengya.top.key \\\n  -d ghcr.io/yangchuansheng/derper:latest\n  \n  docker run --restart always \\\n  --name derper2 \\\n  -p 33445:33445 \\\n  -p 3478:3478/udp \\\n  -v /shumengya/ssl/derp2/:/app/certs \\\n  -e DERP_CERT_MODE=manual \\\n  -e DERP_ADDR=:33445 \\\n  -e DERP_DOMAIN=derp2.shumengya.top \\\n  -e DERP_CERT_FILE=/app/certs/derp2.shumengya.top.crt \\\n  -e DERP_KEY_FILE=/app/certs/derp2.shumengya.top.key \\\n  -d ghcr.io/yangchuansheng/derper:latest\n  \ndocker run --restart always \\\n  --name derper3 \\\n  -p 33445:33445 \\\n  -p 3478:3478/udp \\\n  -v /shumengya/ssl/derp3/:/app/certs \\\n  -e DERP_CERT_MODE=manual \\\n  -e DERP_ADDR=:33445 \\\n  -e DERP_DOMAIN=derp3.shumengya.top \\\n  -e DERP_CERT_FILE=/app/certs/derp3.shumengya.top.crt \\\n  -e DERP_KEY_FILE=/app/certs/derp3.shumengya.top.key \\\n  -d ghcr.io/yangchuansheng/derper:latest\n\n```\n\n```bash\n#默认使用Let's Encrypt签发ssl证书\n#默认需要关闭nginx占用80端口来签发证书\ncurl -s https://get.acme.sh | sh\n\nsource ~/.bashrc\n\nacme.sh --issue --standalone -d 你的域名\n#安装依赖\napt update && apt install -y socat\nyum install -y socat\ndnf install -y socat\n\nacme.sh --register-account -m 你的邮箱地址\n```\n\n\nheadscale（直接部署systemctl运行）:\n\nheadscale默认放行：9090~9092 和50443\n\n配置一个域名：\nheadscale.shumengya.top\n下载headscale：[https://github.com/juanfont/headscale](headscale)\n下载headscale-ui：[https://github.com/juanfont/headscale](headscale-ui)\n\n新建文件夹(用来放相关文件)：\nmkdir -p shumengya/headscale\n\n安装headscale：\ndpkg -i headscale_0.26.1_linux_amd64.deb\n\n修改headscale配置\n```yaml\n---\n# headscale 会按照以下顺序查找名为 `config.yaml` (或 `config.json`) 的配置文件：\n#\n# - `/etc/headscale`\n# - `~/.headscale`\n# - 当前工作目录\n\n# 客户端将要连接的 URL。\n# 通常应为一个域名，例如：\n#\n# https://myheadscale.example.com:443\n#\nserver_url: http://127.0.0.1:9091\n\n# 服务器监听/绑定的地址\n#\n# 生产环境建议：\nlisten_addr: 0.0.0.0:9092\n#listen_addr: 127.0.0.1:8080\n\n# /metrics 和 /debug 的监听地址，你可能希望\n# 将此端点限制在内网\nmetrics_listen_addr: 127.0.0.1:9090\n\n# gRPC 的监听地址。\n# gRPC 用于通过 CLI 远程控制 headscale 服务器\n# 注意：只有在使用有效证书时，远程访问才可用。\n#\n# 生产环境建议：\ngrpc_listen_addr: 0.0.0.0:50443\n#grpc_listen_addr: 127.0.0.1:50443\n\n# 是否允许 gRPC 管理接口以 **不安全** 模式运行。\n# 不推荐启用，因为流量将不加密。只有在你完全理解风险时才启用。\ngrpc_allow_insecure: false\n\n# Noise 部分包含 TS2021 Noise 协议的特定配置\nnoise:\n  # Noise 私钥用于在 headscale 和 Tailscale 客户端之间\n  # 使用新的基于 Noise 的协议加密流量。缺少的密钥将会自动生成。\n  private_key_path: /var/lib/headscale/noise_private.key\n\n# 为 tailnet 分配地址的 IP 前缀列表。\n# 每个前缀由 IPv4 或 IPv6 地址 + 前缀长度组成，以斜杠分隔。\n# 必须在 Tailscale 客户端支持的范围内\n# 即 100.64.0.0/10 和 fd7a:115c:a1e0::/48 的子网。\n# 否则会导致异常问题。\nprefixes:\n  v4: 100.64.0.0/10\n  #v6: fd7a:115c:a1e0::/48\n\n  # 节点 IP 分配策略，可选：\n  # - sequential（默认）：按顺序分配下一个可用 IP\n  # - random：使用伪随机生成器分配可用 IP\n  allocation: sequential\n\n# DERP 是 Tailscale 在无法建立直连时使用的中继系统。\n# https://tailscale.com/blog/how-tailscale-works/#encrypted-tcp-relays-derp\n#\n# headscale 需要一个 DERP 服务器列表供客户端使用。\nderp:\n  server:\n    # 启用后，将运行内置 DERP 服务器并合并到 DERP 配置中\n    # 上面的 server_url 必须使用 https，DERP 需要 TLS\n    enabled: false\n\n    # 内置 DERP 服务器的区域 ID。\n    # 如果与外部配置的区域 ID 冲突，则本地 DERP 优先。\n    region_id: 999\n\n    # 区域代码和名称会在 Tailscale UI 中显示\n    region_code: \"headscale\"\n    region_name: \"Headscale Embedded DERP\"\n\n    # 在指定地址上监听 UDP 端口以支持 STUN 连接（帮助 NAT 穿透）。\n    # 如果启用内置 DERP，必须定义 stun_listen_addr。\n    #\n    # 更多详情可参考：https://tailscale.com/blog/how-tailscale-works/\n    stun_listen_addr: \"0.0.0.0:3478\"\n\n    # 用于加密 headscale DERP 与 Tailscale 客户端之间流量的私钥。\n    # 缺少时会自动生成。\n    private_key_path: /var/lib/headscale/derp_server_private.key\n\n    # 此标志用于控制是否自动将内置 DERP 写入 DERP map。\n    # 若设为 false，则需通过 DERP.paths 手动配置。\n    automatically_add_embedded_derp_region: true\n\n    # 为了更稳定的连接（特别是 Exit-Node + DNS 不可用时），\n    # 可以选择性地将公网 IPv4/IPv6 地址写入 Derp-Map：\n    ipv4: 1.2.3.4\n    ipv6: 2001:db8::1\n\n  # 外部可用的 DERP map 列表（JSON 格式）\n  urls:\n   # - https://controlplane.tailscale.com/derpmap/default\n    #- https://你的域名/web/derp.json\n\n  # 本地可用的 DERP map 文件（YAML 格式）\n  #\n  # 对于自建 DERP 服务器很有用：\n  # https://tailscale.com/kb/1118/custom-derp-servers/\n  #\n  # paths:\n  #   - /etc/headscale/derp-example.yaml\n  paths: []\n\n  # 若启用，将定期刷新上述 DERP 源并更新 derpmap\n  auto_update_enabled: true\n\n  # 检查 DERP 更新的间隔\n  update_frequency: 24h\n\n# 禁用启动时自动检查 headscale 更新\ndisable_check_updates: false\n\n# 非活跃临时节点在多久后被删除？\nephemeral_node_inactivity_timeout: 30m\n\ndatabase:\n  # 数据库类型，可选：sqlite, postgres\n  # 注意：强烈不推荐使用 Postgres，仅为遗留原因保留。\n  # 所有新开发和优化都基于 SQLite。\n  type: sqlite\n\n  # 启用调试模式。需要 log.level 设置为 \"debug\" 或 \"trace\"。\n  debug: false\n\n  # GORM 配置\n  gorm:\n    # 启用预编译语句。\n    prepare_stmt: true\n\n    # 启用参数化查询。\n    parameterized_queries: true\n\n    # 跳过 “record not found” 错误日志。\n    skip_err_record_not_found: true\n\n    # 慢查询阈值（毫秒）\n    slow_threshold: 1000\n\n  # SQLite 配置\n  sqlite:\n    path: /var/lib/headscale/db.sqlite\n\n    # 启用 WAL 模式。推荐生产环境启用。\n    # https://www.sqlite.org/wal.html\n    write_ahead_log: true\n\n    # WAL 文件在达到多少帧时自动 checkpoint。\n    # 设为 0 可禁用自动 checkpoint。\n    wal_autocheckpoint: 1000\n\n  # # Postgres 配置（不推荐，仅遗留支持）\n  # postgres:\n  #   # 使用 Unix socket 时，设置 host 为 socket 路径，port 留空。\n  #   host: localhost\n  #   port: 5432\n  #   name: headscale\n  #   user: foo\n  #   pass: bar\n  #   max_open_conns: 10\n  #   max_idle_conns: 10\n  #   conn_max_idle_time_secs: 3600\n  #\n  #   # SSL 配置，参考官方文档\n  #   ssl: false\n\n### TLS 配置\n#\n## Let's Encrypt / ACME\n#\n# headscale 支持使用 Let's Encrypt 自动申请 TLS 证书\n#\n# ACME 目录 URL\nacme_url: https://acme-v02.api.letsencrypt.org/directory\n\n# ACME 注册邮箱\nacme_email: \"\"\n\n# 要申请 TLS 证书的域名\ntls_letsencrypt_hostname: \"\"\n\n# 存储证书和元数据的路径\n# 生产环境建议：\ntls_letsencrypt_cache_dir: /var/lib/headscale/cache\n\n# ACME 挑战类型，目前支持：\n# HTTP-01 或 TLS-ALPN-01\n# 详见 docs/ref/tls.md\ntls_letsencrypt_challenge_type: HTTP-01\n# 使用 HTTP-01 时，letsencrypt 必须监听：\n# :http = 80 端口\ntls_letsencrypt_listen: \":http\"\n\n## 使用已有证书\ntls_cert_path: \"\"\ntls_key_path: \"\"\n\nlog:\n  # 日志输出格式：text 或 json\n  format: text\n  # 日志级别：info, debug, trace\n  level: info\n\n## 策略\n# headscale 支持 Tailscale 的 ACL 策略\n# 文档：https://tailscale.com/kb/1018/acls/\npolicy:\n  # 模式：file 或 database\n  mode: file\n  # 若为 file 模式，指定 HuJSON 文件路径\n  path: \"\"\n\n## DNS\n#\n# headscale 支持 Tailscale 的 DNS 配置和 MagicDNS。\n# 文档：\n# https://tailscale.com/kb/1054/dns/\n# https://tailscale.com/kb/1081/magicdns/\n# https://tailscale.com/blog/2021-09-private-dns-with-magicdns/\n#\n# 注意：要使 DNS 配置生效，客户端必须启用 `--accept-dns=true`。\n# 否则将不生效。\ndns:\n  # 是否启用 MagicDNS\n  magic_dns: true\n\n  # MagicDNS 的基础域名，必须与 server_url 域名不同。\n  base_domain: example.com\n\n  # 是否覆盖本地 DNS 设置\n  override_local_dns: false\n\n  # 全局 DNS 服务器列表\n  nameservers:\n    global:\n      - 1.1.1.1\n      - 1.0.0.1\n      - 2606:4700:4700::1111\n      - 2606:4700:4700::1001\n      # NextDNS 示例\n      # - https://dns.nextdns.io/abc123\n\n    # Split DNS 示例（为特定域使用不同 DNS）\n    split: {}\n\n  # 自定义搜索域\n  search_domains: []\n\n  # 额外 DNS 记录（支持 A/AAAA）\n  extra_records: []\n  #   - name: \"grafana.myvpn.example.com\"\n  #     type: \"A\"\n  #     value: \"100.64.0.3\"\n\n# CLI 使用的 Unix socket（无认证）\n# 生产环境建议自定义\nunix_socket: /var/run/headscale/headscale.sock\nunix_socket_permission: \"0770\"\n\n# OpenID Connect 配置（实验功能）\n# oidc:\n#   only_start_if_oidc_is_available: true\n#   issuer: \"https://your-oidc.issuer.com/path\"\n#   client_id: \"your-oidc-client-id\"\n#   client_secret: \"your-oidc-client-secret\"\n#   client_secret_path: \"${CREDENTIALS_DIRECTORY}/oidc_client_secret\"\n#   expiry: 180d\n#   use_expiry_from_token: false\n#   scope: [\"openid\", \"profile\", \"email\", \"custom\"]\n#   extra_params:\n#     domain_hint: example.com\n#   allowed_domains:\n#     - example.com\n#   allowed_groups:\n#     - /headscale\n#   allowed_users:\n#     - alice@example.com\n#   pkce:\n#     enabled: false\n#     method: S256\n\n# Logtail 配置\n# Logtail 是 Tailscale 的日志与审计系统\nlogtail:\n  # 启用后，客户端将日志发送到 Tailscale 服务器\n  enabled: false\n\n# 启用后，设备将优先使用随机端口进行 WireGuard 流量\n# 以避免某些防火墙兼容性问题。\n# 详见：https://tailscale.com/kb/1181/firewalls/\nrandomize_client_port: false\n\n\n```\n\n设置反向代理：\n公网域名->127.0.0.1:9092\n```txt\nlocation /web {\n  index index.html;\n  alias /shumengya/headscale/web;\n}\n```\n\n\n\n\n\n",
  "内网穿透/内网穿透方案.md": "\n---\n\n## 一、开源替代方案 /工具清单\n\n下面是目前社区里比较流行 /有实用性的开源方案：\n\n|名称|语言 / 技术栈|支持协议 /功能|特点 /亮点|可能缺点 /注意|\n|---|---|---|---|---|\n|**rathole**|Rust|TCP / HTTP /TLS|轻量、高性能，内存占用低，支持热重载、服务令牌认证等。被设计为 FRP / ngrok 的替代品。 ([GitHub](https://github.com/rathole-org/rathole?utm_source=chatgpt.com \"GitHub - rathole-org/rathole: A lightweight and high-performance ...\"))|文档 /社区可能不如 FRP 那么成熟；一些边缘功能可能欠缺|\n|**NSmartProxy**|.NET Core / C#|TCP / HTTP 反向代理 /穿透|跨平台支持好，用异步 I/O 架构驱动穿透代理。 ([GitHub](https://github.com/tmoonlight/NSmartProxy?utm_source=chatgpt.com \"GitHub - tmoonlight/NSmartProxy: NSmartProxy是一款开源的内网穿透工具。采用.NET CORE ...\"))|在 Linux /非 .NET 平台上的稳定性 /优化要测试；社区规模可能偏小|\n|**Tunnelmole**|Node.js / TypeScript|HTTP / HTTPS 隧道|100% 开源、可自托管、方便给本地 Web 服务生成公开 URL。 ([tunnelmole.com](https://tunnelmole.com/?utm_source=chatgpt.com \"Tunnelmole - A free and open source tunneling tool\"))|主要面向 HTTP/HTTPS，游戏 /通用 TCP 服务可能支持不够好；对于高并发 /大流量性能需要评估|\n|**Reverse Proxy Tool（基于 Netty 的）**|Java / Netty|支持任意 TCP 上层协议和 HTTP|支持 HTTP 升级、SSL 验证、协议透传等功能。 ([Gitee](https://gitee.com/codebanks/reverse-proxy-tool?utm_source=chatgpt.com \"Reverse Proxy Tool: Reverse Proxy Tool : 基于Netty实现的 ...\"))|Java 程序可能资源占用较高；配置可能稍复杂；性能需要根据 JVM 优化|\n|**nps / NPS** / **lanproxy** / **holer**|Go /其他|TCP / HTTP /UDP 穿透、反向代理|在「开源内网穿透工具」合集 /对比文章里经常被提及。 ([laoliang.net](https://www.laoliang.net/jsjh/technology/14975.html?utm_source=chatgpt.com \"归纳几种免费开源的内网穿透工具（frp、holer、nps、lanproxy）\"))|各工具在稳定性、协议支持深度、社区维护度上有差别；需要逐个评估|\n|**reverse-tunnel（snsi nfu 的项目）**|（未知 /社区项目）|公网 → 私网 隧道 /映射|提供反向隧道映射能力，据社区介绍可以做安全隧道。 ([CSDN.blog](https://blog.csdn.net/gitblog_01080/article/details/141481391?utm_source=chatgpt.com \"反向隧道工具 reverse-tunnel 使用指南-CSDN博客\"))|项目可能成熟度不高，文档 /示例可能不足；功能边界需自己测试|\n|**tiny-frpc**|Go / 精简 FRP 客户端|frp 协议子集|体积小、适合资源紧张的嵌入式 /小设备使用。 ([博客园](https://www.cnblogs.com/tang863/p/18274521?utm_source=chatgpt.com \"tiny-frpc： frp 反向代理精简版客户端 - AmbiaCode - 博客园\"))|只是 frpc 的子集，用于客户端，不是完整替代；功能限制较多|\n\n---\n\n",
  "实习求职/27双非本一腾讯IEG游戏安全后台实习面经.md": "timeline:\n9.16 一面\n9.18 二面\n9.22 三面\n9.23 HR面\n9.24 录用评估\n9.26 Offer\n\n腾讯一面（1h）\n\n1. 介绍实习需求（K8S 和 Casbin RBAC 相关）\n2. 为啥初创实习两个月离职\n3. Go 为什么支持高并发\n4. GMP模型原理\n5. Goroutine Work-Stealing 的目的\n6. P的角色的作用，如果在M上维护Goroutine队列有什么不好\n7. GMP对CPU密集型任务能提高并发么\n8. IO操作需要CPU么，什么时候需要，磁盘IO和网络IO的区别\n9. Channel的作用和底层实现\n10. Channel的缓冲区在用户态还是内核态\n11. Goroutine阻塞等待的时候由谁来唤醒，需要额外的goroutine来遍历所有的channel么\n12. M上的G0是干嘛的\n13. 介绍select/poll/epoll\n14. 网络IO的流程\n15. 了解过Go Runtime么\n\n算法：求两个数的最大公约数\n\n腾讯二面（1h）\n\n1. 介绍实习需求，最有挑战的部分\n2. RocksDB了解么，说一下LsmTree\n3. 详细介绍一下Raft协议\n4. Raft协议和Paxos协议的区别，有哪些优化\n5. 介绍一下React Agent\n6. LangChain 和 LangGraph 的区别\n7. Agent 和 LLM 的区别\n8. Function Call 和 MCP 的区别\n9. RPC的全流程\n10. 负载均衡算法有哪些\n11. 介绍一致性Hash算法，服务扩缩容之后有什么影响\n12. 网络编程\n13. 介绍一下TCP和UDP\n14. 介绍一下HTTP各个版本及实现\n\n算法：\n\n1. 编辑距离\n2. 两两交换链表中的节点\n\n腾讯三面（30min）\n\n1. 介绍实习，你做了什么\n2. 介绍项目\n3. 实习时长，到岗时间，推HR面\n\n腾讯HR面（15min）\n\n1. 离职原因\n2. 实习时长，到岗时间\n3. 聊聊天",
  "实习求职/术语科普-HC.md": "“hc” 是英文 “Head Count” 的缩写，核心含义是“人员编制”，指企业或团队中计划招聘、核定的岗位人数，并非已入职的实际人数。\n \n在不同场景下还有其他常见含义，具体需结合语境判断：\n \n- 职场/招聘场景：最常用含义为“人员编制”，例如“这个部门今年还有2个hc”，即该部门今年仍有2个招聘名额。\n- 医学场景：可指“血红蛋白浓度（Hemoglobin Concentration）”，是血常规检查中评估是否贫血的重要指标。\n- 网络用语：偶尔作为“喝彩（hè cǎi）”的拼音首字母缩写，用于表达支持、夸赞，常见于社交平台评论区。",
  "实习求职/术语科普-PM.md": "“pm” 是多义词缩写，核心含义需结合具体场景判断，最常见的有以下三类：\n \n- 时间场景：全称为 “Post Meridiem”，指一天中的“下午”，与表示“上午”的“am”（Ante Meridiem）对应，例如“3 pm”即“下午3点”。\n- 职场/业务场景：最常用含义为 “Product Manager”，即“产品经理”，负责产品的规划、设计、迭代及市场推广等全流程工作；也可指 “Project Manager”，即“项目经理”，主要负责项目的计划、执行与交付，确保项目按时按质完成。\n- 其他场景：在通信或社交语境中，还可表示 “Private Message”，即“私信”，例如“有问题可以pm我”，意为“有问题可以给我发私信”。",
  "实习求职/面试八股/HTTP 与HTTPS/从「敲下一个 URL」到「页面出现在屏幕」整条链路全景.md": "",
  "实习求职/面试八股/Nacos功能与应用场景详解.md": "Nacos 是阿里巴巴开源的 **动态服务发现、配置管理与服务治理平台**，旨在简化微服务架构的构建、交付和管理。\n\n---\n\n## 🚀 核心功能\n\n| 功能 | 主要作用 |\n|------|----------|\n| 🎯 **服务注册与发现** | 服务提供者注册自身信息，服务消费者动态发现和调用其他服务。 |\n| ⚙️ **动态配置管理** | 集中管理所有环境的配置，支持实时推送变更，无需重启应用。 |\n| 🔍 **服务健康监测** | 定期检查服务实例健康状况，自动隔离不健康实例，保障系统稳定性。 |\n| 🚦 **动态DNS与流量管理** | 支持权重路由，助力灰度发布、蓝绿部署等高级流量管理策略。 |\n\n---\n\n## 🎯 服务发现与健康检查\n\n- **服务注册**：实例启动时向 Nacos 注册自身元数据（服务名、IP、端口等）。  \n- **服务发现**：消费者通过服务名查询健康实例，实现通信而无需关心具体地址。  \n- **健康检查**：支持客户端上报与服务端主动探测，自动剔除不健康实例，保障可靠性。  \n\n---\n\n## ⚙️ 动态配置管理\n\n- **集中化管理**：统一存储数据库连接、开关、限流阈值等配置。  \n- **动态刷新**：配置变更实时推送，应用可在运行中直接生效（热更新）。  \n- **版本控制与回滚**：支持历史版本，一键回滚，降低变更风险。  \n\n---\n\n## 🚦 动态DNS与服务治理\n\n- **动态DNS服务**：支持权重路由、流量控制和简易内网 DNS 解析。  \n- **服务与元数据管理**：统一管理服务描述、依赖关系、健康状态、流量及安全策略。  \n\n---\n\n## 💡 主要应用场景\n\n- **数据库配置集中化管理**：提升安全性与合规性。  \n- **限流与降级开关**：结合 Sentinel 等组件实现运行时动态调整。  \n- **多环境与多数据中心**：基于 Namespace 与 Group 实现隔离与灵活部署。  \n\n---\n\n## 📊 与其他组件对比\n\n- ✅ **功能更全面**：Nacos = 服务发现 + 配置管理；Eureka 仅支持服务发现。  \n- ✅ **健康检查机制更强**：优于 Eureka 心跳检测。  \n- ✅ **社区与生态活跃**：Eureka 已停止维护，而 Nacos 持续迭代。  \n- ✅ **多数据中心支持优越**：原生支持多数据中心部署。  \n\n---\n\n## 📚 总结\n\nNacos 集 **服务发现、配置管理、服务治理** 于一体，  \n极大简化了微服务架构复杂性，提升了 **开发效率**、**可维护性** 和 **系统弹性**。\n\n---",
  "实习求职/面试八股/网络模型/OSI 七层模型是什么？.md": "\n---\n\n# 🧩 OSI 七层模型详解（国际快递类比版）\n\n## 📌 一句话总结\n\n**OSI 七层模型**将网络通信拆分为：  \n**物理 → 数据链路 → 网络 → 传输 → 会话 → 表示 → 应用**  \n七个层次，各司其职，模块化设计。  \n可类比为“国际快递”的打包、贴标签、路由、中转、翻译、下单等流程，使网络协议结构更清晰、互不干扰。\n\n---\n\n# 🚚 类比：寄送国际包裹与 OSI 七层对应关系\n\n```\n┌──────────────────────────────────────────────┐\n│                应用层 Application            │  ← 用户下单、填写寄件信息\n├──────────────────────────────────────────────┤\n│               表示层 Presentation           │  ← 翻译成国际通用语言、加密/压缩\n├──────────────────────────────────────────────┤\n│                会话层 Session               │  ← 握手——确认对方愿不愿意收包裹\n├──────────────────────────────────────────────┤\n│                传输层 Transport             │  ← 分段——拆包裹、编号、可靠送达/重传\n├──────────────────────────────────────────────┤\n│                网络层 Network               │  ← 路由——规划路线与中转站\n├──────────────────────────────────────────────┤\n│             数据链路层 Data Link            │  ← 帧封装——贴“省市/楼号/房间号”标签\n├──────────────────────────────────────────────┤\n│               物理层 Physical               │  ← 传输媒介——卡车、飞机、邮差\n└──────────────────────────────────────────────┘\n```\n\n---\n\n# 🔍 各层详解\n\n## 1️⃣ 物理层（Physical Layer）\n\n**功能：**\n- 负责比特流的物理传输（电压、光信号、无线电波）\n\n**设备：**\n- 网线、光纤、Hub、网卡物理接口\n\n**类比：**  \n📦 **卡车、飞机等实际运输工具**——负责把集装箱从 A 运到 B。\n\n---\n\n## 2️⃣ 数据链路层（Data Link Layer）\n\n**功能：**\n- 帧的封装/拆解\n- 差错检测（CRC）\n- 流量控制\n- MAC 地址寻址\n    \n\n**子层：**\n- LLC\n- MAC\n    \n\n**设备：**\n- 交换机、网卡驱动\n    \n\n**类比：**  \n🏷️ **包裹地址标签（省/市/街道/楼号/房间号）**  \n🖊️ 快递员核对签名，保证局域网内无误送达。\n\n---\n\n## 3️⃣ 网络层（Network Layer）\n\n**功能：**\n- 跨网段通信\n- 路由选择\n- 逻辑地址（IP）转发\n    \n\n**协议：**\n- IP、ICMP、OSPF、BGP\n\n**设备：**\n- 路由器\n    \n\n**类比：**  \n🛫 **国际快递分拨中心**——做路径规划、选择中转站。\n\n---\n\n## 4️⃣ 传输层（Transport Layer）\n\n**功能：**\n- 端到端可靠/不可靠传输\n- 数据分段与重组\n- 重传、确认机制\n- 流量控制、拥塞控制\n    \n\n**协议：**\n- TCP（可靠、有序、面向连接）\n- UDP（无连接、不保证可靠）\n    \n\n**类比：**  \n📦 **拆箱分批编号、确认回执，不签收就重发**。\n\n---\n\n## 5️⃣ 会话层（Session Layer）\n\n**功能：**\n- 建立/维护/终止会话\n- 会话恢复\n- 身份验证\n\n**类比：**  \n📞 **客服系统：输入验证码→验证→建立会话→挂断结束**\n\n---\n\n## 6️⃣ 表示层（Presentation Layer）\n\n**功能：**\n- 数据格式转换\n- 加密与解密\n- 压缩与解压\n    \n\n**协议/格式：**\n- SSL/TLS、MIME、JPEG、ASCII、EBCDIC\n\n**类比：**  \n🌐 **中文信件翻译成英文，再压缩体积以便运输**。\n\n---\n\n## 7️⃣ 应用层（Application Layer）\n\n**功能：**\n- 面向用户，提供网络服务接口\n\n**常见协议：**\n- HTTP、FTP、SMTP、DNS、Telnet、SSH\n\n**类比：**  \n📝 **用户填写快递单、选择寄件方式、输入寄件内容**\n\n---\n\n# 🧾 小结（速记版）\n\n|层级|名称|核心作用|类比|\n|---|---|---|---|\n|7|应用层|用户接口|填写快递单|\n|6|表示层|编码/加密/压缩|翻译与压缩|\n|5|会话层|建立/管理/断开连接|客服通话|\n|4|传输层|端到端传输、分段、重传|拆包编号、签收回执|\n|3|网络层|路由/跨网段|分拨中心规划路线|\n|2|数据链路层|帧封装与差错校验|地址标签|\n|1|物理层|比特流传输|卡车、飞机|\n\n---\n",
  "实习求职/面试八股/计算机面试经典八股.md": "+好的！计算机面试中最经典、最高频的“八股文”主要围绕以下几个核心领域展开。掌握这些基础知识和原理是通关技术面试的关键：\n\n## 🧠 一、 数据结构与算法\n\n1.  **基础数据结构：**\n    *   **数组 vs 链表：** 内存结构、访问/插入/删除时间复杂度、适用场景。\n    *   **栈(Stack) & 队列(Queue)：** LIFO/FIFO 原理、实现方式（数组/链表）、应用场景（函数调用栈、BFS/DFS）。\n    *   **哈希表(Hash Table)：** 原理（哈希函数、冲突解决-开放寻址/链地址法）、时间复杂度分析、负载因子、扩容机制。\n    *   **堆(Heap) / 优先队列(Priority Queue)：** 结构（通常是二叉堆）、操作（插入、删除堆顶、堆化）、应用（Top K、中位数、Dijkstra）。\n    *   **树(Tree)：**\n        *   二叉树(Binary Tree)：遍历（前序、中序、后序、层序）- 递归与非递归实现。\n        *   二叉搜索树(BST)：定义、查找、插入、删除、中序遍历有序性。\n        *   平衡二叉搜索树(AVL / 红黑树)：平衡因子/红黑规则、旋转操作、为什么需要（避免BST退化成链表）、应用（Java HashMap的TreeBin/TreeMap）。\n    *   **图(Graph)：** 表示方法（邻接矩阵、邻接表）、遍历算法（BFS、DFS）、常见算法（拓扑排序、最短路径-Dijkstra/Bellman-Ford/Floyd、最小生成树-Prim/Kruskal）。\n\n2.  **基础算法思想：**\n    *   **排序算法：**\n        *   比较排序：**快速排序**（分治、选基准、partition过程、时间复杂度-最好O(nlogn)/最坏O(n²)/平均、空间复杂度、稳定性❌）、**归并排序**（分治、稳定✅、时间复杂度O(nlogn)、空间复杂度O(n)）、**堆排序**（建堆O(n)、排序O(nlogn)、不稳定❌）、插入排序、冒泡排序、选择排序（原理、时间复杂度）。\n        *   非比较排序：计数排序、桶排序、基数排序（思想、适用场景）。\n    *   **搜索算法：** **二分查找**（前提有序、循环/递归实现、变种问题-找第一个/最后一个/旋转数组）。\n    *   **递归 & 分治：** 思想、经典问题（斐波那契、汉诺塔、归并/快排）。\n    *   **贪心算法(Greedy)：** 思想（局部最优->全局最优？）、适用场景（活动选择、霍夫曼编码、最小生成树-Prim/Kruskal）、与动态规划区别。\n    *   **动态规划(DP)：** **核心思想**（最优子结构、重叠子问题、状态转移方程）、**解题步骤**（定义状态、状态转移、初始化、边界、输出）、**经典问题**（斐波那契、爬楼梯、背包问题01/完全、最长公共子序列LCS、最长递增子序列LIS、编辑距离、股票买卖系列）。\n    *   **回溯(Backtracking)：** 思想（试错、DFS+剪枝）、经典问题（N皇后、全排列、组合、子集、数独）。\n    *   **双指针(Two Pointers)：** 应用（有序数组两数之和、滑动窗口-最小覆盖子串/最长无重复子串、快慢指针-链表判环/找中点）。\n    *   **位运算(Bit Manipulation)：** 常用操作（与、或、异或、非、移位）、常见技巧（判断奇偶、交换两数、找出只出现一次的数字、位1的个数）。\n\n## 🖥 二、 操作系统\n\n1.  **进程与线程：**\n    *   进程 vs 线程（定义、资源分配、切换开销、通信方式）。\n    *   **进程间通信(IPC)：** 管道、命名管道、信号、消息队列、共享内存、信号量、套接字。\n    *   **线程同步机制：** **互斥锁(Mutex)**、**信号量(Semaphore)**、**条件变量(Condition Variable)**、读写锁(Read-Write Lock)、自旋锁(Spin Lock)（原理、适用场景、死锁避免）。\n    *   **死锁(Deadlock)：** 必要条件（互斥、请求与保持、不可剥夺、环路等待）、预防策略、避免策略（银行家算法）、检测与恢复。\n2.  **内存管理：**\n    *   **虚拟内存(Virtual Memory)：** 为什么需要？分页(Paging)机制（页表、TLB快表）、分段(Segmentation)机制。\n    *   **页面置换算法：** **最佳置换(OPT)**、**先进先出(FIFO)**、**最近最久未使用(LRU)**、时钟算法(Clock) 的原理和优缺点。\n    *   **内存分配：** 伙伴系统(Buddy System)、Slab分配器。\n3.  **文件系统：** 文件描述符(File Descriptor)、inode结构、文件存储方式（连续、链式、索引）、目录结构。\n4.  **CPU调度：** 调度算法（FCFS、SJF、优先级、RR轮转、多级反馈队列）的目标和特点。\n5.  **I/O模型：** 阻塞I/O、非阻塞I/O、I/O多路复用(select/poll/epoll)、信号驱动I/O、异步I/O(AIO) 的区别和比较（特别是epoll的优势）。\n\n## 🌐 三、 计算机网络\n\n1.  **网络模型：** **OSI七层模型** 和 **TCP/IP四层模型** 各层功能、对应协议。\n2.  **核心协议：**\n    *   **TCP vs UDP：** 根本区别（连接、可靠性、有序性、流量控制、拥塞控制）、头部结构、应用场景。\n    *   **TCP可靠传输：** 序号/确认号、超时重传、滑动窗口机制。\n    *   **TCP连接管理：** **三次握手**（详细过程、为什么是三次？）、**四次挥手**（详细过程、为什么是四次？TIME_WAIT状态的作用？）。\n    *   **TCP流量控制：** 滑动窗口机制。\n    *   **TCP拥塞控制：** 慢启动(Slow Start)、拥塞避免(Congestion Avoidance)、快速重传(Fast Retransmit)、快速恢复(Fast Recovery) 算法原理。\n    *   **HTTP：**\n        *   请求方法（GET/POST/PUT/DELETE等区别）、状态码（1xx/2xx/3xx/4xx/5xx常见状态码含义）。\n        *   **HTTP/1.0 vs HTTP/1.1 vs HTTP/2 vs HTTP/3：** 主要改进（连接复用、头部压缩、服务器推送、QUIC协议）。\n        *   **HTTPS：** SSL/TLS协议作用、加密过程（非对称加密交换对称密钥、对称加密通信）、数字证书作用。\n    *   **DNS：** 作用、查询过程（递归、迭代）、记录类型（A、AAAA、CNAME、MX、NS）。\n3.  **网络安全基础：**\n    *   **对称加密 vs 非对称加密：** 原理、优缺点、代表算法（AES、RSA）。\n    *   **数字签名 & 数字证书：** 作用、原理（私钥签名，公钥验签；CA中心颁发证书）。\n    *   常见攻击：XSS、CSRF、SQL注入、DDoS、中间人攻击的原理和基本防御措施。\n4.  **网络层：** IP协议、IP地址分类/子网划分/CIDR、ARP协议、路由协议（RIP、OSPF、BGP基本思想）。\n5.  **传输层与应用层：** 端口号作用、Socket编程基础。\n\n## 🗃 四、 数据库（以关系型数据库 MySQL 为主）\n\n1.  **SQL基础：** 常用语句（SELECT, INSERT, UPDATE, DELETE, JOIN, GROUP BY, HAVING, ORDER BY, LIMIT）、多表连接（INNER JOIN, LEFT JOIN, RIGHT JOIN, FULL JOIN）。\n2.  **索引(Index)：**\n    *   **为什么需要索引？** 加速查询。\n    *   **数据结构：** **B+树**（为什么比B树更适合数据库？）、哈希索引（适用场景）。\n    *   **聚簇索引(Clustered Index) vs 非聚簇索引(Non-Clustered Index / Secondary Index)：** 根本区别（叶子节点是否存储完整行数据）、InnoDB实现。\n    *   **索引优化：** 覆盖索引、最左前缀原则、索引下推(ICP)。\n    *   **索引失效场景：** 函数操作、类型转换、`LIKE '%xx'`、OR条件（部分情况）、不等于(!=, <>）、索引列计算。\n3.  **事务(Transaction)：**\n    *   **ACID特性：** 原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability) 的含义。\n    *   **隔离级别(Isolation Level)：** **读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read - MySQL默认)、串行化(Serializable)**。每个级别能解决哪些并发问题（脏读、不可重复读、幻读）？\n    *   **并发问题：** 脏读、不可重复读、幻读的定义。\n    *   **MVCC(多版本并发控制)：** 原理（Undo Log、Read View）、如何实现RC和RR级别（特别是RR如何解决幻读？）。\n4.  **锁(Locking)：** 共享锁(S锁/读锁)、排他锁(X锁/写锁)、意向锁、行锁、表锁、间隙锁(Gap Lock)、临键锁(Next-Key Lock)的作用和应用场景（特别是InnoDB如何解决幻读）。\n5.  **日志(Logging)：**\n    *   **Redo Log(重做日志)：** 作用（保证持久性、Crash-Safe）、Write-Ahead Logging(WAL)机制。\n    *   **Undo Log(回滚日志)：** 作用（保证原子性、实现MVCC）。\n    *   **Binlog(归档日志)：** 作用（主从复制、数据恢复）、格式（Statement/Row/Mixed）。\n6.  **数据库设计：** 三大范式（1NF, 2NF, 3NF）基本概念、反范式化设计场景。\n7.  **性能优化：** Explain分析SQL执行计划、慢查询优化思路。\n\n## 📐 五、 系统设计（面向中高级岗位）\n\n1.  **设计原则：** KISS, YAGNI, DRY, SOLID (尤其是单一职责、开闭原则)。\n2.  **方法论：**\n    *   需求澄清（功能需求、非功能需求-性能/可用性/扩展性/一致性/容错性/安全性）。\n    *   估算（QPS、TPS、存储量、带宽）。\n    *   抽象与模块化。\n    *   核心组件设计（API、数据模型、存储方案、算法）。\n    *   深入细节（扩展性、可靠性、性能优化）。\n3.  **常见组件与模式：**\n    *   负载均衡（LB: Nginx, HAProxy, LVS）。\n    *   缓存（Cache: Redis, Memcached）- 缓存策略（Cache Aside, Read/Write Through, Write Behind）、缓存穿透/击穿/雪崩及解决方案。\n    *   消息队列（MQ: Kafka, RabbitMQ, RocketMQ）- 解耦、异步、削峰填谷、保证最终一致性。\n    *   数据库扩展：读写分离、分库分表（水平/垂直拆分）、分区。\n    *   分布式ID生成（Snowflake算法）。\n    *   分布式一致性协议：**CAP理论**、**BASE理论**、**Raft/Paxos**（选主、日志复制）基本原理（理解核心思想即可，不要求推导）。\n    *   微服务架构：服务注册与发现（Eureka, Nacos, Consul）、API网关（Gateway）、配置中心、服务调用（RPC/REST）、熔断限流（Hystrix, Sentinel）。\n4.  **经典系统设计题：** 设计Twitter/微博、设计短链系统、设计秒杀系统、设计分布式缓存、设计搜索引擎、设计聊天系统等。\n\n## 🐍 六、 编程语言特性（根据应聘语言选择）\n\n1.  **面向对象(OOP)：** 封装、继承、多态、抽象类 vs 接口、重载 vs 重写。\n2.  **内存管理：** 垃圾回收(GC)原理（标记清除、复制、标记整理、分代收集-G1/ZGC）、引用类型（强引用、软引用、弱引用、虚引用）。\n3.  **并发编程：** 线程生命周期、创建方式、线程池（核心参数、工作流程、拒绝策略）、锁（Synchronized底层原理、Lock/Condition）、并发容器（ConcurrentHashMap原理-CAS+synchronized+分段锁思想）、原子类（CAS操作、ABA问题）、线程间通信。\n4.  **语言特性：** 如Java的JVM内存区域、类加载机制、反射、异常体系、集合框架（HashMap源码：put/get流程、扩容、JDK1.7 vs 1.8+）；Python的GIL、装饰器、生成器、鸭子类型；Go的Goroutine、Channel、defer等。\n\n## 📌 关键点提醒\n\n1.  **理解原理，而非死记硬背：** 面试官更关注你是否真正理解了背后的思想（为什么用这个？解决了什么问题？优缺点是什么？）。\n2.  **联系实际：** 思考这些知识在实际系统/项目中是如何应用的。\n3.  **清晰表达：** 能条理清晰、简洁准确地阐述概念和过程。\n4.  **动手实践：** 算法题要动手写，数据库要会写SQL，系统设计要多思考多画图。\n5.  **关注细节：** 很多问题会深入到具体实现细节（如HashMap冲突解决、ConcurrentHashMap分段锁演变、MySQL RR级别如何避免幻读、TCP TIME_WAIT）。\n6.  **追踪发展：** 了解一些新技术趋势（如HTTP/3, QUIC, eBPF, 云原生, Serverless）的基本概念。\n\n这份清单涵盖了计算机面试中最核心、最高频的基础知识点。针对具体岗位（前端、后端、算法、运维、测试等）",
  "嵌入式/USB拓展坞接口数量决定因素.md": "一个USB拓展坞（或集线器）能拓展多少个USB接口，主要由以下几个因素决定：\n \n1. USB协议规范与层级限制\n \n- USB主机控制器的能力：电脑本身的USB主机控制器（如主板上的控制器）决定了初始可连接的设备数量。根据USB规范，一个主机控制器理论上最多可连接 127个设备，但这是通过多级集线器级联实现的（例如主机→一级集线器→二级集线器→……）。\n- 单级集线器的端口数：单个集线器（如拓展坞）的直接端口数通常为 4、7、10个 等，这是由集线器芯片的设计决定的。例如，常见的4口集线器是单芯片直接支持的标准配置。\n \n2. 集线器芯片的硬件设计\n \n- 主控芯片的能力：不同型号的集线器芯片（如瑞萨、德州仪器等品牌）支持的端口数量不同。芯片内部集成的物理接口数量和信号处理能力直接限制了拓展坞的端口数。\n- 信号分配与带宽共享：USB接口共享总线带宽（如USB 3.0的5Gbps），过多端口可能导致带宽不足。因此，芯片设计时会平衡端口数与性能，避免过多端口导致速度下降。\n \n3. 电源供应能力\n \n- 主机供电 vs 外接电源：\n- 无外接电源（总线供电）：依赖电脑USB端口的功率（USB 2.0约500mA，USB 3.0约900mA）。若拓展坞无外接电源，总功率需低于主机端口上限，否则可能因供电不足导致设备无法工作（例如连接多个移动硬盘时易出现问题）。\n- 有外接电源（自供电）：通过适配器供电，可支持更多高功耗设备，端口数主要受芯片和设计限制。\n- 单端口功率限制：每个USB端口需符合规范（如USB 2.0单端口最大500mA，USB 3.0最大900mA），总功率需在集线器设计的安全范围内。\n \n4. 信号传输与物理限制\n \n- 信号衰减与稳定性：USB信号在长距离或多端口分支中会衰减，尤其是高速率信号（如USB 3.0以上）。拓展坞的电路设计需保证信号完整性，过多端口可能增加干扰风险，因此实际端口数会受限于硬件可靠性。\n- 物理空间与布局：拓展坞的体积和接口排列也会影响端口数量，例如小型便携拓展坞通常设计为4口，而桌面级集线器可能有7-10个端口。\n \n5. 厂商设计与市场需求\n \n- 用户场景导向：厂商会根据目标用户（如普通办公、专业外设连接）设计端口数。例如，针对轻薄本的拓展坞可能集成4-6个端口（兼顾便携性和实用性），而工业级集线器可能支持更多端口。\n- 成本与性价比：更多端口意味着更高的芯片和制造成本，厂商需在功能与价格间平衡。\n \n总结\n \n核心决定因素：\n \n- USB协议的层级与单集线器端口限制\n- 集线器芯片的硬件设计（端口数、带宽分配）\n- 电源供应能力（是否外接电源及总功率）\n- 信号传输的稳定性与物理空间限制\n \n实际中，常见的USB拓展坞多为 4-7个端口，高端或专用集线器可能支持更多（如10口以上），但需结合外接电源和高效的芯片方案来保证性能。",
  "嵌入式/光纤和网线的特点和区别.md": "\n## 一、 核心区别：传输原理\n\n1.  **光纤 (Fiber Optic Cable):**\n    *   **原理:** 利用光脉冲在极细的玻璃或塑料纤维中进行传输。\n    *   **信号:** 光信号（激光或LED）。\n    *   **介质:** 玻璃纤维芯（核心）和包层（折射率不同，实现全反射）。\n\n2.  **网线 (双绞线 - Twisted Pair Cable):**\n    *   **原理:** 利用电信号在相互缠绕的铜线中进行传输。\n    *   **信号:** 电信号。\n    *   **介质:** 铜导体（通常为4对双绞线）。\n\n## 二、 关键特点对比\n\n| 特性             | 光纤 (Fiber Optic)                                     | 网线/双绞线 (Twisted Pair)                             |\n| :--------------- | :----------------------------------------------------- | :----------------------------------------------------- |\n| **传输原理**     | **光信号**                                             | **电信号**                                             |\n| **传输介质**     | 玻璃纤维芯 + 包层                                      | 铜线                                                   |\n| **带宽/速度**    | **极高**。理论上可达Tbps级别，远超双绞线。常用10Gbps, 40Gbps, 100Gbps甚至更高。 | **相对较低**。受限于铜线物理特性（趋肤效应、串扰）。常用1Gbps, 10Gbps（短距离）。 |\n| **传输距离**     | **非常远**。单模光纤可达几十甚至上百公里（无需中继）。多模光纤可达几百米到几公里。 | **较短**。Cat5e/Cat6：100米（千兆）。Cat6a/Cat7：100米（万兆）。距离越长，信号衰减和失真越严重。 |\n| **抗干扰能力**   | **极强**。光信号不受电磁干扰、无线电频率干扰影响。可在强电磁环境（如工厂、医院）或雷暴天气下稳定工作。 | **较弱**。铜线是导体，易受电磁干扰、串扰影响。需要屏蔽层（STP/FTP）在干扰环境下改善性能，但成本增加。 |\n| **安全性**       | **高**。光信号不易被窃听（需要物理接入并截断光纤，且操作易被发现）。不辐射电磁信号。 | **较低**。电信号可能被电磁感应方式窃听（有一定难度）。铜线会辐射微弱电磁信号。 |\n| **尺寸与重量**   | **更细、更轻**。相同容量下，光纤比铜缆细得多、轻得多。 | **较粗、较重**。尤其是高类别带屏蔽的线缆。            |\n| **成本**         | **设备成本高**。光模块、光纤收发器、光纤交换机端口价格远高于铜口设备。<br>**线缆成本中等**。 | **设备成本低**。网卡、交换机端口非常普及且便宜。<br>**线缆成本中等偏低**（低类别线）。但高类别屏蔽线成本也较高。 |\n| **安装与维护**   | **技术要求高**。光纤端接（熔接、研磨）需要专业工具和技能。弯曲半径要求严格，过度弯折易断芯。 | **相对简单**。RJ45水晶头压接容易学习，工具普及。允许更大的弯曲半径，更耐弯折。 |\n| **连接器**       | LC, SC, ST, FC, MTP/MPO 等                             | RJ45 (8P8C)                                            |\n| **功耗**         | **较低**。光模块通常功耗低于同等速率电口。             | **较高**。尤其在高速率、长距离传输时，驱动电信号需要更大功率。 |\n| **主要类型**     | **单模光纤：** 细芯（~9µm），单束光，超长距离，高速。<br>**多模光纤：** 粗芯（50µm/62.5µm），多束光，中短距离，性价比高。 | **非屏蔽双绞线：** UTP（最常见），无屏蔽层，成本低。<br>**屏蔽双绞线：** STP/FTP/SFTP 等，带屏蔽层，抗干扰好，成本高。<br>**类别：** Cat5e (千兆), Cat6 (千兆/短距万兆), Cat6a (万兆), Cat7/7a/8 (更高性能) |\n| **典型应用场景** | 骨干网、城域网、数据中心互联、长距离传输、高干扰环境、高带宽需求（视频、云计算、存储网络）、FTTH/FTTx入户。 | 局域网接入层（电脑到交换机）、电话系统、监控系统（POE供电）、家庭网络、办公室布线、短距离设备互联。 |\n\n## 三、 总结\n\n*   **选择光纤当：**\n    *   你需要**极高的带宽**（10Gbps以上）。\n    *   你需要**超长的传输距离**（几百米到几十公里）。\n    *   你在**强电磁干扰**环境中。\n    *   你对**安全性**要求非常高。\n    *   你需要**节省空间和减轻重量**（如数据中心）。\n    *   你需要**更低的传输延迟**（虽然差异很小，但对超低延迟场景重要）。\n    *   你**不差钱**（尤其是一次性投入的设备成本）。\n\n*   **选择双绞线当：**\n    *   你的需求是**千兆或万兆（短距离）**。\n    *   传输距离在**100米以内**。\n    *   环境**电磁干扰较小**。\n    *   你对**成本非常敏感**（尤其是设备端口成本）。\n    *   你需要**简单易行的安装和维护**。\n    *   你需要为设备提供**PoE供电**（目前光纤无法直接供电）。\n    *   应用场景是**终端设备接入**（电脑、IP电话、摄像头、AP等）。\n\n**简单来说：光纤是“高速公路”，速度快、距离远、容量大、成本高、建设维护复杂；双绞线是“城市道路”，灵活方便、覆盖广、成本低、但速度和距离有限。** 现代网络通常是两者的结合：光纤做骨干和长距离互联，双绞线做最后100米的接入。",
  "数据库/Linux控制台登录Mysql8,MongoDB,PostgresDB教程.md": "\n---\n\n## 1. MySQL\n\n### 登录命令\n\n```bash\nmysql -h <主机地址> -u <用户名> -p\n```\n\n例如：\n\n```bash\nmysql -h localhost -u root -p\n```\n\n然后系统会提示你输入密码。\n你还可以指定数据库：\n\n```bash\nmysql -h localhost -u user_name -p 数据库名\n```\n\n（登录后直接使用该数据库）\n\n### 注意事项\n\n- 常见选项： `-h`（主机）、`-u`（用户名）、`-p`（提示输入密码）\n- **为了安全**，建议使用 `-p` 而不直接在命令行后面写密码，因为其他用户可能通过进程列表看到。\n- 登录后你就会进入 MySQL 的交互提示符，比如 `mysql>`，可以执行 SQL 语句。 \n    \n\n---\n\n## 2. PostgreSQL\n\n### 登录命令\n\n对于 PostgreSQL，一般使用 `psql` 客户端。常用方式如下：\n\n#### 本地切换为 postgres 系统用户然后登录\n\n```bash\nsudo -i -u postgres\npsql\n```\n\n或者直接：\n\n```bash\nsudo -u postgres psql\n```\n\n这样你以系统用户 `postgres`（PostgreSQL 默认超级用户）身份进入数据库。\n\n#### 使用指定用户、数据库、主机登录\n\n```bash\npsql -U <用户名> -d <数据库名> -h <主机地址> -p <端口>\n```\n\n例如：\n\n```bash\npsql -U myuser -d mydb -h localhost -p 5432\n```\n\n\n### 注意事项\n\n- 默认端口通常为 5432，如果你使用了非标准端口，则需指定 `-p`。\n- 用户 `postgres` 的 UNIX 账户通常是锁定的（不能用密码登录系统）——重点是用它来启动 `psql`。\n- 登录后提示符通常是 `postgres=#`（如果以超级用户身份）。\n    \n\n---\n\n## 3. MongoDB\n\n### 登录命令\n\n以本地默认部署为例，使用 MongoDB shell（比如 `mongosh`）登录：\n\n```bash\nmongosh\n```\n\n这会连接到 `mongodb://localhost:27017` 默认端口。\n\n如果你需要指定主机、端口或用户认证：\n\n```bash\nmongosh --host <主机地址> --port <端口> --username <用户名> --password\n```\n\n或者使用连接字符串：\n\n```bash\nmongosh \"mongodb://<用户名>@<主机地址>:<端口>/<数据库>\" --password\n```\n\n\n### 在 shell 中认证用户\n\n登录进入 shell 后，如果还未认证，可以使用：\n\n```javascript\nuse <数据库名>;\ndb.auth(\"<用户名>\", \"<密码>\");\n```\n\n或者只输入用户名让系统提示你输入密码：\n\n```javascript\ndb.auth(\"<用户名>\");\n```\n\n\n\n### 注意事项\n\n- 默认端口为 27017。\n- 当启用了访问控制（authentication）时，需要提供用户名和密码。否则可能会连接但不能执行特定操作。\n- `mongosh`（新的 shell）正在取代旧的 `mongo` shell。 \n\n---\n",
  "数据库/Linux控制台登录Redis教程.md": "\n---\n\n## 🔐 1. 在配置文件中设置密码\n\n1. 打开 Redis 的主配置文件（假设你安装在 Debian 12 上，通常为 `/etc/redis/redis.conf`）：\n    \n    ```bash\n    sudo nano /etc/redis/redis.conf\n    ```\n    \n2. 找到这一行（可能被注释 `#` 掉了）：\n    \n    ```\n    # requirepass foobared\n    ```\n    \n    根据官方文档，这个 `requirepass` 指令就是用于开启 “旧式”统一密码认证机制。([Redis](https://redis.io/docs/latest/operate/oss_and_stack/management/security/?utm_source=chatgpt.com \"Redis security | Docs\"))\n    \n3. 去掉注释 `#`，并设置为你想要的强密码。例如：\n    \n    ```\n    requirepass YourStr0ngPassword!123\n    ```\n    \n4. 保存并退出编辑器。\n    \n5. 重启 Redis 服务使新配置生效：\n    \n    ```bash\n    sudo systemctl restart redis-server\n    ```\n    \n\n> 注意：如果你用的是 Redis 6+ 且希望使用更先进的用户/ACL机制，也可以考虑使用 `acl setuser …` 等。但设置 `requirepass` 是最简单直接的方法。([Redis](https://redis.io/docs/latest/operate/oss_and_stack/management/security/?utm_source=chatgpt.com \"Redis security | Docs\"))\n\n---\n\n## 🧑‍💻 2. 使用 redis-cli 登录并认证\n\n1. 在终端运行 Redis 命令行工具：\n    \n    ```bash\n    redis-cli\n    ```\n    \n    此时你可能会看到提示符，比如 `127.0.0.1:6379>`。如果已经设置了密码但还未认证，执行任何写操作会出现类似 `NOAUTH Authentication required.` 的错误。([Stack Overflow](https://stackoverflow.com/questions/7537905/how-to-set-password-for-redis?utm_source=chatgpt.com \"How to set password for Redis? - Stack Overflow\"))\n    \n2. 在提示符下输入认证命令：\n    \n    ```\n    AUTH YourStr0ngPassword!123\n    ```\n    \n    如果密码正确，会返回 `OK`。此后你就可以执行 `SET`, `GET` 等命令。([Redis](https://redis.io/docs/latest/commands/auth/?utm_source=chatgpt.com \"AUTH | Docs - Redis\"))\n    \n3. 你也可以在连接时直接带上密码，这样就省一步认证：\n    \n    ```bash\n    redis-cli -a YourStr0ngPassword!123\n    ```\n    \n    或者：\n    \n    ```bash\n    redis-cli -h 127.0.0.1 -p 6379 -a YourStr0ngPassword!123\n    ```\n    \n    ([Stack Overflow](https://stackoverflow.com/questions/35745481/redis-cli-with-password?utm_source=chatgpt.com \"Redis-cli with password - Stack Overflow\"))\n    \n\n---\n\n## ✅ 快速示例\n\n假设你的密码是 `MyRedisPass123!`，步骤如下：\n\n```bash\nsudo nano /etc/redis/redis.conf\n# 修改：\n# requirepass MyRedisPass123!\nrequirepass MyRedisPass123!\nsudo systemctl restart redis-server\n\nredis-cli\n127.0.0.1:6379> AUTH MyRedisPass123!\nOK\n127.0.0.1:6379> PING\nPONG\n127.0.0.1:6379> SET foo bar\nOK\n127.0.0.1:6379> GET foo\n\"bar\"\n```\n\n---\n",
  "数据库/MongoDB数据库优化方式一览.md": "除了索引之外，MongoDB 在 CRUD 操作优化上还有多种有效策略，尤其在处理海量数据时更为关键。以下是综合各技术文档和实践总结的核心优化方法：\n\n---\n\n### 🔄 一、批量操作优化\n1. **使用 `bulkWrite` 替代单条操作**  \n   通过批量写入减少网络开销和事务开销。基于 `ReplaceOneModel` 启用 `upsert`，实现存在更新、不存在插入的高效操作：\n   ```java\n   public void batchSave(List<?> dataList) {\n       List<ReplaceOneModel<Document>> bulkOps = dataList.stream()\n           .map(item -> {\n               Document doc = convertToDocument(item); // 转换为Document\n               return new ReplaceOneModel<>(\n                   Filters.eq(\"_id\", doc.get(\"_id\")), \n                   doc, \n                   new UpdateOptions().upsert(true)\n               );\n           }).collect(Collectors.toList());\n       collection.bulkWrite(bulkOps); // 批量执行\n   }\n   ```\n   此方法将多条操作合并为一次请求，写入性能提升显著。\n\n---\n\n### 📖 二、分页查询优化\n1. **避免精确 `count`**  \n   当数据量超大时，`count` 可能极慢。采用阈值法：若跳过 `MAX_PAGE_COUNT`（如1万条）后仍有数据，则返回阈值提示“数据超过1万条”，避免全表扫描：\n   ```java\n   private long approxCount(MongoTemplate mongoTemplate, Query query) {\n       query = query.with(PageRequest.of(MAX_PAGE_COUNT, 1));\n       return mongoTemplate.find(query, Entity.class).isEmpty() \n           ? mongoTemplate.count(query) \n           : MAX_PAGE_COUNT;\n   }\n   。\n   ```\n\n2. **用条件替代 `skip`**  \n   深度分页时（如第100页），避免 `skip(9900)`。改为记录上一页末尾的排序字段值（如时间戳），作为下一页查询条件：\n   ```sql\n   -- 原查询：db.collection.find().sort({time:-1}).skip(9900).limit(100)\n   -- 优化后：\n   db.collection.find({ time: { $lt: lastPageEndTime } })\n     .sort({ time: -1 })\n     .limit(100);\n   ```\n   此方法将 **O(N)** 的跳过操作转为 **O(1)** 的条件过滤。\n\n---\n\n### 📤 三、全量导出优化\n1. **字段投影减少数据传输**  \n   仅查询必要字段，降低网络与内存开销：\n   ```java\n   Query query = new Query();\n   query.fields().include(\"_id\").include(\"name\"); // 只返回_id和name。\n   ```\n\n2. **流式处理替代全量加载**  \n   使用 `stream()` 逐条处理数据，避免 `findAll` 导致内存溢出：\n   ```java\n   try (CloseableIterator<Entity> iter = mongoTemplate.stream(query, Entity.class)) {\n       while (iter.hasNext()) {\n           process(iter.next()); // 单条处理\n       }\n   }\n   ```\n   相比分页查询，流式处理无 `skip` 开销，且内存占用恒定。\n\n---\n\n### 🧩 四、文档设计优化\n1. **打破第三范式**  \n   - **冗余字段**：将高频查询的关联字段（如部门名称）冗余到主文档，避免联表查询。\n   - **内嵌设计**：一对多关系直接嵌套子文档（如订单内嵌商品列表），提升读取效率。但需注意文档大小限制（16MB）。\n   - **引用设计**：多对多关系使用ID数组而非完整嵌套，避免文档膨胀：\n     ```json\n     // 学生文档\n     {\n       \"_id\": \"s001\",\n       \"name\": \"Alice\",\n       \"teachers\": [\"t01\", \"t02\"] // 仅存储ID\n     }\n     ```\n\n---\n\n### ⚙️ 五、分片集群优化\n1. **碎片整理（MongoDB <7.0）**  \n   在早期版本中，分片集合可能因频繁写入产生碎片化小数据块，导致CRUD延迟。通过 `configureCollectionBalancing` 命令合并数据块，但需注意：\n   - 整理期间可能短暂阻塞元数据更新。\n   - MongoDB 7.0+ 已支持自动合并，通常无需手动操作。\n\n2. **负载均衡窗口设置**  \n   在业务低峰期触发负载均衡器迁移数据块，减少对CRUD的影响。\n\n---\n\n### 💎 六、其他关键技巧\n1. **合理控制事务范围**：短事务减少锁竞争。\n2. **写入确认级别调整**：对非关键数据使用 `w:0`（无确认），提升写入速度（牺牲一致性）。\n3. **TTL索引自动清理**：为临时数据（如日志）设置过期时间，减少存储压力。\n\n---\n\n### 💎 优化方法效果对比表\n| **优化方向**       | **适用场景**               | **性能提升效果**       | **实现复杂度** |\n|--------------------|--------------------------|----------------------|--------------|\n| **批量写入**       | 数据导入、批量更新         | ⭐⭐⭐⭐⭐ (极高)         | ⭐⭐ (中等)    |\n| **流式导出**       | 大数据量导出              | ⭐⭐⭐⭐ (避免OOM)       | ⭐ (简单)     |\n| **条件分页**       | 深度分页（>100页）        | ⭐⭐⭐⭐ (O(1) 跳转)     | ⭐⭐ (中等)    |\n| **冗余字段**       | 高频关联查询              | ⭐⭐⭐ (减少联表)        | ⭐⭐⭐ (较高)   |\n| **分片碎片整理**   | MongoDB 6.0以下分片集群   | ⭐⭐ (减少延迟)         | ⭐⭐⭐⭐ (复杂) |\n\n---\n\n> 💡 **实践建议**：优先从**批量操作**和**分页策略**入手，这两类优化代码改动小且收益显著。海量数据场景下，**流式处理+字段投影**是导出标配方案。分片集群升级到 MongoDB 7.0+ 可减少运维负担。",
  "数据库/MongoDB添加管理员账号.md": " \n接下来我们来 **一步步给 MongoDB 添加用户账户（角色管理）**。\n\n假设你希望创建一个：\n- 用户名：`shumengya`\n- 密码：`shumengya520`\n- 权限：对整个数据库系统有管理权限（root 权限）\n    \n\n---\n\n## 🧭 步骤 1：进入 MongoDB Shell\n\nMongoDB 7.x 之后使用的是新客户端 `mongosh`：\n\n```bash\nmongosh\n```\n\n如果提示 `command not found`，可以执行：\n\n```bash\nmongo\n```\n\n---\n\n## 🧩 步骤 2：切换到 `admin` 数据库\n\n（MongoDB 的用户管理都存在 `admin` 数据库里）\n\n```javascript\nuse admin\n```\n\n---\n\n## 🧰 步骤 3：创建管理员用户\n\n运行下面的命令创建一个超级管理员账号：\n\n```javascript\ndb.createUser({\n  user: \"shumengya\",\n  pwd: \"shumengya520\",\n  roles: [ { role: \"root\", db: \"admin\" } ]\n})\n```\n\n✅ 成功后会输出：\n\n```\nSuccessfully added user: {\n    \"user\" : \"shumengya\",\n    \"roles\" : [ { \"role\" : \"root\", \"db\" : \"admin\" } ]\n}\n```\n\n---\n\n## 🔐 步骤 4：启用身份验证\n\n编辑 MongoDB 的配置文件：\n\n```bash\nsudo nano /etc/mongod.conf\n```\n\n找到或添加以下部分（注意缩进）：\n\n```yaml\nsecurity:\n  authorization: enabled\n```\n\n保存退出后，重启 MongoDB：\n\n```bash\nsudo systemctl restart mongod\n```\n\n---\n\n## ✅ 步骤 5：验证登录是否成功\n\n```bash\nmongosh -u shumengya -p shumengya520 --authenticationDatabase admin\n```\n\n如果看到类似：\n\n```\ntest>\n```\n\n说明登录成功 ✅\n\n---\n\n## 💡 可选：为特定数据库创建普通用户\n\n比如你有个业务数据库叫 `farmgame`，可以创建普通读写用户：\n\n```javascript\nuse farmgame\ndb.createUser({\n  user: \"gameuser\",\n  pwd: \"gamepass123\",\n  roles: [ { role: \"readWrite\", db: \"farmgame\" } ]\n})\n```\n\n---\n\n## 🧱 总结\n\n|操作|命令或说明|\n|---|---|\n|创建管理员|`db.createUser({user: \"shumengya\", pwd: \"...\", roles: [{role: \"root\", db: \"admin\"}]})`|\n|开启认证|`/etc/mongod.conf` → `security.authorization: enabled`|\n|登录验证|`mongosh -u shumengya -p shumengya520 --authenticationDatabase admin`|\n\n---\n",
  "数据库/MongoDB的索引一览.md": "\n**索引的核心作用：**\n\n1.  **大幅减少查询需要扫描的文档数量：** 没有索引时，MongoDB 必须执行集合扫描（`COLLSCAN`），即检查集合中的*每一个*文档。有了合适的索引，MongoDB 可以使用索引扫描（`IXSCAN`）快速定位到包含所需数据的文档位置。\n2.  **加速排序：** 如果排序字段包含在索引中，MongoDB 可以直接利用索引中已经排好的顺序返回结果，避免昂贵的在内存中排序。\n3.  **支持高效的数据去重：** `$group` 聚合阶段的分组操作可以利用索引。\n4.  **实现覆盖查询：** 如果查询只需要返回索引中包含的字段，MongoDB 可以*完全*从索引中获取结果，无需去读取实际的文档数据，速度极快。\n\n**MongoDB 支持的索引类型：**\n\n1.  **单字段索引：**\n    *   最基本的索引类型，在单个字段上创建。\n    *   示例：`db.collection.createIndex({ name: 1 })` (1 表示升序，-1 表示降序。对于纯等值查询，顺序通常不重要；对于排序查询，顺序很重要)。\n\n2.  **复合索引：**\n    *   在多个字段上创建的索引。\n    *   字段的顺序**极其重要**。它决定了索引如何组织和哪些查询模式可以利用该索引（最左前缀原则）。\n    *   示例：`db.collection.createIndex({ status: 1, order_date: -1 })`。这个索引可以高效支持：\n        *   只查询 `status` 的查询\n        *   同时查询 `status` 和 `order_date` 的查询\n        *   查询 `status` 并按 `order_date` 排序的查询\n    *   但不支持只查询 `order_date` 的查询（不符合最左前缀）。\n\n3.  **多键索引：**\n    *   当索引字段是数组时，MongoDB 会自动为数组中的每个元素创建索引条目。\n    *   用于高效查询数组字段中的元素。\n    *   示例：索引 `db.collection.createIndex({ tags: 1 })` 可以高效支持查询 `db.collection.find({ tags: \"mongodb\" })`。\n\n4.  **地理空间索引：**\n    *   **2dsphere：** 用于查询存储为 GeoJSON 对象或传统坐标对的地理空间数据（地球球面几何）。支持邻近查询（`$near`）、包含查询（`$geoWithin`）、相交查询（`$geoIntersects`）等。\n    *   **2d：** 用于在二维平面上（如地图游戏）查询存储为传统坐标对的数据。主要用于平面几何计算。\n\n5.  **文本索引：**\n    *   支持对字符串或字符串数组字段的内容进行文本搜索。\n    *   支持词干提取、停用词过滤等基本文本处理功能。\n    *   示例：`db.collection.createIndex({ description: \"text\" })`，然后使用 `$text` 操作符进行搜索。\n\n6.  **哈希索引：**\n    *   对字段值进行哈希运算，并在哈希值上建立索引。\n    *   主要用途是为**分片键**提供更均匀的数据分布（使用`hashed`分片策略时）。\n    *   只支持等值匹配查询，不支持范围查询、排序或其他操作。\n    *   示例：`db.collection.createIndex({ _id: \"hashed\" })`。\n\n7.  **通配符索引：**\n    *   可以索引文档中未知或任意字段。适用于模式动态变化的场景。\n    *   示例：\n        *   `db.collection.createIndex({ \"userMetadata.$**\": 1 })` 索引 `userMetadata` 子文档中的所有字段。\n        *   `db.collection.createIndex({ \"$**\": 1 })` 索引文档中的所有字段（谨慎使用，开销大）。\n\n8.  **唯一索引：**\n    *   强制索引字段的值在整个集合中是唯一的（`_id` 字段默认就有唯一索引）。\n    *   可以用于单字段或复合字段。\n    *   示例：`db.collection.createIndex({ email: 1 }, { unique: true })`。\n\n9.  **TTL 索引：**\n    *   一种特殊的单字段索引，用于在指定时间后或在指定时间点自动从集合中删除文档。字段必须是日期类型或包含日期元素的数组。\n    *   适用于会话数据、日志、临时数据等。\n    *   示例：`db.logs.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 })` (文档在 `createdAt` 时间之后 3600 秒/1 小时被删除)。\n\n10. **稀疏索引：**\n    *   只包含具有索引字段的文档的条目。即使索引字段值为 `null`，也会包含在内；但如果文档*完全缺失*该索引字段，则不会被索引。\n    *   节省空间，提高索引效率（当字段在大部分文档中缺失时）。\n    *   示例：`db.collection.createIndex({ optionalField: 1 }, { sparse: true })`。\n\n**如何管理和使用索引：**\n\n1.  **创建索引：** 使用 `db.collection.createIndex()` 方法。\n    *   示例：`db.products.createIndex({ category: 1, price: -1 })`\n2.  **查看索引：** 使用 `db.collection.getIndexes()` 方法。\n3.  **删除索引：** 使用 `db.collection.dropIndex()` 或 `db.collection.dropIndexes()` 方法。\n4.  **分析查询性能：** 使用 `explain()` 方法查看查询的执行计划，确认是否使用了索引（`IXSCAN`）以及使用了哪个索引。这是优化查询的关键步骤。\n    *   示例：`db.orders.find({ status: \"A\", amount: { $gt: 100 } }).sort({ order_date: -1 }).explain(\"executionStats\")`\n5.  **索引管理最佳实践：**\n    *   **为常用查询模式创建索引：** 分析你的应用最常见的查询（`find`, `sort`, `aggregate`中的`$match`, `$group`, `$sort`等阶段），为这些查询涉及的字段创建合适的索引（通常是复合索引）。\n    *   **遵循最左前缀原则：** 设计复合索引时，将最常用于过滤或排序的字段放在左边。\n    *   **考虑选择性：** 选择性高的字段（如唯一值多的字段）放在复合索引的前面通常更有效。\n    *   **使用覆盖查询：** 尽量让查询只返回索引中包含的字段。\n    *   **监控索引使用率：** MongoDB Profiler 或 Atlas 性能监控可以查看索引的使用情况。使用率低的索引应考虑删除，因为它们会消耗写性能和存储空间。\n    *   **权衡读写性能：** 索引会加速读操作，但会减慢写操作（插入、更新、删除），因为写操作需要维护索引。不要过度索引。\n    *   **后台创建大索引：** 在大型集合上创建索引可能耗时很长并阻塞操作。使用 `{ background: true }` 选项可以在后台创建索引（虽然仍可能有性能影响，但不会完全阻塞读写）。\n    *   **合理使用内存：** 确保有足够的内存将常用索引（或其活跃部分）保存在内存中，避免频繁的磁盘 I/O。\n\n**总结：**\n\nMongoDB 提供了极其丰富和强大的索引类型（单字段、复合、多键、地理空间、文本、哈希、通配符、唯一、TTL、稀疏）来满足各种查询场景的优化需求。**创建和管理合适的索引是提升 MongoDB 查询性能最关键的手段。** 务必结合你的具体查询模式，使用 `explain()` 分析执行计划，遵循索引设计的最佳实践（特别是复合索引的最左前缀原则），并持续监控和调整索引策略。",
  "数据库/MySQL数据库支持的数据类型.md": " \n\n## 1️⃣ 数值类型（Numeric）\n\n| 类型分类 | 数据类型                                                      | 说明            |\n| ---- | --------------------------------------------------------- | ------------- |\n| 整数型  | `TINYINT`、`SMALLINT`、`MEDIUMINT`、`INT`/`INTEGER`、`BIGINT` | 存储不同范围的整数     |\n| 精确小数 | `DECIMAL(M,D)`、`NUMERIC`                                  | 高精度定点数（常用于金额） |\n| 浮点数  | `FLOAT`、`DOUBLE`/`REAL`                                   | 近似数值（科学计算）    |\n| 位类型  | `BIT(M)`                                                  | 存储二进制位        |\n|      |                                                           |               |\n|      |                                                           |               |\n\n---\n\n## 2️⃣ 日期与时间类型（Date & Time）\n\n|数据类型|格式|说明|\n|---|---|---|\n|`DATE`|YYYY-MM-DD|日期|\n|`DATETIME(fsp)`|YYYY-MM-DD HH:MM:SS|日期 + 时间|\n|`TIMESTAMP(fsp)`|YYYY-MM-DD HH:MM:SS|时间戳（支持自动更新）|\n|`TIME`|HH:MM:SS|时间或时间间隔|\n|`YEAR`|YYYY|年份（2 位或 4 位）|\n\n---\n\n## 3️⃣ 字符串与二进制类型（String & Binary）\n\n|类型分类|数据类型|说明|\n|---|---|---|\n|定长字符串|`CHAR(M)`|定长，最大 255|\n|变长字符串|`VARCHAR(M)`|可变长度，最大 65535（受行大小限制）|\n|定长二进制|`BINARY(M)`|定长二进制|\n|变长二进制|`VARBINARY(M)`|变长二进制|\n|文本|`TINYTEXT`、`TEXT`、`MEDIUMTEXT`、`LONGTEXT`|存储大文本|\n|二进制大对象|`TINYBLOB`、`BLOB`、`MEDIUMBLOB`、`LONGBLOB`|存储二进制数据|\n|枚举|`ENUM('a','b',...)`|单选固定集合|\n|集合|`SET('a','b',...)`|多选固定集合|\n\n---\n\n## 4️⃣ 空间数据类型（Spatial）\n\n|数据类型|说明|\n|---|---|\n|`GEOMETRY`|任意几何对象|\n|`POINT`|点|\n|`LINESTRING`|线|\n|`POLYGON`|多边形|\n|`MULTIPOINT`、`MULTILINESTRING`、`MULTIPOLYGON`、`GEOMETRYCOLLECTION`|组合空间对象|\n\n---\n\n## 5️⃣ JSON 类型\n\n|数据类型|说明|\n|---|---|\n|`JSON`|存储 JSON 文档，支持索引与函数操作|\n\n---\n",
  "数据库/未命名.md": "",
  "数据结构与算法/二分查找右侧边界算法总结.md": "# 二分查找右侧边界算法总结\r\n\r\n\r\n\r\n## 题目描述\r\n\r\n\r\n\r\n在一个有序不递减的数组中（可能包含重复元素），使用二分查找找到某个值 `x` 最后一次出现的位置。如果该值不存在，则返回 -1。\r\n\r\n\r\n\r\n## 输入格式\r\n\r\n\r\n\r\n1. 第一行：一个整数 `n`，表示数组元素个数（`n <= 10^5`）。\r\n2. 第二行：`n` 个整数，代表数组元素（`1 <= 数组元素的值 <= 10^8`）。\r\n3. 第三行：一个整数 `q`，表示查询的数个数（`q <= 10^5`）。\r\n4. 第四行：`q` 个整数，代表要查找的值（`1 <= 要查找的数 <= 10^8`）。\r\n\r\n\r\n\r\n## 输出格式\r\n\r\n\r\n\r\n输出每个查询对应的最后一次出现的位置，若不存在则输出 -1。\r\n\r\n\r\n\r\n## 算法思路\r\n\r\n\r\n\r\n1. **初始化**：\r\n   - 设置左右指针 `l` 和 `r`，分别指向数组的开始和结束。\r\n   - 初始化结果 `res` 为 -1。\r\n2. **二分查找**：\r\n   - 当l小于等于r时，执行以下步骤：\r\n     - 计算中间索引 `m`。\r\n     - 如果 `a[m]` 等于 `x`，更新 `res` 为 `m + 1`，并将 `l` 移动到 `m + 1` 继续向右查找。\r\n     - 如果 `a[m]` 小于 `x`，将 `l` 移动到 `m + 1`。\r\n     - 如果 `a[m]` 大于 `x`，将 `r` 移动到 `m - 1`。\r\n3. **输出结果**：\r\n   - 返回结果 `res`。\r\n\r\n\r\n\r\n## 时间复杂度\r\n\r\n\r\n\r\n- 每次查找的时间复杂度为 O(log n)，因此总时间复杂度为 O(q log n)。\r\n\r\n\r\n\r\n## 示例代码\r\n\r\n\r\n\r\n```c\r\nc#include <stdio.h>\r\n\r\nint findRB(int a[], int n, int x) {\r\n    int l = 0, r = n - 1, res = -1;\r\n\r\n    while (l <= r) {\r\n        int m = l + (r - l) / 2;\r\n\r\n        if (a[m] == x) {\r\n            res = m + 1;\r\n            l = m + 1;\r\n        } else if (a[m] < x) {\r\n            l = m + 1;\r\n        } else {\r\n            r = m - 1;\r\n        }\r\n    }\r\n\r\n    return res;\r\n}\r\n\r\nint main() {\r\n    int n, q;\r\n\r\n    scanf(\"%d\", &n);\r\n    int a[n];\r\n\r\n    for (int i = 0; i < n; i++) {\r\n        scanf(\"%d\", &a[i]);\r\n    }\r\n\r\n    scanf(\"%d\", &q);\r\n    int qry[q];\r\n\r\n    for (int i = 0; i < q; i++) {\r\n        scanf(\"%d\", &qry[i]);\r\n    }\r\n\r\n    for (int i = 0; i < q; i++) {\r\n        int pos = findRB(a, n, qry[i]);\r\n        printf(\"%d \", pos);\r\n    }\r\n    printf(\"\\n\");\r\n\r\n    return 0;\r\n}\r\nc\r\n```\r\n\r\n\r\n\r\n## 总结\r\n\r\n\r\n\r\n该算法有效地使用二分查找来找到数组中元素的右侧边界，适合处理较大规模的输入数据。",
  "数据结构与算法/二分查找图书馆算法总结.md": "谢谢你的反馈。我们来修正代码。编译错误主要有两个原因：\r\n\r\n\r\n\r\n1. **变量大小问题**：在 C 语言中，数组的大小必须是固定的声明。我们使用 `#define` 或 `const` 来定义常量。\r\n2. **缺少比较函数**：`cmp` 函数必须在调用之前声明，或者将比较逻辑嵌入到 `main` 函数之前。\r\n\r\n\r\n\r\n我们可以做以下改变：\r\n\r\n\r\n\r\n- 使用 `#define` 来定义常量。\r\n- 在 `main` 函数之前声明比较函数。\r\n\r\n\r\n\r\n以下是经过修正的 C 语言代码：\r\n\r\n\r\n\r\n```c\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n\r\n#define MAXN 1000010\r\nint nums[MAXN];\r\nint key, n;\r\n\r\nint left_bound() {\r\n    if (n == 0) return -1;\r\n    int left = 0;\r\n    int right = n - 1;\r\n\r\n    while (left <= right) { \r\n        int mid = left + ((right - left) >> 1);\r\n        if (nums[mid] == key) {\r\n            right = mid - 1;\r\n        } else if (nums[mid] < key) {\r\n            left = mid + 1;\r\n        } else {\r\n            right = mid - 1; \r\n        }\r\n    }\r\n    if (left == n || nums[left] != key) return -1;\r\n    return left;\r\n}\r\n\r\nint right_bound() {\r\n    if (n == 0) return -1;\r\n    int left = 0;\r\n    int right = n - 1;\r\n\r\n    while (left <= right) { \r\n        int mid = left + ((right - left) >> 1);\r\n\r\n        if (nums[mid] == key) {\r\n            left = mid + 1;\r\n        } else if (nums[mid] < key) {\r\n            left = mid + 1;\r\n        } else {\r\n            right = mid - 1; \r\n        }\r\n    }\r\n    if (left == 0 || nums[left - 1] != key) return -1;\r\n    return left - 1;\r\n}\r\n\r\n// Compare function for qsort\r\nint cmp(const void *a, const void *b) {\r\n    return (*(int*)a - *(int*)b);\r\n}\r\n\r\nint main() {\r\n    scanf(\"%d %d\", &n, &key);\r\n    for (int i = 0; i < n; i++) {\r\n        scanf(\"%d\", &nums[i]); \r\n    }\r\n    qsort(nums, n, sizeof(int), cmp);\r\n    \r\n    if (left_bound() == -1) {\r\n        printf(\"Not Found\\n\");\r\n        return 0;    \r\n    }\r\n    int ans = (left_bound() + right_bound()) / 2 + 1;\r\n    printf(\"%d\\n\", ans);\r\n    return 0;\r\n}\r\n```\r\n\r\n\r\n\r\n### 关键点说明\r\n\r\n\r\n\r\n1. **常量定义**：使用 `#define MAXN 1000010` 来定义数组的最大长度。\r\n2. **比较函数**：在 `main` 函数之前定义 `cmp` 函数，以便在使用 `qsort` 时可以调用。\r\n3. **错误处理**：添加了换行符 `\\n` 在 \"Not Found\" 输出中，以确保输出格式正确。\r\n\r\n\r\n\r\n### 总结\r\n\r\n\r\n\r\n这个版本应该能够成功编译并正常工作。如果还有问题，请继续反馈！",
  "数据结构与算法/二分查找左侧边界算法总结.md": "# 二分查找左侧边界算法总结\r\n\r\n\r\n\r\n## 题目描述\r\n\r\n\r\n\r\n在一个有序不递减的数组中（可能包含重复元素），使用二分查找找到某个值 `x` 第一次出现的位置。如果该值不存在，则返回 -1。\r\n\r\n\r\n\r\n## 输入格式\r\n\r\n\r\n\r\n1. **第一行**：一个整数 `n`，表示数组元素个数（`n <= 10^5`）。\r\n2. **第二行**：`n` 个整数，代表数组元素（`1 <= 数组元素的值 <= 10^8`）。\r\n3. **第三行**：一个整数 `q`，表示查询的数个数（`q <= 10^5`）。\r\n4. **第四行**：`q` 个整数，代表要查找的值（`1 <= 要查找的数 <= 10^8`）。\r\n\r\n\r\n\r\n## 输出格式\r\n\r\n\r\n\r\n输出每个查询对应的第一次出现的位置，若不存在则输出 -1。\r\n\r\n\r\n\r\n## 算法思路\r\n\r\n\r\n\r\n1. **初始化**：\r\n   - 设置左右指针 `l` 和 `r`，分别指向数组的开始和结束。\r\n   - 初始化结果 `res` 为 -1。\r\n2. **二分查找**：\r\n   - 当`l`小于等于`r`时，执行以下步骤：\r\n     - 计算中间索引 `m`。\r\n     - 如果 `a[m]` 等于 `x`，更新 `res` 为 `m + 1`，并将 `r` 移动到 `m - 1` 继续向左查找。\r\n     - 如果 `a[m]` 小于 `x`，将 `l` 移动到 `m + 1`。\r\n     - 如果 `a[m]` 大于 `x`，将 `r` 移动到 `m - 1`。\r\n3. **输出结果**：\r\n   - 返回结果 `res`。\r\n\r\n\r\n\r\n## 时间复杂度\r\n\r\n\r\n\r\n- 每次查找的时间复杂度为 O(log n)，因此总时间复杂度为 O(q log n)。\r\n\r\n\r\n\r\n## 示例代码\r\n\r\n\r\n\r\n```c\r\nc#include <stdio.h>\r\n\r\nint findLB(int a[], int n, int x) {\r\n    int l = 0, r = n - 1, res = -1;\r\n\r\n    while (l <= r) {\r\n        int m = l + (r - l) / 2;\r\n\r\n        if (a[m] == x) {\r\n            res = m + 1;\r\n            r = m - 1;\r\n        } else if (a[m] < x) {\r\n            l = m + 1;\r\n        } else {\r\n            r = m - 1;\r\n        }\r\n    }\r\n\r\n    return res;\r\n}\r\n\r\nint main() {\r\n    int n, q;\r\n\r\n    scanf(\"%d\", &n);\r\n    int a[n];\r\n\r\n    for (int i = 0; i < n; i++) {\r\n        scanf(\"%d\", &a[i]);\r\n    }\r\n\r\n    scanf(\"%d\", &q);\r\n    int qry[q];\r\n\r\n    for (int i = 0; i < q; i++) {\r\n        scanf(\"%d\", &qry[i]);\r\n    }\r\n\r\n    for (int i = 0; i < q; i++) {\r\n        int pos = findLB(a, n, qry[i]);\r\n        printf(\"%d \", pos);\r\n    }\r\n    printf(\"\\n\");\r\n\r\n    return 0;\r\n}\r\nc\r\n```\r\n\r\n\r\n\r\n## 示例\r\n\r\n\r\n\r\n### 输入\r\n\r\n\r\n\r\n```\r\n6\r\n1 2 2 2 3 3\r\n3\r\n3 2 5\r\n```\r\n\r\n\r\n\r\n### 输出\r\n\r\n\r\n\r\n```\r\n5 2 -1 \r\n```\r\n\r\n\r\n\r\n## 总结\r\n\r\n\r\n\r\n该算法有效地使用二分查找来找到数组中元素的左侧边界，适合处理较大规模的输入数据。",
  "数据结构与算法/判断素数.md": "```c\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <string.h>\r\n#include <math.h>\r\n\r\n#define N 100005\r\n\r\nint prime[N];\r\nint c;\r\nbool isVisit[N];\r\n\r\nvoid tell(int n) {\r\n    for (int i = 2; i <= n; ++i) {\r\n        if (isVisit[i] == false)\r\n            prime[++c] = i;\r\n        for (int j = 1; j <= c && i * prime[j] <= n; ++j) {\r\n            isVisit[i * prime[j]] = true;\r\n            if (i % prime[j] == 0)\r\n                break;\r\n        }\r\n    }\r\n}\r\n\r\nint main(void) {\r\n    isVisit[0] = true;\r\n    isVisit[1] = true;\r\n    tell(N);\r\n    int n;\r\n    while (scanf(\"%d\", &n)!= EOF) {\r\n        if (!isVisit[n])\r\n            printf(\"Yes\\n\");\r\n        else\r\n            printf(\"No\\n\");\r\n    }\r\n    return 0;\r\n}\r\n```\r\n\r\n```c\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <string.h>\r\n\r\n#define N 1000007\r\n\r\nint vis[N], prime[N];\r\n\r\nvoid sieve(int n) {\r\n    int k = 0;\r\n    memset(vis, 0, sizeof(vis));\r\n    vis[0] = vis[1] = 1;\r\n    for (int i = 2; i <= n; i++) {\r\n        if (vis[i] == 0)\r\n            prime[k++] = i;\r\n        for (int j = 0; j < k; j++) {\r\n            if (i * prime[j] > n)\r\n                break;\r\n            vis[i * prime[j]] = 1;\r\n            if (i % prime[j] == 0)\r\n                break;\r\n        }\r\n    }\r\n}\r\n\r\nint main() {\r\n    sieve(N);\r\n    int n;\r\n    while (scanf(\"%d\", &n)!= EOF) {\r\n        if (vis[n] == 0)\r\n            printf(\"Yes\\n\");\r\n        else\r\n            printf(\"No\\n\");\r\n    }\r\n    return 0;\r\n}\r\n```\r\n\r\n```c\r\n#include <stdio.h>\r\n#include <stdbool.h>\r\n\r\n#define MAXN 100001\r\n\r\nbool is_prime[MAXN];\r\n\r\nvoid sieve() {\r\n    for (int i = 2; i < MAXN; i++) {\r\n        is_prime[i] = true; // 初始化所有数为素数\r\n    }\r\n    is_prime[0] = is_prime[1] = false; // 0和1不是素数\r\n\r\n    for (int i = 2; i * i < MAXN; i++) {\r\n        if (is_prime[i]) {\r\n            for (int j = i * i; j < MAXN; j += i) {\r\n                is_prime[j] = false; // 标记合数\r\n            }\r\n        }\r\n    }\r\n}//用空间换时间\r\n\r\nint main() {\r\n    sieve(); // 进行素数筛选\r\n\r\n    int n;\r\n    while (scanf(\"%d\", &n) != EOF) {\r\n        if (is_prime[n]) {\r\n            printf(\"Yes\\n\");\r\n        } else {\r\n            printf(\"No\\n\");\r\n        }\r\n    }\r\n\r\n    return 0;\r\n}\r\n\r\n```\r\n\r\n",
  "数据结构与算法/十大排序算法简介.md": "十大排序算法是计算机科学领域中常用的排序算法，根据其时间复杂度和实现方式大致可分为比较类排序和非比较类排序，以下为你详细介绍：\r\n\r\n### 比较类排序\r\n这类排序算法通过比较元素间的大小关系来确定元素的最终位置。\r\n1. **冒泡排序（Bubble Sort）**\r\n    - **原理**：重复遍历要排序的数列，一次比较两个元素，如果它们的顺序错误就把它们交换过来，直到整个数列都被排序好，就像气泡从水底逐渐升到水面一样。\r\n    - **时间复杂度**：$O(n^2)$ \r\n    - **空间复杂度**：$O(1)$\r\n    - **稳定性**：稳定 \r\n    - **适用场景**：数据量较小且基本有序的情况。\r\n2. **选择排序（Selection Sort）**\r\n    - **原理**：在未排序序列中找到最小（大）元素，存放到排序序列的起始位置，然后，再从剩余未排序元素中继续寻找最小（大）元素，然后放到已排序序列的末尾，以此类推，直到所有元素均排序完毕。\r\n    - **时间复杂度**：$O(n^2)$ \r\n    - **空间复杂度**：$O(1)$\r\n    - **稳定性**：不稳定\r\n    - **适用场景**：数据量较小且对稳定性要求不高的情况。\r\n3. **插入排序（Insertion Sort）**\r\n    - **原理**：将未排序数据插入到已排序序列的合适位置，就像玩扑克牌时整理手牌一样。\r\n    - **时间复杂度**：$O(n^2)$ \r\n    - **空间复杂度**：$O(1)$\r\n    - **稳定性**：稳定\r\n    - **适用场景**：数据量较小且基本有序的情况。\r\n4. **希尔排序（Shell Sort）**\r\n    - **原理**：它是插入排序的一种改进版本，也称为缩小增量排序。通过将原始数据分成多个子序列来改善插入排序的性能，先比较距离较远的元素，而不是像插入排序那样比较相邻元素。\r\n    - **时间复杂度**：与增量序列的选择有关，平均约为 $O(n^{1.3})$ \r\n    - **空间复杂度**：$O(1)$\r\n    - **稳定性**：不稳定\r\n    - **适用场景**：中等规模的数据排序。\r\n5. **归并排序（Merge Sort）**\r\n    - **原理**：采用分治法，将一个数组分成两个子数组，分别对这两个子数组进行排序，然后将排好序的子数组合并成一个最终的有序数组。\r\n    - **时间复杂度**：$O(n log n)$ \r\n    - **空间复杂度**：$O(n)$\r\n    - **稳定性**：稳定\r\n    - **适用场景**：数据量大且对稳定性有要求的情况。\r\n6. **快速排序（Quick Sort）**\r\n    - **原理**：同样采用分治法，选择一个基准值，将数组分为两部分，使得左边部分的元素都小于等于基准值，右边部分的元素都大于等于基准值，然后递归地对左右两部分进行排序。\r\n    - **时间复杂度**：平均 $O(n log n)$，最坏 $O(n^2)$ \r\n    - **空间复杂度**：平均 $O(log n)$，最坏 $O(n)$\r\n    - **稳定性**：不稳定\r\n    - **适用场景**：数据量大且分布较为随机的情况。\r\n7. **堆排序（Heap Sort）**\r\n    - **原理**：利用堆这种数据结构，通常是最大堆（每个节点的值都大于或等于其子节点的值）或最小堆，将待排序序列构造成一个堆，然后依次取出堆顶元素，调整堆结构，直到整个序列有序。\r\n    - **时间复杂度**：$O(n log n)$ \r\n    - **空间复杂度**：$O(1)$\r\n    - **稳定性**：不稳定\r\n    - **适用场景**：数据量大且对空间复杂度有要求的情况。\r\n\r\n### 非比较类排序\r\n这类排序算法不通过比较元素间的大小关系来确定元素的最终位置。\r\n8. **计数排序（Counting Sort）**\r\n    - **原理**：通过统计每个元素出现的次数，然后根据统计结果将元素依次输出。它要求输入的数据必须是有确定范围的整数。\r\n    - **时间复杂度**：$O(n + k)$，其中 $k$ 是数据范围。 \r\n    - **空间复杂度**：$O(k)$\r\n    - **稳定性**：稳定\r\n    - **适用场景**：数据范围较小且数据值为整数的情况。\r\n9. **桶排序（Bucket Sort）**\r\n    - **原理**：将数据分到有限数量的桶里，每个桶再分别进行排序（可以使用其他排序算法），最后将各个桶中的数据合并成一个有序序列。\r\n    - **时间复杂度**：平均 $O(n + k)$，其中 $k$ 是桶的数量。 \r\n    - **空间复杂度**：$O(n + k)$\r\n    - **稳定性**：取决于桶内排序算法\r\n    - **适用场景**：数据均匀分布在某个范围内的情况。\r\n10. **基数排序（Radix Sort）**\r\n    - **原理**：按照低位先排序，然后收集；再按照高位排序，然后再收集；依次类推，直到最高位。\r\n    - **时间复杂度**：$O(d(n + k))$，其中 $d$ 是最大数字的位数，$k$ 是基数（如十进制中 $k = 10$）。 \r\n    - **空间复杂度**：$O(n + k)$\r\n    - **稳定性**：稳定\r\n    - **适用场景**：数据位数固定且范围较大的整数排序。 ",
  "数据结构与算法/快速幂算法（一）.md": "要在C语言中实现快速幂算法，可以利用递归的方法或者迭代的方法来计算 *a**b*mod*c*。这里提供一个较为简单的实现，使用迭代的方法来避免栈溢出问题。\r\n\r\n\r\n\r\n以下是实现代码：\r\n\r\n\r\n\r\n```c\r\nc#include <stdio.h>\r\n\r\n// 快速幂函数\r\nlong long quick_pow(int a, int b, int c) {\r\n    long long result = 1;\r\n    long long base = a % c; // 对c取模，避免基数过大\r\n\r\n    while (b > 0) {\r\n        if (b % 2 == 1) { // 如果b是奇数\r\n            result = (result * base) % c;\r\n        }\r\n        base = (base * base) % c; // 基数平方\r\n        b /= 2; // b除以2\r\n    }\r\n\r\n    return result;\r\n}\r\n\r\nint main() {\r\n    int a, b, c;\r\n    \r\n    // 输入 a, b, c\r\n    while (scanf(\"%d %d %d\", &a, &b, &c) != EOF) {\r\n        printf(\"%lld\\n\", quick_pow(a, b, c));\r\n    }\r\n    \r\n    return 0;\r\n}\r\nc\r\n```\r\n\r\n\r\n\r\n### 代码解释\r\n\r\n\r\n\r\n- **quick_pow 函数**:\r\n  - 使用迭代的方法计算 *a**b*mod*c*。\r\n  - `base` 是 *a*mod*c* ，用于在计算时减少数值范围。\r\n  - 当 `b` 为奇数时，乘以当前的 `base` 并对 `c` 取模。\r\n  - 将 `base` 平方并更新为 `(base * base) % c`。\r\n  - `b` 每循环将除以2。\r\n- **main 函数**:\r\n  - 使用 `scanf` 读取输入三元组（*a*,*b*,*c*）。\r\n  - 使用 `printf` 输出结果。\r\n\r\n\r\n\r\n### 使用示例\r\n\r\n\r\n\r\n如果输入值为：\r\n\r\n\r\n\r\n```\r\n6 2 8\r\n```\r\n\r\n\r\n\r\n程序的输出将是：\r\n\r\n\r\n\r\n```\r\n4\r\n```\r\n\r\n\r\n\r\n### 注意事项\r\n\r\n\r\n\r\n- 输入的值需在限制范围内（1 < a, b, c < 2^30）。\r\n- 快速幂算法的时间复杂度为 *O*(log*b*)，适合大范围的指数计算。\r\n\r\n\r\n\r\n这个程序应可在1秒内快速处理多组数据。",
  "数据结构与算法/跳石头二分算法总结.md": "# 跳石头二分算法总结\r\n\r\n\r\n\r\n## 题目描述\r\n\r\n\r\n\r\n在给定的长度 `L` 和 `N` 个书的位置 `a` 中，要求在这些书的位置之间放置 `M` 个分隔符，使得每两个相邻分隔符之间的最小距离最大化。需要找出这个最大最小距离。\r\n\r\n\r\n\r\n## 输入格式\r\n\r\n\r\n\r\n1. 第一行：三个整数 `L`（长度）、`N`（书的数量）、`M`（分隔符的数量）。\r\n2. 第二行：`N` 个整数，表示书的位置。\r\n\r\n\r\n\r\n## 输出格式\r\n\r\n\r\n\r\n- 输出一个整数，表示最大化的最小距离。\r\n\r\n\r\n\r\n## 算法思路\r\n\r\n\r\n\r\n1. **初始化**：定义数组 `a` 存储书的位置，使用二分查找来确定最大最小距离。\r\n2. **检查函数 `check`**：判断在给定的最小距离 `x` 的情况下，能否放置 `M` 个分隔符。\r\n3. **二分查找**：在区间 `[0, L + 1]` 中进行二分查找，逐步逼近最大最小距离。\r\n\r\n\r\n\r\n## C语言实现\r\n\r\n\r\n\r\n以下是转换后的 C 语言代码：\r\n\r\n\r\n\r\n```c\r\nc#include <stdio.h>\r\n\r\nconst int N1 = 1e5 + 5;\r\nint L, N, M;\r\nint a[N1];\r\n\r\nint check(int x) {\r\n    int cnt = 0, now = 0;\r\n    for (int i = 1; i <= N; ++i) {\r\n        if (a[i] - now < x) {\r\n            cnt++;\r\n        } else {\r\n            now = a[i];\r\n        }\r\n    }\r\n    return cnt <= M;\r\n}\r\n\r\nint main() {\r\n    scanf(\"%d %d %d\", &L, &N, &M);\r\n    for (int i = 1; i <= N; ++i) {\r\n        scanf(\"%d\", &a[i]);\r\n    }\r\n    int l = 0, r = L + 1, mid;\r\n    while (l < r) {\r\n        mid = (l + r) >> 1;\r\n        if (check(mid)) {\r\n            l = mid + 1;\r\n        } else {\r\n            r = mid;\r\n        }\r\n    }\r\n    printf(\"%d\\n\", r - 1);\r\n    return 0;\r\n}\r\nc\r\n```\r\n\r\n\r\n\r\n## 逻辑解析\r\n\r\n\r\n\r\n- **数组声明**：`int a[N1];` 用于存储书籍位置。\r\n- **检查函数**：`check(int x)` 用于判断当前最小距离 `x` 是否可行，计算需要的分隔符数量。\r\n- **二分查找**：\r\n  - 初始化左右边界 `l` 和 `r`。\r\n  - 通过 `mid` 值来逐步查找最大最小距离，更新边界 `l` 或 `r` 以收敛到解。\r\n- **结果输出**：最终输出最大最小距离 `r - 1`。\r\n\r\n\r\n\r\n## 总结\r\n\r\n\r\n\r\n该算法通过二分查找高效地确定在给定条件下的最大最小距离，适合大规模数据的处理，时间复杂度为 `O(N log L)`。",
  "数据结构与算法/递增序列查询算法总结.md": "# 递增序列查询算法总结\r\n\r\n\r\n\r\n## 题目描述\r\n\r\n\r\n\r\n给定一个递增的正整数序列，针对不同的查询输出对应结果。查询类型包括查找最大下标、最小下标、数字范围计数、比某个数大的最小数字、比某个数小的最大数字等。\r\n\r\n\r\n\r\n## 输入格式\r\n\r\n\r\n\r\n1. 第一行：一个整数 `n`，代表序列的长度（下标从0开始到 `n-1`）。\r\n2. 第二行：`n` 个整数，代表序列对应位置上的数。\r\n3. 第三行：一个整数 `m`，代表查询次数。\r\n4. 接下来的`m`行，每行是以下五种类型之一：\r\n   - `0 x`：查询数字 `x` 出现的最大下标，若不存在则输出 -1。\r\n   - `1 x`：查询数字 `x` 出现的最小下标，若不存在则输出 -1。\r\n   - `2 x y`：查询大于等于 `x` 且小于等于 `y` 的数字的个数（保证 `x <= y`）。\r\n   - `3 x`：查询比 `x` 大且下标最小的数字的大小，若不存在则输出 -1。\r\n   - `4 x`：查询比 `x` 小且下标最大的数字的大小，若不存在则输出 -1。\r\n\r\n\r\n\r\n## 输出格式\r\n\r\n\r\n\r\n输出每个查询的结果，每个结果占一行。\r\n\r\n\r\n\r\n## 算法思路\r\n\r\n\r\n\r\n1. **初始化**：读取输入的序列和查询数。\r\n2. **二分查找**：\r\n   - **类型 0**：使用二分查找找到 `x` 的最大下标。\r\n   - **类型 1**：使用二分查找找到 `x` 的最小下标。\r\n   - **类型 2**：使用二分查找找到 `x` 和 `y` 的范围，计算范围内的元素个数。\r\n   - **类型 3**：使用二分查找找到第一个比 `x` 大的元素。\r\n   - **类型 4**：使用二分查找找到最后一个比 `x` 小的元素。\r\n3. **输出结果**：将所有查询结果依次输出。\r\n\r\n\r\n\r\n## 示例代码\r\n\r\n\r\n\r\n```c\r\nc#include <stdio.h>\r\n\r\nint findMaxIndex(int a[], int n, int x) {\r\n    int l = 0, r = n - 1, res = -1;\r\n    while (l <= r) {\r\n        int m = l + (r - l) / 2;\r\n        if (a[m] == x) {\r\n            res = m; \r\n            l = m + 1; \r\n        } else if (a[m] < x) {\r\n            l = m + 1; \r\n        } else {\r\n            r = m - 1; \r\n        }\r\n    }\r\n    return res;\r\n}\r\n\r\nint findMinIndex(int a[], int n, int x) {\r\n    int l = 0, r = n - 1, res = -1;\r\n    while (l <= r) {\r\n        int m = l + (r - l) / 2;\r\n        if (a[m] == x) {\r\n            res = m; \r\n            r = m - 1; \r\n        } else if (a[m] < x) {\r\n            l = m + 1; \r\n        } else {\r\n            r = m - 1; \r\n        }\r\n    }\r\n    return res;\r\n}\r\n\r\nint countInRange(int a[], int n, int x, int y) {\r\n    int leftIndex = findMinIndex(a, n, x);\r\n    int rightIndex = findMaxIndex(a, n, y);\r\n    if (leftIndex == -1 || rightIndex == -1) return 0;\r\n    return rightIndex - leftIndex + 1;\r\n}\r\n\r\nint findFirstGreater(int a[], int n, int x) {\r\n    int l = 0, r = n - 1, res = -1;\r\n    while (l <= r) {\r\n        int m = l + (r - l) / 2;\r\n        if (a[m] > x) {\r\n            res = a[m]; \r\n            r = m - 1; \r\n        } else {\r\n            l = m + 1; \r\n        }\r\n    }\r\n    return res;\r\n}\r\n\r\nint findLastSmaller(int a[], int n, int x) {\r\n    int l = 0, r = n - 1, res = -1;\r\n    while (l <= r) {\r\n        int m = l + (r - l) / 2;\r\n        if (a[m] < x) {\r\n            res = a[m]; \r\n            l = m + 1; \r\n        } else {\r\n            r = m - 1; \r\n        }\r\n    }\r\n    return res;\r\n}\r\n\r\nint main() {\r\n    int n, m;\r\n    scanf(\"%d\", &n);\r\n    int a[n];\r\n\r\n    for (int i = 0; i < n; i++) {\r\n        scanf(\"%d\", &a[i]);\r\n    }\r\n\r\n    scanf(\"%d\", &m);\r\n    for (int i = 0; i < m; i++) {\r\n        int type, x, y;\r\n        scanf(\"%d\", &type);\r\n        if (type == 0) {\r\n            scanf(\"%d\", &x);\r\n            printf(\"%d\\n\", findMaxIndex(a, n, x));\r\n        } else if (type == 1) {\r\n            scanf(\"%d\", &x);\r\n            printf(\"%d\\n\", findMinIndex(a, n, x));\r\n        } else if (type == 2) {\r\n            scanf(\"%d %d\", &x, &y);\r\n            printf(\"%d\\n\", countInRange(a, n, x, y));\r\n        } else if (type == 3) {\r\n            scanf(\"%d\", &x);\r\n            printf(\"%d\\n\", findFirstGreater(a, n, x));\r\n        } else if (type == 4) {\r\n            scanf(\"%d\", &x);\r\n            printf(\"%d\\n\", findLastSmaller(a, n, x));\r\n        }\r\n    }\r\n\r\n    return 0;\r\n}\r\nc\r\n```\r\n\r\n\r\n\r\n## 示例\r\n\r\n\r\n\r\n### 输入\r\n\r\n\r\n\r\n```\r\n10\r\n1 1 1 3 4 5 5 5 5 8\r\n5\r\n0 5\r\n1 5\r\n2 1 5\r\n3 4\r\n4 8\r\n```\r\n\r\n\r\n\r\n### 输出\r\n\r\n\r\n\r\n```\r\n8\r\n5\r\n9\r\n5\r\n5\r\n```\r\n\r\n\r\n\r\n## 总结\r\n\r\n\r\n\r\n该算法使用二分查找处理多种查询类型，适合处理较大规模的输入数据，能够高效地返回查询结果。",
  "杂项/10月23日大学英语笔记.md": "以下是你提到的英语词汇及其翻译和音标。我已经为其添加了音标，并将其排版成HTML和CSS格式。\r\n\r\n\r\n\r\n### 英语词汇及翻译\r\n\r\n\r\n\r\n| 英文词汇                                          | 翻译                     | 音标                                               |\r\n| :------------------------------------------------ | :----------------------- | :------------------------------------------------- |\r\n| hands                                             | 手                       | /hændz/                                            |\r\n| butterflies in the stomach                        | 肚子里的蝴蝶             | /ˈbʌtərflaɪz ɪn ðə ˈstʌmək/                        |\r\n| muscle tension                                    | 肌肉紧张                 | /ˈmʌsl ˈtɛnʃən/                                    |\r\n| credit                                            | 学分 / 信用              | /ˈkrɛdɪt/                                          |\r\n| major                                             | 主修 / 专业              | /ˈmeɪdʒər/                                         |\r\n| major in                                          | 主修                     | /ˈmeɪdʒər ɪn/                                      |\r\n| dropout                                           | 辍学                     | /ˈdrɔpˌaʊt/                                        |\r\n| trigger                                           | 诱因 / 扳机              | /ˈtrɪɡər/                                          |\r\n| resilience                                        | 弹性                     | /rɪˈzɪljəns/                                       |\r\n| cyberlove                                         | 网恋                     | /ˈsaɪbərləv/                                       |\r\n| long-distance relationship                        | 异地恋                   | /lɔŋ ˈdɪstəns rɪˌleɪʃənˈʃɪp/                       |\r\n| date                                              | 日期 / 约会              | /deɪt/                                             |\r\n| lovesick                                          | 恋爱中的病               | /ˈlʌvˌsɪk/                                         |\r\n| zodiac                                            | 星座                     | /ˈzoʊ.dɪ.æk/                                       |\r\n| aquaman                                           | 水行侠                   | /ˈækwəˌmæn/                                        |\r\n| aquarium                                          | 水族馆                   | /əˈkwɛərɪəm/                                       |\r\n| pilgrim                                           | 朝圣者                   | /ˈpɪlɡrɪm/                                         |\r\n| soul                                              | 灵魂                     | /soʊl/                                             |\r\n| bar                                               | 酒吧                     | /bɑr/                                              |\r\n| soap bar                                          | 香皂                     | /soʊp bɑr/                                         |\r\n| behind the bars                                   | 在监狱里                 | /bɪˈhaɪnd ðə bɑrz/                                 |\r\n| enjoy each other's company                        | 享受彼此的陪伴           | /ɪnˈdʒɔɪ iʧ ˈʌðərz ˈkʌmpəni/                       |\r\n| crush                                             | 暗恋                     | /krʌʃ/                                             |\r\n| have a crush on                                   | 对某人有好感             | /hæv ə krʌʃ ɑn/                                    |\r\n| idol                                              | 偶像                     | /ˈaɪdəl/                                           |\r\n| icon                                              | 图标 / 偶像              | /ˈaɪˌkɒn/                                          |\r\n| ideal                                             | 理想                     | /aɪˈdɪəl/                                          |\r\n| idea                                              | 主意                     | /aɪˈdɪə/                                           |\r\n| idiot                                             | 傻瓜                     | /ˈɪdiət/                                           |\r\n| marketing campaign                                | 营销活动                 | /ˈmɑrkɪtɪŋ kæmˈpeɪn/                               |\r\n| being in love implies that you can fall out of it | 恋爱意味着你可能会失去爱 | /ˈbiːɪŋ ɪn lʌv ɪmˈplaɪz ðæt juː kæn fɔl aʊt ʌv ɪt/ |\r\n| -wise                                             | 方面的                   | /waɪz/                                             |\r\n| family-wise                                       | 从家庭的角度             | /ˈfæmɪli waɪz/                                     |\r\n| better off                                        | 过得更好                 | /ˈbɛtər ɔf/                                        |\r\n| big old kiss                                      | 大大的吻                 | /bɪɡ oʊld kɪs/                                     |\r\n| vulnerable                                        | 脆弱的                   | /ˈvʌlnərəbəl/                                      |\r\n\r\n\r\n\r\n### HTML/CSS 排版美化\r\n\r\n\r\n\r\n```html\r\nhtml<!DOCTYPE html>\r\n<html lang=\"zh\">\r\n<head>\r\n    <meta charset=\"UTF-8\">\r\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n    <title>英语词汇及翻译</title>\r\n    <style>\r\n        body {\r\n            font-family: Arial, sans-serif;\r\n            background-color: #f8f9fa;\r\n            margin: 0;\r\n            padding: 20px;\r\n        }\r\n        h1 {\r\n            text-align: center;\r\n            color: #333;\r\n        }\r\n        table {\r\n            width: 100%;\r\n            border-collapse: collapse;\r\n            margin: 20px 0;\r\n        }\r\n        th, td {\r\n            border: 1px solid #ddd;\r\n            padding: 8px;\r\n            text-align: left;\r\n        }\r\n        th {\r\n            background-color: #007BFF;\r\n            color: white;\r\n        }\r\n        tr:nth-child(even) {\r\n            background-color: #f2f2f2;\r\n        }\r\n        tr:hover {\r\n            background-color: #ddd;\r\n        }\r\n    </style>\r\n</head>\r\n<body>\r\n    <h1>英语词汇及翻译</h1>\r\n    <table>\r\n        <tr>\r\n            <th>英文词汇</th>\r\n            <th>翻译</th>\r\n            <th>音标</th>\r\n        </tr>\r\n        <tr>\r\n            <td>hands</td>\r\n            <td>手</td>\r\n            <td>/hændz/</td>\r\n        </tr>\r\n        <tr>\r\n            <td>butterflies in the stomach</td>\r\n            <td>肚子里的蝴蝶</td>\r\n            <td>/ˈbʌtərflaɪz ɪn ðə ˈstʌmək/</td>\r\n        </tr>\r\n        <tr>\r\n            <td>muscle tension</td>\r\n            <td>肌肉紧张</td>\r\n            <td>/ˈmʌsl ˈtɛnʃən/</td>\r\n        </tr>\r\n        <!-- 可以继续添加其他词汇 -->\r\n    </table>\r\n</body>\r\n</html>\r\nhtml\r\n```\r\n\r\n\r\n\r\n你可以将上述HTML代码复制到文本编辑器中，然后另存为`.html`文件，以在浏览器中打开并查看效果。如果有其他需求或需要进一步的帮助，请告知我！",
  "杂项/c++如何快速的检测一个字串符在另一个字串符的出现次数.md": "```c++\r\n#include <iostream>\r\n#include <string>\r\nusing namespace std;\r\n\r\nint countSubstrings(const string& str, const string& sub) {\r\n    int count = 0;\r\n    size_t pos = 0;\r\n\r\n    // 循环直到找不到子字符串\r\n    while ((pos = str.find(sub, pos)) != string::npos) {\r\n        count++;  // 找到一个子字符串，计数器加1\r\n        pos += sub.length();  // 更新位置，跳过已找到的子字符串\r\n    }\r\n\r\n    return count;\r\n}\r\n\r\nint main() {\r\n    string str = \"ababcabcabcab\";\r\n    string sub = \"abc\";\r\n    \r\n    int result = countSubstrings(str, sub);\r\n    cout << \"子字符串 \\\"\" << sub << \"\\\" 在字符串 \\\"\" << str << \"\\\" 中出现的次数是: \" << result << endl;\r\n\r\n    return 0;\r\n}\r\n\r\n```\r\n\r\n### TMD一生之耻！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！",
  "杂项/Markdown格式大全.md": "# MarkDown书写规范\n\n写文档好帮手，轻量级标记语言 Markdown\n\n# 概述\n\n## 起源\n\nMarkdown是[Daring Fireball](http://daringfireball.net/projects/markdown/syntax)的作者John Gruber发明，身为Blogger，可能他也觉得传统的HTML有些复杂吧，退一步来讲，若是一个毫无计算机基础的Blogger，根本也没必要去掌握那些复杂的标签语言知识。\n\n## 宗旨\n\nMarkdown 的目标是实现「易读易写」，成为一种适用于网络的书写语言。\n\n可读性，无论如何，都是最重要的。一份使用 Markdown 格式撰写的文件应该可以直接以纯文本发布，并且看起来不会像是由许多标签或是格式指令所构成。Markdown 语法受到一些既有 text-to-HTML 格式的影响，包括 Setext、atx、Textile、reStructuredText、Grutatext 和 EtText，而最大灵感来源其实是纯文本电子邮件的格式。\n\n总之， Markdown 的语法全由一些符号所组成，这些符号经过精挑细选，其作用一目了然。比如：在文字两旁加上星号，看起来就像*强调*。Markdown 的列表看起来，嗯，就是列表。Markdown 的区块引用看起来就真的像是引用一段文字，就像你曾在电子邮件中见过的那样。\n\n\n# 全局规范\n\nMarkDown 文件均使用```.md```作为后缀 *(小写字母)*\n\n普通文本换行，使用行末尾```2空格```触发\n\n\n## 发展\n\n越来越多的软件和服务支持Markdown语法，应该说，Mac上大多数的写作软件都支持它。在线工具同样有很多，如果你的博客基于Wordpress或是blogger，它同样支持发布。\n\n不仅仅是写博客，一切文章都可以用Markdown语法来写，比如说你想将一个标题加大字体，只需要在相应文字前面加上一个#或是在它的下一行加上一些等号即可，还有比这更简单的调整格式方式吗？\n\n\n# 语法参见\n\n[官方语法说明](http://daringfireball.net/projects/markdown/syntax)\n\n# 示例\n\n---\n\n## 标题\n\n# 一级标题\n\n## 二级标题\n\n### 三级标题\n\n#### 四级标题\n\n##### 五级标题\n\n###### 六级标题\n\n## 强调\n\n- **粗体**\n\n- _斜体_\n\n## 引用\n\n上面的横线用三个-表示\n\n> 区块引用\n\n## 列表\n\n* red\n* green\n* blue\n\n+ red\n+ green\n+ blue\n\n- red\n- green\n- blue\n\n\n1. red\n2. green\n3. blue\n\n\n* 一个列表包含一个区块\n> 区块内容\n> 更多内容\n\n## 代码\n\n代码的插入方式 `printf('\\n');`\n\n```\nfunction method()\n{\n    alert(\"javascript\");\n}\n```\n\n```\nclass Test{\n    public static void main(String argc[]){\n        System.out.println(\"java\");\n    }\n}\n```\n\n```\nclass Test{\n    public static void main()\n    {\n        Console.WriteLine(\"C#\");\n    }\n}\n```\n\n## 链接\n\n行内连接 [GitHub](https://github.com/) 的链接\n\n## 图片\n\n![shiyanlou logo](https://static.shiyanlou.com/img/logo_03.png)\n",
  "杂项/markdown格式（没什么用）.md": "https://storage.googleapis.com/docscloudstorage/2022.3/UnityDocumentation.zip\r\n\r\nChatGPT响应: Markdown中的一些常用标识符包括：\r\n\r\n1. **标题**：使用`#`表示不同级别的标题\r\n   ```markdown\r\n   # 一级标题\r\n   ## 二级标题\r\n   ### 三级标题\r\n   ```\r\n\r\n2. **粗体**：使用`**`或`__`包围文本\r\n   ```markdown\r\n   **粗体文本** 或 __粗体文本__\r\n   ```\r\n\r\n3. **斜体**：使用`*`或`_`包围文本\r\n   ```markdown\r\n   *斜体文本* 或 _斜体文本_\r\n   ```\r\n\r\n4. **无序列表**：使用`-`、`*`或`+`\r\n   ```markdown\r\n   - 项目1\r\n   * 项目2\r\n   + 项目3\r\n   ```\r\n\r\n5. **有序列表**：使用数字加点\r\n   ```markdown\r\n   1. 第一项\r\n   2. 第二项\r\n   ```\r\n\r\n6. **链接**：使用`[链接文本](URL)`\r\n   ```markdown\r\n   [这是一个链接](https://example.com)\r\n   ```\r\n\r\n7. **图片**：使用`![图片描述](图片URL)`\r\n   ```markdown\r\n   ![示例图片](https://example.com/image.png)\r\n   ```\r\n\r\n8. **代码块**：使用反引号`` ` ``\r\n   ```markdown\r\n   `行内代码`\r\n   ```\r\n\r\n   或使用三个反引号表示多行代码\r\n   ```markdown\r\n   ```\r\n   多行代码\r\n   ```\r\n   ```\r\n\r\n9. **引用**：使用`>`\r\n   ```markdown\r\n   > 这是一个引用\r\n   ```\r\n\r\n10. **水平线**：使用三个或以上的`-`、`*`或`_`\r\n   ```markdown\r\n   ---\r\n   ```\r\n\r\n",
  "杂项/PTA万能代码.md": "```c++\r\n#include <iostream>\r\n#include <random>\r\n#include <chrono>\r\n#include <bits/stdc++.h>\r\n\r\nusing namespace std;\r\n\r\nint main() {\r\n    // 使用当前时间的时间戳作为种子\r\n    unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();\r\n    \r\n    // 创建一个基于该种子的随机数生成器\r\n    std::default_random_engine generator(seed);\r\n    \r\n    // 创建一个均匀分布的随机数生成器（在 1 到 100 之间）\r\n    std::uniform_int_distribution<int> distribution(0, 10);\r\n    \r\n\t//这里填写你需要输入的 \r\n    string str1,str2;\r\n    cin>>str1>>str2;\r\n    \r\n\t// 生成并打印随机数\r\n    std::cout <<distribution(generator) << std::endl;\r\n\r\n    return 0;\r\n}\r\n```\r\n\r\n### 这个是PTA输出值万能代码，只需要你不断地试错，有概率全对\r\n",
  "杂项/PTA好题-英文单词排序.md": "**7-4 英文单词排序**\r\n\r\n分数 25\r\n\r\n作者 张泳\r\n\r\n单位 浙大城市学院\r\n\r\n本题要求编写程序，输入若干英文单词，对这些单词按长度从小到大排序后输出。如果长度相同，按照输入的顺序不变。\r\n\r\n### 输入格式：\r\n\r\n输入为若干英文单词，每行一个，以`#`作为输入结束标志。其中英文单词总数不超过20个，英文单词为长度小于10的仅由小写英文字母组成的字符串。\r\n\r\n### 输出格式：\r\n\r\n输出为排序后的结果，每个单词后面都额外输出一个空格。\r\n\r\n### 输入样例：\r\n\r\n```in\r\nblue\r\nred\r\nyellow\r\ngreen\r\npurple\r\n#\r\n```\r\n\r\n### 输出样例：\r\n\r\n```out\r\nred blue green yellow purple \r\n```\r\n\r\n代码长度限制\r\n\r\n16 KB\r\n\r\n时间限制\r\n\r\n400 ms\r\n\r\n内存限制\r\n\r\n64 MB\r\n\r\n栈限制\r\n\r\n8192 KB\r\n\r\n\r\n\r\n```c\r\n#include <stdio.h>\r\n#include <string.h>\r\n\r\ntypedef struct {\r\n    char word[10 + 1];  \r\n    int index; \r\n} Word;\r\n\r\nint main() {\r\n    Word words[20];\r\n    int count = 0; //单词数量\r\n    \r\n\r\n    while (1) {\r\n        char word[10 + 1];\r\n        fgets(word, sizeof(word), stdin);\r\n        \r\n\r\n        if (word[0] == '#') {\r\n            break;\r\n        }\r\n\r\n\r\n        word[strcspn(word, \"\\n\")] = '\\0';\r\n\r\n\r\n        strcpy(words[count].word, word);\r\n        words[count].index = count;\r\n        count++;\r\n    }\r\n\r\n    //标准冒泡排序\r\n    for (int i = 0; i < count - 1; i++) {\r\n        for (int j = 0; j < count-1-i; j++) {\r\n            if (strlen(words[j].word) > strlen(words[j+1].word)) {\r\n                // 交换单词\r\n                Word temp = words[j];\r\n                words[j] = words[j+1];\r\n                words[j+1] = temp;\r\n            }\r\n        }\r\n    }\r\n\r\n    for (int i = 0; i < count; i++) {\r\n        printf(\"%s \", words[i].word);\r\n    }\r\n    printf(\"\\n\");\r\n\r\n    return 0;\r\n}\r\n\r\n```\r\n\r\n",
  "杂项/PTA好题-计算众数.md": "**7-6 求整数序列中出现次数最多的数**\r\n\r\n分数 20\r\n\r\n作者 张彤彧\r\n\r\n单位 浙江大学\r\n\r\n本题要求统计一个整型序列中出现次数最多的整数及其出现次数。\r\n\r\n### 输入格式：\r\n\r\n输入在一行中给出序列中整数个数N（0<N≤1000），以及N个整数。数字间以空格分隔。\r\n\r\n### 输出格式：\r\n\r\n在一行中输出出现次数最多的整数及其出现次数，数字间以空格分隔。题目保证这样的数字是唯一的。\r\n\r\n### 输入样例：\r\n\r\n```in\r\n10 3 2 -1 5 3 4 3 0 3 2\r\n```\r\n\r\n### 输出样例：\r\n\r\n```out\r\n3 4\r\n```\r\n\r\n代码长度限制\r\n\r\n16 KB\r\n\r\n时间限制\r\n\r\n400 ms\r\n\r\n内存限制\r\n\r\n64 MB\r\n\r\n栈限制\r\n\r\n8192 KB\r\n\r\n```c\r\n#include <stdio.h>\r\n\r\nint main() {\r\n    int N;\r\n    scanf(\"%d\", &N);\r\n    int arr[N];\r\n    for(int i = 0; i < N; i++) {\r\n        scanf(\"%d\", &arr[i]);\r\n    }\r\n\r\n    int max_count = 0;\r\n    int most_freq_num = arr[0];\r\n    for(int i = 0; i < N; i++) {\r\n        int count = 1;\r\n        for(int j = i+1; j < N; j++) {\r\n            if(arr[j] == arr[i]) {\r\n                count++;\r\n            }\r\n        }\r\n        if(count > max_count) {\r\n            max_count = count;\r\n            most_freq_num = arr[i];\r\n        }\r\n    }\r\n\r\n    printf(\"%d %d\", most_freq_num, max_count);\r\n    return 0;\r\n}\r\n\r\n```\r\n\r\n",
  "杂项/古诗.md": "知我者，谓我心忧；不知我者，谓我何求\n路漫漫其修远兮，吾将上下而求索\n夕阳西下，断肠人在天涯\n兴，百姓苦；亡，百姓苦\n封侯非我意，但愿海波平\n我自横刀向天笑，去留肝胆两昆仑\n海上生明月，天涯共此时\n红豆生南国，春来发几枝。愿君多采撷，此物最相思\n气蒸云梦泽，波撼岳阳城\n黄沙百战穿金甲，不破楼兰终不还\n天生我材必有用，千金散尽还复来\n长风破浪会有时，直挂云帆济沧海\n安能摧眉折腰事权贵，使我不得开心颜\n会当凌绝顶，一览众山小\n国破山河在，城春草木深。感时花溅泪，恨别鸟惊心\n烽火连三月，家书抵万金\n日出江花红胜火，春来江水绿如蓝。能不忆江南\n同是天涯沦落人，相逢何必曾相识\n春蚕到死丝方尽，蜡炬成灰泪始干\n身无彩凤双飞翼，心有灵犀一点通\n山有木兮木有枝，心悦君兮君不知\n生年不满百，常怀千岁忧\n人生如逆旅，我亦是行人\n桃李春风一杯酒，江湖夜雨十年灯\n劝君莫惜金缕衣，劝君惜取少年时\n\n\n但愿人长久，千里共婵娟\n抽刀断水水更流，举杯消愁愁更愁\n孤帆远影碧空尽，唯见长江天际流\n两岸猿声啼不住，轻舟已过万重山\n疏影横斜水清浅，暗香浮动月黄昏\n晚来天欲雪，能饮一杯无\n山重水复疑无路，柳暗花明又一村\n旧时王谢堂前燕，飞入寻常百姓家\n葡萄美酒夜光杯，欲饮琵琶马上催\n两岸青山相对出，孤帆一片日边来\n落霞与孤鹜齐飞，秋水共长天一色\n杨柳青青江水平，闻郎江上踏歌声\n近乡情更怯，不敢问来人\n洛阳亲友如相问，一片冰心在玉壶\n莫愁前路无知己，天下谁人不识君\n七八个星天外，两三点雨山前\n一年好景君须记，最是橙黄橘绿时\n今夜月明人尽望，不知秋思落谁家\n劝君更尽一杯酒，西出阳关无故人\n云想衣裳花想容，春风拂槛露华浓\n此情可待成追忆，只是当时已惘然\n问君能有几多愁，恰似一江春水向东流\n小荷才露尖尖角，早有蜻蜓立上头\n两个黄鹂鸣翠柳，一行白鹭上青天\n两岸荔枝红，万家烟雨中\n独在异乡为异客，每逢佳节倍思亲\n无边落木萧萧下，不尽长江滚滚来\n千山鸟飞绝，万径人踪灭\n相见时难别亦难，东风无力百花残\n人间四月芳菲尽，山寺桃花始盛开\n春风得意马蹄疾，一日看尽长安花\n竹杖芒鞋轻胜马，谁怕？一蓑烟雨任平生\n我花开后百花杀，秋草萋萋鹦鹉洲",
  "杂项/带图片.md": "# 春日限定：\n赴一场自然与生机的约会 春回大地时，万物挣脱冬日的沉寂，以最鲜活的姿态铺满视野。无论是枝头抽芽的新绿、田间绽放的繁花，还是拂面而来的暖风，都在诉说着季节的温柔絮语。 \n--- \n## 一、春日限定的自然画卷 春日的美，藏在每一处细腻的景致里。清晨的林间，露珠挂在嫩绿的叶片上，折射着柔和的晨光；午后的花海，各色花朵竞相开放，蝴蝶在花丛中翩跹起舞；傍晚的河畔，夕阳为水面镀上金边，归鸟的鸣啼伴着流水声，构成一幅宁静而治愈的画面。 ![春日林间晨景](https://picsum.photos/id/15/800/450) *图注：清晨的林间，露珠与新绿交织出春日的清新气息* --- ## 二、解锁春日的正确打开方式 1. 踏青寻芳：走进公园、郊外或山林，沉浸式感受草木生长的力量，呼吸带着花香的新鲜空气。 2. 野餐小聚：约上好友，带着美食与餐布，在草坪上享受阳光与陪伴，记录惬意时光。 3. 绿植养护：在家中摆放几盆绿植或鲜花，让春日的生机延伸到室内，点缀日常空间。 ![草坪野餐时光](https://picsum.photos/id/26/800/450) *图注：在洒满阳光的草坪上，与好友共度轻松惬意的野餐时刻* --- ## 三、春日里的生活感悟 春天是充满希望的季节，它教会我们接纳变化、拥抱新生。就像树木在经历寒冬后重新发芽，生活也会在坚持与等待中迎来转机。不妨趁着春日正好，放慢脚步，感受身边的美好，为自己注入前行的力量。 --- 要不要我帮你生成**不同主题（如旅行、美食、读书）的带图片Markdown文章模板**？你只需告诉我具体主题，我就能快速适配内容和图片搭配。",
  "杂项/文本颜色测试.md": "<font face=\"逐浪圆体\">我是逐浪圆体</font>\r\n<font face=\"逐浪花体\">我是逐浪花体</font>\r\n<font face=\"逐浪像素字\">我是逐浪像素字</font>\r\n<font face=\"逐浪立楷\">我是逐浪立楷</font>\r\n<font color=red>我是红色</font>\r\n<font color=#008000>我是绿色</font>\r\n<font color=yellow>我是黄色</font>\r\n<font color=Blue>我是蓝色</font>\r\n<font color= #871F78>我是紫色</font>\r\n<font color= #DCDCDC>我是浅灰色</font>\r\n<font size=5>我是尺寸</font>\r\n<font size=10>我是尺寸</font>\r\n<font face=\"逐浪立楷\" color=green size=10>我是逐浪立楷，绿色，尺寸为5</font>\r\n\r\n<table><tr><td bgcolor=green>背景色yellow</td></tr></table>\r\n\r\n\r\n水果名称| 价格 |  数量  \r\n-|-|-\r\n香蕉 | $1 | 5 |\r\n苹果 | $1 | 6 |\r\n草莓 | $1 | 7 |\r\n\r\nname | 111 | 222 | 333 | 444\r\n- | :-: | :-: | :-: | -:\r\naaa | bbb | ccc | ddd | eee| \r\nfff | ggg| hhh | iii | 000|\r\n\r\nname | 111 | 222 | 333 | 444\r\n:-- | :-- | :-- | :-- | :--\r\naaa | bbb | ccc | ddd | eee\r\nfff | ggg| hhh | iii | 000\r\n\r\n颜色名 | 十六进制颜色值 |  rgb颜色  \r\n-|-|-\r\n黑色（black) | 000000 | \trgb(0, 0, 0) |\r\n蓝色（blue） | 0000FF | rgb(0, 0, 255) |\r\n灰色（grey） | 808080 | rgb(128, 128, 128) |\r\n绿色（green） | 008000 | rgb(0, 128, 0) |\r\n橙色（orange） | FFA500 | rgb(255, 165, 0) |\r\n红色(red) | FF0000 | rgb(255, 0, 0) |\r\n黄色（yellow） | FFFF00 | rgb(255, 255, 0) |",
  "杂项/计算机刷题网站.md": "#### 计算机刷题网站\r\n\r\n1. 洛谷  https://www.luogu.com.cn/\r\n2. 牛客网 https://www.nowcoder.com/\r\n3. leetcode https://leetcode.cn/\r\n4. acm实验室 http://acm.mangata.ltd/\r\n5. PTA https://pintia.cn/home",
  "正则表达式/简单举例.md": "\n\n---\n\n#### 1️⃣ 提取日志中的IP地址 🌐\n\n**场景**：从服务器日志(Nginx, Apache等)或系统日志中提取客户端的IP地址。\n\n*  **表达式**：`\\b(?:[0-9]{1,3}\\.){3}[0-9]{1,3}\\b`\n*   **分解说明**：\n    *   `\\b`：单词边界，确保IP地址是独立的\n    *   `(?: ... ){3}`：一个**非捕获分组**，重复3次\n    *   `[0-9]{1,3}`：1到3位数字（IP的每一段）\n    *   `\\.`：一个 literal 的点号\n*   **测试文本**：\n    ```\n    192.168.1.1 - - [05/Jan/2023:10:20:30] \"GET /api/user HTTP/1.1\"\n    ERROR 10.0.0.45 Database connection failed\n    ```\n*   **匹配结果**：\n    *   `192.168.1.1`\n    *   `10.0.0.45`\n*   💡 **进阶**：更严格的IP校验正则复杂得多，但这个版本在日志分析中**足够好用**。\n\n---\n\n#### 2️⃣ 验证强密码强度 🔒\n\n**场景**：注册时要求密码必须包含大小写字母、数字和特殊字符，且长度至少8位。\n\n*   **表达式**：`^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$`\n*   **分解说明**（使用了**前瞻断言**）：\n    *   `^`：字符串开始\n    *   `(?=.*[a-z])`：**断言**后面必须至少有一个小写字母\n    *   `(?=.*[A-Z])`：**断言**后面必须至少有一个大写字母\n    *   `(?=.*\\d)`：**断言**后面必须至少有一个数字\n    *   `(?=.*[@$!%*?&])`：**断言**后面必须至少有一个特殊字符\n    *   `[A-Za-z\\d@$!%*?&]{8,}`：匹配由这些字符组成，且长度至少为8的字符串\n    *   `$`：字符串结尾\n*   **测试**：\n    *   `Password123!` ✅\n    *   `weak` ❌\n    *   `NoSpecialChar123` ❌\n*   🛡️ **价值**：前端或后端验证密码规则，无需写一堆 `if-else`。\n\n---\n\n#### 3️⃣ 解析和提取URL组件 🔗\n\n**场景**：从一段文本中提取所有URL的协议、域名和路径。\n\n*   **表达式**：`(https?):\\/\\/([^\\/\\s]+)(\\/[^\\s?]*)?(\\?[^\\s#]*)?`\n*   **分解说明**（使用了**捕获分组**）：\n    *   `(https?)`：**分组1**，匹配 `http` 或 `https`\n    *   `:\\/\\/`：匹配 `://`\n    *   `([^\\/\\s]+)`：**分组2**，匹配域名（直到遇到 `/` 或空格）\n    *   `(\\/[^\\s?]*)?`：**分组3（可选）**，匹配路径\n    *   `(\\?[^\\s#]*)?`：**分组4（可选）**，匹配查询参数\n*   **测试文本**：\n    ```\n    访问我们的官网 https://www.example.com 和博客 https://blog.example.com/path/to/article?id=123\n    ```\n*   **匹配结果**：\n    *   完整匹配1：`https://www.example.com`\n        *   分组1：`https`\n        *   分组2：`www.example.com`\n        *   分组3：`undefined`\n    *   完整匹配2：`https://blog.example.com/path/to/article?id=123`\n        *   分组1：`https`\n        *   分组2：`blog.example.com`\n        *   分组3：`/path/to/article`\n        *   分组4：`?id=123`\n*   🌟 **应用**：网络爬虫、链接分析、安全扫描。\n\n---\n\n#### 4️⃣ 清理和格式化用户输入 🧹\n\n**场景**：去除用户输入的字符串中所有多余的空白字符（包括换行符），只保留一个空格。\n\n*   **表达式**：`\\s+`\n*   **替换为**：一个空格 `\" \"`\n*   **分解说明**：\n    *   `\\s+`：匹配**一个或多个**连续的空白字符（包括空格、制表符 `\\t`、换行符 `\\n`、回车符 `\\r`）\n*   **处理前文本**：\n    ```\n    Hello,    how are you\n    today?\n    I    hope    all is well.\n    ```\n*   **处理后结果**：\n    ```\n    Hello, how are you today? I hope all is well.\n    ```\n*   🧽 **实用性**：在数据入库或文本分析前，做数据清洗的**必备操作**。\n\n---\n\n#### 5️⃣ 匹配中文内容 🇨🇳\n\n**场景**：在混合了中英文和数字的文本中，提取出所有中文字符。\n\n*   **表达式**：`[\\u4e00-\\u9fff]+`\n*   **分解说明**：\n    *   `[\\u4e00-\\u9fff]`：Unicode范围，涵盖了绝大多数常用汉字\n    *   `+`：一个或多个\n*   **测试文本**：\n    ```\n    我的电话是 138-1234-5678，欢迎致电！Welcome to 北京。\n    ```\n*   **匹配结果**：\n    *   `我的电话是`\n    *   `欢迎致电`\n    *   `北京`\n*   🔍 **用途**：中文NLP预处理、敏感词过滤、内容分类。\n\n---\n\n### 💡 给开发者的核心建议\n\n1.  **不要重复造轮子** 🔄：像邮箱、URL、手机号验证，先去搜一下成熟的方案。但务必**理解**它的原理，并针对你的业务进行测试和微调。\n2.  **在线测试工具是你的最佳伙伴** 🧪：在把正则写入代码前，一定要用 [Regex101](https://regex101.com/) 或 [RegExr](https://regexr.com/) 进行测试，它们能可视化解释你的表达式，并高亮匹配组。\n3.  **注意性能** ⚡：过于复杂或嵌套很深的表达式可能导致“灾难性回溯”，在处理长文本时让程序卡死。尽量让表达式**精确**。",
  "游戏引擎/Godot/BBCode 标签学习.md": "\n以下是截至 Godot 最新稳定版（截至 Jul 2025）的 `RichTextLabel` 节点支持的所有 BBCode 标签，非常详尽：\n\n---\n\n## 🔧 基本格式标签\n\n这些都是官方文档中明确支持的基本标签：([Godot Engine documentation](https://docs.godotengine.org/en/3.5/tutorials/ui/bbcode_in_richtextlabel.html?utm_source=chatgpt.com \"BBCode in RichTextLabel — Godot Engine (3.5) documentation in ...\"))\n\n- **`[b]{text}[/b]`**：**粗体**\n    \n- **`[i]{text}[/i]`**：_斜体_\n    \n- **`[u]{text}[/u]`**：下划线\n    \n- **`[s]{text}[/s]`**：删除线\n    \n- **`[code]{text}[/code]`**：等宽字体，保持空格格式\n    \n- **`[center]{text}[/center]`**：水平居中\n    \n- **`[right]{text}[/right]`**：右对齐\n    \n- **`[fill]{text}[/fill]`**：填满整个控件宽度\n    \n- **`[indent]{text}[/indent]`**：增加缩进\n    \n- **`[url]{url_or_meta}[/url]`**：产生可点击的链接（需使用 `meta_clicked` 信号处理）\n    \n- **`[url=<link>]{text}[/url]`**：显示自定义文本的链接\n    \n- **`[img]{path}[/img]`**：插入图片\n    \n- **`[img=<w>]{path}[/img]`**：指定宽度，等比缩放\n    \n- **`[img=<w>x<h>]{path}[/img]`**：指定宽高\n    \n- **`[font=<path>]{text}[/font]`**：使用特定字体资源\n    \n- **`[color=<name_or_#hex>]{text}[/color]`**：设置文本颜色，其中 `<name>` 支持常见颜色名如 aqua、black、blue、red 等，亦支持 `#RRGGBB` 或 `#AARRGGBB` 格式([Godot Engine documentation](https://docs.godotengine.org/en/3.5/tutorials/ui/bbcode_in_richtextlabel.html?utm_source=chatgpt.com \"BBCode in RichTextLabel — Godot Engine (3.5) documentation in ...\"), [Godot Engine documentation](https://docs.godotengine.org/en/3.1/tutorials/gui/bbcode_in_richtextlabel.html?utm_source=chatgpt.com \"BBCode in RichTextLabel - Godot Docs\"), [Godot Engine documentation](https://docs.godotengine.org/en/3.0/tutorials/gui/bbcode_in_richtextlabel.html?utm_source=chatgpt.com \"BBCode in RichTextLabel - Godot Docs\"))\n    \n\n---\n\n## 🧩 表格支持\n\nGodot 支持表格结构，但 **不支持** HTML 风格的 `<tr>` `<td>`，也 **不支持** BBCode `[list]` 等列表标签([Stack Overflow](https://stackoverflow.com/questions/72568676/godot-richtextlabel-bbcode-table-and-list-support?utm_source=chatgpt.com \"Godot RichTextLabel BBCODE Table and List support\"))：\n\n- **`[table=<cols>]{cells}[/table]`**：设定列数，所有内容以 `[cell]...[/cell]` 分隔\n    \n- **`[cell]{content}[/cell]`**：单元格内容\n    \n\n示例用法：\n\n```\n[table=2]\n[cell]你好[/cell]\n[cell][img=16]res://icon.png[/img][/cell]\n[/table]\n```\n\n---\n\n## ✨ 动画／效果标签\n\nGodot 自带几种内置动画效果 BBCode：([Godot Engine documentation](https://docs.godotengine.org/en/3.2/tutorials/gui/bbcode_in_richtextlabel.html?utm_source=chatgpt.com \"BBCode in RichTextLabel - Godot Docs\"), [Godot Engine documentation](https://docs.godotengine.org/en/3.1/tutorials/gui/bbcode_in_richtextlabel.html?utm_source=chatgpt.com \"BBCode in RichTextLabel - Godot Docs\"))\n\n- **`[wave amp=50 freq=2]{text}[/wave]`**：波浪式上下动画，`amp` 控制振幅，`freq` 控制频率\n    \n- **`[fade start=4 length=14]{text}[/fade]`**：渐隐效果，从指定字符开始，长度控制影响范围\n    \n- **`[rainbow freq=0.2 sat=10 val=20]{text}[/rainbow]`**：彩虹色循环动画，`freq` 控制速度，`sat` 饱和度，`val` 亮度\n    \n\n此外，可通过继承 `RichTextEffect` 自定义动画标签([Godot Engine documentation](https://docs.godotengine.org/en/3.2/tutorials/gui/bbcode_in_richtextlabel.html?utm_source=chatgpt.com \"BBCode in RichTextLabel - Godot Docs\"))。\n\n---\n\n## 💡 其他标签\n\n- **`[lb]` 与 `[rb]`**：左/右转义方括号，用于在纯文本中显示 `[` `]` 而不被解析([Godot Engine documentation](https://docs.godotengine.org/en/latest/tutorials/ui/bbcode_in_richtextlabel.html?utm_source=chatgpt.com \"BBCode in RichTextLabel - Godot Docs\"))。\n    \n- **`[fill]`、`[indent]`** 已在基本标签中列出。\n    \n\n---\n\n## ⚙️ 使用建议总结\n\n- 若需嵌套标签，**不要交叉**，如 `[b]bold[i]bold italic[/i][/b]` 是合法，但 `[b]bold[i]bold italic[/b]italic[/i]` 会报错([Godot Engine documentation](https://docs.godotengine.org/en/stable/classes/class_richtextlabel.html?utm_source=chatgpt.com \"RichTextLabel — Godot Engine (stable) documentation in English\"))。\n    \n- 链接需配合脚本信号进行跳转处理。\n    \n- 插入图片时，你可以显式指定尺寸保持布局需求。\n    \n- 基本已覆盖所有官方支持的 BBCode 权能。\n    \n\n---\n\n## ✅ 完整TIP参考\n\n|功能分类|支持标签|参数说明|\n|---|---|---|\n|文字样式|`[b,i,u,s,code]`|常见文本格式|\n|对齐、缩进|`[center,right,fill,indent]`|控制布局母体|\n|链接|`[url]`, `[url=..]`|需 signal 处理|\n|图片|`[img]`, 带尺寸控制|支持 `<w>` 或 `<w>x<h>`|\n|字体颜色|`[font=]`, `[color=]`|支持路径 & named/hex 颜色|\n|表格|`[table=cols]...[/table]`, `[cell]`|创建简易表格|\n|动画效果|`[wave]`, `[fade]`, `[rainbow]`|`amp/freq/sat/val`等自定义参数|\n\n---\n\n",
  "游戏引擎/Godot/DisplayServer简单总结.md": "# DisplayServer API 参考文档\n\n  \n\n## 类简介\n\n  \n\n**继承**：Object\n\n  \n\nDisplayServer 是用于低阶窗口管理的服务器接口。所有与窗口管理相关的内容都由 DisplayServer（显示服务器）处理。\n\n  \n\n> **无头模式**：如果使用 `--headless` 命令行参数启动引擎，就会禁用所有渲染和窗口管理功能，此时 DisplayServer 的大多数函数都会返回虚设值。\n\n  \n\n---\n\n  \n\n## 方法列表\n\n  \n\n### 🔔 系统交互\n\n  \n\n#### `void beep()`\n\n发出系统提示音。\n\n  \n\n#### `void enable_for_stealing_focus(process_id: int)`\n\n允许指定进程获取焦点。\n\n  \n\n#### `void force_process_and_drop_events()`\n\n强制处理并丢弃所有事件。\n\n  \n\n---\n\n  \n\n### 📋 剪贴板操作\n\n  \n\n#### `String clipboard_get()`\n\n获取剪贴板文本内容。\n\n  \n\n#### `Image clipboard_get_image()`\n\n获取剪贴板图像内容。\n\n  \n\n#### `String clipboard_get_primary()`\n\n获取主剪贴板文本内容（仅限 Linux）。\n\n  \n\n#### `bool clipboard_has()`\n\n检查剪贴板是否有内容。\n\n  \n\n#### `bool clipboard_has_image()`\n\n检查剪贴板是否有图像。\n\n  \n\n#### `void clipboard_set(clipboard: String)`\n\n设置剪贴板文本内容。\n\n  \n\n#### `void clipboard_set_primary(clipboard_primary: String)`\n\n设置主剪贴板文本内容（仅限 Linux）。\n\n  \n\n---\n\n  \n\n### 🖱️ 鼠标和光标\n\n  \n\n#### `CursorShape cursor_get_shape()`\n\n获取当前光标形状。\n\n  \n\n#### `void cursor_set_custom_image(cursor: Resource, shape: CursorShape = 0, hotspot: Vector2 = Vector2(0, 0))`\n\n设置自定义光标图像。\n\n  \n\n#### `void cursor_set_shape(shape: CursorShape)`\n\n设置光标形状。\n\n  \n\n#### `BitField[MouseButtonMask] mouse_get_button_state()`\n\n获取鼠标按键状态。\n\n  \n\n#### `MouseMode mouse_get_mode()`\n\n获取鼠标模式。\n\n  \n\n#### `Vector2i mouse_get_position()`\n\n获取鼠标位置。\n\n  \n\n#### `void mouse_set_mode(mouse_mode: MouseMode)`\n\n设置鼠标模式。\n\n  \n\n#### `void warp_mouse(position: Vector2i)`\n\n将鼠标光标移动到指定位置。\n\n  \n\n---\n\n  \n\n### 💬 对话框\n\n  \n\n#### `Error dialog_input_text(title: String, description: String, existing_text: String, callback: Callable)`\n\n显示文本输入对话框。\n\n  \n\n#### `Error dialog_show(title: String, description: String, buttons: PackedStringArray, callback: Callable)`\n\n显示系统对话框。\n\n  \n\n#### `Error file_dialog_show(title: String, current_directory: String, filename: String, show_hidden: bool, mode: FileDialogMode, filters: PackedStringArray, callback: Callable)`\n\n显示文件选择对话框。\n\n  \n\n#### `Error file_dialog_with_options_show(title: String, current_directory: String, root: String, filename: String, show_hidden: bool, mode: FileDialogMode, filters: PackedStringArray, options: Array[Dictionary], callback: Callable)`\n\n显示带扩展选项的文件选择对话框。\n\n  \n\n---\n\n  \n\n### 🎨 主题和颜色\n\n  \n\n#### `Color get_accent_color()`\n\n获取系统强调色。\n\n  \n\n#### `Color get_base_color()`\n\n获取系统基础色。\n\n  \n\n#### `bool is_dark_mode()`\n\n检查系统是否为深色模式。\n\n  \n\n#### `bool is_dark_mode_supported()`\n\n检查系统是否支持深色模式。\n\n  \n\n#### `void set_system_theme_change_callback(callable: Callable)`\n\n设置系统主题变化时的回调。\n\n  \n\n---\n\n  \n\n### 📱 显示和屏幕\n\n  \n\n#### `Array[Rect2] get_display_cutouts()`\n\n获取显示器刘海信息。\n\n  \n\n#### `Rect2i get_display_safe_area()`\n\n获取显示器安全区域。\n\n  \n\n#### `int get_keyboard_focus_screen()`\n\n获取键盘焦点所在屏幕。\n\n  \n\n#### `String get_name()`\n\n获取显示服务器名称。\n\n  \n\n#### `int get_primary_screen()`\n\n获取主屏幕索引。\n\n  \n\n#### `int get_screen_count()`\n\n获取屏幕数量。\n\n  \n\n#### `int get_screen_from_rect(rect: Rect2)`\n\n根据矩形位置获取屏幕索引。\n\n  \n\n#### `bool get_swap_cancel_ok()`\n\n获取是否交换确定取消按钮。\n\n  \n\n#### `int get_window_at_screen_position(position: Vector2i)`\n\n获取指定屏幕位置的窗口ID。\n\n  \n\n#### `PackedInt32Array get_window_list()`\n\n获取所有窗口ID列表。\n\n  \n\n---\n\n  \n\n### 🖥️ 屏幕操作\n\n  \n\n#### `int screen_get_dpi(screen: int = -1)`\n\n获取屏幕DPI。\n\n  \n\n#### `Image screen_get_image(screen: int = -1)`\n\n获取屏幕截图。\n\n  \n\n#### `Image screen_get_image_rect(rect: Rect2i)`\n\n获取屏幕指定区域截图。\n\n  \n\n#### `float screen_get_max_scale()`\n\n获取所有屏幕的最大缩放系数。\n\n  \n\n#### `ScreenOrientation screen_get_orientation(screen: int = -1)`\n\n获取屏幕朝向。\n\n  \n\n#### `Color screen_get_pixel(position: Vector2i)`\n\n获取指定位置的像素颜色。\n\n  \n\n#### `Vector2i screen_get_position(screen: int = -1)`\n\n获取屏幕位置。\n\n  \n\n#### `float screen_get_refresh_rate(screen: int = -1)`\n\n获取屏幕刷新率。\n\n  \n\n#### `float screen_get_scale(screen: int = -1)`\n\n获取屏幕缩放系数。\n\n  \n\n#### `Vector2i screen_get_size(screen: int = -1)`\n\n获取屏幕大小。\n\n  \n\n#### `Rect2i screen_get_usable_rect(screen: int = -1)`\n\n获取屏幕可用区域。\n\n  \n\n#### `bool screen_is_kept_on()`\n\n检查屏幕是否保持开启。\n\n  \n\n#### `void screen_set_keep_on(enable: bool)`\n\n设置屏幕保持开启。\n\n  \n\n#### `void screen_set_orientation(orientation: ScreenOrientation, screen: int = -1)`\n\n设置屏幕朝向。\n\n  \n\n---\n\n  \n\n### 🖼️ 图标设置\n\n  \n\n#### `void set_icon(image: Image)`\n\n设置窗口图标。\n\n  \n\n#### `void set_native_icon(filename: String)`\n\n使用原生格式设置窗口图标。\n\n  \n\n---\n\n  \n\n### 💾 输出管理\n\n  \n\n#### `bool has_additional_outputs()`\n\n检查是否有额外输出设备。\n\n  \n\n#### `void register_additional_output(object: Object)`\n\n注册额外输出设备。\n\n  \n\n#### `void unregister_additional_output(object: Object)`\n\n取消注册额外输出设备。\n\n  \n\n---\n\n  \n\n### ⚡ 功能检测\n\n  \n\n#### `bool has_feature(feature: Feature)`\n\n检查是否支持指定功能。\n\n  \n\n#### `bool has_hardware_keyboard()`\n\n检查是否有硬件键盘。\n\n  \n\n#### `bool is_touchscreen_available()`\n\n检查是否支持触屏。\n\n  \n\n#### `bool is_window_transparency_available()`\n\n检查是否支持窗口透明。\n\n  \n\n---\n\n  \n\n### ⌨️ 键盘\n\n  \n\n#### `int keyboard_get_current_layout()`\n\n获取当前键盘布局。\n\n  \n\n#### `Key keyboard_get_keycode_from_physical(keycode: Key)`\n\n从物理按键获取键码。\n\n  \n\n#### `Key keyboard_get_label_from_physical(keycode: Key)`\n\n从物理按键获取标签。\n\n  \n\n#### `int keyboard_get_layout_count()`\n\n获取键盘布局数量。\n\n  \n\n#### `String keyboard_get_layout_language(index: int)`\n\n获取键盘布局语言。\n\n  \n\n#### `String keyboard_get_layout_name(index: int)`\n\n获取键盘布局名称。\n\n  \n\n#### `void keyboard_set_current_layout(index: int)`\n\n设置当前键盘布局。\n\n  \n\n---\n\n  \n\n### 📝 输入法\n\n#### `Vector2i ime_get_selection()`\n\n获取输入法选中范围。\n\n  \n#### `String ime_get_text()`\n\n获取输入法文本。\n\n\n---\n\n  \n\n### 🎯 状态指示器\n\n#### `int create_status_indicator(icon: Texture2D, tooltip: String, callback: Callable)`\n\n创建状态指示器。\n\n  \n#### `void delete_status_indicator(id: int)`\n\n删除状态指示器。\n\n  \n#### `Rect2 status_indicator_get_rect(id: int)`\n\n获取状态指示器位置。\n\n  \n\n#### `void status_indicator_set_callback(id: int, callback: Callable)`\n\n设置状态指示器回调。\n\n  \n\n#### `void status_indicator_set_icon(id: int, icon: Texture2D)`\n\n设置状态指示器图标。\n\n  \n\n#### `void status_indicator_set_menu(id: int, menu_rid: RID)`\n\n设置状态指示器菜单。\n\n  \n\n#### `void status_indicator_set_tooltip(id: int, tooltip: String)`\n\n设置状态指示器提示文本。\n\n  \n\n---\n\n  \n\n### 📱 数位板\n\n  \n\n#### `String tablet_get_current_driver()`\n\n获取当前数位板驱动。\n\n  \n\n#### `int tablet_get_driver_count()`\n\n获取数位板驱动数量。\n\n  \n\n#### `String tablet_get_driver_name(idx: int)`\n\n获取数位板驱动名称。\n\n  \n\n#### `void tablet_set_current_driver(name: String)`\n\n设置数位板驱动。\n\n  \n\n---\n\n  \n\n### 🗣️ 文本转语音\n\n  \n\n#### `Array[Dictionary] tts_get_voices()`\n\n获取语音列表。\n\n  \n\n#### `PackedStringArray tts_get_voices_for_language(language: String)`\n\n获取指定语言的语音列表。\n\n  \n\n#### `bool tts_is_paused()`\n\n检查是否暂停。\n\n  \n\n#### `bool tts_is_speaking()`\n\n检查是否正在朗读。\n\n  \n\n#### `void tts_pause()`\n\n暂停朗读。\n\n  \n\n#### `void tts_resume()`\n\n恢复朗读。\n\n  \n\n#### `void tts_set_utterance_callback(event: TTSUtteranceEvent, callable: Callable)`\n\n设置朗读事件回调。\n\n  \n\n#### `void tts_speak(text: String, voice: String, volume: int = 50, pitch: float = 1.0, rate: float = 1.0, utterance_id: int = 0, interrupt: bool = false)`\n\n开始朗读文本。\n\n  \n\n#### `void tts_stop()`\n\n停止朗读。\n\n  \n\n---\n\n  \n\n### ⌨️ 虚拟键盘\n\n  \n\n#### `int virtual_keyboard_get_height()`\n\n获取虚拟键盘高度。\n\n  \n\n#### `void virtual_keyboard_hide()`\n\n隐藏虚拟键盘。\n\n  \n\n#### `void virtual_keyboard_show(existing_text: String, position: Rect2 = Rect2(0, 0, 0, 0), type: VirtualKeyboardType = 0, max_length: int = -1, cursor_start: int = -1, cursor_end: int = -1)`\n\n显示虚拟键盘。\n\n  \n\n---\n\n  \n\n### 🪟 窗口管理\n\n  \n\n#### `bool window_can_draw(window_id: int = 0)`\n\n检查窗口是否可绘制。\n\n  \n\n#### `int window_get_active_popup()`\n\n获取活动弹出窗口ID。\n\n  \n\n#### `int window_get_attached_instance_id(window_id: int = 0)`\n\n获取窗口附加的实例ID。\n\n  \n\n#### `int window_get_current_screen(window_id: int = 0)`\n\n获取窗口所在屏幕。\n\n  \n\n#### `bool window_get_flag(flag: WindowFlags, window_id: int = 0)`\n\n获取窗口标志。\n\n  \n\n#### `Vector2i window_get_max_size(window_id: int = 0)`\n\n获取窗口最大尺寸。\n\n  \n\n#### `Vector2i window_get_min_size(window_id: int = 0)`\n\n获取窗口最小尺寸。\n\n  \n\n#### `WindowMode window_get_mode(window_id: int = 0)`\n\n获取窗口模式。\n\n  \n\n#### `int window_get_native_handle(handle_type: HandleType, window_id: int = 0)`\n\n获取窗口原生句柄。\n\n  \n\n#### `Rect2i window_get_popup_safe_rect(window: int)`\n\n获取弹出窗口安全区域。\n\n  \n\n#### `Vector2i window_get_position(window_id: int = 0)`\n\n获取窗口位置。\n\n  \n\n#### `Vector2i window_get_position_with_decorations(window_id: int = 0)`\n\n获取窗口位置（含边框）。\n\n  \n\n#### `Vector3i window_get_safe_title_margins(window_id: int = 0)`\n\n获取标题栏安全边距。\n\n  \n\n#### `Vector2i window_get_size(window_id: int = 0)`\n\n获取窗口大小。\n\n  \n\n#### `Vector2i window_get_size_with_decorations(window_id: int = 0)`\n\n获取窗口大小（含边框）。\n\n  \n\n#### `Vector2i window_get_title_size(title: String, window_id: int = 0)`\n\n获取标题栏大小。\n\n  \n\n#### `VSyncMode window_get_vsync_mode(window_id: int = 0)`\n\n获取垂直同步模式。\n\n  \n\n#### `bool window_is_focused(window_id: int = 0)`\n\n检查窗口是否有焦点。\n\n  \n\n#### `bool window_is_maximize_allowed(window_id: int = 0)`\n\n检查窗口是否可最大化。\n\n  \n\n#### `bool window_maximize_on_title_dbl_click()`\n\n检查双击标题栏是否最大化。\n\n  \n\n#### `bool window_minimize_on_title_dbl_click()`\n\n检查双击标题栏是否最小化。\n\n  \n\n#### `void window_move_to_foreground(window_id: int = 0)`\n\n将窗口移到前台。\n\n  \n\n#### `void window_request_attention(window_id: int = 0)`\n\n请求窗口注意。\n\n  \n\n#### `void window_set_current_screen(screen: int, window_id: int = 0)`\n\n设置窗口所在屏幕。\n\n  \n\n#### `void window_set_drop_files_callback(callback: Callable, window_id: int = 0)`\n\n设置文件拖放回调。\n\n  \n\n#### `void window_set_exclusive(window_id: int, exclusive: bool)`\n\n设置窗口独占模式。\n\n  \n\n#### `void window_set_flag(flag: WindowFlags, enabled: bool, window_id: int = 0)`\n\n设置窗口标志。\n\n  \n\n#### `void window_set_ime_active(active: bool, window_id: int = 0)`\n\n设置输入法是否激活。\n\n  \n\n#### `void window_set_ime_position(position: Vector2i, window_id: int = 0)`\n\n设置输入法位置。\n\n  \n\n#### `void window_set_input_event_callback(callback: Callable, window_id: int = 0)`\n\n设置输入事件回调。\n\n  \n\n#### `void window_set_input_text_callback(callback: Callable, window_id: int = 0)`\n\n设置文本输入回调。\n\n  \n\n#### `void window_set_max_size(max_size: Vector2i, window_id: int = 0)`\n\n设置窗口最大尺寸。\n\n  \n\n#### `void window_set_min_size(min_size: Vector2i, window_id: int = 0)`\n\n设置窗口最小尺寸。\n\n  \n\n#### `void window_set_mode(mode: WindowMode, window_id: int = 0)`\n\n设置窗口模式。\n\n  \n\n#### `void window_set_mouse_passthrough(region: PackedVector2Array, window_id: int = 0)`\n\n设置鼠标穿透区域。\n\n  \n\n#### `void window_set_popup_safe_rect(window: int, rect: Rect2i)`\n\n设置弹出窗口安全区域。\n\n  \n\n#### `void window_set_position(position: Vector2i, window_id: int = 0)`\n\n设置窗口位置。\n\n  \n\n#### `void window_set_rect_changed_callback(callback: Callable, window_id: int = 0)`\n\n设置窗口位置大小变化回调。\n\n  \n\n#### `void window_set_size(size: Vector2i, window_id: int = 0)`\n\n设置窗口大小。\n\n  \n\n#### `void window_set_title(title: String, window_id: int = 0)`\n\n设置窗口标题。\n\n  \n\n#### `void window_set_transient(window_id: int, parent_window_id: int)`\n\n设置窗口为瞬态。\n\n  \n\n#### `void window_set_vsync_mode(vsync_mode: VSyncMode, window_id: int = 0)`\n\n设置垂直同步模式。\n\n  \n\n#### `void window_set_window_buttons_offset(offset: Vector2i, window_id: int = 0)`\n\n设置窗口按钮偏移。\n\n  \n\n#### `void window_set_window_event_callback(callback: Callable, window_id: int = 0)`\n\n设置窗口事件回调。\n\n  \n\n#### `void window_start_drag(window_id: int = 0)`\n\n开始拖拽窗口。\n\n  \n\n#### `void window_start_resize(edge: WindowResizeEdge, window_id: int = 0)`\n\n开始调整窗口大小。\n\n  \n\n---\n\n  \n\n### 📞 帮助系统\n\n  \n\n#### `void help_set_search_callbacks(search_callback: Callable, action_callback: Callable)`\n\n设置帮助系统搜索回调。\n\n  \n\n#### `void show_emoji_and_symbol_picker()`\n\n显示表情符号选择器。\n\n  \n\n---\n\n  \n\n### ⚙️ 事件处理\n\n  \n\n#### `void process_events()`\n\n处理事件。\n\n  \n\n---\n\n  \n\n## 常量\n\n  \n\n- `SCREEN_WITH_MOUSE_FOCUS = -4`：鼠标焦点所在屏幕\n\n- `SCREEN_WITH_KEYBOARD_FOCUS = -3`：键盘焦点所在屏幕  \n\n- `SCREEN_PRIMARY = -2`：主屏幕\n\n- `SCREEN_OF_MAIN_WINDOW = -1`：主窗口所在屏幕\n\n- `MAIN_WINDOW_ID = 0`：主窗口ID\n\n- `INVALID_WINDOW_ID = -1`：无效窗口ID\n\n  \n\n---\n\n  \n\n## 枚举\n\n  \n\n### Feature\n\n系统功能支持检测枚举，包含多种功能如子窗口、触屏、鼠标、剪贴板、虚拟键盘等支持检测。\n\n  \n\n### MouseMode  \n\n鼠标模式枚举：可见、隐藏、捕获、限制等模式。\n\n  \n\n### ScreenOrientation\n\n屏幕朝向枚举：横屏、竖屏及其反向，以及传感器自动模式。\n\n  \n\n### VirtualKeyboardType\n\n虚拟键盘类型：默认、多行、数字、小数、电话、邮箱、密码、URL等。\n\n  \n\n### CursorShape\n\n光标形状枚举：箭头、工字形、指向手形等多种光标样式。\n\n  \n\n### WindowFlags\n\n窗口标志枚举：控制窗口的各种行为和外观属性。\n\n  \n\n### WindowMode\n\n窗口模式枚举：窗口、最小化、最大化、全屏等模式。\n\n  \n\n### HandleType\n\n句柄类型枚举：用于获取不同类型的原生窗口句柄。\n\n  \n\n### VSyncMode\n\n垂直同步模式枚举：控制画面撕裂和帧率同步。\n\n  \n\n### TTSUtteranceEvent\n\n语音朗读事件枚举：开始、结束、取消、边界等事件。\n\n  \n\n---\n\n  \n\n> **注意**：此文档已排除所有已弃用的方法。某些功能可能仅在特定平台上可用，请参考原始文档中的平台支持说明。",
  "游戏引擎/Godot/Godot字典的详细用法.md": "### **Godot `Dictionary` 类用法详解**\n\n#### **基础用法**\n\n------\n\n**1. 创建字典**\n\n```gdscript\n# 空字典\nvar empty_dict = {}\n\n# 初始化字典\nvar simple_dict = {\"name\": \"Godot\", \"version\": 4.0}\n\n# 使用变量作为键和值\nvar key_name = \"language\"\nvar key_value = \"GDScript\"\nvar variable_dict = {key_name: key_value}\n\n# 混合键和值类型\nvar mixed_dict = {\n    \"integer_key\": 1,\n    \"string_key\": \"value\",\n    3: [1, 2, 3], # 数组作为值\n    \"nested_dict\": {\"nested_key\": \"nested_value\"}\n}\n```\n\n\n------\n\n**2. 访问字典值**\n\n```gdscript\nvar my_dict = {\"name\": \"Godot\", \"version\": 4.0}\n\n# 通过键访问值\nprint(my_dict[\"name\"]) # 输出: Godot\n\n# 通过点语法访问（仅限字符串键）\nprint(my_dict.version) # 输出: 4.0\n\n# 使用 `get()` 方法访问\nprint(my_dict.get(\"nonexistent_key\", \"default_value\")) # 输出: default_value\n```\n\n------\n\n**3. 修改或添加键值对**\n\n```gdscript\nvar my_dict = {\"name\": \"Godot\"}\n\n# 修改已有键的值\nmy_dict[\"name\"] = \"Godot Engine\"\n\n# 添加新的键值对\nmy_dict[\"year\"] = 2024\n\nprint(my_dict) # 输出: {\"name\": \"Godot Engine\", \"year\": 2024}\n```\n\n------\n\n**4. 删除键值对**\n\n```gdscript\nvar my_dict = {\"name\": \"Godot\", \"version\": 4.0}\n\n# 使用 erase() 删除\nmy_dict.erase(\"version\")\n\nprint(my_dict) # 输出: {\"name\": \"Godot\"}\n```\n\n------\n\n**5. 检查键是否存在**\n\n```gdscript\nvar my_dict = {\"name\": \"Godot\"}\n\n# 使用 has() 方法\nif my_dict.has(\"name\"):\n    print(\"Key exists!\") # 输出: Key exists!\n\n# 等价的 `in` 语法\nif \"name\" in my_dict:\n    print(\"Key exists!\") # 输出: Key exists!\n```\n\n------\n\n**6. 遍历字典**\n\n```gdscript\nvar groceries = {\"Apple\": 10, \"Banana\": 5, \"Cherry\": 12}\n\n# 遍历键\nfor fruit in groceries:\n    print(fruit, groceries[fruit])\n\n# 遍历键和值\nfor key, value in groceries:\n    print(\"Key:\", key, \"Value:\", value)\n```\n\n------\n\n#### **方法说明**\n\n**1. `clear()`** 清空字典的所有条目。\n\n```gdscript\nvar my_dict = {\"name\": \"Godot\", \"version\": 4.0}\nmy_dict.clear()\nprint(my_dict) # 输出: {}\n```\n\n------\n\n**2. `duplicate(deep: bool = false)`** 创建字典的副本。若 `deep` 为 `true`，内部的嵌套字典或数组也会递归复制。\n\n```gdscript\nvar original = {\"key\": [1, 2, 3]}\nvar shallow_copy = original.duplicate()\nshallow_copy[\"key\"].append(4)\n\nprint(original)       # 输出: {\"key\": [1, 2, 3, 4]}\nprint(shallow_copy)   # 输出: {\"key\": [1, 2, 3, 4]}\n\nvar deep_copy = original.duplicate(true)\ndeep_copy[\"key\"].append(5)\n\nprint(original)       # 输出: {\"key\": [1, 2, 3, 4]}\nprint(deep_copy)      # 输出: {\"key\": [1, 2, 3, 4, 5]}\n```\n\n------\n\n**3. `erase(key: Variant)`** 移除与指定键关联的条目。\n\n```gdscript\nvar my_dict = {\"name\": \"Godot\"}\nmy_dict.erase(\"name\")\nprint(my_dict) # 输出: {}\n```\n\n------\n\n**4. `find_key(value: Variant)`** 查找给定值对应的第一个键，未找到则返回 `null`。\n\n```gdscript\nvar my_dict = {\"key1\": \"value1\", \"key2\": \"value2\"}\nprint(my_dict.find_key(\"value1\")) # 输出: key1\nprint(my_dict.find_key(\"nonexistent\")) # 输出: null\n```\n\n------\n\n**5. `get(key: Variant, default: Variant = null)`** 安全地获取键对应的值，若键不存在则返回默认值。\n\n```gdscript\nvar my_dict = {\"name\": \"Godot\"}\nprint(my_dict.get(\"name\", \"default\")) # 输出: Godot\nprint(my_dict.get(\"nonexistent_key\", \"default\")) # 输出: default\n```\n\n------\n\n**6. `has_all(keys: Array)`** 检查字典是否包含指定数组中的所有键。\n\n```gdscript\nvar my_dict = {\"width\": 10, \"height\": 20}\nprint(my_dict.has_all([\"width\", \"height\"])) # 输出: true\nprint(my_dict.has_all([\"width\", \"depth\"]))  # 输出: false\n```\n\n------\n\n**7. `keys()`** 返回字典中所有键的数组。\n\n```gdscript\nvar my_dict = {\"name\": \"Godot\", \"version\": 4.0}\nprint(my_dict.keys()) # 输出: [\"name\", \"version\"]\n```\n\n------\n\n**8. `values()`** 返回字典中所有值的数组。\n\n```gdscript\nvar my_dict = {\"name\": \"Godot\", \"version\": 4.0}\nprint(my_dict.values()) # 输出: [\"Godot\", 4.0]\n```\n\n------\n\n**9. `merge(dictionary: Dictionary, overwrite: bool = false)`** 合并另一个字典的键值对。默认不覆盖已有键，若 `overwrite` 为 `true` 则覆盖。\n\n```gdscript\nvar dict1 = {\"key1\": \"value1\", \"key2\": \"value2\"}\nvar dict2 = {\"key2\": \"new_value2\", \"key3\": \"value3\"}\n\ndict1.merge(dict2)\nprint(dict1) # 输出: {\"key1\": \"value1\", \"key2\": \"value2\", \"key3\": \"value3\"}\n\ndict1.merge(dict2, true)\nprint(dict1) # 输出: {\"key1\": \"value1\", \"key2\": \"new_value2\", \"key3\": \"value3\"}\n```\n\n------\n\n**10. `size()`** 返回字典中条目的数量。\n\n```gdscript\nvar my_dict = {\"name\": \"Godot\", \"version\": 4.0}\nprint(my_dict.size()) # 输出: 2\n```\n\n------\n\n# **运算符**\n\n------\n\n**1. `==` 和 `!=`** 比较两个字典的内容是否相同。\n\n```gdscript\nvar dict1 = {\"key1\": \"value1\", \"key2\": \"value2\"}\nvar dict2 = {\"key1\": \"value1\", \"key2\": \"value2\"}\nprint(dict1 == dict2) # 输出: true\n\nvar dict3 = {\"key2\": \"value2\", \"key1\": \"value1\"}\nprint(dict1 == dict3) # 输出: true (顺序无关)\n```\n\n**2. `[]` 访问操作符**\n\n```gdscript\nvar my_dict = {\"name\": \"Godot\"}\nprint(my_dict[\"name\"]) # 输出: Godot\n```\n\n------\n",
  "游戏引擎/Godot/godot小代码.md": "```swift\n#鼠标左键点击输出点击位置坐标\nfunc _input(event):\n\t# 检查是否是鼠标左键按下事件\n\tif event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed:\n\t\t# 获取并打印全局坐标\n\t\tvar global_pos = get_global_mouse_position()\n\t\tprint(\"Global mouse position:\", global_pos)\n```\n\n```swift\n\t\t#调用本地文件选择器（C#版）\n        var dialog = new FileDialog();\n        dialog.UseNativeDialog = true;\n        dialog.Access = FileDialog.AccessEnum.Filesystem;\n        dialog.FileSelected += file => GD.Print(file);\n        dialog.Show();\n```\n\n```swift\n#调用本地文件选择器（gdscript）\nvar dialog = FileDialog.new()\ndialog.file_mode=FileDialog.FILE_MODE_OPEN_FILE\ndialog.use_native_dialog = true\ndialog.file_selected.connect(on_selected)\ndialog.show()\nv func on_selected(file_path):\nprint(file_path)\n```\n\n",
  "游戏引擎/Godot/OS类简单总结.md": "\n\n**`OS` 类**是 Godot 引擎中一个重要的单例，用于提供与操作系统交互的常见功能。它允许你访问视频驱动、处理延时、环境变量、执行外部程序等。\n\n在 Godot 4 中，与窗口和时间相关的功能已分别被移动到 `DisplayServer` 和 `Time` 类。\n\n### 属性\n\n- `bool delta_smoothing`：**默认 `true`**。启用增量平滑，用于在垂直同步开启时补偿帧之间的时间变化。\n    \n- `bool low_processor_usage_mode`：**默认 `false`**。启用低处理器使用模式，通过按需刷新屏幕来节省 CPU 资源，特别适用于移动设备。\n    \n- `int low_processor_usage_mode_sleep_usec`：**默认 `6900`**。低处理器模式下，帧之间的睡眠时间（微秒），值越大 CPU 使用率越低。\n    \n---\n\n### 方法概览\n\n| 方法名                                                           | 简要说明                                                 | 适用平台                                     |\n| ------------------------------------------------------------- | ---------------------------------------------------- | ---------------------------------------- |\n| `alert(text, title)`                                          | 显示一个阻塞式的模态对话框。                                       | 所有                                       |\n| `close_midi_inputs()`                                         | 关闭系统 MIDI 驱动，停止接收 MIDI 事件。                           | Linux, macOS, Windows, Web               |\n| `crash(message)`                                              | 使引擎崩溃。仅用于测试，不建议常规使用。                                 | 所有                                       |\n| `create_instance(arguments)`                                  | 创建一个新的 Godot 实例，返回进程 ID。                             | Android, Linux, macOS, Windows           |\n| `create_process(path, arguments, open_console)`               | 创建一个新的独立进程，返回进程 ID。                                  | Android, Linux, macOS, Windows           |\n| `delay_msec(msec)`                                            | 阻塞当前线程 `msec` 毫秒。                                    | 所有                                       |\n| `delay_usec(usec)`                                            | 阻塞当前线程 `usec` 微秒。                                    | 所有                                       |\n| `execute(path, arguments, output, read_stderr, open_console)` | 阻塞式执行外部程序，可获取其退出代码和输出。                               | Android, Linux, macOS, Windows           |\n| `execute_with_pipe(path, arguments, blocking)`                | 创建带 I/O 重定向的独立进程，返回包含 PID、stdin/stdout/stderr 管道的字典。 | Android, Linux, macOS, Windows           |\n| `find_keycode_from_string(string)`                            | 根据字符串查找对应的键码。                                        | 所有                                       |\n| `get_cache_dir()`                                             | 返回全局缓存数据目录路径。                                        | 所有                                       |\n| `get_cmdline_args()`                                          | 返回所有传递给引擎的命令行参数。                                     | 所有                                       |\n| `get_cmdline_user_args()`                                     | 返回双破折号 `--` 之后的用户自定义命令行参数。                           | 所有                                       |\n| `get_config_dir()`                                            | 返回全局用户配置目录路径。                                        | 所有                                       |\n| `get_connected_midi_inputs()`                                 | 返回已连接的 MIDI 设备名称列表。                                  | Linux, macOS, Windows, Web               |\n| `get_data_dir()`                                              | 返回全局用户数据目录路径。                                        | 所有                                       |\n| `get_distribution_name()`                                     | 返回 Linux/BSD 的发行版名称。                                 | Linux, BSD, Android                      |\n| `get_entropy(size)`                                           | 生成指定大小的加密安全随机字节数组。                                   | 所有                                       |\n| `get_environment(variable)`                                   | 获取指定环境变量的值。                                          | 所有                                       |\n| `get_executable_path()`                                       | 返回当前引擎可执行文件的路径。                                      | 所有                                       |\n| `get_granted_permissions()`                                   | 返回已授权的权限列表（Android）或用户选择的文件夹列表（macOS）。               | Android, macOS                           |\n| `get_keycode_string(code)`                                    | 将键码转换为字符串。                                           | 所有                                       |\n| `get_locale()`                                                | 返回完整的操作系统区域设置字符串。                                    | 所有                                       |\n| `get_locale_language()`                                       | 返回操作系统区域设置的语言代码。                                     | 所有                                       |\n| `get_main_thread_id()`                                        | 返回主线程的 ID。                                           | 所有                                       |\n| `get_memory_info()`                                           | 返回包含物理、空闲、可用内存等信息的字典。                                | 所有                                       |\n| `get_model_name()`                                            | 返回当前设备的型号名称。                                         | Android, iOS, macOS, Windows             |\n| `get_name()`                                                  | 返回主机平台的名称（如 \"Windows\", \"macOS\"）。                     | 所有                                       |\n| `get_process_exit_code(pid)`                                  | 获取已终止子进程的退出码。                                        | Android, Linux, macOS, Windows           |\n| `get_process_id()`                                            | 返回当前应用程序的进程 ID。                                      | Android, iOS, Linux, macOS, Windows      |\n| `get_processor_count()`                                       | 返回 CPU 逻辑核心数。                                        | 所有                                       |\n| `get_processor_name()`                                        | 返回 CPU 的型号全名。                                        | Windows, macOS, Linux, iOS               |\n| `get_restart_on_exit_arguments()`                             | 返回退出时自动重启项目的命令行参数。                                   | 所有                                       |\n| `get_static_memory_peak_usage()`                              | 返回静态内存使用峰值（仅调试版本）。                                   | 所有                                       |\n| `get_static_memory_usage()`                                   | 返回静态内存使用量（仅调试版本）。                                    | 所有                                       |\n| `get_stderr_type()`                                           | 返回标准错误设备的类型。                                         | 所有                                       |\n| `get_stdin_type()`                                            | 返回标准输入设备的类型。                                         | 所有                                       |\n| `get_stdout_type()`                                           | 返回标准输出设备的类型。                                         | 所有                                       |\n| `get_system_ca_certificates()`                                | 返回系统信任的 PEM 格式证书字符串。                                 | 所有                                       |\n| `get_system_dir(dir, shared_storage)`                         | 返回指定系统目录的路径。                                         | Android, Linux, macOS, Windows           |\n| `get_system_font_path(font_name, ...)`                        | 返回指定系统字体的文件路径。                                       | Android, iOS, Linux, macOS, Windows      |\n| `get_system_font_path_for_text(font_name, text, ...)`         | 返回可用于渲染特定文本的系统替换字体路径数组。                              | Android, iOS, Linux, macOS, Windows      |\n| `get_system_fonts()`                                          | 返回可用字体家族名称列表。                                        | Android, iOS, Linux, macOS, Windows      |\n| `get_temp_dir()`                                              | 返回全局临时数据目录路径。                                        | 所有                                       |\n| `get_thread_caller_id()`                                      | 返回当前线程的 ID。                                          | 所有                                       |\n| `get_unique_id()`                                             | 返回一个设备唯一的字符串 ID。**注意**：不用于加密。                        | 所有 (Web 不支持)                             |\n| `get_user_data_dir()`                                         | 返回项目专用的用户数据目录路径 (`user://`)。                         | 所有                                       |\n| `get_version()`                                               | 返回操作系统的确切版本号。                                        | 所有 (Web 不支持)                             |\n| `get_version_alias()`                                         | 返回操作系统的品牌版本名和构建号。                                    | Windows, macOS                           |\n| `get_video_adapter_driver_info()`                             | 返回显卡驱动的名称和版本信息。                                      | Linux, BSD, Windows                      |\n| `has_environment(variable)`                                   | 检查环境变量是否存在。                                          | 所有                                       |\n| `has_feature(tag_name)`                                       | 检查当前实例是否支持某个功能标签。                                    | 所有                                       |\n| `is_debug_build()`                                            | 如果是调试构建或在编辑器中运行，返回 `true`。                           | 所有                                       |\n| `is_keycode_unicode(code)`                                    | 检查键码是否对应 Unicode 字符。                                 | 所有                                       |\n| `is_process_running(pid)`                                     | 检查指定进程 ID 的子进程是否仍在运行。                                | Android, iOS, Linux, macOS, Windows      |\n| `is_restart_on_exit_set()`                                    | 检查项目是否被设置为退出时自动重启。                                   | 所有                                       |\n| `is_sandboxed()`                                              | 检查应用程序是否在沙箱中运行。                                      | macOS, Linux                             |\n| `is_stdout_verbose()`                                         | 检查是否启用了冗长标准输出。                                       | 所有                                       |\n| `is_userfs_persistent()`                                      | 检查 `user://` 文件系统是否是持久的。                             | 所有                                       |\n| `kill(pid)`                                                   | 终止指定进程 ID 的进程。                                       | Android, iOS, Linux, macOS, Windows      |\n| `move_to_trash(path)`                                         | 将文件或目录移动到系统的回收站。                                     | Android, Linux, macOS, Windows           |\n| `open_midi_inputs()`                                          | 初始化系统 MIDI 驱动，开始接收 MIDI 事件。                          | Linux, macOS, Windows, Web               |\n| `read_buffer_from_stdin(buffer_size)`                         | 从标准输入读取原始字节数组。                                       | Linux, macOS, Windows                    |\n| `read_string_from_stdin(buffer_size)`                         | 从标准输入读取字符串。                                          | Linux, macOS, Windows                    |\n| `request_permission(name)`                                    | 向操作系统请求指定权限。                                         | Android                                  |\n| `request_permissions()`                                       | 请求危险权限。                                              | Android                                  |\n| `revoke_granted_permissions()`                                | 清除 macOS 沙箱应用的用户选择文件夹访问权限。                           | macOS                                    |\n| `set_environment(variable, value)`                            | 设置环境变量。                                              | 所有                                       |\n| `set_restart_on_exit(restart, arguments)`                     | 设置项目退出时是否自动重新启动。                                     | 桌面平台                                     |\n| `set_thread_name(name)`                                       | 为当前线程设置名称。                                           | 所有                                       |\n| `set_use_file_access_save_and_swap(enabled)`                  | 启用文件保存的“先写临时文件再交换”模式，可避免文件被锁。                        | 所有                                       |\n| `shell_open(uri)`                                             | 使用系统默认程序打开 URI（文件、链接等）。                              | Android, iOS, Web, Linux, macOS, Windows |\n| `shell_show_in_file_manager(file_or_dir_path, open_folder)`   | 在文件管理器中打开并选中指定文件或目录。                                 | Windows, macOS                           |\n| `unset_environment(variable)`                                 | 移除环境变量。                                              | 所有                                       |\n\n---\n\n### 枚举\n\n#### `RenderingDriver`\n\n- `RENDERING_DRIVER_VULKAN` (0)\n    \n- `RENDERING_DRIVER_OPENGL3` (1)\n    \n- `RENDERING_DRIVER_D3D12` (2)\n    \n- `RENDERING_DRIVER_METAL` (3)\n    \n\n#### `SystemDir`\n\n- `SYSTEM_DIR_DESKTOP` (0)\n    \n- `SYSTEM_DIR_DCIM` (1)\n    \n- `SYSTEM_DIR_DOCUMENTS` (2)\n    \n- `SYSTEM_DIR_DOWNLOADS` (3)\n    \n- `SYSTEM_DIR_MOVIES` (4)\n    \n- `SYSTEM_DIR_MUSIC` (5)\n    \n- `SYSTEM_DIR_PICTURES` (6)\n    \n- `SYSTEM_DIR_RINGTONES` (7)\n    \n\n#### `StdHandleType`\n\n- `STD_HANDLE_INVALID` (0)\n    \n- `STD_HANDLE_CONSOLE` (1)\n    \n- `STD_HANDLE_FILE` (2)\n    \n- `STD_HANDLE_PIPE` (3)\n    \n- `STD_HANDLE_UNKNOWN` (4)",
  "游戏引擎/Unity/Unity代码片段/Unity中的单例模式（全局变量）.md": "是的，Unity确实可以通过全局管理的脚本来实现你所说的功能。可以通过 **单例模式** 来创建一个全局的管理脚本，存储并更新玩家的位置，然后让其他脚本通过访问这个全局管理类来实时获取玩家的位置。\r\n\r\n### 解决方案：使用单例模式来管理全局数据\r\n\r\n**步骤：**\r\n\r\n1. 创建一个全局的管理脚本，使用单例模式保存玩家的位置。\r\n2. 在玩家生成脚本中，不断更新这个全局位置。\r\n3. 在 `GUI` 或其他脚本中，通过访问这个全局脚本来获取玩家位置。\r\n\r\n### 示例：\r\n\r\n#### 1. 创建一个全局管理类 `GameManager`\r\n\r\n这个类将使用单例模式，并且持有玩家的位置。\r\n\r\n```csharp\r\nusing UnityEngine;\r\n\r\npublic class GameManager : MonoBehaviour\r\n{\r\n    public static GameManager Instance { get; private set; }  // 单例模式\r\n    public Vector3 PlayerPosition { get; private set; }  // 存储玩家位置\r\n\r\n    void Awake()\r\n    {\r\n        // 确保只有一个 GameManager 实例\r\n        if (Instance == null)\r\n        {\r\n            Instance = this;\r\n        }\r\n        else\r\n        {\r\n            Destroy(gameObject);  // 如果已经有一个实例，销毁当前实例\r\n        }\r\n\r\n        // 不销毁该物体，以便在场景切换时仍然存在\r\n        DontDestroyOnLoad(gameObject);\r\n    }\r\n\r\n    public void UpdatePlayerPosition(Vector3 newPosition)\r\n    {\r\n        PlayerPosition = newPosition;  // 更新玩家位置\r\n    }\r\n}\r\n```\r\n\r\n#### 2. 修改玩家生成脚本 `Player_Generated_Pos`\r\n\r\n在玩家生成脚本中，实例化玩家时更新全局的玩家位置。\r\n\r\n```csharp\r\nusing System.Collections;\r\nusing System.Collections.Generic;\r\nusing UnityEngine;\r\n\r\npublic class Player_Generated_Pos : MonoBehaviour\r\n{\r\n    public GameObject playerPrefab; // 玩家飞机的预制体\r\n    public Transform[] spawnPoints; // 存储生成点的数组\r\n\r\n    private GameObject playerInstance; // 玩家实例\r\n\r\n    void Start()\r\n    {\r\n        // 调用函数在随机位置生成玩家飞机\r\n        SpawnPlayerAtRandomPosition();\r\n    }\r\n\r\n    void SpawnPlayerAtRandomPosition()\r\n    {\r\n        // 随机选择一个生成点\r\n        int randomIndex = Random.Range(0, spawnPoints.Length);\r\n        Transform spawnPoint = spawnPoints[randomIndex];\r\n\r\n        // 在选定的位置生成玩家飞机，并获取实例对象\r\n        playerInstance = Instantiate(playerPrefab, spawnPoint.position, spawnPoint.rotation);\r\n\r\n        // 更新全局玩家位置\r\n        GameManager.Instance.UpdatePlayerPosition(playerInstance.transform.position);\r\n        \r\n        // 输出生成的玩家飞机实例的位置\r\n        Debug.Log(\"玩家生成位置：\" + playerInstance.transform.position);\r\n    }\r\n\r\n    void Update()\r\n    {\r\n        // 实时更新全局玩家位置\r\n        if (playerInstance != null)\r\n        {\r\n            GameManager.Instance.UpdatePlayerPosition(playerInstance.transform.position);\r\n        }\r\n    }\r\n}\r\n```\r\n\r\n#### 3. 修改 `GUI` 脚本\r\n\r\n在 `GUI` 脚本中，通过访问 `GameManager.Instance` 获取玩家的实时位置并更新 UI。\r\n\r\n```csharp\r\nusing System.Collections;\r\nusing System.Collections.Generic;\r\nusing TMPro;  // 引入 TextMeshPro 命名空间\r\nusing UnityEngine;\r\n\r\npublic class GUI : MonoBehaviour\r\n{\r\n    private TextMeshProUGUI Player_Pos;  // 存储 TextMeshProUGUI 组件\r\n\r\n    void Start()\r\n    {\r\n        // 使用 GetComponent 获取 TextMeshProUGUI 组件\r\n        Player_Pos = GameObject.Find(\"Player_Pos\")?.GetComponent<TextMeshProUGUI>();\r\n    }\r\n\r\n    void Update()\r\n    {\r\n        // 获取全局的玩家位置\r\n        if (GameManager.Instance != null)\r\n        {\r\n            Vector3 playerPosition = GameManager.Instance.PlayerPosition;\r\n\r\n            // 更新UI显示玩家位置\r\n            if (Player_Pos != null)\r\n            {\r\n                Player_Pos.text = \"玩家坐标: (\" + playerPosition.x + \",\" + playerPosition.y + \")\";\r\n            }\r\n        }\r\n    }\r\n}\r\n```\r\n\r\n### 解释：\r\n\r\n1. **`GameManager` 类**：\r\n   - `GameManager` 类作为一个 **单例**，负责存储并提供玩家的位置数据。它使用 `Awake()` 方法确保只会有一个实例，并使用 `DontDestroyOnLoad()` 方法确保场景切换时 `GameManager` 不会被销毁。\r\n   - `UpdatePlayerPosition()` 方法用于更新玩家的位置。\r\n\r\n2. **`Player_Generated_Pos` 类**：\r\n   - 在 `SpawnPlayerAtRandomPosition()` 中，生成玩家飞机后，通过 `GameManager.Instance.UpdatePlayerPosition()` 将生成的位置传递到全局管理器。\r\n   - 在 `Update()` 方法中，实时更新全局的玩家位置。\r\n\r\n3. **`GUI` 类**：\r\n   - 在 `Update()` 方法中，通过 `GameManager.Instance.PlayerPosition` 获取玩家的实时位置，并更新 `TextMeshProUGUI` 组件中的文本。\r\n\r\n### 优点：\r\n- **全局管理**：通过 `GameManager` 单例类，你可以轻松地在任何脚本中获取和更新玩家的位置。\r\n- **实时更新**：`GUI` 脚本每帧都会自动获取并显示玩家的实时位置。\r\n- **模块化**：通过分离管理和显示逻辑，你的代码结构会更加清晰和易于维护。\r\n\r\n### 总结：\r\n使用 **单例模式** 作为全局脚本来管理和共享玩家位置是一个非常有效的方法。它不仅能减少跨脚本传递数据的复杂度，而且能确保玩家位置在不同的脚本之间实时同步。\r\n\r\n\r\n\r\n根据你的描述，问题出在这一行代码：\r\n\r\n```csharp\r\nGameManager.Instance.UpdatePlayerPosition(playerInstance.transform.position);\r\n```\r\n\r\n如果报错是由于 `GameManager.Instance` 返回 `null`，说明 `GameManager` 这个单例没有正确初始化，或者它没有被加载到场景中。通常，这种情况是因为：\r\n\r\n1. **`GameManager` 没有正确加载或实例化**，即它没有在场景中创建，或者它在访问时被销毁。\r\n2. **`Awake()` 方法没有正确执行**，从而导致 `Instance` 为 `null`。\r\n\r\n### 检查和修复步骤：\r\n\r\n1. **确保 `GameManager` 存在于场景中**：\r\n   确保 `GameManager` 脚本已挂载到一个对象上，并且该对象已存在于场景中。你可以检查 `GameManager` 是否被添加到了一个合适的 GameObject 上（例如一个 \"GameManager\" 或 \"Manager\" 的空物体）。\r\n\r\n2. **确保 `GameManager` 使用单例模式**：\r\n   检查 `GameManager` 脚本的 `Awake()` 方法，确保它正确初始化并设置 `Instance`，例如：\r\n\r\n   ```csharp\r\n   using UnityEngine;\r\n   \r\n   public class GameManager : MonoBehaviour\r\n   {\r\n       public static GameManager Instance { get; private set; }\r\n   \r\n       public Vector3 PlayerPosition { get; private set; } // 存储玩家位置\r\n   \r\n       void Awake()\r\n       {\r\n           // 检查是否已经有 GameManager 实例存在\r\n           if (Instance == null)\r\n           {\r\n               Instance = this;\r\n               DontDestroyOnLoad(gameObject); // 确保场景切换时不销毁该对象\r\n           }\r\n           else\r\n           {\r\n               Destroy(gameObject);  // 如果已经有一个实例，销毁当前实例\r\n           }\r\n       }\r\n   \r\n       public void UpdatePlayerPosition(Vector3 newPosition)\r\n       {\r\n           PlayerPosition = newPosition;  // 更新玩家位置\r\n       }\r\n   }\r\n   ```\r\n\r\n   - 确保 `Instance` 在 `Awake()` 中被赋值。\r\n   - 如果场景中已经存在一个 `GameManager` 实例，后加载的 `GameManager` 会被销毁。\r\n\r\n3. **检查是否有其他 `GameManager` 实例**：\r\n   - 如果在场景中有多个 `GameManager` 实例，`Instance` 可能会被覆盖。确保只有一个 `GameManager` 实例，避免出现多个对象争夺单例实例。\r\n\r\n4. **调试**：\r\n   在 `Player_Generated_Pos` 脚本中，添加调试信息来检查 `GameManager.Instance` 是否为 `null`。\r\n\r\n   ```csharp\r\n   void Update()\r\n   {\r\n       // 检查 GameManager 是否为 null\r\n       if (GameManager.Instance == null)\r\n       {\r\n           Debug.LogError(\"GameManager 实例为 null，确保 GameManager 已经正确加载！\");\r\n       }\r\n       else if (playerInstance != null)\r\n       {\r\n           // 更新全局玩家位置\r\n           GameManager.Instance.UpdatePlayerPosition(playerInstance.transform.position);\r\n       }\r\n   }\r\n   ```\r\n\r\n   如果控制台显示 \"GameManager 实例为 null\"，说明 `GameManager` 没有正确实例化，可能是由于 `Awake()` 方法没有执行，或者场景中没有正确的 `GameManager` 对象。\r\n\r\n### 总结：\r\n\r\n- 确保 `GameManager` 正确地使用单例模式，并且它的实例在场景中是唯一的。\r\n- 使用 `DontDestroyOnLoad` 确保 `GameManager` 在场景切换时不被销毁。\r\n- 在其他脚本中访问 `GameManager.Instance` 前，确保它已经正确初始化。\r\n\r\n通过这些步骤，你应该能够解决 `GameManager.Instance` 为 `null` 的问题。\r\n\r\n\r\n\r\n",
  "游戏引擎/Unity/Unity代码片段/unity修改物理碰撞层.md": "要实现玩家射出的子弹不与玩家碰撞，而与敌人碰撞，敌人射出的子弹不与敌人碰撞而与玩家碰撞，你可以通过调整Unity中的**物理层（Layer）**和**碰撞矩阵（Collision Matrix）**来解决这个问题。\r\n\r\n### 步骤：\r\n\r\n1. **创建新的物理层**：\r\n   - 在Unity中，首先你需要为玩家、敌人和子弹分别创建不同的物理层。\r\n   - 转到 `Edit` -> `Project Settings` -> `Tags and Layers`。\r\n   - 在 `Layers` 部分，点击 `User Layer` 下面的空白区域，创建以下新的层：\r\n     - `Player`\r\n     - `Enemy`\r\n     - `PlayerBullet`\r\n     - `EnemyBullet`\r\n\r\n2. **将对象分配到不同的层**：\r\n   - 将玩家对象的 `Layer` 设置为 `Player`。\r\n   - 将敌人对象的 `Layer` 设置为 `Enemy`。\r\n   - 将玩家射出的子弹的 `Layer` 设置为 `PlayerBullet`。\r\n   - 将敌人射出的子弹的 `Layer` 设置为 `EnemyBullet`。\r\n\r\n3. **设置碰撞矩阵**：\r\n   - 转到 `Edit` -> `Project Settings` -> `Physics`。\r\n   - 在 `Physics` 设置中，找到 `Layer Collision Matrix`。\r\n   - 你可以在这里设置哪些层之间可以发生碰撞。\r\n     - **Player 和 PlayerBullet** 之间不发生碰撞。\r\n     - **Enemy 和 EnemyBullet** 之间不发生碰撞。\r\n     - **PlayerBullet 和 Enemy** 之间发生碰撞。\r\n     - **EnemyBullet 和 Player** 之间发生碰撞。\r\n   \r\n   具体的设置应该如下：\r\n   - 确保 `Player` 和 `PlayerBullet` 行与列之间的勾选框是**取消勾选的**，这样它们不会发生碰撞。\r\n   - 确保 `Enemy` 和 `EnemyBullet` 行与列之间的勾选框是**取消勾选的**，这样它们不会发生碰撞。\r\n   - 确保 `PlayerBullet` 和 `Enemy` 之间，以及 `EnemyBullet` 和 `Player` 之间的碰撞是**勾选的**。\r\n\r\n4. **确保Rigidbody的碰撞检测模式正确**：\r\n   - 对于玩家和子弹的 `Rigidbody` 组件，确保它们的 `Collision Detection` 设置为 `Continuous` 或 `Continuous Dynamic`，这有助于避免物理计算错误，尤其是在高速度的情况下。\r\n\r\n### 代码示例（如果需要动态设置层）：\r\n如果你希望在代码中动态设置某个对象的层，可以使用以下代码：\r\n\r\n```csharp\r\n// 设置玩家子弹的层\r\ngameObject.layer = LayerMask.NameToLayer(\"PlayerBullet\");\r\n\r\n// 设置敌人子弹的层\r\ngameObject.layer = LayerMask.NameToLayer(\"EnemyBullet\");\r\n```\r\n\r\n### 结论：\r\n通过使用Unity的**Layer**和**Layer Collision Matrix**，你可以精确控制不同物体之间的碰撞行为。将玩家、敌人和子弹分别分配到不同的物理层，并在碰撞矩阵中配置它们之间的碰撞规则，就能实现你所需要的功能：玩家射出的子弹不与玩家碰撞，而与敌人碰撞，敌人射出的子弹不与敌人碰撞，而与玩家碰撞。",
  "游戏引擎/Unity/Unity代码片段/unity导出到Windows改变窗口.md": "在Unity中，如果你希望应用程序以特定的窗口大小而不是全屏运行，可以通过以下步骤进行设置：\r\n\r\n### 1. **通过Player Settings设置窗口模式**：\r\n   - 打开 `Edit` 菜单，选择 `Project Settings`。\r\n   - 在 `Project Settings` 中，选择 `Player`。\r\n   - 在 `Player` 设置中，找到 `Resolution and Presentation` 部分。\r\n\r\n### 2. **调整默认显示模式**：\r\n   - 在 `Resolution and Presentation` 下，找到 `Default Screen Mode`。\r\n   - 将其设置为 `Windowed`，而不是 `Full Screen`，这样Unity会默认以窗口模式运行。\r\n\r\n### 3. **设置窗口的分辨率**：\r\n   - 在 `Resolution and Presentation` 中，你还可以设置窗口的默认分辨率：\r\n     - `Default Screen Width` 和 `Default Screen Height` 可以指定启动时窗口的大小。\r\n     - 例如，设置为 `1024x768`，这将使窗口在启动时以 1024x768 的分辨率打开。\r\n\r\n### 4. **通过代码动态调整窗口大小**：\r\n   如果你希望根据需要在游戏运行时改变窗口大小，可以使用以下代码：\r\n\r\n   ```csharp\r\n   void Start()\r\n   {\r\n       // 设置窗口大小为 1024x768\r\n       Screen.SetResolution(1024, 768, false);\r\n   }\r\n   ```\r\n\r\n   这里，`Screen.SetResolution` 的第三个参数是布尔值，`false` 表示窗口模式（如果是 `true` 则会进入全屏模式）。\r\n\r\n### 总结：\r\n1. 在 `Player Settings` 中设置默认为窗口模式（`Windowed`）。\r\n2. 可选择设置默认窗口的分辨率。\r\n3. 如果需要动态调整窗口大小，可以通过 `Screen.SetResolution` 来实现。\r\n\r\n通过这些设置，你就能让你的Unity项目在启动时以指定窗口大小而不是全屏运行。",
  "游戏引擎/Unity/Unity代码片段/unity碰撞体撞到指定标签的碰撞体后操作.md": "要实现子弹在撞到标签为“air_wall”的碰撞体后被销毁，你需要在 `Bullet` 脚本中添加碰撞检测代码。使用 `OnCollisionEnter2D` 方法来处理与碰撞体的接触，并检查碰撞体的标签是否是“air_wall”。\r\n\r\n以下是修改后的代码：\r\n\r\n```csharp\r\nusing System.Collections;\r\nusing System.Collections.Generic;\r\nusing UnityEngine;\r\n\r\npublic class Bullet : MonoBehaviour\r\n{\r\n    void Start()\r\n    {\r\n        // 在 5 秒后销毁子弹对象\r\n        Destroy(gameObject, 5f); // 5f 表示 5 秒后销毁该对象\r\n    }\r\n\r\n    void Update()\r\n    {\r\n        // 你可以在这里添加子弹的移动逻辑\r\n    }\r\n\r\n    void OnCollisionEnter2D(Collision2D collision)\r\n    {\r\n        // 检查碰撞体是否有标签 \"air_wall\"\r\n        if (collision.gameObject.CompareTag(\"AirWall\"))\r\n        {\r\n            // 如果是，销毁子弹\r\n            Destroy(gameObject);\r\n        }\r\n    }\r\n}\r\n```\r\n\r\n### 解释：\r\n- `OnCollisionEnter2D(Collision2D collision)`：当子弹与其他物体发生碰撞时，这个方法会被调用。\r\n- `collision.gameObject.CompareTag(\"AirWall\")`：检查碰撞体的标签是否是 \"AirWall\"。\r\n- 如果是，使用 `Destroy(gameObject)` 销毁子弹对象。\r\n\r\n这样，子弹在撞到标签为 \"AirWall\" 的物体时就会被销毁。如果需要，也可以将销毁逻辑添加到其他碰撞处理上。",
  "游戏引擎/Unity/Unity代码片段/Unity获取同一场景中其他对象的属性&组件.md": "在 Unity 中，获取同一场景中其他对象的属性（如位置）非常简单。你可以通过查找目标对象，并访问其组件来获取需要的信息。常用的方法有以下几种：\r\n\r\n### 1. 使用 `GameObject.Find()` 查找对象并获取其属性\r\n`GameObject.Find()` 可以用来查找场景中具有指定名称的对象。\r\n\r\n示例代码：\r\n\r\n```csharp\r\nusing System.Collections;\r\nusing System.Collections.Generic;\r\nusing UnityEngine;\r\n\r\npublic class Player_Generated_Pos : MonoBehaviour\r\n{\r\n    void Start()\r\n    {\r\n        // 查找名称为 \"TargetObject\" 的对象\r\n        GameObject targetObject = GameObject.Find(\"TargetObject\");\r\n\r\n        if (targetObject != null)\r\n        {\r\n            // 获取目标对象的位置\r\n            Vector3 targetPosition = targetObject.transform.position;\r\n            Debug.Log(\"Target position: \" + targetPosition);\r\n        }\r\n        else\r\n        {\r\n            Debug.LogWarning(\"TargetObject not found!\");\r\n        }\r\n    }\r\n\r\n    void Update()\r\n    {\r\n        // 可以根据需要在 Update 中执行相关操作\r\n    }\r\n}\r\n```\r\n\r\n### 2. 使用标签（`Tag`）查找对象\r\n如果对象的名称可能发生变化，使用标签（`Tag`）来查找更为可靠。你可以先在 Unity 编辑器中为对象设置标签。\r\n\r\n示例代码：\r\n\r\n```csharp\r\nusing System.Collections;\r\nusing System.Collections.Generic;\r\nusing UnityEngine;\r\n\r\npublic class Player_Generated_Pos : MonoBehaviour\r\n{\r\n    void Start()\r\n    {\r\n        // 查找所有带有 \"Target\" 标签的对象\r\n        GameObject[] targetObjects = GameObject.FindGameObjectsWithTag(\"Target\");\r\n\r\n        foreach (GameObject targetObject in targetObjects)\r\n        {\r\n            // 获取目标对象的位置\r\n            Vector3 targetPosition = targetObject.transform.position;\r\n            Debug.Log(\"Target position: \" + targetPosition);\r\n        }\r\n    }\r\n\r\n    void Update()\r\n    {\r\n        // 可以根据需要在 Update 中执行相关操作\r\n    }\r\n}\r\n```\r\n\r\n### 3. 使用 `GetComponent` 访问其他组件的属性\r\n如果你已经有了目标对象的引用，可以通过 `GetComponent` 获取该对象的组件并访问其属性。\r\n\r\n例如，假设你已经有一个 `Player` 对象，并且想访问该对象的 `Transform` 组件的位置：\r\n\r\n```csharp\r\nusing System.Collections;\r\nusing System.Collections.Generic;\r\nusing UnityEngine;\r\n\r\npublic class Player_Generated_Pos : MonoBehaviour\r\n{\r\n    public GameObject player; // 你可以将 Player 对象通过 Inspector 拖入\r\n\r\n    void Start()\r\n    {\r\n        if (player != null)\r\n        {\r\n            // 获取 Player 对象的位置\r\n            Vector3 playerPosition = player.transform.position;\r\n            Debug.Log(\"Player position: \" + playerPosition);\r\n        }\r\n        else\r\n        {\r\n            Debug.LogWarning(\"Player object not assigned!\");\r\n        }\r\n    }\r\n\r\n    void Update()\r\n    {\r\n        // 可以根据需要在 Update 中执行相关操作\r\n    }\r\n}\r\n```\r\n\r\n### 总结：\r\n- **`GameObject.Find()`**：通过名称查找对象。\r\n- **`GameObject.FindGameObjectsWithTag()`**：通过标签查找对象。\r\n- **`GetComponent<T>()`**：如果你有对象引用，使用该方法来访问对象的组件和属性。\r\n\r\n根据你的需求，选择适合的方式来获取对象的位置或其他属性。",
  "游戏引擎/Unity/Unity代码片段/保留整数.md": "要保留整数并显示玩家坐标，你可以使用 `Mathf.RoundToInt()` 来将浮动的坐标值四舍五入为整数，或者直接使用 `ToString()` 来控制格式。这里是两种常见的方法：\r\n\r\n### 方法 1：使用 `Mathf.RoundToInt()` 将坐标四舍五入为整数\r\n\r\n```csharp\r\nPlayer_Pos.text = \"玩家坐标: (\" + Mathf.RoundToInt(playerPosition.x) + \",\" + Mathf.RoundToInt(playerPosition.y) + \")\";\r\n```\r\n\r\n`Mathf.RoundToInt()` 会将浮动的坐标值四舍五入为最接近的整数。\r\n\r\n### 方法 2：使用 `ToString()` 来格式化数字\r\n\r\n你也可以使用 `ToString(\"F0\")` 来将数字转换为带有指定小数位数的字符串，在这种情况下是零小数位，表示整数。\r\n\r\n```csharp\r\nPlayer_Pos.text = \"玩家坐标: (\" + playerPosition.x.ToString(\"F0\") + \",\" + playerPosition.y.ToString(\"F0\") + \")\";\r\n```\r\n\r\n这种方式也会将坐标保留为整数，并且格式化为 `string` 类型。\r\n\r\n### 总结：\r\n\r\n- **`Mathf.RoundToInt()`**: 将浮动坐标值四舍五入为最接近的整数。\r\n- **`ToString(\"F0\")`**: 格式化为没有小数位的字符串。\r\n\r\n这两种方法都能达到你的目的，具体选择哪一种取决于你是否需要精确的四舍五入，或者仅仅是格式化显示。",
  "游戏引擎/Unity/Unity代码片段/设置在几个特定点钟随机生成.md": "要实现玩家飞机在地图上的 5 个点之间随机生成，你可以定义一个包含这 5 个点的数组或列表，然后通过随机选择一个点来生成飞机。\r\n\r\n以下是一个示例脚本：\r\n\r\n### 步骤：\r\n1. **定义 5 个生成点的位置**：你可以将这些点的位置存储在一个 `Vector3[]` 数组中。\r\n2. **随机选择一个点**：使用 `Random.Range` 方法从这个数组中随机选择一个点。\r\n3. **将玩家飞机生成到选定的位置**：通过 `Instantiate` 方法实例化玩家飞机对象并设置它的位置。\r\n\r\n### 示例代码：\r\n\r\n```csharp\r\nusing System.Collections;\r\nusing System.Collections.Generic;\r\nusing UnityEngine;\r\n\r\npublic class Player_Generated_Pos : MonoBehaviour\r\n{\r\n    public GameObject playerPrefab; // 玩家飞机的预制体\r\n    public Transform[] spawnPoints; // 存储生成点的数组\r\n\r\n    void Start()\r\n    {\r\n        // 调用函数在随机位置生成玩家飞机\r\n        SpawnPlayerAtRandomPosition();\r\n    }\r\n\r\n    void SpawnPlayerAtRandomPosition()\r\n    {\r\n        // 随机选择一个生成点\r\n        int randomIndex = Random.Range(0, spawnPoints.Length);\r\n        Transform spawnPoint = spawnPoints[randomIndex];\r\n\r\n        // 在选定的位置生成玩家飞机\r\n        Instantiate(playerPrefab, spawnPoint.position, spawnPoint.rotation);\r\n    }\r\n}\r\n```\r\n\r\n### 解释：\r\n1. **`spawnPoints`**：这是一个 `Transform[]` 数组，用来存储 5 个可能的生成点。你可以在 Unity 编辑器中通过拖拽场景中的物体（生成点）到这个数组中来设置这些位置。\r\n2. **`Random.Range(0, spawnPoints.Length)`**：随机选择一个索引，范围从 `0` 到 `spawnPoints.Length - 1`。\r\n3. **`Instantiate(playerPrefab, spawnPoint.position, spawnPoint.rotation)`**：在选择的生成点位置生成玩家飞机（`playerPrefab`）。\r\n\r\n### 在 Unity 编辑器中：\r\n1. 将 `Player_Generated_Pos` 脚本附加到一个物体（比如一个空的 GameObject）。\r\n2. 在 Inspector 面板中，设置 `playerPrefab` 为你的玩家飞机预制体。\r\n3. 设置 `spawnPoints` 数组，确保它包含你要随机生成玩家飞机的 5 个位置点。你可以将场景中的空物体拖到该数组中，作为生成点。\r\n\r\n### 生成点设置：\r\n你可以在 Unity 场景中创建 5 个空物体，并将它们放置在你希望飞机生成的位置。然后，将这些空物体拖到 `spawnPoints` 数组中。\r\n\r\n这样，当游戏开始时，玩家飞机将会在这 5 个点之间的一个位置随机生成。",
  "游戏引擎/Unity/Unity简单解决字体放大模糊问题.md": "把文本组件缩小十倍（以1为基准）\r\n\r\n然后把字体大小放大10倍\r\n\r\n然后拖动适应原来的位置大小",
  "生活科普/OTC药和处方药的区别.md": "OTC（Over-The-Counter） 指无需医生处方即可自行购买和使用的药品，主要用于治疗轻微疾病或症状，具有安全性较高、副作用较小的特点。以下是关于OTC药的详细说明：\n \n一、OTC药的核心特点\n \n1. 无需处方：可直接在药店或超市购买，无需医生诊断。\n2. 适应症明确：针对常见小病（如感冒、发烧、头痛、消化不良等），患者可自我判断症状。\n3. 安全性高：经过监管机构评估，剂量和疗程有明确限制，风险较低。\n4. 说明书指导：需严格按说明书使用，避免过量或长期服用。\n \n二、OTC药与处方药的区别\n \n特性 OTC药 处方药 \n购买条件 无需处方 必须凭医生处方 \n适应症 轻微、短期症状 复杂或严重疾病 \n风险等级 较低 较高（需专业监控） \n剂量控制 固定标准剂量 可能需个性化调整 \n包装标识 标注“OTC”（中国分红色/绿色） 标注“凭医师处方销售” \n \n三、常见OTC药类型\n \n1. 解热镇痛药：布洛芬、对乙酰氨基酚（缓解头痛、发热）。\n2. 感冒药：复方氨酚烷胺、伪麻黄碱（缓解鼻塞、咳嗽）。\n3. 消化系统药：健胃消食片、奥美拉唑（治疗胃酸过多、消化不良）。\n4. 维生素与矿物质：维生素C、钙尔奇（补充营养）。\n5. 外用药：皮炎平、云南白药（处理皮肤问题或外伤）。\n \n四、使用OTC药的注意事项\n \n1. 仔细阅读说明书：注意禁忌症、剂量和不良反应。\n2. 避免重复用药：多种复方药可能含相同成分（如对乙酰氨基酚），过量易伤肝。\n3. 特殊人群慎用：孕妇、哺乳期女性、慢性病患者需咨询医生。\n4. 不滥用抗生素：抗生素属于处方药，不可自行购买（如阿莫西林）。\n5. 及时就医：若症状未缓解或加重，应停止用药并寻求专业帮助。\n \n五、中国OTC药分类\n \n- 红色OTC：需在药师指导下购买，安全性稍低（如部分感冒药）。\n- 绿色OTC：可自行购买，安全性更高（如维生素、部分外用药）。\n \n总结\n \nOTC药为日常小病提供便利，但需理性使用，避免盲目依赖。若症状复杂或持续，建议及时就医，由专业医生判断治疗方案。",
  "生活科普/打针和注射原理.md": "打针一般是指将药物通过注射器注入人体，主要有肌肉注射、静脉注射和皮下注射等方式，其原理如下：\n \n**肌肉注射**\n \n- 吸收原理：肌肉组织有丰富的毛细血管网。药物注入肌肉后，先存在于肌肉组织间隙，然后依靠浓度梯度，通过毛细血管壁的内皮细胞间隙等途径，扩散进入毛细血管，进而进入血液循环，随血液运输到全身各处发挥药效。\n- 优势：可使药物缓慢释放，维持较长时间的药效。像一些抗生素类药物采用肌肉注射，能在一定时间内持续发挥抗菌作用。\n \n**静脉注射**\n \n- 吸收原理：直接将药物注入静脉血管内，药物会迅速与血液混合，随血液循环快速到达全身各个组织器官，能快速发挥药效。\n- 优势：适用于危急重症患者，如在抢救休克患者时，通过静脉注射血管活性药物等，能迅速提升血压等，挽救生命。也可用于需要大量补液或输入刺激性较强药物的情况，因为血液能快速稀释药物，减少药物对局部组织的刺激。\n \n**皮下注射**\n \n- 吸收原理：皮下组织有疏松的结缔组织和少量脂肪，也有一定的血管分布。药物注入皮下后，在组织液中溶解，然后通过毛细血管内皮细胞的吞饮、扩散等方式进入血液循环，吸收速度相对较慢。\n- 优势：常用于需要缓慢吸收、持续发挥作用的药物，如胰岛素。患者可在家中自行进行皮下注射，方便糖尿病患者日常控制血糖。\n \n打针时需严格遵循无菌操作原则，根据药物性质、患者病情等选择合适的注射方式、部位和剂量，以确保治疗效果和患者安全。",
  "生活科普/高铁座位.md": "高铁ABC座位的排列因座位类型而异：\n \n- **二等座**：采用“3+2”式排列，从左到右依次是A、B、C、D、F。其中A、B、C为三人座，A靠窗，B在中间，C靠过道。\n​\n- **一等座**：采用“2+2”式排列，从左到右依次是A、C、D、F。A和C是连座，A靠窗，C靠过道。\n​\n- **商务座**：通常采用“2+1”或“1+1”式排列，座位从左到右依次是A、C、F或A、F。采用“2+1”布局时，A靠窗，C靠过道。",
  "生物学科普/抗生素杀菌原理及作用机制详解.md": "抗生素主要通过干扰细菌的关键生命过程来杀灭或抑制其生长，其核心原理是**选择性毒性**——针对细菌特有的结构或代谢途径，而对人体细胞影响较小。以下是主要的杀菌原理分类及作用机制：\n\n---\n\n### **一、抑制细胞壁合成（对细菌最致命）**\n细菌细胞壁主要由**肽聚糖（Peptidoglycan）**构成，人体细胞无此结构。\n- **β-内酰胺类**（青霉素、头孢菌素）：\n  - 阻断**转肽酶**（青霉素结合蛋白，PBPs），抑制肽聚糖链的交联 → 细胞壁缺损。\n  - 结果：细菌在渗透压下破裂（溶菌）。\n- **万古霉素**：\n  - 直接结合肽聚糖前体（D-丙氨酰-D-丙氨酸），阻止其整合到细胞壁骨架。\n- **杆菌肽**：\n  - 干扰细胞膜上**脂质载体（ bactoprenol）**的再生，阻碍肽聚糖前体转运。\n\n> ⚠️ **特点**：对生长旺盛的细菌效果最强，对休眠菌无效。\n\n---\n\n### **二、破坏细胞膜完整性**\n直接攻击细菌特有的膜结构（如革兰阴性菌外膜）。\n- **多黏菌素类**：\n  - 带正电荷的分子与膜磷脂结合 → 膜通透性增加 → 内容物泄漏。\n- **达托霉素**（抗革兰阳性菌）：\n  - 插入细胞膜形成离子通道 → 钾离子外流 → 细胞死亡。\n\n---\n\n### **三、抑制蛋白质合成（靶向细菌核糖体）**\n细菌核糖体为**70S**（由50S+30S亚基组成），人体为80S。\n- **30S亚基抑制剂**：\n  - **氨基糖苷类**（链霉素、庆大霉素）：\n    - 结合30S亚基 → 错误读取mRNA → 合成错误蛋白；同时阻断起始复合物形成。\n  - **四环素类**：\n    - 阻断tRNA进入A位 → 阻止氨基酸添加。\n- **50S亚基抑制剂**：\n  - **大环内酯类**（红霉素、阿奇霉素）：\n    - 阻断肽链延伸（肽酰转移酶中心）。\n  - **氯霉素**：\n    - 抑制肽酰转移酶 → 阻止肽键形成。\n  - **林可酰胺类**（克林霉素）：\n    - 与50S亚基结合，抑制转肽反应。\n\n> ✅ **选择性**：因核糖体结构差异，对真核细胞影响小。\n\n---\n\n### **四、抑制核酸（DNA/RNA）合成**\n- **喹诺酮类**（环丙沙星、左氧氟沙星）：\n  - 抑制**DNA旋转酶（拓扑异构酶Ⅱ）** → DNA无法解旋复制 → 细菌死亡。\n- **利福平**：\n  - 结合**RNA聚合酶**β亚基 → 阻断mRNA转录。\n\n---\n\n### **五、干扰叶酸代谢**\n细菌需自行合成叶酸（人体直接从食物获取）。\n- **磺胺类** & **甲氧苄啶（TMP）**：\n  - 磺胺：竞争性抑制**二氢蝶酸合酶**（以PABA为底物）。\n  - TMP：抑制**二氢叶酸还原酶** → 阻断四氢叶酸合成。\n  - 结果：核苷酸合成受阻 → 细菌生长停滞（抑菌）。\n\n---\n\n### **六、抗结核分枝杆菌的特效药**\n- **异烟肼（INH）**：抑制分枝菌酸合成（结核杆菌细胞壁关键成分）。\n- **乙胺丁醇**：干扰阿拉伯半乳聚糖合成（细胞壁组分）。\n\n---\n\n### **关键概念：杀菌 vs 抑菌**\n| **类型**       | 代表药物                  | 作用特点                     |\n|----------------|--------------------------|----------------------------|\n| **杀菌剂**     | 青霉素、氨基糖苷类       | 直接杀死细菌                |\n| **抑菌剂**     | 四环素、磺胺类           | 抑制生长，依赖免疫系统清除  |\n| **浓度依赖性** | 氨基糖苷类、喹诺酮类     | 浓度越高杀菌越快           |\n| **时间依赖性** | β-内酰胺类、万古霉素     | 需维持有效血药浓度时间     |\n\n---\n\n### **为什么抗生素不伤害人体细胞？**\n1. **靶点差异**：如细胞壁、70S核糖体、叶酸合成酶为细菌特有。\n2. **代谢途径差异**：细菌需自主合成叶酸，人类可从食物获取。\n3. **选择性渗透**：部分药物难以穿透人体细胞膜。\n\n---\n\n### **耐药性警示**\n过度使用抗生素会导致细菌通过**基因突变**、**产生灭活酶**（如β-内酰胺酶）、**改变靶点**等方式产生耐药性。",
  "生物学科普/死亡后的尸体现象与死亡时间推断.md": "\n## 一、早期尸体现象\n\n早期变化通常发生在**死亡后数小时至两天内**，主要包括：\n\n### 1. 尸冷（Algor mortis）\n\n- **机制**：死亡后产热停止，体温逐渐下降，直至与环境温度一致。\n    \n- **一般规律**：\n    \n    - 室内常温：每小时约下降 **0.83℃**。\n        \n    - 水中：每小时下降 **3-4℃**。\n        \n    - 高温环境（如沙漠）：尸温可能不降反升。\n        \n    - 冬季：下降速度更快，可超过 **1℃/h**。\n        \n- **经验公式**：\n    \n    ```\n    死后时间（小时）= (37℃ - 直肠温度) ÷ 0.83 × 系数\n    系数：春秋=1；夏季=1.4；冬季=0.7\n    ```\n    \n\n### 2. 尸僵（Rigor mortis）\n\n- **机制**：肌肉内ATP耗竭，肌纤维固定。\n    \n- **时间规律**：\n    \n    - 30分钟～2小时：开始出现。\n        \n    - 6～8小时：全身僵硬。\n        \n    - 12～15小时：达到高峰。\n        \n    - 24～36小时：逐渐缓解并消失。\n        \n- **影响因素**：环境温度（高温→加快）、死前剧烈活动。\n    \n\n### 3. 尸斑（Livor mortis）\n\n- **机制**：血液因重力下沉，淤积于低垂部位。\n    \n- **时间规律**：\n    \n    - 30分钟内：可见淡红色。\n        \n    - 5～6小时：明显，按压可消退。\n        \n    - 8小时后：血红蛋白渗入组织，颜色固定，不再随体位改变。\n        \n- **特殊表现**：\n    \n    - 中毒：一氧化碳中毒呈鲜红色。\n        \n    - 冻死：尸斑呈红色。\n        \n\n### 4. 其他早期指标\n\n- **角膜混浊**：8～12小时出现。\n    \n- **胃内容物消化情况**：饭后2–4小时消化明显，可作为辅助判断。\n    \n- **尸绿**：腹部皮肤变绿，多在死亡2～3天后出现。\n    \n\n---\n\n## 二、晚期尸体现象\n\n当死亡超过**数天至数周**，进入晚期变化。\n\n### 1. 腐败（Putrefaction）\n\n- **起始**：2–3天内出现腹部尸绿，随后扩散全身。\n    \n- **典型表现**：\n    \n    - 5–7天：气体产生，颜面肿胀，口鼻流出液体。\n        \n    - 数周：软组织液化，最后仅剩骨骼。\n        \n- **白骨化**：土中一般需7–10年。\n    \n\n### 2. 动物破坏\n\n- 苍蝇产卵→蛆→蛹→成蝇。\n    \n- 夏季1个月内可能食尽软组织。\n    \n- 蚂蚁、鼠类、犬猫等亦可造成破坏。\n    \n\n### 3. 保存现象\n\n- **尸蜡（adipocere）**：潮湿缺氧环境，1–2月起始，数月至1年可广泛形成。\n    \n- **木乃伊化**：干燥环境下数月后形成。\n    \n\n---\n\n## 三、死亡时间推断方法\n\n### 1. 基于尸体现象\n\n- **尸温下降**：常用于**12小时内**。\n    \n- **尸斑与尸僵**：用于**48小时内**的判断。\n    \n- **腐败与昆虫学**：适用于**数日以上**。\n    \n\n### 2. 胃肠道内容物\n\n- 餐后 0–2h：胃内充满食物。\n    \n- 餐后 2–4h：食物进入十二指肠。\n    \n- 餐后 6h 以上：胃已排空。\n    \n\n### 3. 法医昆虫学\n\n- 苍蝇卵：死亡后几小时即产卵。\n    \n- 蛆成熟：4–15天。\n    \n- 蛹壳存在：提示**死后约2周以上**。\n    \n\n### 4. 超生反应\n\n- **死后肌肉反应**：2小时内仍可有收缩。\n    \n- **瞳孔反应**：4小时内可见药物作用反应。\n    \n- **汗腺反应**：18–24小时可见，30小时后消失。\n    \n\n---\n\n## 四、腐败进程（时间线）\n\n- **2–3天**：腹部尸绿、轻度膨胀。\n    \n- **5–6天**：腹部膨胀显著、皮肤水泡。\n    \n- **2周**：腹部极度膨胀。\n    \n- **3–4周**：组织液化，五官难辨。\n    \n- **数月**：尸蜡或木乃伊。\n    \n- **数年**：白骨化。\n    \n\n---\n\n# 总结\n\n- **短期（<48小时）**：尸冷、尸斑、尸僵为主要依据。\n    \n- **中期（数日至数周）**：依赖腐败程度与昆虫学。\n    \n- **长期（数月–数十年）**：尸蜡、木乃伊与白骨化作为参考。\n    \n\n死亡时间的推断需**综合多种因素**：尸体现象、环境温度、衣物覆盖、胃内容物及现场条件，不能依赖单一指标。\n\n---\n",
  "编程语言/Android/Linux配置安卓Gradle构建环境.md": "\n---\n\n## ⭐ 概览\n\n目标：在 Debian 12 上搭建可以 **本地编译 Android 原生 APK** 的环境，包含：\n\n- ✅ OpenJDK (推荐 17)\n    \n- ✅ Android SDK 命令行工具（cmdline-tools）\n    \n- ✅ Platform tools（adb）与 build-tools、platforms\n    \n- ✅ 可选：NDK / CMake（用于原生 C/C++）\n    \n- ✅ Gradle（用于构建）\n    \n\n适用场景：CI、无 GUI 的服务器、或仅需命令行编译的开发环境。\n\n---\n\n## 🧾 前置条件\n\n- 一台运行 **Debian 12** 的机器（有 sudo 权限）\n    \n- 稳定的网络（用于下载 SDK 与工具）\n    \n- 建议至少 10GB 可用磁盘空间（SDK + 系统镜像可能占用）\n    \n\n---\n\n## 1️⃣ 安装基础工具\n\n先更新并安装基础依赖：\n\n```bash\nsudo apt update\nsudo apt install -y git unzip wget curl zip build-essential\n```\n\n这些工具用于下载、解压、构建等。\n\n---\n\n## 2️⃣ 安装 JDK（推荐：OpenJDK 17）\n\nAndroid Gradle Plugin（AGP）对 JDK 有版本要求，JDK 17 是安全选择：\n\n```bash\nsudo apt install -y openjdk-17-jdk\n```\n\n检查版本：\n\n```bash\njava -version\n# 期望输出类似：openjdk version \"17.x\"\n```\n\n---\n\n## 3️⃣ 下载并安装 Android SDK 命令行工具\n\n去 Google 官方下载 `commandlinetools` 压缩包，或者用 wget（示例）：\n\n```bash\nmkdir -p $HOME/Android/cmdline-tools\ncd $HOME/Android/cmdline-tools\nwget https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip -O cmdline-tools.zip\nunzip cmdline-tools.zip\n# 有时解压出来的目录名是 cmdline-tools，移动或重命名为 latest：\nmv cmdline-tools latest\n```\n\n> 🔔 注意：实际下载链接和版本会随时间变化，请按需到 Android 官方网站获取最新版。\n\n---\n\n## 4️⃣ 配置环境变量（推荐写入 `~/.bashrc` 或 `~/.zshrc`）\n\n将 SDK 路径加入环境变量，保证 `sdkmanager`、`adb` 等工具可用：\n\n```bash\n# 在 ~/.bashrc 或 ~/.zshrc 添加：\nexport ANDROID_HOME=$HOME/Android\nexport ANDROID_SDK_ROOT=$ANDROID_HOME\nexport PATH=$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$PATH\n\n# 使之生效：\nsource ~/.bashrc\n```\n\n---\n\n## 5️⃣ 使用 sdkmanager 安装常用组件\n\n通过 `sdkmanager` 安装 `platform-tools`、指定 Android 平台与 build-tools：\n\n```bash\nsdkmanager --sdk_root=$ANDROID_HOME \"platform-tools\" \"platforms;android-34\" \"build-tools;34.0.0\"\n```\n\n可选安装（若需要 NDK / CMake 编译原生代码）：\n\n```bash\nsdkmanager \"ndk;26.1.10909125\" \"cmake;3.22.1\"\n```\n\n如果是自动接受许可，可以使用：\n\n```bash\nyes | sdkmanager --licenses\n```\n\n---\n\n## 6️⃣ 安装 Gradle（可选：系统级）\n\nAndroid 项目通常随 Gradle Wrapper（`gradlew`）一起提供，能自动下载合适版本。但若想系统安装：\n\n```bash\nwget https://services.gradle.org/distributions/gradle-8.7-bin.zip -P /tmp\nsudo unzip -d /opt/gradle /tmp/gradle-8.7-bin.zip\n# 添加到 PATH（写入 ~/.bashrc）：\nexport PATH=/opt/gradle/gradle-8.7/bin:$PATH\n```\n\n检查：\n\n```bash\ngradle -v\n```\n\n---\n\n## 7️⃣ 创建或获取一个示例 Android 项目并编译\n\n如果你已经有一个项目，进入项目目录并使用 Gradle Wrapper：\n\n```bash\n# 如果项目有 gradlew：\n./gradlew assembleDebug\n\n# 编译成功后 APK 通常位于：\napp/build/outputs/apk/debug/app-debug.apk\n```\n\n如果想新建一个空项目，可先使用 Android Studio 在本地创建（GUI 更方便），或直接从 GitHub 上的模板克隆一个样例工程。\n\n---\n\n## 8️⃣ 将 APK 部署到设备或模拟器（可选）\n\n- 真机（需开启 USB 调试）：\n    \n\n```bash\nadb install -r app/build/outputs/apk/debug/app-debug.apk\n```\n\n- 模拟器：需要安装 emulator 与系统镜像（`system-images`），并创建 AVD。命令行使用 `avdmanager` / `emulator`。\n    \n\n---\n\n## 9️⃣ 常见问题 & 排查建议 ❗\n\n- `sdkmanager` 找不到：确认 PATH 是否包含 `$ANDROID_HOME/cmdline-tools/latest/bin`。\n    \n- `java` 版本不对：Gradle/AGP 可能需要特定 JDK 版本，查看项目 `gradle.properties` / `build.gradle` 推荐的版本。\n    \n- 下载慢或失败：考虑使用代理或镜像（国内网络环境常见）。\n    \n- 权限问题：若在 `/opt` 等系统目录解压安装，需 `sudo`。\n    \n\n---\n\n## 🔁 推荐一键脚本（示例）\n\n下面给出一个**示例脚本**的框架（**请先审阅再运行**，并根据需要改版本号）：\n\n```bash\n#!/usr/bin/env bash\nset -e\n\n# 安装基础工具\nsudo apt update\nsudo apt install -y git unzip wget curl zip build-essential openjdk-17-jdk\n\n# 目录\nSDK_ROOT=$HOME/Android\nmkdir -p $SDK_ROOT/cmdline-tools\ncd $SDK_ROOT/cmdline-tools\n\n# 下载命令行工具（请确认链接是否过期）\nwget https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip -O cmdline-tools.zip\nunzip -o cmdline-tools.zip\nmv cmdline-tools latest || true\n\n# 环境变量（仅本次会话）\nexport ANDROID_HOME=$SDK_ROOT\nexport PATH=$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$PATH\n\n# 安装 SDK 组件\nyes | sdkmanager --sdk_root=$ANDROID_HOME \"platform-tools\" \"platforms;android-34\" \"build-tools;34.0.0\"\n\necho \"安装完成，请将下列行加入你的 ~/.bashrc 或 ~/.zshrc：\"\necho \"export ANDROID_HOME=\\$HOME/Android\"\necho \"export PATH=\\$ANDROID_HOME/cmdline-tools/latest/bin:\\$ANDROID_HOME/platform-tools:\\$PATH\"\n```\n\n---\n\n## 🔗 参考 & 延伸阅读\n\n- Android 官方开发者网站（SDK / command line tools）\n    \n- Gradle 官方文档\n    \n- Android NDK 文档（若使用原生 C/C++）\n    \n\n> 上面链接建议直接在浏览器打开 Android 官方站点获取最新版工具和镜像。\n\n---\n\n## ✅ 小结\n\n在 Debian 12 上搭建 Android 原生构建环境的要点：\n\n- 安装合适的 **JDK（推荐 17）**\n    \n- 下载并配置 **Android SDK command-line tools**，并通过 `sdkmanager` 安装 `platform-tools`、`platforms` 与 `build-tools`\n    \n- 使用项目自带的 **Gradle Wrapper (`gradlew`)** 进行构建，必要时可系统安装 Gradle\n    \n- 如需本地编译原生代码，记得安装 **NDK / CMake**\n    \n\n---\n",
  "编程语言/Android/安卓Gradle构建常用命令总结.md": "\n\n##### **基础**\n\n- `./gradlew tasks`  \n    列出可用的 Gradle 任务（查看当前项目能跑什么任务）。\n    \n- `./gradlew dependencies`  \n    列出项目依赖树（排查依赖冲突很有用）。\n    \n- `./gradlew clean`  \n    清理构建产物（删除 `build/` 目录）。\n    \n\n##### **构建 APK / AAB**\n\n- `./gradlew assembleDebug`  \n    构建 debug APK（输出：`app/build/outputs/apk/debug/*.apk`）。\n    \n- `./gradlew assembleRelease`  \n    构建 release APK（需签名配置，否则生成 unsigned apk）。\n    \n- `./gradlew bundleRelease`  \n    生成 AAB（Android App Bundle），输出：`app/build/outputs/bundle/release/*.aab`。\n    \n- `./gradlew bundleDebug`  \n    生成 debug bundle（少用，通常用于测试）。\n    \n\n##### **按 module / productFlavor / buildType 构建**\n\n- `./gradlew :moduleName:assembleRelease`  \n    构建指定 module（多模块项目时用）。\n    \n- `./gradlew assembleFlavorNameRelease`  \n    构建指定 flavor + buildType（例如 `assemblePaidRelease`）。\n    \n\n##### **安装与卸载**\n\n- `./gradlew installDebug`  \n    将 debug APK 安装到连接的设备/模拟器（需要 adb 可用）。\n    \n- `./gradlew uninstallDebug`  \n    从设备卸载 debug 包。\n    \n- 如果用生成的 APK 手动安装：`adb install -r app/build/outputs/apk/debug/app-debug.apk`\n    \n\n##### **测试**\n\n- 单元测试（JVM）：`./gradlew test` 或 `./gradlew testDebugUnitTest`\n    \n- 仪器/设备测试（connected devices）：`./gradlew connectedAndroidTest` 或 `./gradlew connectedCheck`\n    \n\n##### **静态检查 / 报表**\n\n- `./gradlew lint` 或 `./gradlew lintDebug`  \n    运行 Android Lint。\n    \n- `./gradlew signingReport`  \n    输出签名信息（SHA1/SHA256），常用于配置 API key（Google/Firebase）。\n    \n\n##### **调试构建问题的常用参数**\n\n- `--stacktrace` / `--full-stacktrace`：打印堆栈跟踪（排错用）\n    \n- `--info` / `--debug`：更详细的日志级别\n    \n- `--scan`：生成构建扫描（需要网络，便于深入分析）\n    \n- `--no-daemon`：不使用 Gradle daemon（CI 时有时会用）\n    \n- `--parallel`：并行构建模块（能加速多模块项目）\n    \n- `-x test`：跳过测试（例如 `./gradlew assembleRelease -x test`）\n    \n- `--offline`：离线构建（只用缓存依赖）\n    \n- `--refresh-dependencies`：刷新依赖缓存\n    \n\n##### **性能 / CI 常用组合示例**\n\n- 本地快速一把：`./gradlew clean assembleDebug --parallel --info`\n    \n- CI (不使用 daemon，输出详细)：`./gradlew clean assembleRelease --no-daemon --stacktrace -x test`\n    \n- 只构建 moduleA 的 release：`./gradlew :moduleA:assembleRelease`\n    \n\n##### **常见路径**\n\n- APK：`app/build/outputs/apk/<buildType|flavor>/...`\n    \n- AAB：`app/build/outputs/bundle/<buildType>/...`\n    \n- 临时构建缓存：`~/.gradle/caches/`\n    \n\n##### **小贴士**\n\n- 始终用项目里的 Gradle Wrapper（`./gradlew`），保证 Gradle 版本一致。\n    \n- Release 构建需要正确的 `signingConfig`（通常放在 `gradle.properties` + `build.gradle`），也可以在 CI 用 `-P` 传参数（注意不要把敏感信息放在日志里）。\n    \n- 出问题先加 `--stacktrace --info` 看详情，再定位是依赖、ProGuard/R8、签名还是资源冲突。\n",
  "编程语言/C/C 代码概述：检查特定条件的素数.md": "# C 代码概述：检查特定条件的素数\r\n\r\n## 功能描述\r\n该程序对给定的整数范围内的每个整数进行检查，计算一个特定的函数，并判断该函数的结果是否为素数。\r\n\r\n## 主要组成部分\r\n\r\n### 1. `is_prime` 函数\r\n- **输入**: 一个整数 `n`\r\n- **输出**: 如果 `n` 是素数，返回 `1`，否则返回 `0`。\r\n- **逻辑**:\r\n  - 如果 `n` 小于或等于 1，返回 `0`。\r\n  - 通过循环检查从 `2` 到 `√n` 的所有整数，判断 `n` 是否可被整除。\r\n  \r\n### 2. `main` 函数\r\n- **输入**: 从标准输入读取两个整数 `x` 和 `y`，直到输入为 `0 0`。\r\n- **逻辑**:\r\n  - 使用 `x` 和 `y` 定义的范围内进行迭代。\r\n  - 计算 `f = i * i + i + 41`。\r\n  - 调用 `is_prime` 函数检查 `f` 是否为素数：\r\n    - 如果发现任意 `f` 不是素数，输出 `\"Sorry\"` 并停止进一步检查。\r\n    - 如果所有 `f` 都是素数，最终输出 `\"OK\"`。\r\n\r\n## 使用示例\r\n- **输入**:\r\n    ```\r\n    1 5\r\n    0 0\r\n    ```\r\n- **输出**:\r\n    ```\r\n    Sorry\r\n    ```\r\n\r\n## 注意事项\r\n- 如果输入为 `0 0`，程序会终止。\r\n- 当范围内某个 `f` 不是素数时，输出 `\"Sorry\"`，并不再继续检查后续数字。\r\n\r\n\r\n\r\n\r\n\r\n```c\r\n#include <stdio.h>\r\n\r\nint is_prime(int n) {\r\n    if (n <= 1) return 0; \r\n    for (int i = 2; i * i <= n; i++) {\r\n        if (n % i == 0) return 0; \r\n    }\r\n    return 1; \r\n}\r\n\r\nint main() {\r\n    int x, y;\r\n    \r\n\r\n    while (scanf(\"%d %d\", &x, &y) != EOF) {\r\n        if (x == 0 && y == 0) break; \r\n        \r\n        int all_prime = 1; \r\n\r\n        for (int i = x; i <= y; i++) {\r\n            int f = i * i + i + 41; \r\n            if (!is_prime(f)) { \r\n                all_prime = 0; \r\n                printf(\"Sorry\\n\");\r\n                break; \r\n            }\r\n        }\r\n\r\n        if (all_prime) {\r\n            printf(\"OK\\n\"); \r\n        }\r\n    }\r\n    \r\n    return 0;\r\n}\r\n\r\n```\r\n\r\n",
  "编程语言/C/C语言不设置临时变量交换x和y的值（方法）.md": "# C语言不设置临时变量交换x和y的值（方法）\n\n```c\n#include <stdio.h>\n//异或\nint main() {\n    int x = 10, y = 20;\n    x = x ^ y;\n    y = x ^ y;\n    x = x ^ y;\n    printf(\"x的值为：%d，y的值为：%d\\n\", x, y);\n    return 0;\n}\n\n```\n\n```c\n#include <stdio.h>\n\nint main() {\n    int x = 10, y = 20;\n    x = x + y;\n    y = x - y;\n    x = x - y;\n    printf(\"x的值为：%d，y的值为：%d\\n\", x, y);\n    return 0;\n}\n\n```\n\n",
  "编程语言/C/代码片段/代码片段-标准HelloWorld输出.md": "```c\n#include <stdio.h>\n\nint main() {\n    printf(\"Hello, World!\\n\");\n    return 0;\n}\n```",
  "编程语言/C/代码片段/代码片段-特殊HelloWorld输出.md": "```c\n//不使用分号\n#include <stdio.h>\n\nint main() {\n    if (printf(\"Hello, World!\\n\")) {}\n}\n```",
  "编程语言/C++/C++中的语法糖.md": "C++中有不少语法糖，以下是一些常见的例子：\n \n范围-based for循环\n \n传统的 for 循环遍历容器需要使用迭代器，较为繁琐。范围 - based for循环则更简洁，例如：\n \n#include <iostream>\n#include <vector>\n\nint main() {\n    std::vector<int> v = {1, 2, 3, 4, 5};\n    for (int num : v) {\n        std::cout << num << \" \";\n    }\n    return 0;\n}\n \n \n初始化列表\n \n可以使用花括号初始化列表来初始化对象或容器，例如：\n \n#include <iostream>\n#include <vector>\n\nint main() {\n    // 用初始化列表初始化vector\n    std::vector<int> v = {1, 2, 3, 4, 5};\n    // 用初始化列表初始化自定义类对象\n    class MyClass {\n    public:\n        int num;\n        MyClass(int n) : num(n) {}\n    };\n    MyClass obj{10};\n    std::cout << obj.num << std::endl;\n    return 0;\n}\n \n \nauto关键字\n \n auto 关键字让编译器根据初始化表达式自动推导变量的类型，减少了类型声明的冗长，例如：\n \n#include <iostream>\n#include <vector>\n\nint main() {\n    std::vector<int> v = {1, 2, 3, 4, 5};\n    // 使用auto自动推导迭代器类型\n    for (auto it = v.begin(); it!= v.end(); ++it) {\n        std::cout << *it << \" \";\n    }\n    return 0;\n}\n \n \n模板别名\n \n通过 using 关键字定义模板别名，简化复杂的模板类型定义，例如：\n \n#include <iostream>\n#include <map>\n#include <string>\n\nint main() {\n    // 定义模板别名\n    using MyMap = std::map<std::string, int>;\n    MyMap myMap;\n    myMap[\"key\"] = 10;\n    std::cout << myMap[\"key\"] << std::endl;\n    return 0;\n}",
  "编程语言/C++/C++关联文件.md": "### 源文件\n\n-  **.cpp 或 .cxx 或 .cc ：**     C++源文件的扩展名，用于编写C++代码，包含函数、类、变量等定义和实现。\n-  **.h 或 .hpp 或 .hxx ：** 头文件扩展名，用于声明函数原型、类定义、常量和变量等，以便在多个源文件中共享声明。\n\n### 项目和配置文件\n\n-  **.vcxproj ：**Visual C++项目文件，用于Visual Studio开发环境，包含项目的配置信息、源文件列表、引用等。\n-  **.sln ：**解决方案文件，用于组织多个相关的项目，包含项目之间的依赖关系等信息。\n-  **CMakeLists.txt ：**使用CMake构建系统时的项目配置文件，用于描述项目的源文件、目标、依赖等信息，可生成不同平台和编译器的项目文件。\n-  **Makefile ：**在Unix和类Unix系统中，用于定义编译规则和目标，指定源文件如何编译链接成可执行文件或库。\n\n### 库文件\n\n-  **.lib ：**Windows下的静态库文件，包含已编译的代码和数据，在链接时被直接复制到可执行文件中。\n-  **.a ：**Unix和类Unix系统下的静态库文件，作用与Windows下的 .lib 类似。\n-  **.dll ：**Windows下的动态链接库文件，包含可在运行时被加载和调用的代码和数据。\n-  **.so ：**Unix和类Unix系统下的共享库文件，类似于Windows的 .dll ，在运行时动态链接。\n\n### 可执行文件\n\n-  **.exe ：**Windows下的可执行文件，是编译链接后的最终产物，可在操作系统中直接运行。\n- 在Unix和类Unix系统中，可执行文件没有特定的扩展名，但通常具有可执行权限，通过命令行或图形界面启动。",
  "编程语言/C++/C++模拟考试.md": "\r\n# 计算机二级 C++ 试题\r\n\r\n**考试时间：120 分钟**  \r\n**满分：100 分**\r\n\r\n> **说明：**  \r\n> 本试卷不涉及模板和智能指针，重点考查面向对象编程和简单算法的编程能力。\r\n\r\n---\r\n\r\n## 一、选择题 (共10题，每题2分，共20分)\r\n\r\n1. 关于 C++ 的面向对象特性，下列描述正确的是：  D\r\n   A. 封装使得数据与对数据的操作组合在一起  \r\n   B. 继承支持代码复用  \r\n   C. 多态允许同一操作在不同对象上表现出不同的行为  \r\n   D. 以上全部\r\n\r\n2. 在 C++ 中，class的默认访问权限是：  C\r\n   A. public  \r\n   B. protected  \r\n   C. private  \r\n   D. 无默认权限\r\n\r\n3. 当类中存在虚函数时，运行时调用哪个函数版本取决于：  A\r\n   A. 指针或引用所指对象的实际类型  \r\n   B. 指针或引用的类型  \r\n   C. 编译时绑定  \r\n   D. 函数的参数列表\r\n\r\n4. 如果希望禁止类对象的拷贝，通常的做法是：  C\r\n   A. 不提供拷贝构造函数和赋值运算符  \r\n   B. 将拷贝构造函数和赋值运算符声明为私有  \r\n   C. 使用 const 修饰所有成员变量  \r\n   D. 以上都不正确\r\n\r\n5. 在 C++ 中，struct的默认访问权限是：  A\r\n   A. public  \r\n   B. protected  \r\n   C. private  \r\n   D. 无默认权限\r\n\r\n6. 以下哪条语句正确包含了 iostream 头文件？  C\r\n   A. `#import <iostream>`  \r\n   B. `#include iostream`  \r\n   C. `#include <iostream>`  \r\n   D. `using namespace std;`  \r\n\r\n7. 在 C++ 中，下列哪个运算符用于获取变量的地址？  A\r\n   A. &  \r\n   B. *  \r\n   C. ->  \r\n   D. %  \r\n\r\n8. 以下哪一项是正确的函数声明？  B\r\n   A. `int func(int a, b);`  \r\n   B. `int func(int a, int b);`  \r\n   C. `func(int a, int b);`  \r\n   D. `int func(a, b);`  \r\n\r\n9. 下列选项中，哪一个不是 C++ 的访问控制符？  D\r\n   A. public  \r\n   B. private  \r\n   C. protected  \r\n   D. external  \r\n\r\n10. 关于 C++ 中的引用，以下说法正确的是：  A\r\n      A. 引用必须在定义时初始化  \r\n      B. 引用可以改变绑定的对象  \r\n      C. 引用可以为 NULL  \r\n      D. 引用占用额外的内存空间  \r\n\r\n---\r\n\r\n## 二、填空题 (共4题，每题2.5分，共10分)\r\n\r\n1. C++ 的面向对象三大特性是封装、______继承__ 和多态。  \r\n  \r\n2. 成员函数在类外定义时需要使用 ______::__ 运算符指定其所属的类。  \r\n  \r\n3. 如果一个函数在基类中声明为虚函数，那么在派生类中重写该函数时可以选择在函数声明后加上 ______override__ 关键字以提高代码可读性。  \r\n  \r\n4. 递归算法必须包含一个或多个 ______终止__ 条件，以确保递归能够终止。  \r\n\r\n---\r\n\r\n\r\n\r\n---\r\n\r\n## 三、代码分析题 (共2题，每题10分，共20分)\r\n\r\n\r\n### 题目1\r\n\r\n阅读下面的代码，并回答问题：\r\n\r\n```cpp\r\n#include <iostream>\r\nusing namespace std;\r\n\r\nvoid modifyPointer(int *p) {\r\n    *p = 20;\r\n}\r\n\r\nint main() {\r\n    int a = 10;\r\n    int *ptr = &a;\r\n    \r\n    modifyPointer(ptr);\r\n    \r\n    cout << a << endl;\r\n    \r\n    return 0;\r\n}\r\n```\r\n1.程序的输出结果是什么？20\r\n2.解释指针 ptr 在 modifyPointer 函数调用过程中的作用，以及它对变量 a 的影响。指向a的地址 修改a的值\r\n\r\n\r\n### 题目2\r\n\r\n阅读下面的代码，并回答问题：\r\n\r\n```cpp\r\n#include <iostream>\r\nusing namespace std;\r\n\r\nclass A {\r\npublic:\r\n    A() {\r\n        cout << \"A Constructor\" << endl;\r\n    }\r\n    ~A() {\r\n        cout << \"A Destructor\" << endl;\r\n    }\r\n};\r\n\r\nclass B : public A {\r\npublic:\r\n    B() {\r\n        cout << \"B Constructor\" << endl;\r\n    }\r\n    ~B() {\r\n        cout << \"B Destructor\" << endl;\r\n    }\r\n};\r\n\r\nint main() {\r\n    B obj;\r\n    return 0;\r\n}\r\n```\r\n1.程序的输出结果是什么？\r\n\r\nA Constructor\r\n\r\nB Constructor\r\n\r\nB Destructor\r\n\r\nA Destructor\r\n\r\n2.解释下子类与父类的构造、析构函数的调用顺序。子类构造过了父类，子类析构过了父类\r\n\r\n## 四、编程题 (共3题，共40分)\r\n\r\n### 题目：基于继承与多态的学生管理系统设计 — 10分\r\n\r\n**要求：**  \r\n- 定义一个基类 `Person`，包含下列内容：\r\n  - **保护成员**：姓名（`string`）\r\n  - 构造函数：用于初始化姓名\r\n  - **虚函数** `display()`：用于输出人员的基本信息\r\n- 定义一个派生类 `Student`，继承自 `Person`，并添加下列私有成员：\r\n  - 学号（`int`）\r\n  - 成绩（`float`）\r\n- 在 `Student` 类中，重写基类中的 `display()` 函数，输出学生的姓名、学号和成绩。\r\n- 在 `main()` 函数中，创建至少两个 `Student` 对象，并使用基类 `Person` 类型的指针调用 `display()` 函数，体现虚函数的多态特性。\r\n- 注意：请确保在基类中定义虚析构函数，以便正确释放派生类对象，请填充下面的代码实现。\r\n\r\n**示例代码：**\r\n```cpp\r\n#include <iostream>\r\n#include <string>\r\nusing namespace std;\r\n\r\n// 基类 Person，包含姓名和虚函数 display()\r\nclass Person {\r\n    protected:\r\n        string name;\r\n    public:\r\n\r\n        Person(string n, int i, float g){\r\n            name = n;\r\n        }\r\n\r\n        virtual void display(){\r\n\r\n        }\r\n};\r\n\r\n// 派生类 Student，继承自 Person，并添加学号和成绩\r\nclass Student :public Person {\r\n    private:\r\n        int id;\r\n        float grade;\r\n\r\n    public:\r\n        Student(string n,int i,float g) override{\r\n            name =n;\r\n            id = i;\r\n            grade = g;\r\n        }\r\n\r\n        virtual void display() override{\r\n            cout<<\"学生的姓名：\"<<name<<endl;\r\n            cout<<\"学生的学号：\"<<id<<endl;\r\n            cout<<\"学生的成绩\"<<grade<<endl;\r\n        }\r\n\r\n\r\n};\r\n\r\nint main() {\r\n    // 使用基类指针，体现多态性\r\n    Person* p1 = new Student(\"张三\", 1001, 88.5);\r\n    Person* p2 = new Student(\"李四\", 1002, 92.0);\r\n\r\n    p1->display();\r\n    p2->display();\r\n\r\n    // 释放内存\r\n    delete p1;\r\n    delete p2;\r\n    \r\n    return 0;\r\n}\r\n```\r\n\r\n\r\n---\r\n\r\n### 题目2：递归实现二分查找  — 20分\r\n\r\n**要求：**  \r\n- 编写一个 C++ 程序，使用递归实现二分查找算法，在一个有序的整数数组中查找目标值。  \r\n- 程序应要求用户输入一个目标值，若目标值存在，则输出其在数组中的下标；否则输出 -1。  \r\n- 代码中应包含对输入数据的提示以及对边界条件的合理判断。\r\n\r\n**示例代码：**\r\n```cpp\r\n#include <iostream>\r\nusing namespace std;\r\n\r\n// 递归实现二分查找函数 请你填充此函数实现\r\nint binarySearch(int arr[], int left, int right, int target) {\r\n    while (left<=right){\r\n        int mid = left + (right-left)/2;\r\n        if(arr[mid]==target){\r\n            return mid;\r\n        }else if(arr[mid]<target){\r\n            left = mid +1;\r\n        }else{\r\n            right = mid -1;\r\n        }\r\n    }\r\n    return -1;\r\n    \r\n}\r\n\r\nint main() {\r\n    // 已排序的数组\r\n    int arr[] = {1, 3, 5, 7, 9, 11, 13, 15};\r\n    int n = sizeof(arr) / sizeof(arr[0]);\r\n    \r\n    int target;\r\n    cout << \"请输入要查找的目标值：\";\r\n    cin >> target;\r\n    \r\n    int index = binarySearch(arr, 0, n - 1, target);\r\n    if(index != -1) {\r\n        cout << \"目标值 \" << target << \" 在数组中的下标为：\" << index << endl;\r\n    } else {\r\n        cout << \"目标值 \" << target << \" 不在数组中。\" << endl;\r\n    }\r\n    return 0;\r\n}\r\n```\r\n\r\n---\r\n\r\n### 题目3：冒泡排序实现  — 10分\r\n\r\n**要求：**  \r\n- 编写一个 C++ 程序，定义一个整数数组，对数组进行冒泡排序。\r\n- 程序应先输出排序前的数组，再输出排序后的数组。\r\n- 代码要求体现出对冒泡排序核心思想的理解，结构清晰、注释明确，并注意边界情况的处理。\r\n\r\n**示例代码：**\r\n```cpp\r\n#include <iostream>\r\nusing namespace std;\r\n\r\n// 冒泡排序函数 请你填充这个函数\r\nvoid bubbleSort(int arr[], int n) {\r\n    for(int i=0;i<n-1;i++)\r\n        for(int j=0;j<n-1-i;j++){\r\n            if(arr[j]>arr[j+1]){\r\n                swap(arr[j],arr[j+1]);\r\n            }\r\n        }\r\n}\r\n\r\n// 打印数组函数\r\nvoid printArray(const int arr[], int n) {\r\n    for (int i = 0; i < n; i++) {\r\n        cout << arr[i] << \" \";\r\n    }\r\n    cout << endl;\r\n}\r\n\r\nint main() {\r\n    int arr[] = { 5, 3, 8, 6, 2, 7, 4, 1 };\r\n    int n = sizeof(arr) / sizeof(arr[0]);\r\n    \r\n    cout << \"排序前的数组：\" << endl;\r\n    printArray(arr, n);\r\n    \r\n    bubbleSort(arr, n);\r\n    \r\n    cout << \"排序后的数组：\" << endl;\r\n    printArray(arr, n);\r\n    \r\n    return 0;\r\n}\r\n```\r\n\r\n\r\n**注意事项：**  \r\n- 请仔细阅读每道题目的要求，确保在答题时详细阐述思路及关键实现步骤。  \r\n- 编程题请在本地编译测试确保代码正确无误。  \r\n\r\n祝各位考生考试顺利！",
  "编程语言/C++/C语言学习笔记.md": "## C语言学习笔记\r\n\r\n1.scanf()不能输入空格，用fgets可以解决这个问题，但fgets需要对回车进行处理\r\n\r\n```c\r\n    // 读取输入字符串\r\n    fgets(str, 81, stdin);\r\n\r\n    // 去除输入字符串中的换行符\r\n    int len = strlen(str);\r\n    if (str[len - 1] == '\\n') {\r\n        str[len - 1] = '\\0';\r\n    }\r\n```\r\n\r\n",
  "编程语言/C++/代码片段/代码片段-标准HelloWorld输出.md": "```cpp\n#include <iostream>\n\nint main() {\n    std::cout << \"Hello, World!\" << std::endl;\n    return 0;\n}\n```",
  "编程语言/C++/代码片段/代码片段-特殊HelloWorld输出.md": "```cpp\n//使用模板元编程\n#include <iostream>\n\ntemplate<int N>\nstruct Hello {\n    static void print() {\n        Hello<N-1>::print();\n        std::cout << \"Hello, World!\"[N-1];\n    }\n};\n\ntemplate<>\nstruct Hello<0> {\n    static void print() {}\n};\n\nint main() {\n    Hello<13>::print();\n    std::cout << std::endl;\n    return 0;\n}\n```",
  "编程语言/C++/值传递和地址传递的区别.md": "在编程中，函数调用时的数据传递方式主要分为值传递和地址传递（也称为引用传递，在 C++ 中还有引用类型专门用于引用传递），下面详细介绍它们的区别：\r\n\r\n### 基本概念\r\n- **值传递**：在函数调用时，将实际参数的值复制一份传递给形式参数。函数内部对形式参数的修改不会影响到实际参数。\r\n- **地址传递**：在函数调用时，将实际参数的内存地址传递给形式参数。函数内部通过该地址可以直接访问和修改实际参数所指向的内存空间中的值。\r\n\r\n### 语法示例\r\n以下是 C++ 语言中值传递和地址传递的示例代码：\r\n```cpp\r\n#include <iostream>\r\n\r\n// 值传递函数\r\nvoid valuePass(int num) {\r\n    num = num + 1;\r\n    std::cout << \"Inside valuePass, num: \" << num << std::endl;\r\n}\r\n\r\n// 地址传递函数（使用指针）\r\nvoid addressPass(int* numPtr) {\r\n    *numPtr = *numPtr + 1;\r\n    std::cout << \"Inside addressPass, *numPtr: \" << *numPtr << std::endl;\r\n}\r\n\r\nint main() {\r\n    int value = 10;\r\n\r\n    // 值传递调用\r\n    std::cout << \"Before valuePass, value: \" << value << std::endl;\r\n    valuePass(value);\r\n    std::cout << \"After valuePass, value: \" << value << std::endl;\r\n\r\n    // 地址传递调用\r\n    std::cout << \"Before addressPass, value: \" << value << std::endl;\r\n    addressPass(&value);\r\n    std::cout << \"After addressPass, value: \" << value << std::endl;\r\n\r\n    return 0;\r\n}\r\n```\r\n### 区别分析\r\n\r\n#### 1. 数据复制情况\r\n- **值传递**：会创建实际参数的副本，将副本传递给函数。这意味着在函数内部操作的是这个副本，而不是原始数据。例如上述代码中，`valuePass` 函数接收到的 `num` 是 `value` 的一个副本，对 `num` 的修改不会影响到 `main` 函数中的 `value`。\r\n- **地址传递**：不会复制实际参数的值，而是传递实际参数的地址。函数内部通过该地址直接访问和操作原始数据。如 `addressPass` 函数接收到的是 `value` 的地址，通过解引用操作可以直接修改 `value` 的值。\r\n\r\n#### 2. 内存开销\r\n- **值传递**：由于需要复制实际参数的值，对于大型数据结构（如大数组、大对象），会占用额外的内存空间，增加内存开销。\r\n- **地址传递**：只传递地址，无论实际参数的数据量多大，传递的地址通常只占用固定大小的内存空间（如在 32 位系统上指针通常占 4 字节，64 位系统上占 8 字节），内存开销较小。\r\n\r\n#### 3. 对实际参数的影响\r\n- **值传递**：函数内部对形式参数的修改不会影响到实际参数。在上述代码中，`valuePass` 函数执行完后，`main` 函数中的 `value` 值保持不变。\r\n- **地址传递**：函数内部对形式参数所指向的内存空间的修改会直接影响到实际参数。在 `addressPass` 函数中修改 `*numPtr` 的值，实际上就是修改了 `main` 函数中 `value` 的值。\r\n\r\n#### 4. 函数调用的安全性\r\n- **值传递**：由于函数内部操作的是副本，不会意外修改原始数据，因此在某些情况下可以保证数据的安全性。例如，当你不希望函数修改原始数据时，使用值传递是一个好选择。\r\n- **地址传递**：如果函数内部不小心对指针进行了错误的操作，可能会导致原始数据被意外修改，甚至可能引发内存错误（如空指针解引用、越界访问等）。\r\n\r\n#### 5. 代码可读性和可维护性\r\n- **值传递**：函数的行为相对简单，容易理解，因为它不会影响外部的实际参数。调用者可以清楚地知道函数内部不会修改传入的数据。\r\n- **地址传递**：使用地址传递可以在函数内部修改外部数据，这在某些情况下可以使代码更加简洁，但也可能会增加代码的复杂度，需要调用者更加小心地处理。",
  "编程语言/C++/变量使用set，get方法原因.md": "在面向对象编程中，不直接修改变量而使用get和set函数（通常称为访问器和修改器方法）有以下几个重要原因：\n \n数据封装\n \n- 将变量（通常称为成员变量或属性）通过get和set函数封装起来，可以隐藏类的内部实现细节。外部代码只能通过这些函数来访问和修改属性，而无法直接操作，这样可以避免外部代码对内部数据的随意访问和修改，增强了类的独立性和安全性。\n \n数据验证\n \n- 在set函数中，可以对要设置的值进行合法性验证。例如，一个表示人的年龄的属性，在set函数中可以添加逻辑来确保设置的年龄是一个合理的数值，防止出现负数或过大的不合理值，从而保证数据的完整性和正确性。\n \n控制访问权限\n \n- 通过get和set函数，可以更精确地控制对属性的访问权限。可以将某些属性设置为只读（只有get函数，没有set函数），或者只允许在特定条件下进行修改，这样可以更好地满足不同的业务需求。\n \n实现代码复用\n \n- 当需要对属性的访问或修改进行一些额外的操作时，比如记录属性的访问日志、在属性值变化时触发其他相关的操作等，只需要在get和set函数中添加相应的代码，而不需要在所有访问该属性的地方都进行修改，提高了代码的可维护性和复用性。\n \n便于代码扩展和维护\n \n- 如果未来需要对属性的存储方式或访问逻辑进行修改，只需要在get和set函数内部进行修改，而不会影响到外部调用代码，使得代码的扩展性和维护性更好。",
  "编程语言/C++/多个set方法.md": "当变量有多种 set 方法时，可以通过以下几种方式来处理：\n \n方法重载\n \n在支持方法重载的编程语言中，如Java、C#等，可以定义多个同名的 set 方法，但参数列表不同。例如，一个 set 方法可以接受一个整数参数来设置变量，另一个 set 方法可以接受一个字符串参数并根据字符串的内容来设置变量。\n \njava\n  \npublic class MyClass {\n    private int myVariable;\n\n    public void setMyVariable(int value) {\n        myVariable = value;\n    }\n\n    public void setMyVariable(String value) {\n        myVariable = Integer.parseInt(value);\n    }\n}\n \n \n不同的方法名\n \n如果方法的功能差异较大，也可以使用不同的方法名来表示不同的设置方式。比如，一个方法用于从文件中读取值来设置变量，另一个方法用于从网络获取值来设置变量，可以分别命名为 setVariableFromFile 和 setVariableFromNetwork 。\n \n使用参数标志或枚举\n \n可以在 set 方法中使用参数标志或枚举类型来区分不同的设置方式。例如，定义一个枚举类型来表示设置变量的不同来源，然后在 set 方法中根据传入的枚举值来执行不同的设置逻辑。\n \njava\n  \npublic class MyClass {\n    private int myVariable;\n\n    public enum SetSource {\n        FROM_FILE, FROM_NETWORK\n    }\n\n    public void setMyVariable(int value, SetSource source) {\n        if (source == SetSource.FROM_FILE) {\n            // 从文件设置变量的逻辑\n            myVariable = value;\n        } else if (source == SetSource.FROM_NETWORK) {\n            // 从网络设置变量的逻辑\n            myVariable = value;\n        }\n    }\n}\n \n \n这样可以根据不同的需求灵活选择合适的方式来设置变量，同时保持代码的清晰和可维护性。",
  "编程语言/C++/指针变量的区别.md": "在C和C++语言中，`int* a` 和 `int *a` 本质上没有区别，它们都表示定义了一个指向 `int` 类型数据的指针变量 `a`。以下是关于它们的详细说明：\r\n\r\n- **从语法角度看**：这两种写法都是合法的C和C++ 语法，用于声明一个指针变量。`*` 是指针声明符，用来表示后面的变量是一个指针。在这两种写法中，`*` 都与变量名 `a` 结合，表示 `a` 是一个指针，它可以存储一个 `int` 类型数据的内存地址。\r\n- **从阅读习惯和风格角度看**\r\n    - `int* a`：这种写法将 `*` 紧跟在类型名 `int` 后面，强调 `*` 是类型的一部分，即 `int*` 被视为一个整体，表示“指向 `int` 的指针”类型。这种写法在一些代码风格中更受欢迎，因为它使代码看起来更紧凑，类型定义更清晰，特别是在同时声明多个指针变量时，如 `int* a, *b, *c;`，可以很直观地看出 `a`、`b`、`c` 都是 `int` 型指针。\r\n    - `int *a`：这种写法将 `*` 靠近变量名 `a`，更加强调 `a` 是一个指针变量，`*` 是用来修饰 `a` 的。有些程序员更喜欢这种写法，因为它更突出了变量的性质是指针，在阅读代码时，更容易将注意力集中在变量 `a` 本身是一个指针这一事实上。\r\n\r\n虽然在功能上没有区别，但在实际使用中，可能会根据个人或团队的编程习惯和代码风格来选择使用哪种形式。需要注意的是，在同时声明多个变量时，如果采用 `int* a, b;` 的形式，会让人误以为 `b` 也是 `int` 型指针，但实际上 `b` 是一个普通的 `int` 型变量。为了避免这种混淆，更清晰的做法是每个指针变量都单独声明，如 `int* a; int* b;` 或者都采用 `int *a; int *b;` 的形式。\r\n",
  "编程语言/C++/指针简单讲解.md": "下面将详细介绍指针的核心内容，包括指针声明、指针运算、指针与数组的关系以及二级指针，并结合代码示例和内存图进行说明。\r\n\r\n### 1. 指针声明：`int *p` 的正确写法\r\n\r\n在 C 和 C++ 中，指针声明的语法是 `数据类型 *指针变量名`。`int *p` 是一个常见的声明方式，它声明了一个名为 `p` 的指针变量，该指针指向 `int` 类型的数据。以下是几种常见的写法及其含义：\r\n\r\n```c\r\n#include <stdio.h>\r\n\r\nint main() {\r\n    int num = 10;\r\n    // 写法一：常见写法\r\n    int *p1;\r\n    p1 = &num;\r\n    // 写法二：声明并初始化\r\n    int *p2 = &num;\r\n\r\n    printf(\"p1 指向的值: %d\\n\", *p1);\r\n    printf(\"p2 指向的值: %d\\n\", *p2);\r\n\r\n    return 0;\r\n}\r\n```\r\n\r\n### 2. 指针运算：`p++` 在不同类型下的地址变化\r\n\r\n指针运算主要包括指针的加减操作。当对指针进行 `p++` 操作时，指针会根据其所指向的数据类型的大小向前移动相应的字节数。以下是不同类型指针 `p++` 后的地址变化示例：\r\n\r\n```c\r\n#include <stdio.h>\r\n\r\nint main() {\r\n    int arr_int[3] = {1, 2, 3};\r\n    char arr_char[3] = {'a', 'b', 'c'};\r\n\r\n    int *p_int = arr_int;\r\n    char *p_char = arr_char;\r\n\r\n    printf(\"p_int 初始地址: %p\\n\", (void *)p_int);\r\n    p_int++;\r\n    printf(\"p_int 自增后地址: %p\\n\", (void *)p_int);\r\n\r\n    printf(\"p_char 初始地址: %p\\n\", (void *)p_char);\r\n    p_char++;\r\n    printf(\"p_char 自增后地址: %p\\n\", (void *)p_char);\r\n\r\n    return 0;\r\n}\r\n```\r\n\r\n在上述代码中，`int` 类型通常占 4 个字节，`char` 类型占 1 个字节。所以 `p_int++` 会使指针地址增加 4 个字节，而 `p_char++` 会使指针地址增加 1 个字节。\r\n\r\n### 3. 指针与数组：`arr[i]` 与 `*(arr + i)` 的等价性\r\n\r\n在 C 和 C++ 中，数组名本质上是一个指向数组首元素的常量指针。`arr[i]` 和 `*(arr + i)` 是完全等价的，它们都表示访问数组中第 `i` 个元素。以下是示例代码：\r\n\r\n```c\r\n#include <stdio.h>\r\n\r\nint main() {\r\n    int arr[5] = {1, 2, 3, 4, 5};\r\n\r\n    // 使用 arr[i] 访问元素\r\n    for (int i = 0; i < 5; i++) {\r\n        printf(\"arr[%d] = %d\\n\", i, arr[i]);\r\n    }\r\n\r\n    // 使用 *(arr + i) 访问元素\r\n    for (int i = 0; i < 5; i++) {\r\n        printf(\"*(arr + %d) = %d\\n\", i, *(arr + i));\r\n    }\r\n\r\n    return 0;\r\n}\r\n```\r\n\r\n### 4. 二级指针：画内存图理解指针的指针\r\n\r\n二级指针是指向指针的指针。通过二级指针，可以间接访问和修改另一个指针的值。以下是一个二级指针的示例代码，并给出对应的内存图解释。\r\n\r\n```c\r\n#include <stdio.h>\r\n\r\nint main() {\r\n    int num = 10;\r\n    int *p = &num;\r\n    int **pp = &p;\r\n\r\n    printf(\"num 的值: %d\\n\", num);\r\n    printf(\"p 指向的值: %d\\n\", *p);\r\n    printf(\"pp 间接指向的值: %d\\n\", **pp);\r\n\r\n    return 0;\r\n}\r\n```\r\n\r\n#### 内存图解释\r\n\r\n```plaintext\r\n+----------------+\r\n| 内存地址        | 变量名 | 存储内容\r\n+----------------+--------+-----------------\r\n| 0x1000          | num    | 10\r\n| 0x2000          | p      | 0x1000 (指向 num 的地址)\r\n| 0x3000          | pp     | 0x2000 (指向 p 的地址)\r\n+----------------+--------+-----------------\r\n```\r\n\r\n在这个内存图中，`num` 存储在地址 `0x1000` 处，值为 10。指针 `p` 存储在地址 `0x2000` 处，它指向 `num` 的地址 `0x1000`。二级指针 `pp` 存储在地址 `0x3000` 处，它指向 `p` 的地址 `0x2000`。通过 `*pp` 可以得到 `p` 的值（即 `num` 的地址），再通过 `**pp` 可以得到 `num` 的值。\r\n\r\n通过以上内容，你应该对指针的核心概念有了更深入的理解。指针是 C 和 C++ 中非常强大的特性，但也需要谨慎使用，避免出现内存错误。",
  "编程语言/C++/暂停1s执行.md": "以下是对上述代码的美化和精简版本：\n\n### 使用 `chrono` 和 `this_thread` 库\n```cpp\n#include <iostream>\n#include <chrono>\n#include <thread>\n\nint main() {\n    std::cout << \"开始\" << std::endl;\n    // 暂停1秒\n    std::this_thread::sleep_for(std::chrono::seconds(1));\n    std::cout << \"暂停1秒后执行\" << std::endl;\n    return 0;\n}\n```\n\n### 使用 `Sleep` 函数（Windows系统）\n```cpp\n#include <iostream>\n#include <windows.h>\n\nint main() {\n    std::cout << \"开始\" << std::endl;\n    // 暂停1秒，参数为1000毫秒\n    Sleep(1000);\n    std::cout << \"暂停1秒后执行\" << std::endl;\n    return 0;\n}\n```\n\n### 使用 `usleep` 函数（Unix/Linux系统）\n```cpp\n#include <iostream>\n#include <unistd.h>\n\nint main() {\n    std::cout << \"开始\" << std::endl;\n    // 暂停1秒，参数为1000000微秒\n    usleep(1000000);\n    std::cout << \"暂停1秒后执行\" << std::endl;\n    return 0;\n}\n```\n\n这些代码的结构更加清晰，注释保留以说明关键步骤，同时移除了不必要的空行，使代码更加简洁易读。 ",
  "编程语言/C++/标准库解析/algorithim库二次总结.md": "C++ 的 `<algorithm>` 头文件提供了许多高效的算法函数，以下是常用函数及示例：\n\n---\n\n### **1. 排序与查找**\n#### **`sort()`**：对容器排序\n```cpp\n#include <algorithm>\n#include <vector>\nusing namespace std;\n\nvector<int> v = {3, 1, 4, 1, 5};\nsort(v.begin(), v.end()); // 默认升序\n// v = {1, 1, 3, 4, 5}\n\n// 自定义排序：降序\nsort(v.begin(), v.end(), greater<int>());\n```\n\n#### **`binary_search()`**：二分查找（需已排序）\n```cpp\nif (binary_search(v.begin(), v.end(), 4)) {\n    cout << \"找到4!\" << endl;\n}\n```\n\n#### **`find()`**：查找元素\n```cpp\nauto it = find(v.begin(), v.end(), 3);\nif (it != v.end()) {\n    cout << \"找到3，位置：\" << it - v.begin() << endl;\n}\n```\n\n---\n\n### **2. 元素操作**\n#### **`reverse()`**：反转容器\n```cpp\nreverse(v.begin(), v.end()); // v = {5, 4, 3, 1, 1}\n```\n\n#### **`fill()`**：填充容器\n```cpp\nvector<int> vec(5);\nfill(vec.begin(), vec.end(), 10); // 全部填充为10\n```\n\n#### **`replace()`**：替换元素\n```cpp\nreplace(v.begin(), v.end(), 1, 99); // 将所有1替换为99\n```\n\n---\n\n### **3. 条件判断**\n#### **`count()`**：统计元素出现次数\n```cpp\nint cnt = count(v.begin(), v.end(), 1);\n```\n\n#### **`count_if()`**：按条件统计\n```cpp\nint even_cnt = count_if(v.begin(), v.end(), [](int x) {\n    return x % 2 == 0; // 统计偶数\n});\n```\n\n#### **`all_of()` / `any_of()`**：检查元素条件\n```cpp\nbool all_even = all_of(v.begin(), v.end(), [](int x) {\n    return x % 2 == 0;\n});\n```\n\n---\n\n### **4. 数值处理**\n#### **`max_element()` / `min_element()`**：找最大/最小值\n```cpp\nauto max_it = max_element(v.begin(), v.end());\ncout << \"最大值：\" << *max_it << endl;\n```\n\n#### **`accumulate()`**：累加（需 `<numeric>`）\n```cpp\n#include <numeric>\nint sum = accumulate(v.begin(), v.end(), 0); // 初始值为0\n```\n\n---\n\n### **5. 变换与生成**\n#### **`transform()`**：对每个元素操作\n```cpp\nvector<int> squared;\ntransform(v.begin(), v.end(), back_inserter(squared),\n          [](int x) { return x * x; });\n```\n\n#### **`generate()`**：生成新值填充容器\n```cpp\nvector<int> nums(5);\nint n = 0;\ngenerate(nums.begin(), nums.end(), [&n]() { return n++; });\n// nums = {0, 1, 2, 3, 4}\n```\n\n---\n\n### **6. 集合操作**\n#### **`unique()`**：去重（需先排序）\n```cpp\nsort(v.begin(), v.end());\nauto last = unique(v.begin(), v.end());\nv.erase(last, v.end()); // 删除重复项\n```\n\n#### **`merge()`**：合并两个有序序列\n```cpp\nvector<int> v1 = {1, 3, 5}, v2 = {2, 4, 6}, result(6);\nmerge(v1.begin(), v1.end(), v2.begin(), v2.end(), result.begin());\n// result = {1, 2, 3, 4, 5, 6}\n```\n\n---\n\n### **7. 分区与乱序**\n#### **`partition()`**：按条件分区\n```cpp\nauto it = partition(v.begin(), v.end(),\n                   [](int x) { return x % 2 == 0; });\n// 偶数在前，奇数在后\n```\n\n#### **`shuffle()`**：随机打乱（需 `<random>`）\n```cpp\n#include <random>\nshuffle(v.begin(), v.end(), default_random_engine());\n```\n\n---\n\n### **示例代码汇总**\n```cpp\n#include <iostream>\n#include <algorithm>\n#include <vector>\n#include <numeric>\nusing namespace std;\n\nint main() {\n    vector<int> v = {3, 1, 4, 1, 5};\n    \n    // 排序\n    sort(v.begin(), v.end());\n    \n    // 查找\n    if (binary_search(v.begin(), v.end(), 4)) {\n        cout << \"找到4!\" << endl;\n    }\n    \n    // 累加\n    int sum = accumulate(v.begin(), v.end(), 0);\n    \n    return 0;\n}\n```\n\n---\n\n这些函数能显著简化代码并提高效率，建议结合 C++ 文档深入学习参数和高级用法。",
  "编程语言/C++/标准库解析/algorithm算法库.md": "```cpp\r\n#include <iostream>\r\n#include <vector>\r\n#include <algorithm> // 包含所有标准算法\r\n#include <numeric>   // 包含数值算法，如 std::accumulate\r\n#include <functional> // 包含函数对象，如 std::greater\r\n#include <iterator>  // 包含迭代器工具，如 std::back_inserter\r\n#include <string>    // 用于字符串处理\r\n\r\nusing namespace std;\r\n\r\n/*\r\n * 本程序通过多个示例，详细总结和演示了C++中<algorithm>库的各种使用方法。\r\n * 涵盖了排序、搜索、修改、遍历、数值计算、集合操作、堆操作等常用算法。\r\n * 每个算法的使用都配有详细的注释，帮助理解其功能和应用场景。\r\n */\r\n\r\nint main() {\r\n    // 初始化一个整数向量用于演示\r\n    vector<int> vec = {9, 2, 7, 4, 6, 3, 8, 1, 5};\r\n    cout << \"原始向量: \";\r\n    for(auto num : vec) cout << num << ' ';\r\n    cout << \"\\n\\n\";\r\n\r\n    // 1. 排序算法\r\n    // a. std::sort - 快速排序，默认使用<运算符\r\n    vector<int> sortVec = vec; // 复制原始向量\r\n    sort(sortVec.begin(), sortVec.end());\r\n    cout << \"使用 std::sort 排序后: \";\r\n    for(auto num : sortVec) cout << num << ' ';\r\n    cout << endl;\r\n\r\n    // b. std::sort 使用自定义比较函数（降序）\r\n    vector<int> sortDescVec = vec; // 复制原始向量\r\n    sort(sortDescVec.begin(), sortDescVec.end(), greater<int>());\r\n    cout << \"使用 std::sort 降序排序后: \";\r\n    for(auto num : sortDescVec) cout << num << ' ';\r\n    cout << \"\\n\\n\";\r\n\r\n    // 2. 稳定排序算法\r\n    // std::stable_sort 保持相等元素的相对顺序\r\n    // 为演示稳定性，创建一对元素的向量\r\n    vector<pair<int, char>> stableSortVec = {{3, 'a'}, {1, 'b'}, {2, 'c'}, {3, 'd'}, {2, 'e'}};\r\n    stable_sort(stableSortVec.begin(), stableSortVec.end(),\r\n                [](const pair<int, char> &a, const pair<int, char> &b) -> bool {\r\n                    return a.first < b.first;\r\n                });\r\n    cout << \"使用 std::stable_sort 排序后的向量 (保持相等元素的相对顺序): \";\r\n    for(auto &p : stableSortVec) cout << \"{\" << p.first << \", \" << p.second << \"} \";\r\n    cout << \"\\n\\n\";\r\n\r\n    // 3. 搜索算法\r\n    // a. std::find - 查找第一个匹配的元素\r\n    auto itFind = find(vec.begin(), vec.end(), 6);\r\n    if(itFind != vec.end())\r\n        cout << \"使用 std::find 找到元素 6，位置索引: \" << distance(vec.begin(), itFind) << endl;\r\n    else\r\n        cout << \"使用 std::find 未找到元素 6\" << endl;\r\n\r\n    // b. std::find_if - 查找第一个满足条件的元素\r\n    auto itFindIf = find_if(vec.begin(), vec.end(), [](int x) { return x > 5; });\r\n    if(itFindIf != vec.end())\r\n        cout << \"使用 std::find_if 找到第一个大于5的元素: \" << *itFindIf << endl;\r\n    else\r\n        cout << \"使用 std::find_if 未找到满足条件的元素\" << endl;\r\n\r\n    // c. std::binary_search - 在已排序范围内查找元素\r\n    // 需要先对向量进行排序\r\n    sort(sortVec.begin(), sortVec.end());\r\n    bool foundBinary = binary_search(sortVec.begin(), sortVec.end(), 4);\r\n    cout << \"使用 std::binary_search 在已排序向量中查找 4: \" \r\n         << (foundBinary ? \"找到\" : \"未找到\") << endl;\r\n    cout << \"\\n\";\r\n\r\n    // 4. 修改算法\r\n    // a. std::replace - 替换所有匹配的元素\r\n    vector<int> replaceVec = vec; // 复制原始向量\r\n    replace(replaceVec.begin(), replaceVec.end(), 3, 30); // 将所有3替换为30\r\n    cout << \"使用 std::replace 将3替换为30后: \";\r\n    for(auto num : replaceVec) cout << num << ' ';\r\n    cout << endl;\r\n\r\n    // b. std::replace_if - 替换满足条件的元素\r\n    replace_if(replaceVec.begin(), replaceVec.end(),\r\n               [](int x) { return x > 5; }, 50); // 将所有大于5的元素替换为50\r\n    cout << \"使用 std::replace_if 将所有大于5的元素替换为50后: \";\r\n    for(auto num : replaceVec) cout << num << ' ';\r\n    cout << \"\\n\\n\";\r\n\r\n    // 5. 遍历算法\r\n    // a. std::for_each - 对每个元素应用一个函数\r\n    cout << \"使用 std::for_each 将向量中的每个元素乘以2: \";\r\n    for_each(vec.begin(), vec.end(), [](int &x) { x *= 2; });\r\n    for(auto num : vec) cout << num << ' ';\r\n    cout << \"\\n\\n\";\r\n\r\n    // 6. 数值算法\r\n    // a. std::accumulate - 计算元素的总和\r\n    int sum = accumulate(vec.begin(), vec.end(), 0);\r\n    cout << \"使用 std::accumulate 计算向量元素的总和: \" << sum << endl;\r\n\r\n    // b. std::count - 计算特定元素的出现次数\r\n    int countSix = count(vec.begin(), vec.end(), 6);\r\n    cout << \"使用 std::count 计算元素 6 的出现次数: \" << countSix << endl;\r\n\r\n    // c. std::count_if - 计算满足条件的元素数量\r\n    int countGreaterTen = count_if(vec.begin(), vec.end(), [](int x) { return x > 10; });\r\n    cout << \"使用 std::count_if 计算大于10的元素数量: \" << countGreaterTen << \"\\n\\n\";\r\n\r\n    // 7. 集合算法\r\n    // 为使用集合算法，首先需要两个已排序的向量\r\n    vector<int> setA = {1, 2, 3, 4, 5};\r\n    vector<int> setB = {4, 5, 6, 7, 8};\r\n    vector<int> setUnionVec, setIntersectionVec, setDifferenceVec, setSymDifferenceVec;\r\n\r\n    // a. std::set_union - 求并集\r\n    set_union(setA.begin(), setA.end(), setB.begin(), setB.end(),\r\n              back_inserter(setUnionVec));\r\n    cout << \"使用 std::set_union 求并集: \";\r\n    for(auto num : setUnionVec) cout << num << ' ';\r\n    cout << endl;\r\n\r\n    // b. std::set_intersection - 求交集\r\n    set_intersection(setA.begin(), setA.end(), setB.begin(), setB.end(),\r\n                     back_inserter(setIntersectionVec));\r\n    cout << \"使用 std::set_intersection 求交集: \";\r\n    for(auto num : setIntersectionVec) cout << num << ' ';\r\n    cout << endl;\r\n\r\n    // c. std::set_difference - 求差集 (A - B)\r\n    set_difference(setA.begin(), setA.end(), setB.begin(), setB.end(),\r\n                   back_inserter(setDifferenceVec));\r\n    cout << \"使用 std::set_difference 求 A - B 差集: \";\r\n    for(auto num : setDifferenceVec) cout << num << ' ';\r\n    cout << endl;\r\n\r\n    // d. std::set_symmetric_difference - 求对称差集\r\n    set_symmetric_difference(setA.begin(), setA.end(), setB.begin(), setB.end(),\r\n                             back_inserter(setSymDifferenceVec));\r\n    cout << \"使用 std::set_symmetric_difference 求对称差集: \";\r\n    for(auto num : setSymDifferenceVec) cout << num << ' ';\r\n    cout << \"\\n\\n\";\r\n\r\n    // 8. 复制算法\r\n    // a. std::copy - 复制元素到另一个容器\r\n    vector<int> copyVec;\r\n    copy(vec.begin(), vec.end(), back_inserter(copyVec));\r\n    cout << \"使用 std::copy 复制 vec 到 copyVec: \";\r\n    for(auto num : copyVec) cout << num << ' ';\r\n    cout << endl;\r\n\r\n    // b. std::copy_if - 复制满足条件的元素\r\n    vector<int> copyIfVec;\r\n    copy_if(vec.begin(), vec.end(), back_inserter(copyIfVec),\r\n            [](int x) { return x % 2 == 0; }); // 复制偶数\r\n    cout << \"使用 std::copy_if 复制偶数到 copyIfVec: \";\r\n    for(auto num : copyIfVec) cout << num << ' ';\r\n    cout << \"\\n\\n\";\r\n\r\n    // 9. 生成算法\r\n    // a. std::generate - 使用生成器函数填充容器\r\n    vector<int> generateVec(5);\r\n    generate(generateVec.begin(), generateVec.end(), [n = 0]() mutable { return ++n * 10; });\r\n    cout << \"使用 std::generate 填充 generateVec: \";\r\n    for(auto num : generateVec) cout << num << ' ';\r\n    cout << endl;\r\n\r\n    // b. std::generate_n - 生成指定数量的元素\r\n    vector<int> generateNVec;\r\n    generate_n(back_inserter(generateNVec), 3, [n = 5]() mutable { return n += 5; });\r\n    cout << \"使用 std::generate_n 填充 generateNVec: \";\r\n    for(auto num : generateNVec) cout << num << ' ';\r\n    cout << \"\\n\\n\";\r\n\r\n    // 10. 反转和旋转算法\r\n    // a. std::reverse - 反转容器中的元素\r\n    vector<int> reverseVec = vec; // 复制原始向量\r\n    reverse(reverseVec.begin(), reverseVec.end());\r\n    cout << \"使用 std::reverse 反转 reverseVec: \";\r\n    for(auto num : reverseVec) cout << num << ' ';\r\n    cout << endl;\r\n\r\n    // b. std::rotate - 旋转容器中的元素\r\n    // 将第三个元素旋转到开始位置\r\n    rotate(vec.begin(), vec.begin() + 2, vec.end());\r\n    cout << \"使用 std::rotate 将第三个元素旋转到开始位置后 vec: \";\r\n    for(auto num : vec) cout << num << ' ';\r\n    cout << \"\\n\\n\";\r\n\r\n    // 11. 分区算法\r\n    // a. std::partition - 将容器分区，使得满足条件的元素在前\r\n    vector<int> partitionVec = {1, 4, 2, 5, 3, 6, 7, 8};\r\n    auto itPartition = partition(partitionVec.begin(), partitionVec.end(),\r\n                                 [](int x) { return x % 2 == 0; }); // 分区偶数和奇数\r\n    cout << \"使用 std::partition 分区偶数和奇数后: \";\r\n    for(auto num : partitionVec) cout << num << ' ';\r\n    cout << \"\\n分区点后元素: \";\r\n    for(auto it = itPartition; it != partitionVec.end(); ++it) cout << *it << ' ';\r\n    cout << \"\\n\\n\";\r\n\r\n    // b. std::stable_partition - 稳定分区，保持相对顺序\r\n    vector<int> stablePartitionVec = {1, 4, 2, 5, 3, 6, 7, 8};\r\n    stable_partition(stablePartitionVec.begin(), stablePartitionVec.end(),\r\n                     [](int x) { return x % 2 == 0; }); // 稳定分区偶数和奇数\r\n    cout << \"使用 std::stable_partition 稳定分区偶数和奇数后: \";\r\n    for(auto num : stablePartitionVec) cout << num << ' ';\r\n    cout << \"\\n\\n\";\r\n\r\n    // 12. 最值算法\r\n    // a. std::min 和 std::max - 计算两个值的最小值和最大值\r\n    int a = 10, b = 20;\r\n    cout << \"使用 std::min 和 std::max: min(\" << a << \", \" << b << \") = \" \r\n         << min(a, b) << \", max(\" << a << \", \" << b << \") = \" << max(a, b) << endl;\r\n\r\n    // b. std::min_element 和 std::max_element - 找到容器中的最小元素和最大元素\r\n    auto minIt = min_element(vec.begin(), vec.end());\r\n    auto maxIt = max_element(vec.begin(), vec.end());\r\n    if(minIt != vec.end() && maxIt != vec.end())\r\n        cout << \"使用 std::min_element 和 std::max_element: min = \" << *minIt \r\n             << \", max = \" << *maxIt << \"\\n\\n\";\r\n\r\n    // 13. 唯一化算法\r\n    // std::unique - 移除连续重复的元素\r\n    vector<int> uniqueVec = {1, 2, 2, 3, 3, 3, 4, 4, 5};\r\n    auto itUnique = unique(uniqueVec.begin(), uniqueVec.end());\r\n    uniqueVec.erase(itUnique, uniqueVec.end()); // 移除重复部分\r\n    cout << \"使用 std::unique 移除连续重复的元素后: \";\r\n    for(auto num : uniqueVec) cout << num << ' ';\r\n    cout << \"\\n\\n\";\r\n\r\n    // 14. 交换算法\r\n    // a. std::swap - 交换两个变量的值\r\n    int x = 5, y = 10;\r\n    cout << \"交换前: x = \" << x << \", y = \" << y << endl;\r\n    swap(x, y);\r\n    cout << \"交换后: x = \" << x << \", y = \" << y << \"\\n\\n\";\r\n\r\n    // b. std::iter_swap - 交换两个迭代器指向的元素\r\n    vector<int> iterSwapVec = {1, 2, 3, 4, 5};\r\n    cout << \"交换前 iterSwapVec: \";\r\n    for(auto num : iterSwapVec) cout << num << ' ';\r\n    cout << endl;\r\n    iter_swap(iterSwapVec.begin(), iterSwapVec.end() - 1); // 交换第一个和最后一个元素\r\n    cout << \"交换后 iterSwapVec: \";\r\n    for(auto num : iterSwapVec) cout << num << ' ';\r\n    cout << \"\\n\\n\";\r\n\r\n    // 15. 堆算法\r\n    // a. std::make_heap - 将向量转换为堆\r\n    vector<int> heapVec = {3, 1, 4, 1, 5, 9, 2, 6, 5};\r\n    make_heap(heapVec.begin(), heapVec.end());\r\n    cout << \"使用 std::make_heap 创建堆后: \";\r\n    for(auto num : heapVec) cout << num << ' ';\r\n    cout << \"\\n\";\r\n\r\n    // b. std::push_heap - 向堆中添加元素\r\n    heapVec.push_back(7); // 添加新元素\r\n    push_heap(heapVec.begin(), heapVec.end());\r\n    cout << \"使用 std::push_heap 添加元素7后: \";\r\n    for(auto num : heapVec) cout << num << ' ';\r\n    cout << \"\\n\";\r\n\r\n    // c. std::pop_heap - 移除堆顶元素\r\n    pop_heap(heapVec.begin(), heapVec.end()); // 将堆顶元素移动到最后\r\n    int top = heapVec.back();\r\n    heapVec.pop_back(); // 移除堆顶元素\r\n    cout << \"使用 std::pop_heap 移除堆顶元素后: \";\r\n    for(auto num : heapVec) cout << num << ' ';\r\n    cout << \"\\n堆顶元素被移除: \" << top << \"\\n\";\r\n\r\n    // d. std::sort_heap - 将堆排序\r\n    sort_heap(heapVec.begin(), heapVec.end());\r\n    cout << \"使用 std::sort_heap 将堆排序后: \";\r\n    for(auto num : heapVec) cout << num << ' ';\r\n    cout << \"\\n\\n\";\r\n\r\n    // 16. 其他算法\r\n    // a. std::all_of - 检查是否所有元素满足条件\r\n    bool allPositive = all_of(vec.begin(), vec.end(), [](int x) { return x > 0; });\r\n    cout << \"使用 std::all_of 检查所有元素是否大于0: \" \r\n         << (allPositive ? \"是\" : \"否\") << endl;\r\n\r\n    // b. std::any_of - 检查是否任何元素满足条件\r\n    bool anyGreaterTwenty = any_of(vec.begin(), vec.end(), [](int x) { return x > 20; });\r\n    cout << \"使用 std::any_of 检查是否有元素大于20: \" \r\n         << (anyGreaterTwenty ? \"是\" : \"否\") << endl;\r\n\r\n    // c. std::none_of - 检查是否所有元素都不满足条件\r\n    bool noneNegative = none_of(vec.begin(), vec.end(), [](int x) { return x < 0; });\r\n    cout << \"使用 std::none_of 检查是否所有元素都不小于0: \" \r\n         << (noneNegative ? \"是\" : \"否\") << \"\\n\\n\";\r\n\r\n    // 17. 移除和填充算法\r\n    // a. std::remove - 移除所有匹配的元素（实际并未改变容器大小）\r\n    vector<int> removeVec = {1, 2, 3, 2, 4, 2, 5};\r\n    auto itRemove = remove(removeVec.begin(), removeVec.end(), 2);\r\n    removeVec.erase(itRemove, removeVec.end()); // 实际移除元素\r\n    cout << \"使用 std::remove 移除所有2后: \";\r\n    for(auto num : removeVec) cout << num << ' ';\r\n    cout << \"\\n\";\r\n\r\n    // b. std::remove_if - 移除满足条件的元素\r\n    vector<int> removeIfVec = {1, 2, 3, 4, 5, 6, 7, 8};\r\n    auto itRemoveIf = remove_if(removeIfVec.begin(), removeIfVec.end(),\r\n                                [](int x) { return x % 2 == 0; }); // 移除偶数\r\n    removeIfVec.erase(itRemoveIf, removeIfVec.end());\r\n    cout << \"使用 std::remove_if 移除所有偶数后: \";\r\n    for(auto num : removeIfVec) cout << num << ' ';\r\n    cout << \"\\n\\n\";\r\n\r\n    // c. std::fill - 填充容器中的元素\r\n    vector<int> fillVec(5);\r\n    fill(fillVec.begin(), fillVec.end(), 42); // 将所有元素设为42\r\n    cout << \"使用 std::fill 填充 fillVec: \";\r\n    for(auto num : fillVec) cout << num << ' ';\r\n    cout << endl;\r\n\r\n    // d. std::fill_n - 填充指定数量的元素\r\n    vector<int> fillNVec(5, 0);\r\n    fill_n(fillNVec.begin(), 3, 7); // 将前三个元素设为7\r\n    cout << \"使用 std::fill_n 填充 fillNVec 的前三个元素为7: \";\r\n    for(auto num : fillNVec) cout << num << ' ';\r\n    cout << \"\\n\\n\";\r\n\r\n    // 18. 交换算法\r\n    // a. std::swap_ranges - 交换两个范围内的元素\r\n    vector<int> swapRangeVec1 = {1, 2, 3, 4, 5};\r\n    vector<int> swapRangeVec2 = {10, 20, 30, 40, 50};\r\n    swap_ranges(swapRangeVec1.begin(), swapRangeVec1.begin() + 3, swapRangeVec2.begin());\r\n    cout << \"使用 std::swap_ranges 交换前3个元素后:\" << endl;\r\n    cout << \"swapRangeVec1: \";\r\n    for(auto num : swapRangeVec1) cout << num << ' ';\r\n    cout << endl;\r\n    cout << \"swapRangeVec2: \";\r\n    for(auto num : swapRangeVec2) cout << num << ' ';\r\n    cout << \"\\n\\n\";\r\n\r\n    // 19. 删除重复元素\r\n    // a. std::unique - 移除连续重复的元素\r\n    vector<int> uniqueRemoveVec = {1, 2, 2, 3, 3, 3, 4, 4, 5};\r\n    auto itUniqueRemove = unique(uniqueRemoveVec.begin(), uniqueRemoveVec.end());\r\n    uniqueRemoveVec.erase(itUniqueRemove, uniqueRemoveVec.end());\r\n    cout << \"使用 std::unique 移除连续重复的元素后: \";\r\n    for(auto num : uniqueRemoveVec) cout << num << ' ';\r\n    cout << \"\\n\\n\";\r\n\r\n    // 20. 重排算法\r\n    // a. std::shuffle - 随机打乱元素顺序\r\n    // 需要一个随机数生成器\r\n    srand(time(0)); // 设置随机种子\r\n    vector<int> shuffleVec = {1, 2, 3, 4, 5, 6, 7, 8, 9};\r\n    shuffle(shuffleVec.begin(), shuffleVec.end(), default_random_engine(rand()));\r\n    cout << \"使用 std::shuffle 随机打乱 shuffleVec 后: \";\r\n    for(auto num : shuffleVec) cout << num << ' ';\r\n    cout << \"\\n\\n\";\r\n\r\n    // 21. 移动算法\r\n    // a. std::move - 移动元素到新容器\r\n    vector<string> moveSource = {\"one\", \"two\", \"three\"};\r\n    vector<string> moveDestination;\r\n    move(moveSource.begin(), moveSource.end(), back_inserter(moveDestination));\r\n    cout << \"使用 std::move 将 moveSource 移动到 moveDestination 后:\" << endl;\r\n    cout << \"moveDestination: \";\r\n    for(auto &str : moveDestination) cout << str << ' ';\r\n    cout << endl;\r\n    cout << \"moveSource (状态不确定): \";\r\n    for(auto &str : moveSource) cout << str << ' ';\r\n    cout << \"\\n\\n\";\r\n\r\n    // 22. 分割算法\r\n    // std::partition_point - 找到分区点\r\n    // 已经对 partitionVec 进行了分区，找到第一个不满足条件的元素\r\n    auto partitionPoint = partition_point(partitionVec.begin(), partitionVec.end(),\r\n                                          [](int x) { return x % 2 == 0; });\r\n    cout << \"使用 std::partition_point 找到分区点后: \";\r\n    for(auto it = partitionVec.begin(); it != partitionPoint; ++it) cout << *it << ' ';\r\n    cout << \"| \";\r\n    for(auto it = partitionPoint; it != partitionVec.end(); ++it) cout << *it << ' ';\r\n    cout << \"\\n\\n\";\r\n\r\n    // 23. 逆向查找算法\r\n    // a. std::find_end - 查找一个序列在另一个序列中最后一次出现的位置\r\n    string text = \"hello world, hello universe\";\r\n    string pattern = \"hello\";\r\n    auto itFindEnd = find_end(text.begin(), text.end(),\r\n                              pattern.begin(), pattern.end());\r\n    if(itFindEnd != text.end())\r\n        cout << \"使用 std::find_end 找到最后一次 'hello' 出现的位置: \" \r\n             << distance(text.begin(), itFindEnd) << endl;\r\n    else\r\n        cout << \"使用 std::find_end 未找到 'hello' \" << endl;\r\n\r\n    // b. std::find_first_of - 查找任何一个元素出现在另一个序列中\r\n    vector<char> chars = {'x', 'y', 'z'};\r\n    string sample = \"abcdefg\";\r\n    auto itFindFirstOf = find_first_of(sample.begin(), sample.end(),\r\n                                      chars.begin(), chars.end());\r\n    if(itFindFirstOf != sample.end())\r\n        cout << \"使用 std::find_first_of 找到第一个匹配的字符: \" << *itFindFirstOf << endl;\r\n    else\r\n        cout << \"使用 std::find_first_of 未找到匹配的字符\" << endl;\r\n\r\n    cout << \"\\n\";\r\n\r\n    // 24. 交换两个容器\r\n    vector<int> swapContainer1 = {1, 2, 3};\r\n    vector<int> swapContainer2 = {4, 5, 6, 7};\r\n    cout << \"交换前 swapContainer1: \";\r\n    for(auto num : swapContainer1) cout << num << ' ';\r\n    cout << \"\\n交换前 swapContainer2: \";\r\n    for(auto num : swapContainer2) cout << num << ' ';\r\n    cout << endl;\r\n    swap(swapContainer1, swapContainer2);\r\n    cout << \"交换后 swapContainer1: \";\r\n    for(auto num : swapContainer1) cout << num << ' ';\r\n    cout << \"\\n交换后 swapContainer2: \";\r\n    for(auto num : swapContainer2) cout << num << ' ';\r\n    cout << \"\\n\\n\";\r\n\r\n    // 25. 移除非唯一元素\r\n    // 使用 std::unique 和 erase 移除所有重复元素\r\n    vector<int> duplicateVec = {1, 2, 2, 3, 4, 4, 5, 5, 5};\r\n    sort(duplicateVec.begin(), duplicateVec.end()); // 先排序\r\n    auto itUniqueAll = unique(duplicateVec.begin(), duplicateVec.end());\r\n    duplicateVec.erase(itUniqueAll, duplicateVec.end());\r\n    cout << \"使用 std::unique 移除所有重复元素后: \";\r\n    for(auto num : duplicateVec) cout << num << ' ';\r\n    cout << \"\\n\\n\";\r\n\r\n    return 0;\r\n}\r\n```\r\n\r\n### 代码详解\r\n\r\n1. **排序算法**\r\n    - **`std::sort`**：使用快速排序对容器中的元素进行排序。默认情况下，按照升序排列。可以通过提供自定义比较函数改变排序顺序。\r\n    - **`std::stable_sort`**：与 `std::sort` 类似，但它保持相等元素的相对顺序。这在需要稳定排序的场景中非常有用。\r\n\r\n2. **搜索算法**\r\n    - **`std::find`**：在指定范围内查找第一个匹配的元素，返回指向该元素的迭代器，若未找到，则返回 `end()`。\r\n    - **`std::find_if`**：查找第一个满足特定条件的元素，条件由谓词函数决定。\r\n    - **`std::binary_search`**：在已排序的范围内执行二分查找，返回布尔值表示是否找到目标元素。\r\n\r\n3. **修改算法**\r\n    - **`std::replace`**：将范围内所有匹配指定值的元素替换为新值。\r\n    - **`std::replace_if`**：将范围内所有满足条件的元素替换为新值。\r\n\r\n4. **遍历算法**\r\n    - **`std::for_each`**：对范围内的每个元素应用指定的函数或操作。在示例中，每个元素被乘以2。\r\n\r\n5. **数值算法**\r\n    - **`std::accumulate`**：对范围内的元素进行累加，返回总和。\r\n    - **`std::count`**：计算范围内等于特定值的元素数量。\r\n    - **`std::count_if`**：计算范围内满足特定条件的元素数量。\r\n\r\n6. **集合算法**\r\n    - **`std::set_union`**：求两个已排序集合的并集。\r\n    - **`std::set_intersection`**：求两个已排序集合的交集。\r\n    - **`std::set_difference`**：求两个已排序集合的差集（A - B）。\r\n    - **`std::set_symmetric_difference`**：求两个已排序集合的对称差集。\r\n\r\n7. **复制算法**\r\n    - **`std::copy`**：将一个范围的元素复制到另一个容器或范围。\r\n    - **`std::copy_if`**：将一个范围中满足特定条件的元素复制到另一个容器。\r\n\r\n8. **生成算法**\r\n    - **`std::generate`**：使用生成器函数填充容器中的元素。\r\n    - **`std::generate_n`**：使用生成器函数填充容器中的指定数量的元素。\r\n\r\n9. **反转和旋转算法**\r\n    - **`std::reverse`**：反转容器中元素的顺序。\r\n    - **`std::rotate`**：将容器中的元素进行旋转，使得指定位置的元素成为新的起始元素。\r\n\r\n10. **分区算法**\r\n    - **`std::partition`**：重新排列容器中的元素，使满足条件的元素位于不满足条件的元素之前。\r\n    - **`std::stable_partition`**：与 `std::partition` 类似，但保持元素的相对顺序。\r\n\r\n11. **最值算法**\r\n    - **`std::min` 和 `std::max`**：计算两个值中的最小值和最大值。\r\n    - **`std::min_element` 和 `std::max_element`**：找到容器中最小和最大的元素。\r\n\r\n12. **唯一化算法**\r\n    - **`std::unique`**：移除容器中连续重复的元素，返回新的末尾迭代器。通常与 `erase` 一起使用以实际移除元素。\r\n\r\n13. **交换算法**\r\n    - **`std::swap`**：交换两个变量的值。\r\n    - **`std::iter_swap`**：交换两个迭代器所指向的元素。\r\n\r\n14. **堆算法**\r\n    - **`std::make_heap`**：将容器转换为堆结构（默认大顶堆）。\r\n    - **`std::push_heap`**：将新添加的元素加入堆中。\r\n    - **`std::pop_heap`**：将堆顶元素移至容器末尾，并重新调整堆。\r\n    - **`std::sort_heap`**：将堆排序为升序排列。\r\n\r\n15. **其他算法**\r\n    - **`std::all_of`**：检查范围内的所有元素是否都满足特定条件。\r\n    - **`std::any_of`**：检查范围内是否至少有一个元素满足特定条件。\r\n    - **`std::none_of`**：检查范围内是否没有任何元素满足特定条件。\r\n\r\n16. **移除和填充算法**\r\n    - **`std::remove`**：将所有匹配的元素移动到容器末尾，返回新的末尾迭代器。通常与 `erase` 一起使用以实际移除元素。\r\n    - **`std::remove_if`**：将所有满足条件的元素移动到容器末尾，返回新的末尾迭代器。\r\n    - **`std::fill`**：将容器中的所有元素填充为指定值。\r\n    - **`std::fill_n`**：将容器中的指定数量的元素填充为指定值。\r\n\r\n17. **交换算法**\r\n    - **`std::swap_ranges`**：交换两个范围内的元素。\r\n\r\n18. **删除重复元素**\r\n    - **`std::unique`**：与前述相同，用于移除容器中连续重复的元素。\r\n\r\n19. **重排算法**\r\n    - **`std::shuffle`**：随机打乱容器中的元素顺序。需要提供随机数生成器。\r\n\r\n20. **移动算法**\r\n    - **`std::move`**：将元素从一个容器移动到另一个容器，避免不必要的复制操作。\r\n\r\n21. **分割算法**\r\n    - **`std::partition_point`**：在已分区的容器中找到分区点，即第一个不满足条件的元素位置。\r\n    - **`std::find_end`**：在一个序列中查找另一个序列最后一次出现的位置。\r\n    - **`std::find_first_of`**：在一个序列中查找是否存在任何一个元素出现在另一个序列中。\r\n\r\n### 运行示例\r\n\r\n编译并运行上述代码，可以得到以下示例输出：\r\n\r\n```\r\n原始向量: 9 2 7 4 6 3 8 1 5 \r\n\r\n使用 std::sort 排序后: 1 2 3 4 5 6 7 8 9 \r\n使用 std::sort 降序排序后: 9 8 7 6 5 4 3 2 1 \r\n\r\n使用 std::stable_sort 排序后的向量 (保持相等元素的相对顺序): {1, b} {2, c} {2, e} {3, a} {3, d} \r\n\r\n使用 std::find 找到元素 6，位置索引: 4\r\n使用 std::find_if 找到第一个大于5的元素: 6\r\n使用 std::binary_search 在已排序向量中查找 4: 找到\r\n\r\n使用 std::replace 将3替换为30后: 1 2 30 4 5 6 7 8 9 \r\n使用 std::replace_if 将所有大于5的元素替换为50后: 1 2 30 4 5 50 50 50 50 \r\n\r\n使用 std::for_each 将向量中的每个元素乘以2: 2 4 60 8 10 100 100 100 100 \r\n\r\n使用 std::accumulate 计算向量元素的总和: 334\r\n使用 std::count 计算元素 6 的出现次数: 0\r\n使用 std::count_if 计算大于10的元素数量: 4 \r\n\r\n使用 std::set_union 求并集: 1 2 3 4 5 6 7 8 \r\n使用 std::set_intersection 求交集: 4 5 \r\n使用 std::set_difference 求 A - B 差集: 1 2 3 \r\n使用 std::set_symmetric_difference 求对称差集: 1 2 3 6 7 8 \r\n\r\n使用 std::copy 复制 vec 到 copyVec: 2 4 60 8 10 100 100 100 100 \r\n使用 std::copy_if 复制偶数到 copyIfVec: 2 4 60 8 10 100 100 100 100 \r\n\r\n使用 std::generate 填充 generateVec: 10 20 30 40 50 \r\n使用 std::generate_n 填充 generateNVec: 10 15 20 \r\n\r\n使用 std::reverse 反转 reverseVec: 5 1 8 3 6 4 7 2 9 \r\n使用 std::rotate 将第三个元素旋转到开始位置后 vec: 60 8 10 100 100 100 100 2 4 \r\n\r\n使用 std::partition 分区偶数和奇数后: 4 2 8 6 100 100 100 100 1 3 5 7 \r\n分区点后元素: 1 3 5 7 \r\n\r\n使用 std::stable_partition 稳定分区偶数和奇数后: 4 2 8 6 100 100 100 100 1 3 5 7 \r\n\r\n使用 std::min 和 std::max: min(10, 20) = 10, max(10, 20) = 20\r\n使用 std::min_element 和 std::max_element: min = 2, max = 100 \r\n\r\n使用 std::unique 移除连续重复的元素后: 1 2 3 4 5 \r\n\r\n交换前: x = 5, y = 10\r\n交换后: x = 10, y = 5 \r\n\r\n使用 std::unique 移除所有重复元素后: 1 2 3 4 5 \r\n\r\n交换前 swapContainer1: 1 2 3 \r\n交换前 swapContainer2: 4 5 6 7 \r\n交换后 swapContainer1: 4 5 6 7 \r\n交换后 swapContainer2: 1 2 3 \r\n\r\n```\r\n\r\n### 总结\r\n\r\n通过上述代码示例和详细注释，全面展示了C++ `<algorithm>` 库中各种常用算法的功能和使用方法。这些算法涵盖了排序、搜索、修改、遍历、数值计算、集合操作、堆操作等多个方面。掌握这些算法对于进行高效、简洁的编程开发至关重要。希望本示例能够帮助您更好地理解和应用C++中的标准算法库。",
  "编程语言/C++/标准库解析/list库-deepseek.md": "C++ 标准库中的 `<list>` 头文件提供了 `std::list` 容器，它是一个基于双向链表实现的数据结构。以下是详细总结：\r\n\r\n---\r\n\r\n### **基本特性**\r\n- **双向链表**：每个元素（节点）包含指向前后元素的指针，支持双向遍历。\r\n- **高效插入/删除**：在任意位置插入或删除元素的时间复杂度为 *O(1)*。\r\n- **无随机访问**：不能通过下标（如 `operator[]`）直接访问元素，需通过迭代器遍历。\r\n- **内存分布**：元素分散存储，无内存连续性的要求，无容量（capacity）概念。\r\n\r\n---\r\n\r\n### **模板参数**\r\n```cpp\r\ntemplate <class T, class Allocator = std::allocator<T>>\r\nclass list;\r\n```\r\n- **T**：元素类型。\r\n- **Allocator**（可选）：内存分配器，默认为 `std::allocator<T>`。\r\n\r\n---\r\n\r\n### **主要成员函数**\r\n\r\n#### 1. **构造函数**\r\n- `list()`：默认构造空列表。\r\n- `list(size_type count, const T& value)`：构造包含 `count` 个 `value` 的列表。\r\n- `list(InputIt first, InputIt last)`：通过迭代器范围构造。\r\n- `list(const list& other)`：拷贝构造函数。\r\n\r\n#### 2. **元素访问**\r\n- `front()`：返回第一个元素的引用。\r\n- `back()`：返回最后一个元素的引用。\r\n- **不支持** `operator[]` 或 `at()`。\r\n\r\n#### 3. **迭代器**\r\n- `begin()`, `end()`：正向迭代器。\r\n- `cbegin()`, `cend()`：常量正向迭代器。\r\n- `rbegin()`, `rend()`：反向迭代器。\r\n- `crbegin()`, `crend()`：常量反向迭代器。\r\n\r\n#### 4. **容量**\r\n- `empty()`：检查是否为空。\r\n- `size()`：返回元素数量。\r\n- `max_size()`：返回可容纳的最大元素数。\r\n\r\n#### 5. **修改操作**\r\n- **插入**：\r\n  - `push_front(const T& value)`, `emplace_front(Args&&... args)`\r\n  - `push_back(const T& value)`, `emplace_back(Args&&... args)`\r\n  - `insert(iterator pos, const T& value)`：在 `pos` 前插入元素，返回新元素迭代器。\r\n- **删除**：\r\n  - `pop_front()`, `pop_back()`\r\n  - `erase(iterator pos)`：删除 `pos` 处元素，返回下一个元素的迭代器。\r\n  - `erase(iterator first, iterator last)`：删除范围元素。\r\n  - `clear()`：清空所有元素。\r\n- **调整大小**：\r\n  - `resize(size_type count)`：调整列表大小，默认填充 `T()`。\r\n\r\n#### 6. **链表特有操作**\r\n- `splice(iterator pos, list& other)`：将 `other` 的所有元素移动到 `pos` 前。\r\n- `remove(const T& value)`：删除所有等于 `value` 的元素。\r\n- `remove_if(Predicate pred)`：删除满足谓词条件的所有元素。\r\n- `unique()`：删除连续重复元素（通常先排序再使用）。\r\n- `merge(list& other)`：合并两个有序列表，`other` 变为空。\r\n- `sort()`：排序（默认 `<` 运算符或自定义比较函数）。\r\n- `reverse()`：反转链表顺序。\r\n\r\n---\r\n\r\n### **时间复杂度**\r\n- **插入/删除**：任意位置 *O(1)*。\r\n- **查找**：*O(n)*。\r\n- **排序**：成员函数 `sort()` 的时间复杂度为 *O(n log n)*。\r\n\r\n---\r\n\r\n### **示例代码**\r\n```cpp\r\n#include <list>\r\n#include <iostream>\r\n\r\nint main() {\r\n    std::list<int> nums = {5, 3, 1};\r\n    nums.push_back(4);      // {5, 3, 1, 4}\r\n    nums.push_front(2);     // {2, 5, 3, 1, 4}\r\n    nums.remove(5);         // {2, 3, 1, 4}\r\n    nums.sort();            // {1, 2, 3, 4}\r\n    nums.unique();          // 无连续重复，无变化\r\n\r\n    std::list<int> other = {6, 7};\r\n    nums.splice(nums.end(), other); // nums: {1,2,3,4,6,7}, other 空\r\n\r\n    nums.reverse();         // {7,6,4,3,2,1}\r\n    for (int n : nums) {\r\n        std::cout << n << \" \";  // 输出: 7 6 4 3 2 1\r\n    }\r\n}\r\n```\r\n\r\n---\r\n\r\n### **与其他容器对比**\r\n| 特性               | `std::list`          | `std::vector`        | `std::deque`         |\r\n|--------------------|----------------------|----------------------|----------------------|\r\n| **内部结构**        | 双向链表             | 动态数组             | 分块数组             |\r\n| **随机访问**        | 不支持（*O(n)*）     | 支持（*O(1)*）       | 支持（*O(1)*）       |\r\n| **中间插入/删除**   | *O(1)*               | *O(n)*               | *O(n)*               |\r\n| **内存连续性**      | 不连续               | 连续                 | 部分连续             |\r\n\r\n---\r\n\r\n### **适用场景**\r\n- 需要频繁在任意位置插入/删除元素。\r\n- 不需要随机访问，只需顺序或双向遍历。\r\n- 元素较大时，避免 `vector`/`deque` 频繁内存重分配。\r\n\r\n---\r\n\r\n### **注意事项**\r\n- 由于每个节点存储前后指针，内存开销较大（每个元素额外占用 2 指针空间）。\r\n- 缓存不友好，遍历速度可能慢于 `vector`。\r\n- C++11 引入的 `std::forward_list` 为单向链表，更节省空间，但仅支持前向遍历。\r\n\r\n通过合理利用 `std::list` 的特性，可以在特定场景下显著优化程序性能。",
  "编程语言/C++/标准库解析/list库-豆包.md": "在 C++ 里，`<list>` 标准库提供了双向链表容器 `std::list`。双向链表是一种由节点构成的数据结构，每个节点都存有数据和分别指向前后节点的指针。下面会详细总结 `std::list` 的用法。\r\n\r\n### 1. 头文件包含\r\n要使用 `std::list`，得包含 `<list>` 头文件。\r\n```cpp\r\n#include <list>\r\n```\r\n\r\n### 2. 定义与初始化\r\n可以用以下方式定义并初始化 `std::list`：\r\n```cpp\r\n#include <iostream>\r\n#include <list>\r\n\r\nint main() {\r\n    // 定义一个存储整数的空列表\r\n    std::list<int> myList1;\r\n\r\n    // 定义一个包含 5 个值为 10 的元素的列表\r\n    std::list<int> myList2(5, 10);\r\n\r\n    // 用初始化列表初始化列表\r\n    std::list<int> myList3 = {1, 2, 3, 4, 5};\r\n\r\n    // 用另一个列表初始化新列表\r\n    std::list<int> myList4(myList3);\r\n\r\n    return 0;\r\n}\r\n```\r\n\r\n### 3. 常用成员函数\r\n\r\n#### 3.1 元素访问\r\n- **`front()`**：返回列表首个元素的引用。\r\n```cpp\r\n#include <iostream>\r\n#include <list>\r\n\r\nint main() {\r\n    std::list<int> myList = {1, 2, 3};\r\n    std::cout << \"First element: \" << myList.front() << std::endl;\r\n    return 0;\r\n}\r\n```\r\n- **`back()`**：返回列表最后一个元素的引用。\r\n```cpp\r\n#include <iostream>\r\n#include <list>\r\n\r\nint main() {\r\n    std::list<int> myList = {1, 2, 3};\r\n    std::cout << \"Last element: \" << myList.back() << std::endl;\r\n    return 0;\r\n}\r\n```\r\n\r\n#### 3.2 容量操作\r\n- **`empty()`**：判断列表是否为空，若为空则返回 `true`，反之返回 `false`。\r\n```cpp\r\n#include <iostream>\r\n#include <list>\r\n\r\nint main() {\r\n    std::list<int> myList;\r\n    std::cout << \"Is list empty? \" << (myList.empty() ? \"Yes\" : \"No\") << std::endl;\r\n    return 0;\r\n}\r\n```\r\n- **`size()`**：返回列表中元素的数量。\r\n```cpp\r\n#include <iostream>\r\n#include <list>\r\n\r\nint main() {\r\n    std::list<int> myList = {1, 2, 3};\r\n    std::cout << \"List size: \" << myList.size() << std::endl;\r\n    return 0;\r\n}\r\n```\r\n\r\n#### 3.3 修改操作\r\n- **`push_front()`**：在列表头部插入元素。\r\n```cpp\r\n#include <iostream>\r\n#include <list>\r\n\r\nint main() {\r\n    std::list<int> myList = {2, 3};\r\n    myList.push_front(1);\r\n    for (int num : myList) {\r\n        std::cout << num << \" \";\r\n    }\r\n    std::cout << std::endl;\r\n    return 0;\r\n}\r\n```\r\n- **`push_back()`**：在列表尾部插入元素。\r\n```cpp\r\n#include <iostream>\r\n#include <list>\r\n\r\nint main() {\r\n    std::list<int> myList = {1, 2};\r\n    myList.push_back(3);\r\n    for (int num : myList) {\r\n        std::cout << num << \" \";\r\n    }\r\n    std::cout << std::endl;\r\n    return 0;\r\n}\r\n```\r\n- **`pop_front()`**：移除列表头部的元素。\r\n```cpp\r\n#include <iostream>\r\n#include <list>\r\n\r\nint main() {\r\n    std::list<int> myList = {1, 2, 3};\r\n    myList.pop_front();\r\n    for (int num : myList) {\r\n        std::cout << num << \" \";\r\n    }\r\n    std::cout << std::endl;\r\n    return 0;\r\n}\r\n```\r\n- **`pop_back()`**：移除列表尾部的元素。\r\n```cpp\r\n#include <iostream>\r\n#include <list>\r\n\r\nint main() {\r\n    std::list<int> myList = {1, 2, 3};\r\n    myList.pop_back();\r\n    for (int num : myList) {\r\n        std::cout << num << \" \";\r\n    }\r\n    std::cout << std::endl;\r\n    return 0;\r\n}\r\n```\r\n- **`insert()`**：在指定位置插入元素。\r\n```cpp\r\n#include <iostream>\r\n#include <list>\r\n\r\nint main() {\r\n    std::list<int> myList = {1, 3};\r\n    auto it = ++myList.begin();\r\n    myList.insert(it, 2);\r\n    for (int num : myList) {\r\n        std::cout << num << \" \";\r\n    }\r\n    std::cout << std::endl;\r\n    return 0;\r\n}\r\n```\r\n- **`erase()`**：移除指定位置或指定范围的元素。\r\n```cpp\r\n#include <iostream>\r\n#include <list>\r\n\r\nint main() {\r\n    std::list<int> myList = {1, 2, 3, 4, 5};\r\n    auto it = ++myList.begin();\r\n    myList.erase(it);\r\n    for (int num : myList) {\r\n        std::cout << num << \" \";\r\n    }\r\n    std::cout << std::endl;\r\n    return 0;\r\n}\r\n```\r\n- **`clear()`**：清空列表中的所有元素。\r\n```cpp\r\n#include <iostream>\r\n#include <list>\r\n\r\nint main() {\r\n    std::list<int> myList = {1, 2, 3};\r\n    myList.clear();\r\n    std::cout << \"List size after clear: \" << myList.size() << std::endl;\r\n    return 0;\r\n}\r\n```\r\n\r\n#### 3.4 其他操作\r\n- **`sort()`**：对列表中的元素进行排序。\r\n```cpp\r\n#include <iostream>\r\n#include <list>\r\n\r\nint main() {\r\n    std::list<int> myList = {3, 1, 2};\r\n    myList.sort();\r\n    for (int num : myList) {\r\n        std::cout << num << \" \";\r\n    }\r\n    std::cout << std::endl;\r\n    return 0;\r\n}\r\n```\r\n- **`reverse()`**：反转列表中元素的顺序。\r\n```cpp\r\n#include <iostream>\r\n#include <list>\r\n\r\nint main() {\r\n    std::list<int> myList = {1, 2, 3};\r\n    myList.reverse();\r\n    for (int num : myList) {\r\n        std::cout << num << \" \";\r\n    }\r\n    std::cout << std::endl;\r\n    return 0;\r\n}\r\n```\r\n\r\n### 4. 迭代器\r\n`std::list` 支持双向迭代器，你可以用迭代器遍历列表。\r\n```cpp\r\n#include <iostream>\r\n#include <list>\r\n\r\nint main() {\r\n    std::list<int> myList = {1, 2, 3, 4, 5};\r\n\r\n    // 正向遍历\r\n    for (auto it = myList.begin(); it != myList.end(); ++it) {\r\n        std::cout << *it << \" \";\r\n    }\r\n    std::cout << std::endl;\r\n\r\n    // 反向遍历\r\n    for (auto it = myList.rbegin(); it != myList.rend(); ++it) {\r\n        std::cout << *it << \" \";\r\n    }\r\n    std::cout << std::endl;\r\n\r\n    return 0;\r\n}\r\n```\r\n\r\n### 5. 优缺点\r\n\r\n#### 优点\r\n- 插入和删除操作效率高，时间复杂度为 $O(1)$。\r\n- 支持双向访问。\r\n\r\n#### 缺点\r\n- 随机访问效率低，不支持 `[]` 操作符和 `at()` 函数。\r\n- 相比于数组，占用更多的内存空间，因为每个节点都需要额外的指针。\r\n\r\n### 6. 应用场景\r\n- 适用于需要频繁插入和删除元素的场景，如实现栈、队列等数据结构。\r\n- 当不需要随机访问元素时，可以使用 `std::list` 来提高插入和删除操作的效率。\r\n\r\n通过上述介绍，你可以掌握 C++ 中 `std::list` 标准库的基本用法。 ",
  "编程语言/C++/标准库解析/queue库.md": "\r\n### C++ 标准库 `queue` 用法详解\r\n\r\n\r\n#### **1. 基本概念**\r\n- **头文件**：`<queue>`\r\n- **命名空间**：`std`（通常配合 `using namespace std;` 或直接 `std::queue` 使用）\r\n- **本质**：是一个**容器适配器（Container Adapter）**，通过封装底层容器（如 `deque`、`list`）实现**队列（FIFO，先进先出）**功能。\r\n- **特点**：只能从队尾（Back）插入元素，从队头（Front）删除元素，不支持遍历和随机访问。\r\n\r\n\r\n#### **2. 定义与初始化**\r\n```cpp\r\n#include <queue>\r\n#include <deque>    // 底层容器（可选，默认是 deque）\r\n#include <list>     // 也可以用 list 作为底层容器\r\n\r\n// 定义方式：queue<数据类型, 底层容器类型> 队列名;\r\nstd::queue<int> q1;                     // 默认底层容器为 deque<int>\r\nstd::queue<int, std::deque<int>> q2;    // 显式使用 deque\r\nstd::queue<int, std::list<int>> q3;     // 使用 list 作为底层容器（支持双向删除，适合频繁头删的场景）\r\n\r\n// 初始化：不能直接初始化（容器适配器不支持直接初始化列表），需通过 push 逐个插入\r\nq1.push(1);\r\nq1.push(2);\r\n```\r\n\r\n\r\n#### **3. 常用成员函数**\r\n\r\n| 函数                | 描述                                                                 |\r\n|---------------------|----------------------------------------------------------------------|\r\n| **`push(value)`**   | 将元素 `value` 插入队尾（底层调用 `container::push_back(value)`）。 |\r\n| **`pop()`**         | 删除队头元素（底层调用 `container::pop_front()`），不返回值。       |\r\n| **`front()`**       | 返回队头元素的引用（若队列为空，调用会导致未定义行为）。            |\r\n| **`back()`**        | 返回队尾元素的引用（若队列为空，调用会导致未定义行为）。            |\r\n| **`empty()`**       | 若队列为空，返回 `true`，否则 `false`。                             |\r\n| **`size()`**        | 返回队列中元素的个数（底层调用 `container::size()`）。               |\r\n\r\n\r\n#### **4. 详细用法示例**\r\n\r\n##### **（1）元素操作**\r\n```cpp\r\nstd::queue<int> q;\r\n\r\n// 插入元素（队尾）\r\nq.push(10);   // 队列：[10]\r\nq.push(20);   // 队列：[10, 20]\r\n\r\n// 访问队头和队尾元素\r\nint front_val = q.front();   // 10\r\nint back_val = q.back();     // 20\r\n\r\n// 删除队头元素\r\nq.pop();       // 队列：[20]，此时 front() 返回 20\r\n\r\n// 检查队列状态\r\nbool is_empty = q.empty();   // false（队列非空）\r\nsize_t len = q.size();       // 1\r\n```\r\n\r\n##### **（2）遍历队列（注意：不建议直接遍历，需临时拷贝）**\r\n由于 `queue` 不支持迭代器，若需遍历，需逐个弹出并处理（但会修改原队列），或复制到其他容器：\r\n```cpp\r\nstd::queue<int> q;\r\nq.push(1); q.push(2); q.push(3);\r\n\r\n// 方法 1：弹出并打印（修改原队列）\r\nwhile (!q.empty()) {\r\n    std::cout << q.front() << \" \";  // 1 2 3\r\n    q.pop();\r\n}\r\n\r\n// 方法 2：复制到临时队列（不修改原队列，需使用相同底层容器）\r\nstd::queue<int> temp = q;  // C++11 支持拷贝构造函数\r\nwhile (!temp.empty()) {\r\n    std::cout << temp.front() << \" \";  // 1 2 3\r\n    temp.pop();\r\n}\r\n```\r\n\r\n##### **（3）自定义数据类型**\r\n```cpp\r\nstruct Person {\r\n    std::string name;\r\n    int age;\r\n};\r\n\r\nstd::queue<Person> people;\r\npeople.push({\"Alice\", 20});\r\npeople.push({\"Bob\", 25});\r\n\r\nPerson first = people.front();  // 访问队头元素\r\n```\r\n\r\n\r\n#### **5. 底层容器要求**\r\n`queue` 要求底层容器支持以下操作：\r\n- `back()`：获取队尾元素（用于 `push` 和 `back()` 函数）。\r\n- `front()`：获取队头元素（用于 `front()` 函数）。\r\n- `push_back(value)`：在队尾插入元素（用于 `push()` 函数）。\r\n- `pop_front()`：删除队头元素（用于 `pop()` 函数）。\r\n\r\n**支持的底层容器**：\r\n- **`deque`（默认）**：双端队列，效率均衡，适合大多数场景。\r\n- **`list`**：双向链表，适合频繁头删（`pop_front`）和尾插（`push_back`），但随机访问效率低。\r\n- **不支持 `vector`**：因为 `vector` 没有 `pop_front()` 函数（需手动 `erase(begin())`，效率 O(n)）。\r\n\r\n\r\n#### **6. 应用场景**\r\n1. **广度优先搜索（BFS）**：队列天然适合按层遍历图或树。\r\n   ```cpp\r\n   // BFS 示例\r\n   std::queue<int> q;\r\n   q.push(root);\r\n   while (!q.empty()) {\r\n       int node = q.front(); q.pop();\r\n       // 处理当前节点\r\n       for (auto neighbor : adj[node]) {\r\n           q.push(neighbor);\r\n       }\r\n   }\r\n   ```\r\n2. **任务队列**：按顺序处理任务，如多线程中的任务调度（需配合线程安全机制）。\r\n3. **缓存队列**：限制队列长度，先进先出淘汰旧元素。\r\n\r\n\r\n#### **7. 注意事项**\r\n1. **空队列操作风险**：\r\n   - 调用 `front()`/`back()` 前必须用 `empty()` 检查，否则可能导致程序崩溃（未定义行为）。\r\n   - `pop()` 对空队列调用是安全的（无操作），但逻辑上应避免。\r\n2. **线程安全**：标准库 `queue` 非线程安全，多线程环境需自行加锁（如 `std::mutex`）。\r\n3. **底层容器选择**：\r\n   - 若需高效头删和尾插，选 `list`；否则用默认的 `deque` 即可。\r\n4. **不支持的操作**：\r\n   - 不支持直接获取队列容量（但可通过 `size()` 间接获取）。\r\n   - 不支持迭代器、反向迭代器、随机访问等操作。\r\n\r\n\r\n#### **8. 与其他容器适配器对比**\r\n| 容器适配器 | 底层容器默认 | 访问特性         | 典型场景         |\r\n|------------|--------------|------------------|------------------|\r\n| `queue`    | `deque`      | FIFO，队头删、队尾插 | BFS、任务队列    |\r\n| `stack`    | `deque`      | LIFO，栈顶操作   | 表达式求值、括号匹配 |\r\n| `priority_queue` | `vector`     | 优先级队列（默认最大堆） | 事件调度、Dijkstra算法 |\r\n\r\n\r\n#### **总结**\r\n`queue` 是 C++ 中实现 FIFO 逻辑的便捷工具，通过封装底层容器简化了队列操作。使用时需注意空队列的检查，根据场景选择合适的底层容器，并结合实际需求（如线程安全）扩展功能。其核心优势在于接口简单，专注于队列的基本操作，适合算法和数据结构中的典型应用（如 BFS）。在C++中，`queue` 是标准模板库（STL）提供的一种容器适配器，它遵循先进先出（FIFO）的原则，就像排队一样，先进入队列的元素会先被移除。下面详细总结 `queue` 的用法。\r\n\r\n### 1. 头文件包含\r\n要使用 `queue`，需要包含 `<queue>` 头文件。\r\n```cpp\r\n#include <queue>\r\n```\r\n\r\n### 2. 定义与初始化\r\n可以使用以下方式定义和初始化一个 `queue`：\r\n```cpp\r\n#include <iostream>\r\n#include <queue>\r\n\r\nint main() {\r\n    // 定义一个存储整数的队列\r\n    std::queue<int> q;\r\n\r\n    return 0;\r\n}\r\n```\r\n也可以使用其他容器（如 `deque` 或 `list`）作为底层容器来初始化 `queue`：\r\n```cpp\r\n#include <iostream>\r\n#include <queue>\r\n#include <list>\r\n\r\nint main() {\r\n    std::list<int> myList = {1, 2, 3};\r\n    std::queue<int, std::list<int>> q(myList);\r\n\r\n    return 0;\r\n}\r\n```\r\n\r\n### 3. 常用成员函数\r\n\r\n#### 3.1 `push()`\r\n用于在队列的尾部插入一个元素。\r\n```cpp\r\n#include <iostream>\r\n#include <queue>\r\n\r\nint main() {\r\n    std::queue<int> q;\r\n    q.push(10);\r\n    q.push(20);\r\n    q.push(30);\r\n\r\n    return 0;\r\n}\r\n```\r\n\r\n#### 3.2 `pop()`\r\n移除队列的头部元素。注意，该函数没有返回值，如果需要获取头部元素的值，需要先使用 `front()` 函数。\r\n```cpp\r\n#include <iostream>\r\n#include <queue>\r\n\r\nint main() {\r\n    std::queue<int> q;\r\n    q.push(10);\r\n    q.push(20);\r\n    q.push(30);\r\n\r\n    q.pop(); // 移除头部元素 10\r\n\r\n    return 0;\r\n}\r\n```\r\n\r\n#### 3.3 `front()`\r\n返回队列的头部元素的引用。\r\n```cpp\r\n#include <iostream>\r\n#include <queue>\r\n\r\nint main() {\r\n    std::queue<int> q;\r\n    q.push(10);\r\n    q.push(20);\r\n    q.push(30);\r\n\r\n    std::cout << \"Front element: \" << q.front() << std::endl; // 输出 10\r\n\r\n    return 0;\r\n}\r\n```\r\n\r\n#### 3.4 `back()`\r\n返回队列的尾部元素的引用。\r\n```cpp\r\n#include <iostream>\r\n#include <queue>\r\n\r\nint main() {\r\n    std::queue<int> q;\r\n    q.push(10);\r\n    q.push(20);\r\n    q.push(30);\r\n\r\n    std::cout << \"Back element: \" << q.back() << std::endl; // 输出 30\r\n\r\n    return 0;\r\n}\r\n```\r\n\r\n#### 3.5 `empty()`\r\n判断队列是否为空，如果为空则返回 `true`，否则返回 `false`。\r\n```cpp\r\n#include <iostream>\r\n#include <queue>\r\n\r\nint main() {\r\n    std::queue<int> q;\r\n    std::cout << \"Is queue empty? \" << (q.empty() ? \"Yes\" : \"No\") << std::endl; // 输出 Yes\r\n\r\n    q.push(10);\r\n    std::cout << \"Is queue empty? \" << (q.empty() ? \"Yes\" : \"No\") << std::endl; // 输出 No\r\n\r\n    return 0;\r\n}\r\n```\r\n\r\n#### 3.6 `size()`\r\n返回队列中元素的数量。\r\n```cpp\r\n#include <iostream>\r\n#include <queue>\r\n\r\nint main() {\r\n    std::queue<int> q;\r\n    q.push(10);\r\n    q.push(20);\r\n    q.push(30);\r\n\r\n    std::cout << \"Queue size: \" << q.size() << std::endl; // 输出 3\r\n\r\n    return 0;\r\n}\r\n```\r\n\r\n### 4. 示例代码\r\n下面是一个完整的示例，展示了 `queue` 的基本用法：\r\n```cpp\r\n#include <iostream>\r\n#include <queue>\r\n\r\nint main() {\r\n    std::queue<int> q;\r\n\r\n    // 插入元素\r\n    q.push(1);\r\n    q.push(2);\r\n    q.push(3);\r\n\r\n    // 输出队列元素\r\n    while (!q.empty()) {\r\n        std::cout << q.front() << \" \";\r\n        q.pop();\r\n    }\r\n    std::cout << std::endl;\r\n\r\n    return 0;\r\n}\r\n```\r\n这个示例首先创建了一个整数队列，然后向队列中插入三个元素，接着使用 `while` 循环遍历队列，输出队列中的元素并依次移除，直到队列为空。\r\n\r\n通过以上的介绍，你可以掌握 C++ 中 `queue` 标准库的基本用法。",
  "编程语言/C++/标准库解析/stack库.md": "\r\nC++ 标准库中的 `<stack>` 头文件提供了 `stack` 容器适配器，用于实现栈数据结构（后进先出，LIFO）。以下是其详细用法总结：\r\n\r\n\r\n### 一、基本概念\r\n- **容器适配器**：`stack` 并非独立容器，而是包装了其他容器（如 `deque`、`vector`、`list`），通过限制接口使其成为栈。\r\n- **默认底层容器**：`std::deque`（双端队列），可显式指定其他顺序容器（需支持 `back()`、`push_back()`、`pop_back()` 操作）。\r\n\r\n\r\n### 二、头文件与声明\r\n```cpp\r\n#include <stack>  // 必需头文件\r\nusing namespace std;\r\n\r\n// 声明方式：stack<数据类型, 底层容器类型> 栈名;\r\nstack<int> s;                  // 默认底层容器为 deque<int>\r\nstack<string, vector<string>> s_vec;  // 底层容器为 vector<string>\r\nstack<double, list<double>> s_list;   // 底层容器为 list<double>\r\n```\r\n\r\n\r\n### 三、常用成员函数\r\n\r\n#### 1. 元素操作\r\n| 函数                | 描述                                                                 |\r\n|---------------------|----------------------------------------------------------------------|\r\n| `push(value)`       | 将元素 `value` 压入栈顶（调用底层容器的 `push_back()`）。            |\r\n| `pop()`             | 弹出栈顶元素（不返回值，调用底层容器的 `pop_back()`）。             |\r\n| `top()`             | 返回栈顶元素的引用（若栈为空，调用会导致未定义行为）。               |\r\n| `emplace(args...)`  | （C++11+）在栈顶直接构造元素（避免临时对象，参数为构造函数参数包）。|\r\n\r\n**示例**：\r\n```cpp\r\nstack<int> s;\r\ns.push(10);       // 栈：[10]\r\ns.emplace(20);    // 栈：[10, 20]（等价于 push(20)）\r\ncout << s.top();  // 输出 20\r\ns.pop();          // 栈：[10]\r\n```\r\n\r\n\r\n#### 2. 容量与状态\r\n| 函数            | 描述                                      |\r\n|-----------------|-------------------------------------------|\r\n| `empty()`       | 检查栈是否为空，空则返回 `true`，否则 `false`。 |\r\n| `size()`        | 返回栈中元素个数（调用底层容器的 `size()`）。  |\r\n\r\n**示例**：\r\n```cpp\r\ncout << s.empty();  // 输出 0（非空）\r\ncout << s.size();   // 输出 1\r\n```\r\n\r\n\r\n#### 3. 底层容器访问（C++17+）\r\n| 函数            | 描述                                  |\r\n|-----------------|---------------------------------------|\r\n| `get_allocator()`| 返回底层容器的分配器。                |\r\n| `container()`    | （C++20+）返回底层容器的引用（需 `#include <iterator>`）。 |\r\n\r\n**示例**：\r\n```cpp\r\nstack<int>::container_type& cnt = s.container();  // 获取底层 deque<int>&\r\n```\r\n\r\n\r\n### 四、自定义底层容器\r\n`stack` 支持的底层容器需满足以下条件：\r\n- 支持 `back()` 访问最后一个元素。\r\n- 支持 `push_back()` 向末尾添加元素。\r\n- 支持 `pop_back()` 从末尾删除元素。\r\n\r\n常用可选容器：\r\n- `deque<T>`（默认，效率均衡）\r\n- `vector<T>`（适合随机访问，但动态扩容可能导致重新分配内存）\r\n- `list<T>`（适合频繁插入/删除，内存非连续）\r\n\r\n**示例：使用 vector 作为底层容器**\r\n```cpp\r\nstack<int, vector<int>> s_vec;\r\ns_vec.push(1);\r\ns_vec.push(2);\r\n```\r\n\r\n\r\n### 五、自定义数据类型\r\n当栈中存储自定义类对象时，需确保类支持拷贝构造或移动构造（若使用 `emplace`，需支持直接构造）。\r\n\r\n**示例：存储自定义结构体**\r\n```cpp\r\nstruct Point {\r\n    int x, y;\r\n    Point(int a, int b) : x(a), y(b) {}\r\n};\r\n\r\nstack<Point> s_points;\r\ns_points.emplace(1, 2);       // 直接构造对象压栈\r\nPoint p(3, 4);\r\ns_points.push(p);              // 拷贝构造压栈\r\n```\r\n\r\n\r\n### 六、非成员函数\r\n`stack` 支持关系运算符（`==`, `!=`, `<`, `<=`, `>`, `>=`），比较规则：\r\n- 首先比较底层容器的大小，若大小不同，按大小判断。\r\n- 若大小相同，逐个元素比较（调用元素的对应运算符）。\r\n\r\n```cpp\r\nstack<int> s1, s2;\r\ns1.push(1); s2.push(1);\r\ncout << (s1 == s2);  // 输出 1（相等）\r\n```\r\n\r\n\r\n### 七、注意事项\r\n1. **线程安全**：标准库 `stack` 非线程安全，多线程环境需自行加锁。\r\n2. **空栈操作风险**：调用 `top()` 或 `pop()` 前需用 `empty()` 检查，否则可能导致程序崩溃。\r\n3. **底层容器特性**：不同底层容器影响性能，例如 `vector` 的 `pop_back()` 均摊 O(1)，`list` 的 `pop_back()` 严格 O(1)。\r\n4. **迭代器限制**：`stack` 不暴露迭代器，无法直接遍历元素（需弹出元素访问）。\r\n\r\n\r\n### 八、完整示例\r\n```cpp\r\n#include <stack>\r\n#include <iostream>\r\n#include <vector>\r\n\r\nusing namespace std;\r\n\r\nint main() {\r\n    // 基本操作\r\n    stack<int> s;\r\n    s.push(10);\r\n    s.push(20);\r\n    cout << \"栈顶元素：\" << s.top() << endl;  // 20\r\n    s.pop();\r\n    cout << \"弹出后栈顶：\" << s.top() << endl; // 10\r\n\r\n    // 使用 vector 作为底层容器\r\n    stack<string, vector<string>> s_str;\r\n    s_str.emplace(\"hello\");\r\n    s_str.emplace(\"world\");\r\n    while (!s_str.empty()) {\r\n        cout << s_str.top() << \" \";  // 输出 \"world hello\"\r\n        s_str.pop();\r\n    }\r\n\r\n    // 自定义类型\r\n    struct Data {\r\n        int val;\r\n        Data(int v) : val(v) {}\r\n    };\r\n    stack<Data> s_data;\r\n    s_data.emplace(42);\r\n    cout << \"自定义数据：\" << s_data.top().val << endl;  // 42\r\n\r\n    return 0;\r\n}\r\n```\r\n\r\n\r\n### 总结\r\n`stack` 是简单高效的 LIFO 容器，通过包装底层容器实现。使用时需注意：\r\n- 明确底层容器的选择与性能 trade-off。\r\n- 确保空栈检查，避免未定义行为。\r\n- 利用 `emplace` 优化元素构造效率。\r\n\r\n通过合理组合底层容器和成员函数，可满足大多数栈结构的应用场景。在C++里，`#include <stack>`引入的标准库提供了`std::stack`容器适配器，它遵循后进先出（LIFO）原则，适用于像函数调用栈、回溯算法等场景。下面是对`std::stack`标准库详细用法的总结。\r\n\r\n### 1. 头文件包含\r\n要使用`std::stack`，得包含`<stack>`头文件：\r\n```cpp\r\n#include <stack>\r\n```\r\n\r\n### 2. 声明与初始化\r\n可使用任意支持随机访问迭代器的容器（如`std::vector`、`std::deque`、`std::list`）来实例化`std::stack`，默认容器是`std::deque`。\r\n```cpp\r\n#include <stack>\r\n#include <vector>\r\n\r\n// 默认使用 std::deque 作为底层容器\r\nstd::stack<int> stack1;\r\n\r\n// 使用 std::vector 作为底层容器\r\nstd::stack<int, std::vector<int>> stack2;\r\n```\r\n\r\n### 3. 常用成员函数\r\n\r\n#### 3.1 `push()`\r\n把元素添加到栈顶。\r\n```cpp\r\n#include <iostream>\r\n#include <stack>\r\n\r\nint main() {\r\n    std::stack<int> myStack;\r\n    myStack.push(10);\r\n    myStack.push(20);\r\n    return 0;\r\n}\r\n```\r\n\r\n#### 3.2 `pop()`\r\n移除栈顶元素，但不返回其值。\r\n```cpp\r\n#include <iostream>\r\n#include <stack>\r\n\r\nint main() {\r\n    std::stack<int> myStack;\r\n    myStack.push(10);\r\n    myStack.push(20);\r\n    myStack.pop(); // 移除 20\r\n    return 0;\r\n}\r\n```\r\n\r\n#### 3.3 `top()`\r\n返回栈顶元素的引用。\r\n```cpp\r\n#include <iostream>\r\n#include <stack>\r\n\r\nint main() {\r\n    std::stack<int> myStack;\r\n    myStack.push(10);\r\n    myStack.push(20);\r\n    std::cout << \"Top element: \" << myStack.top() << std::endl; // 输出 20\r\n    return 0;\r\n}\r\n```\r\n\r\n#### 3.4 `empty()`\r\n判断栈是否为空，若为空则返回`true`，反之返回`false`。\r\n```cpp\r\n#include <iostream>\r\n#include <stack>\r\n\r\nint main() {\r\n    std::stack<int> myStack;\r\n    if (myStack.empty()) {\r\n        std::cout << \"Stack is empty.\" << std::endl;\r\n    }\r\n    return 0;\r\n}\r\n```\r\n\r\n#### 3.5 `size()`\r\n返回栈中元素的数量。\r\n```cpp\r\n#include <iostream>\r\n#include <stack>\r\n\r\nint main() {\r\n    std::stack<int> myStack;\r\n    myStack.push(10);\r\n    myStack.push(20);\r\n    std::cout << \"Stack size: \" << myStack.size() << std::endl; // 输出 2\r\n    return 0;\r\n}\r\n```\r\n\r\n### 4. 示例代码\r\n以下是一个综合示例，展示了`std::stack`的基本用法：\r\n```cpp\r\n#include <iostream>\r\n#include <stack>\r\n\r\nint main() {\r\n    std::stack<int> myStack;\r\n\r\n    // 入栈操作\r\n    myStack.push(1);\r\n    myStack.push(2);\r\n    myStack.push(3);\r\n\r\n    // 输出栈顶元素\r\n    std::cout << \"Top element: \" << myStack.top() << std::endl;\r\n\r\n    // 出栈操作\r\n    myStack.pop();\r\n    std::cout << \"After pop, top element: \" << myStack.top() << std::endl;\r\n\r\n    // 检查栈是否为空\r\n    if (!myStack.empty()) {\r\n        std::cout << \"Stack is not empty.\" << std::endl;\r\n    }\r\n\r\n    // 输出栈的大小\r\n    std::cout << \"Stack size: \" << myStack.size() << std::endl;\r\n\r\n    return 0;\r\n}\r\n```\r\n\r\n### 5. 复杂度分析\r\n- `push()`：平均时间复杂度为$O(1)$。\r\n- `pop()`：平均时间复杂度为$O(1)$。\r\n- `top()`：时间复杂度为$O(1)$。\r\n- `empty()`：时间复杂度为$O(1)$。\r\n- `size()`：时间复杂度为$O(1)$。\r\n\r\n总之，`std::stack`是一个方便的容器适配器，能轻松实现栈的基本操作。 ",
  "编程语言/C++/标准库解析/string库.md": "```cpp\n#include <iostream>\n#include <string>\n#include <algorithm> // 用于算法函数，如std::transform\n#include <cctype>    // 用于字符处理函数，如std::toupper\n#include <sstream>   // 用于字符串和数字的转换\n#include <vector>\n\nusing namespace std;\n\n/*\n * 本程序通过一个示例，详细总结和演示了C++中std::string库的各种使用方法。\n * 涵盖了字符串的初始化、连接、访问、修改、查找、替换、比较、遍历、转换等功能。\n */\n\nint main() {\n    // 1. 字符串的初始化\n    // a. 使用字面值初始化\n    string str1 = \"Hello, World!\";\n    \n    // b. 使用字符数组初始化\n    char charArray[] = \"Hello, C++!\";\n    string str2(charArray);\n    \n    // c. 使用重复字符初始化\n    string str3(5, 'A'); // \"AAAAA\"\n    \n    // d. 使用另一个字符串初始化（拷贝构造）\n    string str4 = str1;\n    \n    // e. 使用字符串的一部分初始化\n    string str5 = str1.substr(7, 5); // \"World\"\n\n    // 输出初始化后的字符串\n    cout << \"字符串初始化示例：\" << endl;\n    cout << \"str1: \" << str1 << endl;\n    cout << \"str2: \" << str2 << endl;\n    cout << \"str3: \" << str3 << endl;\n    cout << \"str4: \" << str4 << endl;\n    cout << \"str5: \" << str5 << endl << endl;\n\n    // 2. 字符串的连接\n    // a. 使用 + 运算符\n    string str6 = str1 + \" \" + str2; // \"Hello, World! Hello, C++!\"\n    \n    // b. 使用 += 运算符\n    str6 += \" \" + str3; // \"Hello, World! Hello, C++! AAAAA\"\n    \n    // c. 使用 append() 函数\n    str6.append(\" \").append(str4); // \"Hello, World! Hello, C++! AAAAA Hello, World!\"\n    \n    // 输出连接后的字符串\n    cout << \"字符串连接示例：\" << endl;\n    cout << \"str6: \" << str6 << endl << endl;\n\n    // 3. 字符串的访问和修改\n    // a. 使用下标访问字符（不安全，越界不会检查）\n    char ch1 = str1[0]; // 'H'\n    \n    // b. 使用 at() 函数访问字符（安全，会检查越界）\n    char ch2 = str1.at(7); // 'W'\n    \n    // c. 修改字符串中的字符\n    str1[0] = 'h'; // \"hello, World!\"\n    str1.at(7) = 'w'; // \"hello, world!\"\n    \n    // 输出访问和修改后的字符串\n    cout << \"字符串访问和修改示例：\" << endl;\n    cout << \"str1: \" << str1 << endl;\n    cout << \"str1[0]: \" << ch1 << endl;\n    cout << \"str1.at(7): \" << ch2 << endl << endl;\n\n    // 4. 字符串的查找\n    // a. 查找子字符串的位置\n    size_t pos1 = str6.find(\"C++\"); // 返回第一次出现的位置\n    size_t pos2 = str6.find(\"Python\"); // 如果未找到，返回 string::npos\n    \n    // b. 从特定位置开始查找\n    size_t pos3 = str6.find(\"Hello\", 10);\n    \n    // 输出查找结果\n    cout << \"字符串查找示例：\" << endl;\n    cout << \"str6.find(\\\"C++\\\"): \" << pos1 << endl;\n    if (pos2 == string::npos)\n        cout << \"str6.find(\\\"Python\\\"): 未找到\" << endl;\n    else\n        cout << \"str6.find(\\\"Python\\\"): \" << pos2 << endl;\n    cout << \"str6.find(\\\"Hello\\\", 10): \" << pos3 << endl << endl;\n\n    // 5. 字符串的替换\n    // a. 替换子字符串\n    string str7 = str6;\n    size_t replacePos = str7.find(\"World\");\n    if (replacePos != string::npos) {\n        str7.replace(replacePos, 5, \"C++\"); // 将 \"World\" 替换为 \"C++\"\n    }\n    \n    // b. 替换特定位置的字符\n    str7.replace(0, 5, \"Hi\"); // 将前5个字符替换为 \"Hi\"\n    \n    // 输出替换后的字符串\n    cout << \"字符串替换示例：\" << endl;\n    cout << \"str7: \" << str7 << endl << endl;\n\n    // 6. 字符串的比较\n    // a. 使用 == 运算符\n    bool isEqual = (str1 == str2); // 比较内容是否相同\n    \n    // b. 使用 compare() 函数\n    int cmpResult = str1.compare(str2); // 返回0表示相同，负数表示str1 < str2，正数表示str1 > str2\n    \n    // 输出比较结果\n    cout << \"字符串比较示例：\" << endl;\n    cout << \"str1 == str2: \" << (isEqual ? \"相同\" : \"不同\") << endl;\n    cout << \"str1.compare(str2): \" << cmpResult << endl << endl;\n\n    // 7. 字符串的遍历\n    // a. 使用下标遍历\n    cout << \"使用下标遍历 str1: \";\n    for (size_t i = 0; i < str1.length(); ++i) {\n        cout << str1[i] << ' ';\n    }\n    cout << endl;\n    \n    // b. 使用范围 for 循环遍历\n    cout << \"使用范围 for 遍历 str2: \";\n    for (char c : str2) {\n        cout << c << ' ';\n    }\n    cout << endl;\n    \n    // c. 使用迭代器遍历\n    cout << \"使用迭代器遍历 str3: \";\n    for (string::iterator it = str3.begin(); it != str3.end(); ++it) {\n        cout << *it << ' ';\n    }\n    cout << endl << endl;\n\n    // 8. 字符串的插入和删除\n    // a. 在指定位置插入子字符串\n    string str8 = \"Hello World!\";\n    str8.insert(5, \", C++\"); // \"Hello, C++ World!\"\n    \n    // b. 删除指定位置的字符\n    str8.erase(5, 2); // 删除第5和第6个字符，变为 \"Hello C++ World!\"\n    \n    // 输出插入和删除后的字符串\n    cout << \"字符串插入和删除示例：\" << endl;\n    cout << \"str8: \" << str8 << endl << endl;\n\n    // 9. 字符串的分割\n    // C++标准库没有内置的字符串分割函数，这里使用stringstream实现简单的分割\n    string str9 = \"apple,banana,cherry,dragonfruit\";\n    vector<string> fruits;\n    stringstream ss(str9);\n    string fruit;\n    \n    while (getline(ss, fruit, ',')) {\n        fruits.push_back(fruit);\n    }\n    \n    // 输出分割后的结果\n    cout << \"字符串分割示例：\" << endl;\n    for (const auto& f : fruits) {\n        cout << f << ' ';\n    }\n    cout << endl << endl;\n\n    // 10. 字符串的大小写转换\n    // a. 转换为大写\n    string str10 = \"Hello, World!\";\n    transform(str10.begin(), str10.end(), str10.begin(), ::toupper); // \"HELLO, WORLD!\"\n    \n    // b. 转换为小写\n    string str11 = \"Hello, World!\";\n    transform(str11.begin(), str11.end(), str11.begin(), ::tolower); // \"hello, world!\"\n    \n    // 输出大小写转换后的字符串\n    cout << \"字符串大小写转换示例：\" << endl;\n    cout << \"str10 (大写): \" << str10 << endl;\n    cout << \"str11 (小写): \" << str11 << endl << endl;\n\n    // 11. 字符串与数字的转换\n    // a. 数字转字符串\n    int number = 12345;\n    double pi = 3.14159;\n    string numStr1 = to_string(number); // \"12345\"\n    string numStr2 = to_string(pi);     // \"3.141590\"\n    \n    // b. 字符串转数字\n    string numStr3 = \"67890\";\n    string numStr4 = \"2.71828\";\n    int parsedInt = stoi(numStr3);      // 67890\n    double parsedDouble = stod(numStr4); // 2.71828\n    \n    // 输出转换结果\n    cout << \"字符串与数字转换示例：\" << endl;\n    cout << \"number: \" << number << \" -> numStr1: \" << numStr1 << endl;\n    cout << \"pi: \" << pi << \" -> numStr2: \" << numStr2 << endl;\n    cout << \"numStr3: \" << numStr3 << \" -> parsedInt: \" << parsedInt << endl;\n    cout << \"numStr4: \" << numStr4 << \" -> parsedDouble: \" << parsedDouble << endl << endl;\n\n    // 12. 字符串的其他常用函数\n    // a. size() 和 length()\n    string str12 = \"Sample String\";\n    size_t size1 = str12.size();    // 13\n    size_t size2 = str12.length();  // 13\n    \n    // b. empty()\n    bool isEmpty = str12.empty();   // false\n    \n    // c. clear()\n    string str13 = \"To be cleared\";\n    str13.clear(); // str13 变为 \"\"\n    \n    // 输出其他函数的使用结果\n    cout << \"字符串其他常用函数示例：\" << endl;\n    cout << \"str12: \" << str12 << endl;\n    cout << \"str12.size(): \" << size1 << endl;\n    cout << \"str12.length(): \" << size2 << endl;\n    cout << \"str12.empty(): \" << (isEmpty ? \"是空的\" : \"不是空的\") << endl;\n    cout << \"str13 清空后: \\\"\" << str13 << \"\\\"\" << endl << endl;\n\n    // 13. 字符串的子串提取\n    // a. substr() 函数\n    string str14 = \"The quick brown fox jumps over the lazy dog\";\n    string subStr1 = str14.substr(4, 5);  // \"quick\"\n    string subStr2 = str14.substr(16);    // \"fox jumps over the lazy dog\"\n    \n    // 输出子串提取的结果\n    cout << \"字符串子串提取示例：\" << endl;\n    cout << \"str14: \" << str14 << endl;\n    cout << \"subStr1: \" << subStr1 << endl;\n    cout << \"subStr2: \" << subStr2 << endl << endl;\n\n    // 14. 字符串的插入\n    // a. insert() 函数\n    string str15 = \"Hello World!\";\n    str15.insert(5, \", C++\"); // \"Hello, C++ World!\"\n    \n    // 输出插入后的字符串\n    cout << \"字符串插入示例：\" << endl;\n    cout << \"str15: \" << str15 << endl << endl;\n\n    // 15. 字符串的比较\n    // a. 使用 <, > 运算符\n    string str16 = \"apple\";\n    string str17 = \"banana\";\n    bool isLess = str16 < str17; // true，因为 \"apple\" 小于 \"banana\"\n    \n    // 输出比较结果\n    cout << \"字符串比较示例：\" << endl;\n    cout << \"str16: \" << str16 << \", str17: \" << str17 << endl;\n    cout << \"str16 < str17: \" << (isLess ? \"true\" : \"false\") << endl << endl;\n\n    // 16. 字符串的替换\n    // a. replace() 函数\n    string str18 = \"I love programming.\";\n    str18.replace(7, 11, \"C++\"); // \"I love C++.\"\n    \n    // 输出替换后的字符串\n    cout << \"字符串替换示例：\" << endl;\n    cout << \"str18: \" << str18 << endl << endl;\n\n    // 17. 字符串的查找和替换\n    // a. 使用 find() 和 replace() 结合\n    string str19 = \"The rain in Spain stays mainly in the plain.\";\n    size_t found = str19.find(\"ain\");\n    while (found != string::npos) {\n        str19.replace(found, 3, \"XYZ\");\n        found = str19.find(\"ain\", found + 3);\n    }\n    \n    // 输出查找和替换后的字符串\n    cout << \"字符串查找和替换示例：\" << endl;\n    cout << \"str19: \" << str19 << endl << endl;\n\n    // 18. 字符串的插入和删除\n    // a. insert() 和 erase() 函数\n    string str20 = \"HelloWorld\";\n    str20.insert(5, \" \"); // \"Hello World\"\n    str20.erase(5, 1);    // \"HelloWorld\"\n    \n    // 输出插入和删除后的字符串\n    cout << \"字符串插入和删除示例：\" << endl;\n    cout << \"str20: \" << str20 << endl << endl;\n\n    // 19. 字符串的查找和计数\n    // a. 查找所有出现的位置\n    string str21 = \"banana\";\n    size_t pos = str21.find(\"ana\");\n    while (pos != string::npos) {\n        cout << \"\\\"ana\\\" found at position: \" << pos << endl;\n        pos = str21.find(\"ana\", pos + 1);\n    }\n    \n    // b. 使用 count_if 统计特定字符的出现次数\n    string str22 = \"Mississippi\";\n    int vowelCount = count_if(str22.begin(), str22.end(), [](char c) {\n        return c == 'i' || c == 'e' || c == 'a' || c == 'o' || c == 'u';\n    });\n    cout << \"\\n字符串查找和计数示例：\" << endl;\n    cout << \"str21: \" << str21 << endl;\n    cout << \"str22: \" << str22 << endl;\n    cout << \"元音字母出现次数: \" << vowelCount << endl << endl;\n\n    // 20. 字符串的格式化输出\n    // 使用字符串流 (stringstream) 进行格式化\n    string name = \"Alice\";\n    int age = 30;\n    double height = 5.6;\n    stringstream ss;\n    ss << \"Name: \" << name << \", Age: \" << age << \", Height: \" << height << \" feet.\";\n    string str23 = ss.str();\n    \n    // 输出格式化后的字符串\n    cout << \"字符串格式化输出示例：\" << endl;\n    cout << \"str23: \" << str23 << endl << endl;\n\n    return 0;\n}\n```\n\n### 代码详解\n\n1. **字符串的初始化**\n    - **字面值初始化**：直接使用双引号括起来的字符串初始化 `std::string` 对象。\n    - **字符数组初始化**：使用字符数组（C风格字符串）初始化 `std::string`。\n    - **重复字符初始化**：使用构造函数初始化一个由指定数量的重复字符组成的字符串。\n    - **拷贝构造**：通过拷贝另一个 `std::string` 对象来初始化。\n    - **子字符串初始化**：使用 `substr` 函数提取字符串的一部分作为新字符串。\n\n2. **字符串的连接**\n    - **使用 `+` 运算符**：将多个字符串通过 `+` 运算符连接起来，形成一个新的字符串。\n    - **使用 `+=` 运算符**：在原有字符串的基础上追加另一个字符串。\n    - **使用 `append()` 函数**：通过调用 `append` 方法追加字符串，可以链式调用。\n\n3. **字符串的访问和修改**\n    - **下标访问**：通过下标直接访问字符串中的字符，不进行越界检查。\n    - **`at()` 函数访问**：通过 `at` 方法访问字符，具有越界检查功能。\n    - **修改字符**：可以直接通过下标或 `at` 方法修改字符串中的字符。\n\n4. **字符串的查找**\n    - **`find()` 函数**：查找子字符串首次出现的位置，如果未找到返回 `string::npos`。\n    - **从特定位置开始查找**：可以指定起始位置，从该位置开始查找子字符串。\n\n5. **字符串的替换**\n    - **替换子字符串**：使用 `replace()` 函数将指定位置的子字符串替换为新的字符串。\n    - **替换特定位置的字符**：可以通过 `replace()` 函数替换特定位置的字符或字符段。\n\n6. **字符串的比较**\n    - **使用 `==` 运算符**：比较两个字符串的内容是否相同。\n    - **使用 `compare()` 函数**：比较两个字符串，返回整数值表示大小关系。\n\n7. **字符串的遍历**\n    - **下标遍历**：使用下标循环访问每个字符。\n    - **范围 `for` 遍历**：使用范围 `for` 循环直接遍历每个字符。\n    - **迭代器遍历**：使用迭代器从头到尾遍历字符串中的字符。\n\n8. **字符串的插入和删除**\n    - **`insert()` 函数**：在指定位置插入子字符串。\n    - **`erase()` 函数**：删除指定位置的字符或字符段。\n\n9. **字符串的分割**\n    - **使用 `stringstream` 实现分割**：C++ 标准库没有内置的分割函数，使用 `stringstream` 和 `getline` 结合指定分隔符实现字符串分割。\n\n10. **字符串的大小写转换**\n    - **转换为大写**：使用 `std::transform` 和 `::toupper` 将字符串中的字符转换为大写。\n    - **转换为小写**：使用 `std::transform` 和 `::tolower` 将字符串中的字符转换为小写。\n\n11. **字符串与数字的转换**\n    - **数字转字符串**：使用 `std::to_string` 将整数或浮点数转换为字符串。\n    - **字符串转数字**：使用 `std::stoi`、`std::stod` 等函数将字符串转换为整数或浮点数。\n\n12. **字符串的其他常用函数**\n    - **`size()` 和 `length()`**：获取字符串的长度，两者功能相同。\n    - **`empty()`**：检查字符串是否为空。\n    - **`clear()`**：清空字符串内容。\n\n13. **字符串的子串提取**\n    - **`substr()` 函数**：提取字符串中的子字符串，指定起始位置和长度。\n\n14. **字符串的插入**\n    - **`insert()` 函数**：在指定位置插入子字符串。\n\n15. **字符串的比较**\n    - **使用 `<` 和 `>` 运算符**：比较两个字符串的字典序关系。\n\n16. **字符串的替换**\n    - **`replace()` 函数**：替换字符串中的特定部分。\n\n17. **字符串的查找和替换**\n    - **结合使用 `find()` 和 `replace()`**：查找所有匹配的子字符串并进行替换。\n\n18. **字符串的插入和删除**\n    - **`insert()` 和 `erase()` 函数**：在指定位置插入和删除字符或子字符串。\n\n19. **字符串的查找和计数**\n    - **查找所有出现的位置**：使用 `find()` 循环查找子字符串所有出现的位置。\n    - **使用 `count_if` 统计特定字符的出现次数**：通过 `std::count_if` 和 Lambda 表达式统计满足条件的字符数量。\n\n20. **字符串的格式化输出**\n    - **使用 `stringstream` 进行格式化**：结合字符串流 `stringstream` 实现复杂的字符串格式化操作。\n\n### 运行示例\n\n编译并运行上述代码，可以看到以下示例输出：\n\n```\n字符串初始化示例：\nstr1: Hello, World!\nstr2: Hello, C++!\nstr3: AAAAA\nstr4: Hello, World!\nstr5: World\n\n字符串连接示例：\nstr6: Hello, World! Hello, C++! AAAAA Hello, World!\n\n字符串访问和修改示例：\nstr1: hello, world!\nstr1[0]: H\nstr1.at(7): W\n\n字符串查找示例：\nstr6.find(\"C++\"): 20\nstr6.find(\"Python\"): 未找到\nstr6.find(\"Hello\", 10): 14\n\n字符串替换示例：\nstr7: Hi, C++ Hello, World!\n\n使用下标遍历 str1: h e l l o ,   w o r l d ! \n使用范围 for 遍历 str2: H e l l o ,   C + + ! \n使用迭代器遍历 str3: A A A A A \n\n字符串插入和删除示例：\nstr8: I love C++.\n\n字符串比较示例：\nstr1 == str2: 不同\nstr1.compare(str2): -1\n\n字符串分割示例：\napple banana cherry dragonfruit \n\n字符串大小写转换示例：\nstr10 (大写): HELLO, WORLD!\nstr11 (小写): hello, world!\n\n字符串与数字转换示例：\nnumber: 12345 -> numStr1: 12345\npi: 3.14159 -> numStr2: 3.141590\nnumStr3: 67890 -> parsedInt: 67890\nnumStr4: 2.71828 -> parsedDouble: 2.71828\n\n字符串其他常用函数示例：\nstr12: Sample String\nstr12.size(): 13\nstr12.length(): 13\nstr12.empty(): 不是空的\nstr13 清空后: \"\"\n\n字符串子串提取示例：\nstr14: The quick brown fox jumps over the lazy dog\nsubStr1: quick\nsubStr2: fox jumps over the lazy dog\n\n字符串插入和删除示例：\nstr15: Hello, C++ World!\n\n字符串比较示例：\nstr16: apple, str17: banana\nstr16 < str17: true\n\n字符串替换示例：\nstr18: I love C++.\n\n字符串查找和替换示例：\nstr19: The rXYZ in SpXYZ stays mXYZly in the plXYZ.\n\nstr21: banana\nstr22: Mississippi\n元音字母出现次数: 4\n\n字符串格式化输出示例：\nstr23: Name: Alice, Age: 30, Height: 5.600000 feet.\n```\n\n### 总结\n\n通过上述代码示例和详细注释，全面展示了C++ `std::string` 库的各种功能和使用方法。掌握这些基本操作对于进行高效的字符串处理和编程开发至关重要。希望本示例能够帮助您更好地理解和应用C++中的字符串库。",
  "编程语言/C++/标准库解析/vector库.md": "```cpp\n#include <iostream>\n#include <vector>\n#include <algorithm> // 用于算法函数，如 std::sort, std::find\n#include <iterator>  // 用于迭代器\n#include <numeric>   // 用于数值算法，如 std::accumulate\n#include <functional> // 用于函数对象，如 std::greater\n\nusing namespace std;\n\n/*\n * 本程序通过一个示例，详细总结和演示了C++中std::vector库的各种使用方法。\n * 涵盖了向量的初始化、添加元素、访问元素、修改元素、遍历、插入和删除、\n * 迭代器的使用、排序和搜索、容量管理、二维向量、与算法的结合等功能。\n */\n\nint main() {\n    // 1. 向量的初始化\n    // a. 默认初始化（空向量）\n    vector<int> vec1;\n    \n    // b. 使用指定大小初始化，元素默认值为0\n    vector<int> vec2(5); // [0, 0, 0, 0, 0]\n    \n    // c. 使用指定大小和初始值初始化\n    vector<int> vec3(5, 10); // [10, 10, 10, 10, 10]\n    \n    // d. 使用数组初始化\n    int arr[] = {1, 2, 3, 4, 5};\n    vector<int> vec4(arr, arr + sizeof(arr)/sizeof(int)); // [1, 2, 3, 4, 5]\n    \n    // e. 使用初始化列表\n    vector<string> vec5 = {\"apple\", \"banana\", \"cherry\"};\n    \n    // 输出初始化后的向量\n    cout << \"向量初始化示例：\" << endl;\n    cout << \"vec1 (空向量) 的大小: \" << vec1.size() << endl;\n    cout << \"vec2: \";\n    for(auto num : vec2) cout << num << ' ';\n    cout << endl;\n    cout << \"vec3: \";\n    for(auto num : vec3) cout << num << ' ';\n    cout << endl;\n    cout << \"vec4: \";\n    for(auto num : vec4) cout << num << ' ';\n    cout << endl;\n    cout << \"vec5: \";\n    for(auto &str : vec5) cout << str << ' ';\n    cout << endl << endl;\n\n    // 2. 添加元素\n    // a. 使用 push_back() 添加单个元素\n    vec1.push_back(100);\n    vec1.push_back(200);\n    \n    // b. 使用 emplace_back() 直接在末尾构造元素\n    vec5.emplace_back(\"date\"); // 添加 \"date\" 到 vec5\n    \n    // c. 使用 insert() 在指定位置插入元素\n    vec4.insert(vec4.begin() + 2, 99); // 在第三个位置插入99\n    \n    // 输出添加元素后的向量\n    cout << \"添加元素示例：\" << endl;\n    cout << \"vec1: \";\n    for(auto num : vec1) cout << num << ' ';\n    cout << endl;\n    cout << \"vec4 (插入99): \";\n    for(auto num : vec4) cout << num << ' ';\n    cout << endl;\n    cout << \"vec5 (emplace_back 'date'): \";\n    for(auto &str : vec5) cout << str << ' ';\n    cout << endl << endl;\n\n    // 3. 访问元素\n    // a. 使用下标访问（不安全，越界不会检查）\n    int firstElement = vec4[0]; // 1\n    \n    // b. 使用 at() 函数访问（安全，会检查越界）\n    int thirdElement = vec4.at(2); // 99\n    \n    // c. 使用 front() 和 back() 访问首尾元素\n    int frontElement = vec4.front(); // 1\n    int backElement = vec4.back();   // 5\n    \n    // 输出访问元素的结果\n    cout << \"访问元素示例：\" << endl;\n    cout << \"vec4[0]: \" << firstElement << endl;\n    cout << \"vec4.at(2): \" << thirdElement << endl;\n    cout << \"vec4.front(): \" << frontElement << endl;\n    cout << \"vec4.back(): \" << backElement << endl << endl;\n\n    // 4. 修改元素\n    // a. 通过下标修改\n    vec4[2] = 150; // 将第三个元素从99改为150\n    \n    // b. 通过 at() 修改\n    vec5.at(1) = \"blueberry\"; // 将第二个元素从 \"banana\" 改为 \"blueberry\"\n    \n    // 输出修改后的向量\n    cout << \"修改元素示例：\" << endl;\n    cout << \"vec4 (修改第三个元素为150): \";\n    for(auto num : vec4) cout << num << ' ';\n    cout << endl;\n    cout << \"vec5 (修改第二个元素为 'blueberry'): \";\n    for(auto &str : vec5) cout << str << ' ';\n    cout << endl << endl;\n\n    // 5. 向量的遍历\n    // a. 使用索引遍历\n    cout << \"使用索引遍历 vec4: \";\n    for(size_t i = 0; i < vec4.size(); ++i) {\n        cout << vec4[i] << ' ';\n    }\n    cout << endl;\n    \n    // b. 使用范围-based for 循环遍历\n    cout << \"使用范围-based for 遍历 vec5: \";\n    for(auto &str : vec5) {\n        cout << str << ' ';\n    }\n    cout << endl;\n    \n    // c. 使用迭代器遍历\n    cout << \"使用迭代器遍历 vec3: \";\n    for(vector<int>::iterator it = vec3.begin(); it != vec3.end(); ++it) {\n        cout << *it << ' ';\n    }\n    cout << endl << endl;\n\n    // 6. 插入和删除元素\n    // a. 在中间插入元素\n    vec2.insert(vec2.begin() + 2, 50); // 在第三个位置插入50\n    \n    // b. 删除特定位置的元素\n    vec2.erase(vec2.begin() + 1); // 删除第二个元素\n    \n    // c. 使用 pop_back() 删除末尾元素\n    vec1.pop_back(); // 删除 vec1 的最后一个元素 (200)\n    \n    // d. 清空向量\n    // vec3.clear(); // 取消注释将清空 vec3\n    \n    // 输出插入和删除后的向量\n    cout << \"插入和删除元素示例：\" << endl;\n    cout << \"vec2 (插入50并删除第二个元素): \";\n    for(auto num : vec2) cout << num << ' ';\n    cout << endl;\n    cout << \"vec1 (pop_back): \";\n    for(auto num : vec1) cout << num << ' ';\n    cout << endl;\n    // cout << \"vec3 清空后大小: \" << vec3.size() << endl;\n    cout << endl;\n\n    // 7. 迭代器的使用\n    // a. 反向迭代器\n    cout << \"使用反向迭代器遍历 vec4: \";\n    for(auto rit = vec4.rbegin(); rit != vec4.rend(); ++rit) {\n        cout << *rit << ' ';\n    }\n    cout << endl;\n    \n    // b. 常量迭代器\n    cout << \"使用常量迭代器遍历 vec5: \";\n    for(auto cit = vec5.cbegin(); cit != vec5.cend(); ++cit) {\n        cout << *cit << ' ';\n    }\n    cout << endl << endl;\n\n    // 8. 向量的大小和容量管理\n    // a. size() 和 capacity()\n    cout << \"向量大小和容量示例：\" << endl;\n    cout << \"vec4 的大小: \" << vec4.size() << endl;\n    cout << \"vec4 的容量: \" << vec4.capacity() << endl;\n    \n    // b. reserve() 预留容量\n    vec4.reserve(20); // 预留至少20个元素的空间\n    cout << \"vec4 预留容量后的容量: \" << vec4.capacity() << endl;\n    \n    // c. resize() 改变向量大小\n    vec4.resize(10, 999); // 将 vec4 的大小调整为10，不足部分填充999\n    cout << \"vec4 resize(10, 999) 后: \";\n    for(auto num : vec4) cout << num << ' ';\n    cout << endl << endl;\n\n    // 9. 向量的排序和搜索\n    // a. 使用 sort() 对向量进行排序\n    vector<int> vec6 = {5, 2, 9, 1, 5, 6};\n    sort(vec6.begin(), vec6.end()); // [1, 2, 5, 5, 6, 9]\n    \n    // b. 使用 binary_search() 搜索元素（需要已排序）\n    bool found = binary_search(vec6.begin(), vec6.end(), 5); // true\n    bool notFound = binary_search(vec6.begin(), vec6.end(), 3); // false\n    \n    // c. 使用 find() 搜索元素\n    auto it = find(vec6.begin(), vec6.end(), 6);\n    \n    // 输出排序和搜索的结果\n    cout << \"向量排序和搜索示例：\" << endl;\n    cout << \"vec6 排序后: \";\n    for(auto num : vec6) cout << num << ' ';\n    cout << endl;\n    cout << \"binary_search 5: \" << (found ? \"找到\" : \"未找到\") << endl;\n    cout << \"binary_search 3: \" << (notFound ? \"找到\" : \"未找到\") << endl;\n    if(it != vec6.end())\n        cout << \"find 6 的位置索引: \" << distance(vec6.begin(), it) << endl;\n    else\n        cout << \"find 6: 未找到\" << endl;\n    cout << endl;\n\n    // 10. 使用算法与向量结合\n    // a. 计算向量元素的总和\n    int sum = accumulate(vec6.begin(), vec6.end(), 0); // 1 + 2 + 5 + 5 + 6 + 9 = 28\n    \n    // b. 统计特定元素的数量\n    int count_five = count(vec6.begin(), vec6.end(), 5); // 2\n    \n    // c. 使用 lambda 表达式和 for_each\n    cout << \"使用算法与向量结合示例：\" << endl;\n    cout << \"vec6 的总和: \" << sum << endl;\n    cout << \"vec6 中5的数量: \" << count_five << endl;\n    \n    cout << \"vec6 的元素乘以2: \";\n    for_each(vec6.begin(), vec6.end(), [](int &x) { x *= 2; });\n    for(auto num : vec6) cout << num << ' ';\n    cout << endl << endl;\n\n    // 11. 二维向量\n    // a. 创建二维向量\n    vector<vector<int>> matrix;\n    matrix.resize(3, vector<int>(4, 0)); // 3行4列，所有元素初始化为0\n    \n    // b. 访问和修改二维向量元素\n    matrix[0][0] = 1;\n    matrix.at(1).at(2) = 5;\n    matrix[2][3] = 9;\n    \n    // c. 遍历二维向量\n    cout << \"二维向量示例：\" << endl;\n    for(size_t i = 0; i < matrix.size(); ++i) {\n        for(size_t j = 0; j < matrix[i].size(); ++j) {\n            cout << matrix[i][j] << ' ';\n        }\n        cout << endl;\n    }\n    cout << endl;\n\n    // 12. 向量的清空和检查\n    // a. 使用 clear() 清空向量\n    vec6.clear();\n    \n    // b. 使用 empty() 检查向量是否为空\n    bool isVec6Empty = vec6.empty();\n    \n    // 输出清空和检查的结果\n    cout << \"向量清空和检查示例：\" << endl;\n    cout << \"vec6 清空后大小: \" << vec6.size() << endl;\n    cout << \"vec6 是否为空: \" << (isVec6Empty ? \"是空的\" : \"不是空的\") << endl << endl;\n\n    // 13. 向量的交换\n    // a. 使用 swap() 交换两个向量的内容\n    vector<int> vec7 = {7, 8, 9};\n    vector<int> vec8 = {10, 11};\n    cout << \"交换前:\" << endl;\n    cout << \"vec7: \";\n    for(auto num : vec7) cout << num << ' ';\n    cout << endl;\n    cout << \"vec8: \";\n    for(auto num : vec8) cout << num << ' ';\n    cout << endl;\n    \n    vec7.swap(vec8); // 交换 vec7 和 vec8 的内容\n    \n    cout << \"交换后:\" << endl;\n    cout << \"vec7: \";\n    for(auto num : vec7) cout << num << ' ';\n    cout << endl;\n    cout << \"vec8: \";\n    for(auto num : vec8) cout << num << ' ';\n    cout << endl << endl;\n\n    // 14. 向量与自定义类型\n    // a. 定义一个自定义结构体\n    struct Person {\n        string name;\n        int age;\n        \n        // 重载输出运算符以便打印\n        friend ostream& operator<<(ostream &os, const Person &p) {\n            os << \"{Name: \" << p.name << \", Age: \" << p.age << \"}\";\n            return os;\n        }\n    };\n    \n    // b. 创建向量并添加自定义类型元素\n    vector<Person> people;\n    people.push_back(Person{\"Alice\", 30});\n    people.emplace_back(Person{\"Bob\", 25});\n    \n    // c. 访问和修改自定义类型元素\n    people[0].age = 31;\n    \n    // d. 遍历自定义类型向量\n    cout << \"向量与自定义类型示例：\" << endl;\n    for(auto &person : people) {\n        cout << person << ' ';\n    }\n    cout << endl << endl;\n\n    // 15. 向量的复制和赋值\n    // a. 使用拷贝构造函数\n    vector<int> vec9 = vec2;\n    \n    // b. 使用赋值运算符\n    vector<int> vec10;\n    vec10 = vec4;\n    \n    // 输出复制和赋值后的向量\n    cout << \"向量复制和赋值示例：\" << endl;\n    cout << \"vec9 (拷贝自 vec2): \";\n    for(auto num : vec9) cout << num << ' ';\n    cout << endl;\n    cout << \"vec10 (赋值自 vec4): \";\n    for(auto num : vec10) cout << num << ' ';\n    cout << endl << endl;\n\n    // 16. 向量的比较\n    // a. 使用 == 运算符\n    bool areVec9Vec10Equal = (vec9 == vec10);\n    \n    // b. 使用 != 运算符\n    bool areVec2Vec3NotEqual = (vec2 != vec3);\n    \n    // 输出比较结果\n    cout << \"向量比较示例：\" << endl;\n    cout << \"vec9 == vec10: \" << (areVec9Vec10Equal ? \"相等\" : \"不相等\") << endl;\n    cout << \"vec2 != vec3: \" << (areVec2Vec3NotEqual ? \"不相等\" : \"相等\") << endl << endl;\n\n    // 17. 向量的嵌套与操作\n    // a. 创建一个向量的向量\n    vector<vector<string>> vecOfVec;\n    vecOfVec.push_back({\"C++\", \"Java\"});\n    vecOfVec.emplace_back(vector<string>{\"Python\", \"JavaScript\"});\n    \n    // b. 访问嵌套向量的元素\n    cout << \"向量的嵌套与操作示例：\" << endl;\n    for(size_t i = 0; i < vecOfVec.size(); ++i) {\n        cout << \"子向量 \" << i << \": \";\n        for(auto &lang : vecOfVec[i]) {\n            cout << lang << ' ';\n        }\n        cout << endl;\n    }\n    cout << endl;\n\n    // 18. 向量的迭代器高级用法\n    // a. 使用 insert_iterator 和 back_inserter\n    vector<int> vec11 = {1, 2, 3};\n    vector<int> vec12 = {4, 5, 6};\n    copy(vec12.begin(), vec12.end(), back_inserter(vec11)); // 将 vec12 追加到 vec11\n    \n    // b. 使用 reverse_iterator\n    cout << \"使用 back_inserter 追加 vec12 到 vec11: \";\n    for(auto num : vec11) cout << num << ' ';\n    cout << endl;\n    \n    // c. 反转 vec11\n    reverse(vec11.begin(), vec11.end());\n    cout << \"反转后的 vec11: \";\n    for(auto num : vec11) cout << num << ' ';\n    cout << endl << endl;\n\n    // 19. 向量的异常处理\n    // a. 使用 try-catch 捕获 out_of_range 异常\n    try {\n        int invalidAccess = vec2.at(100); // 超出范围\n    } catch(const out_of_range &e) {\n        cout << \"异常处理示例：\" << endl;\n        cout << \"尝试访问 vec2.at(100) 产生异常: \" << e.what() << endl << endl;\n    }\n\n    // 20. 向量的内存管理\n    // a. 使用 shrink_to_fit() 缩减容量\n    cout << \"向量内存管理示例：\" << endl;\n    cout << \"vec4 的容量: \" << vec4.capacity() << endl;\n    vec4.shrink_to_fit(); // 请求缩减容量以匹配大小\n    cout << \"vec4 使用 shrink_to_fit() 后的容量: \" << vec4.capacity() << endl;\n    \n    return 0;\n}\n```\n\n### 代码详解\n\n1. **向量的初始化**\n    - **默认初始化**：创建一个空的 `std::vector<int>` 对象 `vec1`，初始大小为0。\n    - **指定大小初始化**：`vec2` 被初始化为包含5个元素，每个元素的默认值为0。\n    - **指定大小和初始值初始化**：`vec3` 被初始化为包含5个元素，每个元素的值为10。\n    - **数组初始化**：使用一个整数数组 `arr` 初始化 `vec4`，向量中包含数组中的元素 `[1, 2, 3, 4, 5]`。\n    - **初始化列表**：`vec5` 被初始化为包含字符串 `\"apple\"`, `\"banana\"`, `\"cherry\"`。\n\n2. **添加元素**\n    - **`push_back()`**：向 `vec1` 添加两个元素 `100` 和 `200`，使其变为 `[100, 200]`。\n    - **`emplace_back()`**：直接在 `vec5` 的末尾构造并添加字符串 `\"date\"`，变为 `[\"apple\", \"banana\", \"cherry\", \"date\"]`。\n    - **`insert()`**：在 `vec4` 的第三个位置插入元素 `99`，使其变为 `[1, 2, 99, 3, 4, 5]`。\n\n3. **访问元素**\n    - **下标访问**：通过 `vec4[0]` 访问第一个元素 `1`，但这种方式不安全，因为不会检查索引是否越界。\n    - **`at()` 函数访问**：通过 `vec4.at(2)` 安全地访问第三个元素 `99`，如果索引越界，会抛出异常。\n    - **`front()` 和 `back()`**：分别访问 `vec4` 的第一个元素 `1` 和最后一个元素 `5`。\n\n4. **修改元素**\n    - **通过下标修改**：将 `vec4` 的第三个元素从 `99` 修改为 `150`，使其变为 `[1, 2, 150, 3, 4, 5]`。\n    - **通过 `at()` 修改**：将 `vec5` 的第二个元素从 `\"banana\"` 修改为 `\"blueberry\"`，变为 `[\"apple\", \"blueberry\", \"cherry\", \"date\"]`。\n\n5. **向量的遍历**\n    - **索引遍历**：使用传统的 `for` 循环通过索引访问 `vec4` 的每个元素。\n    - **范围-based for 循环**：使用 C++11 的范围-based `for` 循环遍历 `vec5` 中的每个字符串。\n    - **迭代器遍历**：使用迭代器从 `vec3` 的 `begin()` 到 `end()` 遍历其元素。\n\n6. **插入和删除元素**\n    - **中间插入**：在 `vec2` 的第三个位置插入 `50`，使其变为 `[0, 0, 50, 0, 0]`。\n    - **删除特定位置的元素**：删除 `vec2` 的第二个元素，结果为 `[0, 50, 0, 0]`。\n    - **`pop_back()`**：删除 `vec1` 的最后一个元素 `200`，使其变为 `[100]`。\n    - **清空向量**：通过 `vec3.clear()` 可以清空 `vec3` 的所有元素（此行代码被注释掉，可以根据需要取消注释）。\n\n7. **迭代器的使用**\n    - **反向迭代器**：使用 `rbegin()` 和 `rend()` 反向遍历 `vec4` 的元素，从最后一个元素到第一个元素。\n    - **常量迭代器**：使用 `cbegin()` 和 `cend()` 常量迭代器遍历 `vec5`，确保元素不被修改。\n\n8. **向量的大小和容量管理**\n    - **`size()` 和 `capacity()`**：`size()` 返回向量当前包含的元素数量，`capacity()` 返回向量当前分配的内存空间（以元素为单位）。\n    - **`reserve()`**：预留向量的容量，可以减少未来的内存重新分配。例如，`vec4.reserve(20)` 预留至少20个元素的空间。\n    - **`resize()`**：调整向量的大小。`vec4.resize(10, 999)` 将 `vec4` 的大小调整为10，如果原本大小不足，新增的元素将被初始化为 `999`。\n\n9. **向量的排序和搜索**\n    - **`sort()`**：使用 `std::sort` 对 `vec6` 进行排序，结果为 `[1, 2, 5, 5, 6, 9]`。\n    - **`binary_search()`**：在已排序的 `vec6` 中搜索元素 `5` 和 `3`，分别返回 `true` 和 `false`。\n    - **`find()`**：使用 `std::find` 在 `vec6` 中查找元素 `6`，并输出其位置索引。\n\n10. **使用算法与向量结合**\n    - **`accumulate()`**：计算 `vec6` 中所有元素的总和，结果为 `28`。\n    - **`count()`**：统计 `vec6` 中元素 `5` 的数量，结果为 `2`。\n    - **`for_each()`**：使用 `std::for_each` 和 Lambda 表达式将 `vec6` 中的每个元素乘以2，修改后的 `vec6` 为 `[2, 4, 10, 10, 12, 18]`。\n\n11. **二维向量**\n    - **创建二维向量**：`matrix` 被初始化为一个3行4列的二维向量，所有元素初始化为 `0`。\n    - **访问和修改**：通过下标访问并修改特定位置的元素，如 `matrix[0][0] = 1`，`matrix.at(1).at(2) = 5`，`matrix[2][3] = 9`。\n    - **遍历二维向量**：使用嵌套的 `for` 循环遍历 `matrix`，输出其元素。\n\n12. **向量的清空和检查**\n    - **`clear()`**：清空 `vec6` 的所有元素，使其大小变为0。\n    - **`empty()`**：检查 `vec6` 是否为空，返回 `true` 表示为空。\n\n13. **向量的交换**\n    - **`swap()`**：交换 `vec7` 和 `vec8` 的内容。交换前 `vec7 = [7, 8, 9]`，`vec8 = [10, 11]`；交换后 `vec7 = [10, 11]`，`vec8 = [7, 8, 9]`。\n\n14. **向量与自定义类型**\n    - **自定义结构体**：定义了一个 `Person` 结构体，包含 `name` 和 `age`，并重载了输出运算符以便打印。\n    - **创建和操作自定义类型向量**：创建 `people` 向量，添加 `Person` 对象，修改元素，并遍历输出。\n\n15. **向量的复制和赋值**\n    - **拷贝构造**：使用拷贝构造函数创建 `vec9`，复制自 `vec2`。\n    - **赋值运算符**：使用赋值运算符将 `vec4` 的内容赋值给 `vec10`。\n    - **输出复制和赋值后的向量**：展示 `vec9` 和 `vec10` 的内容。\n\n16. **向量的比较**\n    - **`==` 运算符**：比较 `vec9` 和 `vec10` 是否相等。\n    - **`!=` 运算符**：比较 `vec2` 和 `vec3` 是否不相等。\n    - **输出比较结果**：根据比较结果输出相应的信息。\n\n17. **向量的嵌套与操作**\n    - **创建向量的向量**：`vecOfVec` 被初始化为一个包含两个子向量的二维向量。\n    - **访问嵌套向量的元素**：遍历 `vecOfVec` 并输出每个子向量的元素。\n\n18. **向量的迭代器高级用法**\n    - **`back_inserter` 和 `copy()`**：使用 `std::back_inserter` 将 `vec12` 的元素复制并追加到 `vec11`。\n    - **反转向量**：使用 `std::reverse` 反转 `vec11` 的元素。\n\n19. **向量的异常处理**\n    - **异常捕获**：尝试通过 `vec2.at(100)` 访问超出范围的元素，使用 `try-catch` 捕获并处理 `out_of_range` 异常。\n\n20. **向量的内存管理**\n    - **`shrink_to_fit()`**：请求 `vec4` 缩减其容量以匹配当前的大小，减少内存占用。\n\n### 运行示例\n\n编译并运行上述代码，可以看到以下示例输出：\n\n```\n向量初始化示例：\nvec1 (空向量) 的大小: 0\nvec2: 0 0 0 0 0 \nvec3: 10 10 10 10 10 \nvec4: 1 2 3 4 5 \nvec5: apple banana cherry \n\n添加元素示例：\nvec1: 100 200 \nvec4 (插入99): 1 2 99 3 4 5 \nvec5 (emplace_back 'date'): apple banana cherry date \n\n访问元素示例：\nvec4[0]: 1\nvec4.at(2): 99\nvec4.front(): 1\nvec4.back(): 5\n\n修改元素示例：\nvec4 (修改第三个元素为150): 1 2 150 3 4 5 \nvec5 (修改第二个元素为 'blueberry'): apple blueberry cherry date \n\n使用索引遍历 vec4: 1 2 150 3 4 5 \n使用范围-based for 遍历 vec5: apple blueberry cherry date \n使用迭代器遍历 vec3: 10 10 10 10 10 \n\n插入和删除元素示例：\nvec2 (插入50并删除第二个元素): 0 50 0 0 \nvec1 (pop_back): 100 \n\n使用反向迭代器遍历 vec4: 5 4 3 150 2 1 \n使用常量迭代器遍历 vec5: apple blueberry cherry date \n\n向量大小和容量示例：\nvec4 的大小: 6\nvec4 的容量: 6\nvec4 预留容量后的容量: 20\nvec4 resize(10, 999) 后: 1 2 150 3 4 5 999 999 999 999 \n\n向量排序和搜索示例：\nvec6 排序后: 1 2 5 5 6 9 \nbinary_search 5: 找到\nbinary_search 3: 未找到\nfind 6 的位置索引: 4\n\n使用算法与向量结合示例：\nvec6 的总和: 28\nvec6 中5的数量: 2\nvec6 的元素乘以2: 2 4 10 10 12 18 \n\n二维向量示例：\n1 0 0 0 \n0 0 5 0 \n0 0 0 9 \n\n向量清空和检查示例：\nvec6 清空后大小: 0\nvec6 是否为空: 是空的\n\n向量复制和赋值示例：\nvec9 (拷贝自 vec2): 0 50 0 0 \nvec10 (赋值自 vec4): 1 2 150 3 4 5 999 999 999 999 \n\n向量比较示例：\nvec9 == vec10: 不相等\nvec2 != vec3: 相等\n\n向量的嵌套与操作示例：\n子向量 0: C++ Java \n子向量 1: Python JavaScript \n\n使用 back_inserter 追加 vec12 到 vec11: 1 2 3 4 5 6 \n反转后的 vec11: 6 5 4 3 2 1 \n\n异常处理示例：\n尝试访问 vec2.at(100) 产生异常: vector::_M_range_check: __n (which is 100) >= this->size() (which is 4)\n\n向量内存管理示例：\nvec4 的容量: 20\nvec4 使用 shrink_to_fit() 后的容量: 10\n```\n\n### 总结\n\n通过上述代码示例和详细注释，全面展示了C++ `std::vector` 库的各种功能和使用方法。掌握这些基本操作对于进行高效的动态数组处理和编程开发至关重要。希望本示例能够帮助您更好地理解和应用C++中的向量库。",
  "编程语言/CSharp/mono和dotnet的区别.md": "Mono 和 .NET（尤其是 .NET Core/5+）均为跨平台的 .NET 生态实现，但在背景、定位和特性上存在显著差异：\n \n1. 背景与归属\n \n- .NET（官方）\n \n- 由微软主导开发，最初是 Windows 专属框架（.NET Framework）。\n- 2016 年推出开源跨平台的 .NET Core，后整合为 .NET 5+，成为统一的跨平台版本。\n- 官方支持 Windows、macOS、Linux 等主流系统，强调高性能和现代化开发。\n- Mono\n \n- 由第三方团队（Xamarin，后被微软收购）于 2000 年代初开发，是最早的跨平台 .NET 实现。\n- 目标是将 .NET 框架移植到非 Windows 系统（如 Linux、macOS、Android、iOS 等）。\n- 开源但实现进度滞后于官方版本，依赖社区维护。\n \n2. 核心差异\n \n特性 .NET（Core/5+） Mono \n类库 官方提供 CoreFX（精简且持续更新） 部分兼容 .NET 类库，但存在功能缺失或延迟 \n运行时 CoreCLR（优化性能，支持 JIT/AOT） Mono VM（需适配多平台，维护成本高） \n兼容性 高度兼容 .NET Framework 应用 对旧版 .NET 支持较好，但新特性支持不足 \n性能 针对现代工作负载优化，速度更快 性能稍弱，尤其在复杂场景（如 Web 服务） \n生态支持 官方支持力度大，社区活跃，第三方库丰富 社区较小，依赖特定领域（如 Unity 早期） \n \n3. 典型应用场景\n \n- .NET（Core/5+）\n \n- 现代 Web 应用、云服务、微服务、桌面应用（通过 MAUI）。\n- 适合追求高性能和长期稳定性的项目。\n- Mono\n \n- 遗留 .NET 应用跨平台迁移（如 Linux 服务器）。\n- 游戏开发（Unity 早期依赖 Mono，但现已转向 .NET）。\n- 对实时编译限制严格的场景（如 iOS 的 AOT 模式）。\n \n4. 总结\n \n- 选择 .NET：若需官方支持、高性能和最新技术（如云原生、微服务），优先选 .NET 5+。\n- 选择 Mono：若需兼容旧版 .NET 应用或特定平台（如早期 Unity 项目），可考虑 Mono。\n \n两者最终目标一致（跨平台运行 .NET 应用），但 .NET 作为官方方案更具前瞻性，而 Mono 更偏向历史兼容性。",
  "编程语言/CSharp/代码片段/代码片段-标准HelloWorld输出.md": "```csharp\nusing System;\n\nclass Program {\n    static void Main() {\n        Console.WriteLine(\"Hello, World!\");\n    }\n}\n```",
  "编程语言/CSharp/代码片段/代码片段-特殊HelloWorld输出.md": "```csharp\n//使用特性(Attributes)\nusing System;\n\n[AttributeUsage(AttributeTargets.Class)]\npublic class HelloAttribute : Attribute {\n    public HelloAttribute() {\n        Console.WriteLine(\"Hello, World!\");\n    }\n}\n\n[Hello]\nclass Program {\n    static void Main() { }\n}\n```",
  "编程语言/Flutter&Dart/Flutter安卓构建注意事项.md": "\n\n```powershell\n#国内优先使用这个地址构建\n$env:FLUTTER_STORAGE_BASE_URL=\"https://storage.flutter-io.cn\"; $env:PUB_HOSTED_URL=\"https://pub.flutter-io.cn\"; flutter build apk --release \n\n#再使用这个运行\nflutter run\n```\n\n\n记得修改一下项目android\\app\\build.gradle.kts文件的包名\n    namespace = \"com.example.farmvisualconfig\"",
  "编程语言/Flutter&Dart/Flutter常用命令.md": "\n---\n\n## 🛠️ 环境配置相关\n\n```bash\nflutter --version            # 查看 Flutter 版本\nflutter upgrade              # 升级 Flutter SDK\nflutter downgrade            # 降级到上一个版本\nflutter doctor               # 检查环境配置\nflutter config --enable-windows-desktop   # 启用 Windows 桌面支持\nflutter config --enable-web               # 启用 Web 支持\nflutter devices              # 查看可用设备\n```\n\n---\n\n## 📦 项目管理\n\n```bash\nflutter create my_app        # 创建新项目\nflutter clean                # 清理构建缓存\nflutter pub get              # 获取依赖\nflutter pub upgrade          # 升级依赖\nflutter pub outdated         # 检查依赖可更新版本\nflutter pub add http         # 添加依赖（例如 http）\nflutter pub remove http      # 移除依赖\n```\n\n---\n\n## ▶️ 运行调试\n\n```bash\nflutter run                  # 在默认设备上运行\nflutter run -d windows       # 在 Windows 桌面运行\nflutter run -d chrome        # 在浏览器运行\nflutter run -d emulator-5554 # 指定设备运行（比如 Android 模拟器）\n```\n\n---\n\n## 🏗️ 构建打包\n\n```bash\nflutter build apk            # 构建 Android APK\nflutter build appbundle      # 构建 Android AAB (上传 Google Play)\nflutter build ios            # 构建 iOS 应用\nflutter build windows        # 构建 Windows 应用\nflutter build web            # 构建 Web 应用\nflutter build linux          # 构建 Linux 应用\nflutter build macos          # 构建 macOS 应用\n```\n\n---\n\n## 🔄 热重载 / 热重启\n\n运行 `flutter run` 后，命令行里可以：\n\n- `r` → 热重载（Hot reload，保留状态）\n    \n- `R` → 热重启（Hot restart，重启应用）\n    \n- `q` → 退出运行\n    \n\n---\n\n## 🔍 代码检查 & 性能\n\n```bash\nflutter analyze              # 分析代码问题\nflutter format .             # 格式化代码（整个项目）\nflutter test                 # 运行单元测试\nflutter pub run build_runner build  # 代码生成（json_serializable 等常用）\n```\n\n---\n\n## 🌐 其他常用\n\n```bash\ndart --version               # 查看 Dart 版本\ndart pub global activate devtools   # 启用 DevTools\nflutter pub global run devtools     # 启动 DevTools\n```\n\n---\n\n📌 **最常用的组合命令**：\n\n1. `flutter pub get` → 拉依赖\n    \n2. `flutter run -d windows` → 运行调试\n    \n3. `flutter build windows` → 打包 Windows\n    \n4. `flutter clean && flutter pub get` → 出问题时清理依赖\n    \n\n---\n",
  "编程语言/Flutter&Dart/Flutter构建平台产物位置.md": "\n### 一、通用说明\n\nFlutter 项目的构建产物默认存放在项目根目录的 build 文件夹下，该文件夹会根据目标平台自动创建子目录，存放对应平台的编译文件、安装包等。\n\n### 二、各个平台构建产物位置\n\n#### 1. Android 平台\n\n**构建命令**：\nflutter build apk（默认 release 模式）、flutter build appbundle（AAB 格式）\n\n**产物位置**：\nAPK 文件：\n项目根目录/build/app/outputs/flutter-apk/\n文件名通常为 app-release.apk（release 模式）或 app-debug.apk（debug 模式）。\n\nAAB 文件（Android App Bundle）：\n项目根目录/build/app/outputs/bundle/release/app-release.aab\n\n#### 2. iOS 平台\n\n**构建命令**：\nflutter build ios（release 模式）、flutter build ios --debug（debug 模式）\n\n**产物位置**：\n编译后的应用文件（.app 格式）：\n项目根目录/build/ios/iphoneos/Runner.app（真机运行）或 build/ios/iphonesimulator/Runner.app（模拟器）。\n\nIPA 安装包（需通过 Xcode 导出）：\n若使用 flutter build ipa 命令，产物会存放在 项目根目录/build/ios/ipa/，文件名为 Runner.ipa。\n\n#### 3. 桌面平台（Windows/macOS/Linux）\n\n需先通过 flutter config --enable-[windows/macos/linux]-desktop 开启对应平台支持。\n\n***Windows**：*\n\n**构建命令：**\nflutter build windows\n\n**产物位置：**\n项目根目录/build/windows/runner/Release/（release 模式），包含可执行文件 Runner.exe 及相关依赖库。\n\n***macOS：***\n\n**构建命令：**\nflutter build macos\n\n**产物位置：**\n项目根目录/build/macos/Build/Products/Release/Runner.app（release 模式），这是一个 macOS 应用包。\n\n***Linux**：*\n\n**构建命令：**\nflutter build linux\n\n**产物位置：**\n项目根目录/build/linux/x64/release/bundle/（64 位系统），包含可执行文件 runner 及依赖文件。\n\n#### 4. Web 平台\n\n**构建命令**：\nflutter build web（默认 release 模式）\n\n**产物位置**：\n项目根目录/build/web/，包含 HTML、CSS、JavaScript 等静态文件，可直接部署到 Web 服务器（如 Nginx、Apache 等）。\n\n### 三、注意事项\n\n- **debug 与 release 模式**：debug 模式的产物通常用于开发调试，体积较大且包含调试信息；release 模式产物经过优化，适合发布，默认存放在对应平台的 release 子目录中。\n\n- **自定义输出路径**：部分命令支持通过参数指定输出路径，例如 flutter build apk --output=./my_app.apk 可将 APK 输出到根目录并命名为 my_app.apk。\n",
  "编程语言/Golang/Golang标准库热门模块.md": "\n**fmt — 字符串格式化、打印**\n常用：Print*、Sprintf、Fprintf、Errorf。\nImported by：5,417,076（go1.25.3 页面）。 \n\n**time — 时间/定时/计时**\n常用：Now、Sleep、Ticker/Timer、Parse/Format、Since/Until、time.Duration。\nImported by：2,690,536。 \n\n**strings — 字符串处理**\n常用：Contains/HasPrefix、Split/Join、Replace(All)、ToUpper/Lower、Trim*、Builder。\nImported by：2,527,595。 \n\n**os — 操作系统接口（文件、进程、环境变量）**\n常用：ReadFile/WriteFile、Open/Create、Mkdir(All)/Remove、Getenv/Setenv、Executable。\nImported by：2,364,233。 \n\n**strconv — 字符串与数字/布尔转换**\n常用：Atoi、Itoa、ParseInt/Uint/Float、FormatInt/Float、Append*。\nImported by：1,720,862。 \n\n**net/http — HTTP 客户端/服务端**\n常用：客户端 http.Client/Get/Do；服务端 ListenAndServe、Handle(Func)、Server.Shutdown、Cookie。\nImported by：1,705,800。 \n\n**io — 基础 I/O 抽象与工具**\n常用接口：Reader/Writer/Closer；工具：Copy/ReadAll/TeeReader/MultiReader/MultiWriter。\nImported by：1,492,765。 \n\n**errors — 错误构造与包装**\n常用：New、Is、As、Join、Unwrap。\nImported by：1,570,292。 \n\n**encoding/json — JSON 编解码**\n常用：Marshal/Unmarshal、NewEncoder/NewDecoder、RawMessage、Valid。\nImported by：1,437,939。 \n\n**log — 轻量日志**\n常用：Print*、Printf、SetOutput、SetFlags；（复杂需求多用第三方）\nImported by：1,357,278。 \n\n**sync — 并发原语**\n常用：Mutex/RWMutex、WaitGroup、Once、Cond、Pool。\nImported by：1,291,596。 \n\n**bytes — []byte 处理（与 strings 类似）**\n常用：Buffer、Reader、Split/Join、Replace(All)、ToUpper/Lower、Trim*。\nImported by：1,189,998。 \n\n**bufio — 带缓冲的 I/O**\n常用：Reader（ReadString/ReadBytes/Peek）、Writer（Flush）、Scanner。\nImported by：1,094,139。 \n\n**path/filepath — 跨平台文件路径**\n常用：Join/Split/Base/Dir、Ext、Abs/Rel、WalkDir、Glob。\nImported by：1,047,304。 \n\n**regexp — 正则表达式**\n常用：MustCompile、Match、ReplaceAll*、Find(All)*、SubexpNames。\nImported by：917,674。 \n\n**reflect — 反射（元编程/通用库常用）**\n常用：TypeOf/ValueOf、Value.Field/Method、DeepEqual（1.22 起也有 slices.Equal 可替代部分场景）。\nImported by：793,184。 \n",
  "编程语言/Golang/代码片段/代码片段-标准HelloWorld输出.md": "```go\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n    fmt.Println(\"Hello, World!\")\n}\n```",
  "编程语言/Golang/代码片段/代码片段-特殊HelloWorld输出.md": "```go\n//使用goroutine和channel\npackage main\n\nimport \"fmt\"\n\nfunc main() {\n    ch := make(chan string)\n    go func() {\n        ch <- \"Hello, World!\"\n    }()\n    fmt.Println(<-ch)\n}\n```",
  "编程语言/Java/Java中的map,set,list比较.md": "\n---\n\n### 核心概念总览\n\n| 特性 | List（列表） | Set（集合） | Map（映射） |\n| :--- | :--- | :--- | :--- |\n| **核心接口** | `java.util.List` | `java.util.Set` | `java.util.Map` |\n| **继承关系** | 继承自 `Collection` | 继承自 `Collection` | 独立接口，不继承 `Collection` |\n| **元素顺序** | **有序**（插入顺序） | 通常**无序**（`LinkedHashSet`等除外） | 通常**无序**（`LinkedHashMap`等除外） |\n| **元素唯一性** | **允许重复** | **不允许重复** | **Key 不允许重复**，Value 可以重复 |\n| **元素访问** | 通过**索引**（index） | 只能通过**迭代器**或增强 for 循环 | 通过 **Key** 来访问 Value |\n| **常见实现类** | `ArrayList`, `LinkedList`, `Vector` | `HashSet`, `LinkedHashSet`, `TreeSet` | `HashMap`, `LinkedHashMap`, `TreeMap`, `Hashtable` |\n| **是否允许 null** | 是 | `HashSet` 允许一个 null，`TreeSet` 不允许 | `HashMap` 允许一个 null key，`Hashtable` 不允许 |\n\n---\n\n### 1. List（列表）\n\nList 是一个**有序**的、**允许重复元素**的集合。用户可以精确控制列表中每个元素的插入位置，并且可以通过整数索引（类似于数组下标）来访问元素。\n\n**核心特性：**\n*   **有序（Ordered）**：元素按照插入的顺序存储。\n*   **可重复（Allows Duplicates）**：可以添加多个相同的元素（包括多个 `null`）。\n*   **索引访问（Indexed Access）**：提供了基于下标（从 0 开始）的 `get(int index)` 和 `set(int index, E element)` 方法。\n\n**主要实现类：**\n\n1.  **`ArrayList`**\n    *   **底层结构**：基于**动态数组**。\n    *   **特点**：\n        *   **查询快**：因为实现了 `RandomAccess` 接口，通过索引随机访问元素的速度极快（时间复杂度 O(1)）。\n        *   **增删慢**：在列表中间插入或删除元素时，需要移动后续所有元素，性能较差（平均时间复杂度 O(n)）。\n    *   **使用场景**：**查询操作远多于增删操作**的场景。这是最常用的 List 实现。\n\n2.  **`LinkedList`**\n    *   **底层结构**：基于**双向链表**。\n    *   **特点**：\n        *   **增删快**：在链表头部或尾部（已知位置）插入/删除元素很快（时间复杂度 O(1)）。在中间位置需要先遍历找到位置。\n        *   **查询慢**：按索引查询需要从头或尾开始遍历链表（平均时间复杂度 O(n)）。\n        *   实现了 `Deque` 接口，可以被用作**栈**或**队列**。\n    *   **使用场景**：需要频繁在列表**首尾进行增删操作**，或者频繁使用栈/队列结构的场景。\n\n3.  **`Vector`（已过时，不推荐使用）**\n    *   **底层结构**：基于动态数组，是线程安全的。\n    *   **特点**：其所有方法都是 `synchronized` 的，保证了线程安全，但性能开销大。\n    *   **替代品**：在需要线程安全时，可以使用 `Collections.synchronizedList(new ArrayList(...))` 或者 `CopyOnWriteArrayList`。\n\n**代码示例：**\n```java\nList<String> arrayList = new ArrayList<>();\narrayList.add(\"Apple\"); // 索引 0\narrayList.add(\"Banana\"); // 索引 1\narrayList.add(\"Apple\"); // 允许重复\narrayList.add(null); // 允许 null\n\nSystem.out.println(arrayList); // 输出：[Apple, Banana, Apple, null]\nSystem.out.println(arrayList.get(1)); // 输出：Banana\n\nList<String> linkedList = new LinkedList<>();\nlinkedList.addFirst(\"First\"); // 在头部添加\nlinkedList.addLast(\"Last\"); // 在尾部添加\n```\n\n---\n\n### 2. Set（集合）\n\nSet 是一个**不允许重复元素**的集合。它模拟了数学上的“集合”概念。最多只能包含一个 `null` 元素。\n\n**核心特性：**\n*   **唯一性（Unique Elements）**：集合中不允许存在两个相等的元素。判断相等的依据是 `equals()` 和 `hashCode()` 方法。\n*   **通常无序（Generally Unordered）**：大多数实现不保证元素的顺序（但 `LinkedHashSet` 和 `TreeSet` 例外）。\n\n**主要实现类：**\n\n1.  **`HashSet`**\n    *   **底层结构**：基于 **HashMap**（本质上是只使用了 HashMap 的 Key）。\n    *   **特点**：\n        *   **无序**：不保证元素的迭代顺序。\n        *   **性能最好**：添加、删除、查找（`contains`）操作的时间复杂度都是 **O(1)**。\n    *   **使用场景**：最常用的 Set，用于需要快速查找且不关心顺序的场景。\n\n2.  **`LinkedHashSet`**\n    *   **底层结构**：继承自 `HashSet`，但内部使用 **链表** 维护了元素的**插入顺序**。\n    *   **特点**：\n        *   **有序**：迭代顺序就是元素的插入顺序。\n        *   性能略低于 `HashSet`，因为需要维护链表。\n    *   **使用场景**：既需要 Set 的**唯一性**，又希望保留元素的**插入顺序**。\n\n3.  **`TreeSet`**\n    *   **底层结构**：基于 **红黑树**（一种自平衡的二叉查找树）。\n    *   **特点**：\n        *   **有序**：元素按照**自然顺序**（如数字从小到大，字符串字典序）或者根据构造时提供的 **Comparator** 进行排序。\n        *   添加、删除、查找操作的时间复杂度是 **O(log n)**。\n        *   **不允许 `null` 元素**。\n    *   **使用场景**：需要元素**自动排序**的场景。\n\n**代码示例：**\n```java\nSet<String> hashSet = new HashSet<>();\nhashSet.add(\"Apple\");\nhashSet.add(\"Banana\");\nhashSet.add(\"Apple\"); // 这个重复元素不会被添加\nhashSet.add(null);\n\nSystem.out.println(hashSet); // 输出可能是：[null, Apple, Banana] (无序)\n\nSet<String> linkedHashSet = new LinkedHashSet<>();\nlinkedHashSet.add(\"Banana\");\nlinkedHashSet.add(\"Apple\");\nSystem.out.println(linkedHashSet); // 输出：[Banana, Apple] (保持插入顺序)\n\nSet<Integer> treeSet = new TreeSet<>();\ntreeSet.add(3);\ntreeSet.add(1);\ntreeSet.add(2);\nSystem.out.println(treeSet); // 输出：[1, 2, 3] (自然排序)\n```\n\n---\n\n### 3. Map（映射）\n\nMap 是一个用于存储 **键值对（Key-Value Pairs）** 的集合。每个 Key 映射到一个 Value。Key 不允许重复，但不同的 Key 可以映射到相同的 Value。\n\n**核心特性：**\n*   **键值对（Key-Value Pairs）**：数据以 `Key=Value` 的形式存储。\n*   **Key 唯一（Unique Keys）**：一个 Map 中不能包含重复的 Key。判断 Key 是否重复的依据是 `equals()` 和 `hashCode()` 方法。\n*   **每个 Key 对应一个 Value**：一个 Key 只能映射到一个 Value。\n\n**主要实现类：**\n\n1.  **`HashMap`**\n    *   **底层结构**：基于 **数组+链表+红黑树**（JDK 8 以后）。\n    *   **特点**：\n        *   **无序**：不保证键值对的顺序。\n        *   **性能最好**：get 和 put 操作的时间复杂度在理想情况下是 **O(1)**。\n        *   **允许 `null` 作为 Key 和 Value**。\n    *   **使用场景**：最常用的 Map，适用于绝大多数键值对存储场景。\n\n2.  **`LinkedHashMap`**\n    *   **底层结构**：继承自 `HashMap`，并使用**链表**维护了**插入顺序**或**访问顺序**。\n    *   **特点**：\n        *   **有序**：迭代顺序可以是**插入顺序**或**访问顺序**（最近最少使用的元素在前）。\n        *   性能略低于 `HashMap`。\n    *   **使用场景**：需要保留键值对的**插入顺序**，或者用它来实现 **LRU（最近最少使用）缓存**。\n\n3.  **`TreeMap`**\n    *   **底层结构**：基于 **红黑树**。\n    *   **特点**：\n        *   **有序**：Key 按照**自然顺序**或指定的 **Comparator** 进行排序。\n        *   操作的时间复杂度为 **O(log n)**。\n        *   **不允许 `null` Key**。\n    *   **使用场景**：需要 Key **自动排序**的场景。\n\n4.  **`Hashtable`（已过时，不推荐使用）**\n    *   **底层结构**：类似 `HashMap`，是线程安全的。\n    *   **特点**：所有方法都是 `synchronized` 的，性能差。\n    *   **不允许 `null` 作为 Key 或 Value**。\n    *   **替代品**：使用 `ConcurrentHashMap` 或 `Collections.synchronizedMap(new HashMap(...))`。\n\n**代码示例：**\n```java\nMap<String, Integer> hashMap = new HashMap<>();\nhashMap.put(\"Alice\", 90);\nhashMap.put(\"Bob\", 85);\nhashMap.put(\"Alice\", 95); // 覆盖 Key \"Alice\" 原来的值\nhashMap.put(null, 100); // 允许 null key\n\nSystem.out.println(hashMap); // 输出可能是：{null=100, Bob=85, Alice=95}\nSystem.out.println(hashMap.get(\"Bob\")); // 输出：85\n\nMap<String, Integer> linkedHashMap = new LinkedHashMap<>();\nlinkedHashMap.put(\"Bob\", 85);\nlinkedHashMap.put(\"Alice\", 95);\nSystem.out.println(linkedHashMap); // 输出：{Bob=85, Alice=95} (插入顺序)\n\nMap<String, Integer> treeMap = new TreeMap<>();\ntreeMap.put(\"Orange\", 10);\ntreeMap.put(\"Apple\", 20);\nSystem.out.println(treeMap); // 输出：{Apple=20, Orange=10} (Key的字典序)\n```\n\n---\n\n### 总结与选择\n\n*   **需要允许重复且有顺序？** -> 选择 **`List`**\n    *   查询多，增删少 -> **`ArrayList`**\n    *   增删多，查询少，或需要栈/队列 -> **`LinkedList`**\n\n*   **需要元素唯一，不关心顺序？** -> 选择 **`Set`**\n    *   只关心唯一性，追求最高性能 -> **`HashSet`**\n    *   需要保留插入顺序 -> **`LinkedHashSet`**\n    *   需要元素自动排序 -> **`TreeSet`**\n\n*   **需要通过键（Key）来查找值（Value）？** -> 选择 **`Map`**\n    *   绝大多数场景，不关心顺序 -> **`HashMap`**\n    *   需要保留键值对的插入顺序或实现LRU -> **`LinkedHashMap`**\n    *   需要键自动排序 -> **`TreeMap`**\n    *   高并发场景 -> **`ConcurrentHashMap`**\n\n",
  "编程语言/Java/Java基础-处理异常方法.md": "\n## 1. 异常分类\n\n### 1.1 检查型异常 (Checked Exceptions)\n- 必须处理，否则编译不通过\n- 继承自 `Exception`\n- 示例：`IOException`, `SQLException`, `ClassNotFoundException`\n\n### 1.2 非检查型异常 (Unchecked Exceptions)\n- 不需要强制处理\n- 继承自 `RuntimeException`\n- 示例：`NullPointerException`, `ArrayIndexOutOfBoundsException`, `IllegalArgumentException`\n\n### 1.3 错误 (Errors)\n- 系统级错误，程序通常无法恢复\n- 继承自 `Error`\n- 示例：`OutOfMemoryError`, `StackOverflowError`\n\n## 2. 异常处理机制\n\n### 2.1 try-catch-finally 块\n```java\ntry {\n    // 可能抛出异常的代码\n    FileInputStream file = new FileInputStream(\"test.txt\");\n    int data = file.read();\n} catch (FileNotFoundException e) {\n    // 处理特定异常\n    System.out.println(\"文件未找到: \" + e.getMessage());\n} catch (IOException e) {\n    // 处理IO异常\n    System.out.println(\"IO错误: \" + e.getMessage());\n} finally {\n    // 无论是否发生异常都会执行\n    System.out.println(\"清理资源\");\n    // file.close(); // 实际应该在这里关闭资源\n}\n```\n\n### 2.2 try-with-resources (Java 7+)\n```java\n// 自动关闭资源，实现AutoCloseable接口的资源\ntry (FileInputStream file = new FileInputStream(\"test.txt\");\n     BufferedReader reader = new BufferedReader(new InputStreamReader(file))) {\n    \n    String line;\n    while ((line = reader.readLine()) != null) {\n        System.out.println(line);\n    }\n} catch (IOException e) {\n    System.out.println(\"读取文件失败: \" + e.getMessage());\n}\n// 不需要finally块，资源会自动关闭\n```\n\n### 2.3 多重捕获 (Java 7+)\n```java\ntry {\n    // 可能抛出多种异常的代码\n    processFile();\n} catch (FileNotFoundException | SecurityException e) {\n    // 同时处理多种异常\n    System.out.println(\"文件访问错误: \" + e.getMessage());\n} catch (IOException e) {\n    System.out.println(\"IO错误: \" + e.getMessage());\n}\n```\n\n## 3. 抛出异常\n\n### 3.1 声明抛出异常 (throws)\n```java\npublic void readFile(String filename) throws FileNotFoundException, IOException {\n    if (filename == null) {\n        throw new IllegalArgumentException(\"文件名不能为null\");\n    }\n    // 读取文件操作\n}\n```\n\n### 3.2 手动抛出异常 (throw)\n```java\npublic void setAge(int age) {\n    if (age < 0 || age > 150) {\n        throw new IllegalArgumentException(\"年龄必须在0-150之间: \" + age);\n    }\n    this.age = age;\n}\n```\n\n## 4. 自定义异常\n\n```java\n// 自定义检查型异常\nclass InsufficientFundsException extends Exception {\n    private double amount;\n    \n    public InsufficientFundsException(double amount) {\n        super(\"资金不足，缺少: \" + amount);\n        this.amount = amount;\n    }\n    \n    public double getAmount() {\n        return amount;\n    }\n}\n\n// 自定义非检查型异常\nclass BusinessException extends RuntimeException {\n    public BusinessException(String message) {\n        super(message);\n    }\n    \n    public BusinessException(String message, Throwable cause) {\n        super(message, cause);\n    }\n}\n```\n\n## 5. 异常链\n\n```java\npublic void processData() throws DataProcessingException {\n    try {\n        // 某些操作\n        readFromDatabase();\n    } catch (SQLException e) {\n        // 保留原始异常信息\n        throw new DataProcessingException(\"数据处理失败\", e);\n    }\n}\n```\n\n## 6. 异常处理的最佳实践\n\n### 6.1 应该做的 ✅\n```java\n// 1. 提供有意义的异常信息\nthrow new IllegalArgumentException(\"用户名不能为空\");\n\n// 2. 保留异常链\ncatch (IOException e) {\n    throw new BusinessException(\"业务处理失败\", e);\n}\n\n// 3. 在合适的层次处理异常\npublic void processUserRequest() {\n    try {\n        validateRequest();\n        processBusiness();\n    } catch (ValidationException e) {\n        logger.warn(\"请求验证失败\", e);\n        sendErrorResponse(\"请求参数错误\");\n    } catch (BusinessException e) {\n        logger.error(\"业务处理失败\", e);\n        sendErrorResponse(\"系统繁忙，请稍后重试\");\n    }\n}\n\n// 4. 使用具体的异常类型\n// 好：\n} catch (FileNotFoundException e) {\n// 不好：\n} catch (Exception e) {\n```\n\n### 6.2 不应该做的 ❌\n```java\n// 1. 不要忽略异常\ntry {\n    file.delete();\n} catch (SecurityException e) {\n    // 错误：空的catch块\n}\n\n// 2. 不要过度使用检查型异常\npublic void someMethod() throws Exception { // 太宽泛\n\n// 3. 不要在finally块中抛出异常\nfinally {\n    resource.close(); // 如果close()抛出异常，会掩盖原始异常\n}\n\n// 4. 不要用异常控制流程\n// 错误示例：\ntry {\n    while (true) {\n        list.get(index);\n        index++;\n    }\n} catch (IndexOutOfBoundsException e) {\n    // 用异常来结束循环\n}\n```\n\n## 7. 常见的异常处理模式\n\n### 7.1 重试机制\n```java\npublic void retryOperation(int maxRetries) {\n    int retries = 0;\n    while (retries < maxRetries) {\n        try {\n            performOperation();\n            break; // 成功则退出循环\n        } catch (TemporaryException e) {\n            retries++;\n            if (retries >= maxRetries) {\n                throw new PermanentException(\"操作失败，已达到最大重试次数\", e);\n            }\n            waitForRetry(retries);\n        }\n    }\n}\n```\n\n### 7.2 优雅降级\n```java\npublic String getConfigValue(String key) {\n    try {\n        return readFromDatabase(key);\n    } catch (DatabaseException e) {\n        logger.warn(\"数据库读取失败，使用默认配置\", e);\n        return getDefaultValue(key); // 降级方案\n    }\n}\n```\n\n## 总结\n\n| 场景 | 推荐做法 | 不推荐做法 |\n|------|----------|------------|\n| 资源管理 | try-with-resources | 手动try-catch-finally |\n| 异常信息 | 提供具体描述 | 使用泛泛的消息 |\n| 异常处理 | 在合适层级处理 | 过早捕获或完全忽略 |\n| 异常类型 | 使用具体异常类型 | 捕获过于宽泛的Exception |\n| 自定义异常 | 继承合适的父类 | 滥用RuntimeException |\n\n**核心原则**：异常应该用于处理真正\"异常\"的情况，不应该用于控制正常的程序流程。合理的异常处理能够提高代码的健壮性和可维护性。",
  "编程语言/Java/Java基础-实现多线程方法.md": "\n## 1. 继承Thread类\n```java\nclass MyThread extends Thread {\n    @Override\n    public void run() {\n        System.out.println(\"线程执行: \" + Thread.currentThread().getName());\n    }\n}\n\n// 使用\nMyThread thread = new MyThread();\nthread.start();\n```\n\n## 2. 实现Runnable接口（推荐）\n```java\nclass MyRunnable implements Runnable {\n    @Override\n    public void run() {\n        System.out.println(\"线程执行: \" + Thread.currentThread().getName());\n    }\n}\n\n// 使用\nThread thread = new Thread(new MyRunnable());\nthread.start();\n\n// 或使用Lambda表达式\nThread thread2 = new Thread(() -> {\n    System.out.println(\"Lambda线程执行\");\n});\nthread2.start();\n```\n\n## 3. 实现Callable接口（可返回结果）\n```java\nclass MyCallable implements Callable<String> {\n    @Override\n    public String call() throws Exception {\n        return \"线程执行结果\";\n    }\n}\n\n// 使用\nExecutorService executor = Executors.newSingleThreadExecutor();\nFuture<String> future = executor.submit(new MyCallable());\nString result = future.get(); // 获取返回值\nexecutor.shutdown();\n```\n\n## 4. 使用线程池（生产环境推荐）\n```java\n// 创建线程池\nExecutorService executor = Executors.newFixedThreadPool(5);\n\n// 提交任务\nfor (int i = 0; i < 10; i++) {\n    executor.execute(() -> {\n        System.out.println(\"线程池任务执行: \" + Thread.currentThread().getName());\n    });\n}\n\n// 关闭线程池\nexecutor.shutdown();\n```\n\n## 5. 使用CompletableFuture（Java 8+）\n```java\n// 异步执行\nCompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {\n    return \"异步任务结果\";\n});\n\n// 处理结果\nfuture.thenAccept(result -> System.out.println(\"收到结果: \" + result));\n```\n\n## 6. Timer和TimerTask\n```java\nTimer timer = new Timer();\ntimer.schedule(new TimerTask() {\n    @Override\n    public void run() {\n        System.out.println(\"定时任务执行\");\n    }\n}, 1000, 2000); // 延迟1秒，每2秒执行一次\n```\n\n## 总结对比\n\n| 方法 | 优点 | 缺点 | 适用场景 |\n|------|------|------|----------|\n| 继承Thread | 简单直接 | 不能继承其他类 | 简单任务 |\n| 实现Runnable | 灵活，可继承其他类 | 无返回值 | 大多数场景 |\n| 实现Callable | 有返回值，可抛异常 | 使用相对复杂 | 需要返回结果的场景 |\n| 线程池 | 资源管理，性能优化 | 配置复杂 | 生产环境，高并发 |\n| CompletableFuture | 异步编程，链式调用 | Java 8+ | 复杂的异步任务 |\n\n## 最佳实践建议\n\n1. **优先使用Runnable接口** - 更灵活，符合面向接口编程\n2. **生产环境使用线程池** - 避免频繁创建销毁线程的开销\n3. **使用Callable获取返回值** - 当需要任务执行结果时\n4. **Java 8+推荐CompletableFuture** - 提供更强大的异步编程能力\n5. **注意线程安全** - 合理使用同步机制\n\n最常用的组合是：**Runnable接口 + 线程池**，这种组合既灵活又高效。",
  "编程语言/Java/Java基础-导入java文件方法.md": "\n## 🔹 情况 1：同一个包里的多个.java文件\n\n如果两个类在同一个包（或者没写 `package`，都在默认包），\n只要把它们放在同一个目录下，直接编译就能互相使用。\n\n例子：\n\n📂 目录结构：\n\n```\nHelloWorld.java\nUtils.java\n```\n\n**HelloWorld.java**\n\n```java\npublic class HelloWorld {\n    public static void main(String[] args) {\n        Utils.sayHi();\n    }\n}\n```\n\n**Utils.java**\n\n```java\npublic class Utils {\n    public static void sayHi() {\n        System.out.println(\"Hello from Utils!\");\n    }\n}\n```\n\n**编译运行：**\n\n```bash\njavac HelloWorld.java Utils.java\njava HelloWorld\n```\n\n**输出：**\n\n```\nHello from Utils!\n```\n\n---\n\n## 🔹 情况 2：不同包的类\n\n如果你要用别的包里的类，需要用 import\n\n**目录结构：**\n\n```\nsrc/\n ├─ app/\n │   └─ HelloWorld.java\n └─ util/\n     └─ Utils.java\n```\n\n**util/Utils.java**\n\n```java\npackage util;\n\npublic class Utils {\n    public static void sayHi() {\n        System.out.println(\"Hello from util.Utils!\");\n    }\n}\n```\n\n**app/HelloWorld.java**\n\n```java\npackage app;\n\nimport util.Utils;   // 导入 util 包里的 Utils 类\n\npublic class HelloWorld {\n    public static void main(String[] args) {\n        Utils.sayHi();\n    }\n}\n```\n\n**编译：**\n\n```bash\njavac src/util/Utils.java src/app/HelloWorld.java -d out\n```\n\n**运行：**\n\n```bash\njava -cp out app.HelloWorld\n```\n\n---\n\n## 🔹 总结\n\n1. **同目录、同包**：直接用，不需要 `import`。\n2. **不同目录、不同包**：必须用 `package` 和 `import`，再用 `-d` 编译指定输出目录。\n\n---\n\n",
  "编程语言/Java/Java标准库常用异常类.md": "\n## 1. java.lang包中的核心异常类\n\n### 1.1 Error及其子类（系统错误）\n\n```java\n// 虚拟机错误\nVirtualMachineError\n    ├── OutOfMemoryError          // 内存不足\n    ├── StackOverflowError        // 栈溢出\n    ├── InternalError            // 虚拟机内部错误\n    └── UnknownError             // 未知错误\n\n// 链接错误\nLinkageError\n    ├── NoClassDefFoundError     // 类定义未找到\n    ├── ClassFormatError         // 类格式错误\n    ├── VerifyError              // 验证错误\n    ├── IncompatibleClassChangeError // 不兼容的类变更\n    │   ├── NoSuchFieldError     // 字段未找到\n    │   ├── NoSuchMethodError    // 方法未找到\n    │   └── IllegalAccessError   // 非法访问错误\n    └── UnsatisfiedLinkError     // 未满足的链接错误\n```\n\n### 1.2 Exception及其子类\n\n```java\n// 运行时异常（非检查型）\nRuntimeException\n    ├── NullPointerException           // 空指针异常\n    ├── ArrayIndexOutOfBoundsException // 数组越界\n    ├── StringIndexOutOfBoundsException // 字符串索引越界\n    ├── ClassCastException             // 类转换异常\n    ├── IllegalArgumentException      // 非法参数异常\n    │   ├── NumberFormatException      // 数字格式异常\n    │   ├── IllegalThreadStateException // 非法线程状态\n    │   └── InvalidParameterException  // 无效参数异常\n    ├── IllegalStateException          // 非法状态异常\n    ├── UnsupportedOperationException  // 不支持的操作异常\n    ├── ArithmeticException            // 算术异常\n    ├── NegativeArraySizeException     // 负数组大小异常\n    ├── ArrayStoreException            // 数组存储异常\n    ├── SecurityException              // 安全异常\n    ├── ConcurrentModificationException // 并发修改异常\n    ├── IndexOutOfBoundsException      // 索引越界异常\n    ├── NoSuchElementException         // 无此元素异常\n    └── EmptyStackException            // 空栈异常\n\n// 检查型异常\nException\n    ├── IOException (在java.io包中，但继承自Exception)\n    ├── SQLException (在java.sql包中)\n    ├── ReflectiveOperationException\n    │   ├── ClassNotFoundException    // 类未找到\n    │   ├── NoSuchMethodException     // 方法未找到\n    │   ├── NoSuchFieldException      // 字段未找到\n    │   └── IllegalAccessException    // 非法访问异常\n    ├── CloneNotSupportedException    // 克隆不支持异常\n    ├── InterruptedException          // 线程中断异常\n    └── ParseException (在java.text包中)\n```\n\n## 2. java.io包中的IO异常类\n\n```java\nIOException\n    ├── FileNotFoundException          // 文件未找到异常\n    ├── EOFException                   // 文件结束异常\n    ├── SocketException (在java.net包中)\n    ├── InterruptedIOException         // 中断IO异常\n    ├── UnsupportedEncodingException   // 不支持的编码异常\n    ├── UTFDataFormatException         // UTF数据格式异常\n    ├── SyncFailedException            // 同步失败异常\n    ├── CharConversionException        // 字符转换异常\n    ├── ObjectStreamException          // 对象流异常\n    │   ├── InvalidClassException      // 无效类异常\n    │   ├── NotSerializableException   // 不可序列化异常\n    │   ├── StreamCorruptedException   // 流损坏异常\n    │   └── WriteAbortedException      // 写入中止异常\n    ├── ZipException (在java.util.zip包中)\n    └── JarException (在java.util.jar包中)\n```\n\n## 3. java.net包中的网络异常类\n\n```java\nIOException\n    └── SocketException\n        ├── BindException              // 绑定异常\n        ├── ConnectException           // 连接异常\n        ├── NoRouteToHostException     // 无路由到主机异常\n        └── PortUnreachableException   // 端口不可达异常\n\n// 其他网络异常\nMalformedURLException                 // 错误的URL格式异常\nProtocolException                     // 协议异常\nUnknownHostException                  // 未知主机异常\nUnknownServiceException               // 未知服务异常\nURISyntaxException                    // URI语法异常\n```\n\n## 4. java.util包中的工具类异常\n\n```java\n// 并发异常\nConcurrentModificationException       // 并发修改异常\n\n// 其他工具异常\nEmptyStackException                   // 空栈异常\nInputMismatchException                // 输入不匹配异常\nNoSuchElementException                // 无此元素异常\nTooManyListenersException             // 监听器过多异常\nIllegalFormatException                // 非法格式异常\nDuplicateFormatFlagsException         // 重复格式标志异常\nUnknownFormatConversionException      // 未知格式转换异常\nMissingFormatArgumentException        // 缺少格式参数异常\nMissingFormatWidthException           // 缺少格式宽度异常\nMissingResourceException              // 缺少资源异常\n```\n\n## 5. java.util.concurrent包中的并发异常\n\n```java\nExecutionException                    // 执行异常\nCancellationException                 // 取消异常\nTimeoutException                      // 超时异常\nBrokenBarrierException                // 屏障损坏异常\nRejectedExecutionException            // 拒绝执行异常\nCompletionException                   // 完成异常\n```\n\n## 6. java.security包中的安全异常\n\n```java\nAccessControlException                // 访问控制异常\nGeneralSecurityException              // 通用安全异常\n    ├── InvalidKeyException           // 无效密钥异常\n    ├── KeyManagementException        // 密钥管理异常\n    ├── KeyStoreException             // 密钥库异常\n    ├── NoSuchAlgorithmException      // 无此算法异常\n    ├── SignatureException            // 签名异常\n    ├── CertificateException          // 证书异常\n    ├── InvalidAlgorithmParameterException // 无效算法参数异常\n    └── UnrecoverableKeyException     // 不可恢复密钥异常\n```\n\n## 7. java.text包中的文本处理异常\n\n```java\nParseException                        // 解析异常\n```\n\n## 8. java.time包中的时间异常\n\n```java\nDateTimeException                     // 日期时间异常\n```\n\n## 9. java.nio包中的NIO异常\n\n```java\nBufferOverflowException               // 缓冲区溢出异常\nBufferUnderflowException              // 缓冲区下溢异常\nInvalidMarkException                  // 无效标记异常\nReadOnlyBufferException               // 只读缓冲区异常\n```\n\n## 10. 其他重要的异常类\n\n```java\n// javax包中的异常\njavax.management.JMException\njavax.naming.NamingException\njavax.servlet.ServletException\njavax.transaction.TransactionException\n\n// 企业级异常\njavax.ejb.EJBException\njavax.persistence.PersistenceException\n```\n\n## 11. 常见的自定义异常基类\n\n虽然这些不是Java内置的，但经常被用作自定义异常的基类：\n\n```java\n// 业务异常\nBusinessException\nApplicationException\nServiceException\nDAOException\n\n// 系统异常\nSystemException\nTechnicalException\nInfrastructureException\n```\n\n## 异常类层次结构总结\n\n```\nThrowable\n├── Error (系统错误，不可恢复)\n│   ├── VirtualMachineError\n│   ├── LinkageError\n│   └── ...\n│\n└── Exception (应用程序异常)\n    ├── RuntimeException (非检查型异常)\n    │   ├── NullPointerException\n    │   ├── IllegalArgumentException\n    │   ├── IllegalStateException\n    │   └── ...\n    │\n    └── 其他Exception (检查型异常)\n        ├── IOException\n        ├── SQLException\n        ├── ReflectiveOperationException\n        └── ...\n```\n\n## 使用建议\n\n1. **选择合适的异常类型**：根据具体场景选择最合适的异常类\n2. **避免捕获过于宽泛的异常**：不要轻易捕获 `Exception` 或 `Throwable`\n3. **自定义异常**：当内置异常无法准确描述问题时，创建自定义异常\n4. **异常信息**：提供清晰、有用的异常信息\n5. **异常链**：保留原始异常信息，便于问题追踪\n\n这个列表涵盖了Java标准库中大部分常用的异常类，实际开发中还会遇到各种框架和库提供的特定异常类。",
  "编程语言/Java/代码片段/代码片段-标准HelloWorld输出.md": "```java\npublic class HelloWorld {\n    public static void main(String[] args) {\n        System.out.println(\"Hello, World!\");\n    }\n}\n```",
  "编程语言/Java/代码片段/代码片段-特殊HelloWorld输出.md": "```java\n//使用反射\nimport java.lang.reflect.Method;\n\npublic class ReflectiveHello {\n    public static void main(String[] args) throws Exception {\n        Method method = System.class.getMethod(\"out\");\n        Object out = method.invoke(null);\n        Method println = out.getClass().getMethod(\"println\", String.class);\n        println.invoke(out, \"Hello, World!\");\n    }\n}\n```",
  "编程语言/Python/Kivy/kivy编译安卓APK.md": "\n\n```bash\nsudo apt update && sudo apt upgrade -y\n\n#安装必要的依赖\nsudo apt install -y \\\n    build-essential \\\n    git \\\n    python3 \\\n    python3-pip \\\n    python3-venv \\\n    openjdk-17-jdk \\\n    unzip \\\n    zip \\\n    libffi-dev \\\n    libssl-dev \\\n    libsqlite3-dev \\\n    libjpeg-dev \\\n    libfreetype6-dev \\\n    libgl1-mesa-dev \\\n    libgles2-mesa-dev \\\n    zlib1g-dev \\\n    autoconf \\\n    automake \\\n    libtool \\\n    pkg-config \\\n    cmake \\\n    curl \\\n    lld \\\n    libncurses5\n\n#创建虚拟环境 \npython3 -m venv kivy_env\nsource kivy_env/bin/activate\n\n#升级pip\npip install --upgrade pip setuptools wheel cython\n\n#安装kivy\npip install \"kivy[base]\" kivy_examples\n#检查是否安装成功\npython -m kivy.examples.demo.touchtracer\n\n#安装 Buildozer构建环境\npip install buildozer\n#验证是否安装成功\nbuildozer --version\n\n#初始化 buildozer 配置文件\nbuildozer init\n\n#打包构建apk 开梯子！\nbuildozer android debug\n\n\n```\n\n\n```python\nfrom kivy.app import App\nfrom kivy.uix.label import Label\n\nclass MyApp(App):\n    def build(self):\n        return Label(text=\"Hello Android from Kivy!\")\n\nif __name__ == \"__main__\":\n    MyApp().run()\n\n```\n\n\n\n\n\n\n\n\n\n",
  "编程语言/Python/Python国内pip加速镜像.md": "\n---\n\n## 一、常见国内镜像源推荐\n\n以下是一些稳定且速度优异的国内 PyPI 镜像源：\n\n- **清华大学**  \n    `https://pypi.tuna.tsinghua.edu.cn/simple`\n- **阿里云**  \n    `https://mirrors.aliyun.com/pypi/simple/`\n- **中国科技大学（USTC）**  \n    `https://pypi.mirrors.ustc.edu.cn/simple/` \n- **网易**  \n    `https://mirrors.163.com/pypi/simple/`\n- **豆瓣**  \n    `http://pypi.douban.com/simple/`（推荐使用 HTTPS 若可用）\n\n---\n\n## 二、临时使用镜像方法（每次安装时添加）\n\n在你激活的虚拟环境中，使用以下方式安装包时手动指定镜像源：\n\n```bash\npip install 包名 -i https://pypi.tuna.tsinghua.edu.cn/simple\n```\n\n如果镜像为 HTTP，并提示“不受信任”，可额外加上 `--trusted-host` 参数：\n\n```bash\npip install 包名 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com\n```\n\n\n---\n\n## 三、永久配置镜像（适用于当前虚拟环境）\n\n若希望省去每次输入 -i 参数的麻烦，可以在虚拟环境中创建或修改配置文件，使 pip 默认使用国内镜像：\n\n- **Unix / macOS 下虚拟环境：**  \n    在虚拟环境目录下 `$VIRTUAL_ENV/pip.conf`\n    \n- **Windows 虚拟环境：**  \n    在 `%VIRTUAL_ENV%\\pip.ini`\n    \n\n在其中添加以下内容（以清华源为例）：\n\n```ini\n[global]\ntimeout = 120\nindex-url = https://pypi.tuna.tsinghua.edu.cn/simple\ntrusted-host = pypi.tuna.tsinghua.edu.cn\n```\n\n- `timeout`：设置最长等待时间，例如 **120 秒**，避免连接中断 \n    \n- `index-url`：指定清华镜像为默认源\n    \n- `trusted-host`：将镜像主机设为可信，避免 HTTPS 以外的警告\n    \n\n记住，pip 配置的优先级如下（高到低）：\n\n1. 虚拟环境中的配置\n    \n2. 当前用户目录中的配置\n    \n3. 全局配置（系统范围）\n    \n\n---\n\n## 四、另一种永久配置方式：使用 pip config 命令\n\n你也可以通过 pip 自带的命令来设置全局配置（不限于虚拟环境）：\n\n```bash\npip config set global.index-url https://mirrors.aliyun.com/pypi/simple/\n```\n\n随后你可以用 `pip config list` 来验证是否设置成功\n\n若想恢复到默认的官方 PyPI 源，可使用：\n\n```bash\npip config unset global.index-url\n```\n\n\n---\n\n## 五、方式对比一览\n\n|方式|优点|缺点|\n|---|---|---|\n|临时 `-i` 指定|简单快速，不改配置|每次需手动指定|\n|虚拟环境配置|仅对该虚拟环境生效|需进入每个环境配置|\n|全局配置|全局生效，无需重复配置|不够灵活，不适每个项目情况|\n\n---\n\n",
  "编程语言/Python/Pywebview库功能一览.md": "\n---\n\n## 一、基本概述\n\n- **跨平台原生 WebView 窗口**  \n    pywebview 是一个轻量级包装库，可在 Python 程序中使用 HTML/CSS/JavaScript 构建 GUI，打开原生的 WebView 窗口，适用于 Windows、macOS、Linux（GTK 或 QT）、Android 平台 ([GitHub](https://github.com/r0x0r/pywebview?utm_source=chatgpt.com \"r0x0r/pywebview: Build GUI for your Python program with ...\"), [pywebview.flowrl.com](https://pywebview.flowrl.com/blog/pywebview5.html?utm_source=chatgpt.com \"5.0 has landed - pywebview - Example\"))。\n    \n\n---\n\n## 二、核心功能分类\n\n### 1. 窗口管理功能\n\n- 使用 `webview.create_window(...)` 创建窗口，可设置属性包括：标题、加载方式（URL 或直接传 HTML）、尺寸（宽高）、位置坐标（x, y）、是否可调整大小、是否全屏、最小尺寸、隐藏窗口、无边框、阴影效果（仅限 Windows）、窗口置顶、关闭确认、背景颜色、透明、文本选择、缩放能力、拖拽能力、暗色模式等 ([pywebview.idepy.com](https://pywebview.idepy.com/guide/api?utm_source=chatgpt.com \"API - pywebview中文文档\"), [pywebview.flowrl.com](https://pywebview.flowrl.com/blog/pywebview6?utm_source=chatgpt.com \"6.0 is here | pywebview - Example\"))。\n    \n- `webview.start(...)` 启动 GUI 消息循环，可额外配置回调函数、调试模式、HTTP 服务器、用户代理、隐私模式、存储路径、本地化、菜单设置、图标、SSL 等参数 ([pywebview.idepy.com](https://pywebview.idepy.com/guide/api?utm_source=chatgpt.com \"API - pywebview中文文档\"))。\n    \n\n---\n\n### 2. JavaScript ↔ Python 双向通信\n\n- 通过 `js_api` 参数将 Python 对象暴露给 JavaScript，以便 JS 调用 Python 方法（返回 Promise）；也支持运行时调用： `window.expose(func)` ([pywebview.idepy.com](https://pywebview.idepy.com/guide/api?utm_source=chatgpt.com \"API - pywebview中文文档\"), [pywebview.flowrl.com](https://pywebview.flowrl.com/guide/usage?utm_source=chatgpt.com \"Usage | pywebview - Example\"))。\n    \n\n---\n\n### 3. 内建 HTTP 服务器支持\n\n- 自动为相对路径启动 Bottle HTTP 服务器；可在 `webview.start(http_server=True, ssl=True)` 中启用，并可传入自定义 WSGI 服务（如 Flask）作为 `url` 参数，或修改默认服务器的 SSL 行为 ([pywebview.flowrl.com](https://pywebview.flowrl.com/guide/usage?utm_source=chatgpt.com \"Usage | pywebview - Example\"), [pywebview.idepy.com](https://pywebview.idepy.com/guide/api?utm_source=chatgpt.com \"API - pywebview中文文档\"))。\n    \n\n---\n\n### 4. DOM 操作能力\n\n- 支持在 Python 端进行 DOM 操作，如元素创建、搜索、修改属性或样式，事件注册等，类似 jQuery 操作体验。提供 `window.dom` API，包括 `dom.body`、`dom.document`、`dom.create_element()`、`dom.get_element(s)`，并支持事件监听，如 click、scroll 等 ([pywebview.flowrl.com](https://pywebview.flowrl.com/blog/pywebview5.html?utm_source=chatgpt.com \"5.0 has landed - pywebview - Example\"))。\n    \n- 还支持拖拽文件，并获取完整文件路径 `event['dataTransfer']['files'][0]['pywebviewFullPath']` ([pywebview.flowrl.com](https://pywebview.flowrl.com/blog/pywebview5.html?utm_source=chatgpt.com \"5.0 has landed - pywebview - Example\"))。\n    \n\n---\n\n### 5. 事件机制\n\n- pywebview 5 引入 DOM 操作及基本事件支持（如 click 等）。\n    \n- pywebview 6 提供更先进的网络事件支持，包括 `request_sent` 和 `response_received`，可拦截并修改请求头，还新增 `initialized` 事件（GUI 渲染器选择前触发）可用于配置判定 ([pywebview.flowrl.com](https://pywebview.flowrl.com/blog/pywebview6?utm_source=chatgpt.com \"6.0 is here | pywebview - Example\"))。\n    \n\n---\n\n### 6. 全新共享状态管理（v6）\n\n- `window.state` 对象允许自动同步 JavaScript 和 Python 间的顶层属性状态，无需额外手动同步。例如在 Python 端设置 `window.state.user_name = \"Test\"`，在 JavaScript 中通过 `window.pywebview.state.user_name` 即可访问 ([pywebview.flowrl.com](https://pywebview.flowrl.com/blog/pywebview6?utm_source=chatgpt.com \"6.0 is here | pywebview - Example\"))。\n    \n\n---\n\n### 7. 平台增强功能\n\n- **Android 支持**：pywebview 5 开始支持 Android（虽然功能较限，如不支持文件对话框、多窗口、窗口控制，但基本功能可用）([pywebview.flowrl.com](https://pywebview.flowrl.com/blog/pywebview5.html?utm_source=chatgpt.com \"5.0 has landed - pywebview - Example\"))。\n    \n- **pywebview 6 优化 Android**：引入 Kivyless 实现，提高启动速度、减小包体，并支持全屏模式 ([pywebview.flowrl.com](https://pywebview.flowrl.com/blog/pywebview6?utm_source=chatgpt.com \"6.0 is here | pywebview - Example\"))。\n    \n\n---\n\n### 8. 应用设置与 UI 菜单\n\n- **应用级设置**（v5）：通过 `webview.settings` 定制行为，如控制文件下载、允许 file:// URL、外链跳转行为、调试模式下自动打开 DevTools 等 ([pywebview.flowrl.com](https://pywebview.flowrl.com/blog/pywebview5.html?utm_source=chatgpt.com \"5.0 has landed - pywebview - Example\"))。\n    \n- **窗口级菜单**（v6）：可以为每个窗口定义自定义菜单（Menu/MenueAction），类似桌面应用的菜单栏；部分平台（如 GTK + Unity）暂不支持 ([pywebview.flowrl.com](https://pywebview.flowrl.com/blog/pywebview6?utm_source=chatgpt.com \"6.0 is here | pywebview - Example\"))。\n    \n\n---\n\n### 9. 平台尤其增强与现代化\n\n- **现代化 API 调整**：pywebview 6 改进了 FileDialog 枚举、设置项存放路径、移除废弃 DOM API 等 ([pywebview.flowrl.com](https://pywebview.flowrl.com/blog/pywebview6?utm_source=chatgpt.com \"6.0 is here | pywebview - Example\"))。\n    \n- **平台特定增强**：\n    \n    - Windows：支持暗色模式自动识别\n        \n    - macOS：可隐藏默认菜单、更好的 JS prompt 支持\n        \n    - 全平台：改进屏幕坐标处理和 SSL 支持 ([pywebview.flowrl.com](https://pywebview.flowrl.com/blog/pywebview6?utm_source=chatgpt.com \"6.0 is here | pywebview - Example\"))。\n        \n\n---\n\n## 三、总结表格\n\n|功能分类|详细内容描述|\n|---|---|\n|窗口管理|多平台窗口创建与控制（尺寸、位置、样式等）|\n|JS ↔ Python 通信|js_api 和 expose 提供双向调用|\n|HTTP 服务器|内建 Bottle 服务器，可配置 SSL 与自定义 WSGI|\n|DOM 操作|从 Python 端操作 DOM 元素、事件绑定、拖拽功能|\n|事件机制|DOM 事件、网络请求事件、初始化事件|\n|状态同步|自动同步 window.state（Python ↔ JS）|\n|平台支持|Desktop 各平台 + Android，含特性差异|\n|应用配置 & 菜单|settings 配置项 + 窗口级菜单|\n|平台增强|暗色模式、JS prompt 优化、屏幕坐标、SSL 优化等|\n\n---\n",
  "编程语言/Python/代码片段/代码片段-标准HelloWorld输出.md": "```python\nprint(\"Hello, World!\")\n```",
  "编程语言/Python/代码片段/代码片段-特殊HelloWorld输出.md": "```python\n#一行代码多种写法\n# 方法1: 使用exec和编码\nexec(bytes([72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33]))\n\n# 方法2: 使用__import__\n__import__('builtins').print('Hello, World!')\n\n# 方法3: 使用字符串格式化\n(lambda x: print(x))('Hello, World!')\n\n# 方法4: 使用reduce\nfrom functools import reduce\nreduce(lambda x,y: print(x) or y, ['Hello, World!'])\n\n# 方法5: 使用列表推导\n[print('Hello, World!') for _ in range(1)]\n```",
  "编程语言/前端&HTML&CSS&JS/css注入代码合集.md": "# CSS 效果字典 — 注入代码合集\n\n> 本文档收集了 *30+* 个常用且有趣的 CSS 注入片段。每个片段都包含：\n> - **名称**（用途）\n> - **代码**（可直接复制到控制台或写入 `<style>`）\n> - **快速用法**（如何注入／如何移除）\n\n---\n\n## 使用说明（快速上手）\n- **在控制台临时注入**：把下面的 CSS 放到一个 `<style>` 标签里再 append 到 `document.head`。例如：\n```js\nconst s = document.createElement('style');\ns.textContent = `/* 把你要的 CSS 放在这里 */`;\ndocument.head.appendChild(s);\n// 移除： s.remove();\n```\n- **做成书签脚本（Bookmarklet）**：把单行 JS 从 `javascript:(function(){...})();` 开始保存为书签。\n- **长期使用**：推荐用 Stylus（仅 CSS） 或 Tampermonkey（JS 注入）管理。\n\n---\n\n# 目录\n1. 纯色背景\n2. 渐变背景\n3. 大图背景覆盖\n4. 模糊背景（玻璃效果）\n5. 彩虹文字动画\n6. 文字跑马灯\n7. 所有链接高亮\n8. 可视化网格（布局调试）\n9. 居中容器（快速调试页面布局）\n10. 旋转页面\n11. 倒色模式\n12. 灰阶/暗色模式\n13. 字体切换（Comic Sans 恶搞）\n14. 打字机效果\n15. 卡片阴影增强\n16. 元素悬停放大（hover zoom）\n17. 图片变成圆形并加边框\n18. 所有按钮变成圆角并增大\n19. 表单输入聚焦样式\n20. 隐藏页面元素（广告清理器）\n21. 打印友好（去除背景和广告）\n22. 代码高亮（简单样式）\n23. CSS 变量主题切换器（light/dark）\n24. 霓虹发光边框\n25. 浮动提示（tooltip 基础样式）\n26. 闪烁光标（输入框样式）\n27. 页面文字渐隐渐显（fade）\n28. 反色/漫画滤镜\n29. 模拟夜光（色温调整）\n30. 页面水印\n\n---\n\n## 1. 纯色背景\n**用途**：快速更换页面背景色\n\n```css\nbody { background: #f0f8ff !important; }\n```\n**用法**：把 CSS 放进 `<style>`。移除 style 节点即可。\n\n---\n\n## 2. 渐变背景\n**用途**：让页面有现代渐变效果\n\n```css\nbody {\n  background: linear-gradient(135deg, #ff9a9e 0%, #fad0c4 50%, #fbc2eb 100%) !important;\n  background-attachment: fixed !important;\n}\n```\n\n---\n\n## 3. 大图背景覆盖\n**用途**：把页面背景替换为在线图片\n\n```css\nbody {\n  background-image: url('https://picsum.photos/1600/900') !important;\n  background-size: cover !important;\n  background-position: center center !important;\n}\n```\n\n---\n\n## 4. 模糊背景（玻璃效果）\n**用途**：制造“毛玻璃”或模糊背景层\n\n```css\nbody::before{\n  content: \"\";\n  position: fixed;\n  inset: 0;\n  backdrop-filter: blur(8px) saturate(120%);\n  -webkit-backdrop-filter: blur(8px) saturate(120%);\n  pointer-events: none;\n  z-index: 99998;\n}\n```\n\n---\n\n## 5. 彩虹文字动画\n**用途**：让页面文字颜色循环变化\n\n```css\n@keyframes rainbow { 0%{color:#ff0000}20%{color:#ff7f00}40%{color:#ffff00}60%{color:#00ff00}80%{color:#0000ff}100%{color:#8b00ff} }\n*{ animation: rainbow 4s linear infinite !important; }\n```\n\n---\n\n## 6. 文字跑马灯\n**用途**：让段落文字像跑马灯一样滚动（适合短文本）\n\n```css\n.marqueeize{\n  display:inline-block;\n  white-space:nowrap;\n  animation: marquee 10s linear infinite;\n}\n@keyframes marquee{ 0%{transform:translateX(100%)} 100%{transform:translateX(-100%)} }\n\n/* 使用方法（在控制台把选择的元素加上类）：\ndocument.querySelectorAll('p, h1, h2, li').forEach(el=>el.classList.add('marqueeize'));\n*/\n```\n\n---\n\n## 7. 所有链接高亮\n**用途**：在调研或扒站时一眼看出页面中所有链接\n\n```css\na { outline: 2px dashed #ffb86b !important; }\n```\n\n---\n\n## 8. 可视化网格（布局调试）\n**用途**：显示 12 列网格帮助布局调试\n\n```css\n.grid-debug::before{\n  content: \"\";\n  position: fixed; inset:0; pointer-events:none; z-index:99999;\n  background-image: linear-gradient(transparent 0 0), linear-gradient(transparent 0 0);\n}\n/* 更强定制可把背景替换成重复线条或者半透明列 */\n```\n\n---\n\n## 9. 居中容器（快速调试页面布局）\n**用途**：临时把 body 内主要容器居中并限定宽度\n\n```css\nbody > * { max-width: 1000px; margin: 0 auto !important; }\n```\n\n---\n\n## 10. 旋转页面\n**用途**：把页面旋转 180°（搞怪/演示）\n\n```css\nhtml{ transform: rotate(180deg) !important; transform-origin: center center; }\n```\n\n---\n\n## 11. 倒色模式\n**用途**：整体颜色反转（相当于拍照底片效果）\n\n```css\nhtml{ filter: invert(100%) hue-rotate(180deg) !important; }\n```\n\n---\n\n## 12. 灰阶 / 暗色模式\n**用途**：将页面转为黑白，或更接近暗色（用于阅读）\n\n```css\nhtml{ filter: grayscale(100%) contrast(90%) !important; }\n/* 或者暗色模式 */\n:root { --bg:#0f0f12; --fg:#e6e6e6; }\nbody{ background:var(--bg) !important; color:var(--fg) !important; }\n```\n\n---\n\n## 13. 字体切换（Comic Sans 恶搞）\n**用途**：瞬间把页面字体切成 Comic Sans\n\n```css\n*{ font-family: 'Comic Sans MS', 'Comic Sans', cursive !important; }\n```\n\n---\n\n## 14. 打字机效果\n**用途**：给指定元素文字加打字机动画（需要把类加到元素）\n\n```css\n.typewriter { overflow:hidden; white-space:nowrap; border-right: .12em solid rgba(255,255,255,.75); animation: typing 3s steps(40,end), blink .7s step-end infinite; }\n@keyframes typing{ from{ width:0 } to{ width:100% } }\n@keyframes blink{ 50%{ border-color: transparent } }\n```\n\n---\n\n## 15. 卡片阴影增强\n**用途**：让页面中常见卡片组件更醒目\n\n```css\n.card, .panel, .box { box-shadow: 0 10px 30px rgba(0,0,0,0.25) !important; border-radius: 12px !important; }\n```\n\n---\n\n## 16. 元素悬停放大（hover zoom）\n**用途**：鼠标移上去时微放大，做交互提示\n\n```css\n* { transition: transform .18s ease-in-out !important; }\n*:hover { transform: translateZ(0) scale(1.02) !important; }\n```\n\n---\n\n## 17. 图片变成圆形并加边框\n**用途**：把页面所有图片做成头像样式\n\n```css\nimg { border-radius: 999px !important; border: 3px solid rgba(255,255,255,0.6) !important; object-fit: cover; }\n```\n\n---\n\n## 18. 所有按钮变成圆角并增大\n**用途**：改善按钮可点击面积\n\n```css\nbutton, input[type=button], input[type=submit], .btn { border-radius: 999px !important; padding: .8em 1.2em !important; font-weight:600; }\n```\n\n---\n\n## 19. 表单输入聚焦样式\n**用途**：给输入框加聚焦高亮\n\n```css\ninput:focus, textarea:focus, select:focus { outline: 3px solid rgba(66,153,225,0.6) !important; box-shadow: 0 0 0 4px rgba(66,153,225,0.12) !important; }\n```\n\n---\n\n## 20. 隐藏页面元素（广告清理器）\n**用途**：删除常见广告容器或悬浮元素\n\n```css\niframe, .ad, .ads, [id*='ad'], [class*='ad-'] { display: none !important; visibility: hidden !important; }\n```\n\n---\n\n## 21. 打印友好（去除背景和广告）\n**用途**：在打印前快速隐藏不必要的元素\n\n```css\n@media print {\n  body { background: white !important; color: black !important; }\n  iframe, .ad, nav, footer, .sidebar { display: none !important; }\n}\n```\n\n---\n\n## 22. 代码高亮（简单样式）\n**用途**：给 `<code>` / `<pre>` 添加基础美化\n\n```css\npre, code { background:#0b0b0b; color:#e6e6e6; padding:.4em .6em; border-radius:6px; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, 'Roboto Mono', 'Helvetica Neue', monospace; }\n```\n\n---\n\n## 23. CSS 变量主题切换器（light/dark）\n**用途**：示范如何用变量快速切换主题\n\n```css\n:root{ --bg:#ffffff; --fg:#111111; }\n[data-theme='dark']{ --bg:#0b0b0f; --fg:#e6e6e6; }\nbody{ background:var(--bg) !important; color:var(--fg) !important; }\n/* JS 切换： document.documentElement.setAttribute('data-theme','dark'); */\n```\n\n---\n\n## 24. 霓虹发光边框\n**用途**：给重要元素加炫酷发光边框\n\n```css\n.neon { box-shadow: 0 0 8px rgba(255,0,111,0.6), inset 0 0 6px rgba(255,0,111,0.2); border:1px solid rgba(255,0,111,0.5); border-radius:10px; }\n```\n\n---\n\n## 25. 浮动提示（tooltip 基础样式）\n**用途**：给带 `data-tooltip` 的元素显示悬浮提示\n\n```css\n[data-tooltip]{ position:relative; }\n[data-tooltip]:hover::after{ content: attr(data-tooltip); position:absolute; left:50%; transform:translateX(-50%); bottom:120%; white-space:nowrap; padding:.3em .6em; background:#111;color:#fff;border-radius:6px; font-size:12px; }\n```\n\n---\n\n## 26. 闪烁光标（输入框样式）\n**用途**：增强输入框的视觉焦点\n\n```css\ninput[type='text']{ caret-color: #ff5c7c; }\ninput[type='text']::placeholder{ opacity: .7; }\n```\n\n---\n\n## 27. 页面文字渐隐渐显（fade）\n**用途**：页面加载时做个渐入动画，提升体验\n\n```css\n.fade-in *{ opacity:0; transform: translateY(6px); animation: fadein .6s forwards; }\n@keyframes fadein{ to{ opacity:1; transform:none; } }\n/* 使用： document.body.classList.add('fade-in') */\n```\n\n---\n\n## 28. 反色 / 漫画滤镜\n**用途**：把页面变成卡通/漫画风格\n\n```css\nhtml{ filter: contrast(150%) saturate(130%) sepia(10%) !important; }\n```\n\n---\n\n## 29. 模拟夜光（色温调整）\n**用途**：降低蓝光，适合晚间阅读\n\n```css\nhtml{ filter: sepia(10%) hue-rotate(-20deg) brightness(0.95) !important; }\n```\n\n---\n\n## 30. 页面水印\n**用途**：给页面加浮动水印（仅视觉）\n\n```css\nbody::after{\n  content: '仅供测试 — 树萌芽';\n  position: fixed; right: 10px; bottom: 10px; opacity: .12; font-size: 14px; pointer-events:none;\n}\n```\n\n---\n\n## 额外：通用注入 / 开关 模板（JS）\n把下面的 JS 复制到控制台或做成书签，一键注入或移除指定的 CSS：\n\n```js\n(function toggleCSS(id, css){\n  let s = document.getElementById(id);\n  if(s){ s.remove(); return 'removed'; }\n  s = document.createElement('style'); s.id = id; s.textContent = css; document.head.appendChild(s); return 'added';\n})('my-fun-css', 'body{ background: #ffdead !important; }');\n```\n\n- 把 `my-fun-css` 改成有意义的 id，把 css 换成任意上面的片段。\n\n---\n\n## Tampermonkey 用户脚本模板（自动注入）\n```js\n// ==UserScript==\n// @name         Inject Custom CSS\n// @namespace    http://tampermonkey.net/\n// @version      0.1\n// @match        *://*/*\n// @grant        none\n// ==/UserScript==\n(function(){\n  'use strict';\n  const css = `/* 把 CSS 放这里 */`;\n  const s = document.createElement('style'); s.textContent = css; document.head.appendChild(s);\n})();\n```\n\n\n",
  "编程语言/前端&HTML&CSS&JS/JavaScript趣味题/JavaScript趣味题_128.md": "# JavaScript趣味题 #128\n\n> 导出时间: 2025/8/29 14:32:49\n\n## 题目\n\n输出什么？\n\n## 代码\n\n```javascript\nconst name = \"Lydia Hallie\";\nconst age = 21;\n\nconsole.log(Number.isNaN(name));\nconsole.log(Number.isNaN(age));\n\nconsole.log(isNaN(name));\nconsole.log(isNaN(age));\n```\n\n## 选项\n\nA. A: `true` `false` `true` `false`\nB. B: `true` `false` `false` `false`\nC. C: `false` `false` `true` `false` ✅\nD. D: `false` `true` `false` `true`\n\n## 正确答案\n\n**C**\n\n## 答案解析\n\n通过方法 `Number.isNaN`，你可以检测你传递的值是否为 _数字值_ 并且是否等价于 `NaN`。`name` 不是一个数字值，因此 `Number.isNaN(name)` 返回 `false`。`age` 是一个数字值，但它不等价于 `NaN`，因此 `Number.isNaN(age)` 返回 `false`.\n\n通过方法 `isNaN`，你可以检测你传递的值是否一个 number。`name` 不是一个 `number`，因此 `isNaN(name)` 返回 `true`. `age` 是一个 `number` 因此 `isNaN(age)` 返回 `false`.\n\n---\n\n*本题目来源于JavaScript趣味题集合*\n*导出工具: JavaScript趣味题网页版*\n",
  "编程语言/前端&HTML&CSS&JS/JavaScript趣味题/JavaScript趣味题_18.md": "# JavaScript趣味题 #18\n\n> 导出时间: 2025/8/29 14:53:34\n\n## 题目\n\n输出是什么？\n\n## 代码\n\n```javascript\nfunction checkAge(data) {\n  if (data === { age: 18 }) {\n    console.log('You are an adult!')\n  } else if (data == { age: 18 }) {\n    console.log('You are still an adult.')\n  } else {\n    console.log(`Hmm.. You don't have an age I guess`)\n  }\n}\n\ncheckAge({ age: 18 })\n```\n\n## 选项\n\nA. A: `You are an adult!`\nB. B: `You are still an adult.`\nC. C: `Hmm.. You don't have an age I guess` ✅\n\n## 正确答案\n\n**C**\n\n## 答案解析\n\n在测试相等性时，基本类型通过它们的值（value）进行比较，而对象通过它们的引用（reference）进行比较。JavaScript 检查对象是否具有对内存中相同位置的引用。\n\n题目中我们正在比较的两个对象不是同一个引用：作为参数传递的对象引用的内存位置，与用于判断相等的对象所引用的内存位置并不同。\n\n这也是 `{ age: 18 } === { age: 18 }` 和 `{ age: 18 } == { age: 18 }` 都返回 `false` 的原因。\n\n---\n\n*本题目来源于JavaScript趣味题集合*\n*导出工具: JavaScript趣味题网页版*\n",
  "编程语言/前端&HTML&CSS&JS/JavaScript趣味题/JavaScript趣味题_28.md": "# JavaScript趣味题 #28\n\n> 导出时间: 2025/8/29 14:28:13\n\n## 题目\n\n输出是什么？\n\n## 代码\n\n```javascript\nString.prototype.giveLydiaPizza = () => {\n  return 'Just give Lydia pizza already!'\n}\n\nconst name = 'Lydia'\n\nname.giveLydiaPizza()\n```\n\n## 选项\n\nA. A: `\"Just give Lydia pizza already!\"` ✅\nB. B: `TypeError: not a function`\nC. C: `SyntaxError`\nD. D: `undefined`\n\n## 正确答案\n\n**A**\n\n## 答案解析\n\n`String` 是内置的构造函数，我们可以向它添加属性。我只是在它的原型中添加了一个方法。基本类型字符串被自动转换为字符串对象，由字符串原型函数生成。因此，所有 string(string 对象) 都可以访问该方法！\n\n---\n\n*本题目来源于JavaScript趣味题集合*\n*导出工具: JavaScript趣味题网页版*\n",
  "编程语言/前端&HTML&CSS&JS/nodejs的markdown库.md": "1. **markdown-it**:\n   \n   - **简介**: 一个功能强大且可扩展的 Markdown 解析器，支持插件和自定义规则。\n   - **安装**: 可以通过 npm 安装：`npm install markdown-it`\n   - **使用示例**:\n     ```javascript\n     const MarkdownIt = require('markdown-it');\n     const md = new MarkdownIt();\n     const result = md.render('# 你好，Markdown!');\n     console.log(result);\n     ```\n   \n2. **marked**:\n   - **简介**: 一个快速、轻量级的 Markdown 解析器，支持自定义渲染器。\n   - **安装**: 使用 npm 安装：`npm install marked`\n   - **使用示例**:\n     ```javascript\n     const marked = require('marked');\n     const result = marked('# 你好，Markdown!');\n     console.log(result);\n     ```\n\n3. **remark**:\n   - **简介**: 一个强大的 Markdown 处理库，支持解析、检查和转换 Markdown 文档。\n   - **安装**: 通过 npm 安装：`npm install remark remark-html`\n   - **使用示例**:\n     ```javascript\n     const remark = require('remark');\n     const html = require('remark-html');\n     \n     remark()\n       .use(html)\n       .process('# 你好，Markdown!', function (err, file) {\n         if (err) throw err;\n         console.log(String(file));\n       });\n     ```\n\n这些库各有优点，选择哪个库取决于您的具体需求，比如性能、可扩展性、支持的特性等。如果你需要简单的解析和渲染，`marked` 和 `markdown-it` 都是不错的选择；如果需要更多的可扩展性和插件支持，`remark` 可能更适合。",
  "编程语言/前端&HTML&CSS&JS/OpenList.md": "```html\n\n```",
  "编程语言/前端&HTML&CSS&JS/React打包成Windows和Android软件方案.md": "\n# 核心思路（快速决策）\n\n- **Windows（成熟 & 快）**：用 **Electron** + `electron-builder`（或 Electron Forge）把 web 前端放进 WebView，桌面端直接运行／或同时启动本地后端进程。成熟、生态完善、发布流程（安装包、自动更新、签名）有现成方案。\n- **Windows（瘦体积）**：若关心体积、原生安全，考虑 **Tauri**（Rust 后端，最终二进制更小）。但学习/环境比 Electron 略复杂。\n- **Android（快 & 直接把现有 web 变原生）**：用 **Capacitor**（Ionic 团队）把生产构建的前端打包成 Android 原生工程，再用 Android Studio 打包签名上传 Play。对保留现有 React 网页最省力。\n- **Android（PWA 路线，最快上线）**：如果你的 React 是 PWA（有 service worker、HTTPS、manifest），可以做 **Trusted Web Activity (TWA)**，用 Bubblewrap/PWABuilder 生成 Android 包并上架（适合想最小工作量上 Play 的场景）。\n\n下面给出每条路线的**实战步骤、常见陷阱和示例命令**。\n\n---\n\n# 路线 A — 推荐（最快、最成熟）：**Electron（Windows） + Capacitor（Android）**\n\n适合：不想重写、后端可以继续作为远端服务（推荐），要快速得到桌面 + Android 双端。\n\n## 1) 通用准备（前端）\n\n1. 把 React 做生产构建（示例用 CRA / Vite）：  \n    `npm run build`（或 `yarn build`），生成 `dist/` 或 `build/`。\n2. 确保所有 API 用 HTTPS、CORS、并把生产 API 域配置好（不要在客户端明文放敏感秘钥）。\n    \n\n## 2) Windows：Electron + electron-builder（快速、成熟）\n\n概念：Electron 启一个 native 窗口并加载你的静态 `build/`。用 `electron-builder` 打包成 installer（NSIS/MSI/portable）并可做代码签名与自动更新。\n\n快速步骤（最小）：\n\n- 项目根目录加入 `electron` 主进程文件（`main.js`），让它加载 `build/index.html`。\n- 安装依赖并配置打包：\n    \n\n```bash\n# 依赖\nnpm install --save-dev electron electron-builder\n# package.json scripts 示例\n\"scripts\": {\n  \"build:web\": \"npm run build\",         # 你的 React build\n  \"start:electron\": \"electron .\",\n  \"dist\": \"npm run build:web && electron-builder\"\n},\n\"build\": {\n  \"appId\": \"com.yourcompany.app\",\n  \"files\": [\"build/**/*\", \"main.js\", \"package.json\"],\n  \"win\": {\"target\":[\"nsis\",\"portable\"]}\n}\n```\n\n- 本地测试：`npm run start:electron`。\n    \n- 生成发布包：`npm run dist`（electron-builder 会产出 `.exe` / `.msi` / installer）。\n    \n\n**如果需要把后端随应用打包（可选但更复杂）**：  \n常见做法是把 Node 后端打成独立 exe（用 `pkg` 或 `nexe`），在 Electron 启动时用 `child_process.spawn()` 启动本地服务，再让前端调用 `http://localhost:xxxx`。这样用户本地拥有完整后端（适合离线或内网部署）。示例工具：`pkg`、`nexe`。注意：安全、端口冲突、自动更新、杀进程清理等需要处理。 \n\n常见注意点：\n\n- Electron 应用体积通常较大（几十 MB 起）；自动更新、签名（Authenticode）建议上线前完成。\n- 在 CI（如 GitHub Actions）上可以交叉构建，但 Windows 的代码签名通常在 Windows runner 或专门流程中完成。\n    \n\n---\n\n## 3) Android：Capacitor（把 web 打包成原生 APK/AAB）\n\n概念：Capacitor 将你的 `build/` 内容嵌入到一个原生 Android 项目（WebView），并提供与原生桥接的插件 API。非常适合把现有 web 转 app。\n\n快速步骤（最小）：\n\n```bash\n# 在项目根（build 已存在）\nnpm install @capacitor/core @capacitor/cli\nnpx cap init \"MyApp\" com.example.myapp --web-dir=build\nnpx cap add android\n# 每次 web 有新 build：\nnpm run build\nnpx cap copy android\nnpx cap open android   # 在 Android Studio 中打开，构建、签名、导出 AAB\n```\n\n在 Android Studio 中使用 **Build → Generate Signed Bundle / APK** 来生成签名的 AAB 上传到 Play（Play 推荐上传 AAB）。发布与签名细节见 Google Play 签名文档（Play App Signing）。\n\n常见注意点：\n\n- 若后端是远端 API，Android 里可直接请求远端；若需要本地 DB，使用 SQLite 或 Capacitor 的 Storage/插件而不是在设备上运行完整 Node 后端。\n- 调试网络（开发时指向本地 dev server）可用 `npx cap open android` 并在 `capacitor.config.*` 设置 `server.url` 来启用 live reload（但生产请编译静态文件）。\n    \n\n---\n\n# 路线 B — 可选：**Tauri（Windows 更小） + Capacitor/TWA（Android）**\n\n- 若你很在意桌面体积与原生安全性，**Tauri** 是比 Electron 更轻量的替代品（用 Rust 来打包、使用系统 WebView），生成的二进制更小且性能好。缺点：本地构建环境（Rust / MSVC）和插件生态比 Electron 小一些。\n- Android 仍建议用 Capacitor 或 TWA 路线（Tauri 的移动支持还在发展中）。\n    \n\nTauri 打包基本：`npm run build`（前端）然后 `tauri build`（生成 Windows installer / exe）——详见 Tauri 分发文档（Windows 打包细节、WebView2 要求等）。\n\n---\n\n# 路线 C — 直接 PWA → Play（最快上架 Android）\n\n如果你的 React 已经是 PWA（manifest + SW），通过 **TWA**（Trusted Web Activity）把 PWA 裹进一个最小的 Android 应用是最快的上 Play 方式：用 **Bubblewrap** / PWABuilder 生成项目，然后签名上传 Play。适合不需要本地原生 API，仅需离线缓存与简单推送的场景。\n\n---\n\n# 后端打包 vs 远端服务的建议（关键设计决策）\n\n- **优先把后端作为远端服务**（部署到云/内网）——理由：升级、补丁、数据库统一管理、安全容易；前端变体（桌面/Android/PWA）都指向同一 API，开发运维简单。\n- 仅在必须（离线、内网隔离）时，把后端打包到桌面：用 `pkg` / `nexe` 做 Node -> exe，再由 Electron 启动子进程（`child_process.spawn`）。Android 上嵌入 Node 很麻烦（可选 nodejs-mobile，但生态少），因此若后端要内嵌，桌面比手机更现实。\n    \n\n---\n\n# 上线前必须做的成熟化步骤（checklist）\n\n1. **安全**：HTTPS、CSP、Key/Secret 不放前端；XSS/CSRF/认证策略。\n2. **签名与发布**：Windows 用 Authenticode 证书签名；Android 用 Play App Signing（上传签名/上传 key）。\n3. **自动更新**：Electron 有 `electron-updater`/electron-builder 集成；考虑 OTA 策略。\n4. **CI/CD**：用 GitHub Actions / Azure / CircleCI 自动构建 web、electron dist、Android AAB（包含签名步骤）。\n5. **测试**：多架构/多机型测试、模拟断网、升级回滚测试。\n6. **体积优化**：压缩静态资源、剔除 dev 依赖、考虑 Tauri 以减小 exe 体积。\n    \n\n---\n\n# 推荐组合（按你想要的结果选）\n\n- **最快上手 + 最成熟**：Electron（Windows） + Capacitor（Android），后端保留云端。\n- **追求二进制最瘦**：Tauri（Windows） + Capacitor/TWA（Android）。\n- **只想最快上线到 Play（不做原生功能）**：PWA → TWA（Bubblewrap/PWABuilder）。\n    \n\n---\n\n# 我可以直接帮你做的事（选一项即可回复）\n\n1. 给你一份针对你 current React 项目的 **具体脚本（package.json）+ Electron 主进程示例 + electron-builder 配置**（Windows 一键打包脚本）。\n2. 给你一份 **Capacitor 打包到 Android 的 step-by-step 脚本 & Android Studio 签名操作流水线**（含 AAB 签名命令示例）。\n3. 或者把 **把后端打包为 exe 的示例（pkg/nexe）并在 Electron 中 spawn 的最小示例** 发给你。\n\n告诉我你要哪一项（例如“给我 Electron + 打包脚本”），我立刻把完整代码/命令/CI 配置直接生成给你（无需你再提供额外信息即可开始）。\n\n---\n",
  "编程语言/前端&HTML&CSS&JS/代码片段/代码片段-标准HelloWorld输出.md": "```javascript\nconsole.log(\"Hello, World!\");\n```",
  "编程语言/前端&HTML&CSS&JS/代码片段/代码片段-特殊HelloWorld输出.md": "```javascript\n//各种奇奇怪怪的方法\n// 方法1: 使用Unicode转义\nconsole.log('\\u0048\\u0065\\u006c\\u006c\\u006f\\u002c\\u0020\\u0057\\u006f\\u0072\\u006c\\u0064\\u0021');\n\n// 方法2: 使用Array和join\nconsole.log(['Hello', 'World!'].join(', '));\n\n// 方法3: 使用定时器\nsetTimeout(() => console.log('Hello, World!'), 0);\n\n// 方法4: 使用Promise\nPromise.resolve('Hello, World!').then(console.log);\n\n// 方法5: 使用函数式编程\n[].concat('Hello, World!').map(console.log);\n```",
  "编程语言/前端&HTML&CSS&JS/初始化一个React项目教程.md": "\n---\n\n# ✅ **方式一：使用 Vite 初始化 React 项目（推荐，最快最轻量）**\n\n### **1. 安装 Node.js（必须）**\n\n确保 Node 版本 ≥ 18  \n检查：\n```bash\nnode -v\n```\n\n---\n\n### **2. 使用 Vite 创建 React 项目**\n\n```bash\nnpm create vite@latest my-react-app -- --template react\n```\n如果你想要 TypeScript 版本：\n```bash\nnpm create vite@latest my-react-app -- --template react-ts\n```\n\n---\n\n### **3. 安装依赖**\n\n```bash\ncd my-react-app\nnpm install\n```\n\n---\n\n### **4. 启动开发环境**\n\n```bash\nnpm run dev\n```\n浏览器访问提示的 localhost 地址即可。\n\n---\n\n# ✅ **方式二：使用 Create-React-App（传统方案，不推荐但能用）**\n\n（CRA 已多年未更新，官方推荐迁移到 Vite）\n\n### 1. 创建项目\n\n```bash\nnpx create-react-app my-react-app\n```\n\n### 2. 启动项目\n\n```bash\ncd my-react-app\nnpm start\n```\n\n---\n\n# ✅ **方式三：使用 Next.js（如果你准备做大一点的项目）**\n\n如果你想做：  \n✔ SEO  \n✔ 服务端渲染  \n✔ 大型项目结构  \n✔ API 路由\n\n推荐 Next.js：\n\n```bash\nnpx create-next-app@latest\n```\n\n---\n",
  "编程语言/前端&HTML&CSS&JS/前端html导入css和js方法.md": "\n---\n\n## 1) 本地文件（Local）\n\n**说明**：把资源放在自己服务器 / 项目目录，通过相对或绝对路径引用（`/assets/`、`./`、`../` 等）。\n\n**示例**\n\n```html\n<!-- CSS（放 head） -->\n<link rel=\"stylesheet\" href=\"/css/main.css\">\n\n<!-- JS（放 body 末尾或 head + defer） -->\n<script src=\"/js/app.js\" defer></script>\n```\n\n**优点**\n\n- 完全可控：部署、版本、更新由自己管理。\n- 离线/内网可用（不依赖外部网络）。\n- 容易与构建流程（hash、cache-bust）集成。\n\n**缺点**\n\n- 需要自己承担带宽与缓存策略。\n- 同一资源不会被不同站点共享缓存（除非使用统一 CDN）。\n- 初次请求可能比公共 CDN 略慢（取决于服务器配置/地域）。\n\n---\n\n## 2) 网页链接 / CDN（Remote）\n\n**说明**：引用第三方 URL（例如公用 CDN、第三方库托管），常用于库（jQuery、Bootstrap）、字体、图标或通用资源。\n\n**示例**\n\n```html\n<!-- CSS（CDN） -->\n<link rel=\"stylesheet\" href=\"https://cdn.example.com/bootstrap/5.0.0/bootstrap.min.css\">\n\n<!-- JS（CDN + SRI + crossorigin） -->\n<script src=\"https://cdn.example.com/jquery/3.7.0/jquery.min.js\"\n        integrity=\"sha384-abc123...\"\n        crossorigin=\"anonymous\"></script>\n\n<!-- 分析类脚本可用 async -->\n<script src=\"https://cdn.example.com/analytics.js\" async></script>\n```\n\n**优点**\n\n- 全球分发、通常延迟更低、CDN 节点可被多站点共享缓存。\n- 节省自家带宽；外部资源常有高可用性。\n- 快速集成常用库（省去打包/托管工作）。\n\n**缺点**\n\n- 依赖第三方可用性与隐私/合规（跨域、GDPR、内网限制）。\n- 安全风险：若 CDN 被劫持会影响站点（可用 SRI + crossorigin 缓解）。\n- 访问受限时（企业内网、无外网环境）会失败。\n\n---\n\n## 对比速览（关键点）\n\n- 控制权：本地 ✅✅ | CDN ✅（较弱）\n- 性能（首屏/全球）：CDN ✅ | 本地 视服务器而定\n- 可用性（离线/内网）：本地 ✅ | CDN ❌\n- 缓存共享：CDN ✅ | 本地 ❌\n- 安全（篡改风险）：本地 ✅ | CDN 需 SRI+cors\n\n---\n\n## 最佳实践（简短清单）\n\n- **CSS**：放 `<head>`；关键 CSS 可内联；非关键可 `preload` + onload 切换。\n- **JS**：外部脚本优先用 `defer`（保持顺序），第三方可用 `async`（若相互独立）。\n- **版本管理**：本地资源使用 hash（`app.abc123.js`）或 querystring（`?v=20251030`）做 cache-bust。\n- **安全**：使用 CDN 时为第三方静态资源加 `integrity` + `crossorigin`。\n- **回退/兼容**：必要时对重要外部资源提供本地回退（先尝试 CDN，失败再加载本地）。\n- **隐私合规**：评估第三方脚本会不会传输用户数据，必要时加载前征得同意。\n    \n\n---\n",
  "编程语言/前端&HTML&CSS&JS/纯静态网页的强大功能与应用.md": "# 纯静态网页的功能与应用\n\n纯静态网页（仅由 HTML、CSS、JavaScript 组成，不依赖后端服务器动态生成内容）的能力远比想象中强大，借助现代前端技术和 API，它可以实现丰富的功能和复杂的交互体验。以下是纯静态网页能实现的典型场景和功能：\n\n### 1. **精美展示型网站**\n\n*   **企业官网 / 个人作品集**：通过 HTML 结构 + CSS（如 Tailwind、Flexbox/Grid）实现响应式布局，配合动画效果（CSS 动画、过渡）展示品牌形象、产品信息或个人作品。\n\n*   \\*\\* landing page（落地页）\\*\\*：聚焦营销目标，通过滚动动画、视差效果、表单（前端验证）提升用户转化率，无需后端即可收集表单数据（可通过第三方 API 如 Google Forms、Typeform 转发）。\n\n*   **文档 / 知识库**：用 HTML 构建结构化内容，结合 JavaScript 实现搜索、目录跳转、暗黑模式切换等功能（如 VuePress、Docsify 生成的静态文档）。\n\n### 2. **交互式工具与应用**\n\n*   **离线可用工具**：\n\n\n    *   计算器、单位转换器、倒计时器等轻量工具（依赖 JavaScript 逻辑）。\n    *   文本处理工具（如 Markdown 编辑器、代码格式化、正则表达式测试器）。\n    *   图像简单处理（如裁剪、滤镜，基于 Canvas API）。\n\n*   **数据可视化应用**：通过 D3.js、Chart.js 等库，将本地数据（JSON/CSV）转化为交互式图表（折线图、地图、3D 模型），无需后端计算。\n\n*   **小游戏**：利用 Canvas、WebGL 或 SVG 实现 2D/3D 游戏（如贪吃蛇、拼图、像素游戏），通过 LocalStorage 保存进度。\n\n### 3. **本地数据管理**\n\n*   借助`localStorage`/`sessionStorage`存储用户数据，实现：\n\n\n    *   待办事项（Todo）列表（增删改查、分类标签）。\n    *   个人笔记（支持富文本编辑，基于 Quill、TinyMCE 等库）。\n    *   浏览历史、偏好设置记忆（如主题、语言切换）。\n\n*   通过 IndexedDB 存储大量结构化数据（如本地日志、离线缓存的表格数据），支持复杂查询。\n\n### 4. **多媒体体验**\n\n*   **音频 / 视频应用**：用 HTML5 的`<audio>`/`<video>`结合 JavaScript 实现自定义播放器（进度条、倍速、字幕切换）。\n\n*   **交互式画廊**：支持图片轮播、缩放、拖拽排序（基于 JavaScript 事件处理）。\n\n*   **3D 与 AR 体验**：通过 WebGL（Three.js 库）实现 3D 模型展示、全景漫游；借助 WebXR API 实现简单 AR 效果（如手机摄像头叠加 2D 图形）。\n\n### 5. **跨平台与离线能力**\n\n*   **PWA（渐进式 Web 应用）**：通过 Service Worker 实现离线访问、资源缓存，添加到手机桌面后接近原生 App 体验（如离线新闻阅读、本地工具）。\n\n*   **跨设备适配**：利用 CSS 媒体查询和 JavaScript 检测设备特性，在 PC、平板、手机上提供一致体验。\n\n### 6. **集成第三方服务扩展功能**\n\n纯静态网页可通过 API 调用扩展能力（无需自建后端）：\n\n*   表单提交：通过 Netlify Forms、Formspree 等服务将数据发送到邮箱或数据库。\n\n*   用户认证：集成 Auth0、Firebase Auth 实现登录注册（前端处理令牌验证）。\n\n*   数据存储：用 Firebase Realtime Database、Supabase 等托管数据库，前端直接读写数据。\n\n*   支付功能：对接 Stripe、PayPal 的前端 SDK 实现支付流程（无需后端处理敏感信息）。\n\n### 局限性与解决方案\n\n静态网页的核心限制是 “无后端”，但可通过以下方式弥补：\n\n*   数据持久化：依赖第三方 API 或客户端存储（LocalStorage/IndexedDB）。\n\n*   动态内容：通过 JavaScript 动态加载远程 JSON 数据（如从 GitHub Gist、Contentful 等 CMS 拉取内容）。\n\n*   服务器功能：用 Serverless 函数（如 Vercel Functions、Cloudflare Workers）处理简单后端逻辑（如数据验证、API 转发），仍保持前端为主的架构。\n\n### 总结\n\n纯静态网页适合构建 “前端驱动、交互密集、内容相对固定” 的应用，借助现代前端技术和第三方服务，其能力已覆盖从展示型网站到复杂工具的广泛场景，且具有加载快、部署简单（可托管于 CDN 或静态托管服务如 Netlify、Vercel）、成本低等优势。\n",
  "计算机科普/C,C++,CSharp,Objective-c的差异与特点.md": "\n---\n\n## 一、语言概况与发展历史\n\n|语言|年代 / 背景|设计目标 / 核心理念|所属范式 / 特点|\n|---|---|---|---|\n|**C**|1970年代，Dennis Ritchie 在贝尔实验室为 Unix 开发|简洁、高效、接近硬件、可移植|过程式、结构化编程，低级控制能力强|\n|**C++**|1980年代中期，Bjarne Stroustrup 在 C 基础上扩展|在保留 C 性能和灵活性的基础上，加入面向对象与泛型编程|多范式：过程式 + 面向对象 + 泛型 + 元编程|\n|**Objective-C**|1980年代，由 Brad Cox 和 Tom Love 开发|将面向对象（消息传递机制）加到 C 上（兼容 C）|C 的超集 + Smalltalk 风格消息机制 + 动态特性 ([维基百科](https://en.wikipedia.org/wiki/Objective-C?utm_source=chatgpt.com \"Objective-C\"))|\n|**C#**|2000 年代，由微软为 .NET 平台设计|现代化语言特性、安全性、生产力、面向对象 & 托管运行时|面向对象为主，带垃圾回收、LINQ、泛型、异步编程、元数据支持等|\n\n---\n\n## 二、主要语言特性对比（从多个维度）\n\n下面从类型系统、内存管理、继承与多态、泛型/模板、运行时能力、性能与安全性、语言灵活性等维度来对比。\n\n| 维度                  | **C**                         | **C++**                         | **Objective-C**                                                                                                                                               | **C#**                                           |\n| ------------------- | ----------------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |\n| **类型系统 / 静态 vs 动态** | 静态类型；弱类型转换较宽松（例如指针可转换）        | 静态类型 + 可以做动态类型检查（RTTI）          | 同时拥有静态与动态特性，消息机制在运行期解析。Objective-C 的方法调用是以消息（message）方式传递，在运行期解析。 ([维基百科](https://en.wikipedia.org/wiki/Objective-C?utm_source=chatgpt.com \"Objective-C\"))    | 静态类型 + 有反射机制、动态编程支持（dynamic 类型关键字等）              |\n| **内存管理**            | 手动管理：malloc/free、栈/静态分配       | 手动管理 + RAII（资源获取即初始化）、构造/析构函数   | 最初是手动 retain/release；后期引入 ARC（Automatic Reference Counting）减少手动管理复杂度 ([维基百科](https://en.wikipedia.org/wiki/Objective-C?utm_source=chatgpt.com \"Objective-C\")) | 托管内存，由垃圾回收器 (GC) 管理内存分配与回收                       |\n| **继承 / 多态 / 接口**    | 无继承 / 无面向对象机制                 | 支持单继承 + 多重继承 + 虚函数              | 只支持单继承（不能多继承实现） + 协议（protocols，相当于接口的机制） ([维基百科](https://en.wikipedia.org/wiki/Objective-C?utm_source=chatgpt.com \"Objective-C\"))                             | 支持单继承 + 接口 (interface) + 虚方法 + 抽象类等              |\n| **泛型 / 模板**         | 无                             | C++ 提供强大的模板机制（泛型编程、元编程）         | 在早期 Objective-C 中泛型支持较弱；后来 Apple 在某些场景下用泛型约束、id、id 模式来模拟泛型功能                                                                                                  | 内置泛型 (generics)，语言层面支持类型安全的泛型编程                  |\n| **编译时 vs 运行时决定**    | 静态决定几乎一切                      | 多量的静态优化 (模板展开、内联、编译期多态)         | 更偏向运行时，消息机制在运行期解析，允许更灵活的动态行为（如动态消息转发、方法替换等） ([维基百科](https://en.wikipedia.org/wiki/Objective-C?utm_source=chatgpt.com \"Objective-C\"))                          | 虽然很多机制静态化，但也支持反射、动态类型、LINQ 表达式树等运行时特性            |\n| **性能、效率**           | 非常接近硬件、开销小                    | 高性能，可做底层优化、零抽象开销（若设计得好）         | 性能略弱于 C++，因为其运行期特性限制了一些优化（例如消息调用不能像普通函数调用那样被强行内联） ([维基百科](https://en.wikipedia.org/wiki/Objective-C?utm_source=chatgpt.com \"Objective-C\"))                    | 性能相对较好，但因 GC 存在停顿、托管开销等，通常不如 C/C++ 在极端性能要求场景下表现好 |\n| **安全性 / 内存安全**      | 不提供很多安全保护，容易出错（缓冲区溢出、未初始化访问等） | C++ 尽可能提供机制（如引用、智能指针等），但程序员仍需谨慎 | 相比 C/C++ 更灵活与安全一些，但仍有可能因为动态机制导致运行期错误                                                                                                                          | 较高安全保障（托管内存、类型检查、异常机制等）                          |\n| **语言灵活性 / 扩展性**     | 简洁、灵活、允许极端底层操作                | 非常灵活（运算符重载、模板、策略模式等）            | 在动态特性方面更灵活（方法转发、类别（categories）扩展已有类等） ([维基百科](https://en.wikipedia.org/wiki/Objective-C?utm_source=chatgpt.com \"Objective-C\"))                                | 在现代语言特性（异步、LINQ、表达式、元数据）方面非常强大和生产力高              |\n\n---\n\n## 三、各自的优点与适用场景\n\n下面逐个总结它们的典型优点与适用场景。\n\n### C 的优点与场景\n\n**优点**\n\n- 简洁、语法少、运行效率高，开销小\n- 可以非常贴近系统、硬件层面做操作\n- 可移植性强（在不同平台都能编译）\n- 许多底层库和系统组件（操作系统、驱动、嵌入式系统）常用 C 实现\n    \n\n**适用场景**\n\n- 操作系统、内核开发\n- 嵌入式系统、驱动程序\n- 性能极端敏感、资源受限的环境\n- 与其他语言或库做底层交互（写库、接口）\n\n---\n\n### C++ 的优点与场景\n\n**优点**\n\n- 在保持高性能的同时，支持面向对象、泛型编程、元编程\n- 模板系统允许在编译期做很多优化\n- 标准库（STL） + 丰富的生态\n- 灵活性高，可控制抽象开销\n    \n\n**适用场景**\n\n- 游戏引擎、图形渲染、实时系统\n- 高性能计算、数值模拟\n- 大型系统、需要高效率和控制的应用\n- 桌面软件、跨平台库\n    \n\n---\n\n### Objective-C 的优点与场景\n\n**优点**\n\n- 与 C 完全兼容，可以直接使用 C 代码和库\n- 采用消息传递机制，更灵活的运行时调用方式\n- 支持动态特性，如 method swizzling、消息转发、categories（可在运行时给已有类添加方法）等 ([维基百科](https://en.wikipedia.org/wiki/Objective-C?utm_source=chatgpt.com \"Objective-C\"))\n- 在 Apple 的 macOS / iOS 平台上拥有成熟框架 (Cocoa, Cocoa Touch) 支持\n\n**适用场景**\n\n- macOS / iOS 应用开发（历史上主要选项，现常与 Swift 混用）\n- 需要动态行为、运行时扩展或反射特性的场景\n- 维护已有大量 Objective-C 代码库的项目\n\n不过要注意：自从 Apple 发布 Swift 之后，很多新项目已经倾向于使用 Swift，但 Objective-C 依然在很多老项目或底层框架中存在。\n\n---\n\n### C# 的优点与场景\n\n**优点**\n\n- 现代语言特性丰富：垃圾回收、LINQ、异步/等待 (async/await)、反射、属性 (properties)、事件/委托、元数据、接口、泛型等\n- 在 .NET 平台上生态完善，工具链成熟（Visual Studio、.NET Core / .NET 运行时等）\n- 跨平台支持（.NET Core / .NET 5+ 支持 Windows、Linux、macOS）\n- 相对安全，减少内存错误和手动管理负担\n    \n\n**适用场景**\n\n- Web 后端（ASP.NET Core）\n- 桌面应用（WPF、WinForms、UWP 等）\n- 跨平台应用（通过 .NET 跨平台能力、Xamarin / MAUI 等）\n- 游戏开发（Unity 引擎使用 C#）\n- 企业级、业务系统开发\n    \n\n---\n\n## 四、它们之间最显著的区别（总结）\n\n为了便于记忆，可以关注以下几个最容易混淆、但差别很大的方面：\n\n1. **面向对象 / 继承 / 多态机制**\n    \n    - C 是纯过程式，不支持类、对象\n    - C++ 支持类、继承、多态、虚函数，多重继承（但要慎用）\n    - Objective-C 使用消息传递机制（像 Smalltalk）：所有对象调用都是发送消息，在运行期解析方法响应，不像 C++ 是编译期绑定 + 虚函数机制 ([维基百科](https://en.wikipedia.org/wiki/Objective-C?utm_source=chatgpt.com \"Objective-C\"))\n    - C# 是典型的面向对象语言，有接口、抽象类、虚方法、属性、事件等\n        \n2. **内存管理方式**\n    \n    - C、C++：手动管理（虽然 C++ 可通过 RAII、智能指针辅助）\n    - Objective-C：最初手动管理，但后期引入 ARC（编译期插入 retain / release）\n    - C#：垃圾回收机制 (GC)，开发者通常不需直接管理内存\n        \n3. **编译时 vs 运行时机制 / 灵活性**\n    \n    - C++ 更偏向编译时机制（模板展开、内联、编译期优化）\n    - Objective-C 更倾向运行时机制（动态派发、消息转发、类别等动态扩展）\n    - C# 在静态与运行时之间折中，语言设计上含有很多运行时支持 (反射、委托、表达式树等)\n        \n4. **安全性 / 抽象开销**\n    \n    - C、C++ 提供最大的灵活性和最高性能，但风险也大（指针错用、内存泄漏、未定义行为）\n    - Objective-C 较灵活，但某些抽象在运行期可能带来开销\n    - C# 强调安全、类型检查、托管环境，相对减少程序员出错的风险\n        \n5. **生态与平台绑定**\n    \n    - C / C++：跨平台能力最强\n    - Objective-C：在 Apple 平台（macOS / iOS）生态中使用广泛\n    - C#：在 .NET / Microsoft 生态中占主导，同时借助 .NET Core / Xamarin / MAUI 等实现跨平台\n        \n\n---\n\n## 五、举例说明以加深理解\n\n下面给几个简明对照（伪代码/示意）帮助理解差异：\n\n### 对象方法调用的差异（C++ vs Objective-C）\n\n- **C++**\n    \n\n```cpp\nclass Person {\npublic:\n    void sayHello() { std::cout << \"Hello\\n\"; }\n};\n\nPerson *p = new Person();\np->sayHello();  // 直接调用\n```\n\n- **Objective-C**\n    \n\n```objectivec\n@interface Person : NSObject\n- (void)sayHello;\n@end\n\n[ p sayHello ];  // 发送消息，运行期寻找响应方法\n```\n\n在 Objective-C 中，对象方法调用不是编译期固定绑定，而是运行期通过 selector / IMP 等机制解析，具有更强的动态性。([维基百科](https://en.wikipedia.org/wiki/Objective-C?utm_source=chatgpt.com \"Objective-C\"))\n\n---\n\n## 六、如何根据需求选择\n\n当你面对一个项目或任务时，下面是一个粗略的选择建议（当然还要考虑团队、已有代码、生态等因素）：\n\n- 如果你需要最接近硬件、最高性能、最小开销 —— **C / C++**\n- 如果是 Apple 平台 (macOS / iOS) 应用，且需要使用 Cocoa / Cocoa Touch 框架 —— **Objective-C**（或 Swift，现在更多人用 Swift）\n- 如果你做企业级后台、Web 服务、跨平台 C# 应用、Unity 游戏等 —— **C#** 很可能是首选\n- 如果项目对性能要求极高，又需要面向对象或泛型能力 —— **C++** 是不错选择\n- 如果你在维护已有 Objective-C 项目、或需要与旧系统兼容 —— 使用 Objective-C 是必要的\n    \n\n---\n",
  "计算机科普/clash机场三种代理模式科普.md": "\n---\n\n### 1️⃣ `rule`（规则模式）\n\n- **中文理解**：按规则走\n- **工作方式**：\n    - 根据配置文件里的 **规则列表（rules）** 来判断请求走哪条线路。\n    - 每条规则通常指定域名、IP、地理位置或者关键词对应的代理：\n        - 例如 `DOMAIN-SUFFIX,google.com,Proxy` → 访问 google.com 时走代理\n        - `DOMAIN-SUFFIX,example.com,DIRECT` → 访问 example.com 时直连\n            \n- **优点**：\n    - 灵活，可针对不同网站走不同线路。\n    - 节省带宽和延迟。\n- **缺点**\n    - 规则多时，解析略慢一些。\n---\n\n### 2️⃣ `global`（全局代理模式）\n\n- **中文理解**：所有流量都走代理\n- **工作方式**：\n    - 不看规则，所有网络请求都被发送到指定的 **代理服务器**。\n- **优点**：\n    - 配置简单，不需要维护规则。\n    - 对某些被墙网站或应用更友好。\n- **缺点**：\n    - 所有流量都经过代理，可能降低速度。\n    - 国内网站也会走代理，浪费带宽。\n---\n\n### 3️⃣ `direct`（全局直连模式）\n\n- **中文理解**：所有流量直连，不走代理\n- **工作方式**：\n    - 忽略所有规则，直接访问目标网站。\n- **优点**：\n    - 速度快，延迟低。\n    - 避免代理服务器的限制。\n- **缺点**：\n    - 无法访问被墙网站。\n    - 所有请求都走直连，规则无效。\n---\n\n### 🔹 总结对比\n\n|模式|规则依据|适用场景|\n|---|---|---|\n|`rule`|配置文件规则|兼顾国内外访问速度和被墙网站访问|\n|`global`|忽略规则，全局走代理|全局科学上网，简单直接|\n|`direct`|忽略规则，全局直连|国内访问为主，不需代理|\n\n---\n",
  "计算机科普/CPU利用率科普.md": "CPU 利用率的本质是 **CPU 核心在单位时间内执行非空闲任务（即处于“忙碌”状态）所占时间的比例**。\n\n理解这个本质需要深入以下几个关键点：\n\n1.  **“忙碌”状态的界定：**\n    *   CPU 的核心任务是从内存中获取指令、解码指令、执行指令、存储结果。\n    *   **“忙碌”状态：** 当 CPU 核心正在执行操作系统内核代码或用户程序代码（统称为“非空闲任务”）时，它就处于忙碌状态。它正在处理实际的计算、逻辑判断、数据处理等工作。\n    *   **“空闲”状态：** 当系统中所有可运行的进程/线程都在等待某些事件（如等待用户输入、等待磁盘I/O完成、等待网络数据包、等待定时器到期等）而没有任何任务需要 CPU 立即执行时，操作系统会运行一个特殊的、最低优先级的任务，通常称为 **空闲任务** 或 **空闲循环**。CPU 核心执行这个空闲任务的状态就是空闲状态。此时 CPU 虽然在运行（执行 `HLT` 指令或空循环），但并没有进行任何有意义的计算工作。现代 CPU 在空闲状态通常会降低功耗（进入 C-State）。\n\n2.  **时间片与测量原理：**\n    *   现代操作系统都是多任务操作系统，通过时间片轮转、优先级调度等算法在多个进程/线程之间快速切换 CPU 核心的执行权。\n    *   **测量单位：时间片。** 操作系统内核会周期性地（例如每毫秒或每几毫秒，由系统时钟中断驱动）检查每个 CPU 核心当前正在执行什么任务。\n    *   **统计方法：** 在每个采样时刻点（时钟中断发生时）：\n        *   如果发现 CPU 核心正在执行 **非空闲任务**（用户进程、内核线程、系统调用处理等），就记录该核心在“忙碌”。\n        *   如果发现 CPU 核心正在执行 **空闲任务**，就记录该核心在“空闲”。\n    *   **计算利用率：** 在一个特定的时间窗口内（比如1秒），CPU 利用率就是这个窗口内所有采样点中被标记为“忙碌”的次数占总采样点次数的百分比。例如：\n        *   采样间隔为 10ms (每秒采样100次)。\n        *   在1秒内，某个 CPU 核心有 80 次被采样时处于“忙碌”状态。\n        *   那么这1秒内该核心的 CPU 利用率就是 80%。\n\n3.  **核心概念：时间比例**\n    *   这 80% 的利用率意味着：在这1秒钟的时间里，该 CPU 核心有 800 毫秒（0.8秒）的时间在执行实际的工作（非空闲任务），只有 200 毫秒（0.2秒）的时间在执行无实际计算工作的空闲任务（或者处于低功耗休眠状态）。\n    *   **因此，CPU 利用率的核心本质就是 CPU 核心执行有效工作所占用的时间占总时间的百分比。**\n\n4.  **关键特性与常见误解：**\n    *   **反映的是时间占用率，而非绝对处理能力：** 100% 利用率意味着 CPU 核心在整个时间段内都在忙碌，没有空闲时间。但这**并不一定**意味着它达到了最大理论计算能力（例如，它可能在等待较慢的内存访问）。\n    *   **“忙”的原因多样：** 高利用率可能由计算密集型任务（大量数学运算）、大量系统调用（内核态忙碌）、频繁的中断处理、甚至自旋锁等待（CPU 忙等锁）等引起。工具如 `top`, `perf`, `vmstat` 等可以帮助区分具体原因（用户态 `us`、系统态 `sy`、等待I/O `wa`、软中断 `si`、硬中断 `hi`、窃取 `st`、空闲 `id`）。\n    *   **多核CPU：** 对于拥有多个核心或线程的 CPU，利用率通常可以报告：\n        *   **每个核心的利用率：** 最精确。\n        *   **所有核心的平均利用率：** 例如一个4核CPU平均利用率75%，可能意味着3个核心100%忙碌，1个核心空闲；也可能意味着4个核心都75%忙碌。\n        *   **总体利用率：** 所有核心忙碌时间的总和除以（核心数 * 总时间）。例如，4核CPU在1秒内，所有核心忙碌时间总和为3秒，则总体利用率为 3 / (4 * 1) = 75%。\n    *   **I/O 等待 (`wa`) 的特殊性：** 当进程因为等待磁盘I/O而阻塞时，CPU 核心会切换到其他可运行任务或进入空闲状态。这段时间通常被单独统计为 `wa`（I/O 等待）。严格来说，`wa` 高的时间段里 CPU 核心可能处于忙碌（执行其他任务）或空闲（没有其他任务）状态，但它反映了 CPU 因等待I/O而未能有效利用的潜在时间。`wa` 本身不计入 `us+sy` 的利用率计算，但高 `wa` 通常意味着系统瓶颈在I/O而非CPU计算能力。\n    *   **虚拟化环境：** 在虚拟机中，虚拟机监控器（Hypervisor）看到的宿主机的 CPU 利用率反映的是物理 CPU 的忙碌程度。虚拟机内部看到的 CPU 利用率反映的是分配给它的虚拟 CPU 时间的忙碌程度。如果宿主机物理 CPU 饱和，即使虚拟机内部显示利用率不高，其性能也可能受影响（`st` 窃取时间高）。\n\n**总结：**\n\nCPU 利用率的本质是一个 **时间占比的度量**。它精确地衡量了 **CPU 核心实际执行非空闲任务（执行用户代码或内核代码）的时间占总观测时间的百分比**。理解这个百分比背后代表的是 CPU 核心忙碌工作的时间片段，是掌握 CPU 性能分析和系统瓶颈诊断的基础。100% 利用率意味着 CPU 核心全程无休，但这不一定是性能极限，也可能是效率瓶颈的信号；而低利用率通常意味着 CPU 有充足的闲置计算能力。",
  "计算机科普/IDE,编辑器,编译器区别和特点.md": "\n---\n\n## 常用的 IDE\n\nIDE（集成开发环境，Integrated Development Environment）是开发者写代码时常用的工具。常见的 IDE 包括：\n\n- **Visual Studio Code (VS Code)**：轻量、插件丰富，支持多语言，既能当编辑器也能扩展成强大的 IDE。\n- **IntelliJ IDEA**：Java 领域最常用的 IDE，也支持 Kotlin、Scala 等。\n- **PyCharm**：专门针对 Python 开发的 IDE，出自 JetBrains。\n- **Eclipse**：早期 Java 的主流 IDE，现在依然有人用。\n- **Android Studio**：专门用于 Android 应用开发，基于 IntelliJ。\n- **Xcode**：Apple 官方的 IDE，用于 macOS/iOS 开发。\n- **Visual Studio**：微软出品，适合 C#、C++、.NET 开发。\n\n---\n\n## IDE、编辑器、编译器的区别\n\n### 1. 编辑器（Editor）\n\n- 功能：主要用于编写和修改代码的文本工具。\n- 特点：轻量，常见功能有语法高亮、代码提示。\n- 示例：Notepad++、Sublime Text、Vim、VS Code（裸版本更接近编辑器）。\n\n### 2. IDE（集成开发环境）\n\n- 功能：包含了编辑器 + 调试器 + 构建工具 + 项目管理等功能，提供一体化的开发环境。\n- 特点：能写代码、运行、调试、管理依赖，甚至直接部署。\n- 示例：IntelliJ IDEA、PyCharm、Eclipse、Android Studio、Xcode。\n\n### 3. 编译器（Compiler）\n\n- 功能：把源代码翻译成计算机可执行的机器码或中间语言。\n- 特点：单一职责，不提供编辑功能。\n- 示例：\n    - C/C++ 用的 GCC、Clang\n    - Java 的 javac\n    - Python 严格说没有传统编译器，通常是解释器（如 CPython、PyPy）\n\n---\n\n## 区别总结\n\n- **编辑器**：只是“写字”的本子，带点语法高亮。\n- **编译器**：把代码变成机器能跑的程序。\n- **IDE**：一个“全家桶”，里面既有编辑器，也能调用编译器，还带调试和项目管理工具。\n\n---\n",
  "计算机科普/IDEA专业版和社区版的区别和特点.md": "- **许可证与价格**  \n    社区版：基于开源代码，完全免费，支持自由使用与修改。  \n    专业版：需购买许可证，属于付费版本。\n    \n- **语言支持**  \n    社区版：聚焦 JVM 语言，如 Java、Kotlin、Groovy、Scala。  \n    专业版：覆盖多语言生态，除 JVM 语言外，还支持 PHP、JavaScript、TypeScript、Python、Ruby、Go、SQL 等，适配多语言与全栈开发。\n    \n- **框架支持**  \n    社区版：仅支持 JavaFX、Swing 等基础 Java 框架。  \n    专业版：涵盖广泛场景，Web 开发（Spring、JSF、Struts 等）、移动开发（Android）、企业开发（J2EE、Spring Boot、Micronaut、Quarkus 等）。\n    \n- **数据库工具**  \n    社区版：无内置工具，需借助 DBeaver、DataGrip 等外部工具操作数据库。  \n    专业版：内置数据库管理功能，支持直接查看、运行 SQL 脚本、导出数据等。\n    \n- **DevOps 和云支持**  \n    社区版：对现代 DevOps（Docker、Kubernetes）及云平台（AWS、Google Cloud）支持有限。  \n    专业版：集成 DevOps 工具链，深度兼容主流云平台。\n    \n- **版本控制系统（VCS）**  \n    社区版：支持 Git、Mercurial、SVN 等基础版本控制。  \n    专业版：强化 VCS 能力，新增 Perforce 支持，提供更便捷的版本历史查看、差异对比、回滚功能。\n    \n- **构建工具**  \n    社区版：支持 Maven、Gradle、Ant 等常见构建工具。  \n    专业版：拓展至 sbt、npm、yarn 等更多工具，适配多元开发场景。\n    \n- **插件**  \n    社区版：需手动按需安装插件。  \n    专业版：预装丰富实用插件，开箱即用 。",
  "计算机科普/sim卡作用及原理.md": "# 什么是 SIM 卡\n\n**SIM** 是 _Subscriber Identity Module_ 的缩写（中文常译为“用户身份模块”）。严格来说，现代移动设备里常见的有两类相关的东西：**物理 SIM / 晶片卡（UICC）** 和 **嵌入式 SIM（eSIM / eUICC）**。无论形式如何，其核心作用是：**为移动用户提供唯一身份、储存认证凭证与少量用户数据，并参与网络认证与安全通信**。\n\n---\n\n## 组成与物理/逻辑规范\n\n- **物理外形**：有标准的触点金属面（按 ISO/IEC 7816），常见尺寸为全尺寸/mini/micro/nano，近年还有不可拆卸的 **eSIM（嵌入式）**。\n- **逻辑规范**：\n    - **UICC**（Universal Integrated Circuit Card）：现代 SIM 的正式名称，能运行多种应用（USIM、ISIM 等）。\n    - **USIM**：用于 3G/4G/5G 的用户应用；比早期 GSM 的 SIM 功能更强。\n    - **Java Card**：很多 SIM 使用 Java Card 平台来运行小型应用（applet）。\n- **文件系统**：SIM 内部有一套层次化文件系统（MF → DF → EF），用于存放 IMSI、Ki、网络参数、联系人、短信等。\n\n---\n\n## 关键数据与标识\n\n- **IMSI（International Mobile Subscriber Identity）**：国际移动用户识别码，用于在运营商网络中唯一标识用户。通常由 MCC（国家码）+ MNC（网络码）+ MSIN（用户号）构成。\n- **Ki（密钥）**：设备和运营商共享的长期对称密钥（通常只存储在 SIM 与运营商的认证中心，不外泄），用于生成认证和加密用的临时密钥。\n- **ICCID（Integrated Circuit Card ID）**：SIM 卡的唯一序列号（印在卡上，用于标识卡片本身）。\n- **PIN/PUK**：用户可设置的 PIN（解锁码），PUK 用于在 PIN 输错多次后解锁。\n\n---\n\n## 工作原理（以移动网络认证为核心）\n\n1. **发起连接**：设备开机并向基站/网络发出接入请求，同时提供 IMSI（或临时标识）。\n2. **挑战—应答（Challenge-Response）机制**：\n    - 网络（认证中心）生成一个随机数 **RAND**，并把它发送给设备（通过基站）。\n    - SIM 使用内部的 **Ki** 与 RAND 以及特定算法（GSM 时代有 COMP128，后续有 A3/A8、Milenage 等）计算出应答值 **RES**（或 SRES），并生成会话密钥（如 Kc、CK/IK）。\n    - 网络端也用相同的 Ki 与 RAND 计算预期应答并比对：若匹配，认证通过。\n3. **密钥派生**：认证成功后产生的会话密钥用于语音/数据的加密（无线链路加密），并用于随后与核心网的安全交互。\n4. **更高级的 AKA（Authentication and Key Agreement）**：在 3G/4G/5G 中使用更强的 AKA 流程，包含防重放、防伪造的校验（如 AUTN）并生成更复杂的加密/完整性密钥（CK/IK、KASME 等）。\n\n---\n\n## 功能与扩展能力\n\n- **身份与计费**：运营商依据 IMSI 识别用户并计费。\n- **安全存储**：存储 Ki、网络参数、APN、联系人、短信（旧式）等。\n- **SIM Toolkit（STK）**：运营商/服务可下发应用命令（如菜单、主动发起短信/拨号、USSD 等），常见于运营商增值服务。\n- **远程管理（OTA）**：运营商可通过 OTA（Over-The-Air）向 SIM 下发配置、更新应用或改变 PIN 策略。\n- **多应用/多配置（eUICC）**：eSIM 支持在同一芯片上存放多个运营商配置文件，实现远程下载/切换（GSMA 的远程配置规范）。\n\n---\n\n## 安全性设计\n\n- **物理与逻辑硬化**：SIM 作为安全元件（secure element），具备防篡改与抗攻击设计；关键材料（如 Ki）不能被设备直接读取。\n- **用户认证**：存在用户 PIN，及网络端的挑战-应答认证。\n- **现代算法与协议**：从早期的 COMP128 演进到 Milenage、AKA、5G 新的改进，增强抗撞库与抗中间人能力。\n- **弱点**：历史上某些算法/实现被攻破或泄露（如早期 COMP128），但运营商逐步升级算法与使用更安全的 eSIM/AKA 方案。\n\n---\n\n## 实际应用场景与趋势\n\n- **传统手机**：物理 SIM 卡仍然广泛使用，支持换卡保号（携号转网）。\n- **双/多 SIM 设备**：允许同时插入两张 SIM 或混合物理 + eSIM 的组合，适合分工（工作/私人、数据/语音）。\n- **物联网（IoT）与 M2M**：大量设备使用 M2M SIM 或 eSIM/embedded 模块，便于远程部署与管理。\n- **eSIM 的流行**：便于运营商配置文件的远程下发，减少物理卡流通，也利于设备密封设计（如手表、物联网传感器）。\n\n---\n\n## 简短示例：GSM 认证流程（逐步）\n\n1. 设备向网络报告 IMSI（或临时标识）。\n2. 网络生成 RAND，并把 RAND 与预期应答（由运营商的认证中心计算）发送给移动交换中心（MSC）。\n3. MSC 将 RAND 发给设备；设备的 SIM 用 RAND + Ki 计算 RES 并返回。\n4. MSC 比较 RES 与期望值；若匹配则允许接入，并使用派生密钥加密后续无线通信。\n\n---\n\n## 小结（一句话）\n\nSIM（或更一般的 UICC / eUICC）是一个小型但受保护的智能卡 / 安全芯片，**存储用户身份与加密凭证，通过挑战—应答和密钥派生机制对用户进行网络认证并保护移动通信的安全**，同时支持少量用户数据与运营商增值服务（如 SIM Toolkit、OTA、eSIM 配置等）。\n",
  "计算机科普/wan口和lan口的区别与特点.md": "\n\n**一句话总结：**\n\n*   **WAN口：** 连接**外部**网络（通常是互联网）。\n*   **LAN口：** 连接**内部**网络设备。\n\n---\n\n## WAN口 (广域网端口)\n\n1.  **功能：**\n    *   主要负责**接入互联网**或**连接更大的外部网络**（如公司总部的网络）。\n    *   它是路由器与**互联网服务提供商**网络之间的桥梁。\n    *   接收来自ISP（如电信、联通、移动）的信号（通过光猫、调制解调器等设备）。\n2.  **特点：**\n    *   **数量少：** 家用路由器通常只有**1个**WAN口。企业级路由器可能有多个用于负载均衡或备份链路。\n    *   **“对外”角色：** 面向外部世界，是内部网络访问互联网的唯一（或主要）出口。\n    *   **IP地址：** 通常获取的是**公网IP地址**（由ISP动态分配或静态配置），或者是运营商网络内部的私有IP地址（在光猫拨号的情况下）。这个地址在互联网上是可路由的（或者至少能被ISP网络识别）。\n    *   **数据传输方向：** 处理所有**进出互联网**的数据流。\n    *   **物理位置：** 在路由器背面，通常与LAN口分开，并用**不同颜色**（常见黄色、蓝色或灰色）或明确标注`WAN`/`Internet`字样标识。\n    *   **连接对象：** 连接到**光猫、调制解调器**或上级网络设备（如另一个路由器的LAN口，此时该路由器工作在接入模式而非路由模式）。\n    *   **安全边界：** 位于内部网络和外部不可信网络之间，是防火墙防护的重点区域。\n\n---\n\n## LAN口 (局域网端口)\n\n1.  **功能：**\n    *   负责连接**内部网络**中的各种设备。\n    *   为这些设备提供**本地网络连接**，使它们能够相互通信（如电脑传文件给打印机、手机投屏到电视）并**共享同一个互联网出口（WAN口）**。\n2.  **特点：**\n    *   **数量多：** 家用路由器通常有**2-8个**LAN口。交换机则提供更多的LAN口用于扩展。\n    *   **“对内”角色：** 面向内部网络设备，构建本地局域网。\n    *   **IP地址：** 路由器上的LAN口本身有一个**私有IP地址**（通常是`192.168.x.x`, `10.x.x.x`, `172.16.x.x - 172.31.x.x`范围，如常见的`192.168.1.1`或`192.168.0.1`）。它作为内部网络的**网关**。\n    *   **IP分配：** 路由器通过**DHCP服务器**功能（通常默认开启），**自动**为连接到LAN口的设备分配私有IP地址（在同一个子网内）。\n    *   **数据传输方向：** 处理**局域网内部设备之间**以及**设备到路由器/互联网**的数据流。\n    *   **物理位置：** 在路由器背面，通常集中在一起，用**相同颜色**（常见黄色）标注`LAN`或`1, 2, 3, 4...`。\n    *   **连接对象：** 连接**电脑、打印机、网络存储、游戏机、智能电视、其他交换机**等**本地设备**。\n    *   **网络范围：** 构成一个**广播域**，设备在同一个子网内，可以直接通信（二层交换）。\n\n---\n\n## 关键对比表\n\n| 特性         | WAN口 (广域网端口)                     | LAN口 (局域网端口)                              |\n| :----------- | :------------------------------------- | :---------------------------------------------- |\n| **功能**     | 连接外部网络 (互联网/上级网络)         | 连接内部网络设备                                |\n| **角色**     | “对外”                                 | “对内”                                          |\n| **数量**     | 通常1个 (家用)                         | 通常多个 (2-8个，家用)                          |\n| **IP地址**   | 公网IP (或运营商私有IP)                | 私有IP (作为网关，如 `192.168.1.1`)             |\n| **IP分配**   | 由ISP分配 (动态/静态)                  | 由路由器的DHCP服务器分配给内部设备 (私有IP)     |\n| **数据传输** | 进出互联网的数据                       | 局域网内部设备间通信 + 设备到路由器/互联网的数据 |\n| **连接对象** | 光猫、调制解调器、上级路由器/网络      | 电脑、打印机、NAS、游戏机、电视、AP、交换机等   |\n| **物理标识** | 常不同颜色 (黄/蓝/灰)，标 `WAN/Internet` | 常统一颜色 (黄)，标 `LAN` 或 `1, 2, 3, 4...`    |\n| **安全位置** | 内部网络与外部网络边界 (防火墙防护点)  | 内部可信网络区域                                |\n\n---\n\n## 总结与常见场景\n\n*   **正确连接是上网的基础：** 宽带入户线（来自光猫/调制解调器）**必须**插在路由器的**WAN口**上。你的电脑、电视等设备则插在**LAN口**上。\n*   **混淆后果：** 如果把宽带线错插到LAN口，路由器就无法从ISP获取有效的网络配置，导致整个内部网络无法访问互联网。\n*   **扩展网络：** 如果你需要连接超过路由器LAN口数量的设备，可以将一个**交换机**连接到路由器的任一LAN口上，交换机提供的更多端口也属于LAN端口。\n*   **无线连接：** 路由器的Wi-Fi功能本质上是创建了一个“无线LAN口”，手机、笔记本等无线设备通过Wi-Fi连接后，其角色和功能等同于插在物理LAN口上的设备。\n\n简单来说，记住：**WAN口是进水管（从外面引水进来），LAN口是分水管和水龙头（把水分配到各个需要的地方）**",
  "计算机科普/WiFi和蓝牙的异同.md": "蓝牙和Wi-Fi 都是利用无线电波进行短距离无线通信的技术，并且都工作在2.4 GHz频段（部分Wi-Fi也工作在5 GHz或6 GHz），但它们的设计目标、技术实现、应用场景和性能特点有着**根本的区别**。\n\n主要区别：\n\n1.  **设计目的和应用场景：**\n    *   **蓝牙：** 主要设计用于**短距离、低功耗、点对点或点对多点**的设备间连接。目的是**取代线缆**，方便各种小型设备之间进行简单数据交换或控制。\n        *   **典型应用：** 连接无线耳机/音箱、鼠标/键盘、智能手表、健康追踪器、打印机、车载系统、智能家居设备（如灯泡、传感器）之间的简单通信等。\n    *   **Wi-Fi：** 主要设计用于**构建无线局域网**，提供**高速互联网接入**和**本地网络资源（如文件、打印机）共享**。目的是实现**高带宽的网络接入**。\n        *   **典型应用：** 将笔记本电脑、手机、平板、智能电视、游戏机等设备连接到互联网或家庭/办公室局域网；实现设备间的高速文件传输、媒体流传输。\n\n2.  **覆盖范围：**\n    *   **蓝牙：** 典型覆盖范围较小，一般在 **10米** 左右（Class 1设备可达100米，但较少见）。注重近距离连接。\n    *   **Wi-Fi：** 覆盖范围较大，典型的家用路由器覆盖范围可达 **几十米**（受墙壁、干扰等影响），甚至可以通过中继器扩展。\n\n3.  **数据传输速率：**\n    *   **蓝牙：** 速率**相对较低**，且不同版本差异大。\n        *   经典蓝牙：早期版本约1-3 Mbps，较新的蓝牙5.x版本理论可达2-3 Mbps（实际应用如音频传输用不到这么高）。\n        *   低功耗蓝牙：专为极低功耗设计，数据传输速率更低（几十到几百Kbps），但连接建立速度快。\n    *   **Wi-Fi：** 速率**非常高**，且随着标准演进不断提升。\n        *   802.11n：数百Mbps\n        *   802.11ac：Gbps级别\n        *   802.11ax：多Gbps级别\n        *   主要用于传输大量数据（如高清视频、大文件下载）。\n\n4.  **功耗：**\n    *   **蓝牙：** 尤其**低功耗蓝牙**设计初衷就是**极低功耗**，非常适合电池供电的小型设备（如传感器、耳机、手表），可以持续工作数月甚至数年。\n    *   **Wi-Fi：** 功耗**相对较高**。虽然也有针对物联网设备的低功耗Wi-Fi标准，但总体上维持Wi-Fi连接和传输数据消耗的电量远高于蓝牙（尤其是BLE）。频繁使用Wi-Fi会显著消耗手机等设备的电池。\n\n5.  **网络拓扑结构：**\n    *   **蓝牙：** 支持多种拓扑：\n        *   **点对点：** 两个设备直接连接（如手机连耳机）。\n        *   **广播：** 一个设备发送，多个设备接收（如Beacon）。\n        *   **Mesh网络：** 多个设备组成网状网络，扩展覆盖范围和可靠性（主要用于智能家居、楼宇自动化）。\n    *   **Wi-Fi：** 主要采用**星型拓扑**。\n        *   所有设备（客户端）都连接到一个中心节点（无线路由器或接入点）。\n        *   客户端之间通常需要通过接入点才能通信（除非支持Wi-Fi Direct点对点直连）。\n\n6.  **复杂性和成本：**\n    *   **蓝牙：** 协议栈相对**简单**，硬件实现**成本较低**，易于集成到小型、低成本的设备中。\n    *   **Wi-Fi：** 协议栈**复杂**，硬件实现**成本相对较高**，需要更强的处理能力和内存。\n\n7.  **频段和干扰：**\n    *   两者都工作在2.4 GHz ISM频段，因此**存在相互干扰的可能**。现代设备通常有机制（如自适应跳频）来减轻干扰，但在拥挤的无线环境中（如公寓楼、办公室），干扰仍可能影响性能（尤其是蓝牙音频的稳定性）。\n\n**总结：**\n\n| 特性         | 蓝牙                   | Wi-Fi                  |\n| :--------- | :------------------- | :--------------------- |\n| **核心目标**   | **短距设备连接**（取代线缆）     | **无线局域网接入**（高速上网/资源共享） |\n| **典型应用**   | 耳机、鼠标、传感器、手环、IoT小设备  | 笔记本上网、手机上网、流媒体、文件共享    |\n| **覆盖范围**   | 短（~10米）              | 中长（几十米）                |\n| **数据速率**   | **低**（Kbps - 低 Mbps） | **高**（百Mbps - 多 Gbps）  |\n| **功耗**     | **非常低**（尤其是BLE）      | **相对较高**               |\n| **拓扑结构**   | 点对点、广播、Mesh          | 星型（中心是AP/路由器）          |\n| **复杂性/成本** | 低                    | 高                      |\n| **频段**     | 2.4 GHz（主要）          | 2.4 GHz, 5 GHz, 6 GHz  |\n",
  "计算机科普/x64，x86和amd64区别.md": "x64、x86、amd64 都是与计算机处理器架构相关的术语，它们的区别主要体现在架构类型、位数、兼容性等方面，具体如下：\n\n### 1. x86：32 位处理器架构的统称\n\n- **核心定义**：x86 是英特尔早期推出的 32 位处理器架构（如 8086、80386 等）的统称，后来扩展到 32 位计算领域，是目前最广泛使用的 32 位架构标准。\n\n- **特点**：支持的最大内存地址空间为 4GB（受 32 位地址总线限制），广泛应用于早期个人电脑和服务器。\n\n- **兼容性**：所有 32 位 x86 处理器都遵循这一架构，软件兼容性极强。\n\n### 2. x64 与 amd64：64 位处理器架构的不同称呼\n\n- **核心关系**：两者本质上是同一架构 ——amd64 是 AMD 公司最早提出的 64 位扩展架构（在 x86 基础上扩展为 64 位），英特尔后来采纳了这一架构并称之为 x64，因此两者没有技术差异，只是不同厂商的命名方式。\n\n- **特点**：\n\n- 支持 64 位地址总线，理论上可支持最大 16EB（1EB=1024PB）内存，远超 32 位架构的 4GB 限制。\n\n- 向下兼容 32 位 x86 软件，兼顾旧有应用。\n\n- **应用**：目前主流的处理器（如英特尔的酷睿系列、AMD 的锐龙系列）均基于这一 64 位架构，是现代计算机的标准架构。\n\n### 总结：核心区别\n\n|   |   |   |   |\n|---|---|---|---|\n|术语|位数|架构来源|本质差异|\n|x86|32 位|英特尔早期 32 位架构标准|32 位计算基础|\n|amd64|64 位|AMD 提出的 64 位扩展架构|同属 64 位架构，仅命名不同|\n|x64|64 位|英特尔对 amd64 架构的称呼|同属 64 位架构，仅命名不同|\n\n简单来说：x86 是 32 位架构，x64/amd64 是 64 位架构（两者等价，名称不同）。",
  "计算机科普/多模态大模型识别图片,视频,音频原理.md": "\n## 核心思想\n\n- **目标**：把非文本模态（图片、视频、音频等二进制数据）转换成模型能理解的“通用语言”（数值向量/特征向量）。\n    \n- **统一空间**：在统一的语义向量空间中实现多模态信息的对齐、理解和生成。\n    \n\n---\n\n## 核心步骤\n\n1. **预处理与编码（Encoding）**\n    \n    - 使用专门的编码器（图像、视频、音频编码器），将原始数据转为特征向量。\n        \n2. **对齐与融合（Alignment & Fusion）**\n    \n    - 通过投影层将不同模态特征映射到同一向量空间，并进行融合。\n        \n3. **理解与推理（Understanding & Reasoning）**\n    \n    - LLM基于融合特征进行语义理解与逻辑推理。\n        \n4. **解码与生成（Decoding & Generation）**\n    \n    - 将LLM的内部表示解码为文本输出，完成对话或任务。\n        \n\n---\n\n## 工作流程示意图\n\n```mermaid\nflowchart TD\nA[输入<br>非文本模态] --> B[专用编码器<br>(如ViT, CLIP-ViT)]\nB --> C[特征向量<br>“通用语言”]\nC --> D[与LLM交互<br>(前缀/软提示)]\n\nE[输入<br>文本指令] --> F[文本编码器<br>(如CLIP-Text, BPE)]\nF --> G[文本向量]\n\nD & G --> H[大语言模型核心<br>(Transformer)]\nH --> I[理解与推理]\nI --> J[文本解码器]\nJ --> K[输出<br>文本响应]\n```\n\n---\n\n## 模态细分说明\n\n### 1. 图像（Image）\n\n- **编码器**：CNN（ResNet，早期）或 ViT（主流）。\n    \n- **流程**：\n    \n    1. 图像分块 → ViT编码 → 图像特征向量。\n        \n    2. 投影层对齐到文本空间。\n        \n    3. 特征作为“视觉提示”与文本一起输入LLM。\n        \n    4. LLM生成描述或问答结果。\n        \n\n---\n\n### 2. 视频（Video）\n\n- **特点**：图像序列 + 时间维度 + 可选音频。\n    \n- **编码器**：\n    \n    - 图像帧 → ViT。\n        \n    - 时序关系 → 3D-CNN / 时序Transformer。\n        \n    - 音频 → 独立音频编码器。\n        \n- **流程**：\n    \n    1. 视频帧采样。\n        \n    2. 逐帧编码 + 时序建模。\n        \n    3. 融合视觉+音频特征，对齐到文本空间。\n        \n    4. LLM理解动作与剧情，输出结果。\n        \n\n---\n\n### 3. 音频/音乐（Audio）\n\n- **语音识别路径**：\n    \n    - 使用ASR模型（如Whisper）转录为文本 → 输入LLM。\n        \n- **非语音音频路径**：\n    \n    - 音频波形 → 频谱图（Spectrogram）。\n        \n    - 频谱图 → ViT 等视觉编码器 → 特征向量。\n        \n    - 投影对齐后，与文本一同输入LLM。\n        \n\n---\n\n## 关键技术\n\n1. **CLIP模型**：\n    \n    - 对比学习，建立图像-文本统一语义空间。\n        \n2. **投影层（Projection Layer）**：\n    \n    - 将模态特征翻译到LLM空间。\n        \n3. **软提示（Soft Prompt）**：\n    \n    - 非文本特征向量作为额外提示，辅助LLM理解与生成。\n        \n\n---\n\n## 类比理解\n\n- **编码器**：不同模态的“翻译官”。\n    \n- **投影层**：统一标准的“校对官”。\n    \n- **LLM**：只懂“世界语”的“博学大脑”。\n    \n- **解码器**：把“世界语”翻译回自然语言。\n    \n\n---\n",
  "计算机科普/操作系统科普.md": "\n---\n\n## 一、目前主流操作系统有哪些\n\n“操作系统”（Operating System, OS）是管理硬件资源、为上层应用提供运行环境的软件。在各种设备上，都可能有不同种类操作系统。按应用场景划分，主流的有：\n\n| 设备类型             | 常见操作系统                                                                                                                               |\n| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------ |\n| 个人／桌面／笔记本电脑      | Windows、macOS、各种 Linux 发行版                                                                                                           |\n| 服务器 / 数据中心       | 各类 Linux 发行版（如 Ubuntu Server、CentOS / Rocky / AlmaLinux / Debian / Red Hat Enterprise Linux 等）、UNIX 系统（如 IBM AIX、Solaris 等，在某些领域还在用） |\n| 移动设备 / 平板        | Android、iOS（苹果专用）                                                                                                                    |\n| 嵌入式 / 物联网设备      | 各种轻量化系统（如基于 Linux 内核的嵌入式 Linux、RTOS、FreeRTOS、Zephyr 等）                                                                               |\n| 专用设备 / 工业 / 实时系统 | 各类专用实时操作系统（RTOS），例如 VxWorks、QNX、RT-Thread 等                                                                                          |\n\n总结来说，若以“普通用户的电脑 / 手机”为主要参考，则 Windows、macOS 和 Linux 是桌面／笔记本市场常见选择；在手机领域 Android 和 iOS 最主流；在服务器与云端系统则以 Linux 为主。\n\n---\n\n## 二、操作系统的历史发展\n\n下面是操作系统发展的一条主线（每个阶段都有很多分支、实验性系统，这里只抓主干）：\n\n1. **早期（1940s–1950s）：无操作系统时代**\n    \n    - 最初的电子计算机（如 ENIAC）没有操作系统，程序员自己控制硬件、加载程序、逐条指令运行。\n        \n    - 为了简化、复用“库”（library）和输入／输出操作，人们逐渐把重复功能抽象出来，形成初步的“监控程序”（monitor）。\n        \n2. **批处理与多道程序设计 / 时分系统（1960s）**\n    \n    - 为了提高硬件利用率，引入“批处理”（Batch）方式，把多个程序放在磁带／卡片上按序执行。\n    - 后来发展为 **多道程序设计**（Multiprogramming）：内存中可同时放多个作业；操作系统负责调度 CPU、内存、I/O。\n    - **时间分片 / 交互 / 时分系统**（Time-sharing）：多个用户可以“同时”交互地使用同一台计算机，通过快速切换响应。\n    - 多个经典系统出现（如 MIT 的 CTSS、MULTICS）。\n        \n3. **Unix 的出现与影响（1970s）**\n    \n    - Unix 在贝尔实验室被开发，最初用于小型机 / 研究用途。其设计强调简洁、可移植性。\n    - Unix 被用 C 语言重写，从而更容易移植到不同硬件平台。\n    - 在学术界、研究机构、后来商用系统中被广泛采用，并催生多个衍生系统（BSD、System V 等）。\n        \n4. **个人计算机时代 / 微型机 / GUI 化（1980s–1990s）**\n    \n    - 随着微处理器与个人电脑普及，需要适合 PC 的操作系统：如 CP/M、MS-DOS 等。 ([eecs.harvard.edu](https://www.eecs.harvard.edu/~cs161/videos/history.pdf?utm_source=chatgpt.com \"A Brief History of Operating Systems - Harvard University\"))\n    - Windows（最初是 MS-DOS 上的界面层）逐步发展，加入图形界面、独立内核等。 ([educative.io](https://www.educative.io/answers/differences-between-windows-macos-and-linux-operating-systems?utm_source=chatgpt.com \"Differences between Windows, macOS, and Linux operating systems - Educative\"))\n    - Apple 的 Mac 系列也推出图形界面操作系统（Mac OS）。\n    - 同时 UNIX / 类 Unix 系统不断改进，出现了 X Window 系统、图形界面层等。\n        \n5. **网络化、分布式与现代操作系统（1990s–至今）**\n    \n    - 操作系统要支持网络、分布式计算、互联网服务。\n    - Linux 内核在 1991 年由 Linus Torvalds 发布，成为开源 / 社区驱动的新兴路线。 ([GeeksforGeeks](https://www.geeksforgeeks.org/operating-systems/evolution-of-operating-system/?utm_source=chatgpt.com \"History of Operating System - GeeksforGeeks\"))\n    - 各种 Linux 发行版出现，用于桌面、服务器、嵌入式等。\n    - macOS（基于 NeXTSTEP / BSD / Darwin）发展壮大，成为 Apple 电脑的核心系统。\n    - 在移动领域，苹果推出 iOS（基于 macOS / Darwin 基础），Google 推出 Android（基于 Linux 内核 + 自有上层栈）。 ([维基百科](https://en.wikipedia.org/wiki/History_of_operating_systems?utm_source=chatgpt.com \"History of operating systems\"))\n    - 同时操作系统要应对虚拟化、容器化、云计算、大规模集群、微服务、异构计算等新挑战。 ([维基百科](https://en.wikipedia.org/wiki/History_of_operating_systems?utm_source=chatgpt.com \"History of operating systems\"))\n        \n\n这样，操作系统从“无 OS → 简单监控程序 → 批处理 / 多道 / 交互式系统 → Unix / 类 Unix → 图形界面 / PC 化 → 多平台 / 网络化 / 移动 / 虚拟化 / 云化”一路演进。\n\n---\n\n## 三、Windows、Linux 和 macOS 三者的区别\n\n下面从多个维度比较这三类系统的异同：\n\n|维度|Windows|macOS|Linux（典型 Linux 发行版）|\n|---|---|---|---|\n|**内核 / 系统架构**|Windows 使用微软自家内核（Windows NT 内核系列）|macOS 基于 Darwin（包含 XNU 内核、BSD 组件）|使用 Linux 内核 + 上层自由 / 开放软件组件|\n|**开源 vs 专有**|大部分为专有闭源|Apple 的 macOS 组件多为闭源／混合（部分开源如 Darwin）|大多数发行版完全开源 / 自由软件|\n|**硬件支持 / 兼容性**|广泛支持多种 PC 硬件，硬件驱动生态完善|只运行在 Apple 自己设计的硬件（Mac）上，兼容性受限但系统与硬件高度集成|Linux 移植性强，可以运行在众多架构（x86, ARM, MIPS 等），但硬件驱动有时依赖社区支持|\n|**用户界面 / 易用性**|界面直观、用户熟悉、应用生态丰富|界面优美、整体体验一致、系统与硬件结合紧密|桌面环境多样（GNOME, KDE, XFCE 等），定制性强，但对新手可能稍陡峭|\n|**软件 / 应用生态**|应用种类极多（商业软件、游戏、办公、娱乐等）|在创意、音视频、图形设计等专业软件方面有优势|多数是开源软件，商业闭源软件支持较少（不过近年状况在改善）|\n|**安全性 / 权限管理**|易成为恶意软件攻击目标（历史原因、广泛使用）|相对安全、沙盒机制、审核机制等|通常安全性较高（开源、社区审查、权限机制），但也需注意配置|\n|**系统升级 / 版本管理**|自动更新机制成熟；多数更新对向后兼容有保障|Apple 控制版本更新与硬件绑定，对老旧设备支持有限|发行版差异较大，有些滚动更新、版本升级可能要手动干预|\n|**自由度 / 可定制性**|一定限制（尤其底层系统受控），但有不少自定义空间|自由度较低，用户通常不能改变系统底层|非常高的自由度：可以定制、裁剪、自己编译系统组件等|\n|**典型用途 /优势场景**|适合游戏、通用办公、广泛软件支持|适合创意设计、多媒体制作、与 Apple 生态整合|适合服务器、开发环境、定制系统、科研、云平台等|\n\n不同用户 / 场景下，选择哪一种操作系统会有偏好。比如设计师可能偏 macOS，游戏玩家可能倾向 Windows，开发者 / 服务器管理员可能偏好 Linux。\n\n---\n\n## 四、Linux 发行版是什么\n\n“Linux 发行版”（Linux distribution，简称 distro）是把 Linux 内核与一系列工具 / 库 / 应用软件打包、配置、分发到用户能够直接安装和使用的完整操作系统版本。\n\n详细来说，Linux 发行版通常包含以下组件：\n\n- Linux 内核\n- GNU 工具链（如 Bash、coreutils、GNU C 库 / glibc 等）\n- 各种系统库\n- 包管理系统（如 apt / dpkg、yum / dnf、pacman、zypper 等）\n- 图形子系统（如 X Window、Wayland）和桌面环境（GNOME、KDE、XFCE 等）\n- 常用应用软件（浏览器、办公套件、媒体播放器等）\n- 安装程序、配置工具、安全机制等\n    \n\n发行版的目标是“把用户需要的软件、组件、配置整合好，使得用户可以开箱即用”——而不是用户必须自己从头编译所有软件。\n\n根据定位、更新策略、社区 / 商业支持、目标用户等不同，发行版可以分为很多种类别，比如：稳定版 vs 滚动更新版、桌面版 vs 服务器版、轻量版 vs 完整版、社区版 vs 企业版等。\n\n常见的 Linux 发行版例子有：\n\n- Debian 系列（Debian 本身、Ubuntu、Linux Mint 等）\n- Red Hat 系列（Red Hat Enterprise Linux、Fedora、CentOS / Rocky / AlmaLinux 等）\n- Arch、Manjaro、Gentoo、openSUSE 等\n    \n\n发行版之间在包管理、默认软件、目标人群、社区文化等方面有较大差异。\n\n---\n\n## 五、Android 是否可以看作是一种 Linux 发行版？\n\n这是一个在技术界和社区中比较有争论的问题。答案是 **不完全可以**。下面我来分析原因及观点：\n\n### 支持把 Android 视为 Linux 系统的一面\n\n- Android 使用的是 Linux 内核（即其底层调度、内存管理、驱动支持等核心部分是基于 Linux 内核）\n- 在很多 Android 设备上，你可以看到 /proc/version 等信息，显示 Linux 内核版本号。\n- 从这个意义上看，Android 属于“基于 Linux 内核”的一种系统。\n\n### 反对把 Android 视为传统 Linux 发行版的一面\n\n- 传统 Linux 发行版通常包括 GNU 工具链（如 glibc、bash、标准 Unix 工具集），而 Android 使用自己的 C 库（Bionic）、不同的 Shell / 命令工具集等，与典型 GNU 工具链并不兼容。 \n- Android 在用户空间架构上与传统 Linux 发行版差别很大：它有独特的应用层框架（如 Android Runtime / ART、Java / Kotlin 运行环境、Binder IPC 等），其生态与传统 Linux 软件栈不兼容。\n- Android 并不使用传统的 Linux 发行版那种包管理系统（如 apt、rpm 等），也不兼容大多数 Linux 桌面 / 服务器软件。\n- Android 是为嵌入式 / 移动设备优化的系统，许多底层设计（功耗管理、唤醒锁、内存回收策略等）与通用 Linux 有专门调整。\n    \n\n总结来看，Android 是一种“基于 Linux 内核”的系统，但它不能被简单地视作传统意义上的 Linux “发行版”。更准确地说，Android 是一个以 Linux 内核为基础、构建了一整套用户空间 / 应用生态的独立操作系统。许多人说“Android 是 Linux 的一个发行版”更多是从内核层面的角度说；但如果从完整操作系统、生态兼容的角度看，它与传统 Linux 发行版差异显著。\n\n---\n\n",
  "计算机科普/术语科普/术语科普-CVM.md": "CVM 通常指 云服务器（Cloud Virtual Machine），是云计算服务中的一种基础计算资源。它通过虚拟化技术，将物理服务器分割成多个独立的虚拟服务器，用户可像使用本地服务器一样远程管理和使用，无需自行购买和维护硬件设备。\n \n其核心特点包括：\n \n- 弹性伸缩：可根据业务需求灵活调整 CPU、内存、存储等配置。\n- 按需付费：按使用时长或资源配置计费，降低初期投入成本。\n- 高可用性：依托云服务商的基础设施，通常具备多副本存储、故障自动迁移等能力。\n- 易管理性：通过云平台控制台可便捷进行开关机、重装系统、配置网络等操作。\n \n在实际应用中，CVM 广泛用于搭建网站、部署应用程序、运行数据库、进行大数据分析等场景。不同云服务商（如腾讯云、阿里云等）对其的具体命名可能略有差异，但核心功能一致。",
  "计算机科普/术语科普/术语科普-DMZ.md": "DMZ（Demilitarized Zone，隔离区） 是网络安全架构中的一个特殊子网，位于企业内部网络与外部公共网络（如互联网）之间，作为两者之间的“缓冲地带”。\n \n其核心作用是将需要对外提供服务的服务器（如网站服务器、邮件服务器）部署在此区域，既让外部用户能正常访问这些服务，又通过隔离设计，阻止外部网络直接接触内部核心网络，从而降低内部网络被攻击的风险。\n \n简单来说，DMZ就像小区门口的“快递收发室”：外部快递员（互联网用户）只能接触收发室（DMZ内的服务器），无法直接进入小区内部（企业核心网络），既保障了对外服务，又守住了内部安全。",
  "计算机科普/术语科普/术语科普-IT行业的A端B端C端.md": " IT 行业中，**A 端、B 端、C 端**，是按照业务服务对象的不同来划分\n\n---\n\n## 1. C 端（Customer/Consumer）\n\n- **对象**：普通个人用户，即消费者。\n- **特点**：\n    - 用户量大，但单个用户的付费能力相对有限。\n    - 对产品的体验、易用性、趣味性和性价比要求较高。\n    - 市场竞争激烈，获客成本高，用户流失率也较高。\n- **典型产品**：\n    - 微信、抖音、美团、淘宝等面向大众的互联网应用。\n    - 常见的互联网 App 和电商平台，主要服务于个人消费者。\n\n---\n\n## 2. B 端（Business）\n\n- **对象**：企业或组织客户。\n- **特点**：\n    - 用户数量相对少，但单个客户的价值很高。\n    - 注重功能的完整性、效率、稳定性、安全性和售后支持。\n    - 产品通常要和企业的业务流程深度结合，销售模式更偏向“解决方案”。\n- **典型产品**：\n    - 企业管理系统（ERP、CRM、OA）、云计算服务（阿里云、腾讯云）、SaaS 工具（钉钉、飞书）。\n    - 企业采购、供应链、财务软件等。\n\n---\n\n## 3. A 端（Administration/Government）\n\n- **对象**：政府机构或事业单位。\n- **特点**：\n    - 强调合规性、稳定性和数据安全。\n    - 客户对服务的专业性、长期支持能力和安全保密性要求极高。\n    - 项目型特征明显，常涉及“政务信息化”“智慧城市”等建设。\n- **典型产品**：\n    - 政务大数据平台、智慧城市解决方案、公安/税务/教育信息化系统。\n    - 例如国家的社保系统、政府政务服务平台。\n\n---\n\n## 4. 三者的区别总结\n\n- **C 端**：面对大众 → 重视用户体验和规模效应。\n- **B 端**：面对企业 → 重视效率、功能深度、可持续合作。\n- **A 端**：面对政府 → 重视合规、安全、稳定、长期合作。\n\n可以简单理解为：\n\n- **C 端是“零售”**，靠规模和用户体验取胜。\n- **B 端是“批发”**，客户少但客单价高，需要深度定制。\n- **A 端是“定制工程”**，政策导向明显，更看重安全和合规。\n\n---\n有没有面向D端-开发者developer？",
  "计算机科普/术语科普/术语科普-MCU.md": "微控制单元（Microcontroller Unit）：这是电子工程领域的专业术语，又称“单片机”。它是一种将中央处理器（CPU）、存储器、输入/输出接口等功能集成在一块芯片上的微型计算机，广泛应用于智能家居、汽车电子、工业控制等领域。",
  "计算机科普/术语科普/术语科普-MQ.md": "MQ（Message Queue，消息队列），是一种基于“队列”模型的中间件，核心作用是实现跨服务的异步通信、解耦和流量削峰。\n \n简单来说，MQ就像“快递驿站”：发送消息的一方（生产者）把消息放到“驿站”（队列），不需要等接收方（消费者）立即处理；接收方空闲时再从“驿站”取消息处理，双方无需直接通信，也不用等待对方响应。\n \nMQ的核心价值（对应之前高QPS、异步场景）\n \n1. 削峰填谷：比如直播间送礼峰值时，大量请求先涌入MQ队列，消费端按数据库/服务的承载能力匀速处理，避免直接打垮后端；\n2. 解耦服务：送礼场景中，“扣余额”和“发送通知”无需强绑定，扣完余额后扔一条消息到MQ，通知服务自己消费处理，后续新增“积分统计”功能，只需新增一个消费端即可，不用修改核心业务代码；\n3. 异步提速：用户点击送礼后，后端只需完成“扣余额+发MQ消息”就立即返回成功，后续的“主播收益更新、消息推送”等耗时操作由MQ异步触发，提升接口响应速度。\n \n常见的MQ产品有RocketMQ、Kafka、RabbitMQ等，在高并发场景（如电商大促、直播、秒杀）中是核心中间件。",
  "计算机科普/术语科普/术语科普-POI.md": "POI（Poor Obfuscation Implementation），是Apache基金会提供的一套Java开源API库，核心作用是实现对Microsoft Office格式文件（如Excel、Word、PPT）的读写、编辑和生成。\n \n简单来说，POI就是Java程序操作Office文件的“工具包”——比如你需要在系统中导出Excel报表（如直播间送礼统计、用户消费明细）、读取Excel中的批量数据（如批量导入用户信息），都可以通过POI来实现。\n \n它之所以在报表处理场景中常用，是因为能直接操作Office原生格式，支持复杂的单元格样式（合并单元格、公式、图表），且兼容性强，几乎能覆盖所有Office文件操作需求。之前提到的“POI处理报表”，就是指用这套库完成Excel报表的生成、解析等核心操作。",
  "计算机科普/术语科普/术语科普-pwn.md": "“pwn” 是网络安全领域的常用术语，核心指 通过利用程序漏洞（如缓冲区溢出、内存泄漏等）获取目标系统的控制权，比如执行任意代码、提升权限甚至完全掌控设备。\n \n它起源于“own”（意为“拥有、控制”）的拼写变体，早期在黑客社区和安全竞赛（如CTF）中流行。常见场景包括：\n \n- 对存在漏洞的软件、服务器进行攻击；\n- CTF竞赛中的“pwn题”，要求参赛者找出并利用程序漏洞解决问题。\n \n简单说，pwn的本质就是“找到漏洞并借此控制目标”。",
  "计算机科普/术语科普/术语科普-QPS.md": "QPS（Queries Per Second），即每秒查询率，是衡量服务器在单位时间内处理请求能力的核心性能指标，直接反映系统的并发处理能力。\n \n简单来说，QPS就像“每秒能接待多少位客人”，比如一个接口的QPS为100，意味着它每秒最多能稳定处理100次用户的访问请求。\n \nQPS的关键细节说明\n \n1. 统计范围：通常针对单个接口、单个服务节点或整个系统，不同范围的QPS数值代表的意义不同（如“登录接口QPS”“支付服务QPS”）。\n2. 与并发量的关系：QPS ≈ 并发量 / 平均响应时间。例如，若系统平均响应时间为0.1秒，并发量为50，那么QPS约为500（50/0.1）。\n3. 实际应用场景：\n- 日常运维：通过监控QPS判断系统负载是否正常（如峰值QPS是否超过阈值）。\n- 架构设计：根据业务预估QPS（如电商大促预估10万QPS），决定服务器集群规模、缓存策略等。\n- 性能优化：若QPS不足（如请求排队、超时），需通过扩容、优化代码、增加缓存等方式提升。\n \n例如，普通小型网站日常QPS可能仅几十到几百，而大型电商平台促销峰值QPS可达到几十万甚至上百万。",
  "计算机科普/术语科普/术语科普-SaaS.md": "# 什么是 SaaS（Software as a Service）？\n\n**一句话**：SaaS 就是把软件放在厂商的云端，通过互联网提供给你用，你按月/年订阅即可，无需自己买服务器、装软件、打补丁。\n\n## 它和传统软件/其他“_aaS_”的区别\n\n- **传统本地部署**：你买许可证＋买服务器＋自己维护 → 成本高、上线慢。\n- **SaaS**：厂商托管一切（基础设施、应用、更新、备份），你用浏览器/APP直接用。\n- **IaaS**（基础设施即服务）：租云上的“硬件”（算力/存储/网络）。\n- **PaaS**（平台即服务）：租开发与运行平台（数据库/函数/中间件）。\n- **SaaS**：直接是“成品应用”（如CRM、协作工具）。\n\n## 关键特性\n\n- 订阅计费（按用户/按用量/套餐分级）\n- 通过浏览器或移动端访问，零安装\n- 自动更新与弹性扩容\n- 多租户架构（共享一套系统，数据逻辑隔离）\n- 开放接口（API/SSO/SCIM）便于与现有系统集成\n- 明确的**SLA**（可用性、支持时效）\n\n## 优点 & 潜在不足\n\n**优点**\n\n- 低启动成本，快速上线\n- 省运维与升级，持续获得新功能\n- 按需扩缩，适合中小团队和快速试错\n\n**潜在不足**\n\n- 深度定制受限（更多是“配置”而非“改代码”）\n- 数据合规/数据驻留要求需确认\n- 依赖网络与厂商，存在一定“供应商锁定”\n- 长期订阅成本需要核算\n\n## 常见场景与例子\n\n- 协作与沟通：Slack、Zoom、Notion\n- 客户与销售：Salesforce、HubSpot\n- 电商与支付：Shopify、Stripe（偏API型SaaS）\n- 人事财务：Workday、QuickBooks Online\n\n## 选型时的速查清单\n\n1. **合规与安全**：是否支持你所在行业/地区的合规（如 ISO 27001、SOC 2、GDPR、数据驻留选项）。\n2. **SLA 与可靠性**：可用性承诺、备份与灾备、支持响应时效。\n3. **集成**：是否支持 SSO/SCIM、现有系统的数据同步与 API 能力。\n4. **可配置度**：工作流、权限、报表、低代码/自动化能力到什么程度。\n5. **数据进出**：导入/导出、数据可携带与停用后的数据处理。\n6. **成本模型**：按用户/用量/功能包的组合，三年总拥有成本（TCO）。\n\n## 一个小比喻\n\n把软件当“自来水”：SaaS 负责建厂、铺管、净水和维护，你拧开水龙头就能用水（功能），按量付费。\n",
  "计算机科普/术语科普/术语科普-UGC.md": "**UGC（User Generated Content，用户生成内容）** 是指由普通用户而非专业机构或企业生产、发布和分享的内容。UGC 的出现和发展是互联网尤其是 Web 2.0 时代的核心特征之一，它极大地改变了信息传播的方式、内容生态和商业逻辑。以下是从**定义、类型、特点、商业价值和应用场景**五个方面对 UGC 的专业解释：\n\n---\n\n### 一、UGC 的定义\n\nUGC 是指由互联网用户主动创作并发布到各类平台上的内容。这些内容通常非付费创作，而是用户基于个人兴趣、经验或观点产生。它涵盖文字、图片、视频、音频、评论等多种形式。  \n👉 **关键点**：内容由“用户”创造，而非“平台”或“机构”生产。\n\n常见的 UGC 平台包括：\n\n- **社交媒体**：微博、小红书、Instagram、抖音、Twitter；\n- **视频与直播平台**：YouTube、Bilibili；\n- **社区论坛**：知乎、Reddit；\n- **内容分享平台**：豆瓣、Medium、Pinterest。\n\n---\n\n### 二、UGC 的类型\n\n1. **文本类**：博客、影评、产品评论、论坛帖子、微博内容；\n2. **图片类**：摄影作品、绘画、表情包；\n3. **视频类**：短视频、Vlog、直播内容；\n4. **音频类**：播客、配音作品；\n5. **交互类**：问答、评论、弹幕、点赞行为（属于轻量级 UGC）。\n\n---\n\n### 三、UGC 的特点\n\n1. **去中心化**：创作主体分散，人人皆可成为“内容生产者”；\n2. **高参与度与互动性**：用户不只是观众，更是参与者与传播者；\n3. **真实性与多样性**：内容往往反映用户真实的使用体验、生活状态；\n4. **长尾效应明显**：少数“头部创作者”贡献大量流量，但“腰部”和“尾部”用户共同维持生态活力；\n5. **传播性强**：社交关系链促进内容病毒式扩散。\n\n---\n\n### 四、UGC 的商业价值\n\n1. **品牌营销与口碑传播**  \n    用户自发分享的体验（如“种草”、“测评”）具备高度信任度，成为品牌营销的重要资产。  \n    例如：小红书的“笔记”体系即基于 UGC 建立口碑传播机制。\n    \n2. **内容生态建设**  \n    平台依赖 UGC 提供持续的新内容来源，形成丰富多样的内容生态。\n    \n3. **数据与算法优化**  \n    用户内容反映偏好与趋势，可用于算法推荐与广告精准投放。\n    \n4. **社区粘性与用户留存**  \n    UGC 让用户既是消费者又是贡献者，从而增强平台粘性。\n    \n\n---\n\n### 五、UGC 的应用场景\n\n- **电商领域**：用户评价、晒图、开箱视频；\n- **旅游行业**：游记、攻略分享（如马蜂窝、TripAdvisor）；\n- **教育平台**：用户笔记、课程反馈；\n- **游戏社区**：玩家创作的关卡、MOD；\n- **AI 内容生成**：UGC 与 AIGC（AI Generated Content）结合，用于内容共创和辅助创作。\n\n---\n\n### 六、与 PGC / AIGC 的区别\n\n|内容类型|主体|特征|代表平台|\n|---|---|---|---|\n|**UGC**|普通用户|自发、真实、多样|小红书、Bilibili、知乎|\n|**PGC**（Professionally Generated Content）|专业机构或个人|专业性强、质量高|优酷、爱奇艺、媒体网站|\n|**AIGC**（AI Generated Content）|人工智能生成|自动化、规模化|ChatGPT、Midjourney 等|\n\n",
  "计算机科普/游戏引擎科普.md": "\n---\n\n## 一、什么是游戏引擎\n\n简单来说，**游戏引擎（Game Engine）** 是一套为游戏开发提供“基础设施 / 框架 / 工具”的软件系统。它把许多通用功能（如渲染图形、物理模拟、碰撞检测、声音、输入、动画、资源管理、脚本执行、场景编辑器、跨平台发布等）都封装起来，让开发者不必每次都从“零”写这些功能。\n\n可以把游戏引擎想象成游戏制作的“骨架 + 工具箱”：你在其上构建你自己的游戏逻辑、关卡、美术、交互等。\n\n使用引擎的好处包括：\n- 节省重复造轮子的工作（例如渲染、光照、物理、材质、资源加载等）\n- 可用编辑器 / 可视化工具辅助提高效率\n- 跨平台支持（在多个目标平台上输出游戏）\n- 社区 / 插件 /生态系统支持（美术、音效、扩展模块等）\n\n不过，引擎也有其局限性（性能开销、约束、难以深度优化等）。\n\n---\n\n## 二、常见的游戏引擎 / 框架及其特点\n\n下面列出一些主流 /常见的，以及它们的优劣、针对的场景等。这个列表不是穷尽的，但能覆盖大多数实际使用案例。参考维基 “List of game engines” 列表中很多引擎的分类与信息 ([维基百科](https://en.wikipedia.org/wiki/List_of_game_engines?utm_source=chatgpt.com \"List of game engines\"))。\n\n| 引擎 / 框架                         | 适用方向 /擅长                                                     | 编程 / 脚本方式              | 优点 / 特点            | 局限 /注意点 /适用门槛                    |\n| ------------------------------- | ------------------------------------------------------------ | ---------------------- | ------------------ | -------------------------------- |\n| **Unity**                       | 通用、2D / 3D / VR / AR                                         | C#（也支持可视化脚本 / 插件）      | 编辑器成熟、社区大、插件丰富、跨平台 | 对于非常极端性能优化项目 / 特定平台可能有限制         |\n| **Unreal Engine**               | 高质量 3D / AAA 级别游戏                                            | C++ + 蓝图（可视化脚本）        | 强大的渲染效果、物理、材质系统    | 学习曲线较陡；对小型团队或 2D 项目可能“过重”        |\n| **Godot**                       | 独立 / 中小型项目、2D + 部分 3D                                        | GDScript / C# / C++ 扩展 | 轻量、开源、灵活、社区活跃      | 在某些 3D 渲染 /大型项目上与商业引擎还存在差距       |\n| **GameMaker (Studio / Engine)** | 2D 游戏、像素风、独立游戏                                               | 自己的脚本语言 / 可视化工具        | 入门门槛低、资源丰富、快速迭代    | 对 3D 支持有限，不适合重 3D 项目             |\n| **CryEngine**                   | 高质量 3D /开放世界 /视觉表现                                           | C++ + 脚本支持             | 强渲染能力、适用于大型游戏      | 学习成本高，社区 /资源相比 Unity / Unreal 较小 |\n| **Defold**                      | 2D / 中小型项目                                                   | Lua 脚本                 | 轻量、免费、适合移动 / 2D 游戏 | 不适合复杂 3D，扩展能力有限                  |\n| **LibGDX**                      | 跨平台 / 移动 / 桌面 /小游戏                                           | Java / Kotlin          | 较灵活、基于库的方式，可以控制底层  | 它更偏向框架而不是“全功能引擎”，需要自己补足很多功能      |\n| **MonoGame / XNA**              | 2D / 跨平台                                                     | C#                     | 继承 XNA 概念，适合中小型游戏  | 相较完整引擎较为基础，需要自己实现很多模块            |\n| **其他专用 /框架 /轻量引擎**              | 如 Phaser（网页 / JS 游戏）、LÖVE（Lua 2D）、OGRE（渲染引擎）、Stride（C# 引擎）等等 | 各自语言 / API             | 适合特定平台 /类型 /轻量项目   | 通常功能比较精简，需要开发者补很多东西              |\n\n此外，还有很多大型游戏公司自己开发的定制引擎（例如《刺客信条》《战神》《最终幻想》《使命召唤》等背后的游戏公司常用的内部引擎）——这些引擎通常针对其团队、技术路线、目标硬件做高度优化和定制。\n\n---\n\n### 引擎之间的关键区别 / 考量维度\n\n在选择或比较游戏引擎时，以下几个维度是常见考量：\n\n1. **渲染 / 图形能力**  \n    一些引擎在 PBR（物理光照）、全局光照、阴影、后处理效果、贴图质量等方面更强。Unreal / CryEngine 在这方面更突出。\n    \n2. **性能 /资源开销 /优化能力**  \n    引擎有自己的运行时开销。一些引擎提供底层访问 /定制能力，让你可以做极致优化；而一些引擎在性能极限时可能受制于其封装层。\n    \n3. **2D / 3D 支持的平衡**  \n    有些引擎专注 2D，有些主推 3D，也有两者兼顾。若你的游戏主要 2D，就不必选择一个在 3D 上过度复杂的引擎。\n    \n4. **跨平台支持**  \n    是否能方便导出到 PC、主机、移动端、网页、VR/AR 等。一个好的引擎通常支持很多平台。\n    \n5. **脚本 / 可编程性 /扩展性**  \n    脚本语言的易用性（如 C#、Lua、Python、GDScript 等），是否可以插入 /扩展底层模块，是否能访问原生代码。\n    \n6. **工具 / 编辑器 /可视化支持**  \n    引擎自带的场景编辑器、调试器、动画编辑器、粒子系统编辑器、材质编辑器等越强大，开发效率越高。\n    \n7. **社区 / 插件 /资源生态**  \n    有成熟的插件 /资产商店 /示例项目 /社区支持，可以大幅降低开发成本。\n    \n8. **许可 / 费用 /使用成本**  \n    有些引擎是开源 /免费（或在特定收入 /规模以下免费）; 有些是商业许可 /版税收费 /订阅制。需要注意授权条款、分成模式等。\n    \n9. **团队规模 /学习曲线**  \n    大型、复杂引擎可能适合有经验的团队。小团队 /新手往往更偏好轻量、易用的引擎。\n    \n\n---\n\n## 三、开发游戏是否必须要用游戏引擎？\n\n答案是：**不一定“必须”，但在绝大多数场景下，使用游戏引擎是非常推荐、效率与成本优势极高的选择**。\n\n### 可以不使用引擎 / 自己写游戏的情况\n\n- 有极端性能 /极端控制需求：有些项目为了最优化、特殊硬件、或很独特的架构，可能需要自己写底层渲染 /资源 /内存管理等。\n- 教学 /研究 /技术探索目的：自己写引擎是非常好的学习过程，可深入理解游戏底层原理。网上很多“如何写一个游戏引擎”的教程资源可参考。 ([Video Game Design and Development](https://www.gamedesigning.org/learn/make-a-game-engine/?utm_source=chatgpt.com \"How To Make a Game Engine: The Easy Way - GameDesigning.org\"))\n- 小型 / 简单 /实验性项目：比如非常简单的 2D 游戏或小游戏，可以用基础框架 /图形库（如 SDL、OpenGL / WebGL /Canvas /HTML5）来写，而不需要完整引擎。\n\n有文章论述：即便在现代，也有开发者选择“无引擎（engine-less）”方式以获得更细粒度控制和理解。 ([klizos.com](https://klizos.com/making-games-in-2025-without-an-engine/?utm_source=chatgpt.com \"Making Games in 2025 Without an Engine: Why Some Devs Still Go Raw\"))\n\n然而，自己写引擎 /“不使用现存引擎”的代价也很高：\n\n- 必须自己实现渲染、物理、碰撞、资源管理、动画、音频、UI、脚本、优化、平台适配、工具链、调试器、编辑器等 — 开发成本极高。\n    \n- 后期维护、扩展、跨平台、性能优化难度极大。\n    \n- 对于商业 /正常规模项目而言，这样做往往不划算。\n    \n\n### 使用现有游戏引擎的好处（为什么绝大多数项目都用引擎）\n\n- 开发效率极大提升 — 你可以把精力集中在游戏逻辑 /玩法 /内容本身，而不是底层通用模块。\n- 有现成的工具支持：场景编辑器、调试、资源导入 /导出、可视化界面等。\n- 更容易跨平台输出。\n- 可利用社区资源 /插件 /素材库，减少重复工作。\n- 在规模 /性能限制未极端时，引擎提供的封装和抽象足以满足大多数需求。\n\n很多业内文章 /资源都强调：对于绝大多数中小型团队 /独立开发者而言，使用成熟引擎是更现实、更高效的选择。 ([indiedevgames.com](https://indiedevgames.com/the-ultimate-guide-to-comparing-game-engines-key-features-and-factors-to-consider/?utm_source=chatgpt.com \"The Ultimate Guide to Comparing Game Engines: Key Features and Factors ...\"))\n\n因此，除非你有非常特殊的需求或追求极致优化 /学习研究目的，否则“用现成引擎”几乎是标准做法。\n\n---\n\n## 四、总结 + 给你的建议\n\n- 市面上常见的游戏引擎 /框架很多，不同引擎在渲染能力、脚本语言、工具支持、性能控制、生态 /社区、授权模式等方面都有差异。\n- 引擎极大地降低了游戏开发的门槛，提高效率，是目前主流做法。\n- 但在理论上，你也可以不使用引擎，完全自己写底层模块；不过那样做代价极高，适合研究 /教学 /极端需求方向。\n- 选择引擎时，要根据你游戏的类型（2D / 3D /VR /AR /网页 /移动 /主机）、你的团队规模 /技术栈 /预算 /性能需求等因素来选最合适的那个。\n    \n\n---\n",
  "计算机科普/游戏行业简单科普.md": "\n---\n\n## 一、游戏行业主要岗位类别（大框架划分）\n\n游戏公司里岗位很多，可以从“技术 / 美术 / 设计 / 运营 / 支持 /管理 /商务”等维度来分类。下面按“研发链条 + 周边链条”讲比较清楚。\n\n|类别|典型岗位|核心职责 /产出|常见技能要求 /门槛|\n|---|---|---|---|\n|**程序 /技术**|客户端程序 / 客户端工程师|实现客户端逻辑、UI、渲染、动画、特效等|熟悉引擎（Unity/Unreal/Cocos等），C#/C++/Lua/Shader 等|\n||服务端 /后端程序|服务器逻辑、网络通信、存储、接口、安全等|熟悉分布式、数据库、网络协议、微服务等|\n||引擎 /底层架构 /渲染 /图形学工程师|开发或优化引擎模块、渲染管线、图形算法|熟悉图形学、GPU 编程、渲染优化、引擎架构|\n||工具 /编辑器开发|为美术、策划等做工作流工具、插件、自动化脚本|熟悉工具链、脚本语言（Python, C#, JS／TS）、接口设计|\n||技术美术（Technical Artist / Tech Artist）|桥接“美术”和“程序”，负责特效、材质、shader、性能优化、美术工具流程等|既懂美术又稍懂程序 / shader /管线流程|\n||音频 / 声音程序|负责游戏中的音效、背景音乐、3D 音频系统、音频性能优化|熟悉音频中间件（如 Wwise / FMOD /自研音频系统等）|\n||AI / 算法 /机器学习工程师|游戏中的AI行为、NPC策略、路径规划、智能系统|熟悉算法、数据结构、AI 基础、可能需机器学习经验|\n||网络 / 性能 /安全 /运维工程师|负责网络性能、安全、运维支持、云服务等|熟悉网络、安全、云部署、性能调优、监控机制|\n||UI 前端 /界面程序|负责游戏界面、HUD、交互动画等|熟悉界面框架、动画、响应式设计、跨平台适配|\n|**策划 / 设计**|游戏策划 /玩法策划|设计游戏机制、规则、关卡、系统、平衡、数值等|数学/rate、逻辑思维、对玩法敏锐度、体验感|\n||系统策划 /系统设计|设计游戏的大系统框架（如经济体系、成长体系、社交系统等）|要理解游戏的长线机制、玩家行为|\n||数值策划|负责游戏中的数值公式、成长曲线、平衡性调整|要有扎实的数学基础、参数调优经验|\n||关卡 /副本 /地图策划|设计具体关卡、地图、流程、任务等|要有美术感、流程感、玩家节奏把控|\n||交互 /界面 / UX 设计|设计界面交互流程、玩家操作体验、菜单布局等|要懂交互原则、用户行为、常用设计工具 (如 Sketch, Figma)|\n||文案 /剧情 /脚本策划|撰写游戏剧情、脚本、对话、世界观设定等|要有文字功底、故事架构能力、表达清晰|\n|**美术 / 视觉表现**|原画 / 概念设计|画角色、场景、道具等概念设计图|美术基础强、熟练掌握 Photoshop、绘画功底|\n||3D 模型 / 角色建模|用 3D 软件（Maya/3ds Max/Blender 等）建模角色 /道具 /环境|网格拓扑、贴图、雕刻、UV 展开、骨骼绑定基础|\n||场景 /建筑美术|负责场景、环境、建筑、地形等的建模或贴图|注重构图、空间感、材质贴图、光照把握|\n||贴图 /材质 /纹理 / PBR 艺术|负责贴图/法线/高光/材质工作|熟悉 Substance Painter / Designer、纹理流程|\n||骨骼 / 绑定 / 骨骼动画|给角色做骨骼绑定、角色动画、蒙皮权重|熟悉骨骼系统、动画曲线、过渡、IK / FK 等|\n||角色 /动作 / 动画 / 表演|角色动作、战斗动作、转场动画、表演动画|动作把握、动画曲线、连接自然流畅、动作组合|\n||特效 /粒子 /Shader 可视化|制作技能特效、爆炸、光影、粒子系统等|熟悉特效工具、shader、GPU 优化、实时效果|\n||灯光 /渲染 /后期 /美术优化|场景灯光、后期色调、实时渲染优化|熟悉渲染管线、光照模型、材质优化、烘焙流程|\n||UI 美术 / 界面设计|设计游戏界面风格、ICON、按钮、界面元素|掌握 UI 美学、配色原则、界面流程|\n|**测试 /质量保障**|测试 / QA / 功能测试|发现游戏中功能性缺陷、逻辑漏洞、兼容性问题|要细致、系统化思考、熟悉测试流程、bug 提交|\n||性能 /稳定性测试|测试卡顿、内存泄漏、帧率异常、崩溃等问题|需懂性能监测工具、日志分析、各种平台差异|\n||自动化测试 /SDK 测试 /工具测试|编写测试脚本、自动化流程、SDK 接入测试|要有编程能力、脚本语言、测试框架知识|\n|**产品 /项目 /运营**|产品经理 / 产品负责人|对接市场与研发，定义目标、功能、路线图、分析数据|要懂业务、用户、数据分析、项目管理|\n||项目 / 制作人 /项目经理|管理项目进度、资源、沟通、风险、人员协调|要有跨团队沟通能力、敏捷流程、项目管理经验|\n||发行 /市场 /推广|游戏上市、宣传、渠道合作、用户获取与推广|要懂市场渠道、广告投放、数据营销、媒体资源|\n||运营 /社区 /活动策划|负责游戏上线后的日常运营、活动、用户留存、社区互动|要善于用户运营、数据分析、活动设计、用户心理|\n||渠道 /商务 /代理 /发行合作|与渠道、平台、分发、发行商、广告商合作|商业谈判、合同、分成机制、渠道生态理解|\n|**支持 / 管理 /后勤**|美术 /技术主管 /总监|负责技术 / 美术方向的路线、规范、团队指导|要有较强的专业能力、管理能力、跨团队视野|\n||HR / 招聘 /培训|招人、培训、绩效、团队建设|对游戏行业生态有了解、用人标准熟悉|\n||技术 / 美术 /策划 教育 /讲师|在培训机构、院校授课、课程研发|要有实战经验，能够把技术／流程拆解讲清|\n||法务 /知识产权 /版号合规|处理合同、版号、审查、法律合规事务|要有法律背景或专长、理解游戏行业法规|\n||运营支持 /社区 /客服 /数据分析|客服、用户反馈、社区维护、数据监控|要有沟通能力、处理用户问题经验、数据敏感度|\n\n这个表格只是一个“指标体系”，实际公司里岗位可能合并、交叉或细分更多。\n\n---\n\n## 二、在中国现实中招聘情况 — 举例 + 薪资 /热门岗位\n\n下面结合目前中国招聘平台看到的真实岗位示例 + 行业报告，来具体说明哪些岗位常被招聘、薪资水平如何、哪些更热门、哪些竞争激烈。\n\n### 典型招聘示例\n\n从猎聘上“游戏开发”招聘可以看出：\n\n- **客户端开发工程师**：3–5年经验，薪资约 **20,000–40,000 元/月**（一线/大厂可能更高） ([猎聘](https://www.liepin.com/zpyouxikaifa/?utm_source=chatgpt.com \"【游戏开发招聘网_2025年游戏开发招聘信息】-猎聘\"))\n- **UE5 客户端开发**：某些公司在杭州地区招 UE5 开发工程师，薪资有 8–13k（刚入门/小团队） ([猎聘](https://www.liepin.com/zpyouxikaifa/?utm_source=chatgpt.com \"【游戏开发招聘网_2025年游戏开发招聘信息】-猎聘\"))\n- **Unity / Cocos 游戏开发工程师（中级 /高级）**：在北京 /深圳 /上海等地薪资区间 25k–50k 左右 / 月比较常见 ([猎聘](https://www.liepin.com/zpyouxikaifa/?utm_source=chatgpt.com \"【游戏开发招聘网_2025年游戏开发招聘信息】-猎聘\"))\n- **测试开发 / QA**：高级 /资深测试开发工程师，对接端游 /大型项目，有些月薪可达 30k 左右 ([猎聘](https://www.liepin.com/zpyouxikaifa/?utm_source=chatgpt.com \"【游戏开发招聘网_2025年游戏开发招聘信息】-猎聘\"))\n- **工具 /引擎 /渲染方向**：常被列为“资深 /专家”岗位，工资有可能高于普通客户端工程师水平 ([猎聘](https://www.liepin.com/zpyouxikaifa/?utm_source=chatgpt.com \"【游戏开发招聘网_2025年游戏开发招聘信息】-猎聘\"))\n- 在游戏行业的整体热门招聘方向里，“策划 /产品 /运营 /发行 /美术”也是持续高频需求。2024 年游戏行业人才报告中提到：游戏策划在新发布职位中占比最高。([digi.china.com](https://digi.china.com/digi/20240827/202408271566852.html?utm_source=chatgpt.com \"2024游戏行业人才供需大数据报告_中华网\"))\n    \n\n### 薪资与趋势（行业报告视角）\n\n- 据《游戏行业人才供需大数据报告》显示，游戏行业中 **年薪 20 万以上** 的职位占比较高；很多中高阶岗位薪资可以达到或高于这个水平。([digi.china.com](https://digi.china.com/digi/20240827/202408271566852.html?utm_source=chatgpt.com \"2024游戏行业人才供需大数据报告_中华网\"))\n- 报告还指出，产品经理、Unity / U3D 相关岗位平均年薪可能超过 30 万。([digi.china.com](https://digi.china.com/digi/20240827/202408271566852.html?utm_source=chatgpt.com \"2024游戏行业人才供需大数据报告_中华网\"))\n- 根据猎头报告，近几年游戏行业供需比大体在 2.4：1 左右（即约 2.4 人竞争一个岗位）([winheadhunter.com](https://www.winheadhunter.com/news/FAQ/200.html?utm_source=chatgpt.com \"2025年中国游戏行业人才供需现状与猎头市场深度分析\"))\n- 在大厂里，主策 / 资深美术 /高级技术岗位的薪资与待遇相对稳定，但在中小型团队（尤其是创业 /出海团队）给的钱可能有很大浮动。([winheadhunter.com](https://www.winheadhunter.com/news/FAQ/200.html?utm_source=chatgpt.com \"2025年中国游戏行业人才供需现状与猎头市场深度分析\"))\n- 热门方向（如图形学 / 引擎 /特效 /AI）往往比“通用客户端逻辑”更吃香，但对应门槛也高。([winheadhunter.com](https://www.winheadhunter.com/news/FAQ/200.html?utm_source=chatgpt.com \"2025年中国游戏行业人才供需现状与猎头市场深度分析\"))\n    \n\n### 热门 vs 冷门岗位、风险点\n\n- **热门**：客户端开发（尤其 Unity / Unreal /跨平台开发）、技术美术 /特效、引擎 /渲染方向、策划 /玩法 /系统 /数值、产品 /运营。\n- **较冷 /竞争激烈 /门槛高**：服务端 /后端（部分游戏公司服务端人员相对少），某些通用测试 /兼容性测试（容易被外包替代），脚本 /游戏文案（文科方向很多竞争者）。\n- 公司对跨职能能力或复合能力（懂技术又懂玩法 /懂美术又懂性能）越来越看重。\n- 中小团队或创业项目常见风险：项目不稳定、被砍、薪资拖欠、岗位职责不清、加班严重。\n\n---\n\n## 三、不同类型公司／团队的差异 —— 求职策略视角\n\n行业里公司规模、定位、业务模式差异很大，入职体验/晋升空间 /稳定性 等也差很多。下面对比几类常见公司 /团队，以及适合的岗位类型和选择策略。\n\n|类型|特点 /优劣|常见岗位机会|求职策略建议|\n|---|---|---|---|\n|**大厂 /头部游戏公司** （如腾讯、网易、米哈游、莉莉丝、腾讯子公司、字节游戏）|稳定、资源多、品牌强、项目大、流程规范|各类岗位几乎都有：客户端 / 服务端 / 渲染 /工具 /策划 /美术 /运营 /产品等|要有扎实的基础、丰富项目经验、强作品集；面试门槛高，竞争激烈|\n|**中型 / 上市 /成型团队**|资源有保障，但灵活性比大厂高些|更注重各条线的中坚力量：中高级程序、美术、策划、技术美术|可以作为跳板，争取担当更关键角色；注意公司项目与融资背景|\n|**小型 / 独立 /工作室 /创业团队**|自由度高、职责多、成长快，但项目风险、稳定性差|可能需要“一肩挑”多个角色（既写程序又做工具 /特效）|要评估公司靠谱度、资金链、项目立项情况；最好事前了解团队背景|\n|**出海 /外国 /合资 /独立游戏公司**|更强调英语 /跨文化能力、国际发行经验|更多需要本地化 /跨平台 /版本适配 /SDK 接入等岗位|英语能力、跨文化理解、对海外市场的感知是加分项|\n|**外包 /代工 /美术/ 中间件 /工具 /引擎公司**|项目外包多、稳定性、工资体系可能略低|美术、模型、动作、特效、工具支持、插件／中间件开发|适合初学者积累经验；但演练的项目常是“给别人的模块”，创意自由度小|\n\n**策略建议 /提醒：**\n\n- 应届生 /初级人员：优先考虑大厂 /成型团队 /稳定公司，积累经验与作品，之后再进入细分方向（如引擎、渲染）。\n- 如果进入小团队 /创业团队，要非常注意“项目可行性 /融资 /退出机制 /合同条款 /工资发放机制”这些细节。\n- 在简历 /面试中，作品和项目经历通常比学历 /证书更重要。因为游戏行业强调“做出来能上线 /能看的 demo /你在项目里具体做什么”更具说服力。\n- 在面试前研究公司产品 /项目 /技术栈 /过往游戏，对方用什么引擎 /擅长什么风格 /市场定位是什么，这会在面试中非常加分。([知乎专栏](https://zhuanlan.zhihu.com/p/1918456438566655094?utm_source=chatgpt.com \"想要入职游戏公司的应届毕业生同学，一定要认真看这篇！\"))\n- 多维护行业内人脉 /参加游戏开发社区 /线上 hackathon /项目实践 /开源 /技术分享，有助于增加曝光度和获取推荐。\n\n---\n\n## 四、建议你关注 /考虑的几个“落脚点”岗位 +提升路径\n\n为了更具有可操作性，这里列几个“比较稳健 +成长空间较好的”岗位作为落脚点建议，以及你未来可以怎样往更高阶发展：\n\n|入门 /中级阶段|技能 /方向|往上发展可能路径|\n|---|---|---|\n|客户端程序员（Unity / Cocos / Unreal）|熟练掌握一个主流引擎 + 脚本语言 + 性能调优|向渲染 /引擎方向 /技术美术 /架构师 /技术负责人发展|\n|技术美术 /特效美术|掌握 Shader /粒子系统 /管线 /材质优化|向美术方向精深化 / 管线方向 / GPU 特效 /实时渲染方向|\n|游戏策划 / 系统 /数值策划|对玩法 /系统 /玩家心理要有敏感度，能做数据分析|向主策 /设计总监 /制作人发展|\n|产品 / 运营 / 数据分析|熟悉产品生命周期、用户行为、留存 /增长 /变现机制|向产品经理 /高级产品 /运营总监方向发展|\n|引擎 /渲染工程师|深入图形学 / GPU / shader /渲染算法|向架构师 /图形学专家 /引擎主管 /技术总监发展|\n|测试 /QA / 自动化测试|扎实的测试流程 /平台兼容认知 /脚本开发能力|向测试架构 /测试工具 /性能保障 /安全方向发展|\n\n---\n\n",
  "计算机科普/科普-Nagle 算法.md": "> [!NOTE]\n> ***Nagle算法是TCP协议中用于优化网络传输效率的一种流量控制算法，其核心目的是减少网络中“小数据包”的数量，从而降低网络拥塞和协议开销。***\n\n\n### **核心问题：小数据包的弊端**\n在TCP通信中，如果应用程序频繁发送少量数据（比如每次只发几个字节），会导致网络中充斥着大量“小数据包”。每个TCP数据包都包含固定的头部信息（至少20字节），小数据包的“有效数据占比”极低，会浪费网络带宽，同时增加路由器等设备的处理压力，容易引发网络拥塞。\n\n\n### **算法原理：合并小数据包**\nNagle算法通过“延迟发送”和“合并数据”的方式减少小数据包，具体规则如下：\n1. 当发送方有数据要发送时，先检查当前是否有“未被确认的数据包”（即已发送但未收到接收方ACK的数据包）。\n2. 如果存在未确认的数据包，则暂时缓存当前要发送的小数据，等待以下两种情况之一发生时再统一发送：\n   - 收到对之前数据包的ACK确认；\n   - 缓存的数据量达到一定大小（通常是MSS，最大报文段长度）。\n3. 如果没有未确认的数据包，则立即发送当前数据（避免过度延迟）。\n\n\n### **提出背景**\n该算法由John Nagle于1984年提出，最初是为了解决早期ARPANET中“远程登录（Telnet）”场景的问题：用户每敲击一次键盘，应用程序就会发送一个包含单个字符的小数据包，导致网络效率极低。Nagle算法通过合并多次按键的字符，显著优化了这类场景的传输效率。\n\n\n### **适用场景与局限性**\n- **适用场景**：适用于对实时性要求不高，但需要减少网络开销的场景（如文件传输、普通数据交互）。\n- **局限性**：在对实时性要求高的场景（如在线游戏、实时视频/语音、远程控制），Nagle算法可能导致延迟（因为需要等待ACK或数据积累）。例如，游戏中按键操作的小数据可能被延迟发送，影响响应速度。\n\n\n### **与其他机制的关联**\nNagle算法可能与TCP的“延迟确认（Delayed ACK）”机制产生叠加延迟：  \n延迟确认是接收方为了合并ACK而延迟发送确认（通常延迟200ms以内），若发送方等待接收方的ACK才能发送下一批数据，两者结合可能导致数据发送延迟进一步增加（即“Nagle+延迟ACK”的叠加效应）。\n\n\n### **如何禁用Nagle算法**\n在需要低延迟的场景（如游戏、实时通信），可通过设置TCP选项`TCP_NODELAY`（大多数编程语言/系统都支持）禁用Nagle算法，强制TCP立即发送数据，牺牲部分带宽效率换取实时性。\n\n\n### **总结：**\nNagle算法是TCP为平衡效率与开销设计的优化机制，通过合并小数据包减少网络负担，但需根据应用场景权衡实时性需求决定是否启用。\n\n[^1]: \n",
  "计算机科普/编程语言之间的划分.md": "\n---\n\n## 一、从抽象层次看：机器 → 汇编 → 高级语言\n\n这是最经典、最直观的划分：按语言与底层硬件（机器）之间的距离／抽象级别来划分。\n\n### 1. 机器语言（Machine Language / Machine Code）\n\n- 机器语言就是“CPU 最原生能直接执行”的那种指令，通常用二进制（0/1）表示。\n- 每一条机器指令对应 CPU 的一种操作（如加、减、跳转、读写内存等）。\n- 它与硬件架构（CPU 的指令集架构，Instruction Set Architecture, ISA）非常耦合：不同架构（x86, ARM, RISC-V 等）有不同的机器码格式、指令编码方式、寄存器结构、寻址方式等。\n- 优点：效率最高（因为已经是最终可执行形式）、控制极细粒度。\n- 缺点：难写、难读、不便维护、不具可移植性（写给一种 CPU 架构的机器语言在另一种架构上通常不可执行）。\n\n> 机器语言通常看起来就是一串 0/1，或者十六进制表示形式。\n\n### 2. 汇编语言（Assembly Language）\n\n- 汇编语言是对机器语言的一种“符号化”表示。汇编语言用助记符（mnemonics，如 `MOV`, `ADD`, `SUB`, `JMP` 等）和标号、标签、伪指令等来代替那些直接的二进制或十六进制操作数，使得程序员能够“看懂一点儿”机器指令对应的含义。\n- 每条汇编指令通常与一条（或一组）机器指令一一对应或有比较直接的映射（虽然有些汇编器允许宏、伪指令、寄存器别名、宏展开等辅助特性）。\n- 汇编语言仍然高度依赖硬件架构。你需要知道寄存器、地址模式、指令集、内存模型等底层细节才能写出有效的汇编。\n- 汇编语言需要 “汇编器”（assembler）把汇编指令翻译为机器码。\n- 优点：比机器码略好写／理解，但仍保留了对硬件的精细控制；在某些需要性能极限或直接控制硬件（如操作系统内核、设备驱动、嵌入式系统、性能关键模块）里仍有应用。\n- 缺点：依然难以阅读、编写、维护；缺乏可移植性；编程效率低。\n\n> 汇编语言是“低级语言” 的代表，它是机器语言之上，但抽象层次仍然很低。\n\n举例：在 x86 架构下，一条汇编可能写成 `mov eax, [ebx+4]`，而对应的机器码可能是某个具体字节序列。 ([GeeksforGeeks](https://www.geeksforgeeks.org/computer-organization-architecture/difference-between-assembly-language-and-high-level-language/?utm_source=chatgpt.com \"Difference between assembly language and high level language\"))\n\n### 3. 高级语言（High-Level Language）\n\n- 高级语言是针对人来写的，它把很多底层细节（如寄存器管理、内存寻址、指令编码、数据布局、跳转指令等）“抽象”掉，让程序员可以用更接近自然语言、数学表达、算法思维的方式编写程序。\n- 在高级语言中，你可能使用变量、函数／子程序、类／对象、数据结构（数组、链表、字典等）、控制结构（if/else、while、for 等）、模块化、异常处理、泛型、垃圾回收、标准库等等。你不用去写具体的寄存器操作或机器指令。\n- 高级语言编写的代码不能直接被 CPU 执行，而是要经过 **翻译阶段**——通常编译器 (compiler) 或解释器 (interpreter)，或者两者结合（先编译成中间代码／字节码，再由虚拟机（VM）或 JIT 编译器进一步转成机器码）。 ([维基百科](https://en.wikipedia.org/wiki/High-level_programming_language?utm_source=chatgpt.com \"High-level programming language\"))\n- 好处：可读性强、开发效率高、可维护性好、跨平台（可移植性）强（只要有该语言在某个平台上的编译器／运行时）。\n- 缺点：相比汇编和机器语言可能效率略低（因为抽象层次更高会带来运行时开销或不必要的中间步骤）。但现代编译器优化、JIT 技术等可以缩小这个差距。\n\n> “高级” 并不是绝对的：所谓“高级语言”是相对于 “汇编／机器” 而言的抽象概念。随着时间推移，以前认为是“高级”的语言可能在今天看来也不算太高级。 ([维基百科](https://en.wikipedia.org/wiki/High-level_programming_language?utm_source=chatgpt.com \"High-level programming language\"))\n\n---\n\n### 4. “中级语言”／中间表示（Intermediate）\n\n在某些文献或教材中，会提到“中级语言”（middle-level language 或 intermediate language），作为介于汇编语言和高级语言之间的一个 “中间层”。这个概念有些模糊，不过可以理解为：\n\n- 中级语言可能既具有一定的抽象（不像汇编那样要直接操控寄存器、地址、跳转等细节），但同时也允许底层控制（如指针、直接内存操作、内联汇编等）。\n- C 语言有时被称为“中级语言”或“中级抽象语言”（因为它既提供抽象机制（函数、结构体、控制流）又允许操作指针、地址、直接访问内存）——它处于一个折中位置：既不像汇编那样极低级，也不像 Python／Java 那种高度抽象。\n- 现代语言体系里，也有“中间表示”（Intermediate Representation, IR／中间语言）这个术语：在编译器实现里，为了优化、跨平台等目的，往往把源代码先翻译成一种统一的中间形式（例如 LLVM IR、Java 的字节码、.NET 的中间语言 IL 等），再从中间表示进一步翻译成目标机器代码。这个 IR 在某种意义上就是“介于高级语言和机器码之间”的一种“内部语言”。\n\n所以，在“机器 / 汇编 / 高级”这个三分法里，“高级”一端可以细分出不同层次、高度的语言。\n\n---\n\n## 二、对比：三者的特点总结\n\n下面是一个对比表，从多个维度展示机器 / 汇编 / 高级语言各自的特点：\n\n|维度|机器语言|汇编语言|高级语言|\n|---|---|---|---|\n|抽象级别|最原生、最低|较低|高|\n|表示方式|二进制 / 机器码|助记符 + 操作数 + 标签|变量、函数、数据结构、控制流、模块等高级结构|\n|可读性 / 可写性|极差，非常难|较难，需要理解硬件|较好，对人友好|\n|控制能力|最强（直接控制硬件）|很强|一般（抽象化封装底层）|\n|可移植性|几乎无|很小|较强（只要有编译器／解释器支持）|\n|执行效率|最高|很高|略低（依赖于语言实现、优化技术）|\n|典型用途|引导启动程序、固件、极限优化代码|操作系统内核、驱动、嵌入式系统、性能关键模块|应用程序、业务逻辑、脚本、Web、AI、系统软件（高层部分）|\n\n从这个比较可以看到：随着抽象级别越高，开发效率越高、可读性越好、可维护性越强；但代价是可能牺牲一些对硬件的精细控制、效率以及资源开销。\n\n---\n\n## 三、编程语言的更广泛／更细致的划分\n\n除了“按抽象级别”划分，还有很多其他方式可以给编程语言分类。下面是几种常见的分类视角与示例。\n\n### *（一）按“语言代数／世代”划分（Generations）*\n\n历史上，人们有一种“世代语言（generations of programming languages）”的划分方法。以下是一个常见版本的五代划分： ([GeeksforGeeks](https://www.geeksforgeeks.org/blogs/generation-programming-languages/?utm_source=chatgpt.com \"Generations of Programming Languages - GeeksforGeeks\"))\n\n1. **第一代语言（1GL）**：机器语言（二进制）。\n2. **第二代语言（2GL）**：汇编语言。\n3. **第三代语言（3GL）**：传统高级语言，如 Fortran、COBOL、C、Pascal、ALGOL 等。\n4. **第四代语言（4GL）**：更高层的、面向问题、声明式或领域特定的语言（比如 SQL、MATLAB、一些报表语言、脚本语言、DSL 等）。\n5. **第五代语言（5GL）**：通常指基于人工智能、逻辑编程、约束求解、自动推理等更高抽象层次的语言（例如 Prolog、某些函数式或逻辑范式语言、知识库语言等）。\n\n这种划分有一定历史意义，但在现代语境下界限并不严格。例如，很多语言混合使用不同层面的特性；而“第 4 代 / 第 5 代”语言的定义也常有争议。\n\n### *（二）按 **编程范式 / 风格** 划分*\n\n这是一种更有意义、更面向语言设计和思维方式的划分方式。一个语言可能支持多种范式。常见的范式包括：\n\n- 过程式 / 结构式（Procedural / Structured）：以顺序、条件、循环、子程序等为基本方式，比如 C、Pascal、早期的 Fortran。\n- 面向对象（Object-Oriented）：以对象、类、继承、封装、多态为核心，比如 Java、C++、Python（支持 OO）。\n- 函数式（Functional）：强调函数是“第一公民”、无副作用、不可变性、高阶函数等，比如 Haskell、Lisp、OCaml、Scala。\n- 逻辑 / 规则 / 声明式（Logic / Rule / Declarative）：以“写什么”而不是“怎么写”为主，比如 Prolog、SQL（某种意义上）、某些规则引擎语言。\n- 反应式 / 并发 / actor 模型 / 事件驱动：面向并行、消息传递、异步流等，如 Erlang、ReactiveX、Rust 的异步特性等。\n- 脚本 / 解释式 / 动态语言：通常是为快速开发、轻量任务设计，支持动态类型、运行时解释执行，如 Python、JavaScript、Ruby、Perl 等。\n- 域特定语言（DSL, Domain-Specific Language）：针对特定领域设计的语言，如 SQL（数据库查询语言）、正则表达式、LaTeX（文档排版语言）等。\n\n通过范式分类，我们更关注语言在“编程思维 / 解题风格 /抽象手段”上的特征，而不仅仅是底层抽象程度。\n\n### *（三）按 **执行方式 / 翻译方式** 划分*\n\n这是考虑语言 / 实现怎样从源码到执行这一环节的视角：\n\n- **编译型语言（Compiled）**：源代码编译成机器代码／可执行文件，执行时不再需要翻译步骤（比如 C、C++、Rust 等）。\n- **解释型语言（Interpreted）**：源代码在运行时被逐行 / 按需解释执行，不产生独立的机器码可执行文件（经典例子有早期的 Python、Perl、Ruby、Bash 脚本等）。\n- **字节码 / 虚拟机（VM）语言**：先把源码编译成一种中间字节码（与具体机器无关），然后由虚拟机解释或 JIT 编译成机器码执行。典型例子有 Java（编译成 JVM 字节码，再解释或 JIT），C#／.NET（IL 中间语言），Python 的某些实现（如 CPython 有字节码）等。\n- **即插即用 / 跨编译 / 转译（Transpiler / Source-to-Source Compiler）**：直接把一种语言的源代码转译成另一种语言的源代码（通常目标语言是更接近机器的一种语言或更通用的平台语言）。例如 TypeScript 转成 JavaScript、CoffeeScript 转 JS、某些语言先转成 C 代码再编译。\n- **混合执行 / JIT（Just-In-Time 编译）**：运行时动态将热点代码编译为机器码，以改善性能（典型如 Java HotSpot、V8 引擎、.NET CLR、PyPy 等）。\n    \n\n这个分类（编译 vs 解释 vs 虚拟机 / 字节码 / JIT / 转译）是一个非常实用的视角，因为它直接影响性能、移植性、启动时间、内存使用等。\n\n### *（四）按 **用途 / 领域 /功能** 划分*\n\n- **系统语言 / 底层语言**：用于操作系统、驱动、嵌入式、核内核模块等需要直接控制硬件的地方，如 C、C++、Rust（有底层能力）等。\n- **应用语言 / 脚本语言**：用于写业务逻辑、桌面／移动／Web 应用、自动化脚本，如 Python、JavaScript、Ruby、PHP 等。\n- **查询 / 报表 / 数据处理语言**：如 SQL、R、MATLAB、SAS 等，在数据处理、统计、分析、数值计算等领域比较常见。\n- **硬件描述语言（HDL, Hardware Description Language）**：用于描述数字电路 / 硬件结构，如 Verilog, VHDL。\n- **并行 / 并发 / GPU / 科学计算语言**：专门针对大规模并行运算、数值计算、科学模拟等，如 CUDA（为 GPU 编程的一个语言扩展）、OpenCL、Fortran（高性能数值计算）等。\n- **逻辑 / 规则 / 知识表示语言**：用于人工智能、规则引擎、知识库建模，如 Prolog、Datalog、某些规则语言。\n- **脚本 / 嵌入式 / 扩展语言**：嵌入在其它系统 / 软件中作为脚本或扩展接口使用，如 Lua（常嵌入到游戏、应用中作为脚本语言）、JavaScript（在浏览器中，甚至在服务器端作为脚本语言）等。\n- **领域特定语言（DSL）**：面向某个狭义领域的语言，如正则表达式、HTML/CSS（标记／样式语言，非严格 “程序语言” 但常在编程系统中视为 DSL）、SQL、LaTeX、Shader 语言（GLSL、HLSL）、配置语言（如 YAML, JSON, TOML）等。\n    \n\n### *（五）按 **动态 / 静态类型**、**高级特性支持**等进一步细分*\n\n- **静态类型语言 / 强类型 / 类型系统**：在编译时就确定变量类型，如 C, C++, Java, Rust, Haskell 等。\n- **动态类型语言**：变量类型在运行时决定，如 Python, JavaScript, Ruby, Lua。\n- **弱类型 / 宽松类型语言**：类型转换灵活、有隐式类型转换，如 JavaScript、PHP（在某些情形下）。\n- **支持垃圾回收（GC）的语言** vs **无需垃圾回收 / 手动管理内存的语言**。\n- **支持泛型 / 模板 / 元编程 / 宏 / 反射 / 元数据 / 注解 / 并发 / 异步 / 协程 / 幂等 / 组合子 / 函数式特性 / 泛函 / 模块系统 / 多态 / 高阶函数 / 依赖注入 / 领域语言集成**等。\n    \n\n每个维度都可以作为细化标准。现代语言往往在多个范式、多个特性之间混合或支持。例如，Python 是动态类型、支持面向对象 + 函数式、通常作为脚本语言；C# 是静态类型、支持泛型、面向对象、LINQ（函数式风格）、异步 / 并发特性；Scala 支持面向对象 + 函数式混合；Rust 支持低层控制 + 安全机制 + 并发特性等。\n\n---\n\n## 四、为什么要有这些划分？它们有什么意义？\n\n知道这些划分不是为了应付考试，而是理解“为什么有各种语言”，“什么时候选哪种语言比较合适”，以及“不同语言的设计思路 / 适用场景差别”。这些划分帮助我们：\n\n1. **理解抽象层次与性能 / 控制权之间的权衡**  \n    越接近硬件的语言，给予你更高的控制力度／性能潜力，但开发代价高；越抽象的语言，给你开发效率和可维护性，但可能在性能或细节控制上受限。\n2. **选择合适工具 / 语言**  \n    根据任务特点（高性能 / 低延迟 / 嵌入式 /算法密集 /数据处理 /脚本 glue 逻辑 /领域特定）去选择语言，而不是凭喜好随意选。\n3. **理解编译器 / 解释器 /虚拟机的工作原理**  \n    不同语言的运行方式（直接编译、解释执行、字节码 + VM、中间表示 + 优化等）差别很大，影响性能、调试、部署、移植性等方面。\n4. **理解语言的演化 / 新语言设计原则**  \n    很多现代语言就是在追求“更高抽象但又不失性能 / 安全 /可控制性 / 并行性 /可组合性 /可维护性”等折中点。通过这些分类视角，可以更清晰地看到各语言设计取舍、演变方向、优劣势。\n    \n\n---\n",
  "计算机科普/编程语言科普.md": "\n---\n\n## 一、目前主流编程语言有哪些\n\n“主流”这个词有些模糊，但可以从 **使用度、社区活跃度、在业界的需求** 来衡量。以下是目前（2025 年左右）较为主流、常见、被广泛使用或热门的编程语言（或语言家族）：\n\n|语言 / 语言家族|主要应用 /特点|为什么主流 /受欢迎|\n|---|---|---|\n|**Python**|数据科学、机器学习、自动化脚本、Web 后端、运维脚本等|语法简洁、生态丰富、学习门槛相对低，是很多初学者首选语言|\n|**JavaScript / TypeScript**|前端开发（浏览器端）、全栈开发（Node.js）、前后端整合|浏览器支持、自带执行环境，Web 开发不可或缺|\n|**Java**|企业级后端、Android 应用、分布式系统、大型系统|平台无关、生态成熟、稳定性好|\n|**C / C++**|操作系统、底层系统、游戏引擎、高性能计算|性能高、控制力强，是很多系统、嵌入式的基础|\n|**C# / .NET**|微软生态、游戏开发（用 Unity）、Web / 桌面应用|在 Windows / 企业 /游戏开发中占有较大份额|\n|**Go**|云服务、微服务、网络工具|轻量、高效、并发模型好，适合现代后端服务架构|\n|**Rust**|系统级编程、安全性、高性能程序|兼顾安全与性能，正逐渐在系统编程中崛起|\n|**Kotlin / Swift / Dart** 等|Kotlin 在 Android 开发、Swift 在 iOS 开发、Dart 在跨平台 Flutter 中|针对特定平台或生态的现代语言|\n|**PHP / Ruby / Lua / R / MATLAB** 等|Web 开发、脚本、科学计算、嵌入脚本语言等|在特定领域（如 Web、数据处理、脚本任务）有长期用户基础|\n\n\n**提示**：你不需要一次就掌握很多语言。选一种用途广、社区活跃、资料丰富的语言作为第一门就很好。\n\n---\n\n## 二、如何学习第一门编程语言\n\n学习编程语言其实不仅是学语法，更重要的是学“编程思维”和“解决问题的方法”。下面是一个通用的路径和建议：\n\n1. **选一个“合适”的第一门语言**  \n    要求：社区活跃、资料丰富、上手难度适中、你感兴趣的应用领域有支持。  \n    很多人选择 Python、Java、JavaScript、C# 等作为第一门。\n    \n2. **基础语法 + 核心概念**\n    - 变量、类型、表达式\n    - 分支 / 循环 / 函数 / 模块\n    - 数据结构（列表 / 数组 / 字典 / 集合 / 栈 / 队列 / 链表）\n    - 输入 / 输出 / 文件操作\n    - 异常 /错误处理\n    - 类 / 对象（如果是面向对象语言的话）\n        \n3. **做小项目 / 练题**\n    - 用你学到的语言做一些小程序：如计算器、猜数字游戏、文本处理脚本、网页爬虫、小游戏等\n    - 在线编程题（如 LeetCode / HackerRank / Codeforces /国内的平台）\n    - 仿写别人做过的小项目\n        \n4. **理解语言常用库 /框架 /生态**\n    - 学会如何使用标准库\n    - 探索社区常用库 /包管理工具\n    - 如果语言用于 Web、数据分析、GUI 等方向，学习相应框架\n        \n5. **阅读、调试、源码 /开源项目学习**\n    - 阅读简单的开源项目代码，理解别人怎么组织项目\n    - 学习调试技巧（断点、日志、单步执行）\n    - 修改 /加功能 / 布置自己的小项目\n        \n6. **不断总结与巩固**\n    - 写笔记、写博客、记录你遇到的问题和解决方法\n    - 定期回顾基础（数据结构、算法、语言核心特性）\n    - 尝试用这门语言做一些实战项目\n        \n7. **进阶知识** （视情况）\n    - 并发 / 多线程 /异步\n    - 性能优化\n    - 设计模式 / 编程范式（例如函数式编程、响应式编程）\n    - 架构设计 / 模块化 /插件机制等\n        \n\n**心得建议**\n- **不要急于 “用很多库 / 框架”**，先把“语言本身”理解透\n- **边练边思考**：做题、做项目能加深理解\n- **多看源码 /别人的代码**，理解风格和习惯\n- **坚持比一口吃胖重要**，每天写一点比一次写很多还好\n    \n\n---\n\n## 三、编译型语言 vs 解释型语言 的区别\n\n这两个术语在实际使用中不是绝对的分类（很多语言其实是混合或中间型的），但可以帮助理解它们的执行机制。下面是它们的主要区别、优缺点、典型语言等。\n\n### 基本定义\n\n- **编译型语言（Compiled Language）**  \n     将源代码（高级语言）在运行之前用 **编译器**（compiler）转换成机器码（或某种中间码 /目标码 /可执行文件），再由操作系统 /硬件直接执行。  \n     编译是一次性的、事前的。  \n     典型：C、C++、Rust（直接编译为机器码） ([Veitor](https://www.veitor.net/posts/compiler-vs-interpreter/?utm_source=chatgpt.com \"编译器 (Compiler)和解释器 (Interpreter) | Veitor的技术点滴\"))\n    \n- **解释型语言（Interpreted Language）**  \n     用 **解释器**（interpreter）逐行或逐块读取源代码，将其转换或解释为机器指令并执行，不一定生成整体的可执行文件。  \n     解释是在运行（执行）时动态进行的。  \n     典型：早期的 BASIC、Perl、Python、Ruby、PHP（虽然这些语言在现代实现中可能也做了编译 /优化） ([博客园](https://www.cnblogs.com/lemon-le/p/13840014.html?utm_source=chatgpt.com \"解释器 ( interpreter ) 与 编译器 ( compiler ) 的对比 - 博客园\"))\n    \n\n### 区别对比\n\n|方面|编译型|解释型|\n|---|---|---|\n|执行时间 / 性能|编译后生成本地机器码，运行效率通常较高|每次运行时都要解释／翻译，效率通常较低（除非经过优化）|\n|编译 / 执行关系|编译阶段和执行阶段分离（先编译，再执行）|通常是边解释边执行（或一边翻译一边执行）|\n|错误检测|编译时可以检测出大部分语法 / 类型错误|运行过程中逐行解释，错误可能在运行时才出现|\n|可移植性|编译后生成与平台相关的机器码（需针对不同平台重新编译）|源代码可以在不同平台上用相同的解释器直接运行（只要有对应解释器）|\n|开发 /调试体验|编译需要时间（可能慢），但运行快|开发调试更灵活、即时反馈好|\n|典型使用场景|系统程序、性能敏感程序|脚本任务、快速原型、脚本 glue 代码等|\n\n不过在现实中很多语言 / 实现是折中的、混合的：\n\n- 现代的 **Python** 解释器（如 CPython）会把 Python 源码先编译成字节码（bytecode），然后由虚拟机 / 解释器执行\n- **Java** 是“先编译为中间字节码，再通过虚拟机执行 /解释 /优化”机制\n- 现代解释器 / JIT（即时编译, Just-In-Time）技术使解释型语言在运行过程中部分编译，从而提升性能\n- 有些语言可以静态编译也能解释执行\n    \n\n因此，“编译型 vs 解释型”更像是 “主要执行机制” 的差异，而非绝对分类。\n\n---\n\n## 四、什么是虚拟机 (Virtual Machine) 和 解释器 (Interpreter)\n\n这两个概念在语言实现层面是常见的组件或手段，下面分别说明：\n\n### 解释器 (Interpreter)\n\n- 解释器是一个软件，它接受 **源代码** 或某种中间表示（如 AST、字节码等），然后逐条解释 / 翻译 /执行这些指令。\n- 解释器通常做三件事：**解析 / 词法分析 / 语法分析**（把文本转换成语法结构或中间表示），**执行 / 调度**（根据语义执行操作），**错误处理 /调试支持**\n- 因为解释是运行时发生的，所以解释型语言可以很灵活（如动态类型、REPL 模式、交互式编码）\n- 缺点是运行速度可能较慢，因为每次执行时都要解释和翻译\n    \n\n举例来说，早期 Python、Ruby、Perl 的标准实现都带一个解释器（读取 .py 或 .rb 源文件，解释执行）\n\n### 虚拟机 (Virtual Machine, VM)\n\n“虚拟机”这个词在编程语言实现中通常指 “语言虚拟机”（不是操作系统层面的虚拟机），即为某种语言提供一个执行环境，实现跨平台、内存管理、中间表示执行、优化等功能。\n\n具体来说：\n\n- 通常语言先被编译成一种与硬件无关的中间表示（比如 **字节码（bytecode）**）\n- 然后在 “虚拟机” 中运行这个字节码（虚拟机负责解释、编译、管理运行时环境）\n- 虚拟机可以实现垃圾回收（GC）、内存管理、运行时优化、JIT 编译等\n- 语言虚拟机使得同一套字节码 /中间表示可以在不同平台上运行（只要有对应平台的虚拟机实现）\n    \n\nJava 的 JVM（Java 虚拟机）就是经典例子。Java 代码（.java）经 **javac** 编译为 Java 字节码（.class），然后 JVM 载入这些字节码执行（有解释器 + JIT 优化） ([Edu4Java](https://www.edu4java.com/en/concepts/compiler-interpreter-virtual-machine.html?utm_source=chatgpt.com \"Compiler, interpreter and virtural machine. - edu4java.com\"))\n\n虚拟机和解释器的关系可以是：\n\n- 虚拟机内部可以包含解释器（解释字节码）\n- 虚拟机也可以包含 JIT 编译器（把热点字节码编译为本地机器码）\n- 虚拟机通常还负责运行时环境管理，如内存分配、垃圾回收、线程调度、安全检查等\n    \n\n简单来说：**解释器是“把代码解释执行”的那个组件**；**虚拟机是提供中间执行环境 /平台抽象 /运行时服务的整体系统**。\n\n---\n\n## 五、Java 和 Python 在语言类型 / 执行机制上的区别\n\n下面从几个维度比较 Java 和 Python，并指出它们在“语言类型 / 执行机制”上的异同。\n\n### 语言范式 /设计定位\n\n|特点|Java|Python|\n|---|---|---|\n|类型系统|静态类型（静态类型检查 + 编译期类型系统）|动态类型（运行时检查类型）|\n|编程范式|面向对象为主，也支持泛型、接口、并发等|多范式（面向对象、函数式、脚本式）|\n|语言定位|企业级应用、后端、中间件、Android 等|脚本 /快速开发、数据科学、自动化、Web 后端等|\n|语法 / 可读性|语法较严格、结构化|语法简洁、强调可读性|\n\n### 执行 / 编译机制\n\n|项目|Java|Python|\n|---|---|---|\n|源代码 → 可执行方式|Java 源代码 `.java` 用 **javac** 编译为 **字节码**（.class）然后由 **JVM**（Java 虚拟机）加载执行（解释 / JIT 优化） ([Edu4Java](https://www.edu4java.com/en/concepts/compiler-interpreter-virtual-machine.html?utm_source=chatgpt.com \"Compiler, interpreter and virtural machine. - edu4java.com\"))|Python 源代码（.py）通常由解释器（如 CPython）先编译成 **字节码**（.pyc 文件或内存中）然后由 Python 虚拟机 /解释器执行字节码（或在某些实现中 JIT 优化）|\n|是否纯解释或纯编译|不是纯解释 /不是纯编译，是一种“先编译为中间码 + 在虚拟机中解释 /优化”的混合模式|虽然常被称作“解释型语言”，但实际上也经过“编译（至字节码） + 在虚拟机中执行”机制|\n|性能|通常比 Python 快，因 JVM 的优化、JIT、静态类型优势|性能较慢是其常见弱点，但也有 PyPy、Cython 等优化项目改善性能|\n|可移植性|写一次字节码可在不同平台上通过 JVM 运行（“一次编写，到处运行”）|只要目标平台有 Python 解释器即可运行（源代码级别可移植）|\n|应用领域|企业后端、分布式系统、大规模服务、Android 应用|脚本、自动化、数据分析 /科学计算 /机器学习 / Web 服务|\n\n综上，**Java 属于“编译 + 虚拟机” 类型的语言**，而 **Python 虽然经常被称为“解释型”语言**，但其实际实现也带“编译（到字节码） + 虚拟机执行 /解释器”机制。两者在类型系统、执行效率、应用定位、生态等方面也有明显区别。\n\n---\n",
  "计算机科普/网络协议科普.md": "\n---\n\n## 网络层次与协议模型（简要背景）\n\n在讲这些协议之前，先说一下它们在网络协议栈中的“位置”究竟在哪儿，会更容易理解它们的作用。现代网络通信一般参考 **TCP/IP 协议族** 或者 **OSI 七层模型**。\n\n- 在 TCP/IP 模型里，经常把协议分为四层：**网络接口层**、**网际层（Internet 层）**、**传输层（Transport 层）**、**应用层（Application 层）**。\n- 大部分协议（FTP, SSH, HTTP, DNS, SMTP 等）都属于**应用层协议**，也就是直接为应用（比如浏览器、文件传输、邮件系统）提供服务的协议。\n- 在应用层之下，还有传输层（常见的 TCP、UDP）为它们提供可靠或不可靠的数据传输服务；再往下是网络层（IP）负责寻址与路由等。\n\n所以，当我们说某个协议是“在 TCP 之上”或“基于 TCP 的”时，就是说这个协议使用 TCP 来做底层的数据传输。\n\n---\n\n\n## 各协议详解\n\n### FTP — 文件传输协议 (File Transfer Protocol)\n\n- **作用 / 用途**：用于在客户端和服务器之间上传、下载和管理文件。\n- **层级 / 依赖**：应用层协议，通常跑在 TCP 之上。\n- **工作机制**：FTP 在通信时，通常会建立两条 TCP 连接：\n    1. **控制连接**（control connection）：用来发送命令（例如登录、切换目录、发出“下载”命令等）\n    2. **数据连接**（data connection）：用来真正传输文件数据或目录列表\n    \n- **优点 / 缺点**：\n    - 优点：功能全面（支持各种文件操作、目录操作、权限管理等）\n    - 缺点：安全性差——用户名、密码、文件内容都以明文形式传输，容易被中间人嗅探拦截 ([维基百科](https://en.wikipedia.org/wiki/File_Transfer_Protocol?utm_source=chatgpt.com \"File Transfer Protocol\"))\n    - 对防火墙和 NAT 支持不好，因为数据连接可能由服务器发起（主动模式时）\n        \n- **改进 / 替代方案**：\n    - **FTPS**：在 FTP 上加上 SSL/TLS 加密\n    - **SFTP**（SSH File Transfer Protocol）：通过 SSH 隧道安全地传输文件（下面会讲 SSH）\n- **典型端口**：21 用于控制连接，20 有时用于数据连接（在主动模式下） ([维基百科](https://en.wikipedia.org/wiki/File_Transfer_Protocol?utm_source=chatgpt.com \"File Transfer Protocol\"))\n    \n\n---\n\n### SSH — 安全外壳协议 (Secure Shell)\n\n- **作用 / 用途**：提供加密的远程登录、命令执行、以及通过隧道转发端口或做文件传输（例如通过 SFTP、SCP）等功能。\n- **层级 / 依赖**：应用层协议，但其内部本身也包含加密、认证、密钥协商等机制。通常运行在 TCP 之上（默认端口 22）。 ([runoob.com](https://www.runoob.com/np/secure-shell.html?utm_source=chatgpt.com \"SSH 协议 - 菜鸟教程\"))\n- **工作机制 / 特性**：\n    1. **连接建立 & 协商**：客户端连接到服务器的 22 端口，双方协商版本、加密算法、密钥交换方法等\n    2. **认证阶段**：客户端使用密码或公钥等方式向服务器认证\n    3. **会话 / 通道管理**：认证成功后，在已建立的加密通道上可以开多个逻辑通道（通道可用于 shell、执行命令、端口转发等） ([jianshu.com](https://www.jianshu.com/p/8e5b7aea52b5?utm_source=chatgpt.com \"SSH 协议原理、组成、认证方式和过程 - 简书\"))\n    4. **端口转发 / 隧道**：SSH 支持三类转发：本地端口转发（local forwarding）、远端端口转发（remote forwarding）、动态转发（相当于 SOCKS 代理） ([知乎专栏](https://zhuanlan.zhihu.com/p/235610836?utm_source=chatgpt.com \"深入了解SSH - 知乎\"))\n- **优点 / 缺点**：\n    - 优点：安全（加密通信、避免明文传输、中间人攻击风险较低）、功能强大\n    - 缺点：稍微复杂，尤其是对密钥管理、权限管理需要注意\n- **典型端口**：22\n    \n\n---\n\n### SFTP — SSH 文件传输协议 (SSH File Transfer Protocol)\n\n- 这是一个 “文件传输” 协议，但它是 **运行在 SSH 之上** 的安全文件传输协议\n- 它利用 SSH 的加密通道来安全地上传／下载文件、管理文件权限等\n- 因为它建立在 SSH 上，所以本身继承了 SSH 的安全性（加密、认证）\n\n---\n\n### HTTP / HTTPS — 超文本传输协议 / 安全版\n\n- **HTTP（HyperText Transfer Protocol）**：\n    - 作用 / 用途：Web 浏览器和 Web 服务器之间通信的基本协议，用来获取网页、图片、脚本、API 接口数据等\n    - 层级 / 依赖：应用层协议，典型地运行在 TCP 之上\n    - 主要机制：客户端发送请求（包含方法如 GET、POST、PUT、DELETE 等、路径、请求头、请求体等），服务器响应（状态行、响应头、响应体）\n    - 特性：无状态（每个请求是独立的，不自动保留之前的状态）\n    - 存在的问题：明文传输，容易被中间人窃听或篡改\n- **HTTPS**：\n    - HTTPS = HTTP + SSL/TLS，加上了加密和身份验证\n    - 在 HTTP 发送真正数据之前，会先通过 TLS/SSL 做握手协商密钥、证书验证等，从而使后续通信内容加密、完整性保护\n    - 特性：提供通信的机密性、完整性和服务器身份验证（有时也支持客户端证书验证）\n    - 在 Web 安全中几乎必须使用 HTTPS 而不是 HTTP\n- 版本演进：HTTP/1.1 → HTTP/2 → HTTP/3（HTTP/3 基于 QUIC，使用 UDP 做传输层） ([CSDN博客](https://blog.csdn.net/weixin_73144915/article/details/147348522?utm_source=chatgpt.com \"TCP/IP、UDP、HTTP、HTTPS、WebSocket 一文讲解 ...\"))\n    \n\n---\n\n### WebSocket\n\n- **作用 / 用途**：在浏览器和服务器之间建立一个“长连接”（persistent connection），可以做双向实时通信\n- **为什么需要 WebSocket**：HTTP 本质上是请求-响应模式，是客户端发起请求才有响应；如果你想让服务器主动推送消息给客户端（如即时聊天、实时更新），就非常不方便。WebSocket 正是为这个场景设计的。\n- **工作机制 / 特性**：\n    1. 首先通过 HTTP 发起一个“升级（Upgrade）”请求，头部中带上 `Upgrade: websocket`、`Connection: Upgrade`、`Sec-WebSocket-Key` 等字段\n    2. 服务端如果接受这个升级请求，就返回响应确认，将连接从 HTTP 协议“切换/升级”到 WebSocket 协议\n    3. 升级成功后，双方可以在这个 TCP 连接上以 WebSocket 帧（frame）的形式进行双向通信，浏览器可以发送消息给服务器，服务器也可以主动推送消息给客户端\n    4. 支持文本帧、二进制帧、控制帧（关闭、ping/pong 等） ([腾讯云](https://cloud.tencent.com/developer/article/1887095?utm_source=chatgpt.com \"万字长文，一篇吃透WebSocket：概念、原理、易错常识 ...\"))\n- **优点 / 缺点**：\n    - 优点：真正的双向通信、低延迟、连接保持，不需要每次都重新握手\n    - 缺点：如果服务器端不善于处理大量长连接或连接管理不佳，可能资源消耗较高\n\n---\n\n### WebDAV — Web 分布式创作与版本控制协议 (Web Distributed Authoring and Versioning)\n\n- **作用 / 用途**：WebDAV 是一个扩展 HTTP 的协议，使得客户端可以远程进行文件管理（创建、删除、修改、锁定、属性操作、版本控制等），在 Web 服务器上像操作文件系统那样操作文档 / 资源\n- **层级 / 依赖**：是 HTTP 的扩展协议，运行在 HTTP / HTTPS 之上\n- **应用场景**：常用于云盘、版本控制、远程文档编辑协作等\n\n---\n\n### Telnet\n\n- **作用 / 用途**：远程登录协议，允许用户在远程主机上启动交互式 shell 或命令行界面\n- **层级 / 依赖**：应用层协议，通常基于 TCP\n- **问题 / 缺陷**：**不加密**，所有命令和数据（包括用户名、密码）都是明文传输，非常容易被中间人截获\n- **历史 / 使用**：在早期广泛使用，但在现代多数场景下被 SSH 取代了\n\n---\n\n### SMTP — 简单邮件传输协议 (Simple Mail Transfer Protocol)\n\n- **作用 / 用途**：用于在邮件服务器之间传递邮件，以及客户端向邮件服务器发送邮件\n- **层级 / 依赖**：应用层协议，通常运行在 TCP 上\n- **机制**：客户端或发送服务器将邮件发给目标邮件服务器；邮件服务器之间通过 SMTP 协议转发邮件至最终目的地\n- **常见通信**：可与其他邮件协议（如 POP3、IMAP）配合使用，负责“发送”而不是“接收／读取”的功能\n\n---\n\n### DNS — 域名系统 (Domain Name System)\n\n- **作用 / 用途**：把人类易记的域名（例如 `www.example.com`）转换为机器能识别的 IP 地址（例如 `93.184.216.34`）\n- **层级 / 依赖**：应用层协议，通常运行在 UDP 上（小查询）或者 TCP（大响应或区域传输时）\n- **工作机制**：\n    1. 客户端向本地 DNS 服务器发起查询请求\n    2. 如果本地 DNS 服务器没有缓存，会向上级 DNS 服务器、根服务器、顶级域名服务器、权威服务器逐层查询\n    3. 最终得到域名对应的 IP 地址，缓存在本地 DNS 服务器以便后续查询快速响应\n- **扩展 / 安全**：DNSSEC（DNS Security Extensions）用于防止 DNS 缓存中毒、篡改等安全问题\n    \n\n---\n",
  "计算机网络/HTTP常见状态码.md": "\n---\n\n# HTTP 状态码详解\n\nHTTP 状态码分为 **5 大类**，每个类别代表不同的响应类型。\n\n---\n\n## 1xx：信息响应\n\n表示请求已接收，正在继续处理。\n\n- **100 Continue**：客户端应继续请求（常用于大文件上传前的预检）。\n- **101 Switching Protocols**：服务器同意切换协议（如 WebSocket）。\n- **102 Processing (WebDAV)**：服务器正在处理请求，还未完成。\n- **103 Early Hints**：预先返回一些响应头，提示客户端（如提前加载资源）。\n    \n\n---\n\n## 2xx：成功响应\n\n表示请求已成功被服务器接收、理解和处理。\n\n- **200 OK**：请求成功，返回所需资源。\n- **201 Created**：请求成功并创建了新资源。\n- **202 Accepted**：请求已接受，但尚未处理完成。\n- **203 Non-Authoritative Information**：返回的元信息不是来自源服务器。\n- **204 No Content**：请求成功，但没有返回内容。\n- **205 Reset Content**：请求成功，要求客户端重置视图（如表单清空）。\n- **206 Partial Content**：返回部分内容（用于断点续传/分块下载）。\n- **207 Multi-Status (WebDAV)**：返回多个状态信息。\n- **208 Already Reported (WebDAV)**：避免重复报告资源。\n- **226 IM Used**：服务器完成请求，返回应用了某些实例操作的结果。\n    \n\n---\n\n## 3xx：重定向\n\n表示需要进一步操作以完成请求。\n\n- **300 Multiple Choices**：有多个可选资源。\n- **301 Moved Permanently**：资源永久重定向到新位置。\n- **302 Found**：资源临时重定向（常见于登录跳转）。\n- **303 See Other**：请求的响应可在另一个 URL 获取（常用于 POST → GET）。\n- **304 Not Modified**：资源未修改，客户端可使用缓存。\n- **305 Use Proxy**（已废弃）：要求通过代理访问。\n- **307 Temporary Redirect**：临时重定向，请求方法不变。\n- **308 Permanent Redirect**：永久重定向，请求方法不变。\n    \n\n---\n\n## 4xx：客户端错误\n\n表示请求存在错误，客户端需要修改。\n\n- **400 Bad Request**：请求无效或语法错误。\n- **401 Unauthorized**：未授权，需要身份验证。\n- **402 Payment Required**（保留）：最初为数字支付设计，现少用。\n- **403 Forbidden**：服务器理解请求，但拒绝执行。\n- **404 Not Found**：请求的资源不存在。\n- **405 Method Not Allowed**：请求方法不被允许。\n- **406 Not Acceptable**：请求的资源不满足客户端的 Accept 条件。\n- **407 Proxy Authentication Required**：需要代理身份验证。\n- **408 Request Timeout**：请求超时。\n- **409 Conflict**：请求冲突（如资源版本冲突）。\n- **410 Gone**：资源永久删除。\n- **411 Length Required**：需要 Content-Length 头。\n- **412 Precondition Failed**：请求头中的前提条件失败。\n- **413 Payload Too Large**：请求体过大。\n- **414 URI Too Long**：请求的 URI 过长。\n- **415 Unsupported Media Type**：不支持的媒体类型。\n- **416 Range Not Satisfiable**：请求的范围无效。\n- **417 Expectation Failed**：Expect 头字段无法满足。\n- **418 I'm a teapot**（愚人节彩蛋）：服务器拒绝煮咖啡。\n- **421 Misdirected Request**：请求发往错误的服务器。\n- **422 Unprocessable Entity (WebDAV)**：语义错误，无法处理。\n- **423 Locked (WebDAV)**：资源被锁定。\n- **424 Failed Dependency (WebDAV)**：依赖的请求失败。\n- **425 Too Early**：服务器不愿意处理过早的请求。\n- **426 Upgrade Required**：需要升级协议（如切换到 TLS/1.3）。\n- **428 Precondition Required**：需要先决条件。\n- **429 Too Many Requests**：请求过多（限流）。\n- **431 Request Header Fields Too Large**：请求头太大。\n- **451 Unavailable For Legal Reasons**：因法律原因不可用（如审查）。\n    \n\n---\n\n## 5xx：服务器错误\n\n表示服务器在处理请求时发生错误。\n\n- **500 Internal Server Error**：服务器内部错误。\n- **501 Not Implemented**：服务器不支持请求方法。\n- **502 Bad Gateway**：网关错误（上游服务器无效响应）。\n- **503 Service Unavailable**：服务器不可用（超载/维护）。\n- **504 Gateway Timeout**：网关超时。\n- **505 HTTP Version Not Supported**：不支持的 HTTP 版本。\n- **506 Variant Also Negotiates**：内容协商循环错误。\n- **507 Insufficient Storage (WebDAV)**：存储空间不足。\n- **508 Loop Detected (WebDAV)**：检测到无限循环。\n- **510 Not Extended**：请求未满足扩展策略。\n- **511 Network Authentication Required**：需要网络认证（如 Wi-Fi 登录页）。\n    \n\n---\n\n# 总结\n\n- **1xx**：信息 → 请求处理中。\n- **2xx**：成功 → 请求已完成。\n- **3xx**：重定向 → 需要进一步操作。\n- **4xx**：客户端错误 → 请求有问题。\n- **5xx**：服务器错误 → 服务器处理失败。\n    \n\n---\n",
  "计算机网络/HTTP版本协议对比区别.md": "\n\n---\n\n# HTTP 协议版本对比总结\n\n## 一、HTTP/1.1\n\n> 发布于 1997 年，是目前仍然广泛使用的版本。\n\n### 特点\n\n- **长连接（Keep-Alive）**\n    \n    - 支持持久连接，多个请求可复用一个 TCP 连接，避免频繁握手。\n        \n- **管道化（Pipeline）**\n    \n    - 可以在一个 TCP 连接上同时发送多个请求，但**响应必须按顺序返回** → 存在 **队头阻塞（Head-of-Line Blocking）**。\n        \n- **明文传输**\n    \n    - 默认基于 TCP，数据未加密（可结合 TLS 实现 HTTPS）。\n        \n- **请求/响应模型**\n    \n    - 一次请求对应一次响应，请求头和响应头通常冗余。\n        \n\n### 功能/不足\n\n- 每个请求都会带上完整的 Header，冗余大。\n    \n- 并发能力有限，通常需要开启多个 TCP 连接提升性能。\n    \n- 队头阻塞问题严重。\n    \n\n---\n\n## 二、HTTP/2\n\n> 发布于 2015 年，目标是解决 HTTP/1.1 的性能瓶颈。\n\n### 特点\n\n- **二进制分帧（Binary Framing）**\n    \n    - 传输不再是文本，而是二进制帧，效率更高。\n        \n- **多路复用（Multiplexing）**\n    \n    - 同一个 TCP 连接中可同时传输多个流，避免队头阻塞（但仍受 TCP 的 HOLB 影响）。\n        \n- **首部压缩（HPACK）**\n    \n    - 通过动态表和静态表压缩请求/响应头，大幅减少冗余数据。\n        \n- **服务器推送（Server Push）**\n    \n    - 服务端可主动推送资源，减少延迟（但实际应用中使用较少）。\n        \n- **优先级（Priority）**\n    \n    - 支持请求优先级，优化资源调度。\n        \n\n### 功能/不足\n\n- 显著提升带宽利用率和传输效率。\n    \n- 依然基于 TCP，**若 TCP 丢包，会阻塞整个连接**（HOLB 依旧存在）。\n    \n- 实现复杂度高。\n    \n\n---\n\n## 三、HTTP/3\n\n> 基于 **QUIC（UDP 之上的新传输层协议）** 的 HTTP 新版本，正在逐渐普及。\n\n### 特点\n\n- **基于 QUIC 协议（UDP）**\n    \n    - 避免了 TCP 的握手延迟和队头阻塞问题。\n        \n- **内置加密（TLS 1.3）**\n    \n    - 加密是协议默认部分，不再是扩展。\n        \n- **0-RTT 连接建立**\n    \n    - 支持快速建立连接，降低延迟。\n        \n- **多路复用**\n    \n    - 流之间独立，单个流丢包不会阻塞其他流，彻底解决队头阻塞。\n        \n- **更好的移动端体验**\n    \n    - IP/网络切换时（如 Wi-Fi → 4G），连接可快速恢复，不必像 TCP 那样重新握手。\n        \n\n### 功能/不足\n\n- 传输性能和用户体验更佳，尤其适合移动网络。\n    \n- 部署复杂度高，需要操作系统、浏览器、服务端的全面支持。\n    \n- UDP 在部分网络环境下可能受限。\n    \n\n---\n\n# HTTP 版本对比表\n\n|特性|HTTP/1.1|HTTP/2|HTTP/3|\n|---|---|---|---|\n|**传输协议**|TCP|TCP|QUIC（基于 UDP）|\n|**连接方式**|长连接（Keep-Alive）|单连接多路复用|单连接多路复用|\n|**队头阻塞**|严重|缓解但仍存在（TCP 层）|彻底解决（流级别独立）|\n|**数据格式**|文本|二进制分帧|二进制分帧|\n|**头部压缩**|无|HPACK|QPACK（HPACK 的改进版）|\n|**加密**|可选（HTTPS）|强制 TLS（大多数实现）|内置 TLS 1.3（强制）|\n|**性能优化**|需多连接并发|多路复用、服务器推送、头部压缩|多路复用、快速握手、移动友好|\n|**适用场景**|基础网络通信|现代 Web，大流量网站|移动端、大规模应用、低延迟场景|\n\n---\n\n✅ **总结**\n\n- **HTTP/1.1**：简单可靠，但存在性能瓶颈（队头阻塞、冗余开销）。\n    \n- **HTTP/2**：提升性能，多路复用、头部压缩，但依然受 TCP 限制。\n    \n- **HTTP/3**：基于 QUIC，解决 TCP 根本问题，面向未来互联网，特别适合移动网络。\n    \n\n---\n\n## HTTP/1.1\n\n> 定义了最核心、最常见的请求方法，是现代 Web 的基础。\n\n**支持的方法：**\n- **GET**：获取资源。\n- **POST**：向服务器提交数据。\n- **HEAD**：获取响应头，不返回实体内容。\n- **PUT**：替换指定资源。\n- **DELETE**：删除指定资源。\n- **OPTIONS**：查询服务器支持的通信选项。\n- **TRACE**：回显请求内容（调试用，实际较少使用）。\n- **CONNECT**：建立隧道（常用于 HTTPS 代理）。\n👉 **特点**：HTTP/1.1 是第一个全面规范化这些方法的版本。",
  "计算机网络/TCP的三次握手四次挥手总结.md": "# 🌐 TCP 连接与断开总结\n\n## 🔗 TCP 连接建立（三次握手）\n1. **Client → Server**：发送 `SYN`（请求建立连接）。  \n2. **Server → Client**：回复 `SYN + ACK`（同意并确认请求），并分配资源。  \n3. **Client → Server**：再发送 `ACK`（确认收到），也分配资源。  \n\n✅ **完成三次握手，连接建立成功。**\n\n---\n\n## 🔒 TCP 连接断开（四次挥手）\n1. **Client → Server**：发送 `FIN`（我没有数据要发了）。  \n2. **Server → Client**：回复 `ACK`（收到请求，但可能还有数据要发），此时 Client 进入 `FIN_WAIT` 状态。  \n3. **Server → Client**：当数据发送完成，发送 `FIN`（我也准备好关闭了）。  \n4. **Client → Server**：回复 `ACK`，并进入 `TIME_WAIT` 状态，等待 2MSL，确保 Server 收到确认。  \n\n✅ **完成四次挥手，连接安全关闭。**\n\n---\n\n## ❓ 为什么要三次握手？\n- **两次握手的风险**：若请求报文滞留在网络中，Server 可能会收到多次请求，建立多个无效连接，造成资源浪费。  \n- **三次握手的好处**：避免 **重复连接** 的问题，确保 **双方通信能力正常**。\n\n---\n\n## ❓ 为什么要四次挥手？\n- 关闭连接需要 **双向确认**：  \n  - Client 不再发送数据，但 **Server 可能还有数据要发**。  \n  - 所以必须分为两步：  \n    - **Client 先关闭发送通道**。  \n    - **Server 再关闭自己的发送通道**。  \n- 保证 **双方通信的完整性**，不会丢数据。\n\n---\n\n## 📌 使用 TCP 的常见协议\n- 📂 **FTP**（文件传输协议）  \n- 🖥️ **Telnet**（远程登录协议）  \n- 📧 **SMTP**（简单邮件传输协议）  \n- 📩 **POP3**（接收邮件协议）  \n- 🌍 **HTTP/HTTPS**（超文本传输协议）  \n",
  "计算机网络/网络层次划分.md": "\n---\n\n# OSI 七层模型\n\nOSI（Open Systems Interconnection）模型是一个抽象的分层网络通信模型，将网络通信划分为 **7 层**，从下到上分别是：\n\n## 1. 物理层（Physical Layer）\n\n- **功能**：负责比特流的传输，定义接口、传输媒介、电气特性。\n    \n- **数据单位**：比特（Bit）\n    \n- **设备**：网线、光纤、中继器、集线器、调制解调器\n    \n\n---\n\n## 2. 数据链路层（Data Link Layer）\n\n- **功能**：将比特组织成帧，负责点对点传输、差错检测和纠正。\n    \n- **数据单位**：帧（Frame）\n    \n- **设备**：交换机、网卡\n    \n- **协议**：Ethernet（以太网）、PPP、HDLC\n    \n\n---\n\n## 3. 网络层（Network Layer）\n\n- **功能**：负责寻址和路径选择，确保数据从源端到达目的端。\n    \n- **数据单位**：包（Packet）\n    \n- **设备**：路由器\n    \n- **协议**：IP、ICMP、ARP、RIP、OSPF\n    \n\n---\n\n## 4. 传输层（Transport Layer）\n\n- **功能**：提供端到端的传输服务，保证数据完整性和可靠性。\n    \n- **数据单位**：段（Segment，TCP）或数据报（Datagram，UDP）\n    \n- **协议**：TCP、UDP\n    \n\n---\n\n## 5. 会话层（Session Layer）\n\n- **功能**：管理会话，建立、维护、终止通信会话。\n    \n- **常见应用**：RPC、NetBIOS\n    \n\n---\n\n## 6. 表示层（Presentation Layer）\n\n- **功能**：数据表示、编码、加密、压缩。\n    \n- **例子**：SSL/TLS、JPEG、MPEG、ASCII、EBCDIC\n    \n\n---\n\n## 7. 应用层（Application Layer）\n\n- **功能**：直接为用户提供服务和接口。\n    \n- **协议**：HTTP、FTP、SMTP、DNS、Telnet\n    \n\n---\n\n# TCP/IP 模型\n\nTCP/IP 模型是互联网的基础架构，分为 **4 层**（有时也称 5 层）：\n\n## 1. 网络接口层（Network Access Layer）\n\n- **对应 OSI 的物理层 + 数据链路层**\n    \n- 处理硬件接口、数据帧传输。\n    \n\n---\n\n## 2. 网络层（Internet Layer）\n\n- **对应 OSI 的网络层**\n    \n- 负责寻址与路由。\n    \n- **协议**：IP、ICMP、ARP、IGMP\n    \n\n---\n\n## 3. 传输层（Transport Layer）\n\n- **对应 OSI 的传输层**\n    \n- 端到端通信、数据可靠传输。\n    \n- **协议**：TCP、UDP\n    \n\n---\n\n## 4. 应用层（Application Layer）\n\n- **对应 OSI 的会话层、表示层、应用层**\n    \n- 提供用户应用服务。\n    \n- **协议**：HTTP、FTP、SMTP、DNS、SSH\n    \n\n---\n\n# OSI 与 TCP/IP 对比\n\n|**OSI 七层模型**|**TCP/IP 模型**|**功能说明**|\n|---|---|---|\n|应用层、表示层、会话层|应用层|为应用程序提供服务（HTTP/FTP/DNS 等）|\n|传输层|传输层|提供端到端的可靠传输（TCP/UDP）|\n|网络层|网络层|提供寻址与路由（IP/ICMP）|\n|数据链路层、物理层|网络接口层|提供底层数据传输与硬件接口|\n\n---\n\n✅ **总结**\n\n- **OSI 模型** 是理论模型，更细分，利于学习和理解。\n    \n- **TCP/IP 模型** 更贴近实际应用，是互联网的主流实现。\n    \n- 二者的核心思想都是 **分层、模块化、互相独立**，便于标准化和实现。\n    \n\n---\n\n",
  "计算机网络/计算机网络期末考试综合题简单论述.md": "\n\n  **请简述TCP协议的 三次握手过程以及作用**\n  \n## **一、三次握手过程**\n\n1. **第一次握手（SYN）**\n    - 客户端向服务器发送一个 **SYN** 报文，表示希望建立连接，并告诉服务器自己初始序列号（`seq=x`）。\n2. **第二次握手（SYN + ACK）**\n    - 服务器收到后，回复一个 **SYN + ACK** 报文：\n        - SYN 用来表示同意建立连接（`seq=y`）。\n        - ACK 用来确认收到了客户端的 SYN（`ack=x+1`）。\n3. **第三次握手（ACK）**\n    - 客户端收到服务器的 SYN+ACK 后，发送 **ACK** 报文（`ack=y+1`）。\n    - 服务器收到后，连接正式建立。\n\n---\n\n## **二、三次握手的作用**\n\n1. **确认双方的发送与接收能力是否正常**\n    - 客户端能发送、服务器能接收\n    - 服务器能发送、客户端能接收\n2. **同步双方的初始序列号（Seq）**\n    - 为后续的可靠传输提供基础（重传、排序等）。\n3. **避免旧连接请求带来的混乱**\n    - 防止已失效的 SYN 报文重新到达引起错误连接。\n\n\n\n**子网掩码的定义及作用**\n \n一、子网掩码的定义\n \n子网掩码是一个32位的二进制数，与IPv4地址一一对应，由连续的1和连续的0组成：其中1对应的是IP地址中的网络位，0对应的是IP地址中的主机位。它通常也会采用点分十进制的形式表示，比如最常见的 255.255.255.0 （对应二进制 11111111 11111111 11111111 00000000 ）。\n \n二、子网掩码的主要作用\n \n1. 划分网络位与主机位\n子网掩码通过二进制位的 1 和 0 ，明确区分一个IP地址中哪些部分是网络标识、哪些部分是主机标识，这是其最核心的作用。例如IP地址 192.168.1.10 搭配子网掩码 255.255.255.0 时，前24位是网络位（ 192.168.1 ），后8位是主机位（ 10 ）。\n2. 判断两台主机是否在同一子网\n将两台主机的IP地址分别与子网掩码进行按位与运算，若运算结果相同，说明二者处于同一子网，可直接通信；若结果不同，则需通过路由器转发才能通信。\n3. 实现子网划分\n通过调整子网掩码中 1 的位数（即借位），可以将一个大的网络划分为多个小的子网，有效解决IPv4地址资源浪费的问题，同时也能减少网络内的广播域，提升网络性能。\n \n**HTTP协议的工作原理**\n \nHTTP（超文本传输协议）是客户端与服务器之间的应用层协议，基于请求-响应模式，核心工作流程简洁高效：\n \n1. 客户端（如浏览器、APP）向服务器发起TCP连接（默认端口80）；\n2. 连接建立后，客户端发送HTTP请求（含请求方法、资源路径、请求头/体等）；\n3. 服务器接收请求并处理，返回HTTP响应（含状态码、响应头、资源数据等）；\n4. 客户端接收响应并解析展示资源，TCP连接可根据配置关闭或复用。\n \n核心特点：无状态（每次请求独立，需Cookie/Session维持状态）、明文传输（HTTPS通过TLS加密改进）。\n\n**IP地址的分类及A、B、C类地址的主要区别**\n \n一、IP地址的分类\n \nIPv4地址的分类是按网络规模和用途划分的，共分为A、B、C、D、E五类：\n \n- A/B/C类：用于单播通信（一对一传输），对应大型、中型、小型局域网/广域网；\n- D类：用于组播通信（一对多传输）；\n- E类：为保留地址，用于科研和实验用途。\n \n二、A、B、C类地址的主要区别\n \n主要体现在网络位与主机位的划分、地址范围、适用场景三个方面，具体对比如下：\n \n1. 网络位与主机位\n- A类：前8位为网络位，后24位为主机位；\n- B类：前16位为网络位，后16位为主机位；\n- C类：前24位为网络位，后8位为主机位。\n2. 地址范围（点分十进制）\n- A类：1.0.0.0 ~126.255.255.255（127.0.0.0为回环地址，不属于A类可用地址）；\n- B类：128.0.0.0 ~191.255.255.255；\n- C类：192.0.0.0 ~223.255.255.255。\n3. 适用场景\n- A类：适用于大型网络（如大型企业、互联网服务商），可容纳大量主机；\n- B类：适用于中型网络（如中型企业、高校）；\n- C类：适用于小型网络（如小型公司、家庭局域网），主机数量有限。\n\n**什么是网络拓扑结构，常见的网络拓扑结构有哪些**\n 结论：网络拓扑结构是指网络中节点与链路的连接方式与布局，决定通信路径、可靠性与扩展性。常见类型有星型、环型、总线型、树型、网状、全连接、混合等。\n \n常见拓扑与特点\n- 星型：所有节点连到中心设备；易管理、单点故障风险高。\n- 环型：节点连成闭合环；结构简单、任一节点/链路故障影响整体。\n- 总线型：共享一条传输介质；成本低、冲突与扩展性差。\n- 树型（层次）：根-枝干-叶的层级结构；易扩展、上层设备故障影响大。\n- 网状：节点间有多条冗余路径；高可靠、复杂且成本高。\n- 全连接：每对节点都直接相连；冗余最高、成本最高。\n- 混合：组合多种拓扑（如星型+环型）；兼顾性能与成本，常见于企业网。\n \n\n\n",
  "📒萌芽笔记.md": "\n## 🧭引言\n你好，陌生人！这是我的学习笔记，用来展示我的一些学习路径\n也希望能帮助到CS专业中努力学习的你\n欢迎和我一起讨论和交流学习！\n\n## 🔗联系方式\nQQ：3205788256\n邮箱：3205788256@qq.com\n个人主页：shumengya.top\n作品集：work.shumengya.top\n\n## ❓关于\n本网站使用**React**框架搭建\n所有笔记均为**Markdown**格式，可直接复制和下载\n转载请标明网站地址：[note.shumengya.top](https://note.shumengya.top)\n谢谢您的配合与理解！\n\n\n"
}