当前位置: 首页 > news >正文

SQLite数据库C_C++接口(保姆级API应用 1.4W字)(全网最详细介绍,学完必掌握)

目录

sqlite3的C/C++ API应用

前言

SQLite3库安装

API函数

打开、关闭、错误处理

打开

返回值

关闭

错误调试

实际应用

执行SQL(DDL、DML)

API介绍

实际应用

回调函数查询

API介绍

实际应用

全缓冲查询

API介绍

实际应用

字节缓冲查询

API介绍

实际应用

三种查询方式总结

sqlite实现C语言自定义函数封装


sqlite3的C/C++ API应用

前言

对于主键和外键知识点的补充:

  • 主键的值不能重复,一般将自增的字段设置为主键。
    • 主键是用来唯一表示一条数据的值,不能重复的。比如,一条记录包括身份正号,姓名,年龄。身份证号是唯一能确定你这个人的,其他都可能有重复,所以,身份证号薯磨是主键。
  • 外键主要目的是控制存储在外键表中的数据。 使两张表形成关联,外键只能引用外表中的列的值或使用空值。
    • 外键用于与另一张表的关联。是能确定另一张表记录的字段,用于保持数据的一致性。比如,A表中的一个字段,是B表的主键,那他就可以是A表的外键。

SQLite3库安装

在 C/C++ 程序中使用 SQLite 之前,我们需要确保机器上已经有 SQLite 库,这个库提供了C/C++的操作SQLite的编程接口API。

  • 在linux下只需输入安装命令:sudo apt-get install libsqlite3-dev
  • QT下使用SQLite3数据库

https://www.cnblogs.com/tfanalysis/p/4073756.html

  • Windows下:https://www.cnblogs.com/White-strategy-group/p/6360003.html

我使用的是Windows下通过vscode远程SSH访问Linux,因此需要在windows下也安装并添加相应的库文件。

安装前,我们在vscode中添加SQLite的头文件,提示找不到头文件

因此我们需要先定位头文件包含路径

然后到sqlite官网下载源码包(sqlite3的源码)

https://www.cnblogs.com/White-strategy-group/p/6360003.html

解压缩后文件内容如图所示

将三个.h文件添加到之前的includePath中:"D:/myinclude/**"

我们先在目录下新建一个sqlite文件夹

然后将头文件添加进来

如果发现添加完之后仍然自动找不到头文件,如下所示

我们需要手动包含具体头文件路径,如:"D:\\myinclude\\sqlite3"

我们输入sqlite3发现,可以自动提示补全,则表示库文件添加成功!

API函数

打开、关闭、错误处理

打开

第一个参数为指定要打开的数据库的名字,也包括数据库的路径

第二个参数为一个二级指针,这里的作用相当于文件描述符,它是一个数据库文件指针。传入的是一个一级指针的地址作为输出,给指针的具体指向赋值(定义一个空指针传入过来,最终会给这个指针赋值)(通过操作数据库文件指针就相对于操作数据库)

返回值

SQLite3的C/C++接口函数所有返回值如下:

#define SQLITE_OK 0 /* Successful result */
#define SQLITE_ERROR 1 /* SQL error or missing database */
#define SQLITE_INTERNAL 2 /* An internal logic error in SQLite */
#define SQLITE_PERM 3 /* Access permission denied */
#define SQLITE_ABORT 4 /* Callback routine requested an abort */
#define SQLITE_BUSY 5 /* The database file is locked */
#define SQLITE_LOCKED 6 /* A table in the database is locked */
#define SQLITE_NOMEM 7 /* A malloc() failed */
#define SQLITE_READONLY 8 /* Attempt to write a readonly database */
#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite_interrupt() */
#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */
#define SQLITE_CORRUPT 11 /* The database disk image is malformed */
#define SQLITE_NOTFOUND 12 /* (Internal Only) Table or record not found */
#define SQLITE_FULL 13 /* Insertion failed because database is full */
#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
#define SQLITE_EMPTY 16 /* (Internal Only) Database table is empty */
#define SQLITE_SCHEMA 17 /* The database schema changed */
#define SQLITE_TOOBIG 18 /* Too much data for one row of a table */
#define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */
#define SQLITE_MISMATCH 20 /* Data type mismatch */
#define SQLITE_MISUSE 21 /* Library used incorrectly */
#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */
#define SQLITE_AUTH 23 /* Authorization denied */
#define SQLITE_ROW 100 /* sqlite_step() has another row ready */
#define SQLITE_DONE 101 /* sqlite_step() has finished executing */

