使用D++开发Discord Bot时修改实体生命值的文件读写异常问题
问题分析与修复方案
核心问题根源
你代码的问题出在错误使用getline的分隔符:你用':'作为getline的分隔符,导致文件中的换行符被当作普通字符读入,破坏了实体名与生命值的对应关系,最终导致循环次数不足、写入内容异常。
具体来说,原文件每行格式是实体名:生命值\n,当用getline(..., ':')读取时:
- 第一次读取到
Zombie(第一个:前的内容) - 第二次读取到
120\nSkeleton(从第一个:后,到第二个:前的所有内容,包括换行符和下一个实体的名字) - 第三次读取到
200\nVampire(从第二个:后,到第三个:前的所有内容) - 第四次读取到
500(第三个:后的剩余内容)
这就是循环只执行4次的原因——文件里只有3个:,所以getline会生成4个分段。而stoi("120\nSkeleton")只会解析出数字120,剩下的\nSkeleton被丢弃,但实体名列表里会错误地加入200\nVampire这类包含换行符的字符串,写入文件时就会出现换行错乱。
修复代码
正确的做法是先按行读取整个文件内容,再拆分每行的实体名和生命值,这样能避免换行符干扰:
if (event.command.get_command_name() == "change") { vector<string> entities; vector<int> health; string nameChoice = get<string>(event.get_parameter("user")); int64_t delta = get<int64_t>(event.get_parameter("numeral")); // 按行读取文件 ifstream MyReadFile("entities.txt"); string line; while(getline(MyReadFile, line)) { // 找到每行中的冒号位置 size_t colonPos = line.find(':'); if (colonPos == string::npos) { // 跳过格式错误的行 continue; } string entityName = line.substr(0, colonPos); string healthStr = line.substr(colonPos + 1); entities.push_back(entityName); int currentHealth = stoi(healthStr); // 判断是否是要修改的实体 if (entityName == nameChoice) { currentHealth += delta; } health.push_back(currentHealth); } // 写入修改后的内容 ofstream MyFile("entities.txt"); for (size_t i = 0; i < entities.size(); i++) { MyFile << entities[i] << ":" << health[i] << "\n"; } }
额外注意事项
- 异常处理:
stoi在遇到非数字字符串时会抛出异常,建议添加try-catch块或者使用stoll(支持更大数值范围)并配合错误检查。 - 文件操作安全:如果文件不存在或无法读取,
ifstream会处于错误状态,建议先检查MyReadFile.is_open()确保文件成功打开。 - RAII原则:C++的文件流对象会在离开作用域时自动关闭文件,无需手动调用
close(),避免遗漏导致的资源泄漏。
内容的提问来源于stack exchange,提问作者SmawCity
相关产品推荐
相关产品推荐

