基于C语言+SQLite 实现(控制台+图形界面)图书管理系统

♻️ 资源

大小: 10.2MB

➡️ 资源下载: https://download.csdn.net/download/s1t16/87453187

图书管理系统

一. 程序概览

1.简介

本程序具有图书管理的功能,以 CLI1 作为主要交互方式,辅以少量图形界面 2 用于优化用户体验。程序兼容 Windows 和各种发行版 Linux 系统。

设置页面 图形界面修改图书

主页面

2.基础功能

如图所示,本程序作为日常使用具有上述基础功能。在后续章节中将陆续介绍本程序的全部功能。

另外,我们为部分值得一提的基础功能做了进一步的说明。

·图形界面

在处理数据时,命令行窗口的能力略显不足。图形界面相对来说更加用户友好,而且一本图书的数据可以一目了然,在原地编辑,最后只需一下回车即可完成数据增改。考虑到跨平台问题,图形界面只作为额外功能在 Windows 系统中提供。

·高级筛选

价格在 15~30 元之间,并且适合儿童阅读、库存充足的书。或是,近期打折力度超过 8 折、阅读量火爆且出自村上春树笔下的书。再或者,由清华大学出版社、高等教育出版社或人民邮电出版社三者之一所出版的图书。高级筛选支持相等(相同)、(数值或字典顺序上的)大于小于、不等于(不同)和形似于共 5 种条件,支持条件混搭,可以完成绝大多数的筛选需求。另外,条件组可以作为文件导入导出。

·多源导入

一般情况下,从外部数据文件批量导入图书时,要求数据文件严格遵守固定的格式、结构。本程序将"外部文件格式"作为一项独立的设置项目,用户可以定义多种格式约定,并使其同时生效。导入时,只需先选择一项预设约定,便可以导入任意结构的文档,甚至是 Excel 文档 3。

·回收站机制

iOS 和 Android 的官方相册 App 陆续加入了「最近删除」功能,相当实用。我们进行了借鉴,并且在此基础上,去掉了删除图书时的确认提示,使得平时的删除操作既便捷又可逆。

·读者反馈

这里是读者归还图书的通道。在归还的同时,对应图书的借阅次数增加 1 次,然后读者自愿为图书进行 0~5 星的评分。程序根据总分数量和总借阅次数计算一本图书的推荐指数。如果读者放弃评分,当次借阅也将视为无效,不计入统计。

·密码找回机制

用户可随时设置密码保护问题。其采取一问一答形式,用户通常根据一些仅自身拥有的记忆来设问,以确保仅用户本人持有答案。当忘记管理员密码时,如果曾经设置过密码保护问题,可以尝试找回。问题原文将呈现给任何操作者,其中能够给出正确回答的人,将有权立刻重设或清除管理员密码。

以下运行时截图作为本章的补充说明。

图书概览

测试数据中未提供分类、分级,故未显示。

图形界面修改图书 高级筛选

销售系统

图中资金流动仅为模拟,并未实现真实货币交易

多源导入

密码验证

借阅模式

第 N 排序依据

安全模式

单页最大图书数

二. 程序特点

·总览

图中"快速概览"即模糊查询功能,"借阅模式"即读者反馈与销售系统。这是在项目合并时出现的称呼差异。

图中所展示的是本程序的完整结构。

我们尽全力削减硬编码的数量。因此,本程序所用的全部数据,包括但不限于图书表头、语言文字、图书各属性数据类型,皆外置为配置文件,甚至可以在运行时更改,而程序本身只处理必要逻辑。

这为本程序特点功能的开发打下了基础。

1.SQLite 数据库与 AES256 加密

要维护大量的数据,如果不选用合适的数据存储方案,是很不明智的。我们使用开源、轻量级的 SQLite 数据库作为数据存储方案。

同时,数据安全是必须解决的问题。我们将 AES256 加密应用于 SQLite 中,极大程度保障了数据安全。

强度较弱的 AES128 或 AES192 加密算法已经足以将绝大多数破译者拒之门外,因此 AES256 目前可以认为非常安全。

"自定义 SQLite 语句"功能

2.数据云同步

此功能将所有用户数据(包括密码,但除条件组文件外)备份至云端,并支持在其它运行本程序的设备上将数据下载。

