在java/C#中都有类的反射,而C下是不存在的。

java/C#中能够把表设计成类。而C下仅仅能设计成结构体形式。

在java中有hibernate来操作数据库,可是在C以下怎么设计好呢?

如今,我想出了一个点子,下面使用sqlite

先创建一个结构体。表示一张数据库表的结构。

typedef struct User {

int id;

char *name;

char *password;

} User;

创建表的语句:

CREATE TABLE 'User' ('id'  INTEGER PRIMARY KEY AUTOINCREMENT,'name' varchar(100),'password'  varchar(100),'workNumber' varchar(100))

数据库的操作有select ,insert ,delete ,update,而insert,delete,update都是让数据库去操作,但select是有返回数据的。

所以。对于insert,delete,update我採用

int sql_exec(char *format,...) {
char sql[1024];
va_list args;
char *errmsg=NULL;
int rc;
va_start(args, format);
vsprintf(sql,format,args);
va_end(args);
rc=sqlite3_exec(g_mdb,sql,NULL,NULL,&errmsg);
if(rc!=SQLITE_OK){
printf("%s,%s,%s\n",__FUNCTION__,errmsg,sql);
sqlite3_free(errmsg);
return SQLITE_ERROR;
}
return SQLITE_OK;
}

对数据库的操作我定义成

#define SELECT_(_columns,_table,_where) "select "_columns" from "#_table" WHERE "##_where
#define INSERT_INTO_(_table,_columns,_values) "insert into "#_table" ("_columns") values ("_values")"
#define UPDATE_(_table,_set,_where) "UPDATE "#_table" SET "_set" WHERE "##_where
#define DELETE_FROM(_table,_where) "DELETE FROM "#_table" WHERE "##_where

#define insert_table(format,...)  sql_exec(format,__VA_ARGS__)

#define update_table(format,...)  sql_exec(format,__VA_ARGS__)

#define delete_table(format,...)  sql_exec(format,__VA_ARGS__)

终于调用(insert):

insert_table(INSERT_INTO_(User,"id,name,password","%d,'%s','%s'"),us.id,us.name,us.password);

而对于select ,返回的是一个列表数据:

struct select_list {
void *value;
struct select_list *next;
};
typedef void select_value_free(void *value); struct select_list *select_list_new(){
struct select_list *h=(struct select_list*)malloc(sizeof(struct select_list));
memset(h,0,sizeof(struct select_list));
return h;
} void select_list_free(struct select_list *list,select_value_free value_free){
struct select_list *next;
if(list==NULL){
return ;
}
if(list->value){
value_free(list->value);
}
if(list) {
next=list->next;
free(list);
}
select_list_free(next,value_free);
}

select_list *home;

select_table((void**)&home,SELECT_("id",User,"name='%s' and password='%s'"),us.name,us.password);

if(home!=NULL){

for(next=home;next;next=next->next){

User *item=((User*)next->value);

printf("%d,%s,%s\n",item->id,item->name,item->password);

}

select_list_free(home,user_free);

}

//关键是在select_table

通过sqlite3_prepare查找出sqlite3_stmt,遍历stmt,取出当前操作的表名。与定义的结构体user比較,假设等于。则创建User,把查询的数据给User,再把这个User增加链表value就能够了。

void *select_value_item_user(sqlite3_stmt *stmt){
int i;
int count;
User *item=(User*)malloc(sizeof(User));
memset(item,0,sizeof(User));
count=sqlite3_column_count(stmt);
for(i=0;i<count;i++){
if(0==strcmp(sqlite3_column_name(stmt,i),"id")){
item->id=sqlite3_column_int(stmt,i);
}
if(0==strcmp(sqlite3_column_name(stmt,i),"name")){
char_cpy(&item->name,(const char *)sqlite3_column_text(stmt,i));
}
}
return item;
}
int select_table(void **result,char *pszFormat,...) {
sqlite3_stmt * stmt=NULL;
const char *table_name=NULL;
int count=0;
char sql[1024];
va_list args;
struct select_list *next=NULL;
struct select_list *home=NULL;
va_start(args, pszFormat);
vsprintf(sql,pszFormat,args);
va_end(args);
printf("%s\n",sql);
*result=NULL; if(sqlite3_prepare(g_mdb,sql,-1,&stmt,NULL)==SQLITE_OK){
while( sqlite3_step(stmt)==SQLITE_ROW){
/************************************************************************/
/* */
/************************************************************************/
table_name=sqlite3_column_table_name(stmt,0);
if(table_name) {
if(strcmp(table_name,STR(User))==0){
//加入到list就能够了
next=select_list_new();
next->value=select_value_item_user(stmt);
next->next=NULL;
if(*result==NULL){
*result=next;
} else {
home->next=next;
}
home=next;
}
} else {
{
int column_count=sqlite3_column_count(stmt);
int i=0;
for(i=0;i<column_count;i++){
if(sqlite3_column_type(stmt,i)==SQLITE_INTEGER) {
//printf("%s,%d\n",sqlite3_column_name(stmt,i),sqlite3_column_int(stmt,i));
*result=(void*)sqlite3_column_int(stmt,i);
}
}
}
}
count++;
}
} else {
count=-1;
//save errmsg...
}
sqlite3_finalize(stmt);
return count;
}

这仅仅是针对单一表的查询操作,能够增加count(*)功能。

int count;

select_table((void**)&count,SELECT_("count(*)",User,"1=1"));