关闭

错误调试

返回错误信息

返回值错误码

实际应用

#include <stdio.h>
#include <sqlite3.h>int main(int argc, char const *argv[])
{sqlite3 *db;int ret = sqlite3_open(argv[1],&db);if(ret != SQLITE_OK){printf("sqlite3 open:%s\n",sqlite3_errmsg(db));exit(-1);}printf("sqlite open db successfully!\n");sqlite3_close(db);return 0;
}

编译的时候,不能直接编译

我们需要像使用POSIX库一样,手动链接sqlite3库

运行结果:

但是该函数有个bug,即使不传任何参数,也不会报错

因此最好添加一个命令行传参判断

#include <stdio.h>
#include <sqlite3.h>int main(int argc, char const *argv[])
{if(argc != 2){printf("Please input db name!\n");exit(-1);}sqlite3 *db;int ret = sqlite3_open(argv[1],&db);if(ret != SQLITE_OK){printf("sqlite3 open:%s\n",sqlite3_errmsg(db));exit(-1);}printf("sqlite open db successfully!\n");sqlite3_close(db);return 0;
}

执行SQL(DDL、DML)

API介绍

执行SQL语句函数,该函数一共有5个参数

参数1:数据库文件句柄

参数2:要执行的SQL语句

参数3:回调函数,传入一个函数指针(这里的sqlite_callback callback中的sqlite_callback是通过函数指针重命名的,如下图所示)。注:回调函数只对SQL查询语句有效。当指定的是一个非查询操作,该参数应该置为NULL,否则即使传入了回调函数,回调函数也不会被执行。

参数4:回调函数的参数

参数5:保存执行SQL后的错误信息,传入的是一级指针的地址

实际应用

我们首先创建一个学生表,其中我们对错误检查进行了二次封装

#include <stdio.h>
#include <sqlite3.h>
#include <string.h>
#include <stdlib.h>void print_error(int ret, char *err, sqlite3 *db)
{if(ret != SQLITE_OK){printf("%s:%s\n",err,sqlite3_errmsg(db));exit(-1);}
}int main(int argc, char const *argv[])
{if(argc != 2){printf("Please input db name!\n");exit(-1);}sqlite3 *db;char *errmsg;char sql[1024] = {0};int ret = sqlite3_open(argv[1],&db);print_error(ret,"sqlite open",db);printf("sqlite open db successfully!\n");strcpy(sql,"create table student(id integer primary key, name text, age integer)");ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);print_error(ret,"sqlite exec create table",db);printf("create table successfully\n");sqlite3_close(db);return 0;
}

然后通过键盘输入的方式往表里插入三条数据

#include <stdio.h>
#include <sqlite3.h>
#include <string.h>
#include <stdlib.h>void print_error(int ret, char *err, sqlite3 *db)
{if(ret != SQLITE_OK){printf("%s:%s\n",err,sqlite3_errmsg(db));exit(-1);}
}int main(int argc, char const *argv[])
{if(argc != 2){printf("Please input db name!\n");exit(-1);}sqlite3 *db;char *errmsg;char sql[1024] = {0};int id;char name[20];int age;int ret = sqlite3_open(argv[1],&db);print_error(ret,"sqlite open",db);printf("sqlite open db successfully!\n");strcpy(sql,"create table if not exists student(id integer primary key, name text, age integer)");ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);print_error(ret,"sqlite exec create table",db);printf("create table successfully\n");//插入3行数据:id,name,age 键盘输入for(int i=0;i<3;i++){printf("Please input id:\n");scanf("%d",&id);printf("Please input name:\n");scanf("%s",name);printf("Please input age:\n");scanf("%d",&age);//sql:insert into student(id,name,age)values();//sprint();写入到字符串 fprintf();写入到文件memset(sql,0,sizeof(sql));sprintf(sql,"insert into student(id,name,age)values(%d,'%s',%d)",id,name,age);ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);print_error(ret,"sqlite exec create table",db);}sqlite3_close(db);return 0;
}