数据云同步为图书数据迁移提供了极大便利。但是由于个人服务器性能原因,无法保证当数据量大(约十万条以上)时的传输速度。

本程序与云端建立的是符合苹果 ATS 规范的 HTTPS 连接。即使用户数据本身已经是加密的,也要尽可能提升安全等级。

3.可编程性

右侧的文件,根据本程序设定,是作为一个"图书管理系统"所应具有的表头数据。

取其中三行作为示例:

0=STR_BOOK_NAME,TEXT

1=STR_BOOK_PRICE,REAL

order=6,0,9,3,8,4...

第一行表明,第 0 项数据的名字是 STR_BOOK_NAME,它的数据类型为 TEXT4.

第二行表明,第 1 项数据的名字是 STR_BOOK_PRICE,它的数据类型为 REAL5.

第三行表明,表头从左至右的顺序是:第 6 项、第 0 项、第 9 项,以此类推。

简而言之,本程序的这一特点,允许用户自定义所有的数据项。

我们预置了图书的数据项(书名、价格等),它就成为"图书管理系统"。 如果预置学生的数据项(学号、成绩等),它就成为"学生管理系统"。 如果预置票务的数据项(场次、人员等),它就成为"票务管理系统"。

...

4.I18N(国际化)

程序内部没有任何自然语言字符串,全部自然语言外置在独立的语言文件中, 并拥有一定的模板功能。本程序的语言文字可以随时更新。

我们并赋予程序 Unicode 字符集。因此,不论是哪个国家的语言,日语、繁 中、法语、俄语、韩语...只需写好语言文件,程序便可支持。

但是从代码片段中可以看到,即使顾及了全球语言,开发成本也并不高。

另外,这是修改图书信息的代码片段。短短两三行代码就完成了读取设置、验证密码的工作。这些都得益于模块化设计。

5.Linux 兼容

"在一台运行 Windows 系统的电脑上添加几本图书,然后云同步至运行 CentOS 的服务器上长期保存。"

借助 C 语言的跨平台优势,这一功能并不难实现。Linux 版可以享受到除图形界面以外的全部功能。

在 Ubuntu16.04LTS 环境下编译运行

三. 压力测试

1.测试内容

我们生成了包含 100 万条图书数据的文件,并将其导入数据库中。

导入时标记时间的截图

导入后

数据文档

测试环境使用 IntelCorei7-7700HQ 处理器。数据导入时,硬盘 IO 量保持在极低水平。

在对新数据实时进行 AES256 高强度加密的情况下,导入 100 万条数据用时 18 分钟。导入完成后,程序运行流畅如初。筛选、排序等操作基本未受影响。

2.结论

数据量在 0~100 万之间时,程序运行稳定、处理数据所需时间均匀上升,但仍然高效(可立即完成筛选、排序等操作)。因此,可以胜任多数图书馆的电子档案管理。

截至 2018 年 7 月 17 日,美国国会图书馆作为世界最大图书馆,存有书籍约 1.5 亿册,其中超过 2/3 的书籍(约 1 亿)通过多媒体存储。1 亿是 100 万的 100 倍,从本程序目前的表现来说,如果不计书籍内容,有可能在效率下降幅度较低的情况下实现 1 亿存储量。

四. 技术性细节

1.libcurl 与 OpenSSL 的利用

本程序的"数据云同步"功能使用了开源项目 libcurl 作为底层库。然而 libcurl 并不支持 SSL 协议,于是我们使用 OpenSSL 作为支持库重新编译了 libcurl 使其满足我们的要求。

2.程序流程图

高清版本

program.png

由于功能较多,流程图中没有体现部分细节。

3."三权分立"

本程序内部结构分层以及各个模块职能大致如下。

高清版本

arch.png

根据各类模块职能不同,整个程序可划分为三层:UI 层、数据层和安全层。其中安全层禁止主动进行 UI 交互。

UI 层处理程序的流程逻辑,如各级菜单间的切换、菜单的打印、语言文字的输出。封装在 UI 层的函数以 UI或 CP开头。

DATA 层即数据层。它对图书数据加工、负责编码转换、进行外部库的引入、实现全部特点功能,并为程序提供一套内存管理方案。封装在其中的函数以 BA或 NU开头。

