day40 SQLite3单词查询程序设计与实现

核心知识点

  • SQLite3 C接口应用:使用sqlite3_opensqlite3_exec等函数操作数据库
  • 回调函数机制:通过回调函数处理查询结果集
  • SQL语句构建:动态生成SELECTINSERT等SQL语句
  • 事务处理:使用BEGIN TRANSACTIONCOMMIT提高批量插入效率
  • 结果集处理:理解result数组与查询列的对应关系
  • 用户交互设计:实现连续查询和退出机制

完整代码实现(带详细注释)

#include <sqlite3.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>// SQLite查询结果回调函数:用于处理查询到的结果
// 参数说明:
//   arg:传递给回调的用户数据指针(此处用于传递"是否找到"的标志)
//   col:查询结果的列数(本例中固定为1列)
//   result:查询结果数据数组(每行结果的值)
//   title:查询结果的列名数组(本例中为["dict_mean"])
int find(void* arg, int col, char** result, char** title)
{// 将找到结果的标志设为1(表示已找到匹配数据)*(int*)arg = 1;// 打印查询到的单词释义(result[0]对应SELECT指定的dict_mean列)printf("mean:%s\n", result[0]);return 0; // 回调函数返回0表示继续处理其他结果
}int main(int argc, char** argv)
{sqlite3* db = NULL;         // SQLite数据库连接句柄char* errmsg = NULL;        // 用于存储SQL操作错误信息int ret = 0;                // 用于存储函数调用返回值// 打开指定的SQLite数据库(如果不存在则创建)ret = sqlite3_open("./aaa.db", &db);if (SQLITE_OK != ret){// 打开数据库失败,打印错误信息fprintf(stderr, " sqlite3_open %s\n", sqlite3_errstr(ret));sqlite3_close(db);      // 关闭数据库连接return 1;               // 程序异常退出}char sql_cmd[1024] = {0};   // 用于存储SQL命令字符串// 尝试删除已存在的dict表(如果存在) - 清理旧数据strcpy(sql_cmd, "drop table dict");sqlite3_exec(db, sql_cmd, NULL, NULL, &errmsg);// 注意:删除失败可能是表不存在,属于正常情况// 创建新的dict表,包含id(序号)、word(单词)、dict_mean(释义)三个字段bzero(sql_cmd, sizeof(sql_cmd));  // 清空SQL命令缓冲区strcpy(sql_cmd, "create table dict(id int ,word char ,dict_mean text);");ret = sqlite3_exec(db, sql_cmd, NULL, NULL, &errmsg);if (SQLITE_OK != ret){// 创建表失败,打印错误信息fprintf(stderr, " sqlite3_exec sql_cmd:[%s] %s\n", sql_cmd, errmsg);sqlite3_free(errmsg);   // 释放错误信息内存sqlite3_close(db);      // 关闭数据库连接return 1;               // 程序异常退出}// 打开单词词典文件(路径为/home/linux/dict.txt)FILE* fp = fopen("/home/linux/dict.txt", "r");if (NULL == fp){perror("fopen");        // 打开文件失败,打印错误信息return 1;               // 程序异常退出}int num = 1;                // 用于记录单词的序号(id字段)// 开始数据库事务(批量插入时使用事务可提高效率)bzero(sql_cmd, sizeof(sql_cmd));strcpy(sql_cmd, "begin transaction;");sqlite3_exec(db, sql_cmd, NULL, NULL, &errmsg);// 循环读取词典文件内容并插入到数据库中while (1){char linebuf[1024] = {0};   // 用于存储读取到的一行数据// 读取文件中的一行数据,如果读取失败(到文件末尾)则退出循环if (NULL == fgets(linebuf, sizeof(linebuf), fp)){break;}// 解析行数据:以空格分割单词和释义char* word = strtok(linebuf, " ");    // 获取单词部分char* mean = strtok(NULL, "\r");      // 获取释义部分(去除回车符)// 构造插入数据的SQL命令bzero(sql_cmd, sizeof(sql_cmd));sprintf(sql_cmd, "insert into dict values(%d,\"%s\",\"%s\");", num++, word, mean);// 执行插入操作ret = sqlite3_exec(db, sql_cmd, NULL, NULL, &errmsg);if (SQLITE_OK != ret){// 插入失败,打印错误信息fprintf(stderr, " sqlite3_exec sql_cmd:[%s] %s\n", sql_cmd, errmsg);sqlite3_free(errmsg);   // 释放错误信息内存sqlite3_close(db);      // 关闭数据库连接return 1;               // 程序异常退出}}// 提交事务(将之前的批量插入操作真正写入数据库)bzero(sql_cmd, sizeof(sql_cmd));strcpy(sql_cmd, "commit;");sqlite3_exec(db, sql_cmd, NULL, NULL, &errmsg);// 循环接收用户输入,查询单词释义while (1){char want_word[1024] = {0};    // 用于存储用户要查询的单词printf("input word:");         // 提示用户输入单词fgets(want_word, sizeof(want_word), stdin);  // 读取用户输入want_word[strlen(want_word) - 1] = '\0';     // 去除输入中的换行符// 如果用户输入#quit,则退出查询循环if (0 == strcmp(want_word, "#quit")){break;}// 构造查询单词释义的SQL命令(仅选择dict_mean列)bzero(sql_cmd, sizeof(sql_cmd));sprintf(sql_cmd, "select dict_mean from dict where word like  \"%s\"", want_word);int flag = 0;  // 用于标记是否查询到结果(0:未找到,1:找到)// 执行查询操作,使用find函数作为结果回调函数ret = sqlite3_exec(db, sql_cmd, find, &flag, &errmsg);if (SQLITE_OK != ret){// 查询失败,打印错误信息fprintf(stderr, " sqlite3_exec sql_cmd:[%s] %s\n", sql_cmd, errmsg);sqlite3_free(errmsg);   // 释放错误信息内存sqlite3_close(db);      // 关闭数据库连接return 1;               // 程序异常退出}// 如果未找到匹配的单词,提示用户if (0 == flag){printf("cant find %s\n", want_word);}}// 关闭数据库连接sqlite3_close(db);return 0;   // 程序正常退出
}

