目录一、本节作业要求1.1 作业功能要求1插入数据2查找数据3删除数据1.2 作业实现要求1.3 本节作业的意义二、作业需求分析2.1 这个“缓存数据库”本质上是什么2.2 为什么使用两个 vector三、实现思路3.1 用户输入命令3.2 命令拆分3.3 数据存储3.4 数据查找3.5 数据删除四、完整代码实现与运行4.1 代码实现4.2 代码运行效果演示4.2.1 输入示例4.2.2 输出示例4.2.3 结果分析五、代码详细解析5.1 头文件与命名空间5.2 定义两个 vector5.3 使用 getline 获取整行命令5.4 istringstream iss(input); 到底是什么意思5.4.1 它的本质是什么5.4.2 iss cmd; 读取了什么5.5 insert 插入命令的处理过程5.6 查找 key 的逻辑5.6.1 index -1 表示什么5.6.2 if (keys[i] key) 是什么意思5.6.3 为什么 keys[i] 不是一个字母5.7 为什么“前面没存进去”却还能比较六、本节重难点与常见疑问6.1 getline(cin, input) 和 cin input 有什么区别6.2 istringstream 为什么有用6.3 keys 和 key 的区别七、小结一、本节作业要求本节作业的核心目标是使用 C 基础语法实现一个简易缓存数据库程序。这个“小型缓存数据库”并不是真正意义上的数据库系统而是一个入门级的键值存储Key-Value模拟程序。用户通过输入命令可以完成数据的插入、查询和删除。1.1 作业功能要求根据本次作业要求程序需要支持以下功能1插入数据用户输入insert xcj datastring表示将keyxcjvaluedatastring存入缓存数据库中并提示“存储成功”。2查找数据用户输入get xcj程序需要根据关键字xcj找到对应的值并输出datastring3删除数据用户输入delete xcj程序需要删除关键字xcj对应的数据并提示删除成功。1.2 作业实现要求本次作业还要求实现时满足以下几点1使用getline获取用户输入的一整行命令2使用两个vector存储数据1一个vector存key2一个vector存value3程序主体使用main函数完成不额外拆分函数也可以4完成命令解析、查找逻辑和删除逻辑1.3 本节作业的意义把前面学过的知识点串起来完成一个真正可以运行的小项目。虽然这个程序规模不大但它几乎涵盖了 C 初学阶段很多关键知识点比如getline读取整行输入string字符串处理istringstream命令拆分vectorstring存储多个字符串for循环遍历查找if条件判断erase删除元素可以说这一节就是前面基础内容的一次综合练习。二、作业需求分析2.1 这个“缓存数据库”本质上是什么从本质上来说这个作业是在实现一个最简单的键值对存储系统。比如输入insert xcj datastring insert key2 data2 insert key3 data3123那么程序内部要保存的数据关系就是xcj - datastring key2 - data2 key3 - data3123这和真实数据库中的“键值映射”思想很像只不过这里我们没有用真正的数据库而是用vector来模拟。2.2 为什么使用两个vector题目要求一个vector存放 key一个vector存放 value因此可以这样设计vectorstring keys; vectorstring values;它们通过相同下标建立对应关系keys[0] - values[0] keys[1] - values[1] keys[2] - values[2]例如keys[0] xcj; values[0] datastring;表示xcj - datastring三、实现思路3.1 用户输入命令因为用户输入的命令可能是这样insert xcj datastring这里一整行里包含多个单词中间还有空格。如果使用普通的cin input;那么只能读取到第一个单词不能完整获取整行命令。因此这里要使用getline(cin, input);这样就可以把整条命令完整读进来。3.2 命令拆分读取到整行字符串之后还需要把它拆成命令名insertkeyxcjvaluedatastring这里使用istringstream iss(input);把字符串转成“字符串输入流”然后再像cin一样读取string cmd; iss cmd;这样就能先读出命令。3.3 数据存储程序运行过程中用户可能会不断插入数据因此我们使用动态容器vectorstringvectorstring keys; vectorstring values;当执行insert时把 key 放入keys把 value 放入values。3.4 数据查找查找的核心就是遍历keysfor (int i 0; i (int)keys.size(); i) { if (keys[i] key) { index i; break; } }找到后再通过相同下标去values中取值。3.5 数据删除删除时既要删keys中对应位置的 key也要删values中对应位置的 valuekeys.erase(keys.begin() index); values.erase(values.begin() index);这样才能保证两个vector的下标继续一一对应。四、完整代码实现与运行4.1 代码实现#include iostream #include string #include vector #include sstream using namespace std; int main(int argc, char* argv[]) { vectorstring keys; // 存放 key vectorstring values; // 存放 value cout endl; cout 简易缓存数据库系统启动成功 endl; cout 支持命令insert / get / delete / show / exit endl; cout endl; string input; while (true) { cout \n请输入命令 ; getline(cin, input); if (input.empty()) { continue; } istringstream iss(input); string cmd; iss cmd; // 1. 插入数据 if (cmd insert) { string key; string value; iss key; getline(iss ws, value); // 读取剩余内容作为 value支持空格 if (key.empty() || value.empty()) { cout 命令格式错误正确格式insert key value endl; continue; } int index -1; for (int i 0; i (int)keys.size(); i) { if (keys[i] key) { index i; break; } } if (index ! -1) { values[index] value; cout 更新成功[ key ] value endl; } else { keys.push_back(key); values.push_back(value); cout 存储成功[ key ] value endl; } } // 2. 查找数据 else if (cmd get) { string key; iss key; if (key.empty()) { cout 命令格式错误正确格式get key endl; continue; } int index -1; for (int i 0; i (int)keys.size(); i) { if (keys[i] key) { index i; break; } } if (index ! -1) { cout 输出值 values[index] endl; } else { cout 未找到 key: key endl; } } // 3. 删除数据 else if (cmd delete) { string key; iss key; if (key.empty()) { cout 命令格式错误正确格式delete key endl; continue; } int index -1; for (int i 0; i (int)keys.size(); i) { if (keys[i] key) { index i; break; } } if (index ! -1) { keys.erase(keys.begin() index); values.erase(values.begin() index); cout 显示删除成功 endl; } else { cout 删除失败未找到 key: key endl; } } // 4. 显示所有数据 else if (cmd show) { if (keys.empty()) { cout 当前缓存为空 endl; } else { cout 当前缓存内容如下 endl; for (int i 0; i (int)keys.size(); i) { cout keys[i] - values[i] endl; } } } // 5. 退出程序 else if (cmd exit) { cout 程序退出成功 endl; break; } // 6. 未知命令 else { cout 未知命令请重新输入 endl; } } return 0; }4.2 代码运行效果演示4.2.1 输入示例insert xcj datastring insert key2 data2 insert key3 data3123 get xcj delete key2 show exit4.2.2 输出示例存储成功[xcj] datastring 存储成功[key2] data2 存储成功[key3] data3123 输出值datastring 显示删除成功 当前缓存内容如下 xcj - datastring key3 - data3123 程序退出成功4.2.3 结果分析从运行结果可以看出1insert可以成功插入数据2get可以根据 key 取出对应的 value3delete可以删除指定 key 对应的数据4show可以查看当前缓存中的全部内容5整个程序已经具备了一个最基础键值缓存系统的雏形五、代码详细解析5.1 头文件与命名空间#include iostream #include string #include vector #include sstream using namespace std;1iostream用于输入输出比如cin和cout2string用于字符串类型string3vector用于动态数组容器vector4sstream用于字符串流istringstream把一整行字符串拆分成多个部分5.2 定义两个vectorvectorstring keys; vectorstring values;这里定义了两个字符串类型的动态数组。1keys用来保存关键字2values用来保存对应的值例如执行insert xcj datastring后程序内部可能变成keys[0] xcj; values[0] datastring;5.3 使用getline获取整行命令string input; getline(cin, input);这一句的作用是从控制台读取用户输入的一整行内容。比如用户输入insert xcj datastring那么input insert xcj datastring如果这里不用getline而用cin input那么只能读到insert后面的内容就拿不到了。5.4istringstream iss(input);到底是什么意思这是本节一个非常容易疑惑的点。istringstream iss(input); string cmd; iss cmd;5.4.1 它的本质是什么可以把它理解成cin从键盘读取iss从字符串里读取也就是说前面用getline读到的是一整个字符串insert xcj datastring而istringstream的作用就是把这个字符串变成“可按空格一个个读取的流”。5.4.2iss cmd;读取了什么这句会读取第一个单词也就是命令名cmd insert之后再继续读取就可以得到 key 和 value。所以这三句代码的整体作用就是把用户输入的一整行命令拆开先取出第一个单词作为命令。5.5insert插入命令的处理过程if (cmd insert) { string key; string value; iss key; getline(iss ws, value);这里的逻辑是1先读命令后的第一个单词作为key2再把剩余内容作为value例如输入insert xcj datastring那么key xcj value datastring如果用户输入的是insert name hello world那么这里的getline(iss ws, value);还能把带空格的内容一起读出来value hello world5.6 查找 key 的逻辑int index -1; for (int i 0; i (int)keys.size(); i) { if (keys[i] key) { index i; break; } }这一段是整个程序查找逻辑的核心。5.6.1index -1表示什么这里用index表示“目标 key 所在的位置”。如果找到了就让index i如果没找到就保持-1因此-1可以理解为一个“未找到标记”。5.6.2if (keys[i] key)是什么意思这句是在比较keys[i]第i个存进去的 keykey当前用户输入的 key如果两者相等说明找到了对应位置。例如keys[0] xcj keys[1] key2用户输入get key2那么key key2循环时会依次比较keys[0] key2 // false keys[1] key2 // true找到后index 1; break;5.6.3 为什么keys[i]不是一个字母因为vectorstring keys;这里keys里面存的是很多个string 字符串不是字符。所以keys[i]取出来的是第i个字符串比如xcj、key2而不是单个字符。这一点要和下面这种情况区分开string s xcj; s[0]这里的s[0]才是单个字符x。也就是说1keys[i]取vector里的第i个字符串2str[i]取字符串里的第i个字符这两个写法表面看起来很像但含义完全不同。5.7 为什么“前面没存进去”却还能比较很多同学会觉得前面只是定义了vectorstring keys;并没有马上push_back数据那后面怎么比较答案是空的时候其实不会比较。因为查找代码写的是for (int i 0; i (int)keys.size(); i)如果现在keys是空的那么keys.size() 0循环就变成for (int i 0; i 0; i)一次都不会执行。也就是说程序刚启动时keys只是一个空容器只有用户执行insert之后才真正往里面放入内容后面执行get或delete时才会遍历已有的数据进行比较所以不是“没存进去先比较”而是“先定义空容器后续有数据了再比较”。六、本节重难点与常见疑问6.1getline(cin, input)和cin input有什么区别1cin input读取到空格就停止2getline(cin, input)读取整行内容直到按下回车对于本节这种命令行程序来说命令一般都是一整行因此更适合用getline。6.2istringstream为什么有用因为它可以把整行字符串再次拆开读取。例如string input get xcj; istringstream iss(input); string cmd, key; iss cmd key;结果就是cmd get key xcj它特别适合做命令解析、配置行解析、简单脚本输入处理。6.3keys和key的区别这是变量命名上很容易混的地方。1key表示一个单独的关键字2keys表示很多个 key 组成的容器这里同理key一个键keys很多键七、小结本节通过一个“简易缓存数据库”作业把前面学过的多个 C 基础知识点串联了起来。我们不仅练习了stringvectorgetlineistringstreamforiferase还真正完成了一个可运行的小项目。更重要的是这个作业背后体现的是一种很典型的程序设计思想把用户输入解析为命令再根据命令操作程序内部的数据结构。虽然这里实现得还比较简单但它已经非常接近很多真实程序的基本工作流程了比如命令行工具配置解析器简易管理系统键值缓存结构