水果店账单管理系统

一.SQLite相关C接口

如果第一次直接在命令行安装sqlite3,是不包含sqlite3.h这个包的,我们需要单独下载sqlite3支持的库,即通过命令行:

sudo apt install libsqlite3-dev

如果我们不知道该安装什么包来提供sqlite3的C/C++接口,可以通过debian官网通过查询软件包关键词可以知道库是依赖libsqlite3-dev包的。

注意,链接的时候要加上-lsqlite3表示依赖第三方库

关于创建一个数据库,可以通过create table stu (id integer, name text),但是如果连续创建的话会报错,因为已经存在了,所以我们可以使用create table if not exists stu (id integer, name text)来防止重复创建报错。

可以通过句柄来获取错误消息

重要接口

以下是重要的 C&C++ / SQLite 接口程序,基本可以您在 C/C++ 程序中使用 SQLite 数据库的需求。

序号 API & 描述
1 *sqlite3_open(const char *filename, sqlite3 *ppDb) 该例程打开一个指向 SQLite 数据库文件的连接,返回一个用于其他 SQLite 程序的数据库连接对象。如果 filename 参数是 NULL 或 ‘:memory:’,那么 sqlite3_open() 将会在 RAM 中创建一个内存数据库,这只会在 session 的有效时间内持续。如果文件名 filename 不为 NULL,那么 sqlite3_open() 将使用这个参数值尝试打开数据库文件。如果该名称的文件不存在,sqlite3_open() 将创建一个新的命名为该名称的数据库文件并打开。
2 *sqlite3_exec(sqlite3*, const char *sql, sqlite_callback, void *data, char *errmsg) 该例程提供了一个执行 SQL 命令的快捷方式,SQL 命令由 sql 参数提供,可以由多个 SQL 命令组成。在这里,第一个参数 sqlite3 是打开的数据库对象,sqlite_callback 是一个回调,data 作为其第一个参数,errmsg 将被返回用来获取程序生成的任何错误。sqlite3_exec() 程序解析并执行由 sql 参数所给的每个命令,直到字符串结束或者遇到错误为止。
3 sqlite3_close(sqlite3*) 该例程关闭之前调用 sqlite3_open() 打开的数据库连接。所有与连接相关的语句都应在连接关闭之前完成。如果还有查询没有完成,sqlite3_close() 将返回 SQLITE_BUSY 禁止关闭的错误消息。

sqlite3_exec函数原型如下:

int sqlite3_exec(
sqlite3*, /* 数据库句柄 */
const char *sql, /* 执行的SQLite命令 */
int (*callback)(void*,int,char**,char**), /* Callback function */
void *, /* 向回调函数传递的参数是 */
char **errmsg /* Error msg written here */
);

sqlite3_exec()是一个通用函数,可以执行SQLite命令行,相当于间接使用命令行来操作数据库。

打开数据库

直接调用sqlite3_open()打开一个数据库。

检测返回值是否为SQLITE_OK,如果不是,表示出错了,出错信息的获取通过句柄可以获取,如下:

const char *sqlite3_errmsg(sqlite3*);

SQLite有31种返回值,如下:

#define SQLITE_OK           0   /* Successful result */
/* beginning-of-error-codes */
#define SQLITE_ERROR 1 /* Generic error */
#define SQLITE_INTERNAL 2 /* 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 sqlite3_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 /* Unknown opcode in sqlite3_file_control() */
#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 use only */
#define SQLITE_SCHEMA 17 /* The database schema changed */
#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */
#define SQLITE_CONSTRAINT 19 /* Abort due to constraint 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_FORMAT 24 /* Not used */
#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */
#define SQLITE_NOTADB 26 /* File opened that is not a database file */
#define SQLITE_NOTICE 27 /* Notifications from sqlite3_log() */
#define SQLITE_WARNING 28 /* Warnings from sqlite3_log() */
#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */
#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */

插入信息

基于sqlite3_exec()使用命令行语句来插入信息,根据上面所讲,插入的命令行如下:

2-- 插入一条记录
insert into stuinfo values(1001, 'zhangshangngsan', 18, 80);
insert into stuinfo (id, name, score) values(1002, 'lisi', 90);
可以按照全部元素的顺序插入,也可以指定元素插入
插入多条的时候直接在后面加上即可
insert into stuinfo (id, name, score) values(1002, 'lisi', 90), (1001, 'zhangshan', 18, 80);

