【LinuxC Sqlite数据库小项目】基于Sqlite的打卡系统------适合初学者练手的小项目
最近小哥老是想浪,不想好好学习,这不行啊,得想点办法,多少做点努力,于是就自己给自己写了个打卡程序;
该程序基于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 type='table' 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->day,atoi() :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)流程可以考虑开多一个线程或者封装成一个函数,这样代码会更加简洁,这里小哥就懒得改了,大家可以自行修改;纯粹就是写着玩玩的,所以有写的的不好的地方也欢迎大家指正批评;
相关文章:
【LinuxC Sqlite数据库小项目】基于Sqlite的打卡系统------适合初学者练手的小项目
最近小哥老是想浪,不想好好学习,这不行啊,得想点办法,多少做点努力,于是就自己给自己写了个打卡程序; 该程序基于Sqlite数据库,实现一个简单的打卡功能,该函数具有自动初始化的功能…...
在掌握C#基础上再学习C语言
C#和C语言虽然名字相似,但它们在很多方面都有很大的区别。 首先,C#是一种面向对象的语言,而C语言是过程化的语言。这意味着C#具有更丰富的语言特性,如类、接口、继承和多态性等,而C语言则更侧重于直接对计算机硬件进行…...
HTML5 <body> 标签
HTML <body> 标签 实例 一个简单的 HTML 文档,包含尽可能少的必需的标签: <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>文档标题</title> </head><body> 文档内容…...
(链表)反转链表
文章目录前言:问题描述:解题思路:代码实现:总结:前言: 此篇是针对链表的经典练习。 问题描述: 给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1…...
deb文件如何安装到iphone方法分享
Cydia或同类APT管理软件在线安装 Cydia或同类APT管理软件在线安装,这个是最佳的安装方式,因为通常无需考虑依赖关系,但缺点是对网络的要求比较高;命令行中以dpkg-iXXX.deb的形式安装,好处是可以以通配符一次性安装多个deb,而且也可以直接看到脚本的运行状况和安装成功/失…...
mongodb和mysql双写数据一致性问题
文章目录 我们是如何用MongoDB的如何保证双写一致性?先写数据库,再写MongoDB先写MongoDB,再写数据库用户修改操作如何保存数据如何清理新增的垃圾数据定时删除随机删除我们是如何用MongoDB的 MongoDB是一个高可用、分布式的文档数据库,用于大容量数据存储。文档存储一般用…...
Databend 开源周报第 88 期
Databend 是一款现代云数仓。专为弹性和高效设计,为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务:https://app.databend.com 。 Whats On In Databend 探索 Databend 本周新进展,遇到更贴近你心意的 Databend 。 Support Eager…...
Vue3学习笔记(9.4)
Vue3自定义指令 除了默认设置的核心指令(v-model和v-show),Vue也允许注册自定义指令。 下面我们注册一个全局指令v-focus,该指令的功能是在页面加载时,元素获得焦点: <!--* Author: RealRoad10834252…...
导入 Excel 文件时,抛出 413 (Request Entity Too Large) 错误
Excel文件大小:8MB 异常信息:413 (Request Entity Too Large) 环境:IIS10PHP7.2.33 依次检查如下几项: 一、php.ini Maximum amount of memory a script may consume (128MB) 限制代码消耗的最大内存,默认128…...
Verilog学习笔记1——关键词、运算符、数据类型、function/task、initial/always、generate
文章目录前言一、关键词二、运算符三、数据类型1、基本类型:reg、wire、integer、parameter四、条件语句五、循环语句1、for2、generate六、function和task七、initial和always1、initial和always相同点和区别2、always和assign语句区别前言 2023.4.4 2023.4.7 补充…...
探索LeetCode【0005】最长回文子串(未搞懂,未练习)
目录0、题目1、第一个官方答案1.1 动态规划(未懂)1.2 中心扩展(已懂)1.3 Manacher(未懂)2、第二个参考答案2.1 暴力求法(已懂)2.2 反转法(未懂)2.3 动态规划&…...
使用 Docker run 命令简化容器化
使用 Docker run 命令简化容器化 Docker run 是在 Docker 容器中运行应用程序的基本命令。在开始使用 Docker 之前,了解一些重要的命令非常重要。 在本博客中,我们将解释 Docker run 命令的基本语法,并探索其一些最常见的选项,以…...
腾讯TNN神经网络推理框架手动实现多设备单算子卷积推理
文章目录前言1. 简介2. 快速开始2.1 onnx转tnn2.2 编译目标平台的 TNN 引擎2.3 使用编译好的 TNN 引擎进行推理3. 手动实现单算子卷积推理(浮点)4. 代码解析4.1 构建模型(单卷积层)4.2 构建解释器4.3 初始化tnn5. 模型量化5.1 编译量化工具5.2 量化scale的计算5.3 量化流程6. i…...
基础解惑:Linux 下文件描述符标志和文件状态标志区别
简述 文件描述符标志,是体现进程的文件描述符的状态,fork进程时,文件描述符被复制;目前只有一种文件描述符:FD_CLOEXEC文件状态标志,是体现进程打开文件的一些标志,fork时不会复制file 结构&am…...
学弟:如何在3个月内学会自动化测试?
有小学弟问:如何在3个月内学会自动化测试? 老实说如果你现在上班,之前主要在做功能测试,或者编程基础比较弱的话,三个月够呛。 如果你是脱产学习,每天能保持6~8小时学习时间的话,可…...
C-NCAP 2025主动安全ADAS测试研究
中汽中心汽车测评管理中心(简称“中汽测评”)是负责运营C-NCAP、CCRT等测评项目的管理机构。中汽测评以引领汽车行业进步、支撑汽车强国建设为使命,通过独立、公正、专业、开放的测试评价,服务消费者,当好选车购车参谋…...
【Apifox】测试工具自动编写接口文档
在开发过程中,我们总是避免不了进行接口的测试, 而相比手动敲测试代码,使用测试工具进行测试更为便捷,高效 今天发现了一个非常好用的接口测试工具Apifox 相比于Postman,他还拥有一个非常nb的功能, 在接…...
解决brew安装opencv报错问题
目录1.报错12. 解决方案3. 报错24. 解决方案4.1 原因分析4.2 手动下载portable-ruby-2.6.8_1.el_capitan.bottle.tar.gz4.3 拷贝portable-ruby-2.6.8_1.el_capitan.bottle.tar.gz到指定目录1.报错1 mac本用brew报如下错误: xialiangzhideMacBook-Pro:~ xialz$ bre…...
Linux软件安装---Tomcat安装
安装Tomcat 操作步骤: 使用xftp上传工具将tomcat的 二进制发布包上传到Linux解压安装包,命令为tar -zxvf apache-tomcat*** -C /usr/local进入Tomcat的bin的启动目录,命令为sh startup.sh或者./startup.sh 验证Tomcat启动是否成功࿰…...
提示工程师是什么工作?
提示工程师是什么工作? 因为ChatGPT的爆火,大家都把眼光锁定在这个号称“ChatGPT新兴职业” 的“提示工程师”上。“提示工程师”是什么工作?为什么说未来所有职业 都需要提示工程的能力? 先解释一下“提示”,它最早…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
Windows安装Miniconda
一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...
破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...
在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南
在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南 背景介绍完整操作步骤1. 创建Docker容器环境2. 验证GUI显示功能3. 安装ROS Noetic4. 配置环境变量5. 创建ROS节点(小球运动模拟)6. 配置RVIZ默认视图7. 创建启动脚本8. 运行可视化系统效果展示与交互技术解析ROS节点通…...
【java面试】微服务篇
【java面试】微服务篇 一、总体框架二、Springcloud(一)Springcloud五大组件(二)服务注册和发现1、Eureka2、Nacos (三)负载均衡1、Ribbon负载均衡流程2、Ribbon负载均衡策略3、自定义负载均衡策略4、总结 …...