LM 层即安全层。它封装各种数据库操作、负责密码和密保问题的验证、更改。它所使用的内存"阅后即焚",非专业跟踪技巧难以捕捉它的举动。封装的函数以 LM或 SM开头。

4.反省、问题与收获

·改进空间

·没有解决多用户使用、用户权限分级这一刚需,以及远程数据库。如果能采用远程数据库,安全性将得到巨大提升。

·代码注释大多是给自己看的,没考虑到别人能否完全理解。

·未使用版本控制工具,考虑到团队很小,没有必要。

·对于一些编码转换函数,应尝试写出不依赖非 C 标准库的更通用的算法,减少在代码中穿插的(用于判断操作系统的)预处理器宏。

·程序二进制文件未做额外保护(如加壳),且全部密码验证走同一关键跳,易被爆破从而绕过密码验证。

·遇到的问题

开发过程总体相对顺利,但遇到的唯一问题非常棘手,贯穿整个开发过程。通俗的说,这一问题导致大量语言文字"乱码"。另外,由于类似原因,数据库无

法支持非纯英文的 like 子句查询。这一问题导致本程序无法实现"(11 )可以根据部分书名查询图书,如查询"钢铁"+"炼成",可以查到"钢铁是怎样炼成的"这本书"这一基本要求,从而险些导致我们重写整个高级筛选功能。

·问题的解决

最初我们使用宽字符(wchar_t)替代字符型(char)作为数据存储,即 UCS-2LE,并在 UI 层预置转换函数使其能够呈现。没想到在 Linux 系统中 wchar_t 被规定为占 4 字节(Windows 系统中是 2 字节),这一规定使得程序编码体系完全被破坏,如果继续使用宽字符,将无法兼容 Linux 系统。

随后,我们重新用回 char 类型,重写相关代码,并进行了两天的学习,采用 GBK 编码临时解决了系统兼容问题。

然而 GBK 编码显然不能满足国际化的要求,它只映射了简繁中文。同时我们发现,高级筛选功能中,"形似于"条件在部分情况下异常。在测试环境中,存有一本名为"钢铁是怎样炼成的"的图书,使用

复制代码
select * from book where STR_BOOK_NAME like '%钢铁%' and STR_BOOK_NAME like '%炼成%';

无法筛选出任何结果,但

复制代码
select * from book where STR_BOOK_NAME like '%钢铁%';

的筛选结果正常。经过半天学习,得知 SQLite 数据库默认使用 UTF-8 编码。我们正有此意,于是在 sqlite3_exec 的 wrapper 中给每条 SQL 语句转换了编码,至此全部问题解决。

·收获

·应在开发初期确定程序所用字符集以及编码。

·外部库的接口应封装一层,以便参数有误时调试。

·不要用 C++ 编译器编译 C 程序。

·使用宽字符串常量时,不要偷懒使用 L"...",最好封装一个宏,类似

#defineTEXT(x)L#x

·C 语言是支持枚举类型的。

5.开发、构建/测试环境与组内分工

本程序及其所用开源库,皆由纯 C 语言实现。

为了实现"数据云同步"功能,在服务器上使用了少量 PHP.

|--------------|----------------------------------------------------------------------|
| IDE(Windows) | MicrosoftVisualStudioCommunity2017 |
| IDE(Linux) | OracleNetBeans8.2 |
| 编译器(Windows) | MSVC(_MSC_VER=1913)/W4 |
| 编译器(Linux) | LLVM+Clang3.8.0/W4 |
| 开发环境 | Windows10(Build14393) |
| 测试环境 | Windows7(Build7601)Windows10(Build14393)WindowsXP(SP3)Ubuntu16.04LTS |

组内分工如下。

组员邓正望的分工相对较少,但其工作非常重要。部分分工明细如下。

·全部函数间调用的传参正确性检查。 (函数的调用)

·char\[\]\[\]与 char 的误混用检查。 (指针与二维数组)

·编写 advatoi 函数,字符串转整数。 (指针)

·从代码层面确保堆上内存得到及时回收。(手动内存管理)

·配置项的读操作。 (字符串处理)

·承担测试组的工作,寻找 BUG 并给出修改建议。