关键机制解析:result[0]为何精确对应单词释义

1. SQL查询语句的精准投影

sprintf(sql_cmd, "select dict_mean from dict where word like  \"%s\"", want_word);
  • select dict_mean:这是关键的"投影"操作,明确指定只返回dict_mean这一列
  • 结果集结构:当查询命中时,返回的结果集每行只有1列数据
  • 数组索引关系:在回调函数中,result[0]自然对应这唯一一列(即单词释义)

2. 数据存储结构的一致性

sprintf(sql_cmd, "insert into dict values(%d,\"%s\",\"%s\");", num++, word, mean);
  • 插入顺序固定:第二列存储单词(word),第三列存储释义(dict_mean)
  • 查询匹配:当where word like "%s"条件满足时,返回的正是第三列存储的释义数据

3. 回调函数执行机制

查询结果情况回调函数调用result数组内容flag
找到1个匹配结果调用1次result[0] = 释义1
找到N个匹配结果调用N次每次result[0]不同1
无匹配结果不调用-0

重要特性:当查询无结果时,回调函数不会被调用,因此需通过flag标志判断是否找到

代码执行流程与理想结果

初始化阶段(首次运行)

$ gcc word_query.c -lsqlite3 -o word_query
$ ./word_query

理想输出:

input word:hello
mean:你好
input word:world
mean:世界
input word:apple
mean:苹果
input word:banana
mean:香蕉
input word:#quit

查询场景模拟

场景1:成功查询单词
input word:computer
mean:计算机
  • 执行过程
    1. 构造SQL:select dict_mean from dict where word like "computer"
    2. 数据库返回匹配行
    3. 触发回调函数:find()设置flag=1并打印释义
场景2:未找到单词
input word:zxy123
cant find zxy123
  • 执行过程
    1. 构造SQL:select dict_mean from dict where word like "zxy123"
    2. 数据库无匹配结果
    3. 不触发回调函数
    4. 检测flag=0,输出"cant find"提示
场景3:退出程序
input word:#quit
  • 执行过程
    1. 检测到输入#quit
    2. 跳出查询循环
    3. 执行sqlite3_close(db)关闭数据库
    4. 程序正常退出(返回0)

核心结论

