如何在C++中使用getline()函数从多行文本文件每次读取3行?
如何用getline()按3行一组读取文本文件数据并映射到链表节点?
我想用getline()从文本文件里读取3行数据,之前读2行的时候靠判断行号奇偶就能区分数据,运行正常,但改成3行后这个方法就不好使了。能不能用getline()实现按3行一组读取?
文本文件的数据格式是每3行对应一个联系人:第1行是姓名,第2行是群组,第3行是电话号码,需要把这些数据存到链表的节点中。
以下是之前读取2行时能正常运行的代码:
void reopenCB() { bool isEmpty; ifstream myfile("contactbook.txt"); if (myfile.is_open() & myfile.peek() != EOF) { int i = 0; while (getline(myfile, x)) { if (i % 2 == 0) { if (head == NULL) { Node *newer = new Node; newer->name = x; newer->next = NULL; newer->prev == NULL; head = newer; } else { Node *newer = new Node; newer->name = x; newer->next = NULL; Node *temp = head; while (temp->next != NULL) { temp = temp->next; } temp->next = newer; newer->prev = temp; } } else if (i % 2 != 0) { Node *temp = head; if (temp->phone_number == 0) { stringstream convert(x); convert >> z; temp->phone_number = z; } else { Node *temp = head; while (temp->next != NULL) { temp = temp->next; } stringstream convert(x); convert >> z; temp->phone_number = z; } } } myfile.close(); } else { cout << " File is Empty so Cannot open...Sorry" << endl; } }
这段代码读取2行数据时正常,但改成读取3行后无法获取正确值。
编辑:
按建议修改后的代码:
void reopenCB() { bool isEmpty; ifstream myfile("contactbook.txt"); if (myfile.is_open() & myfile.peek() != EOF) { int i = 0; while (getline(myfile, x)) { if (i % 3 == 0) { if (head == NULL) { Node *newer = new Node; newer->name = x; newer->next = NULL; newer->prev == NULL; head = newer; } else { Node *newer = new Node; newer->name = x; newer->next = NULL; Node *temp = head; while (temp->next != NULL) { temp = temp->next; } temp->next = newer; newer->prev = temp; } } else if (i % 3 == 1) { Node *temp = head; if (temp->group_name == "") { temp->group_name = y; } else { Node *temp = head; while (temp->next != NULL) { temp = temp->next; } temp->group_name = y; } } else if (i % 3 == 2) { Node *temp = head; if (temp->phone_number == 0) { stringstream convert(x); convert >> z; temp->phone_number = z; } else { Node *temp = head; while (temp->next != NULL) { temp = temp->next; } stringstream convert(x); convert >> z; temp->phone_number = z; } } i++; } myfile.close(); } else { cout << " File is Empty so Cannot open...Sorry" << endl; } }
问题分析与解决方案
你更新后的代码存在几个明显问题,导致无法正确读取数据:
- 未正确读取群组数据:在
i%3==1的分支里用了变量y,但循环里只读取了x,y未赋值,应该替换为当前行的x - 位运算误用:
myfile.is_open() & myfile.peek() != EOF里的&是位运算符,应使用逻辑与&& - 赋值错误:
newer->prev == NULL是比较操作,不是赋值,应写成newer->prev = NULL - 重复遍历链表:每次找最后一个节点都从头遍历,效率低且易出错
更简洁可靠的方式是直接按3行一组读取,无需维护行号计数器,逻辑更清晰:
#include <fstream> #include <string> #include <sstream> #include <iostream> // 假设Node结构体定义如下 struct Node { std::string name; std::string group_name; long long phone_number; Node* next; Node* prev; }; Node* head = nullptr; Node* tail = nullptr; // 维护尾指针,避免每次遍历链表 void reopenCB() { std::ifstream myfile("contactbook.txt"); if (!myfile.is_open()) { std::cout << " 无法打开文件..." << std::endl; return; } // 检查文件是否为空 if (myfile.peek() == std::ifstream::traits_type::eof()) { std::cout << " 文件为空,无法读取..." << std::endl; myfile.close(); return; } std::string name, group, phone_str; // 一次性读取3行作为一组,只要有一行读取失败就停止循环 while (std::getline(myfile, name) && std::getline(myfile, group) && std::getline(myfile, phone_str)) { // 创建新节点并赋值 Node* newer = new Node; newer->name = name; newer->group_name = group; // 把字符串电话号码转成数字 std::stringstream convert(phone_str); convert >> newer->phone_number; newer->next = nullptr; newer->prev = nullptr; // 插入到链表末尾 if (head == nullptr) { head = newer; tail = newer; } else { tail->next = newer; newer->prev = tail; tail = newer; } } myfile.close(); }
方案优势
- 逻辑直观:直接按联系人的完整数据组读取,无需判断行号,减少出错概率
- 效率更高:用
tail指针维护链表尾部,插入新节点时无需遍历整个链表 - 鲁棒性强:自动处理文件末尾的不完整数据组,避免无效节点的创建
内容的提问来源于stack exchange,提问作者Faseeh Hyder
相关产品推荐
相关产品推荐