·参与本文档的编写。

另外,为了使组员能够理解一些特点功能的运作原理,组内在线交流,也约定提前返校见面,初步向组员介绍了如下内容。

·第三方开源库的使用与遵守开源协议的重要性。

·C 语言中的变长参数。

对应问题:printfscanf 函数为什么能有那么多参数?

·堆、栈、栈帧与入栈出栈。

对应问题:为什么静态定义的数组长度最晚在编译时确定?

函数调用是如何完成的?

·SSL 协议。

·一些代码编写规范。

·几对常用的具有相同作用的 DOS 和 bash 命令。

·Windows 消息机制。

·OllyDbg 的使用。

对应问题:在文档里写的"程序易被爆破从而绕过密码验证"是怎么做到的?

·POSIX 标准。

对应问题:为什么这个程序基本不用修改就能兼容另一种操作系统?

五. 开源许可

各个开源库的开源协议已经内嵌到程序中。

六. 附录

下面包含了本程序的全部头文件定义。由于习惯,注释以英语写成。程序代码总量约为 4326 行(不含注释、空行),不便全部于文档中展示,请参见源代码。

NewStd.h

复制代码
/*
	Name:			NewStd.h
	Description:	bool support and other features.
*/


# pragma once

// bool
# include <stdbool.h>

// disable warnings about unreferenced params.
# ifndef UNREFERENCED_PARAMETER
# define UNREFERENCED_PARAMETER(P) (P)
# endif

// wchar_t deprecated due to linux compatible issue.

/*
	#define char char_t
	// make it more convenient to use wide char.
*/

ConfigUtil.h

复制代码
/*
	Name:			ConfigUtil.h
	Description:	Config support.
*/

# pragma once

# include <stdio.h>
# include "NewStd.h"

# define PATH_CONFIG "config.ini"
# define PATH_CONFIGA "config.ini"
# define PATH_CONDS "conds"
# define PATH_CONDSA "conds"
# define defaultConfig(key) config(PATH_CONFIG, key)

# define CU_BUFFER_SIZE 1024
# define CU_TEXT_SIZE 64
# define CU_INTLEN_SIZE 16

// read a large file line by line.
void massRead(const char* path, void(*Callback)(char* line));

// read config string from file. 
char* config(const char* path, const char* key);

// inherits from config.
int getInt(const char* path, const char* key);

// write config to file.
bool configWrite(const char* path, const char* key, const char* value);

// inherits from configWrite.
bool setInt(const char* path, const char* key, int value);

CoreLibrary.h

复制代码
/*
	Name:			CoreLibrary.h
	Description:	Core library management. 
*/

# pragma once

# include "sqlite3-secure/sqlite3.h"
# include "NewStd.h"
# include "CoreProgram.h"

# define LM_BUFFER_SIZE 1024
# define PATH_CONDITION_FILE "conds\\"

// order of attrs.
extern int* global_order;

// shared sql object.
extern sqlite3* sql;

// more convenient than a lot of malloc.
char** LM_DynamicArray2Make(int width, int height);
void LM_FreeDynamicArray(void** arr, int n);

// initialize function.
bool LM_Init( void );

// reset database and rebuild attr structure.
bool LM_Reset(bool sure);

// wraps sqlite3_exec.
int LM_SQLExec(
	sqlite3* obj, 
	char* exec, 
	int(*callback)(void*, int, char**, char**), 
	void* preserved, 
	char** errmsg);

// wraps sqlite3_get_table.
int LM_SQLQuery(
	sqlite3* obj,
	char* exec,
	char*** pszResult,
	int* nrow,
	int* ncol,
	char** pszErrmsg);


// fetch all books from sqlite.
void LM_QueryBookAll(
	int* nrow,
	int* ncol,
	char*** result,
	int limit,
	int offset);

// fetch books with custom sqlite exec.
void LM_QueryBookWithSqlExec(
	char* exec,
	int* nrow,
	int* ncol,
	char*** result);

// mark if a book is deleted.
void LM_ChangeBookDeleteStatWithConds(
	int n,
	const char* stat,
	CP_Condition* conds,
	bool AND);