result[0]能精确获取单词释义,是由双重保障决定的:

  1. SQL投影约束SELECT dict_mean确保结果集仅包含释义列
  2. 数据存储一致性:插入时严格保证第三列存储释义数据

这种设计使回调函数能直接通过result[0]获取目标数据,无需处理列索引映射问题,是SQLite C接口应用的典型最佳实践。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/98717.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/98717.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/98717.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GitHub 热榜项目 - 日榜(2025-09-08)

GitHub 热榜项目 - 日榜(2025-09-08) 生成于&#xff1a;2025-09-08 统计摘要 共发现热门项目&#xff1a;17 个 榜单类型&#xff1a;日榜 本期热点趋势总结 本期GitHub热榜呈现三大技术趋势&#xff1a;AI智能体与LLM应用持续爆发&#xff08;emcie-co/parlant、coleam00…

设计模式-工厂方法原型模板方法外观

设计模式概述 - 工厂方法 & 原型 & 模板方法 & 外观 工厂方法模式简述 工厂方法模式&#xff08;Factory Method Pattern&#xff09;是一种创建型设计模式&#xff0c;它定义了一个用于创建对象的接口&#xff0c;但由子类决定实例化哪个类。工厂方法将类的实例化…

推动检测认证行业迈向智能化 AITIC一体机发布会在京举办

来源&#xff1a;新华社客户端国家市场监督管理总局认证认可技术研究中心(简称“认研中心”)近日联合技术合作伙伴在北京举办AITIC软硬件一体机发布会。据了解&#xff0c;“AITIC一体机”是专为检测认证行业设计的智能硬件&#xff0c;提供低成本的本地化部署方案&#xff0c;…

权限即数据:企业系统中的字段级访问控制架构实战(β=0.6)

摘要 这篇文章介绍了一个企业系统中的字段权限解析方案&#xff0c;通过规则表与命中记录表&#xff08;biz_rule_hit&#xff09;联动&#xff0c;实现对业务数据的动态权限控制。流程包括替换用户上下文变量、记录命中规则、查询业务数据并关联命中信息&#xff0c;最终在内存…

Python爬虫实战:研究Specialty Plots模块,构建空气质量监测数据采集和分析系统

1. 引言 1.1 研究背景 随着全球城市化进程的加速和工业的快速发展,空气质量问题已成为影响人类健康和生态环境的重要因素。世界卫生组织数据显示,全球超过 90% 的人口生活在空气质量超标的环境中,空气污染每年导致约 700 万人过早死亡。准确、及时地获取和分析空气质量数据…

字典树算法

一、什么是Trie&#xff1f; Trie&#xff08;发音为"try"&#xff09;&#xff0c;也称为字典树、前缀树&#xff0c;是一种多叉树结构&#xff0c;专门用于高效存储和检索字符串集合。其核心特点是共享字符串的公共前缀&#xff0c;从而大幅减少冗余存储&#xff0…

Laya使用VideoNode动态加载视频,可以自定义播放视频此处以及位置