如果我们想要删除zhangsan的数据,可以使用如下

#include <stdio.h>
#include <sqlite3.h>
#include <string.h>
#include <stdlib.h>
#define DELETE_DATA 1
#define INSERT_DATA 0
void print_error(int ret, char *err, sqlite3 *db)
{if(ret != SQLITE_OK){printf("%s:%s\n",err,sqlite3_errmsg(db));exit(-1);}
}int main(int argc, char const *argv[])
{if(argc != 2){printf("Please input db name!\n");exit(-1);}sqlite3 *db;char *errmsg;char sql[1024] = {0};int id;char name[20];int age;int ret = sqlite3_open(argv[1],&db);print_error(ret,"sqlite open",db);printf("sqlite open db successfully!\n");strcpy(sql,"create table if not exists student(id integer primary key, name text, age integer)");ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);print_error(ret,"sqlite exec create table",db);printf("create table successfully\n");#if INSERT_DATA//插入3行数据:id,name,age 键盘输入for(int i=0;i<3;i++){printf("Please input id:\n");scanf("%d",&id);printf("Please input name:\n");scanf("%s",name);printf("Please input age:\n");scanf("%d",&age);//sql:insert into student(id,name,age)values();//sprint();写入到字符串 fprintf();写入到文件memset(sql,0,sizeof(sql));sprintf(sql,"insert into student(id,name,age)values(%d,'%s',%d)",id,name,age);ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);print_error(ret,"sqlite exec create table",db);}
#endif#if DELETE_DATAprintf("Please input who do you want to delete:\n");memset(sql,0,sizeof(sql));memset(name,0,sizeof(name));scanf("%s",name);sprintf(sql,"delete from student where name = '%s'",name);ret = sqlite3_exec(db,sql,NULL,NULL,&errmsg);print_error(ret,"sqlite exec delete data",db);
#endifsqlite3_close(db);return 0;
}

注:SQLite库提供的是原生态的接口,我们可以对其进行二次封装,像之前错误检查那样,对sqlite3_exec要执行的SQL语句,进行封装,避免代码的冗余。

回调函数查询

API介绍

每查询到一条结果就会回调一次这个函数,通过一行行缓冲数据,每次缓冲一行。

参数1:传入的参数

参数2:保存查询到的结果每一行中列的个数

参数3:保存查询到数据中每一列的值,用一个指针数组(保存指针的数组,本质是数组)来接

参数4:保存每一列的字段名字,用一个指针数组来接

实际应用

以打印查询到的结果每行列数为例:如果回调函数不加return 0;,那么将只执行一次

将上return 0;,才可以执行全部

如果想要打印查询到的每一列结果

再加上每一列相应的字段名

注意:对于外部传入回调函数的参数是无法修改的(具体原因可能是由于内部机制)

如:我们传入一个flag变量,然后出函数打印结果

我们在回调函数内对flag进行++

但出函数之后,值仍是0

如果查询不到结果,将会什么信息也不会输出

我们可以通过定义一个全局变量标志位进行判断,是否查询到数据

#include <stdio.h>
#include <sqlite3.h>
#include <stdlib.h>
#include <string.h>int flag=0;void print_error(int ret, char *err, sqlite3 *db)
{if(ret != SQLITE_OK){printf("%s:%s\n",err,sqlite3_errmsg(db));exit(-1);}printf("%s:successfully!\n",err);
}int my_sqlite_callback(void *para,int columnCount,char **columnValue,char**columnName)
{printf("columnCount = %d\n", columnCount);flag=1;for(int i = 0; i < columnCount;i++){printf("%s:%s|",columnName[i],columnValue[i]);}printf("\n");return 0;
}int main(int argc, char const *argv[])
{if(argc != 2){printf("Please input db name!\n");exit(-1);}sqlite3 *db;char *errmsg;char sql[1024] = {0};int ret = sqlite3_open(argv[1],&db);print_error(ret,"sqlite open",db);printf("sqlite open db successfully!\n");strcpy(sql,"select * from student where name = 'zhangsan'");sqlite3_exec(db,sql,my_sqlite_callback,NULL,&errmsg);print_error(ret,"select",db);if(flag==0){printf("The data queried is empty!\n");}sqlite3_close(db);return 0;
}