对于其他的表,你仅仅要创建一个相当于User的结构体就能够了。再加入一个 select_value_item_user 功能数据库值与此绑定功能的函数。再在select中选择这个函数就可。

当然,能够採用C 下的 HashMap 来把 表名(结构体名)与 绑定函数 做一个映像,这样方便一点,但我的表仅仅有几个所以就不用做了。

c语言下的通用数据库接口(之sqlite消化,模拟c#,java的反射)的更多相关文章

  1. c语言下多线程

    原文:c语言下多线程 [问题]创建了10个线程,10个线程公用一个线程体,创建如下: int t1=0,t2=1,t3=2,t4=3,t5=4,t6=5,t7=6,t8=7,t9=8,t10=9; i ...

  2. Kotlin 语言下设计模式的不同实现

    偶然在 Github 上看到 dbacinski 写的 Kotlin 语言下设计模式的不同实现(这里的不同是相对于 Java 语言的),有些实现非常好,但是有些实现的例子不是很赞同.所以自己写了 Ko ...

  3. C语言下的错误处理问题

    今天来分享我认为比较好的几种在C语言下的错误处理方式 方式一: int example(int num) { ) { ; } ; } 在不符合条件的情况下使用return终止程序 方式二: void ...

  4. C语言下文件目录查看

    C语言下文件目录遍历通常会用到下面这些函数 _access()        /* 判断文件或文件夹路径是否合法 */ _chdir() /* 切换当前工作目录 */ _findfirst()   / ...

  5. Linux下shell通用脚本启动jar(微服务)

    Linux下shell通用脚本启动jar(微服务) vim app_jar.sh #!/bin/bash #source /etc/profile # Auth:Liucx # Please chan ...

  6. 64位Ubuntu下的Eclipse、ADT终于可以生成R.java了,虚机也可以正常建立

    64位Ubuntu12下的Eclipse总也不能自动生成R.java,导致无法正常编译程序,建虚拟器的时候总是提示少文件....三天下班机器没关(无奈公司网络不给力)来安装lib包. 各种加载,总结一 ...

  7. Oracle单实例情况下的library cache pin的问题模拟与问题分析

    Oracle单实例情况下的library cache pin的问题模拟与问题分析 參考自: WAITEVENT: "library cache pin" Reference Not ...

  8. 构建一个学生Student,根据类Student的定义,创建五个该类的对象,输出每个学生的信息,计算并输出这五个学生Java语言成绩的平均值,以及计算并输出他们Java语言成绩的最大值和最小值。

    定义一个表示学生信息的类Student,要求如下: (1)类Student的成员变量: sNO 表示学号: sName表示姓名: sSex表示性别: sAge表示年龄: sJava:表示Java课程成 ...

  9. 再整理:Visual Studio Code(vscode)下的通用C语言环境搭建

    版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://www.cnblogs.com/czlhxm/p/11794743.ht ...

随机推荐

  1. Linux基本命令(4)有关关机和查看系统信息的命令

    有关关机和查看系统信息的命令 命令 说明 shutdown 正常关机 reboot 重启计算机 ps 查看目前程序执行的情况 top 查看目前程序执行的情景和内存使用的情况 kill 终止一个进程 d ...

  2. JSP中字符编码转换问题

    问题描述:一个input.jsp页面中的参数,传递到另外一个save.jsp页面上,然后存入到数据库中,如果input.jsp页面输入偶数中文没有问题,输入奇数则出现?,存入数据库的也是?. 问题源码 ...

  3. 在Lua里写unity游戏笔记

    gameobject.GetComponent<Transform>(); 翻译成Lua: gameObject:GetComponent (luanet.ctype (Transform ...

  4. 学习笔记——XSLT转换器的使用(Xalan和Saxon) .(转)

    转自:http://blog.csdn.net/crystalbruce/article/details/7401602 XSLT分为两类: 1:客户端转换:需要浏览器的支持. 2:服务器转换:需要使 ...

  5. bzoj 4006 [JLOI2015]管道连接(斯坦纳树+状压DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4006 [题意] 给定n点m边的图,连接边(u,v)需要花费w,问满足使k个点中同颜色的 ...

  6. 《Genesis-3D开源游戏引擎完整实例教程-2D射击游戏篇05:角色中弹》

    5.角色中弹 概述: 为了使游戏具有挑战性,大部分游戏设定中,游戏角色都有生命限制.即在游戏中,由于玩家的操控操控不当,导致游戏角色死亡游戏终止.打飞机游戏也不例外,当敌人击中角色的时候,角色宣判死亡 ...

  7. C++单例模板

    #pragma once namespace MyGame { template<typename T> class Global { public: static void Create ...

  8. centos6.4 挂载ntfs分区

    默认情况下,CentOS 6.4不支持Widows NTFS硬盘分区读写,要想把NTFS格式的磁盘挂载到CentOS 6.3下面需要安装第三方的插件ntfs-3g,这里我们采用编译安装插件. 1.安装 ...

  9. Spring4整合Hibernate4详细示例

    1. Spring整合Hibernate,主要是解决什么问题? a.让Spring提供的IOC容器来管理Hibernate的SessionFactory b.让Hibernate使用Spring提供的 ...

  10. quartz 时间配置规则

    quartz 时间配置规则 格式: [秒] [分] [小时] [日] [月] [周] [年]  序号 说明  是否必填  允许填写的值 允许的通配符  1  秒  是  0-59    , - * / ...