如何根据参考号条件更新TXT文件中的商品信息?
控制台库存管理程序更新功能异常问题
我正在开发一个学校项目的基础控制台库存管理程序(非SQL相关),通过struct创建商品并写入database.txt文件。现在需要根据商品的参考号(格式为REF:)找到对应条目,更新该参考号下直至下一个参考号的所有内容,但运行代码后出现异常。
当前代码
if(button2 == 2) { string refNo; string word; cout <<"Enter the referance number of item for update" << endl; cin >> refNo; refNo = "REF:"+refNo; fstream file(databaseFile.c_str()); if(file.is_open()) { while(getline(file, word)) { if(word == refNo) { product entity = createItem(true); file << entity.detail.category << endl; file << entity.name << endl; file << entity.price << endl; file << entity.profitMargine << endl; file << entity.stock << endl; } } } }
问题原因
- 文件读写模式错误:默认
fstream打开方式为in|out,写入时仅覆盖当前指针位置的内容,不会替换整段条目,导致新旧内容混杂。 - 未处理原有条目数据:找到目标REF后直接写入新内容,但原有条目下的旧数据未被移除,残留于文件中。
- 指针位置逻辑错误:
getline移动文件指针后,写入操作是在当前位置追加/覆盖,而非从REF开始替换后续行。
解决方法
正确流程是先将文件内容全部读入内存,修改后重新写入文件,步骤如下:
修改后的代码示例
#include <iostream> #include <fstream> #include <vector> #include <string> // 假设已有product结构体定义 struct product { struct { std::string category; } detail; std::string name; double price; double profitMargine; int stock; }; // 假设createItem函数用于获取更新后的商品信息 product createItem(bool isUpdate) { product p; std::cout << "输入商品分类: "; std::cin >> p.detail.category; std::cout << "输入商品名称: "; std::cin >> p.name; std::cout << "输入商品价格: "; std::cin >> p.price; std::cout << "输入利润率: "; std::cin >> p.profitMargine; std::cout << "输入库存数量: "; std::cin >> p.stock; return p; } int main() { int button2 = 2; const std::string databaseFile = "database.txt"; if (button2 == 2) { std::string refNo; std::cout << "输入要更新的商品参考号: "; std::cin >> refNo; refNo = "REF:" + refNo; // 1. 读取文件全部内容到内存 std::vector<std::string> fileLines; std::string line; std::ifstream inFile(databaseFile); if (inFile.is_open()) { while (std::getline(inFile, line)) { fileLines.push_back(line); } inFile.close(); } else { std::cout << "无法打开文件读取内容" << std::endl; return 1; } // 2. 定位目标REF及需要替换的行范围 bool refFound = false; int startIdx = -1; int endIdx = fileLines.size() - 1; for (int i = 0; i < fileLines.size(); ++i) { if (fileLines[i] == refNo) { refFound = true; startIdx = i; // 查找下一个REF的位置,确定替换结束点 for (int j = i + 1; j < fileLines.size(); ++j) { if (fileLines[j].substr(0, 4) == "REF:") { endIdx = j - 1; break; } } break; } } // 3. 替换条目内容并重新写入文件 if (refFound) { product updatedItem = createItem(true); // 删除原有条目下的旧内容 fileLines.erase(fileLines.begin() + startIdx + 1, fileLines.begin() + endIdx + 1); // 插入新的商品信息(注意顺序要和写入时一致) fileLines.insert(fileLines.begin() + startIdx + 1, std::to_string(updatedItem.stock)); fileLines.insert(fileLines.begin() + startIdx + 1, std::to_string(updatedItem.profitMargine)); fileLines.insert(fileLines.begin() + startIdx + 1, std::to_string(updatedItem.price)); fileLines.insert(fileLines.begin() + startIdx + 1, updatedItem.name); fileLines.insert(fileLines.begin() + startIdx + 1, updatedItem.detail.category); // 写入修改后的内容 std::ofstream outFile(databaseFile); if (outFile.is_open()) { for (const auto& l : fileLines) { outFile << l << std::endl; } outFile.close(); std::cout << "商品信息更新成功" << std::endl; } else { std::cout << "无法打开文件写入内容" << std::endl; } } else { std::cout << "未找到参考号为 " << refNo << " 的商品" << std::endl; } } return 0; }
关键步骤说明
- 内存中修改:将文件内容读入
vector<string>,避免直接操作文件导致的指针混乱和内容残留问题。 - 精准定位范围:找到目标REF后,定位到下一个REF的位置,确保只替换当前条目下的内容。
- 全量重写:修改完成后将整个内存中的内容重新写入文件,保证文件结构的完整性。
内容的提问来源于stack exchange,提问作者Alperen Usta
相关产品推荐
相关产品推荐