export class VideoCommand {video: Laya.VideoNode;public duration: number 0;/*** param videoPos 视频位置* param videoSize 视频大小*/public constructor(videoPos: Laya.Vector2, videoSize: Laya.Vector2) {this.video new Laya.VideoNode;//添加到舞台 1是场景中的…

yum localinstall安装本地包

yum localinstall 是一个用于安装本地 RPM 包并自动处理依赖关系的命令。当你有一个或多个本地的 RPM 包需要安装,又希望 yum 能帮你解决可能存在的依赖问题时,这个命令就非常有用。下面我会详细解释它的用法和注意事项。 🖥️ 命令基本用法 yum localinstall 命令的基本…

LeetCode 面试经典 150 题:轮转数组(三次翻转法详解 + 多解法对比)

在数组类算法题中&#xff0c;“轮转数组” 是一道考察 “原地操作” 与 “逻辑转换” 能力的经典题目。所谓 “轮转”&#xff0c;是指将数组元素向右移动指定步数&#xff0c;且超出数组长度的元素需 “循环” 到数组开头。这道题的最优解 ——三次翻转法&#xff0c;能以 O …

网络编程---TCP

1.TCP&#xff1a;传输控制协议&#xff0c;位于传输层2.TCP的特性&#xff1a;a.使用流式套接字&#xff0c;数据连续&#xff0c;有顺序b.TCP是可靠传输&#xff0c;有有应答机制ACK&#xff0c;即收到数据后会明确告知发送方已收到数据&#xff1b;若发送方没有在预计时间收…

对计算机网络模型的理解

文章目录 目录 前言 一、Internet 的核心特点 二、Internet 的组成结构 1. 硬件基础&#xff1a;网络运行的 “物理载体” 2. 软件支撑&#xff1a;网络运行的 “功能桥梁” 3. 协议规则&#xff1a;网络运行的 “通用语言” 三、OSI 七层参考模型&#xff08;理论标准&…

每日一算:分发糖果

在算法面试中&#xff0c;“分发糖果” 是一道经典的贪心算法应用题&#xff0c;核心考察对 “局部最优推导全局最优” 的理解。本文将从问题分析出发&#xff0c;提供两种主流解题思路&#xff0c;并附上 C 实现代码&#xff0c;帮助你彻底掌握这道题。一、问题重述题目要求有…

【WorkManager】无法在 Direct Boot 模式下初始化

【WorkManager】无法在 Direct Boot 模式下初始化一、问题描述二、问题分析2.1 关于 Direct Boot 模式2.2 支持 Direct Boot 模式2.3 手动初始化 WorkManager 组件2.4 WorkManager 不支持 Direct Boot 的官方修改三、解决方案一、问题描述 在使用 WorkManager 库来实现开机上报…

Hybrid应用性能优化实战分享(本文iOS 与 H5为例,安卓同理)

前言在移动应用开发中&#xff0c;Hybrid 架构因其跨平台特性和开发效率优势被广泛采用。然而&#xff0c;WebView 的性能问题一直是开发者面临的挑战。本文将基于实际项目经验&#xff0c;分享 iOS Hybrid 应用的核心优化策略&#xff0c;涵盖 WebView 池化、预加载、用户体验…

点积、叉积、矩阵行列式详解、线性相关与线性无关、矩阵的秩、矩阵可逆与不可逆详解

1.向量 1.1 点积&#xff08;Dot Product&#xff09; 1.1.1 定义 点积是在求一个标量&#xff0c;点积结果没有方向。 对于两个向量u(u1,u2,u3),v(v1,v2,v3)\bold{u}(u_1,u_2,u_3),\bold{v}(v_1,v_2,v_3)u(u1​,u2​,u3​),v(v1​,v2​,v3​) 点积定义为&#xff1a;u⋅vu1v1u…

Mac安装nvm详细教程(超简单)

本章教程,主要介绍如何在Mac操作系统上安装nvm. 我们使用官方一键安装脚本,完成安装 一、安装步骤 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash配置环境变量,编辑.zshrc文件 vim .zshrcexport NVM_DIR="$(

【selenium】网页元素找不到?从$(‘[placeholder=“手机号“]‘)说起

网页元素找不到&#xff1f;从$(‘[placeholder“手机号”]’)说起总结&#xff1a;控制台不骗人&#xff0c;元素选不到&#xff0c;八成是写法、时机或环境的问题。我们在写网页自动化脚本或者调试页面的时候&#xff0c;经常遇到一个让人头疼的问题&#xff1a;明明元素就在…

SSE 模仿 GPT 响应

后端代码 const express require(express) const cors require(cors);const app express(); app.use(cors()); const port 3000;app.listen(port, () > {console.log(Server running at http://localhost:${port}/); });const msg 全国同胞们&#xff0c; 尊敬的各位国…

MAC 多个版本 JDK进行切换

1.查看本机所有的jdk/usr/libexec/java_home -V2、打开bash_profile文件。可以在终端vim ~/.bash_profile打开&#xff0c;也可以打开访达shiftcmdG然后输入/Users/mac/.bash_profile&#xff08;本机bash_profile的路径&#xff09;加入新的环境变量格式如下&#xff08;参考我…

shell 中 expect 详解

一、概述Expect是一个免费的编程工具语言&#xff0c;用来实现自动和交互式任务进行通信&#xff0c;而无需人的干预。Expect的作者DonLibes在1990年开始编写Expect时对Expect做有如下定义&#xff1a;Expect是一个用来实现自动交互功能的软件套件。通过expect系统管理员可以创…