原文地址:自己整理的一个访问SQLite3数据库的C++类作者:vigra
近日,对SQLite3的使用进行了研究。真不愧是优秀的嵌入数据库,API接口也极其简捷。基本上只要使用以下几个接口就能完成数据库的操作:
sqlite3_open()
sqlite3_prepare()
sqlite3_step()
sqlite3_column()
sqlite3_finalize()
sqlite3_close()
但是,API方式不太符合数据库开发的习惯。我们是C++程序员,封装一下吧。
多网上找到了一份Rob Groves在2004写的“C++ wrapper around the SQLite3 embedded database library.”基本可用,但太复杂了,不利于学习。
所以,我对其进行了简化,只保留了3个类:
TSQLite3Exception 用于异常处理
TSQLite3Query 用于处理带返回数据的SQL语句
TSQLite3DB 用于对数据库本身的操作
经过这样的简化,在保证基本数据库操作的前提下,代码行数变成的原来的1/3,简捷、易用,推荐给大家。
还附上一些应用示例代码,方便大家上手。我测试用的SQLite3版本是3.7.3
//---------------------------------------------------------------------------
int __fastcall TDataModule1::UpdateFounds(String sCode, String sName, String sDate, String sValue)
{
char SqlStr[500];
TSQLite3DB *db;
// open the database file
db = new TSQLite3DB();
try
{
try
{
db->open("data.s3db");
//更新记录
sprintf(SqlStr, "UPDATE FOUNDS SET FOUND_NAME='%s', DATE='%s', VALUE='%s' WHERE CODE='%s'",
AnsiString(sName).c_str(), AnsiString(sDate).c_str(), AnsiString(sValue).c_str(), AnsiString(sCode).c_str());
db->execDML(SqlStr);
}
catch(const TSQLite3Exception &e)
{
ShowMessage(String("更新记录失败!") + e.errorMessage());
}
catch(...)
{
return -1;
}
return 0;
}
__finally
{
delete db;
}
}
//---------------------------------------------------------------------------
int __fastcall TDataModule1::FillListViewFirst(TListView *ListView)
{
TListItem *pItem = NULL;
TSQLite3DB *db;
// open the database file
db = new TSQLite3DB();
try
{
try
{
db->open("data.s3db");
TSQLite3Query Results = db->execQuery("SELECT * FROM FOUNDS ORDER BY CODE");
ListView->Items->Clear();
for( ; !Results.eof(); Results.nextRow())
{
//如果不需要显示,则跳过
if(strncmp("是", Results.getStringField(4, ""), 2) == 0)
{
pItem = ListView->Items->Add();
//第1列
pItem->Caption = String(Results.getStringField(0, ""));
//第2列
pItem->SubItems->Add(Results.getStringField(1, ""));
//第3列
pItem->SubItems->Add(Results.getStringField(2, ""));
//第4列
pItem->SubItems->Add(Results.getStringField(3, ""));
}
}
}
catch(const TSQLite3Exception &e)
{
ShowMessage(String("查询记录失败!") + e.errorMessage());
}
catch(...)
{
return -1;
}
return 0;
}
__finally
{
delete db;
}
}
//---------------------------------------------------------------------------
#include <string.h>
#include <time.h>
#pragma hdrstop
#include "SQLite3_unit.h"
#pragma package(smart_init)
// Named constant for passing to TSQLite3Exception when passing it a string
// that cannot be deleted.
static const bool DONT_DELETE_MSG = false;
// Timeout values on busy or lock conditions
static const int SQLTM_TIMEOUT = 6000; // 6 seconds
////////////////////////////////////////////////////////////////////////////////
TSQLite3Exception::TSQLite3Exception(const int nErrCode,
char *szErrMess,
bool bDeleteMsg) :
mnErrCode(nErrCode)
{
mpszErrMess = sqlite3_mprintf("%s[%d]: %s",
errorCodeAsString(nErrCode),
nErrCode,
szErrMess ? szErrMess : "");
if(bDeleteMsg && szErrMess)
{
sqlite3_free(szErrMess);
}
}
//---------------------------------------------------------------------------
TSQLite3Exception::TSQLite3Exception(const TSQLite3Exception &e) :
mnErrCode(e.mnErrCode)
{
mpszErrMess = 0;
if(e.mpszErrMess)
{
mpszErrMess = sqlite3_mprintf("%s", e.mpszErrMess);
}
}
//---------------------------------------------------------------------------
const char *TSQLite3Exception::errorCodeAsString(int nErrCode)
{
switch(nErrCode)
{
case SQLITE_OK :
return "Successful result";
case SQLITE_ERROR :
return "SQL error or missing database";
case SQLITE_INTERNAL :
return "Internal logic error in SQLite ";
case SQLITE_PERM :
return "Access permission denied";
case SQLITE_ABORT :
return "Callback routine requested an abort";
case SQLITE_BUSY :
return "The database file is locked";
case SQLITE_LOCKED :
return "A table in the database is locked";
case SQLITE_NOMEM :
return "A malloc() failed";
case SQLITE_READONLY :
return "Attempt to write a readonly database";
case SQLITE_INTERRUPT :
return "Operation terminated by sqlite3_interrupt()";
case SQLITE_IOERR :
return "Some kind of disk I/O error occurred ";
case SQLITE_CORRUPT :
return "The database disk image is malformed";
case SQLITE_NOTFOUND :
return "NOT USED. Table or record not found";
case SQLITE_FULL :
return "Insertion failed because database is full";
case SQLITE_CANTOPEN :
return "Unable to open the database file";
case SQLITE_PROTOCOL :
return "Database lock protocol error";
case SQLITE_EMPTY :
return "Database is empty";
case SQLITE_SCHEMA :
return "The database schema changed";
case SQLITE_TOOBIG :
return "String or BLOB exceeds size limit";
case SQLITE_CONSTRAINT :
return "Abort due to constraint violation";
case SQLITE_MISMATCH :
return "Data type mismatch";
case SQLITE_MISUSE :
return "Library used incorrectly";
case SQLITE_NOLFS :
return "Uses OS features not supported on host";
case SQLITE_AUTH :
return "Authorization denied";
case SQLITE_FORMAT :
return "Auxiliary database format error";
case SQLITE_RANGE :
return "2nd parameter to sqlite3_bind out of range";
case SQLITE_NOTADB :
return "File opened that is not a database file";
case SQLITE_ROW :
return "sqlite3_step() has another row ready";
case SQLITE_DONE :
return "sqlite3_step() has finished executing";
case TSQLITE_ERROR :
return "TSQLITE_ERROR";
default:
return "UNKNOWN_ERROR";
}
}
//---------------------------------------------------------------------------
TSQLite3Exception::~TSQLite3Exception()
{
if(mpszErrMess)
{
sqlite3_free(mpszErrMess);
mpszErrMess = 0;
}
}
////////////////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------------
TSQLite3Query::TSQLite3Query()
{
mpDB = 0;
mpVM = 0;
mbEof = true;
mnCols = 0;
mbOwnVM = false;
}
//---------------------------------------------------------------------------
TSQLite3Query::TSQLite3Query(const TSQLite3Query &rQuery)
{
mpDB = rQuery.mpDB;
mpVM = rQuery.mpVM;
// Only one object can own the VM
const_cast<TSQLite3Query &>(rQuery).mpVM = 0;
mbEof = rQuery.mbEof;
mnCols = rQuery.mnCols;
mbOwnVM = rQuery.mbOwnVM;
}
//---------------------------------------------------------------------------
TSQLite3Query::TSQLite3Query(sqlite3 *pDB,
sqlite3_stmt *pVM,
bool bEof,
bool bOwnVM)
{
mpDB = pDB;
mpVM = pVM;
mbEof = bEof;
mnCols = sqlite3_column_count(mpVM);
mbOwnVM = bOwnVM;
}
//---------------------------------------------------------------------------
TSQLite3Query::~TSQLite3Query()
{
try
{
finalize();
}
catch(...)
{
}
}
//---------------------------------------------------------------------------
TSQLite3Query &TSQLite3Query::operator=(const TSQLite3Query &rQuery)
{
try
{
finalize();
}
catch(...)
{
}
mpDB = rQuery.mpDB;
mpVM = rQuery.mpVM;
// Only one object can own the VM
const_cast<TSQLite3Query &>(rQuery).mpVM = 0;
mbEof = rQuery.mbEof;
mnCols = rQuery.mnCols;
mbOwnVM = rQuery.mbOwnVM;
return *this;
}
//---------------------------------------------------------------------------
int TSQLite3Query::numFields()
{
checkVM();
return mnCols;
}
//---------------------------------------------------------------------------
const char *TSQLite3Query::fieldValue(int nField)
{
checkVM();
if(nField < 0 || nField > mnCols - 1)
{
throw TSQLite3Exception(TSQLITE_ERROR,
"Invalid field index requested",
DONT_DELETE_MSG);
}
return (const char *)sqlite3_column_text(mpVM, nField);
}
//---------------------------------------------------------------------------
const char *TSQLite3Query::fieldValue(const char *szField)
{
int nField = fieldIndex(szField);
return (const char *)sqlite3_column_text(mpVM, nField);
}
//---------------------------------------------------------------------------
int TSQLite3Query::getIntField(int nField, int nNullValue)
{
if(fieldDataType(nField) == SQLITE_NULL)
{
return nNullValue;
}
else
{
return sqlite3_column_int(mpVM, nField);
}
}
//---------------------------------------------------------------------------
int TSQLite3Query::getIntField(const char *szField, int nNullValue)
{
int nField = fieldIndex(szField);
return getIntField(nField, nNullValue);
}
//---------------------------------------------------------------------------
double TSQLite3Query::getFloatField(int nField, double fNullValue)
{
if(fieldDataType(nField) == SQLITE_NULL)
{
return fNullValue;
}
else
{
return sqlite3_column_double(mpVM, nField);
}
}
//---------------------------------------------------------------------------
double TSQLite3Query::getFloatField(const char *szField, double fNullValue)
{
int nField = fieldIndex(szField);
return getFloatField(nField, fNullValue);
}
//---------------------------------------------------------------------------
const char *TSQLite3Query::getStringField(int nField, const char *szNullValue)
{
if(fieldDataType(nField) == SQLITE_NULL)
{
return szNullValue;
}
else
{
return (const char *)sqlite3_column_text(mpVM, nField);
}
}
//---------------------------------------------------------------------------
const char *TSQLite3Query::getStringField(const char *szField, const char *szNullValue)
{
int nField = fieldIndex(szField);
return getStringField(nField, szNullValue);
}
//---------------------------------------------------------------------------
const unsigned char *TSQLite3Query::getBlobField(int nField, int &nLen)
{
checkVM();
if(nField < 0 || nField > mnCols - 1)
{
throw TSQLite3Exception(TSQLITE_ERROR,
"Invalid field index requested",
DONT_DELETE_MSG);
}
nLen = sqlite3_column_bytes(mpVM, nField);
return (const unsigned char *)sqlite3_column_blob(mpVM, nField);
}
//---------------------------------------------------------------------------
const unsigned char *TSQLite3Query::getBlobField(const char *szField, int &nLen)
{
int nField = fieldIndex(szField);
return getBlobField(nField, nLen);
}
//---------------------------------------------------------------------------
bool TSQLite3Query::fieldIsNull(int nField)
{
return (fieldDataType(nField) == SQLITE_NULL);
}
//---------------------------------------------------------------------------
bool TSQLite3Query::fieldIsNull(const char *szField)
{
int nField = fieldIndex(szField);
return (fieldDataType(nField) == SQLITE_NULL);
}
//---------------------------------------------------------------------------
int TSQLite3Query::fieldIndex(const char *szField)
{
checkVM();
if(szField)
{
for(int nField = 0; nField < mnCols; nField++)
{
const char *szTemp = sqlite3_column_name(mpVM, nField);
if(strcmp(szField, szTemp) == 0)
{
return nField;
}
}
}
throw TSQLite3Exception(TSQLITE_ERROR,
"Invalid field name requested",
DONT_DELETE_MSG);
}
//---------------------------------------------------------------------------
const char *TSQLite3Query::fieldName(int nCol)
{
checkVM();
if(nCol < 0 || nCol > mnCols - 1)
{
throw TSQLite3Exception(TSQLITE_ERROR,
"Invalid field index requested",
DONT_DELETE_MSG);
}
return sqlite3_column_name(mpVM, nCol);
}
//---------------------------------------------------------------------------
const char *TSQLite3Query::fieldDeclType(int nCol)
{
checkVM();
if(nCol < 0 || nCol > mnCols - 1)
{
throw TSQLite3Exception(TSQLITE_ERROR,
"Invalid field index requested",
DONT_DELETE_MSG);
}
return sqlite3_column_decltype(mpVM, nCol);
}
//---------------------------------------------------------------------------
int TSQLite3Query::fieldDataType(int nCol)
{
checkVM();
if(nCol < 0 || nCol > mnCols - 1)
{
throw TSQLite3Exception(TSQLITE_ERROR,
"Invalid field index requested",
DONT_DELETE_MSG);
}
return sqlite3_column_type(mpVM, nCol);
}
//---------------------------------------------------------------------------
bool TSQLite3Query::eof()
{
checkVM();
return mbEof;
}
//---------------------------------------------------------------------------
void TSQLite3Query::nextRow()
{
checkVM();
int nRet = sqlite3_step(mpVM);
if(nRet == SQLITE_DONE)
{
// no rows
mbEof = true;
}
else if(nRet == SQLITE_ROW)
{
// more rows, nothing to do
}
else
{
nRet = sqlite3_reset(mpVM);
mpVM = 0;
const char *szError = sqlite3_errmsg(mpDB);
throw TSQLite3Exception(nRet,
(char *)szError,
DONT_DELETE_MSG);
}
}
//---------------------------------------------------------------------------
void TSQLite3Query::finalize()
{
if(mpVM && mbOwnVM)
{
int nRet = sqlite3_finalize(mpVM);
mpVM = 0;
if(nRet != SQLITE_OK)
{
const char *szError = sqlite3_errmsg(mpDB);
throw TSQLite3Exception(nRet, (char *)szError, DONT_DELETE_MSG);
}
}
else if(mpVM && !mbOwnVM)
{
sqlite3_reset(mpVM);
}
}
//---------------------------------------------------------------------------
void TSQLite3Query::checkVM()
{
if(mpVM == 0)
{
throw TSQLite3Exception(TSQLITE_ERROR,
"Null Virtual Machine pointer",
DONT_DELETE_MSG);
}
}
////////////////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------------
TSQLite3DB::TSQLite3DB()
{
mpDB = 0;
mnBusyTimeoutMs = SQLTM_TIMEOUT;
}
//---------------------------------------------------------------------------
TSQLite3DB::TSQLite3DB(const TSQLite3DB &db)
{
mpDB = db.mpDB;
mnBusyTimeoutMs = SQLTM_TIMEOUT;
}
//---------------------------------------------------------------------------
TSQLite3DB::~TSQLite3DB()
{
close();
}
//---------------------------------------------------------------------------
TSQLite3DB &TSQLite3DB::operator=(const TSQLite3DB &db)
{
mpDB = db.mpDB;
mnBusyTimeoutMs = SQLTM_TIMEOUT;
return *this;
}
//---------------------------------------------------------------------------
void TSQLite3DB::open(const char *szFile)
{
int nRet = sqlite3_open(szFile, &mpDB);
if(nRet != SQLITE_OK)
{
const char *szError = sqlite3_errmsg(mpDB);
throw TSQLite3Exception(nRet, (char *)szError, DONT_DELETE_MSG);
}
setBusyTimeout(mnBusyTimeoutMs);
}
//---------------------------------------------------------------------------
void TSQLite3DB::close()
{
if(mpDB)
{
int Result = sqlite3_close(mpDB);
if(Result != SQLITE_OK)
{
const char *szError = sqlite3_errmsg(mpDB);
throw TSQLite3Exception(Result, (char *)szError, DONT_DELETE_MSG);
}
mpDB = 0;
}
}
//---------------------------------------------------------------------------
int TSQLite3DB::execDML(const char *szSQL)
{
checkDB();
char *szError = 0;
int nRet = sqlite3_exec(mpDB, szSQL, 0, 0, &szError);
if(nRet == SQLITE_OK)
{
return sqlite3_changes(mpDB);
}
else
{
throw TSQLite3Exception(nRet, szError);
}
}
//---------------------------------------------------------------------------
TSQLite3Query TSQLite3DB::execQuery(const char *szSQL)
{
checkDB();
sqlite3_stmt *pVM = compile(szSQL);
int nRet = sqlite3_step(pVM);
if(nRet == SQLITE_DONE)
{
// no rows
return TSQLite3Query(mpDB, pVM, true);
}
else if(nRet == SQLITE_ROW)
{
// at least 1 row
return TSQLite3Query(mpDB, pVM, false);
}
else
{
nRet = sqlite3_finalize(pVM);
const char *szError = sqlite3_errmsg(mpDB);
throw TSQLite3Exception(nRet, (char *)szError, DONT_DELETE_MSG);
}
}
//---------------------------------------------------------------------------
sqlite_int64 TSQLite3DB::lastRowId()
{
return sqlite3_last_insert_rowid(mpDB);
}
//---------------------------------------------------------------------------
void TSQLite3DB::setBusyTimeout(int nMillisecs)
{
mnBusyTimeoutMs = nMillisecs;
sqlite3_busy_timeout(mpDB, mnBusyTimeoutMs);
}
//---------------------------------------------------------------------------
void TSQLite3DB::checkDB()
{
if(!mpDB)
{
throw TSQLite3Exception(TSQLITE_ERROR,
"Database not open",
DONT_DELETE_MSG);
}
}
//---------------------------------------------------------------------------
sqlite3_stmt *TSQLite3DB::compile(const char *szSQL)
{
checkDB();
const char *szTail = 0;
sqlite3_stmt *pVM;
int nRet;
nRet = sqlite3_prepare_v2(mpDB, szSQL, -1, &pVM, &szTail);
if(nRet != SQLITE_OK)
{
const char *szError = sqlite3_errmsg(mpDB);
throw TSQLite3Exception(nRet,
(char *)szError,
DONT_DELETE_MSG);
}
return pVM;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#ifndef SQLite3_unitH
#define SQLite3_unitH
#include "sqlite3.h"
#define TSQLITE_ERROR 1000
//---------------------------------------------------------------------------
class TSQLite3Exception
{
public:
TSQLite3Exception(const int nErrCode,
char *szErrMess,
bool bDeleteMsg = true);
TSQLite3Exception(const TSQLite3Exception &e);
virtual ~TSQLite3Exception();
int errorCode() const
{
return mnErrCode;
}
char *errorMessage() const
{
return mpszErrMess;
}
static const char *errorCodeAsString(int nErrCode);
private:
int mnErrCode;
char *mpszErrMess;
};
//---------------------------------------------------------------------------
class TSQLite3Query
{
public:
TSQLite3Query();
TSQLite3Query(const TSQLite3Query &rQuery);
TSQLite3Query(sqlite3 *pDB,
sqlite3_stmt *pVM,
bool bEof,
bool bOwnVM = true);
TSQLite3Query &operator=(const TSQLite3Query &rQuery);
virtual ~TSQLite3Query();
int numFields();
int fieldIndex(const char *szField);
const char *fieldName(int nCol);
const char *fieldDeclType(int nCol);
int fieldDataType(int nCol);
const char *fieldValue(int nField);
const char *fieldValue(const char *szField);
int getIntField(int nField, int nNullValue = 0);
int getIntField(const char *szField, int nNullValue = 0);
double getFloatField(int nField, double fNullValue = 0.0);
double getFloatField(const char *szField, double fNullValue = 0.0);
const char *getStringField(int nField, const char *szNullValue = "");
const char *getStringField(const char *szField, const char *szNullValue = "");
const unsigned char *getBlobField(int nField, int &nLen);
const unsigned char *getBlobField(const char *szField, int &nLen);
bool fieldIsNull(int nField);
bool fieldIsNull(const char *szField);
bool eof();
void nextRow();
void finalize();
private:
void checkVM();
sqlite3 *mpDB;
sqlite3_stmt *mpVM;
bool mbEof;
int mnCols;
bool mbOwnVM;
};
//---------------------------------------------------------------------------
class TSQLite3DB
{
public:
TSQLite3DB();
virtual ~TSQLite3DB();
void open(const char *szFile);
void close();
int execDML(const char *szSQL);
TSQLite3Query execQuery(const char *szSQL);
void setBusyTimeout(int nMillisecs);
sqlite_int64 lastRowId();
void interrupt()
{
sqlite3_interrupt(mpDB);
}
bool isAutoCommit()
{
return sqlite3_get_autocommit(mpDB) != 0;
}
static const char *SQLiteVersion()
{
return SQLITE_VERSION;
}
sqlite3 *getDB()
{
return mpDB;
}
private:
TSQLite3DB(const TSQLite3DB &db);
TSQLite3DB &operator=(const TSQLite3DB &db);
sqlite3_stmt *compile(const char *szSQL);
void checkDB();
sqlite3 *mpDB;
int mnBusyTimeoutMs;
};
//---------------------------------------------------------------------------
#endif
- Python访问sqlite3数据库取得dictionary的正路!
[引子] 很多人都知道,Python里是内置了很好用的sqlite3的.但这个库有个缺陷,在执行fetchall()/fetchone()等方法后,得到的是一个tuple.以前吧,做自己的小项目,tu ...
- 使用MyBatis搭建一个访问mysql数据库的简单示例
MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以使用简单的XML或注解用 ...
- servlet层调用biz业务层出现浏览器 500错误,解决方法 dao数据访问层 数据库Util工具类都可能出错 通过新建一个测试类复制代码逐步测试查找出最终出错原因
package com.swift.jztk.servlet; import java.io.IOException; import javax.servlet.ServletException; i ...
- [转]html5 js 访问 sqlite 数据库的操作类
本文转自:http://blog.csdn.net/tsxw24/article/details/7613815 webkit 核心的浏览器提供了 3个 api接口,用于访问本地sqlite数据,但使 ...
- Java下一个简单的数据库分库帮助类
简介 前面两篇文章主要讲了数据库读写分离和分表分库的一些问题,这篇文章主要讲一下我个人实现的一个分表分库项目. 在此之前,我有写过一个.Net的分库,最近在做Java的项目,就顺便做出一 ...
- 封装List集合一个批量导入数据库的工具类
public class CommonDal { #region 数据导入相关 /// <summary> /// 批量导入数据 /// </summary> /// < ...
- Sql数据库帮组类
这段时间闲下来写了一些东西,重新写了一个简单的数据库帮组类 public class MyDBHelper { public static readonly string connString = C ...
- iphone/iOS 访问本地数据库sqlite3
Phone也支持访问本地数据库Sqlite 3.这里简单的介绍一下iPhone上Sqlite 3的使用方法. 首先需要在项目中引用Sqlite 3的开发包,下面是在iPhone SDK 3.0下的目录 ...
- 并发访问sqlite数据库出现databse is locked的错误的一个解决办法
作者:朱金灿 来源:http://blog.csdn.net/clever101 在并发访问sqlite数据库会出现这样一个错误:databseis locked,这是sqlite数据库对并发支持不太 ...
随机推荐
- hashCode和identityHashCode的区别你知道吗?
hashCode 关于hashCode参考之前的文章,点击参考之前文章. identityHashCode identityHashCode是System里面提供的本地方法,java.lang.Sys ...
- python中字典排序
一.Python的排序 1.reversed() 这个很好理解,reversed英文意思就是:adj. 颠倒的:相反的:(判决等)撤销的 print list(reversed(['dream','a ...
- "_CMTimeGetSeconds", referenced from:
CMTime is defined in the CoreMedia.framework. Add that framework to your project.
- ionic js ion-tabs选项卡栏操作
ionic 选项卡栏操作 ion-tabs ion-tabs 是有一组页面选项卡组成的选项卡栏.可以通过点击选项来切换页面. 对于 iOS,它会出现在屏幕的底部,Android会出现在屏幕的顶部(导航 ...
- VGDB提示
由于之前地址的版本在未安装.Net 4.0的电脑上安装会出现插件使用装载失败的问题,已更新,新地址为:http://pan.baidu.com/s/1xdnuD,此版本需要.Net 2.0.
- ci用户登录
[list] 预先加载数据库操作类和Session类 即在autoload.php中,$autoload['libraries'] = array('database', 'session'); a. ...
- leetcode-23-合并K个有序链表*
题目描述: 方法一:分治 # Definition for singly-linked list. # class ListNode: # def __init__(self, x): # self. ...
- 概率+后效性处理——cf930B好题
之前题目看错了.. 先用双倍字符串处理后效性 首先要确定一个结论:如果原串s中相距为d的ch1和ch2只有一对,那么如果第一个翻开ch1,第二个翻开ch2,就能确定k 现在要求的是当我们第一次翻开的是 ...
- LUOGU P3161 [CQOI2012]模拟工厂 (贪心)
传送门 解题思路 贪心,首先因为\(n\)比较小,可以\(2^n\)枚举子集.然后判断的时候就每次看后面的如果用最大生产力生产能不能达成目标,解一个二次函数. 代码 #include<iostr ...
- 在类中,调用这个类时,用$this->video_model是不是比每次调用这个类时D('Video')效率更高呢
在类中,调用这个类时,用$this->video_model是不是比每次调用这个类时D('Video')效率更高呢