OSTEP Projects:KV
本文将介绍操作系统导论(Operating Systems: Three Easy Pieces)作者所开源的操作系统相关课程项目 的 KV 部分,包含个人的代码实现和设计思路。
思路
题目要求实现一个最简单的数据库,以支持数据的持久化。
每个操作由格式为 op,[arg1],[arg2] 的命令给出,那么首先要解决的问题就是参数的分离,再根据操作符 op 来对不同的操作进行特殊处理。字符串划分这里采用的是 strsep() 函数:该函数接收两个参数 char** stringp 和 const char* delim,stringp 是指向待分割字符串 string 的指针,delim 则是指定的分隔符,该函数的操作是查找 string 中第一个 delim 的位置 it,并将 stringp 指向 string 中 it + 1 的位置,同时返回string 开头到 it 所有字符所构成的子串(加上 '\0' 终结符)。
插入操作没什么好说的,直接使用 fprintf() 写入文件即可。对于查找和删除,则需要将数据从文件(数据库)中读取到内存,存储在特定的数据结构中,例如哈希表、红黑树等,但为了代码实现的简单,我使用的是最简单的链表。对于查找,先将所有数据读取到一个链表中,然后按顺序逐个进行查找;对于删除,将所有数据读取到一个链表中,然后逐个遍历链表,如果当前结点的键(key)与参数不同,则写入文件中,否则,不写入(相当于删除)。最后,为了防止内存的泄露,需要在每次结束查找和删除操作之后,将存储数据内容的链表结点的内存空间释放。
代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define DATA_BASE "./database.txt"typedef struct LineNode {char* line_buf;struct LineNode* next;
} line_node;// 从文件fp中读取数据
line_node* read_from_file(FILE* fp) {line_node* dummy = (line_node*)malloc(sizeof(line_node)); // 哨兵结点line_node* p = dummy;size_t sz = 0;while (1) {p->next = (line_node*)malloc(sizeof(line_node));p = p->next;if (getline(&(p->line_buf), &sz, fp) == -1) {p->next = NULL;break;}}return dummy->next;
}// 释放链表内存空间
void free_list_mem(line_node* data) {while (data != NULL) {line_node* temp = data;data = data->next;free(temp);}
}int main(int argc, char* argv[]) {for (int i = 1; i < argc; ++i) {char* op = strsep(&argv[i], ","); // 操作符if (!strcmp(op, "p")) {char* key = strsep(&argv[i], ",");char* value = strsep(&argv[i], ",");if (argv[i] != NULL) {printf("bad command\n");continue;}FILE* fp = fopen(DATA_BASE, "a");if (fp == NULL) {fprintf(stderr, "cannot open file %s\n", DATA_BASE);exit(1);}fprintf(fp, "%s,%s\n", key, value);fclose(fp);}else if (!strcmp(op, "g")) {char* key = strsep(&argv[i], ",");if (argv[i] != NULL) {printf("bad command\n");continue;}FILE* fp = fopen(DATA_BASE, "r");if (fp == NULL) {fprintf(stderr, "cannot open file %s\n", DATA_BASE);exit(1);}line_node* data = read_from_file(fp);line_node* p = data;int flag = 0;while (p != NULL) {char* entry = strdup(p->line_buf); // 条目备份(line_buf会被strsep()修改)char* token = strsep(&(p->line_buf), ",");if (!strcmp(token, key)) { // 找到keyflag = 1;printf("%s", entry);break;}p = p->next;}if (!flag) {printf("%s not found\n", key);}free_list_mem(data);fclose(fp);}else if (!strcmp(op, "d")) {char* key = strsep(&argv[i], ",");if (argv[i] != NULL) {printf("bad command\n");continue;}FILE* fp = fopen(DATA_BASE, "r");if (fp == NULL) {fprintf(stderr, "cannot open file %s\n", DATA_BASE);exit(1);}line_node* data = read_from_file(fp);fclose(fp);// 清空文件fp = fopen(DATA_BASE, "w");if (fp == NULL) {fprintf(stderr, "cannot open file %s\n", DATA_BASE);exit(1);}fclose(fp);fp = fopen(DATA_BASE, "a");if (fp == NULL) {fprintf(stderr, "cannot open file %s\n", DATA_BASE);exit(1);}line_node* p = data;while (p != NULL) {char* entry = strdup(p->line_buf); // 条目备份char* token = strsep(&(p->line_buf), ",");if (strcmp(token, key)) { // 当前条目键值为key,不写入(相当于删除)fprintf(fp, "%s", entry);}p = p->next;}free_list_mem(data);fclose(fp);}else if (!strcmp(op, "c")) {if (argv[i] != NULL) {printf("bad command\n");continue;}FILE* fp = fopen(DATA_BASE, "w");if (fp == NULL) {fprintf(stderr, "cannot open file %s\n", DATA_BASE);exit(1);}fclose(fp);}else if (!strcmp(op, "a")) {if (argv[i] != NULL) {printf("bad command\n");continue;}FILE* fp = fopen(DATA_BASE, "r");line_node* data = read_from_file(fp);line_node* p = data;while (p != NULL) {printf("%s", p->line_buf);p = p->next;}free_list_mem(data);fclose(fp);}else {printf("bad command\n");continue;}}return 0;
}
相关文章:
OSTEP Projects:KV
本文将介绍操作系统导论(Operating Systems: Three Easy Pieces)作者所开源的操作系统相关课程项目 的 KV 部分,包含个人的代码实现和设计思路。 思路 题目要求实现一个最简单的数据库,以支持数据的持久化。 每个操作由格式为 o…...
JAVA学习笔记(第三周)
文章目录 继承概述使用场景继承的特点子类继承的内容成员变量访问特点成员方法访问特点方法的重写构造方法this super 多态多态的表现形式多态的前提成员变量和方法调用instanceof优势弊端 包包名的规则全类名final常量 权限修饰符代码块 继承 概述 继承就是子类继承父类的特征…...
linux 内核驱动 -- reboot -f 导致内核死机 而 reboot则不会引起问题
问题描述,定于与解决:...
【vue-echarts】 报错问题解决 “Error: Component series.pie not exists. Load it first.“
目录 问题描述解决【解决1】【解决2】 问题描述 使用 vue-echarts 时导入的文件 import VChart from vue-echarts/components/ECharts import echarts/lib/chart/line import echarts/lib/chart/bar import echarts/lib/chart/pie import echarts/lib/component/legend impor…...
MySQL慢查询SQL优化
一、慢查询日志 描述:通过慢查询日志等定位那些执行效率较低的SQL语句 查看 # 慢查询是否开启 show variables like slow_query_log%; # 慢查询超时时间 show variables like long_query_time%;执行SQL 开启慢查询日志 set global slow_query_log ON;设置慢查…...
【嵌入式DIY实例】-DDS信号生成器
DDS信号生成器 文章目录 DDS信号生成器1、AD9805介绍2、硬件准备与接线3、代码实现在本文中,将详细介绍如何使用AD9850来搭建一个简易的DDS(Direct Digital signal )信号生成器。 1、AD9805介绍 AD9850是一款高度集成的器件,采用先进的DDS技术,内置一个高速、高性能数模转…...
java设计模式四 桥接模式
桥接模式关注于将抽象部分与实现部分分离,使它们可以独立变化。它通过在抽象和实现之间建立一个桥梁来实现这一目的。这种设计模式属于结构型模式。 假设我们要设计一个图形编辑器,其中图形(如圆形、正方形)可以有不同的颜色填充…...
《Python编程从入门到实践》day24
# 昨日知识点学习 创建外星人从一个到一行 # 主程序snipdef _create_fleet(self):"""创建外星人群"""# 创建一个外星人并计算一行可容纳多少个外星人# 外星人的间距为外星人的宽度alien Alien(self)alien_width alien.rect.widthavailable_sp…...
【hackmyvm】 Animetronic靶机
靶机测试 arp-scanporturl枚举exiftool套中套passwordsudo 提权 arp-scan arp-scan 检测局域网中活动的主机 192.168.9.203 靶机IP地址port 通过nmap扫描,获取目标主机的端口信息 ┌──(root㉿kali)-[/usr/share/seclists] └─# nmap -sT -sV -O 192.16…...
[附源码]石器时代_恐龙宝贝内购版_三网H5手游_带GM工具
石器时代之恐龙宝贝内购版_三网H5经典怀旧Q萌全网通手游_Linux服务端源码_视频架设教程_GM多功能授权后台_CDK授权后台 本教程仅限学习使用,禁止商用,一切后果与本人无关,此声明具有法律效应!!!࿰…...
RS2255XN功能和参数介绍及PDF资料
RS2255XN是一款由Runic(润石)公司生产的模拟开关。以下是关于RS2255XN的一些技术参数和特点: 封装:MSOP-10 电源电压范围:2.5V至5.5V 工作温度范围:-40C至125C 类型:模拟开关 品牌:R…...
设计模式——外观模式(Facade)
外观模式(Facade Pattern) 是一种结构型设计模式,它为一个子系统中的一组接口提供一个统一的高层接口,使得子系统更加容易使用。这种类型的设计模式属于结构型模式,它向客户端提供了一个接口,隐藏了子系统的…...
【linux软件基础知识】Linux 中的普通进程的调度机制
活动集Active processes和过期集Expired processes 为了实现静态优先级较低的进程没有完全锁定并有机会运行,Linux 调度程序维护两个不相交的可运行进程集:活动集和过期集。 此机制是完全公平调度程序 (CFS) 算法的一部分。 以下是这两组的工作原理: 活动集Active proces…...
keil5软件安装教程(MDKv5.39)
keil5软件安装分为三部分: 目录 1.安装mdk 2.激活mdk 3.安装STM32芯片包 1.安装mdk 安装包链接:链接:https://pan.baidu.com/s/1PZoGhzI5Y19ROv7xe9QJKA?pwdgt3s 提取码:gt3s 1、下载keil5的压缩包并解压,鼠…...
改变视觉创造力:图像合成中基于样式的生成架构的影响和创新
原文地址:revolutionizing-visual-creativity-the-impact-and-innovations-of-style-based-generative 2024 年 4 月 30 日 介绍 基于风格的生成架构已经开辟了一个利基市场,它将机器学习的技术严谨性与类人创造力的微妙表现力融为一体。这一发展的核…...
【LAMMPS学习】八、基础知识(5.8)LAMMPS 中热化 Drude 振荡器教程
8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语,以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…...
基于SpringBoot的全国风景区WebGIS按省展示实践
目录 前言 一、全国风景区信息介绍 1、全国范围内数据分布 2、全国风景区分布 3、PostGIS空间关联查询 二、后台查询的设计与实现 1、Model和Mapper层 2、业务层和控制层设计 三、WebGIS可视化 1、省份范围可视化 2、省级风景区可视化展示 3、成果展示 总结 前…...
深入理解网络原理3----TCP核心特性介绍(上)【面试高频考点】
文章目录 前言TCP协议段格式一、确认应答【保证可靠性传输的机制】二、超时重传【保证可靠性传输的机制】三、连接管理机制【保证可靠性传输的机制】3.1建立连接(TCP三次握手)---经典面试题3.2断开连接(四次挥手)3.3TCP状态转换 四…...
Java并发编程之锁的艺术:面试与实战指南(三)
Java并发编程之锁的艺术:面试与实战指南(三) 文章目录 Java并发编程之锁的艺术:面试与实战指南(三)前言十七、Java中线程和进程的区别是什么?十八、什么是Java内存模型(JMMÿ…...
Final Draft 12 for Mac:高效专业剧本创作软件
对于剧本创作者来说,一款高效、专业的写作工具是不可或缺的。Final Draft 12 for Mac就是这样一款完美的选择。这款专为Mac用户设计的剧本创作软件,凭借其卓越的性能和丰富的功能,让您的剧本创作更加得心应手。 Final Draft 12支持多种剧本格…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...
视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...
Xela矩阵三轴触觉传感器的工作原理解析与应用场景
Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知,帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量,能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度,还为机器人、医疗设备和制造业的智…...
使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...
JDK 17 序列化是怎么回事
如何序列化?其实很简单,就是根据每个类型,用工厂类调用。逐个完成。 没什么漂亮的代码,只有有效、稳定的代码。 代码中调用toJson toJson 代码 mapper.writeValueAsString ObjectMapper DefaultSerializerProvider 一堆实…...