// convert CP_Condition[] to sqlite exec.
void LM_ConditionExecMakeOpt(
	const char* header,
	int n,
	CP_Condition* conds,
	char* result,
	const char* customParam,
	int limit,
	int offset,
	bool AND);

// (generate exec only) - fetch books with CP_Conditions.
void LM_SelectConditionExecMake(
	int n,
	CP_Condition* conds,
	char* result,
	int limit,
	int offset,
	bool AND);

// (generate exec only) - mark some books as deleted.
void LM_DeleteConditionExecMake(
	int n,
	CP_Condition* conds,
	char* result,
	int limit,
	int offset,
	bool AND);

// (action) - delete books.
void LM_DeleteBooksWithConds(
	int n, 
	CP_Condition* conds, 
	bool AND);

// (action) - delete books permanently. 
void LM_RemoveBooksWithConds(
	int n,
	CP_Condition* conds,
	bool AND);

// (action) - recover deleted books.
void LM_RescueBooksWithConds(
	int n, 
	CP_Condition* conds, 
	bool AND);

// (action) - modify books.
void LM_UpdateExecMakeWithConds(
	int nConds,
	CP_Condition* conds,
	int n,
	char** modifiedItems,
	char** newValues,
	char* exec);

// fetch a specified book.
void LM_QueryBookWithBookNumber(
	char* bookNumber, 
	int* nrow, 
	int* ncol, 
	char*** result);

// (action) - add books from files in prepared formats.
bool LM_AddBookWithFile(
	char* path,
	int n, 
	int* _order,
	int* nsuc,
	int* nfail);
void LM_ConditionFileLoad(
	char* condName,
	CP_Condition* conds,
	int* condition_cnt);


// (action) - add books with given args.
bool LM_AddBookWithOrder(
	char** args, 
	int n, 
	int* order,
	bool flagUseOrder);

bool UI_BookModifyWithGUI(char* bookNumber);
bool LM_Add(char** args, int n, bool flagUseOrder);

// generate a CP_Condition file.
void LM_ConditionFileGen(int n, char* condName,
	CP_Condition* conds);

// get a specified value of a book.
void LM_ValueGetWithBookNumber(char* bookNumber, char* key, char** pvalue);
void LM_ValueGetWithBookNumberFree(char** pvalue);

// translates CP_Condition.cond
void LM_CondRulesCat(char* result, char cond);

void LM_GetOrder(int* _order, int n);
void LM_GetOrderWithCondName(const char* condName, int* _order, int n);


// int LM_Callback(void* NotUsed, int argc, char** argv, char** argn);
// deprecated due to a priv violation (directly LM->UI).

AlgorithmUtil.h

复制代码
/*
	Name:			AlgorithmUtil.h
	Description:	Algorithm support. 
*/

# pragma once

# include "NewStd.h"
# include <stdlib.h>

# define AU_LINE_SIZE 1024

/*
	Umm... This AlgorithmUtil doesn't have any awesome algorithms.
	coz this program bases on sqlite3 who did everything well...
*/

// converts char[] to wchar_t[].
wchar_t* c2w(char* c);

// convert gb2312 between utf-8.
char* G2U(const char* gb2312);
char* U2G(const char* utf8);

// solve SQLite encoding issue in Linux.
void ascii2Utf8(char* ascii, size_t asciiSize, char* utf8);

// converts int to char[]
void advitoa(int i, char* w);

// has a higher accuracy than strlen :)
int wstrlen(const char* str);

// "1aaa2bb3ccccc4dd5eee" -> 12345
int advatoi(const char* str);

// they find out a element in an array.
int uniArrIndexOf(void** of, void* with, bool(*Compare)(void* a, void* b), int limit);
int arrIndexOf(char** of, char* with, int limit);
int arrIndexOfInt(int* of, int with, int limit);

// I wrote this after scanf("[\^n]", ) crashed for 1,000,000,000,000,000,000,000 times.
void readline(char* str, int limit);

// drops \r and \n at the end of string.
void trim(char* r, int limit);

// so why doesn't string.h provide split?!
void split(const char* of, const char with, char** ret, int* n);

CoreNetwork.h

复制代码
/*
	Name:			CoreNetwork.h
	Description:	Core network support.
*/

# pragma once

# include "NewStd.h"

