You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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;
    }
}

问题分析与解决方案

你更新后的代码存在几个明显问题,导致无法正确读取数据:

  1. 未正确读取群组数据:在i%3==1的分支里用了变量y,但循环里只读取了x,y未赋值,应该替换为当前行的x
  2. 位运算误用:myfile.is_open() & myfile.peek() != EOF里的&是位运算符,应使用逻辑与&&
  3. 赋值错误:newer->prev == NULL是比较操作,不是赋值,应写成newer->prev = NULL
  4. 重复遍历链表:每次找最后一个节点都从头遍历,效率低且易出错

更简洁可靠的方式是直接按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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 03:05:27