先读取到要插入的信息,然后使用sprintf函数格式化为字符串,最后将字符串传递给sqlite3_exec()的第二个参数const char *sql来执行命令行操作数据库。

查询

查询有两种基础方法

  • 基于sqlite3_exec和回调函数,参考链接:https://sqlite.org/c3ref/exec.html
  • 直接使用sqlite3_get_table函数,参考链接:https://sqlite.org/c3ref/free_table.html

sqlite3_exec函数原型如下:

int sqlite3_exec(
sqlite3*, /* 数据库句柄 */
const char *sql, /* 执行的SQLite命令 */
int (*callback)(void*,int,char**,char**), /* Callback function */
void *, /* 向回调函数传递的参数是 */
char **errmsg /* Error msg written here */
);

sqlite3_exec()是一个通用函数,可以执行SQLite命令行,相当于间接使用命令行来操作数据库。

查询的结果通过回调函数反馈,有几行记录,就调用几次回调函数,所以每次回调函数的执行都是对一行信息的查询。

关于回调函数有如下说明:

  • 有几条记录就会调用几次回调函数
  • 回调函数的参数通过sqlite3_exec的第三个参数传递,给回调函数的第一个参数
  • 每条记录中有几列,就会传给第二个参数column
  • 第三个参数就是对应字段内容 char **value,以字符串的形式传递
  • 第四个参数char ** name就是字段名
  • 二级指针的用法和main函数的参数 char *argv[]一样
  • 回调函数返回的应该是0 表示正确,返回1代表出错

回调函数的定义可以如下:

static int callback(void *data, int argc, char **argv, char **azColName){
int i;
for(i=0; i<argc; i++){
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}

还有,可以通过sqlite3_get_table来获取表信息,sqlite3_get_table 专门用于查询语句,不需要回调了:

int sqlite3_get_table(
sqlite3 *db, /* 句柄 */
const char *zSql, /* SQL to be evaluated */
char ***pazResult, /* 获取的表信息,传递参数时直接一个二维数组的地址 */
int *pnRow, /* 行数,包括数据名称 */
int *pnColumn, /* 列数 */
char **pzErrmsg /* 出错信息 */
);

直接通过行数和列数来输出信息,不过要注意的是,返回到的查询信息,开始是表的数据名称,后面才是每个行的内容。

二.程序要求

假如我家开了个水果超市,有以下水果,想实现自动化管理,扫描二维码就能知道当前的水果状态,进货几天了,
好久需要再次进货,那些水果畅销,那些水果不畅销,那些水果春夏秋冬的价格波动,好,那么现在我想将
这些信息保存在数据库中,那么我应该怎么做;
提示: 建立一张fruit表,
假如水果有: 苹果,香蕉,梨,橘子,葡萄…(可以自己查一下英文保存到数据库)
水果价格: 苹果 5元/斤 香蕉 3元/斤 梨 3.5元/斤 橘子2.5元/斤 葡萄 8元/斤…
当前存货: 苹果 80斤 香蕉 200斤 梨 50斤 橘子300斤 葡萄 100斤…
超市每天水果都有进货和卖出嘛,水果的价格随着季节和天气也会有波动,顾客也会看一下每天水果的价格的嘛,
所以要求,根据上述提示,利用数据库完成水果店各种水果的增(进货)删(卖出)改(波动)查(看价格)功能。
并将进出货的时间和顾客光顾的时间记录到数据库中保存。

三.程序说明

题目要求:
所以要求,根据上述提示,利用数据库完成水果店各种水果的增(进货)删(卖出)改(波动)查(看价格)功能。
并将进出货的时间和顾客光顾的时间记录到数据库中保存。 程序执行:
直接make即可 显示界面,按照指示输入指令即可实现上述所有功能
make clean用于清除二进制可执行文件 程序说明:
main函数中循环执行菜单栏目
根据用户在菜单栏目中的输入跳转到相应的功能区执行,每项功能都封装在一个函数中
功能区描述如下:
int menu(void); //菜单
|
----void select_fruit(void); //产看所有货物信息
void add_fruit(void); //增加新货物信息
void delete_fruit(void); //删除货物信息
void upadte_fruit(void); //更新信息
|
----void purchase_control(void); //进货
void sell_control(void); //售卖
void price_change(void); //价格变动 更新信息中可以进行:进货、售卖、价格变动等操作,也可退回上一菜单 进货时间在进货、增加货物信息的时候更新
顾客光顾时间在售卖的时候更新

四.实现代码

#include <stdio.h>
#include <sqlite3.h>
#include <stdlib.h>
#include <string.h>
#include <time.h> static int callback(void*,int,char**,char**); int menu(void); //菜单
void select_fruit(void); //产看所有货物信息
void add_fruit(void); //增加新货物信息
void delete_fruit(void); //删除货物信息
void upadte_fruit(void); //更新信息 void purchase_control(void); //进货
void sell_control(void); //售卖
void price_change(void); //价格变动 static char sql[128] = {0};
static sqlite3 *ppdb; //句柄
static int ret;
#define BUFLEN 255
char tmpBuf[BUFLEN]; //时间字符串 int main(int argc, const char *argv[])
{
int n; //open the SQLite3
if (sqlite3_open("./fruit.db", &ppdb) != SQLITE_OK) {
printf("open filed:%s\n", sqlite3_errmsg(ppdb));
exit(1);
} time_t t = time( 0 );
strftime(tmpBuf, BUFLEN, "%Y-%m-%d %H:%M", localtime(&t));
printf("%s\n\n\n", tmpBuf); //创建数据库,在系统初始化的时候使用一次
// memset(sql, 0, sizeof(sql));
// sprintf(sql, "create table fruit (name, price, stockpile, purchase_time, sell_time);");
// ret = sqlite3_exec(ppdb, sql, NULL, NULL, NULL);
// if (ret != SQLITE_OK) {
// printf("create filed:%s\n", sqlite3_errmsg(ppdb));
// exit(1);
// } while (1) {
n = menu(); switch (n)
{
case 1:
select_fruit();
break;
case 2:
add_fruit();
break;
case 3:
upadte_fruit(); //包括 进货、售出、价格修改
break;
case 4:
delete_fruit();
break;
case 5:
sqlite3_close(ppdb);
exit(0); default:
printf("wrong number!!!\n");
break;
}
} return 0;
} int menu(void)
{
int n; printf("---- Welcome to GQ's Fruit commodity management system! ----\n");
printf("- (please input the number as follows) -\n");
printf("- 1.select all commodity -\n");
printf("- 2.add commodity -\n");
printf("- 3.upadte commodity -\n");
printf("- 4.delete commodity -\n");
printf("- 5.exit system -\n");
printf("------------------------------------------------------------\n");
printf("input number here:");
scanf("%d", &n); return n;
} //查看所有货物信息
void select_fruit(void)
{
memset(sql, 0, sizeof(sql));
sprintf(sql, "select * from fruit;");
ret = sqlite3_exec(ppdb, sql, callback, NULL, NULL); //useing callback function
if (ret != SQLITE_OK) {
printf("select filed:%s\n", sqlite3_errmsg(ppdb));
exit(1);
}
printf("select ok!\n\n\n");
} static int callback(void *data, int column_number, char *column_data[], char *column_name[])
{
int i; for (i = 0; i < column_number; i++) {
if (i == column_number-1)
printf("%13s=%7s ", column_name[i], column_data[i]);
else
printf("%13s=%9s , ", column_name[i], column_data[i]);
}
puts("");
return 0;
} //完成添加新货物信息
void add_fruit(void)
{
char name[10];
float price;
int stockpile; printf("please input the fruit message:\n");
printf(" name price stockpile \n>"); scanf("%s", name);
scanf("%f", &price);
scanf("%d", &stockpile);
getchar(); //吃掉回车 time_t t = time( 0 );
strftime(tmpBuf, BUFLEN, "%Y-%m-%d %H:%M", localtime(&t)); memset(sql, 0, sizeof(sql));
sprintf(sql, "insert into fruit values('%s', %f, %d, '%s', NULL);", name, price, stockpile, tmpBuf);//注意冒号
ret = sqlite3_exec(ppdb, sql, NULL, NULL, NULL);
if (ret != SQLITE_OK) {
printf("add filed:%s\n", sqlite3_errmsg(ppdb));
exit(1);
}
printf("add success!\n\n\n");
} //完成删除货物信息
void delete_fruit(void)
{
char name[10]; printf("input delete fruit:");
scanf("%s", name);
getchar(); memset(sql, 0, sizeof(sql));
sprintf(sql, "delete from fruit where name='%s';", name);//注意冒号
ret = sqlite3_exec(ppdb, sql, NULL, NULL, NULL);
if (ret != SQLITE_OK) {
printf("delete filed:%s\n", sqlite3_errmsg(ppdb));
exit(1);
}
printf("delete %s success\n\n\n", name);
} //完成进货、卖出、价格波动
void upadte_fruit(void)
{
int n; printf("---- Welcome to GQ's Fruit commodity management system! ----\n");
printf("- (please input the number as follows) -\n");
printf("- 1.purchase control -\n");
printf("- 2.sell control -\n");
printf("- 3.price change -\n");
printf("- 4.last step -\n");
printf("- 5.exit system -\n");
printf("------------------------------------------------------------\n");
printf("input number here:");
scanf("%d", &n); switch (n)
{
case 1:
purchase_control();
break;
case 2:
sell_control();
break;
case 3:
price_change();
break;
case 4:
return ;
break;
case 5:
sqlite3_close(ppdb);
break;
default:
break;
}
} void purchase_control(void)
{
char name[10];
int stockpile; printf("input fruit name:");
scanf("%s", name);
getchar(); printf("input purchase quantity:");
scanf("%d", &stockpile);
getchar(); sprintf(sql, "update fruit set stockpile=%d where name='%s';", stockpile, name);
ret = sqlite3_exec(ppdb, sql, NULL, NULL, NULL);
if (ret != SQLITE_OK) {
printf("purchase_control filed:%s\n", sqlite3_errmsg(ppdb));
exit(1);
}
printf("purchase_control %s success\n\n\n", name); } void sell_control(void)
{
char name[10];
int stockpile; printf("input fruit name:");
scanf("%s", name);
getchar(); printf("input new stockpile:");
scanf("%d", &stockpile);
getchar(); time_t t = time( 0 );
strftime(tmpBuf, BUFLEN, "%Y-%m-%d %H:%M", localtime(&t)); sprintf(sql, "update fruit set stockpile=%d ,sell_time='%s' where name='%s';", stockpile, tmpBuf, name);
ret = sqlite3_exec(ppdb, sql, NULL, NULL, NULL);
if (ret != SQLITE_OK) {
printf("sell_control filed:%s\n", sqlite3_errmsg(ppdb));
exit(1);
}
printf("sell_control %s success\n\n\n", name);
} void price_change(void)
{
char name[10];
float price; printf("input fruit name:");
scanf("%s", name);
getchar(); printf("input new price:");
scanf("%f", &price);
getchar(); sprintf(sql, "update fruit set price=%f where name='%s';", price, name);
ret = sqlite3_exec(ppdb, sql, NULL, NULL, NULL);
if (ret != SQLITE_OK) {
printf("price_change filed:%s\n", sqlite3_errmsg(ppdb));
exit(1);
}
printf("price_change %s success\n\n\n", name);
}