# define NU_LINE_SIZE 1024
# define NU_PATH_LENGTH 128
# define NU_SRV_URL "https://mikutart.com/libman/"
# define NU_SRV_HANDLER "handler.php"

bool NU_FileUpload(const char* remoteFileName, const char* localFileName);
bool NU_FileDownload(const char* remoteFileName, const char* localFileName);

CoreProgram.h

复制代码
/*
	Name:			CoreProgram.h
	Description:	Core logics. 
*/

# pragma once

# include "NewStd.h"
# include "CoreUI.h"

# define CP_COND_SIZE 64
# define CP_TFORMAT_SIZE 4
# define CP_NATTR_COUNT 64
# define CP_NATTR_SIZE 64
# define CP_FORMAT_SIZE 64
# define CP_COND_NAME_SIZE 64
# define CP_COND_VALUE_SIZE 64
# define CP_EXEC_SIZE 1024

# define LIC_PATH_SQLITE \
"licenses\\LICENSE_SQLITE.txt"
# define LIC_PATH_LIBCURL \
"licenses\\LICENSE_LIBCURL.txt"
# define LIC_PATH_OPENSSL \
"licenses\\LICENSE_OPENSSL.txt"
# define LIC_PATH_APACHEV2 \
"licenses\\LICENSE_APACHEV2.txt"

# define LPADDING printf("  ");
# define TPADDNING printf("   ");
# define NEWLINE putchar('\n');

// a condition includes a name, an operator(cond) and a value.
typedef struct {
	char name[CP_COND_NAME_SIZE];
	char cond;
	char value[CP_COND_VALUE_SIZE];
} CP_Condition;


// (view) - book management.
void CP_BookManage( void );

// (view) - a command line for custom sqlite3 exec.
void CP_AnySqlCmd( void );

// (view) - show open sourse licenses.
void CP_OpenSourceLic( void );

// (method) - condition make.
void CP_ConditionMake(
	CP_Condition* target,
	const char* name,
	const char op,
	const char* value);

// (view) - sell mode.
void CP_BuyMode( void );
void CP_BuyModeCheck( void );

// (navigation) - add a condition to advanced filter.
void CP_AddCondition(CP_Condition cond);

// (method) - add a condition to advanced filter.
void CP_ConditionCpy(CP_Condition* dst, CP_Condition* src);

// (view) - main view.
void CP_Main( void );

// (view) - cloud service.
void CP_CloudService( void );

// (view) - settings.
void CP_Settings( void );

// (view) - books with deleted tag.
void CP_TrashBin( void );

// (navigation) - switch language file.
void CP_SwitchLanguage( void );

// (view) - advanced filter.
void CP_AdvancedFilter(void(*from)( void ));

// (method) - filter.
void CP_FilterWithExistingConds(
	bool AND, 
	int offset,
	bool flagShowDeleted);

// (view) - borrow mode.
void CP_BorrowMode( void );

// (view) - search.
void CP_Search( void );

// (navigation) - delete one.
void CP_DeleteOne( void );

// (navigation) - export to excel.
void CP_ExportExcelNavi(char* addition, bool AND);

// (navigation) - add one.
void CP_AddBook( void );

// (navigation) - recover one.
void CP_RescueOne( void );

// (navigation) - reset database.
void CP_ResetDatabase( void );

// (navigation) - mass add.
void CP_BookImport( void );

// (method) - mass recover.
void CP_RescueAllWithExistingConds(bool AND);

// (method) - mass delete.
void CP_DeleteAll(bool AND);

// (navigation) - delete a condition.
void CP_DeleteFilter( void );

// (navigation) - import condition file.
void CP_LoadConditionFile( void );

CoreUI.h

复制代码
/*
	Name:			CoreUI.h
	Description:	Simulate UI in CLI.
*/

# pragma once

# include <stdio.h>
# include <stdlib.h>

# include "I18N.h"

# define UI_MENU_HEIGHT 64
# define UI_MENU_WIDTH 512
# define UI_ATTR_FORMAT_SIZE 64

// clear CLI.
// Windows: cls
// Linux: clear
void UI_Clear( void );

// set locale to compatible with unicode charset.
void UI_InitWithUnicodeCS( void );

