C/C++ 通过SQLiteSDK增删改查
SQLite,作为一款嵌入式关系型数据库管理系统,一直以其轻量级、零配置以及跨平台等特性而备受青睐。不同于传统的数据库系统,SQLite是一个库,直接与应用程序一同编译和链接,无需单独的数据库服务器进程,实现了数据库的零配置管理。这种设计理念使得SQLite成为许多嵌入式系统、移动应用和小型项目中的首选数据库引擎。
SQLite的特点包括:
- 嵌入式数据库引擎: SQLite 是一个嵌入式数据库引擎,意味着它是一个库,与应用程序一同编译和链接,而不是作为独立的进程运行。
- 零配置: 无需配置或管理。SQLite 不需要一个独立的数据库服务器进程,所有的操作都是直接在存储在文件中的数据库上执行。
- 轻量级: SQLite 是一个轻量级的数据库,相对于一些其他数据库管理系统来说,它的内存占用和资源消耗相对较小。
- 支持 SQL: SQLite 支持大部分标准的 SQL 语法,并提供了事务支持,包括隔离级别和回滚。
- 跨平台: SQLite 可以在各种操作系统上运行,包括 Windows、Linux、macOS 和其他嵌入式系统。
- 自给自足: SQLite 数据库是一个单一的磁盘文件,整个数据库被存储在一个文件中,这使得备份、复制或传输数据库变得非常容易。
- 开源: SQLite 是一个开源项目,采用公共领域授权(Public Domain License),可以在商业和非商业项目中免费使用。
SQLite 数据库以其独特的自给自足特性脱颖而出,整个数据库被存储在一个单一的磁盘文件中,使得备份、复制或传输数据库变得异常简单。而作为一款开源项目,SQLite采用了公共领域授权,可以在商业和非商业项目中免费使用。
- SQLiteSDK下载:https://download.csdn.net/download/lyshark_csdn/88568197
由于该数据库的小巧和简洁所以在使用上也非常容易,当读者下载好附件以后会看到如下图所示的文件;
使用时只需要将sqlite3.h
与sqlite3.c
文件导入到项目中并使用#include "sqlite3.h"
即可,无需做其他配置,图中的sqlite3.dll
是动态库,sqlite3.exe
则是一个命令行版本的数据库可在测试时使用它。
打开与关闭库
sqlite3_open
用于打开或创建一个 SQLite 数据库文件。该函数的原型如下:
int sqlite3_open(const char *filename, /* Database filename (UTF-8) */sqlite3 **ppDb /* OUT: SQLite db handle */
);
filename
: 要打开或创建的 SQLite 数据库文件的路径。如果文件不存在,将会创建一个新的数据库文件。ppDb
: 用于存储 SQLite 数据库句柄(handle)的指针。SQLite 数据库句柄是与一个打开的数据库关联的结构,它在后续的 SQLite 操作中用作标识。
该函数返回一个整数值,代表函数的执行状态。如果函数成功执行,返回 SQLITE_OK
。如果有错误发生,返回一个表示错误代码的整数值。可以通过 sqlite3_errmsg
函数获取更详细的错误信息。
sqlite3_close
用于关闭数据库连接的函数。其原型如下:
int sqlite3_close(sqlite3*);
sqlite3
: 要关闭的 SQLite 数据库连接的句柄。
该函数返回一个整数值,用于表示函数的执行状态。如果函数成功执行,返回 SQLITE_OK
。如果有错误发生,返回一个表示错误代码的整数值。
使用 sqlite3_close
函数可以释放与数据库连接相关的资源,并确保数据库文件被正确关闭。在关闭数据库连接之前,应该确保已经完成了所有需要执行的 SQL 语句,并在需要的情况下检查执行结果。
// 打开数据库并返回句柄
sqlite3* open_database(std::string database_name)
{int ref =-1;sqlite3 *db = 0;ref = sqlite3_open(database_name.c_str(), &db);if (ref == SQLITE_OK)return db;return false;
}// 关闭数据库
bool close_database(sqlite3 *db)
{int ref = sqlite3_close(db);if (ref == SQLITE_OK)return true;return false;
}
执行查询语句
sqlite3_exec
用于执行 SQL 语句的高级接口函数。它的原型如下:
int sqlite3_exec(sqlite3* db, /* Database handle */const char* sql, /* SQL statement, UTF-8 encoded */int (*callback)( /* Callback function */void*, /* Callback parameter */int, /* Number of columns in the result set */char**, /* Array of column values */char** /* Array of column names */),void* callback_param, /* 1st argument to callback function */char** errmsg /* Error msg written here */
);
db
: SQLite 数据库连接的句柄。sql
: 要执行的 SQL 语句,以 UTF-8 编码。callback
: 回调函数,用于处理查询结果的每一行数据。callback_param
: 传递给回调函数的参数。errmsg
: 用于存储错误消息的指针。
sqlite3_exec
函数执行一个或多个 SQL 语句,并对每一条语句的执行结果调用指定的回调函数。回调函数的原型如下:
int callback(void* callback_param, /* 参数,由 sqlite3_exec 传递给回调函数 */int num_columns, /* 结果集中的列数 */char** column_values, /* 指向结果集中当前行的列值的数组 */char** column_names /* 指向结果集中列名的数组 */
);
callback_param
: 回调函数的参数,由sqlite3_exec
传递给回调函数。num_columns
: 结果集中的列数。column_values
: 指向结果集中当前行的列值的数组。column_names
: 指向结果集中列名的数组。
回调函数返回一个整数,用于指示是否继续执行后续的 SQL 语句。如果回调函数返回非零值,sqlite3_exec
将停止执行 SQL,并立即返回。
sqlite3_prepare_v2
用于准备 SQL 语句的接口函数。它的原型如下:
int sqlite3_prepare_v2(sqlite3* db, /* Database handle */const char* sql, /* SQL statement, UTF-8 encoded */int sql_len, /* Length of SQL statement in bytes, or -1 for zero-terminated */sqlite3_stmt** stmt, /* OUT: Statement handle */const char** tail /* OUT: Pointer to unused portion of SQL statement */
);
db
: SQLite 数据库连接的句柄。sql
: 要准备的 SQL 语句,以 UTF-8 编码。sql_len
: SQL 语句的长度,如果为 -1,则表示 SQL 语句以 null 结尾。stmt
: 用于存储准备好的语句句柄的指针。tail
: 用于存储未使用的 SQL 语句的指针。
sqlite3_prepare_v2
函数用于将 SQL 语句编译成一个 SQLite 语句对象(prepared statement)。这个对象可以被多次执行,每次执行时可以绑定不同的参数。stmt
参数将用于存储编译后的语句的句柄,以供后续的操作。
sqlite3_step
执行预编译 SQL 语句的接口函数。它的原型如下:
int sqlite3_step(sqlite3_stmt*);
sqlite3_stmt*
: 由sqlite3_prepare_v2
预编译的 SQL 语句的句柄。
sqlite3_step
函数用于执行由 sqlite3_prepare_v2
预编译的 SQL 语句。在执行过程中,可以通过不断调用 sqlite3_step
来逐行获取查询结果,直到结果集结束。对于非查询语句(如 INSERT
、UPDATE
、DELETE
),sqlite3_step
函数执行一次即可完成操作。
该函数的返回值表示执行的结果,可能的返回值包括:
SQLITE_ROW
: 成功获取一行数据。SQLITE_DONE
: 执行完成,没有更多的数据可用(用于非查询语句)。- 其他错误码,表示执行过程中出现了错误。
sqlite3_column_text
用于获取查询结果集中某一列的文本值。其原型为:
const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
sqlite3_stmt*
: 由sqlite3_prepare_v2
预编译的 SQL 语句的句柄。int iCol
: 列的索引,从0开始。
该函数返回指向字符串值的指针,该字符串值是查询结果集中指定列的文本表示。需要注意的是,返回的指针指向 SQLite 内部的存储区,应该在使用完之后尽早释放资源。
sqlite3_column_int
用于获取查询结果集中某一列的整数值。其原型为:
int sqlite3_column_int(sqlite3_stmt*, int iCol);
sqlite3_stmt*
: 由sqlite3_prepare_v2
预编译的 SQL 语句的句柄。int iCol
: 列的索引,从0开始。
该函数返回查询结果集中指定列的整数表示。需要注意的是,如果该列不是整数类型,或者包含的数据无法转换为整数,那么返回的结果可能不是有效的整数值。
sqlite3_finalize
用于释放一个预备语句对象(prepared statement)。在使用 sqlite3_prepare_v2
函数准备 SQL 语句后,需要使用 sqlite3_finalize
来释放相应的语句对象。
该函数的原型为:
int sqlite3_finalize(sqlite3_stmt *pStmt);
sqlite3_stmt *pStmt
: 指向要释放的语句对象的指针。
该函数返回 SQLITE_OK
表示成功,返回其他错误码表示失败。
// 执行SQL语句
bool exec_sql(sqlite3 *db, char *sql)
{char *error_code = 0;int ref = sqlite3_exec(db, sql, 0, 0, &error_code);if (ref == SQLITE_OK){return true;}return false;
}// 插入数据
bool insert_data(sqlite3 *db, char *sql)
{sqlite3_stmt *stmt = 0;// 插入前检查语句合法性, -1自动计算SQL长度int ref = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);if (ref == SQLITE_OK){sqlite3_step(stmt); // 执行语句sqlite3_finalize(stmt); // 清理语句句柄return true;}sqlite3_finalize(stmt);return false;
}// 查询数据集
bool select_data(sqlite3 *db, char *sql)
{sqlite3_stmt *stmt = 0;int ref = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);if (ref == SQLITE_OK){// 每调一次sqlite3_step()函数,stmt就会指向下一条记录while (sqlite3_step(stmt) == SQLITE_ROW){// 取出第1列字段的值const unsigned char *name = sqlite3_column_text(stmt, 1);// 取出第2列字段的值int age = sqlite3_column_int(stmt, 2);std::cout << "姓名: " << name << " 年龄: " << age << std::endl;}}else{sqlite3_finalize(stmt);return false;}sqlite3_finalize(stmt);return true;
}
调用查询语句
创建数据库
首先打开了名为 "database.db"
的 SQLite 数据库,并创建了一个名为 "LySharkDB"
的表,该表格包含了id、name、age
和 msg
四个字段。随后,通过执行 SQL 语句创建了这个表格。最后,关闭了数据库连接。这段代码主要用于数据库初始化操作,确保了数据库中包含了指定的表格结构。
int main(int argc, char *argv[])
{sqlite3* open_db = open_database("database.db");if (open_db != false){bool create_table_ref;std::string sql = "create table LySharkDB(""id int auto_increment primary key,""name char(30) not null," "age int not null,""msg text default null"")";// 运行创建表操作char run_sql[1024] = { 0 };strcpy(run_sql, sql.c_str());create_table_ref = exec_sql(open_db, run_sql);}close_database(open_db);std::system("pause");return 0;
}
上述代码运行后则可以创建一个数据库database.db
表名为LySharkDB
读者可以使用数据库工具打开该表,其结构如下所示;
插入数据测试
创建数据库后,接着就是插入数据测试,插入时可以使用insert_data
,如下代码项数据库中插入5条记录;
int main(int argc, char *argv[])
{sqlite3* open_db = open_database("./database.db");if (open_db != false){bool create_table_ref;// 运行插入记录if (create_table_ref == true){bool insert_ref = 0;insert_ref = insert_data(open_db, "insert into LySharkDB(id,name,age,msg) values(1,'lyshark',1,'hello lyshark');");insert_ref = insert_data(open_db, "insert into LySharkDB(id,name,age,msg) values(2,'guest',2,'hello guest');");insert_ref = insert_data(open_db, "insert into LySharkDB(id,name,age,msg) values(3,'admin',3,'hello admin');");insert_ref = insert_data(open_db, "insert into LySharkDB(id,name,age,msg) values(4,'wang',4,'hello wang');");insert_ref = insert_data(open_db, "insert into LySharkDB(id,name,age,msg) values(5,'sqlite',5,'hello sql');");if (insert_ref == true){std::cout << "插入完成" << std::endl;}}}close_database(open_db);std::system("pause");return 0;
}
插入后,打开数据库管理软件,可看到插入后的记录;
查询与删除数据
而查询删除与增加记录,我们这里直接使用exec_sql()
函数,通过传入不同的SQL语句实现。
int main(int argc, char *argv[])
{sqlite3* open_db = open_database("./database.db");if (open_db != false){// 删除记录bool delete_ref = exec_sql(open_db, "delete from LySharkDB where id = 5;");if (delete_ref == true){std::cout << "删除完成." << std::endl;}// 更新记录bool update_ref = exec_sql(open_db, "update LySharkDB set name='lyshark' where id = 4;");if (update_ref == true){std::cout << "更新完成." << std::endl;}// 查询数据bool select_ref = select_data(open_db, "select * from LySharkDB;");if (select_ref == true){std::cout << "查询完毕." << std::endl;}}close_database(open_db);std::system("pause");return 0;
}
执行更新后的表记录如下所示;
查询区间数据
首先创建一些数据集,这里通过循环生成并插入数据,如下代码中新建一个TimeDB
数据表,其中有三个字段uid,host_time,cpu_value
;
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <time.h>
#include "sqlite3.h"#include <boost/lexical_cast.hpp>
#include <boost/format.hpp>using namespace std;
using namespace boost;// 获取本地时间日期
std::string get_local_datetime()
{char ct[80];time_t tt;struct tm *tblock;tt = time(NULL);tblock = localtime(&tt);strftime(ct, sizeof(ct), "%Y-%m-%d %H:%M:%S", tblock);return ct;
}// 初始化创建表结构
void Init_Database()
{sqlite3* open_db = open_database("./database.db");if (open_db != false){bool create_table_ref;std::string sql ="create table TimeDB(""uid primary key,""host_time char(128) not null,""cpu_value int not null"");";char run_sql[1024] = { 0 };strcpy(run_sql, sql.c_str());exec_sql(open_db, run_sql);}close_database(open_db);
}// 批量生成时间字符串并插入数据表
void Insert_Test()
{sqlite3* open_db = open_database("./database.db");for (int x = 0; x < 1000; x++){// 获取本地日期时间std::string local_times = get_local_datetime();std::string format_string = boost::str(boost::format("insert into TimeDB(uid,host_time,cpu_value) values(%d,'%s',%d);") % x %local_times %x);std::cout << "执行SQL: " << format_string << std::endl;char run_sql[1024] = { 0 };strcpy(run_sql, format_string.c_str());insert_data(open_db, run_sql);_sleep(1000);}close_database(open_db);
}int main(int argc, char *argv[])
{sqlite3* open_db = open_database("./database.db");Init_Database();Insert_Test();std::system("pause");return 0;
}
如下是五分钟的模拟数据;
当有了数据则再查询,代码中Select_Time_List
函数演示了如何通过时间查询一个区间的数据,并返回一个容器列表给被调用者使用,查询代码如下所示;
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <time.h>
#include "sqlite3.h"#include <boost/lexical_cast.hpp>
#include <boost/format.hpp>using namespace std;
using namespace boost;// 打开数据库并返回句柄
sqlite3* open_database(std::string database_name)
{int ref = -1;sqlite3 *db = 0;ref = sqlite3_open(database_name.c_str(), &db);if (ref == SQLITE_OK)return db;return false;
}// 关闭数据库
bool close_database(sqlite3 *db)
{int ref = sqlite3_close(db);if (ref == SQLITE_OK)return true;return false;
}// 执行SQL语句
bool exec_sql(sqlite3 *db, char *sql)
{char *error_code = 0;int ref = sqlite3_exec(db, sql, 0, 0, &error_code);if (ref == SQLITE_OK){return true;}return false;
}// 插入数据
bool insert_data(sqlite3 *db, char *sql)
{sqlite3_stmt *stmt = 0;// 插入前检查语句合法性, -1自动计算SQL长度int ref = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);if (ref == SQLITE_OK){sqlite3_step(stmt); // 执行语句sqlite3_finalize(stmt); // 清理语句句柄return true;}sqlite3_finalize(stmt);return false;
}// 查询数据集
bool select_data(sqlite3 *db, char *sql)
{sqlite3_stmt *stmt = 0;int ref = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);if (ref == SQLITE_OK){// 每调一次sqlite3_step()函数,stmt就会指向下一条记录while (sqlite3_step(stmt) == SQLITE_ROW){// 取出第1列字段的值const unsigned char *name = sqlite3_column_text(stmt, 1);// 取出第2列字段的值int age = sqlite3_column_int(stmt, 2);std::cout << "姓名: " << name << " 年龄: " << age << std::endl;}}else{sqlite3_finalize(stmt);return false;}sqlite3_finalize(stmt);return true;
}// 获取本地时间日期
std::string get_local_datetime()
{char ct[80];time_t tt;struct tm *tblock;tt = time(NULL);tblock = localtime(&tt);strftime(ct, sizeof(ct), "%Y-%m-%d %H:%M:%S", tblock);return ct;
}// 初始化创建表结构
void Init_Database()
{sqlite3* open_db = open_database("./database.db");if (open_db != false){bool create_table_ref;std::string sql ="create table TimeDB(""uid primary key,""host_time char(128) not null,""cpu_value int not null"");";char run_sql[1024] = { 0 };strcpy(run_sql, sql.c_str());exec_sql(open_db, run_sql);}close_database(open_db);
}// 批量生成时间字符串并插入数据表
void Insert_Test()
{sqlite3* open_db = open_database("./database.db");for (int x = 0; x < 1000; x++){// 获取本地日期时间std::string local_times = get_local_datetime();std::string format_string = boost::str(boost::format("insert into TimeDB(uid,host_time,cpu_value) values(%d,'%s',%d);") % x %local_times %x);std::cout << "执行SQL: " << format_string << std::endl;char run_sql[1024] = { 0 };strcpy(run_sql, format_string.c_str());insert_data(open_db, run_sql);_sleep(1000);}close_database(open_db);
}// 查询时间区间并返回 传入开始时间与结束时间,过滤出特定的记录
bool Select_Time_List(sqlite3 *db, std::vector<std::map<std::string, int>> &time_ref, std::string start_time, std::string end_time)
{sqlite3_stmt *stmt = 0;std::string format_string = boost::str(boost::format("select * from TimeDB where host_time >= '%s' and host_time <= '%s';") % start_time %end_time);char run_sql[1024] = { 0 };strcpy(run_sql, format_string.c_str());int ref = sqlite3_prepare_v2(db, run_sql, -1, &stmt, 0);if (ref == SQLITE_OK){while (sqlite3_step(stmt) == SQLITE_ROW){std::map < std::string, int > ptr;// 取出第一个和第二个字段const unsigned char *time_text = sqlite3_column_text(stmt, 1);const int cpu_value = sqlite3_column_int(stmt, 2);// 放入一个map容器中ptr[boost::lexical_cast<std::string>(time_text)] = cpu_value;time_ref.push_back(ptr);}sqlite3_finalize(stmt);return true;}sqlite3_finalize(stmt);return false;
}int main(int argc, char *argv[])
{sqlite3* open_db = open_database("./database.db");//Init_Database();//Insert_Test();// 查询 2023-11-25 19:52:31 - 2023-11-25 19:53:35 区间内的所有的负载情况std::vector<std::map<std::string, int>> db_time;bool is_true = Select_Time_List(open_db, db_time, "2023-11-25 19:52:31", "2023-11-25 19:53:35");if (is_true == true){for (int x = 0; x < db_time.size(); x++){// 输出该区间内的数据std::map < std::string, int>::iterator ptr;for (ptr = db_time[x].begin(); ptr != db_time[x].end(); ptr++){std::cout << "时间区间: " << ptr->first << " CPU利用率: " << ptr->second << std::endl;}}}std::system("pause");return 0;
}
例如代码中我们查询2023-11-25 19:52:31 - 2023-11-25 19:53:35
这个区间内的数据信息,并返回一个map
容器给被调用者,运行效果如下所示;
相关文章:

C/C++ 通过SQLiteSDK增删改查
SQLite,作为一款嵌入式关系型数据库管理系统,一直以其轻量级、零配置以及跨平台等特性而备受青睐。不同于传统的数据库系统,SQLite是一个库,直接与应用程序一同编译和链接,无需单独的数据库服务器进程,实现…...

软件测评中心进行安全测试有哪些流程?安全测试报告如何收费?
在当今数字化时代,软件安全测试是每个软件开发团队都不能忽视的重要环节。安全测试是指对软件产品进行系统、全面的安全性评测与检测的过程。它旨在发现并修复软件中存在的漏洞和安全隐患,以确保软件能够在使用过程中保护用户的数据和隐私不被非法访问和…...

20年的大厂技术总监给云原生从业者的建议
云原生是一种构建和运行应用程序的方法,是一套技术体系和方法论。云原生的英文可拆解为Cloud和Native。Cloud表示应用程序位于云中,而不是传统的数据中心;Native表示应用程序设计之初就被考虑部署到云的环境,为云而生,…...
音视频项目—基于FFmpeg和SDL的音视频播放器解析(二十)
介绍 在本系列,我打算花大篇幅讲解我的 gitee 项目音视频播放器,在这个项目,您可以学到音视频解封装,解码,SDL渲染相关的知识。您对源代码感兴趣的话,请查看基于FFmpeg和SDL的音视频播放器 如果您不理解本…...

京东数据分析:2023年10月京东彩妆销售大数据采集
鲸参谋监测的京东平台10月份彩妆市场销售数据已出炉! 鲸参谋数据显示,今年10月份,京东平台上彩妆市场的销量将近430万,环比增长约21%,同比下滑约3%;销售额将近5.8亿,环比增长约7%,同…...
uniapp-微信授权登录
目录 一、微信授权登录的介绍 1.用户在微信内点击登录按钮,跳转到授权页面; 2.用户同意授权后,返回授权码给开发者服务器; 3.开发者服务器通过授权码向微信服务器发送请求,获取用户信息; 4.微信服务器…...
在vscode下将ipynb文件转成pdf的方法
正常情况下,可以在vscode的ipynb界面点击上面的三个点,里面有export,可以选择直接输出html和pdf,但是需要latex,由于按扎u安装麻烦,所以我换了一种方法。 ----------------------------------------------…...
css之选择第一个或最后一个元素、第n个标签、选择偶数或奇数标签、选择最后n个标签、等差数列标签的选择、first、last、nth、child
MENU first-child选择列表中的第一个标签last-child选择列表中的最后一个标签nth-child(n)选择列表中的第n个标签nth-child(2n)选择列表中的偶数位标签nth-child(2n-1)选择列表中的奇数位标签nth-child(nm)选择从第m个到最后一个标签nth-child(-nm)选择从第1个到第m个nth-last-…...

CSS实现三角形
CSS实现三角形 前言第一种:bordertransparent第二种borderrgb使用unicode字符 前言 本文讲解三种实现三角形的方式,并且配有图文以及代码解说。那么好,本文正式开始。 第一种:bordertransparent border是边框,而transparent是透明的颜色&a…...
mysql 与 Oracle 的区别,oracle 与 mysql分页查询的区别
文章目录 mysql 与 Oracle 的区别1、并发性2、一致性3、事务4、数据持久性5、提交方式6、逻辑备份7、热备份8、sql语句的扩展和灵活性9、复制10、性能诊断11、权限与安全12、分区表和分区索引13、管理工具 oracle 与 mysql分页查询1.Oracle分页查询中提供了一个伪列:…...

原生实现底部弹窗效果 h5 小程序
<template><div class"home"><div class"btn" click"showPopupshow">弹出底部蒙层</div><div class"popup " catchtouchmove"true" :class"showPopup" ><div class"mask&q…...

最新Midjourney绘画提示词Prompt教程无需魔法
最新Midjourney绘画提示词Prompt教程无需魔法使用 一、AI绘画工具 SparkAi【无需魔法使用】: SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作ChatGPT?小编这里写一个详细图文教程吧!本系统使用NestjsVueTypes…...

大一统模型 Universal Instance Perception as Object Discovery and Retrieval 论文阅读笔记
Universal Instance Perception as Object Discovery and Retrieval 论文阅读笔记 一、Abstract二、引言三、相关工作实例感知通过类别名进行检索通过语言表达式的检索通过指代标注的检索 统一的视觉模型Unified Learning ParadigmsUnified Model Architectures 四、方法4.1 Pr…...

java springboot测试类虚拟MVC环境 匹配返回值与预期内容是否相同 (JSON数据格式) 版
上文java springboot测试类鉴定虚拟MVC请求 返回内容与预期值是否相同我们讲了测试类中 虚拟MVC发送请求 匹配返回内容是否与预期值相同 但是 让我意外的是 既然没人骂我 因为我们实际开发 返回的基本都是json数据 字符串的接口场景是少数的 我们在java文件目录下创建一个 dom…...

react等效memo的方法
视频教程 前端技术|Dan博客|在你写memo()之前_哔哩哔哩_bilibili 把与ExpensiveTree的无关的dom做成一个组件 第二种情况,color在ExpensiveTree组件的父级dom 创建一个组件,将state的color和input写上,而ExpensiveTr…...

2023年亚太杯数学建模A题解题思路(*基于OpenCV的复杂背景下苹果目标的识别定位方法研究)
摘要 由于要求较高的时效性和劳力投入,果实采摘环节成为苹果生产作业中十分重要的一部分。而对于自然环境下生长的苹果,光照影响、枝叶遮挡和果实重叠等情况普遍存在,这严重影响了果实的准确识别以及采摘点的精确定位。针对在复杂背景下苹果的…...

【机器学习】聚类(三):原型聚类:高斯混合聚类
文章目录 一、实验介绍1. 算法流程2. 算法解释3. 算法特点4. 应用场景5. 注意事项 二、实验环境1. 配置虚拟环境2. 库版本介绍 三、实验内容0. 导入必要的库1. 全局调试变量2. 调试函数3. 高斯密度函数(phi)4. E步(getExpectation)…...

线上ES集群参数配置引起的业务异常案例分析
本文介绍了一次排查Elasticsearch node_concurrent_recoveries 引发的性能问题的过程。 一、故障描述 1.1 故障现象 1. 业务反馈 业务部分读请求抛出请求超时的错误。 2. 故障定位信息获取 故障开始时间 19:30左右开始 故障抛出异常日志 错误日志抛出timeout错误。 故障之前…...

【Docker】Docker 仓库管理和Docker Dockerfile
作者简介: 辭七七,目前大二,正在学习C/C,Java,Python等 作者主页: 七七的个人主页 文章收录专栏: 七七的闲谈 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖…...

面试必问:如何快速定位BUG?BUG定位技巧及N板斧!
01 定位问题的重要性 很多测试人员可能会说,我的职责就是找到bug,至于找原因并修复,那是开发的事情,关我什么事? 好,我的回答是,如果您只想做一个测试人员最基本最本分的事情,那么可…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...

label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...

算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...

使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...
深入理解Optional:处理空指针异常
1. 使用Optional处理可能为空的集合 在Java开发中,集合判空是一个常见但容易出错的场景。传统方式虽然可行,但存在一些潜在问题: // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...