全缓冲查询

API介绍

与sqlite_exec不同,sqlite3_get_table是专门用于查询数据的,通过一次性将所有查询到的数据缓冲起来

参数1:数据库文件句柄

参数2:数据库SQL语句

参数3:三维指针,用于保存查询到的结果

参数4:查询到的结果总共的行数

参数5:查询到的结果总共的列数

参数6:保存查询出错的信息

以三维指针为例,我们可以创建一个变相的二维数组:

可以想象创建一个长方体

char ***result;

result = (char***)malloc(sizeof(char**)*4);创建四个存储空间

*result = (char**)malloc(sizeof(char*)*4);每个存储空间里再创建四个存储空间

**result = (char*)malloc(sizeof(char)*4);每个存储空间里再创建一个字符串数组

最终在逻辑上形成16个连续的存储空间(物理上不连续)

我们可以通过三次for循环来创建

但访问方式仍是一维数组的访问方式,因为通过指针创建的空间,本质还是链式的,不是真正的多维数组

实际应用

实际使用时,我们需要定义一个二维指针,将它的地址作为参数传入,查询到的数据都将保存在二维指针中

发现打印是从字段开始打印的,最后少了一行数据,这是因为保存的数据包括了字段那一行,但是返回的行数nrow只算了实际数据的行数

因此需要改正如下:

这样输出的结果就是正确的了

最后一定要记得调用释放空间函数sqlite3_free_table,因为库函数sqlite3_get_table的内部分配了堆区空间

全缓冲查询程序如下:

#include <stdio.h>
#include <sqlite3.h>
#include <stdlib.h>
#include <string.h>void print_error(int ret, char *err, sqlite3 *db)
{if(ret != SQLITE_OK){printf("%s:%s\n",err,sqlite3_errmsg(db));exit(-1);}printf("%s:successfully!\n",err);
}int main(int argc, char const *argv[])
{if(argc != 2){printf("Please input db name!\n");exit(-1);}sqlite3 *db;char *errmsg;char sql[1024] = {0};int ret = sqlite3_open(argv[1],&db);print_error(ret,"sqlite open",db);printf("sqlite open db successfully!\n");char **result;int nrow;int ncolumn;strcpy(sql,"select * from student");ret = sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,&errmsg);print_error(ret,"select",db);for(int i = 1; i<=nrow; i++){for(int j = 0; j < ncolumn; j++){printf("%s|",result[i*ncolumn+j]);}printf("\n");}sqlite3_free_table(result);sqlite3_close(db);return 0;
}

字节缓冲查询

API介绍

sqlite3_prepare

作用:把SQL语句转成字节码,由后面的执行函数去执行,将查询到的数据做字节缓冲

参数1:数据库文件句柄

参数2:SQL语句

参数3:SQL语句的最大字节数,一般设为-1

参数4:Statement句柄,即字节序句柄

参数5:SQL语句无用部分的指针,一般设为NULL

字节缓冲查询还涉及到了以下函数:

  • sqlite3_step:从第一行开始查询,每次查询一行,每调用一次该函数会继续查询下一行数据,数据不为空则返回SQLITE_ROW

  • sqlite3_column_count:获取结果的列数

  • sqlite3_column_text:获取程序的结果当前行中每一列的数据

  • sqlite3_finalize:用于销毁字节序句柄

实际应用