// read a line from CLI and convert to int with advatoi.
int UI_Input( void );

// get command to clear CLI in current operating system.
const char* clearCmd( void );

// get command to list directory in current operating system.
// Windows: dir
// Linux: ls
const char* lsCmd(void);

// print array in menu format.
void UI_MenuMake(const char* title, int num, ...);

// only works on Debug mode.
void dbgprintf(const char* str);

// add book navigation.
void UI_AddBookNavi( void );

// print book attrs table header.
void UI_PrintBookHeader( FILE* target );

// advanced printf which automatically use str().
void UI_Printf(const char* format, ...);
void UI_Fprintf(FILE* target, const char* format, ...);

// simulate a full-screen MessageBox in CLI.
void UI_MessageBoxWithType(const char* msg, const char* caption, bool tryGUI, unsigned int type);
void UI_MessageBox(const char* msg, bool tryGUI);

// check password.
bool UI_MastercodeCheck(bool flagFullScreen);

// check security question.
bool UI_SQCheck( void );

// wraps UI_MastercodeInputWithCustomMsg().
void UI_MastercodeInputSolution(char* 
	uPassword, bool tryGUI);

// input password in CLI. (uses _getch())
void UI_MastercodeInputWithCustomMsg(
	char* msgTag, 
	char* uPassword);

// another way to print a menu.
void UI_MenuMakeWithArray(
	const char* title,
	int num,
	const char** arr);

// wraps UI_MenuMakeWithArray().
char** UI_MenuMakeWithString(
	const char* title,
	const char* str);

// analyze and print sqlite3 result.
void UI_ListMakeWithSqlite3Array(
	const char* title,
	void(*HeaderProcessor)(FILE*),
	int nrow,
	int ncol,
	bool flagShowDeleted,
	int base,
	char** arr,
	void(*callback)(char*, FILE*),
	FILE* target);

// a switch navigation.
void UI_SwitchMake(
	const char* name, 
	const char* intro, 
	const char* key);

// a setting navigation.
void UI_SettingsMake(
	const char* name, 
	const char* intro, 
	const char* key, 
	bool InputOrSwitch);

// determines raw input or select from given list for each attr.
void UI_AttributedInput(int index, char* name, char* target);

// ask for yes or no.
bool UI_Prompt(const char* msg, bool tryGUI);

I18N.h

复制代码
/*
	Name:			I18N.h
	Description:	a solution for internationalization.
*/

# pragma once

# include "ConfigUtil.h"

# define LANG_PATH "languages/%d%hs"

# define FILE_NAME_SIZE 64
# define LINE_SIZE 1024

extern int global_language;

// switch language.
bool switchLanguage(int language);

// read string from corrsponding language file.
char* str(const char* key);
相关推荐
水饺编程18 分钟前
第5章,[Win32 章节] :绘制填充区域
c语言·c++·windows·visual studio
何以解忧,唯有..27 分钟前
LangChain 模型调用方法总结:invoke、batch、stream 的入参与出参
开发语言·langchain·batch
SamChan9031 分钟前
Python+ReportLab自动生成PDF翻译质量审计报告:从数据到可视化的完整方案
开发语言·python·ai·pdf·wpf
深念Y32 分钟前
Makefile vs go run:Go 项目构建方式对比
java·开发语言·golang·k8s·编译·流水线·cicd
whcyhhh33 分钟前
头歌实践教学平台:数据科学与大数据技术导论(十八2)
大数据·开发语言·python
一晌小贪欢34 分钟前
Python办公18:PDF 转 Word——利用 OCR 技术批量提取不可编辑的文档内容
开发语言·python·pdf·word·excel·数据可视化·python办公
我命由我1234543 分钟前
Android Camera - 获取当前设备屏幕的旋转角度、保存帧到外部存储的私有空间
android·java·开发语言·java-ee·android jetpack·android-studio·android runtime
迷迭香yy1 小时前
A股数据本地存储方案对比JSON、SQLite、ClickHouse、DuckDB怎么选 IG50免费开源股票数据API接口
clickhouse·sqlite·json
深念Y1 小时前
QQ 数据库解密与聊天记录导出 — 技术文档
数据库·sqlite·手机·数据恢复·逆向·二进制·qq