165 lines
542 KiB
JSON
165 lines
542 KiB
JSON
{
|
||
"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": "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/大语言模型的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#拉取最新镜像\ndocker pull vikiboss/60s:latest \ndocker pull mlikiowa/napcat-docker:latest\ndocker pull couchdb:latest #Obsidian同步的数据库\ndocker pull aceberg/watchyourlan #扫描局域网的工具\n\ndocker pull dpanel/dpanel:latest\n\n\n#停止并删除旧容器\ndocker stop 60s\ndocker rm 60s\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#60s api后端\ndocker run -d \\\n --restart always \\\n --name 60s \\\n -p 4399:4399 \\\n vikiboss/60s:latest\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镜像/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镜像/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镜像/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 \\\n -e MYSQL_ROOT_PASSWORD=shumengya520 \\\n -e MYSQL_DATABASE=shumengyadb \\\n -e MYSQL_USER=shumengya \\\n -e MYSQL_PASSWORD=shumengya520 \\\n -v /shumengya/docker/storage/mysql:/var/lib/mysql \\\n -p 3306:3306 \\\n --restart=always \\\n mysql:latest\n \n \ndocker run -d \\\n --name mysql \\\n -e MYSQL_ROOT_PASSWORD=shumengya520 \\\n -e MYSQL_DATABASE=shumengyadb \\\n -e MYSQL_USER=shumengya \\\n -e MYSQL_PASSWORD=shumengya520 \\\n -v /shumengya/docker/storage/mysql:/var/lib/mysql \\\n -p 3306:3306 \\\n --restart=always \\\n mysql:5.7.44\n\n```\n\n```bash\n#典型的非关系型数据库(json)\ndocker pull mysql:5.7.44\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#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```",
|
||
"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/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\n代码解释\n\n1. 初始化哈希表:num_map 用于存储元素值到索引的映射\n2. 遍历数组:使用 enumerate 函数同时获取元素的索引 i 和数值 num\n3. 计算补数:对于每个 num,计算 complement = target - num\n4. 检查补数是否存在:如果补数存在于哈希表中,说明找到了两个数,返回它们的索引\n5. 存储当前元素:如果补数不存在,将当前元素及其索引存入哈希表,以便后续查找\n6. 返回结果:如果遍历结束仍未找到,返回空列表(但题目保证有解,所以不会执行到此)\n\n这种方法确保了高效查找,适用于大规模数据输入,是解决此类问题的标准方法。",
|
||
"Linux/busybox v1.36命令简介.md": "以下是针对 **BusyBox** 中每条命令的简要说明:\r\n\r\n1. **[**:测试表达式的真假。\r\n2. **[[**:增强版的条件测试命令。\r\n3. **acpid**:管理系统的 ACPI 事件。\r\n4. **adjtimex**:调整系统时间。\r\n5. **ar**:创建、修改、提取归档文件。\r\n6. **arch**:显示机器架构类型。\r\n7. **arp**:显示或修改 ARP 缓存。\r\n8. **arping**:向网络发送 ARP 请求。\r\n9. **ascii**:显示 ASCII 表。\r\n10. **ash**:一个轻量级的 shell。\r\n11. **awk**:强大的文本处理工具。\r\n12. **base32**:以 Base32 编码格式进行数据转换。\r\n13. **base64**:以 Base64 编码格式进行数据转换。\r\n14. **basename**:从路径中提取文件名。\r\n15. **bbconfig**:配置 BusyBox。\r\n16. **beep**:产生蜂鸣声。\r\n17. **blkdiscard**:丢弃磁盘块。\r\n18. **blkid**:显示块设备的标识。\r\n19. **blockdev**:对块设备进行操作。\r\n20. **brctl**:管理网桥接口。\r\n21. **bunzip2**:解压 `.bz2` 格式文件。\r\n22. **bzcat**:查看 `.bz2` 格式文件内容。\r\n23. **bzip2**:压缩文件为 `.bz2` 格式。\r\n24. **cal**:显示日历。\r\n25. **cat**:连接文件并显示内容。\r\n26. **chat**:发送控制字符以进行调制解调器通信。\r\n27. **chattr**:改变文件的属性。\r\n28. **chcon**:改变文件的 SELinux 上下文。\r\n29. **chgrp**:改变文件的组。\r\n30. **chmod**:改变文件的权限。\r\n31. **chown**:改变文件的拥有者。\r\n32. **chroot**:改变根目录。\r\n33. **chrt**:操作进程的调度策略。\r\n34. **chvt**:切换虚拟终端。\r\n35. **cksum**:计算文件的校验和。\r\n36. **clear**:清除终端屏幕。\r\n37. **cmp**:比较两个文件。\r\n38. **comm**:比较两个已排序文件的内容。\r\n39. **conspy**:查看控制台的输出。\r\n40. **cp**:复制文件。\r\n41. **cpio**:创建、解压 cpio 格式归档。\r\n42. **crc32**:计算 CRC32 校验和。\r\n43. **crond**:周期性执行任务的守护进程。\r\n44. **crontab**:编辑 cron 表。\r\n45. **cttyhack**:改变控制终端。\r\n46. **cut**:按列剪切文本。\r\n47. **date**:显示或设置系统日期和时间。\r\n48. **dc**:计算器程序。\r\n49. **dd**:转换和复制文件。\r\n50. **deallocvt**:释放虚拟终端。\r\n51. **depmod**:生成内核模块依赖关系。\r\n52. **devmem**:访问物理内存。\r\n53. **df**:显示文件系统的磁盘空间使用情况。\r\n54. **dhcprelay**:转发 DHCP 请求。\r\n55. **diff**:比较文件的不同之处。\r\n56. **dirname**:获取路径的目录部分。\r\n57. **dmesg**:显示内核的消息缓冲区内容。\r\n58. **dnsd**:轻量级 DNS 服务器。\r\n59. **dnsdomainname**:显示域名。\r\n60. **dos2unix**:转换 DOS 格式文本为 Unix 格式。\r\n61. **du**:显示磁盘使用情况。\r\n62. **dumpkmap**:转储键盘映射。\r\n63. **dumpleases**:显示 DHCP 租约。\r\n64. **echo**:显示一行文本。\r\n65. **ed**:文本编辑器。\r\n66. **egrep**:扩展正则表达式的 grep 命令。\r\n67. **eject**:弹出光盘。\r\n68. **env**:显示或设置环境变量。\r\n69. **ether-wake**:发送 Wake-on-LAN 魔术包。\r\n70. **expand**:将制表符转换为空格。\r\n71. **expr**:计算表达式的值。\r\n72. **factor**:因数分解。\r\n73. **fakeidentd**:模拟 identd 服务。\r\n74. **false**:返回失败状态。\r\n75. **fatattr**:显示或修改 FAT 文件系统的属性。\r\n76. **fbset**:设置帧缓冲设备的参数。\r\n77. **fbsplash**:管理帧缓冲启动画面。\r\n78. **fdflush**:刷新文件描述符。\r\n79. **fdformat**:格式化软盘。\r\n80. **fdisk**:管理磁盘分区。 \r\n81. **fgconsole**:切换到指定的虚拟终端。\r\n82. **fgrep**:固定字符串搜索工具。\r\n83. **find**:搜索文件。\r\n84. **findfs**:查找文件系统。\r\n85. **flash_eraseall**:擦除闪存设备。\r\n86. **flash_lock**:锁定闪存设备。\r\n87. **flash_unlock**:解锁闪存设备。\r\n88. **flock**:对文件进行锁定。\r\n89. **fold**:折叠文本行。\r\n90. **free**:显示内存使用情况。\r\n91. **freeramdisk**:释放 RAM 磁盘。\r\n92. **fsck**:检查文件系统的完整性。\r\n93. **fsck.minix**:检查 Minix 文件系统。\r\n94. **fsfreeze**:冻结文件系统以进行备份。\r\n95. **fstrim**:修剪未使用的磁盘空间。\r\n96. **fsync**:强制磁盘同步。\r\n97. **ftpd**:启动 FTP 服务器。\r\n98. **ftpget**:下载文件通过 FTP。\r\n99. **ftpput**:上传文件通过 FTP。\r\n100. **fuser**:显示正在使用某个文件的进程。\r\n101. **getenforce**:显示 SELinux 的状态。\r\n102. **getopt**:解析命令行选项。\r\n103. **grep**:搜索文本中的模式。\r\n104. **groups**:显示用户所属的组。\r\n105. **gunzip**:解压 `.gz` 文件。\r\n106. **gzip**:压缩文件为 `.gz` 格式。\r\n107. **hd**:显示硬盘的分区信息。\r\n108. **hdparm**:设置硬盘参数。\r\n109. **head**:显示文件的开头部分。\r\n110. **hexdump**:以十六进制格式显示文件内容。\r\n111. **hexedit**:编辑十六进制文件。\r\n112. **hostname**:显示或设置主机名。\r\n113. **httpd**:启动 HTTP 服务器。\r\n114. **hush**:一个小型 shell。\r\n115. **hwclock**:访问硬件时钟。\r\n116. **id**:显示用户和组信息。\r\n117. **ifconfig**:配置网络接口。\r\n118. **ifdown**:关闭网络接口。\r\n119. **ifenslave**:配置链路聚合。\r\n120. **ifplugd**:监控网络接口的连接状态。\r\n121. **ifup**:启用网络接口。\r\n122. **inetd**:启动网络服务守护进程。\r\n123. **inotifyd**:启动文件系统事件监控。\r\n124. **insmod**:加载内核模块。\r\n125. **install**:复制文件并设置权限。\r\n126. **ionice**:设置进程的 I/O 优先级。\r\n127. **iostat**:显示 CPU 和 I/O 统计信息。\r\n128. **ip**:配置网络接口和路由。\r\n129. **ipaddr**:显示或设置 IP 地址。\r\n130. **ipcalc**:计算和显示 IP 地址信息。\r\n131. **ipcrm**:删除共享内存、消息队列、信号量。\r\n132. **ipcs**:显示进程间通信的状态。\r\n133. **iplink**:管理网络接口的状态。\r\n134. **ipneigh**:显示邻居表。\r\n135. **iproute**:管理路由表。\r\n136. **iprule**:显示或管理路由规则。\r\n137. **iptunnel**:配置 IP 隧道。\r\n138. **kbd_mode**:设置键盘模式。\r\n139. **kill**:终止进程。\r\n140. **killall**:终止指定名称的所有进程。\r\n141. **killall5**:终止所有进程。\r\n142. **klogd**:内核日志守护进程。\r\n143. **less**:分页显示文件内容。\r\n144. **link**:创建硬链接。\r\n145. **ln**:创建硬链接或符号链接。\r\n146. **loadfont**:加载字体。\r\n147. **loadkmap**:加载键盘映射。\r\n148. **logread**:显示日志文件内容。\r\n149. **losetup**:管理环回设备。\r\n150. **ls**:列出目录内容。\r\n\r\n继续接着之前的命令列表进行总结:\r\n\r\n151. **lsattr**:显示文件的属性。\r\n\r\n152. **lsmod**:显示加载的内核模块。\r\n\r\n153. **lsof**:列出打开的文件。\r\n\r\n154. **lspci**:显示所有 PCI 设备。\r\n\r\n155. **lsscsi**:显示 SCSI 设备信息。\r\n\r\n156. **lsusb**:列出 USB 设备。\r\n\r\n157. **lzcat**:解压 `.lz` 文件并显示内容。\r\n\r\n158. **lzma**:压缩文件为 `.lzma` 格式。\r\n\r\n159. **lzop**:快速的文件压缩工具。\r\n\r\n160. **lzopcat**:查看 `.lzo` 格式文件内容。\r\n\r\n161. **makedevs**:创建设备节点。\r\n\r\n162. **makemime**:生成 MIME 类型文件。\r\n\r\n163. **man**:查看手册页(如果有)。\r\n\r\n164. **md5sum**:计算文件的 MD5 校验和。\r\n\r\n165. **mesg**:控制终端消息的接收。\r\n\r\n166. **microcom**:串行通信工具。\r\n\r\n167. **mim**:提取文件的 MIME 类型。\r\n\r\n168. **mkdir**:创建目录。\r\n\r\n169. **mkdosfs**:创建 FAT 文件系统。\r\n\r\n170. **mke2fs**:创建 ext2 文件系统。\r\n\r\n171. **mkfifo**:创建命名管道。\r\n\r\n172. **mkfs.ext2**:创建 ext2 文件系统。\r\n\r\n173. **mkfs.minix**:创建 Minix 文件系统。\r\n\r\n174. **mkfs.reiser**:创建 Reiser 文件系统。\r\n\r\n175. **mkfs.vfat**:创建 VFAT 文件系统。\r\n\r\n176. **mknod**:创建块设备或字符设备文件。\r\n\r\n177. **mkswap**:创建交换分区。\r\n\r\n178. **mktemp**:创建临时文件。\r\n\r\n179. **modinfo**:显示内核模块的信息。\r\n\r\n180. **modprobe**:加载或卸载内核模块。\r\n\r\n181. **more**:分页显示文件内容。\r\n\r\n182. **mount**:挂载文件系统。\r\n\r\n183. **mountpoint**:检查是否为挂载点。\r\n\r\n184. **mpstat**:显示 CPU 使用统计信息。\r\n\r\n185. **mv**:移动或重命名文件。\r\n\r\n186. **nameif**:根据 MAC 地址设置网络接口名称。\r\n\r\n187. **nanddump**:转储 NAND 闪存的内容。\r\n\r\n188. **nandwrite**:将数据写入 NAND 闪存。\r\n\r\n189. **nbd-client**:连接到网络块设备。\r\n\r\n190. **nc**:Netcat 工具,用于读写网络连接。\r\n\r\n191. **netstat**:显示网络连接状态。\r\n\r\n192. **nice**:调整进程的优先级。\r\n\r\n193. **nl**:显示带有行号的文件内容。\r\n\r\n194. **nmeter**:网络带宽监控工具。\r\n\r\n195. **nohup**:在后台运行命令并忽略挂起信号。\r\n\r\n196. **nologin**:禁止用户登录。\r\n\r\n197. **nsenter**:进入其他命名空间。\r\n\r\n198. **nslookup**:查询 DNS 信息。\r\n\r\n199. **nuke**:终止所有与特定进程相关的网络连接。\r\n\r\n200. **od**:以不同格式显示文件内容(如十六进制)。\r\n\r\n201. **openvt**:在指定的虚拟终端上运行命令。\r\n\r\n202. **partprobe**:通知操作系统重新读取分区表。\r\n\r\n203. **paste**:合并多个文件按列显示。\r\n\r\n204. **patch**:应用补丁文件。\r\n\r\n205. **pgrep**:查找匹配指定模式的进程。\r\n\r\n206. **pidof**:查找指定进程的 PID。\r\n\r\n207. **ping**:向网络主机发送 ICMP 请求。\r\n\r\n208. **ping6**:向网络主机发送 ICMPv6 请求。\r\n\r\n209. **pipe_progress**:显示管道中的数据传输进度。\r\n\r\n210. **pivot_root**:更改文件系统根目录。\r\n\r\n211. **pkill**:根据进程名终止进程。\r\n\r\n212. **pmap**:显示进程的内存映射。\r\n\r\n213. **popmaildir**:从邮件目录中获取邮件。\r\n\r\n214. **poweroff**:关闭计算机。\r\n\r\n215. **powertop**:用于优化电源管理的工具。\r\n\r\n216. **printenv**:显示所有环境变量。\r\n\r\n217. **printf**:格式化并输出文本。\r\n\r\n218. **ps**:显示当前进程信息。\r\n\r\n219. **pscan**:扫描当前进程的状态。\r\n\r\n220. **pstree**:以树形结构显示进程。\r\n\r\n221. **pwd**:显示当前工作目录。\r\n\r\n222. **pwdx**:显示指定进程的工作目录。\r\n\r\n223. **raidautorun**:自动启动 RAID 配置。\r\n\r\n224. **rdate**:同步时间。\r\n\r\n225. **rdev**:显示或设置设备的特殊属性。\r\n\r\n226. **readlink**:显示符号链接的目标。\r\n\r\n227. **readprofile**:读取并显示应用的性能配置。\r\n\r\n228. **realpath**:返回文件的绝对路径。\r\n\r\n229. **reboot**:重启系统。\r\n\r\n230. **reformime**:转换 MIME 格式。\r\n\r\n231. **renice**:改变进程的优先级。\r\n\r\n232. **reset**:重置终端。\r\n\r\n233. **resize**:调整终端大小。\r\n\r\n234. **resume**:恢复挂起的进程。\r\n\r\n235. **rev**:反转每行文本。\r\n\r\n236. **rfkill**:管理无线设备的开关。\r\n\r\n237. **rm**:删除文件。\r\n\r\n238. **rmdir**:删除空目录。\r\n\r\n239. **rmmod**:卸载内核模块。\r\n\r\n240. **route**:显示或修改路由表。\r\n\r\n241. **rtcwake**:设置系统的 RTC 来定时唤醒。\r\n\r\n242. **run-init**:运行初始化程序。\r\n\r\n243. **run-parts**:按顺序运行目录中的脚本。\r\n\r\n244. **runcon**:设置进程的 SELinux 上下文。\r\n\r\n245. **rx**:接收串口数据。\r\n\r\n246. **script**:记录终端会话。\r\n\r\n247. **scriptreplay**:重放记录的终端会话。\r\n\r\n248. **sed**:流编辑器,用于处理文本数据。\r\n\r\n249. **seedrng**:种子随机数生成器。\r\n\r\n250. **selinuxenabled**:检查 SELinux 是否启用。\r\n\r\n251. **sendmail**:发送电子邮件。\r\n\r\n252. **seq**:生成一个数字序列。\r\n\r\n253. **sestatus**:显示 SELinux 状态。\r\n\r\n254. **setconsole**:设置控制台的终端类型。\r\n\r\n255. **setenforce**:启用或禁用 SELinux 强制模式。\r\n\r\n256. **setfattr**:设置文件的扩展属性。\r\n\r\n257. **setfont**:设置终端的字体。\r\n\r\n258. **setkeycodes**:设置键盘扫描码到键值的映射。\r\n\r\n259. **setlogcons**:设置日志控制台。\r\n\r\n260. **setpriv**:设置进程的特权级别。\r\n\r\n261. **setserial**:设置串口设备的参数。\r\n\r\n262. **setsid**:创建新的会话并运行命令。\r\n\r\n263. **setuidgid**:设置进程的用户和组标识。\r\n\r\n264. **sh**:启动一个新的 shell。\r\n\r\n265. **sha1sum**:计算文件的 SHA-1 校验和。\r\n\r\n266. **sha256sum**:计算文件的 SHA-256 校验和。\r\n\r\n267. **sha3sum**:计算文件的 SHA-3 校验和。\r\n\r\n268. **sha512sum**:计算文件的 SHA-512 校验和。\r\n\r\n269. **showkey**:显示键盘输入的键值。\r\n\r\n270. **shred**:擦除文件,防止数据恢复。\r\n\r\n271. **shuf**:随机排列输入行。\r\n\r\n272. **slattach**:设置串行连接。\r\n\r\n273. **sleep**:暂停一段时间。\r\n\r\n274. **smemcap**:设置进程内存使用限制。\r\n\r\n275. **sort**:按行排序文本文件。\r\n\r\n276. **split**:将文件分割成多个小文件。\r\n\r\n277. **ssl_client**:通过 SSL 连接远程主机。\r\n\r\n278. **start-stop-daemon**:启动或停止后台守护进程。\r\n\r\n279. **stat**:显示文件或文件系统的状态。\r\n\r\n280. **strings**:显示文件中的可打印字符串。\r\n\r\n281. **stty**:设置终端行属性。\r\n\r\n282. **sum**:计算文件的校验和。\r\n\r\n283. **svc**:启动、停止或重启服务。\r\n\r\n284. **svok**:检查服务的状态。\r\n\r\n285. **swapoff**:禁用交换空间。\r\n\r\n286. **swapon**:启用交换空间。\r\n\r\n287. **switch_root**:切换到新的根文件系统。\r\n\r\n288. **sync**:同步文件系统。\r\n\r\n289. **sysctl**:显示或设置内核参数。\r\n\r\n290. **syslogd**:启动系统日志守护进程。\r\n\r\n291. **tac**:反向显示文件内容。\r\n\r\n292. **tail**:显示文件的最后部分。\r\n\r\n293. **tar**:创建和解压 tar 归档。\r\n\r\n294. **tc**:配置网络流量控制。\r\n295. **tcpsvd**:TCP 服务守护进程。\r\n296. **tee**:将输入内容输出到多个文件。\r\n297. **telnet**:远程登录到另一个计算机。\r\n298. **telnetd**:启动 Telnet 服务器。\r\n299. **test**:检查条件的真假。\r\n300. **tftp**:简易的文件传输协议客户端。\r\n301. **tftpd**:TFTP 服务器。\r\n302. **time**:测量命令执行时间。\r\n303. **timeout**:设置命令的超时时间。\r\n304. **top**:显示系统进程信息。\r\n305. **touch**:创建空文件或更新文件的时间戳。\r\n306. **tr**:替换或删除字符。\r\n307. **traceroute**:追踪数据包在网络中的路由。\r\n308. **traceroute6**:追踪 IPv6 数据包的路由。\r\n309. **tree**:以树形结构显示目录内容。\r\n310. **true**:始终返回成功状态。\r\n311. **truncate**:截断文件到指定长度。\r\n312. **ts**:为每行添加时间戳。\r\n313. **tsort**:排序文件中的时间戳。\r\n314. **tty**:显示终端设备名称。\r\n315. **ttysize**:显示终端的大小。\r\n316. **tunctl**:管理 TUN/TAP 网络设备。\r\n317. **tune2fs**:调整 ext2/ext3/ext4 文件系统的参数。\r\n318. **ubiattach**:附加 UBI 设备。\r\n319. **ubidetach**:分离 UBI 设备。\r\n320. **ubimkvol**:创建 UBI 卷。\r\n321. **ubirename**:重命名 UBI 卷。\r\n322. **ubirmvol**:删除 UBI 卷。\r\n323. **ubirsvol**:恢复 UBI 卷。\r\n324. **ubiupdatevol**:更新 UBI 卷的数据。\r\n325. **udhcpc**:DHCP 客户端,用于获取网络配置信息。\r\n326. **udhcpc6**:DHCPv6 客户端。\r\n327. **udhcpd**:DHCP 服务器。\r\n328. **udpsvd**:UDP 服务守护进程。\r\n329. **uevent**:显示系统的 udev 事件。\r\n330. **umount**:卸载文件系统。\r\n331. **uname**:显示系统信息。\r\n332. **uncompress**:解压 `.Z` 格式文件。\r\n333. **unexpand**:将空格转换为制表符。\r\n334. **uniq**:删除重复的行。\r\n335. **unix2dos**:转换 Unix 格式文本为 DOS 格式。\r\n336. **unlink**:删除文件。\r\n337. **unlzma**:解压 `.lzma` 格式文件。\r\n338. **unlzop**:解压 `.lzo` 格式文件。\r\n339. **unshare**:在新命名空间中运行命令。\r\n340. **unxz**:解压 `.xz` 格式文件。\r\n341. **unzip**:解压 `.zip` 文件。\r\n342. **uptime**:显示系统的运行时间和负载。\r\n343. **usleep**:暂停指定的微秒数。\r\n344. **uudecode**:解码 `.uu` 格式文件。\r\n345. **uuencode**:编码文件为 `.uu` 格式。\r\n346. **vconfig**:管理 VLAN 网络接口。\r\n347. **vi**:文本编辑器。\r\n348. **volname**:显示文件系统的卷标。\r\n349. **watch**:定期执行并显示命令输出。\r\n350. **watchdog**:监控系统状态并在需要时重启。\r\n351. **wc**:计算文件的行数、字数和字符数。\r\n352. **wget**:下载文件。\r\n353. **which**:显示可执行文件的路径。\r\n354. **whoami**:显示当前用户的用户名。\r\n355. **whois**:查询域名注册信息。\r\n356. **xargs**:将标准输入转换为命令行参数。\r\n357. **xxd**:创建十六进制转储。\r\n358. **xz**:压缩文件为 `.xz` 格式。\r\n359. **xzcat**:查看 `.xz` 格式文件内容。\r\n360. **yes**:输出指定字符串,通常用来测试管道。\r\n361. **zcat**:查看 `.gz` 格式文件内容。\r\n362. **zcip**:配置 ZCIP 地址。\r\n\r\n这些命令覆盖了文件操作、系统管理、网络配置、进程管理等多个方面,是 BusyBox 在资源受限环境中为用户提供常用功能的集合。\r\n",
|
||
"Linux/busybox玩法总结.md": "### 一句命令启动busybox的简单http服务器\r\n\r\n```shell\r\nbusybox httpd -f -p 端口 -h 目录\r\n```\r\n\r\n### 使用 `busybox netstat` 查看端口占用情况\r\n\r\n- `-t`:显示 TCP 连接\r\n- `-u`:显示 UDP 连接\r\n- `-l`:只显示正在监听的端口\r\n- `-n`:显示数字形式的地址和端口号,而不进行域名解析\r\n\r\n```shell\r\nbusybox netstat -tuln\r\n```\r\n\r\n### 启动busybox的ftp服务器\r\n\r\n```shell\r\nbusybox ftp -d 目录 -p 端口\r\nbusybox ftp -d 目录 #默认占用21端口\r\n\r\nsudo mkdir -p 目录\r\nsudo chmod 755 目录\r\n\r\n```\r\n\r\n### 启动 `busybox` 的 Telnet 服务器(不安全的ssh)\r\n\r\n```\r\nbusybox telnetd -l /bin/login\r\nbusybox telnetd -p 2323 -l /bin/login\r\n\r\n```\r\n\r\n",
|
||
"Linux/crontab的使用.md": "`crontab` 是一个用于在 Unix 和类 Unix 系统(如 Linux)中设置定时任务的工具。它允许用户根据指定的时间间隔安排脚本或命令的执行。以下是关于 `crontab` 使用方法的详细介绍和示例。\r\n\r\n### 基本概念\r\n`crontab` 的配置文件由一系列行组成,每行代表一个定时任务,其基本格式如下:\r\n```plaintext\r\n* * * * * command\r\n```\r\n这五个 `*` 分别代表分钟(0 - 59)、小时(0 - 23)、日期(1 - 31)、月份(1 - 12)和星期(0 - 7,其中 0 和 7 都代表星期日),`command` 是要执行的命令或脚本。\r\n\r\n### 使用步骤\r\n\r\n#### 1. 编辑 `crontab` 文件\r\n可以使用以下命令编辑当前用户的 `crontab` 文件:\r\n```bash\r\ncrontab -e\r\n```\r\n首次使用时,系统会提示选择一个文本编辑器,选择你熟悉的编辑器(如 `nano` 或 `vim`)即可。\r\n\r\n#### 2. 添加定时任务\r\n在打开的 `crontab` 文件中添加定时任务,下面是一些具体的示例:\r\n\r\n##### 示例 1:每分钟执行一次命令\r\n```plaintext\r\n* * * * * /usr/bin/echo \"This is a test\" >> /tmp/test.log\r\n```\r\n这个任务会每分钟执行一次,将 `\"This is a test\"` 追加到 `/tmp/test.log` 文件中。\r\n\r\n##### 示例 2:每小时的第 30 分钟执行一次命令\r\n```plaintext\r\n30 * * * * /usr/bin/backup_script.sh\r\n```\r\n这个任务会在每小时的第 30 分钟执行 `/usr/bin/backup_script.sh` 脚本。\r\n\r\n##### 示例 3:每天凌晨 2 点执行一次命令\r\n```plaintext\r\n0 2 * * * /usr/bin/daily_cleanup.sh\r\n```\r\n这个任务会在每天凌晨 2 点执行 `/usr/bin/daily_cleanup.sh` 脚本。\r\n\r\n##### 示例 4:每月 1 号的 3 点 15 分执行一次命令\r\n```plaintext\r\n15 3 1 * * /usr/bin/monthly_report.sh\r\n```\r\n这个任务会在每月 1 号的 3 点 15 分执行 `/usr/bin/monthly_report.sh` 脚本。\r\n\r\n##### 示例 5:每周日的 18 点执行一次命令\r\n```plaintext\r\n0 18 * * 0 /usr/bin/weekly_backup.sh\r\n```\r\n这个任务会在每周日的 18 点执行 `/usr/bin/weekly_backup.sh` 脚本。\r\n\r\n##### 示例 6:指定时间范围执行命令\r\n```plaintext\r\n0 9-17 * * 1-5 /usr/bin/workday_check.sh\r\n```\r\n这个任务会在周一至周五的 9 点到 17 点之间,每小时的整点执行 `/usr/bin/workday_check.sh` 脚本。\r\n\r\n##### 示例 7:每隔一段时间执行命令\r\n```plaintext\r\n*/15 * * * * /usr/bin/check_status.sh\r\n```\r\n这个任务会每隔 15 分钟执行一次 `/usr/bin/check_status.sh` 脚本。\r\n\r\n#### 3. 保存并退出\r\n编辑完成后,保存并退出文本编辑器。如果使用 `nano` 编辑器,按 `Ctrl + X`,然后按 `Y` 确认保存,最后按 `Enter` 键退出。如果使用 `vim` 编辑器,按 `Esc` 键,输入 `:wq` 并按 `Enter` 键保存并退出。\r\n\r\n#### 4. 查看 `crontab` 文件内容\r\n可以使用以下命令查看当前用户的 `crontab` 文件内容:\r\n```bash\r\ncrontab -l\r\n```\r\n\r\n#### 5. 删除 `crontab` 文件\r\n如果需要删除当前用户的所有定时任务,可以使用以下命令:\r\n```bash\r\ncrontab -r\r\n```\r\n\r\n### 注意事项\r\n- **环境变量**:`crontab` 任务在执行时使用的环境变量可能与用户登录时不同。如果脚本依赖特定的环境变量,需要在脚本中明确设置。\r\n- **日志记录**:建议将定时任务的输出重定向到日志文件,以便后续排查问题。\r\n- **权限问题**:确保执行的命令或脚本具有足够的权限。\r\n",
|
||
"Linux/docker,LXC,qemu,k8s,chroot等的特点.md": "\r\n以下从技术定义、核心原理、特点、区别及相互关系等方面,详细解析 **LXC、Docker、chroot、虚拟机、QEMU、K8s** 的概念及关联:\r\n\r\n\r\n### **一、核心技术定义与原理**\r\n#### 1. **chroot**\r\n- **本质**:Linux 系统调用,用于修改进程的“根目录”(`/`),创建一个隔离的文件系统视图。\r\n- **原理**:通过 `chroot` 命令,指定一个新的根目录,进程只能访问该目录下的文件(类似“伪根”),但不隔离 CPU、内存、网络等资源。\r\n- **特点**:\r\n - 最轻量的隔离,仅文件系统隔离,无资源限制。\r\n - 进程仍共享宿主机内核、进程空间、网络栈等。\r\n - 非完整容器,常用于调试、环境隔离(如构建跨平台程序)。\r\n\r\n#### 2. **LXC(Linux Containers)**\r\n- **本质**:基于 Linux 内核特性(`namespace` 命名空间 + `cgroups` 资源控制)的操作系统级容器。\r\n- **原理**:\r\n - `namespace`:隔离进程、网络、文件系统、用户等资源(如 `PID namespace` 使容器内进程号独立)。\r\n - `cgroups`:限制容器的 CPU、内存、磁盘 I/O 资源使用。\r\n- **特点**:\r\n - 共享宿主机内核,启动快(秒级),资源占用低。\r\n - 提供接近虚拟机的隔离性,但轻量高效。\r\n - 需要手动配置,侧重系统级隔离(如运行完整的 Linux 发行版)。\r\n\r\n#### 3. **Docker**\r\n- **本质**:基于容器技术的应用打包与部署平台,核心是容器运行时(`runc`,基于 Open Container Initiative 标准)。\r\n- **原理**:\r\n - 继承 LXC 的 `namespace` 和 `cgroups`,但更上层,封装了镜像(`Image`)、容器(`Container`)、仓库(`Registry`)流程。\r\n - 通过镜像分层技术(UnionFS)实现快速打包,通过 `Docker Engine` 管理容器生命周期。\r\n- **特点**:\r\n - 聚焦“应用容器化”,强调“一次构建,到处运行”。\r\n - 比 LXC 更易用(标准化 API、自动化部署),适合微服务、CI/CD。\r\n - 镜像生态丰富(Docker Hub),但隔离性略弱于 LXC(共享内核,依赖宿主机内核版本)。\r\n\r\n#### 4. **虚拟机(Virtual Machine, VM)**\r\n- **本质**:通过虚拟化技术模拟完整硬件环境,运行独立操作系统。\r\n- **分类与原理**:\r\n - **全虚拟化**(如 VMware Workstation):Hypervisor 完全模拟硬件,Guest OS 无需修改。\r\n - **半虚拟化**(如 Xen):Guest OS 知道自己运行在虚拟机中,通过 Hypercall 与 Hypervisor 交互。\r\n - **硬件辅助虚拟化**(如 Intel VT-x):CPU 直接支持虚拟化,提升性能。\r\n- **特点**:\r\n - 隔离性最强(独立内核、硬件资源),支持不同操作系统(如 Windows 跑在 Linux 宿主机上)。\r\n - 资源开销大(需模拟硬件,启动慢,内存/CPU 占用高)。\r\n - 适合需要完整 OS 环境的场景(如测试不同系统、遗留应用迁移)。\r\n\r\n#### 5. **QEMU**\r\n- **本质**:开源的通用模拟器和虚拟机监视器(Virtual Machine Monitor, VMM)。\r\n- **原理**:\r\n - 单独使用时,通过软件模拟目标硬件(如在 x86 上运行 ARM 程序),性能较低。\r\n - 与 **KVM**(Kernel-based Virtual Machine,Linux 内核模块)结合时,利用硬件虚拟化技术(如 VT-x),成为高效的虚拟机引擎(QEMU-KVM)。\r\n- **特点**:\r\n - 跨平台兼容性强,支持多种架构(x86、ARM、RISC-V 等)。\r\n - 是虚拟机技术的具体实现之一,常作为 KVM 的用户空间工具。\r\n\r\n#### 6. **K8s(Kubernetes)**\r\n- **本质**:容器编排平台,用于自动化部署、扩展和管理容器化应用。\r\n- **核心功能**:\r\n - 调度容器到节点(Node),支持负载均衡、服务发现。\r\n - 处理容器的生命周期(重启、扩缩容、滚动更新)。\r\n - 提供资源配额、健康检查、故障恢复等机制。\r\n- **特点**:\r\n - 不绑定特定容器运行时(支持 Docker、containerd、runc 等)。\r\n - 解决“大规模容器集群管理”问题,适合微服务架构、云原生应用。\r\n\r\n\r\n### **二、核心区别对比**\r\n| **维度** | **chroot** | **LXC/Docker(容器)** | **虚拟机(含 QEMU-KVM)** | **K8s** |\r\n|-------------------|------------------|------------------------|---------------------------|------------------------|\r\n| **隔离级别** | 文件系统隔离 | 操作系统级隔离(内核共享) | 硬件级隔离(独立内核) | 编排管理层(不涉及底层隔离) |\r\n| **资源共享** | 完全共享 | 共享宿主机内核 | 独立内核,硬件资源模拟 | 管理多个容器/节点的资源 |\r\n| **启动时间** | 瞬间 | 秒级 | 分钟级(需启动 Guest OS) | 不涉及启动,管理已有容器 |\r\n| **资源开销** | 极低 | 低(仅用户空间隔离) | 高(硬件模拟 + 完整 OS) | 额外控制平面开销 |\r\n| **支持的 OS** | 同宿主机内核 | 同宿主机内核 | 任意 OS(如 Windows/Linux) | 不限制,管理容器化应用 |\r\n| **核心目标** | 文件系统隔离 | 轻量应用隔离/部署 | 完整 OS 环境模拟 | 容器集群管理 |\r\n| **典型用途** | 环境调试 | 应用打包、轻量部署 | 多系统测试、遗留应用兼容 | 大规模容器调度、微服务 |\r\n\r\n\r\n### **三、相互关系**\r\n#### 1. **技术栈分层**\r\n```\r\n应用层(K8s)\r\n├─ 容器运行时(Docker/LXC/containerd)\r\n│ ├─ 内核特性(namespace/cgroups)\r\n│ └─ chroot(基础文件系统隔离)\r\n└─ 虚拟化层(虚拟机/QEMU-KVM)\r\n └─ 硬件(CPU/内存/存储,支持 VT-x 等虚拟化技术)\r\n```\r\n\r\n#### 2. **具体关联**\r\n- **chroot 与容器**: \r\n chroot 是容器实现文件系统隔离的基础(如 Docker 镜像的根文件系统通过 chroot 挂载),但容器在此之上增加了 `namespace` 和 `cgroups` 实现完整隔离。\r\n\r\n- **LXC 与 Docker**: \r\n Docker 早期基于 LXC 开发,后转向自有运行时(`libcontainer`,现 `runc`),二者同属容器技术,但定位不同: \r\n - LXC 偏向“系统级容器”(运行完整 Linux 发行版,如 Ubuntu 容器); \r\n - Docker 偏向“应用级容器”(打包单个应用及其依赖,如 Node.js 服务)。\r\n\r\n- **虚拟机与 QEMU**: \r\n QEMU 是虚拟机的一种实现方式,单独使用时模拟硬件(慢),与 KVM 结合时利用硬件虚拟化(高效),属于虚拟机技术的底层引擎之一(类似 VirtualBox、VMware 的技术定位)。\r\n\r\n- **K8s 与容器/虚拟机**: \r\n - K8s 主要管理容器(如 Docker 容器),但也可通过虚拟机节点(Node)部署(每个 Node 可以是物理机或虚拟机)。 \r\n - 容器运行在宿主机(物理机或虚拟机)上,K8s 不关心底层是物理机还是虚拟机,只调度容器到节点。\r\n\r\n\r\n### **四、应用场景总结**\r\n- **chroot**:简单文件系统隔离(如构建跨版本软件、修复系统)。 \r\n- **Docker/LXC**:轻量应用部署(微服务、Web 服务),追求资源效率和快速启动。 \r\n- **虚拟机/QEMU-KVM**:需要完整 OS 隔离(如运行 Windows 应用、多租户隔离、硬件兼容性测试)。 \r\n- **K8s**:大规模容器集群管理(微服务架构、弹性扩缩容、高可用部署)。\r\n\r\n\r\n### **五、核心总结**\r\n- **隔离性**:虚拟机(强隔离,独立内核)> 容器(共享内核,OS 级隔离)> chroot(仅文件系统)。 \r\n- **效率**:chroot/容器(高效)> 虚拟机(低效,因硬件模拟)。 \r\n- **关系**: \r\n - 容器技术(LXC/Docker)基于内核特性(namespace/cgroups),chroot 是其文件系统隔离的基础。 \r\n - 虚拟机(如 QEMU-KVM)通过硬件虚拟化实现强隔离,与容器形成互补(容器适合同一 OS 下的应用隔离,虚拟机适合跨 OS 隔离)。 \r\n - K8s 是容器的“上层管理工具”,不依赖特定容器运行时,聚焦集群调度与自动化。\r\n\r\n理解这些技术的核心是明确其“隔离目标”和“资源模型”:容器追求轻量高效,虚拟机追求强隔离,K8s 解决规模化管理问题,而 chroot 是最基础的工具。根据需求选择合适的技术(如部署单个应用用 Docker,多 OS 环境用虚拟机,大规模集群用 K8s 编排容器)。",
|
||
"Linux/docker配置.md": "QQ机器人(napcat)\r\ndocker run -d \\\r\n-e NAPCAT_GID=$(id -g) \\\r\n-e NAPCAT_UID=$(id -u) \\\r\n-p 3000:3000 \\\r\n-p 3001:3001 \\\r\n-p 3002:6099 \\\r\n--name napcat \\\r\n--restart=always \\\r\nmlikiowa/napcat-docker:latest\r\n\r\n微信机器人(gewe)\r\ndocker run -itd -v /shumengya/bin/wechatbot:/root/temp -p 2531:2531 -p 2532:2532 --privileged=true --name=gewe gewe /usr/sbin/init\r\n\r\n\r\n\r\n",
|
||
"Linux/frp配置.md": "### 使用 yum 安装 systemd(CentOS/RHEL)\r\n```\r\nyum install systemd\r\n```\r\n\r\n\r\n\r\n### 使用 apt 安装 systemd(Debian/Ubuntu)\r\n```\r\napt install systemd\r\nsudo vim /etc/systemd/system/frps.service\r\n```\r\n\r\n\r\n\r\n### 服务名称,可自定义\r\n```\r\nDescription = frp server\r\nAfter = network.target syslog.target\r\nWants = network.target\r\n\r\n[Service]\r\nType = simple\r\n```\r\n\r\n\r\n### 启动frps的命令,需修改为您的frps的安装路径\r\n```\r\nExecStart = /path/to/frps -c /path/to/frps.toml\r\n\r\n[Install]\r\nWantedBy = multi-user.target\r\n```\r\n\r\n\r\n\r\n### 启动frp\r\n```\r\nsudo systemctl start frps\r\n```\r\n\r\n\r\n### 停止frp\r\n```\r\nsudo systemctl stop frps\r\n```\r\n\r\n\r\n### 重启frp\r\n```\r\nsudo systemctl restart frps\r\n```\r\n\r\n\r\n### 查看frp状态\r\n```\r\nsudo systemctl status frps\r\nsudo systemctl enable frps\r\n```\r\n\r\n",
|
||
"Linux/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",
|
||
"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安装nodejs22.md": "apt install curl\n\n# Download and install nvm:\ncurl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash\n\n# in lieu of restarting the shell\n\\. \"$HOME/.nvm/nvm.sh\"\n\n# Download and install Node.js:\nnvm install 22\n\n# Verify the Node.js version:\nnode -v # Should print \"v22.19.0\".\n\n# Verify npm version:\nnpm -v # Should print \"10.9.3\".\n\n",
|
||
"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/nodejsmarkdown库.md": "1. **markdown-it**:\r\n \r\n - **简介**: 一个功能强大且可扩展的 Markdown 解析器,支持插件和自定义规则。\r\n - **安装**: 可以通过 npm 安装:`npm install markdown-it`\r\n - **使用示例**:\r\n ```javascript\r\n const MarkdownIt = require('markdown-it');\r\n const md = new MarkdownIt();\r\n const result = md.render('# 你好,Markdown!');\r\n console.log(result);\r\n ```\r\n \r\n2. **marked**:\r\n - **简介**: 一个快速、轻量级的 Markdown 解析器,支持自定义渲染器。\r\n - **安装**: 使用 npm 安装:`npm install marked`\r\n - **使用示例**:\r\n ```javascript\r\n const marked = require('marked');\r\n const result = marked('# 你好,Markdown!');\r\n console.log(result);\r\n ```\r\n\r\n3. **remark**:\r\n - **简介**: 一个强大的 Markdown 处理库,支持解析、检查和转换 Markdown 文档。\r\n - **安装**: 通过 npm 安装:`npm install remark remark-html`\r\n - **使用示例**:\r\n ```javascript\r\n const remark = require('remark');\r\n const html = require('remark-html');\r\n \r\n remark()\r\n .use(html)\r\n .process('# 你好,Markdown!', function (err, file) {\r\n if (err) throw err;\r\n console.log(String(file));\r\n });\r\n ```\r\n\r\n这些库各有优点,选择哪个库取决于您的具体需求,比如性能、可扩展性、支持的特性等。如果你需要简单的解析和渲染,`marked` 和 `markdown-it` 都是不错的选择;如果需要更多的可扩展性和插件支持,`remark` 可能更适合。",
|
||
"Linux/QQ机器人napcat命令.md": "输入 xvfb-run -a qq --no-sandbox 命令启动。 \r\n保持后台运行 请输入 screen -dmS napcat bash -c \"xvfb-run -a qq --no-sandbox\" \r\n后台快速登录 请输入 screen -dmS napcat bash -c \"xvfb-run -a qq --no-sandbox -q QQ号码\" \r\nNapcat安装位置 /opt/QQ/resources/app/app_launcher/napcat \r\nWEBUI_TOKEN 请自行查看/opt/QQ/resources/app/app_launcher/napcat/config/webui.json文件获取 \r\n注意, 您可以随时使用 screen -r napcat 来进入后台进程并使用 ctrl + a + d 离开(离开不会关闭后台进程)。 \r\n停止后台运行 \r\n\r\n screen -S napcat -X quit ",
|
||
"Linux/screen常用指令.md": "## `screen`命令简介\r\n\r\n`screen` 是一个窗口管理器,允许用户在一个单一的终端窗口中运行多个会话。它特别适用于需要长时间运行的进程,因为即使网络连接断开,进程也会继续运行。\r\n\r\n## 常用命令\r\n\r\n### 启动和使用\r\n\r\n- **启动一个新的screen会话**\r\n ```bash\r\n screen\r\n ```\r\n 或者为会话命名:\r\n ```bash\r\n screen -S session_name\r\n ```\r\n\r\n- **列出所有screen会话**\r\n ```bash\r\n screen -ls\r\n ```\r\n\r\n- **重新连接到一个已存在的screen会话**\r\n ```bash\r\n screen -r session_name\r\n ```\r\n\r\n- **分离当前会话(让会话在后台继续运行)**\r\n 按下 `Ctrl + A` 然后按 `D`。\r\n\r\n- **终止一个screen会话**\r\n 在会话中按下 `Ctrl + D` 或者输入 `exit`。\r\n\r\n### 会话管理\r\n\r\n- **强制连接到一个会话**\r\n 如果有多个会话在运行,使用:\r\n ```bash\r\n screen -r -d session_name\r\n ```\r\n 这将断开该会话的其他连接并连接到它。\r\n\r\n- **多窗口管理**\r\n - 创建新窗口:`Ctrl + A` 然后 `C`\r\n - 切换窗口:`Ctrl + A` 然后 `N`(下一个),`Ctrl + A` 然后 `P`(上一个)\r\n - 列出所有窗口:`Ctrl + A` 然后 `\"`(双引号)\r\n\r\n### 会话命名\r\n\r\n- **重命名当前窗口**\r\n 按下 `Ctrl + A` 然后 `A`,输入新的名称。\r\n\r\n## 配置文件\r\n\r\n- **自定义screen**\r\n 可以通过编辑 `~/.screenrc` 文件进行配置。例如:\r\n ```bash\r\n # 开启多窗口状态栏\r\n hardstatus on\r\n hardstatus alwayslastline\r\n hardstatus string \"%{= kG}%-Lw%{= BW}%50>%n%f* %t%{-}%+Lw%<\"\r\n ```\r\n\r\n## 提示\r\n\r\n- 使用 `screen` 可以有效防止因网络不稳定导致的会话中断。\r\n- 熟练掌握快捷键可以大大提高效率。\r\n- 对于需要长期运行的任务,如编译或数据处理,`screen` 是一个非常有用的工具。\r\n\r\n",
|
||
"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### 总结\n\n正确配置 SSH 服务端对于保障服务器的安全至关重要。请根据您的具体需求和环境,结合上述指南进行配置。同时,定期审查和更新配置,以应对潜在的安全威胁。",
|
||
"Linux/systemctl命令详细总结-豆包.md": "\r\n### Linux `systemctl` 命令常用用法总结\r\n\r\n\r\n#### **一、服务管理(核心功能)**\r\n`systemctl` 主要用于管理系统服务(`.service` 文件),支持启动、停止、重启、查看状态、设置开机启动等操作。\r\n\r\n##### 1. 服务状态操作\r\n| 操作 | 命令 | 说明 |\r\n|---------------------|---------------------------------------|----------------------------------------------------------------------|\r\n| 启动服务 | `systemctl start <服务名>` | 启动指定服务(仅临时生效,重启后不保留) |\r\n| 停止服务 | `systemctl stop <服务名>` | 停止指定服务 |\r\n| 重启服务 | `systemctl restart <服务名>` | 重启服务(若服务未运行则启动) |\r\n| 重新加载配置 | `systemctl reload <服务名>` | 重新加载服务配置文件(不重启服务,适用于支持此功能的服务,如 Nginx) |\r\n| 平滑重启(优雅重启)| `systemctl try-restart <服务名>` | 仅在服务运行时重启,避免报错 |\r\n\r\n##### 2. 服务状态查询\r\n| 操作 | 命令 | 说明 |\r\n|---------------------|---------------------------------------|----------------------------------------------------------------------|\r\n| 查看状态 | `systemctl status <服务名>` | 显示服务运行状态、日志及依赖关系(按 `Q` 退出) |\r\n| 简洁状态 | `systemctl is-active <服务名>` | 仅显示服务是否激活(active/running) |\r\n| 查看是否启用开机启动| `systemctl is-enabled <服务名>` | 显示服务是否设置为开机启动(enabled/disabled) |\r\n| 列出所有服务 | `systemctl list-units --type=service` | 列出所有运行中的服务 |\r\n| 列出所有服务(含未激活)| `systemctl list-units --type=service --all` | 显示所有服务,包括未激活的(状态为 inactive/failed 等) |\r\n| 列出失败的服务 | `systemctl --failed --type=service` | 查看启动失败的服务 |\r\n\r\n##### 3. 开机启动管理\r\n| 操作 | 命令 | 说明 |\r\n|---------------------|---------------------------------------|----------------------------------------------------------------------|\r\n| 启用开机启动 | `systemctl enable <服务名>` | 设置服务开机自动启动(永久生效,关联到默认运行目标) |\r\n| 禁用开机启动 | `systemctl disable <服务名>` | 取消服务开机启动 |\r\n| 临时启用(仅本次启动)| `systemctl enable --now <服务名>` | 立即启动服务并设置开机启动 |\r\n| 临时禁用(停止并取消启动)| `systemctl disable --now <服务名>` | 立即停止服务并取消开机启动 |\r\n\r\n##### 4. 服务依赖与依赖关系\r\n| 操作 | 命令 | 说明 |\r\n|---------------------|---------------------------------------|----------------------------------------------------------------------|\r\n| 查看依赖关系 | `systemctl list-dependencies <服务名>` | 显示服务的依赖项(依赖它的服务 + 它依赖的服务) |\r\n| 查看直接依赖 | `systemctl list-dependencies --reverse <服务名>` | 仅显示依赖该服务的其他服务 |\r\n\r\n\r\n#### **二、系统状态与控制**\r\n##### 1. 系统基本状态\r\n| 操作 | 命令 | 说明 |\r\n|---------------------|---------------------------------------|----------------------------------------------------------------------|\r\n| 查看系统运行时间 | `systemctl uptime` | 显示系统已运行时间(类似 `uptime` 命令) |\r\n| 查看启动耗时 | `systemctl time` | 显示系统启动总耗时及各阶段(内核、用户空间、服务)耗时 |\r\n| 查看登录会话 | `systemctl list-sessions` | 列出当前登录的用户会话 |\r\n\r\n##### 2. 电源管理(需管理员权限)\r\n| 操作 | 命令 | 说明 |\r\n|---------------------|---------------------------------------|----------------------------------------------------------------------|\r\n| 关机 | `systemctl poweroff` | 立即关机 |\r\n| 重启 | `systemctl reboot` | 立即重启 |\r\n| 休眠(挂起到硬盘) | `systemctl hibernate` | 系统进入休眠状态 |\r\n| 睡眠(挂起到内存) | `systemctl suspend` | 系统进入睡眠状态(低功耗,断电数据丢失) |\r\n| 混合休眠 | `systemctl hybrid-sleep` | 同时休眠到内存和硬盘,结合两者优势 |\r\n| 取消挂起/休眠 | `systemctl wakeup` | 唤醒系统(需配合定时器使用) |\r\n\r\n##### 3. 运行目标(替代传统运行级别)\r\n| 操作 | 命令 | 说明 |\r\n|---------------------|---------------------------------------|----------------------------------------------------------------------|\r\n| 查看当前目标 | `systemctl get-default` | 显示默认运行目标(如 `graphical.target` 对应图形界面) |\r\n| 切换目标 | `systemctl isolate <目标名>` | 切换到指定目标(如 `multi-user.target` 为无图形多用户模式) |\r\n| 设置默认目标 | `systemctl set-default <目标名>` | 设置开机默认目标(需管理员权限) |\r\n\r\n**常用目标对应关系**: \r\n- `graphical.target`:图形界面(对应传统运行级别 5) \r\n- `multi-user.target`:无图形多用户模式(对应级别 3) \r\n- `rescue.target`:单用户救援模式(对应级别 1) \r\n- `emergency.target`:紧急模式(无文件系统挂载,仅基本命令) \r\n\r\n\r\n#### **三、定时器管理(systemd.timer)**\r\n`systemctl` 可管理定时任务(替代传统 `cron`),需配合 `.timer` 文件使用。\r\n\r\n| 操作 | 命令 | 说明 |\r\n|---------------------|---------------------------------------|----------------------------------------------------------------------|\r\n| 列出所有定时器 | `systemctl list-timers` | 显示激活的定时器及其下一次触发时间 |\r\n| 查看定时器状态 | `systemctl status <定时器名>` | 显示定时器详细状态及日志 |\r\n| 启用/禁用定时器 | `systemctl enable/disable <定时器名>` | 控制定时器是否开机启动 |\r\n| 立即触发定时器任务 | `systemctl start <定时器名>` | 强制立即执行定时器关联的服务 |\r\n\r\n\r\n#### **四、资源控制与限制(高级功能)**\r\n可对服务设置 CPU、内存、IO 等资源限制(需在服务文件中配置,或临时生效)。\r\n\r\n| 操作 | 命令 | 说明 |\r\n|---------------------|---------------------------------------|----------------------------------------------------------------------|\r\n| 设置 CPU 核心限制 | `systemctl set-property <服务名> CPUAffinity=0,1` | 限制服务仅运行在 CPU 0 和 1 核心 |\r\n| 设置内存上限 | `systemctl set-property <服务名> MemoryMax=1G` | 限制服务最大内存使用量为 1GB |\r\n| 恢复默认资源配置 | `systemctl unset-property <服务名> CPUAffinity MemoryMax` | 清除已设置的资源限制 |\r\n\r\n\r\n#### **五、日志相关(结合 journalctl)**\r\n| 操作 | 命令 | 说明 |\r\n|---------------------|---------------------------------------|----------------------------------------------------------------------|\r\n| 查看服务日志 | `systemctl status <服务名> -l` | 显示服务状态并附带日志(`-l` 展开完整日志) |\r\n| 实时监控日志 | `journalctl -u <服务名> -f` | 实时追踪服务日志(需结合 `journalctl` 命令) |\r\n| 查看历史日志 | `journalctl -u <服务名> --since \"2025-05-01\"` | 查看指定时间后的服务日志 |\r\n\r\n\r\n#### **六、常用选项与技巧**\r\n- **通配符匹配**: \r\n 可使用通配符管理同类服务,例如: \r\n ```bash\r\n systemctl start nginx*.service # 启动所有以 nginx 开头的服务\r\n systemctl stop *.timer # 停止所有定时器服务\r\n ```\r\n\r\n- **强制操作**: \r\n `--force` 用于强制停止/重启服务(可能终止进程): \r\n ```bash\r\n systemctl --force stop <服务名>\r\n ```\r\n\r\n- **临时生效(不修改配置)**: \r\n 使用 `--now` 可立即执行操作并关联开机启动(或取消): \r\n ```bash\r\n systemctl enable --now <服务名> # 启动并启用开机启动\r\n systemctl disable --now <服务名> # 停止并禁用开机启动\r\n ```\r\n\r\n- **查看帮助**: \r\n ```bash\r\n systemctl --help # 查看全局帮助\r\n systemctl help <子命令> # 查看子命令详细用法(如 systemctl help start)\r\n ```\r\n\r\n\r\n#### **七、示例场景**\r\n1. **管理 Nginx 服务**: \r\n ```bash\r\n systemctl start nginx # 启动 Nginx\r\n systemctl enable nginx # 设置开机启动\r\n systemctl status nginx # 查看运行状态\r\n systemctl reload nginx # 重新加载配置\r\n ```\r\n\r\n2. **系统关机与重启**: \r\n ```bash\r\n systemctl reboot # 立即重启\r\n systemctl poweroff # 立即关机\r\n systemctl suspend # 进入睡眠\r\n ```\r\n\r\n3. **设置默认运行目标**: \r\n ```bash\r\n systemctl set-default multi-user.target # 设为无图形多用户模式\r\n systemctl isolate rescue.target # 进入单用户救援模式\r\n ```\r\n\r\n\r\n### 总结\r\n`systemctl` 是 systemd 生态的核心工具,覆盖服务管理、系统控制、定时任务、资源限制等功能。熟练掌握其常用命令可高效管理 Linux 系统服务与状态,替代传统 SysVinit 的 `service`、`chkconfig` 等工具。建议结合 `journalctl` 分析服务日志,通过服务文件(`/etc/systemd/system/`)自定义复杂配置。`systemctl` 是 Linux 系统中用于控制 `systemd` 系统和服务管理器的命令。以下是 `systemctl` 命令的一些常用用法总结:\r\n\r\n### 1. 服务管理\r\n#### 启动服务\r\n```bash\r\nsystemctl start <服务名>\r\n```\r\n例如,启动 `httpd` 服务:\r\n```bash\r\nsystemctl start httpd\r\n```\r\n\r\n#### 停止服务\r\n```bash\r\nsystemctl stop <服务名>\r\n```\r\n例如,停止 `httpd` 服务:\r\n```bash\r\nsystemctl stop httpd\r\n```\r\n\r\n#### 重启服务\r\n```bash\r\nsystemctl restart <服务名>\r\n```\r\n例如,重启 `httpd` 服务:\r\n```bash\r\nsystemctl restart httpd\r\n```\r\n\r\n#### 重新加载服务配置\r\n```bash\r\nsystemctl reload <服务名>\r\n```\r\n例如,重新加载 `nginx` 服务配置:\r\n```bash\r\nsystemctl reload nginx\r\n```\r\n\r\n#### 查看服务状态\r\n```bash\r\nsystemctl status <服务名>\r\n```\r\n例如,查看 `httpd` 服务状态:\r\n```bash\r\nsystemctl status httpd\r\n```\r\n\r\n### 2. 服务的开机自启管理\r\n#### 设置服务开机自启\r\n```bash\r\nsystemctl enable <服务名>\r\n```\r\n例如,设置 `httpd` 服务开机自启:\r\n```bash\r\nsystemctl enable httpd\r\n```\r\n\r\n#### 禁止服务开机自启\r\n```bash\r\nsystemctl disable <服务名>\r\n```\r\n例如,禁止 `httpd` 服务开机自启:\r\n```bash\r\nsystemctl disable httpd\r\n```\r\n\r\n#### 查看服务是否开机自启\r\n```bash\r\nsystemctl is-enabled <服务名>\r\n```\r\n例如,查看 `httpd` 服务是否开机自启:\r\n```bash\r\nsystemctl is-enabled httpd\r\n```\r\n\r\n### 3. 系统管理\r\n#### 重启系统\r\n```bash\r\nsystemctl reboot\r\n```\r\n\r\n#### 关机\r\n```bash\r\nsystemctl poweroff\r\n```\r\n\r\n#### 挂起系统\r\n```bash\r\nsystemctl suspend\r\n```\r\n\r\n#### 休眠系统\r\n```bash\r\nsystemctl hibernate\r\n```\r\n\r\n#### 混合休眠(挂起并休眠)\r\n```bash\r\nsystemctl hybrid-sleep\r\n```\r\n\r\n### 4. 查看系统状态\r\n#### 查看系统当前运行级别\r\n```bash\r\nsystemctl get-default\r\n```\r\n\r\n#### 设置系统默认运行级别\r\n```bash\r\nsystemctl set-default <目标运行级别>\r\n```\r\n例如,设置系统默认运行级别为多用户模式:\r\n```bash\r\nsystemctl set-default multi-user.target\r\n```\r\n\r\n### 5. 查看服务列表\r\n#### 查看所有已激活的服务\r\n```bash\r\nsystemctl list-units --type=service --state=active\r\n```\r\n\r\n#### 查看所有服务(包括未激活的)\r\n```bash\r\nsystemctl list-units --type=service --all\r\n```\r\n\r\n这些是 `systemctl` 命令的一些常用用法,掌握这些用法可以帮助你有效地管理 Linux 系统中的服务和系统状态。 ",
|
||
"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的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-SSH相关.md": "Termux更改终端密码:\r\n\r\n```\r\npasswd\r\n```\r\n\r\n重启SSH服务\r\n\r\n```\r\npkill sshd \r\nsshd\r\n```\r\n\r\n查看本机IP\r\n\r\n```\r\nifconfig\r\n```\r\n\r\n生成SSH主机密钥\r\n\r\n```\r\nssh-keygen -A\r\n```\r\n\r\n更新Termux包\r\n\r\n```\r\npkg update && pkg upgrade\r\n```\r\n\r\nTermux退出chroot容器\r\n\r\n```\r\nexit\r\n```\r\n\r\nTermux安装软件\r\n\r\n```\r\npkg install \r\n```\r\n\r\n查看终端用户名\r\n\r\n```\r\nwhoami\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妈的旧手机termux终端用户名\r\n\r\nu0_a143\r\n\r\n爸的旧手机termux终端用户名\r\n\r\nu0_a135\r\n\r\nTermux执行sh脚本\r\n\r\n```\r\nbash 脚本名.sh\r\n```\r\n\r\n\r\n\r\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` 路径中**,使其在任何地方都能被执行。常见的目录有:\r\n\r\n### 1. **`/usr/local/bin/`**\r\n这是推荐的目录,因为它是用来放置系统管理员手动安装或编译的软件及脚本的。脚本放在这个目录中,可以确保它对所有用户可用,并且不会与系统自带的命令冲突。\r\n\r\n步骤:\r\n1. 将你的 `.sh` 脚本复制到 `/usr/local/bin/` 目录下。\r\n \r\n ```bash\r\n sudo cp your_script.sh /usr/local/bin/\r\n ```\r\n\r\n2. 赋予脚本执行权限:\r\n\r\n ```bash\r\n sudo chmod +x /usr/local/bin/your_script.sh\r\n ```\r\n\r\n3. 确保脚本能被执行,可以通过命令行直接调用(例如 `your_script.sh`),无需指定路径。\r\n\r\n### 2. **`/usr/bin/`**\r\n这个目录通常用于系统范围内的二进制文件,和 `/usr/local/bin/` 类似。但是,建议将自定义脚本放在 `/usr/local/bin/` 目录下,因为 `/usr/bin/` 通常用于通过包管理器安装的系统级命令。\r\n\r\n步骤:\r\n1. 将脚本复制到 `/usr/bin/` 目录:\r\n\r\n ```bash\r\n sudo cp your_script.sh /usr/bin/\r\n ```\r\n\r\n2. 赋予执行权限:\r\n\r\n ```bash\r\n sudo chmod +x /usr/bin/your_script.sh\r\n ```\r\n\r\n### 3. **`/bin/`**(不推荐)\r\n`/bin/` 目录通常用于存放系统核心命令和工具,普通用户通常不建议将自定义脚本放在这个目录中,除非它们确实是系统必需的命令。通常会将脚本放置在 `/usr/local/bin/` 或 `/usr/bin/` 中。\r\n\r\n### 4. **用户特定的目录(例如 `/home/username/bin/`)**\r\n如果你只想为某个特定用户设置全局脚本,而不是所有用户可以访问的脚本,你可以将脚本放在该用户的 `~/bin/` 目录下(如果该目录不存在,可以自己创建)。确保将 `~/bin/` 添加到用户的 `PATH` 环境变量中。\r\n\r\n步骤:\r\n1. 创建 `~/bin/` 目录(如果没有的话):\r\n\r\n ```bash\r\n mkdir -p ~/bin\r\n ```\r\n\r\n2. 将脚本复制到 `~/bin/` 目录:\r\n\r\n ```bash\r\n cp your_script.sh ~/bin/\r\n ```\r\n\r\n3. 赋予执行权限:\r\n\r\n ```bash\r\n chmod +x ~/bin/your_script.sh\r\n ```\r\n\r\n4. 编辑 `~/.bashrc` 或 `~/.profile`,将 `~/bin/` 添加到 `PATH`:\r\n\r\n ```bash\r\n export PATH=$PATH:~/bin\r\n ```\r\n\r\n5. 使 `~/.bashrc` 变更生效:\r\n\r\n ```bash\r\n source ~/.bashrc\r\n ```\r\n\r\n### 总结\r\n- **最推荐的目录:** `/usr/local/bin/`,适用于系统范围内的自定义脚本。\r\n- **其他可选目录:** `/usr/bin/`(不推荐),如果需要放系统级命令可以选择该目录。\r\n- **特定用户的脚本:** 用户自己的 `~/bin/` 目录。\r\n\r\n将脚本放入上述目录,并设置执行权限后,你就可以在系统中的任何地方执行该脚本了。如果有任何问题,请随时告知!",
|
||
"Linux/手动配置alist.md": "```shell\r\n# 解压下载的文件,得到可执行文件:\r\ntar -zxvf alist-xxxx.tar.gz\r\n# 授予程序执行权限:\r\nchmod +x alist\r\n# 运行程序\r\n./alist server\r\n\r\n# 获得管理员信息 以下两个不同版本,新版本也有随机生成和手动设置\r\n# 低于v3.25.0版本\r\n./alist admin\r\n\r\n# 高于v3.25.0版本\r\n# 随机生成一个密码\r\n./alist admin random\r\n# 手动设置一个密码 `NEW_PASSWORD`是指你需要设置的密码\r\n./alist admin set NEW_PASSWORD\r\n\r\n```\r\n\r\n\r\n\r\n使用任意方式编辑 `/usr/lib/systemd/system/alist.service` 并添加如下内容,其中 path_alist 为 AList 所在的路径\r\n\r\n```shell\r\n[Unit]\r\nDescription=alist\r\nAfter=network.target\r\n \r\n[Service]\r\nType=simple\r\nWorkingDirectory=path_alist\r\nExecStart=path_alist/alist server\r\nRestart=on-failure\r\n \r\n[Install]\r\nWantedBy=multi-user.target\r\n\r\n```\r\n\r\n然后,执行 systemctl daemon-reload 重载配置,现在你可以使用这些命令来管理程序:\r\n**• 启动: systemctl start alist**\r\n**• 关闭: systemctl stop alist**\r\n**• 配置开机自启: systemctl enable alist**\r\n**• 取消开机自启: systemctl disable alist**\r\n**• 状态: systemctl status alist**\r\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完成这些步骤后,你的 Ubuntu 系统应该就会使用阿里云的镜像源了,下载速度会更加快速稳定。\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 && 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 && 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 > RAM block device support (16MB)\r\n# [*] Network device support > Ethernet driver support > 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 && 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 && cd busybox-1.36.1\r\nmake defconfig\r\nmake menuconfig # 选择静态编译:\r\n# Settings -> Build Options -> [*] Build static binary\r\n\r\nmake -j$(nproc) && make install\r\ncd _install\r\n\r\n# 创建必要目录\r\nmkdir -p proc sys dev etc/init.d\r\n\r\n# 创建启动脚本\r\ncat > etc/init.d/rcS <<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 "root=/dev/ram0 console=ttyS0" \\\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 && cd musl-1.2.4\r\n./configure --prefix=/usr/local/musl && make && 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 -> Target Architecture = x86_64\r\n# System configuration -> Root filesystem overlay = ../rootfs\r\n# Kernel -> Linux Kernel = 6.9.8\r\nmake -j$(nrep)\r\n```\r\n\r\n### 系统特性对比\r\n\r\n| 组件 | 手动构建 | Buildroot构建 |\r\n| ------------ | -------- | ------------- |\r\n| 启动时间 | <1s | <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/某安卓板子不知名初始化脚本.md": "adb push busybox /tmp\r\nadb shell\r\ncd /tmp\r\nchmod 777 *\r\n./busybox ifconfig wlan0 up",
|
||
"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\r\n\r\n## ------------------------------------------------------------\r\n\r\n## 10 20 30 40 50 60 70\r\n\r\n## 66 99 88 11 22 33 44 55\r\n\r\n## 110 120 119 \r\n\r\n## 111 222\r\n\r\n## 233\r\n\r\n## ------------------------------------------------------------\r\n\r\n## x86电脑系列\r\n\r\n#### Windows11\r\n\r\n#### Linux Mint\r\n\r\n#### 树萌芽NAS(大萌芽):233\r\n\r\n\r\n\r\n## 安卓手机系列\r\n\r\n#### 红萌芽盘 :222\r\n\r\n#### 黑萌芽盘 :111\r\n\r\n#### 小萌芽盘: \r\n\r\n\r\n\r\n#### vivo平板\r\n\r\n#### OPPO手机\r\n\r\n\r\n\r\n## 随身WiFi系列\r\n\r\n#### UFI1003 \r\n\r\n#### UZ801\r\n\r\n#### UZ901\r\n\r\n#### UFI100C 目前有9个\r\n\r\n### IP:11 - 99\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",
|
||
"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/飞牛os切换root.md": "1.打开飞牛ssh\r\n2.ssh软件连接上飞牛(飞牛账号)\r\n3.给root新建密码:sudo passwd root 回车\r\n再次输入飞牛密码\r\n再输入密码(root密码)两次(不回显,每次输完回车)\r\n4.配置权限文件:sudo nano /etc/ssh/sshd_config 回车\r\n5.光标移动到:permitrootlogin no 把no 改为yes \r\n6.ctrl+o(写入文本)回车 ctrl+x(退出) 重启服务器:sudo reboot\r\n7.重启ssh服务:sudo service sshd restart\r\n8.用命令切换root账号:su -(或者sudo su -)还要输入一次目前飞牛密码回车就切换root了。",
|
||
"Minecraft/Minecraft常用命令.md": "***/kill @e[type=mutant:mskeleton_bones]*** \n清除掉突变骷髅模组的骷髅骨头实体\n\n***/kill @e[type=item]*** \n清除所有掉落物\n\n***/gamerule mobGriefing 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```",
|
||
"嵌入式/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口以上),但需结合外接电源和高效的芯片方案来保证性能。",
|
||
"数据库/json文件储存和MongoDB储存优缺点.md": "游戏玩家数据储存在普通JSON文件和MongoDB中各有其适用场景,二者的优缺点对比可结合游戏数据的特性(如数据量、读写频率、结构灵活性、并发需求等)展开分析:\n \n一、普通JSON文件储存\n \n普通JSON文件储存指将玩家数据以JSON格式写入本地文件(单文件或多文件,如按玩家ID分文件),依赖文件系统直接读写。\n \n优点\n \n1. 简单轻量,开发成本低\n无需部署数据库服务,直接通过编程语言的文件操作API(如Python的 json 模块、Node.js的 fs 模块)即可读写,适合小型团队或开发初期快速验证功能,学习成本几乎为0。\n2. 资源占用少\n仅依赖文件系统,不消耗额外的数据库进程资源(如内存、CPU),适合设备性能有限的场景(如单机小游戏、轻量网页游戏)。\n3. 数据直观可见\nJSON文件为文本格式,可直接用编辑器打开查看或修改,便于开发调试(如临时修改玩家数据测试功能)。\n \n缺点\n \n1. 读写效率低,不适合大数据量\n- 每次读写需加载整个JSON文件到内存解析(或写入时覆盖整个文件),当玩家数据量增大(如10万+玩家),单文件体积膨胀,读写耗时会急剧增加(例如加载100MB的JSON文件可能需要数百毫秒)。\n- 若按玩家ID分文件,虽能缓解单文件压力,但批量查询(如排行榜、全服统计)需遍历所有文件,效率极低。\n2. 并发安全问题突出\n多玩家同时操作时(如多人在线游戏的并发读写),文件系统缺乏原生锁机制,易出现“写覆盖”(如A玩家写入时B玩家同时写入,导致其中一方数据丢失)或数据损坏(如写入中断导致JSON格式错误)。\n3. 结构扩展性差\n若玩家数据结构迭代(如新增“宠物属性”“公会信息”),需手动处理旧JSON文件的格式兼容(如遍历所有文件添加新字段),操作繁琐且易出错。\n4. 缺乏数据一致性保障\n无事务支持,例如玩家“扣金币+加道具”的原子操作,若中途程序崩溃,可能导致金币已扣但道具未加,数据不一致。\n \n二、MongoDB储存\n \nMongoDB是文档型NoSQL数据库,以BSON(JSON的二进制扩展)格式存储数据,天然适配半结构化的玩家数据。\n \n优点\n \n1. 高效读写与查询能力\n- 支持索引(如按玩家ID、等级建索引),可快速定位单玩家数据(毫秒级),解决JSON文件全量解析的性能问题。\n- 支持复杂查询(如“等级>50且在线的玩家”“道具列表包含某物品的玩家”),适合游戏中的排行榜、好友列表、任务统计等场景。\n2. 良好的并发与一致性\n- 内置多版本并发控制(MVCC),支持高并发读写( thousands of TPS),避免JSON文件的并发冲突。\n- 支持事务(MongoDB 4.0+),可保证“扣钱+加道具”“升级+解锁技能”等操作的原子性,防止数据不一致。\n3. 灵活扩展,适配数据增长\n- 玩家数据量随用户增长时,可通过“分片”横向扩展(将数据分布到多台服务器),支持百万级甚至亿级玩家数据。\n- 文档结构动态灵活,新增字段无需修改表结构,旧数据可兼容(查询时自动忽略不存在的字段),适配游戏版本迭代。\n4. 完善的数据管理能力\n提供备份( mongodump )、恢复( mongorestore )、监控(MongoDB Atlas)等工具,支持数据压缩、过期索引(如清理离线玩家缓存),适合长期运行的在线游戏。\n \n缺点\n \n1. 运维与学习成本高\n需要部署、维护数据库服务(如集群配置、索引优化、故障排查),对小型团队可能增加运维压力;开发人员需学习MongoDB的查询语法(如 find 、 aggregate )、索引设计等,门槛高于JSON文件。\n2. 资源占用较高\n相比JSON文件,MongoDB需要额外的内存(缓存索引和热数据)、CPU(处理查询)和磁盘空间(数据文件+日志),不适合资源受限的极简场景(如嵌入式小游戏)。\n3. 过度设计风险\n对于单机游戏、玩家数极少(如几百人)且无复杂查询的场景,MongoDB的优势无法体现,反而因配置复杂降低开发效率。\n \n总结:适用场景\n \n- 普通JSON文件:适合单人游戏、小型休闲游戏、开发测试阶段,或数据量极小(<1万玩家)、读写频率低、无复杂查询的场景。\n- MongoDB:适合多人在线游戏(MMO、MOBA等)、中大型游戏,或玩家数多(>1万)、需高频读写、复杂查询、结构迭代频繁的场景。\n \n实际开发中,也可根据规模过渡:初期用JSON文件快速上线,待用户增长后迁移至MongoDB,利用其扩展性支撑业务。",
|
||
"数据库/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**索引的核心作用:**\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": "# 二分查找右侧边界算法总结\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\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. **图片**:使用``\r\n ```markdown\r\n \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": "<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",
|
||
"游戏引擎/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的值(方法)\r\n\r\n```c\r\n#include <stdio.h>\r\n//异或\r\nint main() {\r\n int x = 10, y = 20;\r\n x = x ^ y;\r\n y = x ^ y;\r\n x = x ^ y;\r\n printf(\"x的值为:%d,y的值为:%d\\n\", x, y);\r\n return 0;\r\n}\r\n\r\n```\r\n\r\n```c\r\n#include <stdio.h>\r\n\r\nint main() {\r\n int x = 10, y = 20;\r\n x = x + y;\r\n y = x - y;\r\n x = x - y;\r\n printf(\"x的值为:%d,y的值为:%d\\n\", x, y);\r\n return 0;\r\n}\r\n\r\n```\r\n\r\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": "### 源文件\r\n\r\n- **.cpp 或 .cxx 或 .cc :**C++源文件的扩展名,用于编写C++代码,包含函数、类、变量等定义和实现。\r\n- **.h 或 .hpp 或 .hxx :**头文件扩展名,用于声明函数原型、类定义、常量和变量等,以便在多个源文件中共享声明。\r\n\r\n### 项目和配置文件\r\n\r\n- **.vcxproj :**Visual C++项目文件,用于Visual Studio开发环境,包含项目的配置信息、源文件列表、引用等。\r\n- **.sln :**解决方案文件,用于组织多个相关的项目,包含项目之间的依赖关系等信息。\r\n- **CMakeLists.txt :**使用CMake构建系统时的项目配置文件,用于描述项目的源文件、目标、依赖等信息,可生成不同平台和编译器的项目文件。\r\n- **Makefile :**在Unix和类Unix系统中,用于定义编译规则和目标,指定源文件如何编译链接成可执行文件或库。\r\n\r\n### 库文件\r\n\r\n- **.lib :**Windows下的静态库文件,包含已编译的代码和数据,在链接时被直接复制到可执行文件中。\r\n- **.a :**Unix和类Unix系统下的静态库文件,作用与Windows下的 .lib 类似。\r\n- **.dll :**Windows下的动态链接库文件,包含可在运行时被加载和调用的代码和数据。\r\n- **.so :**Unix和类Unix系统下的共享库文件,类似于Windows的 .dll ,在运行时动态链接。\r\n\r\n### 可执行文件\r\n\r\n- **.exe :**Windows下的可执行文件,是编译链接后的最终产物,可在操作系统中直接运行。\r\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++/值传递和地址传递的区别.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 = #\r\n // 写法二:声明并初始化\r\n int *p2 = #\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 = #\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 更偏向历史兼容性。",
|
||
"编程语言/Flutter/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/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/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",
|
||
"编程语言/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",
|
||
"编程语言/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",
|
||
"计算机科普/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 有充足的闲置计算能力。",
|
||
"计算机科普/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\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米的接入。",
|
||
"计算机科普/多模态大模型识别图片,视频,音频原理.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",
|
||
"计算机科普/术语科普-CVM.md": "CVM 通常指 云服务器(Cloud Virtual Machine),是云计算服务中的一种基础计算资源。它通过虚拟化技术,将物理服务器分割成多个独立的虚拟服务器,用户可像使用本地服务器一样远程管理和使用,无需自行购买和维护硬件设备。\n \n其核心特点包括:\n \n- 弹性伸缩:可根据业务需求灵活调整 CPU、内存、存储等配置。\n- 按需付费:按使用时长或资源配置计费,降低初期投入成本。\n- 高可用性:依托云服务商的基础设施,通常具备多副本存储、故障自动迁移等能力。\n- 易管理性:通过云平台控制台可便捷进行开关机、重装系统、配置网络等操作。\n \n在实际应用中,CVM 广泛用于搭建网站、部署应用程序、运行数据库、进行大数据分析等场景。不同云服务商(如腾讯云、阿里云等)对其的具体命名可能略有差异,但核心功能一致。",
|
||
"计算机科普/术语科普-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",
|
||
"计算机科普/术语科普-MCU.md": "微控制单元(Microcontroller Unit):这是电子工程领域的专业术语,又称“单片机”。它是一种将中央处理器(CPU)、存储器、输入/输出接口等功能集成在一块芯片上的微型计算机,广泛应用于智能家居、汽车电子、工业控制等领域。",
|
||
"计算机科普/术语科普-pwn.md": "“pwn” 是网络安全领域的常用术语,核心指 通过利用程序漏洞(如缓冲区溢出、内存泄漏等)获取目标系统的控制权,比如执行任意代码、提升权限甚至完全掌控设备。\n \n它起源于“own”(意为“拥有、控制”)的拼写变体,早期在黑客社区和安全竞赛(如CTF)中流行。常见场景包括:\n \n- 对存在漏洞的软件、服务器进行攻击;\n- CTF竞赛中的“pwn题”,要求参赛者找出并利用程序漏洞解决问题。\n \n简单说,pwn的本质就是“找到漏洞并借此控制目标”。",
|
||
"计算机科普/科普-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",
|
||
"计算机网络/TCP的三次握手四次握手.md": "**TCP连接建立过程:**\n首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资源。Client端接收到ACK报文后也向Server段发生ACK报文,并分配资源,这样TCP连接就建立了。\n\n**TCP连接断开过程:**\n假设Client端发起中断连接请求,也就是发送FIN报文。Server端接到FIN报文后,意思是说\"我Client端没有数据要发给你了\",但是如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。所以你先发送ACK,\"告诉Client端,你的请求我收到了,但是我还没准备好,请继续你等我的消息\"。这个时候Client端就进入FIN_WAIT状态,继续等待Server端的FIN报文。当Server端确定数据已发送完成,则向Client端发送FIN报文,\"告诉Client端,好了,我这边数据发完了,准备好关闭连接了\"。Client端收到FIN报文后,\"就知道可以关闭连接了,但是他还是不相信网络,怕Server端不知道要关闭,所以发送ACK后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。\",Server端收到ACK后,\"就知道可以断开连接了\"。Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。Ok,TCP连接就这样关闭了!\n\n**为什么要三次握手?**\n\n在只有两次\"握手\"的情形下,假设Client想跟Server建立连接,但是却因为中途连接请求的数据报丢失了,故Client端不得不重新发送一遍;这个时候Server端仅收到一个连接请求,因此可以正常的建立连接。但是,有时候Client端重新发送请求不是因为数据报丢失了,而是有可能数据传输过程因为网络并发量很大在某结点被阻塞了,这种情形下Server端将先后收到2次请求,并持续等待两个Client请求向他发送数据...问题就在这里,Cient端实际上只有一次请求,而Server端却有2个响应,极端的情况可能由于Client端多次重新发送请求数据而导致Server端最后建立了N多个响应在等待,因而造成极大的资源浪费!所以,\"三次握手\"很有必要!\n\n**为什么要四次挥手?**\n\n试想一下,假如现在你是客户端你想断开跟Server的所有连接该怎么做?第一步,你自己先停止向Server端发送数据,并等待Server的回复。但事情还没有完,虽然你自身不往Server发送数据了,但是因为你们之前已经建立好平等的连接了,所以此时他也有主动权向你发送数据;故Server端还得终止主动向你发送数据,并等待你的确认。其实,说白了就是保证双方的一个合约的完整执行!\n\n使用TCP的协议:FTP(文件传输协议)、Telnet(远程登录协议)、SMTP(简单邮件传输协议)、POP3(和SMTP相对,用于接收邮件)、HTTP协议等。",
|
||
"计算机网络/网络层次划分.md": "著名的OSI/RM模型(Open System Interconnection/Reference Model)。它将计算机网络体系结构的通信协议划分为七层,自下而上依次为:\n物理层(Physics Layer)、\n数据链路层(Data Link Layer)、\n网络层(Network Layer)、\n传输层(Transport Layer)、\n会话层(Session Layer)、\n表示层(Presentation Layer)、\n应用层(Application Layer)。\n其中第四层完成数据传送服务,上面三层面向用户。\n\n除了标准的OSI七层模型以外,常见的网络层次划分还有TCP/IP四层协议以及TCP/IP五层协议",
|
||
"面试八股/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---",
|
||
"面试八股/计算机面试经典八股.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这份清单涵盖了计算机面试中最核心、最高频的基础知识点。针对具体岗位(前端、后端、算法、运维、测试等)",
|
||
"首页.md": "\n## 引言\n你好,陌生人!这是我的学习笔记,用来展示我的一些学习路径\n欢迎和我一起讨论和交流学习!\n\n## 联系方式\nQQ:3205788256\n邮箱:3205788256@qq.com\n个人主页:shumengya.top\n作品集:work.shumengya.top"
|
||
} |