C++读取多行关联的文件时混合getline与>>运算符出错如何解决
问题原因
你判断的问题根源完全正确:>>运算符读取完第二行的整数、姓氏后,会将行末尾的换行符残留在输入缓冲区,下一轮循环调用getline时会直接读取到这个残留换行符,得到空字符串,后续所有读取逻辑就全部错位。
同时原有代码的循环判断逻辑也存在问题,会在文件读取结束后多插入一个无效的Person对象。
解决方法
推荐使用「全getline读行 + 字符串流解析字段」的方案,完全避免混用两种读取方式的兼容问题:
- 每轮循环先调用
getline读取第一行的全名(支持带空格) - 再调用
getline读取第二行完整内容,将内容导入std::istringstream,再用>>从字符串流中解析两个整数和姓氏字段 - 把读取操作的返回值作为循环判断条件,避免插入无效对象
修正后完整代码
#include <iostream> #include <fstream> #include <string> #include <sstream> #include <set> #include <vector> class Person{ private: std::string name1, name2; int i1, i2; public: Person(){} Person(std::string ss1, std::string ss2, int ii1, int ii2) { name1 = ss1; name2 = ss2; i1 = ii1; i2 = ii2; } void show() { std::cout << name1 << ", " << name2 << " , " << i1 <<std::endl; } void init(std::string ss1, std::string ss2, int ii1, int ii2) { name1 = ss1; name2 = ss2; i1 = ii1; i2 = ii2; } bool operator < (const Person& other) const { return (name1 < other.name1 ); } }; int main() { std::string s1, line, s2; int i1, i2; std::set<Person> Personenset; std::vector<Person> Personenvec; Person p; std::ifstream istr("datenprobieren.dat"); // 把读取操作作为判断条件,读取失败直接终止循环 while(getline(istr, s1) && getline(istr, line)) { // 用字符串流解析第二行的字段 std::istringstream iss(line); iss >> i1 >> i2 >> s2; p.init(s1, s2, i1, i2); Personenset.insert(p); Personenvec.push_back(p); } std::cout << Personenvec.size() <<std::endl; Personenvec[1].show(); return 0; }
如果你不想改整体读取逻辑,也可以在原有istr >> i1 >> i2 >> s2;之后加一行istr.ignore();跳过残留的换行符,但是这种方案在第二行末尾有多余空格的场景下容易出问题,更推荐上面的全读行方案。
内容的提问来源于stack exchange,提问作者Elias Sohalt
相关产品推荐
相关产品推荐

