佳能镜头EOS系统EF协议逆向工程(三)解码算法
目录
数据结构
解码算法
解码效果
这篇文章基于上两篇文章继续,
佳能镜头EOS系统EF协议逆向工程(一)转接环电路设计_佳能ef自动对焦协议_岬淢箫声的博客-CSDN博客本文属于专栏——工业相机。此专栏首先提供我人工翻译的法语文档部分,然后通过STM32F103C8T6控制佳能镜头,最后协同上位机或者NVIDIA Xavier实现自动对焦。还有一个用处不大的River文档,它知道如何让相机和镜头通信,也许对当前的摄影实践几乎没有帮助。尽管如此,一些应用程序可能需要独立订购物镜的主要功能。撇开工业世界及其特殊机器不谈,在另一个品牌的图像采集系统上安装佳能光学元件是不可能的,而且是有罪的,无论是出于经济原因还是纯粹的技术原因,获得的组合提供了其他不可用的功能。https://blog.csdn.net/caoshiying/article/details/127609884?spm=1001.2014.3001.5502佳能镜头EOS系统EF协议逆向工程(二)逻辑分析仪测试_岬淢箫声的博客-CSDN博客本章描述了用于解密EF协议函数的思想和分析,如果其读数是可选的,则所获得结果的摘要将在专用章节中进行汇编,这仍然是正确理解EF协议函数的必要来源。随着函数的测试和逐步解码,它们的描述和列表中使用的注释将在过程中变得越来越精确,因为以前的分析或推理错误不会被强制纠正。所使用的逻辑分析仪是一个小型号的低成本8输入TTL USBEE AX Pro,所使用的软件是制造商的标准套件,可免费下载。软件不允许编辑或删除部分结果,某些读数或时钟意外激活,因为通电会导致SPI字解码不同步。https://blog.csdn.net/caoshiying/article/details/129057004?spm=1001.2014.3001.5502
数据结构
逻辑分析仪没有特别要求,某宝上的大部分逻辑分析仪可以用。数据格式要求很简单,举便如下:
; CSV, generated by libsigrok4DSL 0.2.0 on Fri Jul 29 10:17:48 2022
; Channels (3/16)
; Sample rate: 10 MHz
; Sample count: 50.896 M Samples
Time(s), CLK, DLC, DCL
0,1,1,1
0.0498275,1,1,0
0.0498285,1,1,1
0.0498697,1,1,0
0.049876,1,1,1
0.0499793,1,1,0
0.0499986,0,1,0
0.050005,1,1,0
分号开头表示注释,第一列是时间,这个时间是相对开始捕获的时间,用单词elapse表示列标题更合适。这款逻辑分析仪软件导出数据的表头就是这么写的,无所谓了。第二列是CLK信号,CLK是时钟的简写,搞硬件的同学是不是很熟悉呢?第三列是DLC信号。DLC是Data Lens to Camera的首字母缩写。第四列是DCL,DCL是Data Camera to Lens首字母缩写。所有信号用1表示高电平,0表示低电平。佳能相机的电平为3.3V。
我使用Qt写的解码工具,CMake工程代码如下:
cmake_minimum_required(VERSION 3.20)
project(TAMRON VERSION 1.0)find_package(Qt5 COMPONENTS Widgets REQUIRED PATHS $ENV{Qt515_DIR})
link_libraries(Qt5::Widgets)
add_link_options(/SUBSYSTEM:CONSOLE)
file(GLOB TAMRON_SRCS *.cpp *.h *.ui *.qrc *.rc)
add_executable(${PROJECT_NAME} ${TAMRON_SRCS})
target_compile_definitions(${PROJECT_NAME} PRIVATE $<IF:$<CONFIG:DEBUG>,CWDEBUG,CWNDEBUG>)
Qt515_DIR环境变量是必须的。
解码算法
算法是关键是解决ACK干扰。核心思路是寻找U型特征的连续信号。源代码只有一个main.cpp,代码如下:
#include <QApplication>
#include <QMainWindow>
#include <QFileDialog>
#include <QFile>
#include <QMessageBox>
#include <QTextStream>
#include <QDebug>
#include <QFileInfo>
#include <QMetaEnum>typedef struct _spi_signal_t
{uint32_t line_no;//行号double elapse;//消耗的时间,6位小数,单位为秒,存储化为usbool clk;//时钟是否高位bool dcl;//主机信号是否高位bool dlc;//从机信号是否高位
} spi_signal_t;typedef struct _spi_data_t
{uint32_t order;//序号uint32_t start_line;//信号起始行号uint32_t end_line;//信号结束行号uint8_t dcl;//主机命令uint8_t dlc;//从机返回int frame_no;//字节所属帧号bool bad;//是否发生丢失bit的情况double elapse;//消耗的时间double frequency;//实际通讯频率,存储为KHz
} spi_data_t;//信号数据中的U型结构,全部为引用指针,不管理内存
typedef struct _u_shape_t
{spi_signal_t *high_left;//U槽左端spi_signal_t *low_left;//U槽底左边spi_signal_t *low_right;//U槽底右边spi_signal_t *high_right;//U槽右端spi_signal_t *forward;//遍历前进到达的位置bool ok;//此U型结构是否能用int index_cursor;//信号列表遍历时当前的位置
} u_shape_t;typedef QSharedPointer<spi_signal_t> pspi_signal_t;
typedef QSharedPointer<spi_data_t> pspi_data_t;
typedef QSharedPointer<u_shape_t> pu_shape_t;
#define ZERR_CAPTION u8"系统错误"
#define ZOK_CAPTION u8"系统提示"//CSV文件文件转换为信号数据
QList<pspi_signal_t> resolve_csv(const QString &zcsv_path);
//信号数据转换为真实的主机与从机之间交换的信息
QList<pspi_data_t> resolve_signal(const QList<pspi_signal_t> &ps);
//保存信息
void save_spi_data(const QString &zcsv_path, const QList<pspi_data_t> &ds);
//寻找信号中的U形,返回下一个U形右端索引+1,返回值index_cursor与istart_cursor相等表示结束,ok为false表示出错
pu_shape_t find_u_shape(const QList<pspi_signal_t> &ps, int istart_cursor, int ilen);
//保存程序日志
void save_log(QtMsgType type, const QMessageLogContext &cxt, const QString &zlog);
//解析帧
void resolve_frame(QList<pspi_data_t> &ds);//入口函数
int main(int argc, char **argv)
{qInstallMessageHandler(save_log);QApplication app(argc, argv);auto zcsv_path = QFileDialog::getOpenFileName(nullptr,u8"选择一个CSV文件","D:/tamron");if (zcsv_path.isEmpty())return 1;auto ps = resolve_csv(zcsv_path);if (ps.isEmpty())return 2;auto ds = resolve_signal(ps);if (ds.isEmpty())return 3;resolve_frame(ds);save_spi_data(zcsv_path, ds);return 0;
}//CSV文件文件转换为信号数据
QList<pspi_signal_t> resolve_csv(const QString &zcsv_path)
{QFile f(zcsv_path);QList<pspi_signal_t> ps;if (!f.open(QFile::ReadOnly | QFile::Text)){QMessageBox::warning(nullptr, ZERR_CAPTION, f.errorString());return ps;}QTextStream ts(&f);ts.skipWhiteSpace();//DSView导出数据有5行注释和1行标头,应当跳过。for (short i = 0; i < 4; i++){auto zline = ts.readLine();if (ts.atEnd() || !zline.startsWith(";")){QMessageBox::warning(nullptr, ZERR_CAPTION, u8"无效的CSV文件。");break;}}ts.readLine();if (ts.atEnd())return ps;uint32_t iline = 6;while (!ts.atEnd()){QString zline = ts.readLine();if (zline.isEmpty())continue;QStringList cols = zline.split(u8",");if (cols.length() < 4){QMessageBox::critical(nullptr, ZERR_CAPTION, QString(u8"第%1行无效数据").arg(iline));return ps;}spi_signal_t r;r.line_no = iline++;if (iline >= UINT32_MAX){QMessageBox::warning(nullptr,ZERR_CAPTION,u8"input data amount exceed system capacity.");break;}r.elapse = cols[0].toDouble() * 1000000;r.clk = cols[1].toInt() != 0;r.dlc = cols[2].toInt() != 0;r.dcl = cols[3].toInt() != 0;pspi_signal_t p = QSharedPointer<spi_signal_t>::create(r);ps.append(p);}qInfo() << u8"合计" << ps.length() << u8"个信号\n";return ps;
}//寻找信号中的U形,返回下一个U形右端索引+1,返回值index_cursor与istart_cursor相等表示结束,ok为false表示出错
pu_shape_t find_u_shape(const QList<pspi_signal_t> &ps, int istart_cursor, int ilen)
{pu_shape_t pu(new u_shape_t{0,});u_shape_t *u = pu.data();u->index_cursor = istart_cursor;//1.寻找U槽//1.1.寻找下降沿,定位U槽左端while (u->index_cursor < ilen && ps[u->index_cursor]->clk)u->index_cursor++;u->forward = ps[u->index_cursor].data();if (u->index_cursor - 1 < 0){u->ok = false;u->index_cursor++;return pu;}if (u->index_cursor + 1 >= ilen){qWarning() << "data end on finding u->high_left and u->low_left";u->ok = false;return pu;}u->high_left = ps[u->index_cursor - 1].data();u->low_left = ps[u->index_cursor].data();u->forward = u->low_left;
#ifdef DEBUGqInfo() << "u begin: " << u->high_left->line_no;
#endifu->index_cursor++;if (u->index_cursor >= ilen){qWarning() << "data end on finding u->low_right";u->ok = false;return pu;}//1.2.寻找上升沿,定位U槽底有多长while (u->index_cursor < ilen && !ps[u->index_cursor]->clk)u->index_cursor++;u->low_right = ps[u->index_cursor - 1].data();u->forward = u->low_right;if (u->index_cursor >= ilen){qWarning() << "data end on finding u->high_right";u->ok = false;return pu;}//1.3.寻找下降沿,定位U槽右端//while (u->index_cursor < ilen && ps[u->index_cursor]->clk)// u->index_cursor++;u->high_right = ps[u->index_cursor].data();u->forward = u->high_right;//1.4.如果U槽的时间跨度大于28us则不是数据传输,暂不处理佳能中的拱门double fuspan1 = u->high_right->elapse - u->low_right->elapse;double fuspan2 = u->low_right->elapse - u->low_left->elapse;if (fuspan1 > 28 || fuspan1 < 0 || fuspan2 > 28 || fuspan2 < 0){qWarning() << "elapse time out: " << fuspan2 << ", " << fuspan1;u->ok = false;}elseu->ok = true;
#ifdef DEBUGif (u->ok)qInfo() << "u end: " << u->forward->line_no;
#endifreturn pu;
}//信号数据转换为真实的主机与从机之间交换的信息
QList<pspi_data_t> resolve_signal(const QList<pspi_signal_t> &ps)
{int icursor = 0;//遍历ps列表的索引int ilen = ps.length(); //总长度减2,双指针遍历int iorder = 1;QList<pspi_data_t> ds;if (ilen < 17){QMessageBox::critical(nullptr, ZERR_CAPTION, u8"数据量太少。");return ds;}while (icursor < ilen - 17){int ifor_cursor = icursor;//发现问题则回到U槽右端int iu_cursor = 0;pspi_data_t byte(new spi_data_t);pu_shape_t pu;byte->order = iorder;byte->frame_no = 0;byte->dcl = 0;byte->dlc = 0;byte->bad = false;byte->start_line = 0;byte->end_line = 0;byte->elapse = 0;byte->frequency = 0;qInfo() << "byte " << iorder << " begin: " << ps[icursor]->line_no;for (short i = 0; i < 8; i++){pu = find_u_shape(ps, ifor_cursor, ilen);ifor_cursor = pu->index_cursor;if (iu_cursor == 0)iu_cursor = ifor_cursor;if (pu->ok){
#ifdef DEBUGqInfo() << "byte " << iorder << " bit " << i << " at " << pu->low_left->line_no;
#endifif (byte->start_line == 0){byte->start_line = pu->low_left->line_no;byte->elapse = pu->low_left->elapse;}if (pu->high_right->dcl)byte->dcl |= 1 << (7 - i);if (pu->high_right->dlc)byte->dlc |= 1 << (7 - i);}else{byte->bad = true;break;}}if (byte->bad){icursor = iu_cursor;qWarning() << "byte " << iorder << " break: " << pu->forward->line_no;}else{icursor = ifor_cursor;byte->end_line = pu->forward->line_no;byte->elapse = pu->forward->elapse - byte->elapse;byte->frequency = 8000 / byte->elapse;qInfo() << "byte " << iorder << " end: " << pu->high_right->line_no;icursor++;//跳过第9个下降沿while (ps[icursor]->clk && icursor < ilen)icursor++;while (!ps[icursor]->clk && icursor < ilen)icursor++;iorder++;//80KHz下每个bit用时约为13us,1个byte不超过120usif (byte->elapse > 120)byte->bad = true;ds.append(byte);}}return ds;
}//保存信息
void save_spi_data(const QString &zcsv_path, const QList<pspi_data_t> &ds)
{//避免多次执行QChar的构造函数和析构函数static const QChar cfill('0');QFileInfo fi(zcsv_path);QString zresolve_path = fi.dir().absoluteFilePath(fi.baseName() + "resolve.csv");QFile f(zresolve_path);if (!f.open(QFile::ReadWrite | QFile::Text | QFile::Truncate)){QMessageBox::warning(nullptr, ZERR_CAPTION, f.errorString());return;}QTextStream ts(&f);ts << u8" command,sequence, start, end, dcl, dlc,elapse(us),frequency(KHz),bad\n";for (const pspi_data_t &d : ds){// char c = ' ';// if (d->dlc >= 0x20 && d->dlc <= 0x7E && d->dcl == 0)// c = (char)d->dlc;// if (c == ',')// c = ' ';QString zline = QString("%1,%2,%8,%9, %3, %4,%5,%6,%7\n").arg(d->frame_no, 8).arg(d->order, 8).arg(d->dcl, 2, 16, cfill).arg(d->dlc, 2, 16, cfill).arg(d->elapse, 10, 'f', 0).arg(d->frequency, 14, 'f', 0).arg(d->bad, 3).arg(d->start_line, 8).arg(d->end_line, 8);// .arg(c, 4);zline = zline.toUpper();ts << zline;}ts.flush();f.close();QMessageBox::information(nullptr, ZOK_CAPTION, u8"数据转换完成。");qInfo() << u8"数据转换完成。";
}void save_log(QtMsgType type, const QMessageLogContext &cxt, const QString &zlog)
{static QFile f;static QTextStream output(stdout);static QTextStream ts;if (!f.isOpen()){QDir d(QApplication::applicationDirPath());f.setFileName(d.absoluteFilePath("main.log"));if (!f.open(QFile::Append | QFile::Text | QFile::ReadWrite)){QMessageBox::warning(nullptr, ZERR_CAPTION, u8"无法打开日志文件。");return;}ts.setDevice(&f);ts.setAutoDetectUnicode(true);}QString ztype;switch (type){case QtDebugMsg:ztype = u8"DEBG";break;case QtWarningMsg:ztype = u8"WARN";break;case QtCriticalMsg:ztype = u8"CRIT";break;case QtFatalMsg:ztype = u8"FATA";break;case QtInfoMsg:ztype = u8"INFO";break;default:Q_ASSERT(false);break;}ts << ztype << ", " << zlog.toUtf8() << "\n";ts.flush();output << ztype << " " << zlog.toUtf8() << "\n";output.flush();
}//解析帧
void resolve_frame(QList<pspi_data_t> &ds)
{if (ds.length() < 2)return;int ilen = ds.length();int iframe = 0;for (int i = 0; i < ilen; i++){if (ds[i]->dcl > 0)iframe++;ds[i]->frame_no = iframe;}
}
解码效果
如下图所示
解码结果中通信频率、0A与AA应答信号、0x06与0x05的转动信号与实际匹配,说明解码成功。如果想要更多的通信规律,请与我私聊。下一篇讲解常见的指令。
相关文章:
佳能镜头EOS系统EF协议逆向工程(三)解码算法
目录 数据结构 解码算法 解码效果 这篇文章基于上两篇文章继续, 佳能镜头EOS系统EF协议逆向工程(一)转接环电路设计_佳能ef自动对焦协议_岬淢箫声的博客-CSDN博客本文属于专栏——工业相机。此专栏首先提供我人工翻译的法语文档部分&…...
搞互联网吧,线下生意真不是人干的
搞互联网吧,线下生意真不是人干的 应该是正月初几里吧,好巧不巧的被迫去参加了一下我们初中同学的聚会。其实毕业这么多年,无论大学,高中还是中学,类似的聚会我都是能躲则躲,有特别想见的同学也都是私下单…...
MySQL性能调优与设计——MySQL中的索引
MySQL中的索引 InnoDB存储引擎支持以下几种常见索引:B树索引、全文索引、哈希索引,其中比较关键的是B树索引。 B树索引 InnoDB中的索引自然也是按照B树来组织的,B树的叶子节点用来存放数据。 聚集索引/聚簇索引 InnoDB中使用了聚集索引&…...
这5个代码技巧,让我的 Python 加速了很多倍
Python作为一种功能强大的编程语言,因其简单易学而受到很多初学者的青睐。它的应用领域又非常广泛:科学计算、游戏开发、爬虫、人工智能、自动化办公、Web应用开发等等。 而在数据科学领域中,Python 是使用最广泛的编程语言,并且…...
Sphinx+Scws 搭建千万级准实时搜索应用场景详解
目标: 一、搭建准确的千万级数据库的准实时搜索(见详情) 二、实现词语高亮(客户端JS渲染,服务器端渲染,详见7.3) 三、实现搜索联想(输入框onchange,ajax请求搜索,取10条在…...
kafka缩容后,使用tcpdump抓包找到还在连接的用户
1、使用tcpdump抓包监控端口9092 tcpdump src port 9092 16:23:27.680835 IP host01.XmlIpcRegSvc > 192.168.168.1.36199: Flags [R.], seq 0, ack 1493547965, win 0, length 0 16:23:27.681877 IP host01.XmlIpcRegSvc > 192.168.168.2.50416: Flags [R.], seq 0, ac…...
Spring
Spring Spring 是什么? Spring 是于 2003 年兴起的一个轻量级的,IOC 和 AOP 的 Java 开发框架,它 是为了简化企业级应用开发而生的。 Spring有几大特点如下 轻量级的 Spring 框架使用的 jar 都比较小,一般在 1M 以下或者几百 kb。Spring 核 心功能…...
vue2版本《后台管理模式》(中)
文章目录前言一、创建一个文件夹 utils 里面新增一个 setToken.js 文件(设置token验证)二 、创建一个api文件夹 新增 service.js (axios拦截器)三、在api文件夹里 新增一个 api.js 来接收数据(把api封装哪里需要某项数据直接引入就…...
网络游戏开发-服务器篇
1.网络 网络分为弱联网和强联网。 1.弱联网 弱联网是客户端连接到服务端发送一个请求,然后由服务端回应一个内容,这是单向传输的方式,服务端是无法主动给客户端发送消息的,服务端相应请求之后会自动关闭连接。 缺点:传输采用明文,通过抓包可以看到明文信息,安全性不太…...
智慧校园源码:电子班牌,支持手机移动端以及web端对班牌设备的管控
▶ 智慧校园系统有源码,有演示! (电子班牌)设备管理: 1、 管理员查看全校电子班牌设备信息:含有(班级信息、软件版本、设备型号、开关机信息、班牌截屏信息、教室编号、设备ID、设备描述、在线状态、离线状…...
研报精选230216
目录 【行业230216东吴证券】环保行业月报:2023M1环卫新能源渗透率大增至11.91%,上海地区渗透率高达77%【行业230216国元证券】国元新食饮:一图君:22年白酒产量:同降6.2%【行业230216浙商证券】农林牧渔点评报告&#…...
在华为MateBook Ego的arm windows 11上安装hyper-V虚拟机
入手一台华为matebook Ego的笔记本,由于想要测试一些arm的驱动功能,经常会把系统搞蓝屏,于是想安装一个虚拟机,于是试了vmware ,visual-box,由于本机是arm架构上面两个软件都无法进行正常安装,可能是由于有…...
OpenCV Canny边缘检测
本文是OpenCV图像视觉入门之路的第13篇文章,本文详细的介绍了Canny边缘检测算子的各种操作,例如:Canny算子进行边缘检测等操作。 Canny函数是OpenCV中用于执行边缘检测的函数之一,其参数包括: threshold1:…...
C#.Net正则表达式学习笔记
C#.Net正则表达式学习笔记 在处理字符串时,你会经常有查找符合特定条件的字符串的需求,比如判断一串电话号码是否符合格式、一个邮箱是否符合格式、一个密码是否包含了字母大小写等等。 正则表达式(Regular expressions)用于匹配文本,使用一…...
矩阵理论复习(十二)
已知方阵A的不变因子: 求谱半径求矩阵级数判断矩阵幂级数的收敛性 若矩阵B的某个算子范数小于1,则I-B可逆。 矩阵分析 任何相容矩阵范数都存在与之相容的向量范数。 盖尔圆盘定理一的证明 椭圆范数的证明 若||.||是Cm上的向量范数,A为…...
大数据框架之Hadoop:HDFS(七)HDFS 2.X新特性
7.1集群间数据拷贝 scp实现两个远程主机之间的文件复制 scp -r hello.txt roothadoop103:/root/hello.txt // 推 push scp -r roothadoop103:/root/hello.txt hello.txt // 拉 pull scp -r roothadoop103:/root/hello.txt roothadoop104:/root //是通过本地主机中…...
Fluent工作目录
1 工作目录定义工作目录(working directory)是一种文件存储路径设置方式。基于工作目录的方法,写文件时只需要指定文件名,而不需要指定完全的文件路径,从而简化程序编写,对不同操作系统环境有更好的适应性。…...
Learning C++ No.10【STL No.2】
引言: 北京时间:2023/2/14/23:18,放假两个月,没有锻炼,今天去跑了几圈,一个字,累,感觉人都要原地升天了,所以各位小伙伴,准确的说是各位卷王,一定…...
【java 高并发编程之JUC】2w字带你JUC从入门到精通
点击查看脑图目录地址,实时更新 1 什么是 JUC 1.1 JUC 简介 在 Java 中,线程部分是一个重点,本篇文章说的 JUC 也是关于线程的。JUC 就是 java.util .concurrent 工具包的简称。这是一个处理线程的工具包,JDK 1.5 开始出现的。 1.2 进程与…...
QCon演讲实录(下):多云管理关键能力实现与解析-AppManager
在上篇中,我们已经基本了解了多云管理。现在,我们将深入探讨多云管理关键能力实现:AppManager。 什么是AppManager? 上面我们讲了理论、我们自己使用的交付流程和整体架构,下面我们进入关键能力实现与解析的环节&…...
刚刚退出了一个群,关于在要麒麟OS上运行Labview
年龄过了45,看问题,与以前不太一样了。 觉得浪费时间的事,宁可发呆,也不会参和。 竟然一个群里在讨论如何满足客户的需求:麒麟OS上运行Labview。 然后直接退了群。 这种问题,我觉得可能 发在csdn上&…...
el-uploader 文件上传后,又被修改,无法提交到后端 ERR_UPLOAD_FILE_CHANGED
problem 文件上传后,又被修改,无法提交到后端 具体步骤: 文件上传本地文件打开并修改保存提交ajax 这个问题不仅仅局限于el-uploader,是一个普遍性的问题 导致的问题 问题1:提交请求时,控制台报错 net…...
利用Eigen实现点云体素滤波
目录 前言 一、算法原理 二、代码实现 1.头文件 2.源文件 三、效果展示 前言 体素滤波原理简单,是常用的...
linux高级命令之多进程的使用
多进程的使用学习目标能够使用多进程完成多任务1 导入进程包#导入进程包import multiprocessing2. Process进程类的说明Process([group [, target [, name [, args [, kwargs]]]]])group:指定进程组,目前只能使用Nonetarget:执行的目标任务名…...
CSS 圆角边框 盒子阴影 文字阴影
目录 1.圆角边框(重点) 2.盒子阴影(box-shadow) 3.文字阴影(text-shadow) 1.圆角边框(重点) border-radius 属性用于设置元素的外边框圆角。 语法: border-radius: l…...
python简单解析打印onnx模型信息
当我们加载了一个ONNX之后,我们获得的就是一个ModelProto,它包含了一些版本信息,生产者信息和一个GraphProto。在GraphProto里面又包含了四个repeated数组,它们分别是node(NodeProto类型),input(ValueInfoProto类型)&a…...
UE4 编写着色器以及各种宏的理解
参考链接:如何为 UE4 添加全局着色器(Global Shaders) - Unreal Enginehttps://docs.unrealengine.com/5.1/zh-CN/adding-global-shaders-to-unreal-engine/如何为 UE4 添加全局着色器(Global Shaders) - Unreal Engin…...
小笔记:Python 使用字符串调用函数
小笔记:Python中如何使用字符串调用函数/方法?jcLee95:https://blog.csdn.net/qq_28550263?spm1001.2101.3001.5343 本文地址:https://blog.csdn.net/qq_28550263/article/details/111874476 邮箱 :291148484163.co…...
红黑树的原理+实现
文章目录红黑树定义性质红黑树的插入动态效果演示代码测试红黑树红黑树 定义 红黑树是一个近似平衡的搜索树,关于近似平衡主要体现在最长路径小于最短路径的两倍(我认为这是红黑树核心原则),为了达到这个原则,红黑树所…...
用于非线性时间序列预测的稀疏局部线性和邻域嵌入(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
AV91做爰免费网站/湖南长沙今日疫情
介绍了 JavaScript if/else 决策概念的基础知识。 使用JavaScript制定决策 JavaScript 的一个已知功能是决策功能。 可以使用它来控制代码的运行顺序,并使其更易于重复使用且更可靠。 布尔运算符 如果要通过代码定义不同的路径,请使用运算符和布尔变量…...
无锡新吴区建设局网站/百度公司名称
Qt 实现文件校验码生成器(内附源码) 该软件是基于 CertUtil 的一个文件文件校验码生成,旨在提高下载程序的一个安全系数,防止黑客攻击网站后,将携带病毒的程序放在下载链接上,当用户使用程序时,…...
wordpress 百度seo/百度推广助手电脑版
每天都在生成太多数据。尽管有时我们可以使用Rapids或Parallelization等工具来管理大数据,但如果您使用的是TB级数据,Spark是一个很好的工具。尽管这篇文章解释了如何使用RDD和基本的Dataframe操作,但是我在使用PySpark Dataframes时错过了很…...
中小企业网站查询/网站维护主要做什么
传统超级计算机:“看上去很美”“盲目追求Linpack排名的炒作、无休止的价格战、热衷堆砌集群硬件规模,把软件和应用全推给客户、忽视对HPC应用人才培养,掠夺性策略..”在3月2日浪潮“倚天”万亿次桌面超级计算机发布会上,浪潮高性…...
做资源下载网站用什么工具/做运营需要具备什么能力
可以通过使用 CCMSetup.exe 和 /Uninstall 开关从计算机卸载 Configuration Manager 2007 客户端软件。在单台计算机上从命令提示符运行 CCMSetup.exe 或使用 Configuration Manager 2007 软件分发以通过使用脚本在计算机集合上卸载客户端。 方法如下: 1、以管理员身…...
网站如何做百度才会收录/厦门网站设计公司
原题链接 思路: ASCII码中32代表的就是空格’ 。此题不需要加逗号或者加空格 #include <stdio.h>int main() {printf("%c%c%c%c%c%c%c%c%c%c%c%c\n",73,32,99,97,110,32,100,111,32,105,116,33);return 0; }...