#include <stdio.h>
#include <sqlite3.h>
#include <stdlib.h>
#include <string.h>void print_error(int ret, char *err, sqlite3 *db)
{if(ret != SQLITE_OK){printf("%s:%s\n",err,sqlite3_errmsg(db));exit(-1);}printf("%s:successfully!\n",err);
}int main(int argc, char const *argv[])
{if(argc != 2){printf("Please input db name!\n");exit(-1);}sqlite3 *db;char *errmsg;char sql[1024] = {0};int ret = sqlite3_open(argv[1],&db);print_error(ret,"sqlite open",db);printf("sqlite open db successfully!\n");int rc,i,j;int ncolumn;sqlite3_stmt *stmt;strcpy(sql,"select * from student");rc = sqlite3_prepare(db,sql,-1,&stmt,NULL);if(rc){printf("query fail!\n");}else{printf("query success!\n");rc = sqlite3_step(stmt);//查询成功,则返回值rc==SQLITE_ROWncolumn = sqlite3_column_count(stmt);//获取列数while(rc == SQLITE_ROW){for(i = 0;i<ncolumn;i++){printf("%s|",sqlite3_column_text(stmt,i));//获取每一列的数据}printf("\n");rc = sqlite3_step(stmt);//继续获取下一行数据}}sqlite3_finalize(stmt);sqlite3_close(db);return 0;
}

三种查询方式总结

回调函数查询内存开销小,但查询效率相对较低;全缓冲查询的查询效率高,但是内存消耗大;字节缓冲查询兼具查询效率和低开销。(优先使用第三种查询方法)

sqlite实现C语言自定义函数封装

由于数据库提供的API接口过于复杂,使用的过程顺序也很繁琐,所以对于原生态的API在实际工作开发中,会进行一层封装,减少调用传参,减少调用次数,增加代码可读性,提高开发效率。

可封装如下:包括创建数据库、建表、插入数据、查询数据、删除数据

database.h

#ifndef _DATABASE_H_
#define _DATABASE_H_#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <libgen.h>
#include <sqlite3.h>extern int open_database(sqlite3 **db,char *database_name);
extern int create_table(sqlite3 **db,char *table_name,char *table_attribute);
extern int insert_data(sqlite3 **db,char *table_name,char *attr,char *msg);
extern int query_data(sqlite3 **db,char ***azResult,char *table_name);
extern int delete_data(sqlite3 **db,char *table_name);#endif

 database.c

#include "database.h"char            sql[128];
char            *zErrMsg=NULL;
int             nrow=0;
int             ncolumn = 0;int open_database(sqlite3 **db,char *database_name)
{int             len;len = sqlite3_open(database_name,db);if(len){printf("Open database name %s failure.\n",database_name);sqlite3_close(*db);return -1;}printf("Open a sqlite3 database name %s successfully!\n",database_name);return 0;
}int create_table(sqlite3 **db,char *table_name,char *table_attribute)
{snprintf(sql,sizeof(sql),"CREATE TABLE %s(%s);",table_name,table_attribute);//log_info("sql=%s\n",sql);//sql="CREATE TABLE test(TEST CHAR(100));";if(sqlite3_exec(*db,sql,NULL,NULL,&zErrMsg)!=SQLITE_OK){printf("Table %s already exist\n",table_name);}else{printf("Create table %s successfully\n",table_name);}}int insert_data(sqlite3 **db,char *table_name,char *attr,char *msg)
{snprintf(sql,sizeof(sql),"INSERT INTO %s(%s) VALUES('%s');",table_name,attr,msg);   //插入数据if(sqlite3_exec(*db,sql,NULL,NULL,&zErrMsg)!=SQLITE_OK){sqlite3_close(*db);printf("Insert %s to table %s failure:%s\n",msg,table_name,strerror(errno));return -1;}printf("Insert %s to table %s successfully\n",msg,table_name);return 0;
}int query_data(sqlite3 **db,char ***azResult,char *table_name)
{snprintf(sql,sizeof(sql),"select *from %s;",table_name);//sql="select *from test";if(sqlite3_get_table(*db,sql,azResult,&nrow,&ncolumn,&zErrMsg)!=SQLITE_OK){sqlite3_close(*db);printf("Select *from %s failure\n",table_name);return -1;}printf("There are %d pieces of data in table %s\n",nrow,table_name);return nrow;
}int delete_data(sqlite3 **db,char *table_name)
{snprintf(sql,sizeof(sql),"delete from %s;",table_name);//sql="delete from test";if(sqlite3_exec(*db,sql,NULL,NULL,&zErrMsg)!=SQLITE_OK){sqlite3_close(*db);printf("Delete from %s failure\n",table_name);return -1;}printf("Delete data from table %s successfully!\n",table_name);return 0;
}

test_database.c

#include "database.h"int main(void)
{sqlite3 *db;char    **azResult=NULL;if( open_database(&db,"test.db")<0 )return -1;if( create_table(&db,"test","TEST CHAR(100)")<0 )return -2;if( insert_data(&db,"test","TEST","Test nihao")<0 )return -3;if( query_data(&db,&azResult,"test")<0 )return -4;if( delete_data(&db,"test")<0 )return -5;if( query_data(&db,&azResult,"test")<0 )return -6;return 0;
}

相关文章:

SQLite数据库C_C++接口(保姆级API应用 1.4W字)(全网最详细介绍,学完必掌握)

目录 sqlite3的C/C API应用 前言 SQLite3库安装 API函数 打开、关闭、错误处理 打开 返回值 关闭 错误调试 实际应用 执行SQL&#xff08;DDL、DML&#xff09; API介绍 实际应用 回调函数查询 API介绍 实际应用 全缓冲查询 API介绍 实际应用 字节缓冲查询…...

倒计时:心理的镇静剂还是焦虑的火种?

倒计时&#xff1a;心理的镇静剂还是焦虑的火种&#xff1f; 目录 引言倒计时的作用与原理倒计时的双面性&#xff1a;缓解焦虑还是引发焦虑&#xff1f;如何正确使用倒计时结论 引言 在我们的日常生活和工作中&#xff0c;倒计时被广泛的应用。无论是在网购的抢购活动中&a…...

迅睿系统二开自定义函数和插件的自定义函数

全局的自定义函数&#xff1a; 全局的自定义函数文件&#xff1a;dayrui/My/Helper.php 此文件用于放网站自定义函数&#xff0c;程序会自动加载 当前站点的自定义函数文件&#xff1a;网站主目录/config/custom.php 插件的自定义函数&#xff1a; 基于App目录下的插件或模块…...

传统品牌如何通过3D虚拟数字人定制和动捕设备加速年轻化发展?

步入Z时代&#xff0c;年轻一代消费者的生活方式深受互联网技术和媒介环境影响&#xff0c;对新潮事物感兴趣&#xff0c;消费思维也相对前卫&#xff0c;品牌需要探索契合Z世代的消费观念&#xff0c;寻找新的链接拉近品牌与消费者的距离&#xff0c;而3D虚拟数字人定制可以帮…...

sql:SQL优化知识点记录(五)

&#xff08;1&#xff09;explain之例子 &#xff08;2&#xff09;索引单表优化案例 上面的功能已经实现&#xff0c;但是分析功能&#xff0c; 使用explain分析这条sql&#xff1a; 发现type为All Extra&#xff1a;有Using filesort &#xff08;文件内排序&#xff09; 这…...

1.3 Metasploit 生成SSL加密载荷

在本节中&#xff0c;我们将介绍如何通过使用Metasploit生成加密载荷&#xff0c;以隐藏网络特征。前一章节我们已经通过Metasploit生成了一段明文的ShellCode&#xff0c;但明文的网络传输存在安全隐患&#xff0c;因此本节将介绍如何通过生成SSL证书来加密ShellCode&#xff…...

redis windows 版本安装

1. 下载windows安装包并解压 如果是Linux版本可以直接到官网下载&#xff0c;自3.x起官网和微软网站就没有redis安装包更新了&#xff0c;好在github有开发者在编译发布更新&#xff08;目前最新有5.0.9版本可下&#xff09;&#xff0c;地址&#xff1a;redis windows 5版本下…...

限流算法深入

限流定义及目的 当系统流量达到系统或下游承受能力的阈值时对系统进行限流控制以防止系统或下游挂掉&#xff0c;减少影响面。 限流组成&#xff1a;阈值及限流策略。阈值是指系统单位时间接收到的请求qps总数&#xff1b;限流策略是指限流行业触发后对应的系统行为&#xff…...

java 基础知识 循环的几个题目

1、输出1~100的累加和 结果显示在屏幕&#xff0c;显示在文件res1.txt中 2、输出1-~100的偶数和 结果显示在屏幕&#xff0c;显示在文件res2.txt中 3、输出所有水仙花数&#xff1a; 100~999的数中出现个位数的立方十位数的立方百位数的立方这个数本身 4、输出由9行9列星号组成…...

Spring Boot使用LocalDateTime、LocalDate作为入参

0x0 背景 项目中使用LocalDateTime系列作为dto中时间的类型&#xff0c;但是spring收到参数后总报错&#xff0c;为了全局配置时间类型转换&#xff0c;尝试了如下3中方法。 注&#xff1a;本文基于Springboot2.0测试&#xff0c;如果无法生效可能是spring版本较低导致的。PS&…...

第七周第七天学习总结 | MySQL入门及练习学习第二天

实操练习&#xff1a; 1.创建一个名为 cesh的数据库 2.在这个数据库内 创建一个名为 xinxi 的表要求该表可以包含&#xff1a;编号&#xff0c;姓名&#xff0c;备注的信息 3.为 ceshi 表 添加数据 4.为xinxi 表的数据设置中文别名 5.查询 在 xinxi 表中编号 为2 的全部…...

【考研数学】线形代数第三章——向量 | 3)向量组秩的性质、向量空间、过渡矩阵

文章目录 引言三、向量组等价、向量组的极大线性无关组与秩3.2 向量组秩的性质 四、 n n n 维向量空间4.1 基本概念4.2 基本性质 写在最后 引言 紧接前文学习完向量组秩的基本概念后&#xff0c;继续往后学习向量的内容。 三、向量组等价、向量组的极大线性无关组与秩 3.2 向…...

【技术】SpringBoot Word 模板替换

SpringBoot Word 模板替换 什么是 Word 模板替换如何实现 Word 模板替换 什么是 Word 模板替换 模板一般是具有固定格式的内容&#xff0c;其中一部分需要替换。Word 模板通俗的讲是以 Word 的形式制作模板&#xff0c;固定格式和内容&#xff0c;然后将其中的一部分数据替换掉…...

java jni nv21和nv12互转

目录 libyuv性能比较 NV12 NV21 YUV420格式介绍 jni YUV420toYUV420SemiPlanar java YUV420toYUV420SemiPlanar java NV12toYUV420SemiPlanar jni NV12toYUV420SemiPlanar...

后端面试话术集锦第二篇:spring boot面试话术

🚗后端面试集锦目录 💖后端面试话术集锦第一篇:spring面试话术💖 💖后端面试话术集锦第二篇:spring boot面试话术💖 💖后端面试话术集锦第三篇:spring cloud面试话术💖 💖后端面试话术集锦第四篇:ElasticSearch面试话术💖 💖后端面试话术集锦第五篇:r…...

Doris中分区和分桶使用教程

1 分区与分桶 Doris中有两层的数据划分&#xff0c;第一层是分区&#xff08;Partition&#xff09;&#xff0c;第二层是分桶&#xff08;Bucket&#xff09;&#xff0c; Partition又能分为Range分区和List分区。 Bucket仅支持Hash方式。 1.1 Partition 只能指定…...

电脑不安装软件,怎么将手机文件传输到电脑?

很多人都知道&#xff0c;AirDroid有网页版&#xff08;web.airdroid.com&#xff09;。 想要文件传输&#xff0c;却不想在电脑安装软件时&#xff0c;AirDroid的网页版其实也可以传输文件。 然而&#xff0c;要将文件从手机传输文件到网页端所在的电脑时&#xff0c;如果按…...

vue3 publish 出现的问题

vue3项目使用 yarn build 编译出dist文件&#xff0c; 发布后出现错误 #问题与解决 1)登录迭代错误(Maximum call stack size exceeded) >deepclone 的问题 在 GrandhallLayout 中判断菜单和权限中; const mainMenu cloneDeep(router.getRoutes()) lodash.clonedee…...

网络防御和入侵检测

网络防御和入侵检测是维护网络安全的关键任务&#xff0c;可以帮助识别和阻止未经授权的访问和恶意行为。以下是一些基本的步骤和方法&#xff0c;用于进行网络防御和入侵检测。 网络防御&#xff1a; 防火墙设置&#xff1a; 部署防火墙来监控和控制网络流量&#xff0c;阻止…...

【科研论文配图绘制】task5 SciencePlots绘图包入门

【科研论文配图绘制】task5 SciencePlots绘图包入门 task5主要学习了SciencePlots拓展包的出图样式&#xff0c;掌握SciencePlots的安装及具体使用。 SciencePlots作为一个专门用于科研论文绘图的第三方拓展工具包&#xff0c;提供了主流英文科技 期刊(如 Nature、Science 和 …...

R语言常用数学函数

目录 1. - * / ^ 2.%/%和%% 3.ceiling,floor,round 4.signif,trunc,zapsamll 5.max,min,mean,pmax,pmin 6.range和sum 7.prod 8.cumsum,cumprod,cummax,cummin 9.sort 10. approx 11.approx fun 12.diff 13.sign 14.var和sd 15.median 16.IQR 17.ave 18.five…...

公网远程访问局域网SQL Server数据库

文章目录 1.前言2.本地安装和设置SQL Server2.1 SQL Server下载2.2 SQL Server本地连接测试2.3 Cpolar内网穿透的下载和安装2.3 Cpolar内网穿透的注册 3.本地网页发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4.公网访问测试5.结语 1.前言 数据库的重要性相信大家都有所了解&…...

Apache Celeborn 让 Spark 和 Flink 更快更稳更弹性

摘要&#xff1a;本文整理自阿里云/数据湖 Spark 引擎负责人周克勇&#xff08;一锤&#xff09;在 Streaming Lakehouse Meetup 的分享。内容主要分为五个部分&#xff1a; Apache Celeborn 的背景Apache Celeborn——快Apache Celeborn——稳Apache Celeborn——弹Evaluation…...

华为数通方向HCIP-DataCom H12-821题库(单选题:141-160)

第141题 Router-LSA 能够描述不同的链路类型&#xff0c;不属于Router LSA 链路类型的是以下哪一项? A、Link Type 可以用来描述到末梢网络的连接&#xff0c;即 SubNet B、Link Type 可以用来描述到中转网络的连接&#xff0c;即 TranNet C、Link Type 可以用来描述到另一…...

Windows-docker集成SRS服务器的部署和使用

Windows-docker集成SRS服务器的部署和使用 一、Windows Docker安装 Docker Desktop 官方下载地址&#xff1a; https://docs.docker.com/desktop/install/windows-install/ 下载windows版本的就可以了。 注意&#xff1a;此方法仅适用于 Windows 10 操作系统专业版、企业版、…...

element-ui table表格滚动条拉到最右侧 表头与内容不能对齐

1.问题概述 当表格数据太多&#xff0c;会出现纵向滚动条和横向滚动条&#xff0c;把横向滚动条拉到最右侧时&#xff0c;会出现表头与内容不能对齐的现象。 2.解决方法 1.当页面数据加载完毕后&#xff0c;在后面加上 this.$nextTick(() > {this.$refs.table.doLayout()…...

React中的性能测试工具组件Profiler的基本使用

React中的性能测试工具组件Profiler是一个非常有用的工具&#xff0c;它可以帮助我们分析React应用程序的性能瓶颈。在本文中&#xff0c;我们将学习如何使用Profiler组件来测试React应用程序的性能。 首先&#xff0c;让我们来了解一下Profiler组件的基本用法。在React中&…...

提升生产效率,降低运维成本:纺织业物联网网关应用

在众多物联网技术应用中纺织业正逐渐崭露头角。物联网技术通过无线连接纺织设备、PLC、传感器&#xff0c;实现了纺织厂的生产数据信息的远程监控和数据采集、远程管理&#xff0c;为企业提供了更高效、智能的生产方式。智联物联小编在本文中将重点介绍纺织业物联网的应用与通讯…...

【学习笔记】求解线性方程组的G-S迭代法

求解线性方程组的G-S迭代法 // 运行不成功啊function [x,k,index] Gau_Seid(A,b,ep,it_max) % 求解线性方程组的G-S迭代法&#xff0c;其中 % A为方程组的系数矩阵 % b为方程组的右端项 % ep为精度要求&#xff0c;省缺为1e-5 % it_max为最大迭代次数&#xff0c;省缺为100 % …...

Kotlin协程flow缓冲buffer

Kotlin协程flow缓冲buffer 先看一个普通的flow&#xff1a; import kotlinx.coroutines.delay import kotlinx.coroutines.flow.* import kotlinx.coroutines.runBlocking import kotlin.system.measureTimeMillisfun main(args: Array<String>) {val delayTime 100Lru…...