Linux下基于SQLite3 实现商店商品管理系统的更多相关文章

  1. Linux下基于LDAP统一用户认证的研究

    Linux下基于LDAP统一用户认证的研究                   本文出自 "李晨光原创技术博客" 博客,谢绝转载!

  2. Linux下基于.NET5开发CAX应用

    <<.NET5下的三维应用程序开发>>一文中介绍了如何在.NET5下使用AnyCAD开发应用程序.相比.NET4.x,.NET5一大进步便是可以跨平台,即可以在Linux.Ma ...

  3. Linux下基于LVM调整分区容量大小的方法

    Linux下调整分区容量大小的方法(适用于centos6-7) 说明:以下方法均使用centos6.9和centos7.4进行测试. Centos6分区容量调整方法 1.web分区空间不足,新添加一块 ...

  4. Linux下基于多线程的echo

    准备开始写一些Linux 下网络编程以及多线程的blog,就从这个简单的echo程序开始吧. 在echo的服务端使用多线程与客户进行通信,可以实现一个服务端程序同时连接多个客户的功能.那么,到底在服务 ...

  5. linux下安装sqlite3

    1.介绍:sqlite3是linux上的小巧的数据库,一个文件就是一个数据库.2.安装:  要安装sqlite3,可以在终端提示符后运行下列命令:  sudo apt-get install sqli ...

  6. Linux下基于shell脚本实现学生信息管理系统

    #该管理系统是参考两位博主(时间有点远了,我忘了,请博主看到后联系我)后自行修改添加的.登录过程还有很多不完善,我就抛砖引玉啦. 废话不多,直接上码! #!/bin/bash# 学生管理系统# @ve ...

  7. ubuntu下基于sqlite3后台的php环境的搭建

    最近准备把公司的服务器换成linux 数据库sqlite3 搭建过程记录如下: 1 sqlite3安装.. apt-get install sqlite 2.PHP服务器搭建. apt-get ins ...

  8. Linux下基于源代码方式安装MySQL 5.6

    MySQL为开源数据库,因此能够基于源代码实现安装.基于源代码安装有很多其它的灵活性. 也就是说我们能够针对自己的硬件平台选用合适的编译器来优化编译后的二进制代码.依据不同的软件平台环境调整相关的编译 ...

  9. Linux下基于PAM机制的USB Key的制作

    摘自:https://server.zzidc.com/fwqpz/157.html USB Key这个概念最早是由加密锁厂家提出来的,加密锁是用来防止软件盗版的硬件产品,加密锁的概念是使安装在计算机 ...

