FTP客户端实现(文件传输)
文章目录
- 🧱 一、FTP 基础架构回顾
- 🚀 二、FTP 客户端的核心结构
- 🔗 三、连接与登录过程
- 📌 1. `ftp_create()`
- 📌 2. `ftp_connect()`
- 📌 3. `ftp_login()`
- 📁 四、上传文件实现(`ftp_upload_file()`)
- 🚩 流程总览:
- ✨ 细节讲解
- ✅ 1. 判断 remote_path 是目录 or 文件路径
- ✅ 2. 递归创建远程目录
- ✅ 3. 进入 PASV 模式(被动模式)
- ✅ 4. 发起数据连接(客户端主动连接)
- ✅ 5. 发送 STOR 命令
- ✅ 6. 发送文件内容(TCP)
- 🔚 五、退出与清理
- 📢 六、辅助函数详解
- ✅ `send_command()`
- ✅ `read_reply()`
- 📌 七、完整上传流程演示(例子)
- ✅ 总结:功能完整的 FTP 上传模块
这段代码实现了一个 FTP 客户端核心功能模块,可完成如下关键任务:
✅ 建立连接
✅ 登录认证
✅ 递归创建远程目录
✅ 上传文件(支持上传到目录)
✅ 退出登录
下面我将按照功能模块,详细讲解整个 FTP 上传流程的实现原理和关键函数。
🧱 一、FTP 基础架构回顾
FTP 通信包括两个通道:
- 控制通道(control channel):用于发送 FTP 命令和接收响应(TCP 21)
- 数据通道(data channel):用于传输文件、目录等(通过
PASV
或PORT
创建)
本实现采用 PASV(被动模式) 建立数据通道,即客户端主动连接服务端开放的端口。
🚀 二、FTP 客户端的核心结构
typedef struct {int control_sock; // 控制通道 socketstruct sockaddr_in server_addr;
} FTPClient;
🔗 三、连接与登录过程
📌 1. ftp_create()
- 创建控制通道 socket:
socket(AF_INET, SOCK_STREAM, 0)
- 配置远程 IP 和端口(默认 21)
- 返回已初始化的 FTPClient 指针
📌 2. ftp_connect()
- 使用
connect()
发起 TCP 控制连接 - 成功后读取服务端欢迎信息(FTP 状态码应该是
220
)
read_reply(...) == 220 → 成功
📌 3. ftp_login()
- 先发送用户名命令:
USER xxx\r\n
- 响应应为
331
,表示继续输入密码
- 响应应为
- 再发送密码命令:
PASS xxx\r\n
- 响应应为
230
,表示登录成功
- 响应应为
📁 四、上传文件实现(ftp_upload_file()
)
🚩 流程总览:
→ 判断 remote_path 是目录还是完整路径
→ 如果是目录:拼接本地文件名
→ 递归创建远程目录(MKD)
→ 进入 PASV 模式,获取数据连接地址和端口
→ 发起数据连接(客户端连接服务端返回的地址/端口)
→ 发送 STOR 上传命令
→ 传输文件内容
→ 关闭数据连接并读取完成响应(226)
✨ 细节讲解
✅ 1. 判断 remote_path 是目录 or 文件路径
if (remote_path[strlen(remote_path) - 1] == '/') {// 是目录 → 拼接 local_file 的文件名
}
例:
local_file = "/home/user/a.txt"
remote_path = "upload/abc/"
→ final_remote_file = "upload/abc/a.txt"
✅ 2. 递归创建远程目录
ftp_create_remote_path(client, remote_dir);
内部调用:
MKD /upload
MKD /upload/abc
MKD /upload/abc/xyz
错误 550 表示已存在,也视作成功。
✅ 3. 进入 PASV 模式(被动模式)
send_command(..., "PASV\r\n");
read_reply(...); // 解析响应 227→ 解析返回的 IP 和端口:
"227 Entering Passive Mode (192,168,1,10,14,78)"
→ port = 14*256 + 78 = 3678
服务端会在该端口等待数据连接。
✅ 4. 发起数据连接(客户端主动连接)
data_sock = socket(...)
connect(data_sock, ...)
目标 IP = 控制连接 IP,端口 = PASV 返回的端口。
✅ 5. 发送 STOR 命令
STOR upload/abc/a.txt\r\n
→ 服务端响应 150:准备传输数据
✅ 6. 发送文件内容(TCP)
while (fread(...) > 0) {send(data_sock, ...);
}
成功发送完后:
- 关闭
data_sock
- 读取控制通道响应是否为
226
→ 传输完成
🔚 五、退出与清理
ftp_quit(client);
→ 发送 QUIT\r\n,服务端应返回 221ftp_destroy(client);
→ 关闭 socket,释放内存
📢 六、辅助函数详解
✅ send_command()
send(sock, command, strlen(command), 0);
发送命令字符串,例如:
"USER test\r\n"
"STOR /path/file.txt\r\n"
✅ read_reply()
recv(sock, buffer, ...);
→ 返回第一段数字作为 FTP 响应码(例如 220、331、226)
📌 七、完整上传流程演示(例子)
local_file = "/home/user/a.txt"
remote_path = "upload/test/" // 目录
程序实际执行逻辑:
- 拼接路径 → upload/test/a.txt
- 创建路径:MKD /upload、/upload/test
- PASV 模式,服务端返回数据端口
- 建立数据连接
- STOR upload/test/a.txt
- 发送文件数据
- 等待 226 响应
- QUIT → 221
✅ 总结:功能完整的 FTP 上传模块
功能 | 是否支持 |
---|---|
控制连接建立 | ✅ |
用户登录认证 | ✅ |
被动模式数据传输 | ✅ |
自动创建多级目录 | ✅ |
上传任意路径文件 | ✅ |
退出与资源释放 | ✅ |
核心代码:
#include "ftpclient.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define BUF_SIZE 1024// 内部函数声明
static int send_command(int sock, const char* command);
static int read_reply(int sock, char* buffer, size_t size);
static int ftp_create_dir(FTPClient* client, const char* remote_dir);// 创建客户端
FTPClient* ftp_create(const char* server_ip, int server_port) {FTPClient* client = (FTPClient*)malloc(sizeof(FTPClient));if (!client) return NULL;client->control_sock = socket(AF_INET, SOCK_STREAM, 0);if (client->control_sock < 0) {free(client);return NULL;}memset(&client->server_addr, 0, sizeof(client->server_addr));client->server_addr.sin_family = AF_INET;client->server_addr.sin_port = htons(server_port);inet_pton(AF_INET, server_ip, &client->server_addr.sin_addr);return client;
}void ftp_destroy(FTPClient* client) {if (client) {if (client->control_sock >= 0)close(client->control_sock);free(client);}
}int ftp_connect(FTPClient* client) {if (connect(client->control_sock, (struct sockaddr*)&client->server_addr, sizeof(client->server_addr)) < 0)return -1;char buffer[BUF_SIZE];return read_reply(client->control_sock, buffer, sizeof(buffer)) == 220 ? 0 : -1;
}int ftp_login(FTPClient* client, const char* username, const char* password) {char command[BUF_SIZE];char buffer[BUF_SIZE];snprintf(command, sizeof(command), "USER %s\r\n", username);if (send_command(client->control_sock, command) < 0) return -1;if (read_reply(client->control_sock, buffer, sizeof(buffer)) != 331) return -1;snprintf(command, sizeof(command), "PASS %s\r\n", password);if (send_command(client->control_sock, command) < 0) return -1;if (read_reply(client->control_sock, buffer, sizeof(buffer)) != 230) return -1;return 0;
}int ftp_upload_file(FTPClient* client, const char* local_file, const char* remote_path) {FILE* file = fopen(local_file, "rb");if (!file) return -1;char buffer[BUF_SIZE];// 处理 remote_file:判断是否是目录char final_remote_file[BUF_SIZE];if (remote_path[strlen(remote_path) - 1] == '/') {// 提取文件名const char* file_name = strrchr(local_file, '/');file_name = file_name ? file_name + 1 : local_file;snprintf(final_remote_file, sizeof(final_remote_file), "%s%s", remote_path, file_name);} else {strncpy(final_remote_file, remote_path, sizeof(final_remote_file));final_remote_file[sizeof(final_remote_file) - 1] = '\0';}// 提取目录路径并创建char remote_dir[BUF_SIZE];strncpy(remote_dir, final_remote_file, sizeof(remote_dir));remote_dir[sizeof(remote_dir) - 1] = '\0';char* last_slash = strrchr(remote_dir, '/');if (last_slash) {*last_slash = '\0';ftp_create_remote_path(client, remote_dir); // 忽略失败}// PASV 模式if (send_command(client->control_sock, "PASV\r\n") < 0) {fclose(file);return -1;}if (read_reply(client->control_sock, buffer, sizeof(buffer)) != 227) {fclose(file);return -1;}int ip1, ip2, ip3, ip4, p1, p2;sscanf(buffer, "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)",&ip1, &ip2, &ip3, &ip4, &p1, &p2);int data_port = p1 * 256 + p2;int data_sock = socket(AF_INET, SOCK_STREAM, 0);if (data_sock < 0) {fclose(file);return -1;}struct sockaddr_in data_addr;memset(&data_addr, 0, sizeof(data_addr));data_addr.sin_family = AF_INET;data_addr.sin_port = htons(data_port);data_addr.sin_addr = client->server_addr.sin_addr;if (connect(data_sock, (struct sockaddr*)&data_addr, sizeof(data_addr)) < 0) {close(data_sock);fclose(file);return -1;}snprintf(buffer, sizeof(buffer), "STOR %s\r\n", final_remote_file);if (send_command(client->control_sock, buffer) < 0) {close(data_sock);fclose(file);return -1;}if (read_reply(client->control_sock, buffer, sizeof(buffer)) != 150) {close(data_sock);fclose(file);return -1;}size_t bytes_read;while ((bytes_read = fread(buffer, 1, sizeof(buffer), file)) > 0) {if (send(data_sock, buffer, bytes_read, 0) < 0) {close(data_sock);fclose(file);return -1;}}close(data_sock);fclose(file);return (read_reply(client->control_sock, buffer, sizeof(buffer)) == 226) ? 0 : -1;
}void ftp_quit(FTPClient* client) {send_command(client->control_sock, "QUIT\r\n");char buffer[BUF_SIZE];read_reply(client->control_sock, buffer, sizeof(buffer));
}// 创建路径:递归 MKD
int ftp_create_remote_path(FTPClient* client, const char* remote_path) {char path[BUF_SIZE];strncpy(path, remote_path, sizeof(path));path[sizeof(path) - 1] = '\0';char temp[BUF_SIZE] = {0};char* token = strtok(path, "/");while (token) {strcat(temp, "/");strcat(temp, token);ftp_create_dir(client, temp); // 忽略失败token = strtok(NULL, "/");}return 0;
}static int ftp_create_dir(FTPClient* client, const char* remote_dir) {char buffer[BUF_SIZE];snprintf(buffer, sizeof(buffer), "MKD %s\r\n", remote_dir);if (send_command(client->control_sock, buffer) < 0) return -1;int code = read_reply(client->control_sock, buffer, sizeof(buffer));return (code == 257 || code == 550) ? 0 : -1; // 550 表示目录已存在
}static int send_command(int sock, const char* command) {return (send(sock, command, strlen(command), 0) == strlen(command)) ? 0 : -1;
}static int read_reply(int sock, char* buffer, size_t size) {int bytes_read = recv(sock, buffer, size - 1, 0);if (bytes_read <= 0) return -1;buffer[bytes_read] = '\0';return atoi(buffer);
}
相关文章:
FTP客户端实现(文件传输)
文章目录 🧱 一、FTP 基础架构回顾🚀 二、FTP 客户端的核心结构🔗 三、连接与登录过程📌 1. ftp_create()📌 2. ftp_connect()📌 3. ftp_login() 📁 四、上传文件实现(ftp_upload_fi…...
状态管理最佳实践:Bloc架构实践
状态管理最佳实践:Bloc架构实践 引言 Bloc (Business Logic Component) 是Flutter中一种强大的状态管理解决方案,它基于响应式编程思想,通过分离业务逻辑和UI表现层来实现清晰的代码架构。本文将深入探讨Bloc的核心概念、实现原理和最佳实践…...
嵌入式人工智能应用-第三章 opencv操作 5 二值化、图像缩放
嵌入式人工智能应用 嵌入式人工智能应用-第三章 opencv操作 5 二值化 嵌入式人工智能应用1 二值化1.1 概念介绍1.2 函数介绍1.2 基本应用1.3 参考案例 2 图像缩放2.1 基本概念2.2 函数介绍2.3 基本参考代码2.4 pyrUp 和 pyrDown 函数2.5 函数介绍2.6 参考代码2.7 总结 1 二值化…...
[OS_7] 访问操作系统对象 | offset | FHS | Handle
实验代码可以看去年暑假的这篇文章:【Linux】进程间通信:详解 VSCode使用 | 匿名管道 我们已经知道,进程从 execve 后的初始状态开始,可以通过 mmap 改变自己的地址空间,通过 fork 创建新的进程,再通过 exe…...
【Vulkan 入门系列】创建帧缓冲、命令池、命令缓存,和获取图片(六)
这一节主要介绍创建帧缓冲(Framebuffer),创建命令池,创建命令缓存,和从文件加载 PNG 图像数据,解码为 RGBA 格式,并将像素数据暂存到 Vulkan 的 暂存缓冲区中。 一、创建帧缓冲 createFramebu…...
Linux 进程控制(自用)
非阻塞调用waitpid 这样父进程就不会阻塞,此时循环使用我们可以让父进程执行其他任务而不是阻塞等待 进程程序替换 进程PCB加载到内存中的代码和数据 替换就是完全替换当前进程的代码段、数据段、堆和栈,保存当前的PCB 代码指的是二进制代码不是源码&a…...
FreeSWITCH 简单图形化界面41 - 批量SIP视频呼叫测试
FreeSWITCH 简单图形化界面41 - 批量视频测试 0、界面预览00、安装测试工具1、注册分机2、设置接听选项2.1 上传媒体文件2.2 设置接听设置 3、呼叫测试 0、界面预览 http://myfs.f3322.net:8020/ 用户名:admin,密码:admin FreeSWITCH界面安…...
通过爬虫方式实现头条号发布视频(2025年4月)
1、将真实的cookie贴到代码目录中toutiaohao_cookie.txt文件里,修改python代码里的user_agent和video_path, cover_path等变量的值,最后运行python脚本即可; 2、运行之前根据import提示安装一些常见依赖,比如requests等; 3、2025年4月份最新版; 代码如下: import js…...
《AI大模型应知应会100篇》第28篇:大模型在文本创作中的应用技巧
第28篇:大模型在文本创作中的应用技巧 🧠 摘要 在内容为王的时代,AI大模型正在重塑文本创作的每一个环节。从创意构思到风格润色,从论文报告到小说脚本,AI不仅是创作者的助手,更是灵感的激发器。本文将带你…...
字节跳动发布UI-TARS-1.5,入门AI就来近屿智能
近日,字节跳动在 Hugging Face 平台正式开源了其最新多模态代理模型——UI-TARS-1.5。作为 UI-TARS 系列的革新之作,该模型以视觉语言模型为基础,突破性实现跨平台 GUI 自动化交互,为自动化与智能交互领域注入了强劲动能。无论是开…...
大数据学习栈记——MapReduce技术
本文介绍hadoop中的MapReduce技术的应用,使用java API。操作系统:Ubuntu24.04。 MapReduce概述 MapReduce概念 MapReduce是一个分布式运算程序的编程框架,核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序…...
GO语言入门:常用数学函数2
14.6 大型数值 math/big 包中公开了一些实用 API,用于表示大型整数值和浮点数值。当基础类型无法容纳要使用的数值时,应改用 big 包中提供的新类型。例如 Int、Float 等。 14.6.1 大型整数值之间的运算 若希望让下面两个整数值完成加、减法运算&#…...
Django 使用教程
Django 使用教程 Django 是一个高级的 Python Web 框架,采用了 MTV(Model-Template-View)设计模式,旨在帮助开发者快速构建高效、可维护的 Web 应用。它有着非常丰富的功能,包括 ORM、用户认证、表单处理、管理后台等…...
deepseek + kimi制作PPT
目录 一、kimi简介二、deepseek生成内容三、生成PPT四、编辑PPT 一、kimi简介 kimi是一款只能ppt生成器,擅长将文本内容生成PPT。 在这里,DeepSeek 负责内容生成与逻辑梳理,Kimi 优化表达与提供设计建议。 二、deepseek生…...
C++学习:六个月从基础到就业——内存管理:RAII原则
C学习:六个月从基础到就业——内存管理:RAII原则 本文是我C学习之旅系列的第十九篇技术文章,也是第二阶段"C进阶特性"的第四篇,主要介绍C中的RAII原则及其在资源管理中的应用。查看完整系列目录了解更多内容。 引言 在…...
量子计算与经典计算融合:开启计算新时代
一、引言 随着科技的飞速发展,计算技术正迎来一场前所未有的变革。量子计算作为前沿技术,以其强大的并行计算能力和对复杂问题的高效处理能力,吸引了全球科技界的关注。然而,量子计算并非要完全取代经典计算,而是与经典…...
RV1126网络环境TFTPNFS搭建(二)
二、RV1126 开发板TFTP环境搭建 2.1、Ubuntu下安装和配置 xinetd 执行以下指令,安装 xinetd sudo apt-get install xinetd 执行以下指令创建一个 xinetd.conf 文件 sudo vi /etc/xinetd.conf 修改 xinetd.conf 文件内容如下: # Simple configurat…...
计算机视觉7——齐次坐标与相机内外参
一、透视投影 透视投影(Perspective Projection)是计算机视觉和图形学中描述三维物体在二维平面成像的基础模型,其核心思想是模拟人类视觉系统的成像原理——中心投影。具体而言,三维空间中的点通过一个固定的投影中心࿰…...
学习笔记—C++—string(一)
目录 string 为什么学习string的类 string类的常用接口 string类对象的常见构造 string类对象的访问及遍历操作 operator[] 迭代器 范围for auto 迭代器(二) string类对象的容量操作 size,length,max_size,capacity,clear基本用法 reserve 提…...
Linux命令-Shell编程
Shell是一个命令行解释器,它接收应用程序/用户命令,然后调用操作系统内核。 写一个hello.sh脚本: 1.mkdir scripts 2.cd scripts 3.touch hello.sh 4.vim hello.sh #!/bin/bash echo "hello,world" 5.bash hello.sh(…...
基于Django的AI客服租车分析系统
基于Django的AI客服租车分析系统 【包含内容】 【一】项目提供完整源代码及详细注释 【二】系统设计思路与实现说明 【三】AI智能客服与用户交互指导手册 【技术栈】 ①:系统环境:Python 3.8,Django 4.2框架 ②:开发环境&a…...
计算机组成与体系结构:计算机结构的分类(classifications of computer architecture)
目录 Von Neumann Architecture(冯诺依曼结构) Harvard Architecture(哈佛结构) Modified Harvard Architecture(改进哈佛结构) 三种结构对比总结表 💡 从“内存访问结构”角度分类&#x…...
在阿里云和树莓派上编写一个守护进程程序
目录 一、阿里云邮件守护进程 1. 安装必要库 2. 创建邮件发送脚本 mail_daemon.py 3. 设置后台运行 二、树莓派串口守护进程 1. 启用树莓派串口 2. 安装依赖库 3. 创建串口输出脚本 serial_daemon.py 4. 设置开机自启 5. 使用串口助手接收 一、阿里云邮件守护进程 1.…...
Redis 的几种数据类型
Redis 提供了多种数据类型,以支持不同的应用场景。每种数据类型都有其特定的操作方式,并且在内部实现上也有所优化,能够满足不同的业务需求。以下是 Redis 支持的几种常见数据类型: 1. 字符串(String) 描…...
Spring之我见 - Spring Boot Starter 自动装配原理
欢迎光临小站:致橡树 Spring Boot Starter 的核心设计理念是 约定优于配置,其核心实现基于 自动配置(Auto-Configuration) 和 条件化注册(Conditional Registration)。以下是其生效原理: 约定…...
LeRobot 项目部署运行逻辑(二)—— Mobile Aloha 真机部署
LeRobot 在开源项目中详细说明了部署流程,所以首先看一下开源的内容,然后再逐步拆解 首先,LeRobot 开源的硬件是配全部在 examples 文件夹中 包括了 Stretch 3、Aloha and Aloha 2 stationary、SO-100、LeKiwi、Moss v1 等机器人 恰好实验…...
大模型面经 | 介绍一下CLIP和BLIP
大家好,我是皮先生!! 今天给大家分享一些关于大模型面试常见的面试题,希望对大家的面试有所帮助。 往期回顾: 大模型面经 | 春招、秋招算法面试常考八股文附答案(RAG专题一) 大模型面经 | 春招、秋招算法面试常考八股文附答案(RAG专题二) 大模型面经 | 春招、秋招算法…...
Java发生OOM是否必然导致JVM退出
Java发生OOM是否必然导致JVM退出? 核心结论 不一定。OOM是否导致JVM退出取决于以下因素: OOM发生的区域JVM启动参数配置是否捕获了OOM异常 详细分析 1. 不同内存区域的OOM影响 内存区域错误类型默认是否导致JVM退出可恢复性Java堆OutOfMemoryError…...
Docker Compose 外部网络(`external: true`)与内部网络的区别
Docker Compose 外部网络(external: true)与内部网络的区别 在 Docker Compose 中,external: true 声明的外部网络与普通(内部)网络有重要区别,以下是它们的详细对比: 1. 定义与创建方式 特性外部网络 (external: true)内部网络 (默认)创建…...
【Android】Wallpaper学习
从wallpaper的设置来了解相关内容: 一,静态壁纸 静态壁纸设置的原理是在WallpaperManagerService里监听/data/system/users/0/wallpaper_orig相关文件的变化来触发设置,通过相应的组件程序去进行绘制, 相应的组件如:…...
Java基础-第一章、基本数据类型
运算符: 1.算术运算符:加减乘除%等 2.逻辑运算符:与或非等 3.关系运算符:大于、小于... 4.赋值运算符: 这里牵扯运算符的运算先后顺序了。 赋值运算的返回值:就是赋值的变量本身...
《Operating System Concepts》阅读笔记:p748-p748
《Operating System Concepts》学习第 64 天,p748-p748 总结,总计 1 页。 一、技术总结 1.Transmission Control Protocol(TCP) 重点是要自己能画出其过程,这里就不赘述了。 二、英语总结(生词:3) transfer, transport, tran…...
Arduino示例代码讲解:Project 08 - Digital Hourglass 数字沙漏
Arduino示例代码讲解:Project 08 - Digital Hourglass 数字沙漏 Project 08 - Digital Hourglass 数字沙漏程序功能概述功能:硬件要求:输出:代码结构全局变量`setup()` 函数`loop()` 函数计时和点亮LED:读取倾斜开关状态:重置LED和计时器:运行过程注意事项Project 08 - …...
报告总结笔记 | Jeff Dean ETH AI趋势 笔记:AI 的重要趋势:我们是如何走到今天的,我们现在能做什么,以及我们如何塑造 AI 的未来?
报告总结笔记 | Jeff Dean ETH AI趋势 笔记:AI 的重要趋势:我们是如何走到今天的,我们现在能做什么,以及我们如何塑造 AI 的未来? 2025年 4 月 14 日,Google Research 及 Google DeepMind 的首席科学家、A…...
RocketMQ实现基于可靠消息的最终一致性
RocketMQ实现基于可靠消息的最终一致性 文章目录 RocketMQ实现基于可靠消息的最终一致性一、RocketMQ应用场景**应用解耦****流量削峰****数据分发** 二、RocketMQ 基础概念1. 核心组件2. 消费模式3. 消息可靠性 三、消息类型按发送方式分同步发送异步发送单向发送 按使用功能特…...
【题解-Acwing】790. 数的三次方根
题目:790. 数的三次方根 题目描述 给定一个浮点数 n,求它的三次方根。 输入 共一行,包含一个浮点数 n 。 输出 共一行,包含一个浮点数,表示问题的解。 注意,结果保留 6 位小数。 数据范围 −10000 ≤ n ≤ 10000 时空限制 1s / 64MB 输入样例 1000.00输出样…...
一键升级OpenSSH/OpenSSL修复安全漏洞
在服务器安全运维过程中,我们经常面临这样的问题:收到高危漏洞通报(如最近的OpenSSH多个CVE漏洞),但Ubuntu系统无法通过apt直接升级到修复版本。这种情况下,传统方法需要手动编译源码,处理依赖关…...
Pycharm 如何删除某个 Python Interpreter
在PyCharm中,点击右下角的“Interpreter Settings”按钮,或者通过菜单栏选择“File” > “Settings”(macOS用户选择“PyCharm” > “Preferences”)。在设置窗口中,导航到“Project: [Your Project Name]” >…...
【C++】深入浅出之多态
目录 多态的概念多态的定义和实现多态的构造条件虚函数虚函数的重写虚函数重写的两个例外协变析构函数作为虚函数重写 C11的override和final重载、重写(覆盖)、隐藏(重定义)的对比相关面试题⭐ 抽象类概念接口继承和实现继承 多态的原理虚函数表多态的原理动态绑定和静态绑定 e…...
精益数据分析(9/126):如何筛选创业路上的关键数据指标
精益数据分析(9/126):如何筛选创业路上的关键数据指标 大家好!在创业的漫漫长路中,数据就像一盏明灯,指引着我们前行的方向。但要让这盏灯发挥作用,关键在于找到那些真正有价值的数据指标。今天…...
【Python爬虫详解】第二篇:HTML结构的基本分析
在上一篇文章中,我们介绍了网络爬虫的基本概念、发展历程和工作原理。要进行有效的网页内容爬取,首先需要理解我们要爬取的对象 —— 网页的基本结构和语法。网页本质上是由HTML代码构成的,爬虫程序需要从HTML中提取我们需要的信息。因此&…...
【C++】 —— 笔试刷题day_21
一、爱丽丝的人偶 题目解析 现在存在n个玩偶,每个玩偶的身高是1、2、3......n; 现在我们要对这些玩偶进行排序(如果x人偶,它左右两边的玩偶一个比x高、一个比x矮,那这个玩偶就会爆炸)。 我们不想要任何一个…...
云点数据读写
一、常见点云数据格式 LAS/LAZ格式 LAS是点云数据的行业标准格式 LAZ是LAS的压缩版本 支持地理参考信息、颜色、强度等属性 PCD格式(Point Cloud Data) PCL(Point Cloud Library)开发的格式 支持ASCII和二进制存储 包含头部信息和数据部分 PLY格式(Polygon File Format…...
Matlab 汽车行驶速度PID控制系统仿真
1、内容简介 Matlab 213-汽车行驶速度PID控制系统仿真 可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 4、参考论文 略...
STM32嵌入式
一、创建工程项目 1、进入软件首页 2、新建项目,【file】->【new project】 3、选择需要的芯片 4、系统内核部分设置 ① 选择晶振(使用外部的高速晶振) ② 选择debug形式(SW类型) 5、时钟设置 6、选择自己需要的引脚设置&a…...
机器学习(神经网络基础篇)——个人理解篇6(概念+代码)
1 在声明一个类中,构建一个属于类的函数,前面为什要加上“self”? 就像下面这一串代码: class TwoLayerNet:def __init__(self, input_size, hidden_size, output_size,weight_init_std0.01):# 初始化权重self.params {}self.p…...
Java学习手册:Filter 和 Listener
在 JavaWeb 开发中,Filter(过滤器)和 Listener(监听器)是两个重要的技术组件,它们在处理客户端请求、管理应用状态和资源以及实现全局逻辑控制等方面发挥着关键作用。 一、Filter(过滤器&#…...
深度学习总结(25)
抽样偏倚问题 非代表性数据有一个特别隐蔽又特别常见的例子,那就是抽样偏倚(sampling bias)。如果你的数据收集过程与你尝试预测的目标之间存在相互影响,就会出现抽样偏倚,从而导致有偏差的结果。 理解数据 将数据…...
探索 Model Context Protocol (MCP):它如何影响 AI 的表现?
Anthropic 公司 Anthropic 是一家技术实力雄厚的公司,也是大模型领域的重要参与者之一。其开发的 **Claude 模型** 是全球首个以编程能力见长并广受欢迎的大语言模型。这款模型凭借卓越的代码生成和理解能力,迅速成为许多开发者工具的核心组件。例如&am…...
Three.js + React 实战系列-3D 个人主页 :完成 Navbar 导航栏组件
在上一节中,我们搭建了项目的基础结构,搭建好了项目框架。 本节我们将继续完善页面结构,完成第一个视觉组件 —— Navbar 导航栏 ✅ 前置准备: ✅下载静态资源在根目录下 (src 同级)谷歌云盘地址 🎥 02 完成 Navba…...