豫建设标文件在哪个网站公布,wordpress 移动端首页,南平市建设集团网站,锦州做网站多少钱最近小哥老是想浪#xff0c;不想好好学习#xff0c;这不行啊#xff0c;得想点办法#xff0c;多少做点努力#xff0c;于是就自己给自己写了个打卡程序#xff1b;
该程序基于Sqlite数据库#xff0c;实现一个简单的打卡功能#xff0c;该函数具有自动初始化的功能…最近小哥老是想浪不想好好学习这不行啊得想点办法多少做点努力于是就自己给自己写了个打卡程序
该程序基于Sqlite数据库实现一个简单的打卡功能该函数具有自动初始化的功能第一次使用时会自动创建数据库和表格并赋原始初值进入界面后自动显示上次打卡日期以及已经打卡天数用户可以根据提示选择打开或者不打卡退出 先上效果图如下 该程序其实非常基础的一个版本仅有一个简单的打卡记录功能所以也非常适合刚学习sqlite新手小白去练习
如果比较熟练了是可以基于该程序去丰富各种功能做出各种各样更有趣的系统比如接入人脸识别做成考勤打卡系统接入邮件功能要是当天没有学习打卡就疯狂邮件你或者改装成一个词典只要想象力丰富大有可为
好了那么正式看代码前先简单认识一下sqlite的几个基础的函数
sqlite3_open(const char *filename, sqlite3 **ppDb)
打开一个指向 SQLite 数据库文件的连接返回一个用于其他 SQLite 程序的数据库连接对象。
如果打开时没有该filename的数据库则会自动创建改名字的数据库sqlite3_close(sqlite3*)
该例程关闭之前调用 sqlite3_open() 打开的数据库连接。所有与连接相关的语句都应在连接关闭之前完成。
如果还有查询没有完成sqlite3_close() 将返回 SQLITE_BUSY 禁止关闭的错误消息。const char *sqlite3_errmsg(sqlite3*);
返回sqlite执行错误的错误信息sqlite3_exec(sqlite3*, const char *sql, sqlite_callback, void *data, char **errmsg)
提供了一个执行 SQL 命令的快捷方式SQL 命令由 sql 参数提供可以由多个 SQL 命令组成。简单来说就是通过该函数来执行sql语句在这里第一个参数 sqlite3 是打开的数据库对象sqlite_callback 是一个回调
data 作为其第一个参数errmsg 将被返回用来获取程序生成的任何错误。sqlite3_exec中的回调函数sqlite_callback是有固定格式的如下
int callback(void *arg, int column_size, char *column_value[], char *column_name[])其中 void *arg是sqlite3_exec函数的第四个参数 column_size数据库的字段数 column_value[]列的值 column_name字段名字
了解完上述的几个函数看看该系统代码吧代码中已经详细注释了
#include stdio.h
#include fcntl.h
#include sys/stat.h
#include sys/types.h
#include unistd.h
#include stdlib.h
#include string.h
#include sqlite3.h
#include time.h#define BUFSIZE 32
char sql[128];//用于存放打卡天数和打卡时间
struct Data
{int day;char date[BUFSIZE];
};
sqlite3 *db;
char dbName[32] info.db; //默认创建的数据库名叫info.db/*用来判断info.db数据库是否存在如果不存在则在初始化时创建数据库和表*/
int isExist(void *arg, int column_size, char *column_value[], char *column_name[])
{ if (*column_value[0] 0){*(int*)arg 0; //即将existFlag置为0表示不存在info表格,需要创建 }return 0;
}/*初始化数据库如果已经存在info.db和info表格则不操作如果不存在则自动创建数据库和表并赋初值*/
int db_init()
{int ret;int existFlag 1; //先默认数据库info.db是存在的char *errMesg NULL;if ((ret sqlite3_open(dbName,db)) SQLITE_OK){printf(open %s success\n,dbName);}else{printf(error:%s,%d\n,sqlite3_errmsg(db),ret);return -1;} //查询表格是否存在strcpy(sql,SELECT count(*) FROM sqlite_master WHERE typetable AND name info);ret sqlite3_exec(db,sql,isExist,existFlag,errMesg);if (ret ! SQLITE_OK){fprintf(stderr,SQL error:%s\n,errMesg);sqlite3_free(errMesg); //释放掉内存空间}if (existFlag 0 ){ //创建表strcpy(sql,create table info(day integer,date char););ret sqlite3_exec(db,sql,NULL,NULL,errMesg);if (ret ! SQLITE_OK){fprintf(stderr,SQL error:%s\n,errMesg);sqlite3_free(errMesg);}//往表中插入原始数据strcpy(sql,insert into info values(0,20200101););ret sqlite3_exec(db,sql,NULL,NULL,errMesg);if (ret ! SQLITE_OK){fprintf(stderr,SQL error:%s\n,errMesg);sqlite3_free(errMesg);}}sqlite3_free(errMesg);
}/*用来从数据库中捞取数据*/
int get_data(void *arg, int column_size, char *column_value[], char *column_name[])
{int i;struct Data *dataInfoTmp;dataInfoTmp (struct Data *)arg; //将void型强制转化为 struct Data*型strcpy(dataInfoTmp-date,column_value[1]); //将数据库存放的第二列的值即日期赋给dataInfoTmp-date dataInfoTmp-day atoi(column_value[0]); //将打开天数赋给dataInfoTmp-dayatoi() :Convert char into intreturn 0;
}/*用户确认打卡后刷新数据库数据*/
int sign_in(struct Data *arg)
{struct Data *infoDataTmp NULL;infoDataTmp arg;char *errMesg NULL; int ret; //日期相关time_t timep;struct tm* tm;time(timep);tm localtime(timep);strftime(infoDataTmp-date,BUFSIZE,%Y-%m-%d %H:%M,tm); //将日期字符串制作成自己想要的格式//update the dayinfoDataTmp-day 1;//刷新数据库数据memset(sql,0,sizeof(sql));sprintf(sql,update info set day%d,date%s;,infoDataTmp-day,infoDataTmp-date);ret sqlite3_exec(db,sql,get_data,infoDataTmp,errMesg); if (ret ! SQLITE_OK){fprintf(stderr,SQL error:%s\n,errMesg);sqlite3_free(errMesg);}return 0;
}int main()
{int ret,len;char cmd[BUFSIZE] {\0}; //存放用户输入的指令char *errMesg NULL; struct Data infoData;db_init(); //初始化数据库//捞取数据库数据到结构体infoData中strcpy(sql,select * from info;);ret sqlite3_exec(db,sql,get_data,infoData,errMesg); if (ret ! SQLITE_OK){fprintf(stderr,SQL error:%s\n,errMesg);sqlite3_free(errMesg);}//初始化界面 printf(欢迎来打卡\n);printf(上次打卡是%s,已打卡%d天\n,infoData.date,infoData.day);while(1){memset(cmd,\0,sizeof(cmd));printf(确认打卡请输入Y退出输入Q:\n);scanf(%s,cmd);getchar(); if(strcmp(cmd,Y) 0){sign_in(infoData);printf(已打卡\n);break; }else if (strcmp(cmd,Q) 0){sqlite3_free(errMesg);printf(退出打卡\n);break;}else{printf(输入错误请重新输入:\n); } }return 0;
}其实该程序中的while(1)流程可以考虑开多一个线程或者封装成一个函数这样代码会更加简洁这里小哥就懒得改了大家可以自行修改纯粹就是写着玩玩的所以有写的的不好的地方也欢迎大家指正批评