水果店账单管理系统

一.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. Laravel使用Observer(观察者)

      1.创建observer文件,我这里是要记录仓库库存模块的操作日志,所以执行下面的语句,会在app/Observers下面创建WarehouseInventoryObserver文件. php a ...

  2. Redis中的布隆过滤器及其应用

    什么是布隆过滤器 布隆过滤器(Bloom Filter)是由Howard Bloom在1970年提出的一种比较巧妙的概率型数据结构,它可以告诉你某种东西一定不存在或者可能存在.当布隆过滤器说,某种东西 ...

  3. 重新梳理调度器——GMP 调度模型

    调度器--GMP 调度模型 Goroutine 调度器,它是负责在工作线程上分发准备运行的 goroutines. 首先在讲 GMP 调度模型之前,我们先了解为什么会有这个模型,之前的调度模型是什么样 ...

  4. SEO入门一篇就够-SEO教程

    大家口中的SEO(Search Engine Optimization),中文翻译为"搜索引擎优化",从本质上来说,其实就是如何迎合搜索引擎的规则,使得网站在搜索结果中能有更好的排 ...

  5. python 获取当前py文件所在的位置 及对应的文件名称

    # 导入sys整个模块 import sys # 使用sys模块名作为前缀来访问模块中的成员 print(sys.argv[0]) 当前文件名:12.py 程序运行结果: ============== ...

  6. 从sql2008导入表结构及数据到mysql

    打开navicat for mysql连接mysqlcreate database lianxi刷新,双击lianxi,双击"表"点击右边的"导入向导"选择&q ...

  7. Java基础00-反射35

    1. 类加载器 深入理解java类加载器类加载器 1.1 类加载 类加载或类初始化的三个步骤:类的加载.类的连接.类的初始化 加载:类加载过程的一个阶段:通过一个类的完全限定查找此类字节码文件,并利用 ...

  8. Spring RestTemplate 之put、delete请求

    ●PUT请求:在RestTemplate中,PUT请求可以通过put方法调用,put方法的参数和前面介绍的postForEntity方法的参数基本一致,只是put方法没有返回值而已.举一个简单的例子, ...

  9. deepin安装Motrix,cocomusic

    1,motrix(下载工具):https://motrix.app/ 2,cocomusic(开源音乐播放器):https://github.com/xtuJSer/CoCoMusic/release ...

  10. ArcGis Server安装与使用

    ArcGis Server安装 下载ArcGisServer 双击Setup.exe,然后一直下一步. 安装完成后,点击完成,弹出如下界面: 选择第三个选项,然选择[.ecp]后缀名的授权文件. 然后 ...