随机推荐

  1. [Vue入门及介绍,基础使用、MVVM架构、插值表达式、文本指令、事件指令]

    [Vue入门及介绍,基础使用.MVVM架构.插值表达式.文本指令.事件指令] 1)定义:javascript渐进式框架 ​ 渐进式:可以控制一个页面的一个标签,也可以控制一系列标签,也可以控制整个页面 ...

  2. Redhat 6.9 升级SSH到OpenSSH_8.6p1完整文档

    这个文章是转载,原文连接在这个:https://www.cnblogs.com/xshrim/p/6472679.html 这个问题遇到过,下面可以解决 ----------------------- ...

  3. docker起不来报错:Failed to start Docker Application Container Engine.

    报错信息如下: [root@localhost localdisk]# systemctl restart docker Job for docker.service failed because t ...

  4. 安装PyTorch后,又安装TensorFlow,CUDA相关问题思考

    下面的话是我的观察和思考,请多多批评. TensorFlow 要用 CUDA.CUDA toolkit.CUDNN,看好版本的对应关系再安装,磨刀不误砍柴工. 1)NVIDIA Panel 里显示的N ...

  5. Dapper的基本使用 [转]

    Dapper是.NET下一个micro的ORM,它和Entity Framework或Nhibnate不同,属于轻量级的,并且是半自动的.也就是说实体类都要自己写.它没有复杂的配置文件,一个单文件就可 ...

  6. 章节1-Prometheus基础(1)

    目录 一.Prometheus安装部署 1. 简介 监控的目的 Prometheus的优势 2. Prometheus工作流程: 2.1 服务端 2.2 客户端 2.3 metrics主要数据类型 3 ...

  7. python使用笔记006-函数+json操作

    一.函数 函数:提高代码的复用性 1.1 函数的定义 1 def hello(): 2 print('hello') 3 print('fdsfjslkfs') 4 5 #函数不调用就不会执行 6 h ...

  8. Scala学习——函数

    一.函数的定义(def) object FunctionApp { //定义函数:方法体内最后一行为返回值,不需要使用return def add(a:Int,b:Int):Int={ a + b } ...

  9. CRUD搬砖两三年了,怎么阅读Spring源码?

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! ‍连读同事写的代码都费劲,还读Spring? 咋的,Spring 很难读! 这个与我们码农朝夕 ...

  10. sqliab刷题笔记-联合注入

    Less-1 测试是字符型还是数字型 判断所在字段数 查看显示值 可以看出显示2,3位置.因此我们选择2的位置进行联合注入 查看表名 我们要对admin,users等字符敏感 查看admin表中的字段 ...