C++ getline 函数缺少 txt 文件的第一行

C++ getline function missing the first line of txt file

我已经编写了一个函数来读取 .txt 文件并构建一个链表,但是该函数错过了文件的第一行。有人知道为什么会这样吗?

输出:

//empty line  
gmail  
San Francisco  
123456

.txt 文件

person1
gmail
San Francisco
123456

读取文件函数

void list::readFile(std::string fileName){
    fstream fs;
    string dummy = "";
    string firstline;
    record * previous = new record;
    record * temp = new record;
    int recordCount = 0;
    fs.open(fileName, ios::in | ios::binary);
        do{
            std::getline(fs, temp->name);
            std::getline(fs, temp->email);
            std::getline(fs, temp->address);
            fs >> temp->phoneNo;
            std::getline(fs, dummy);
            recordCount++;

            if(head == NULL){
                head = temp;
                previous = temp;
                tail = temp;
            } else {
                previous->next = temp;
                previous = temp;
                tail = temp;
            }

        } while(!fs.eof());
    // } else {
    //     cout << "there's no record in the file yet." << endl;
    // }

    cout << head->name << endl;
    cout << head->address <<endl;
    cout << head->email << endl;
    cout << head->phoneNo << endl;
}

您创建了一个节点,因此循环中的每次迭代都会覆盖之前读取的值。

在 while 循环的第二次迭代中,您对 getline 的第一次调用可能会失败,并将 name 的值设置为空字符串。由于流现在处于失败状态,您的其余读取将被忽略,最后循环在循环结束时中断。

这可能更接近您想要的:

    int recordCount = 0;
    fs.open(fileName, ios::in | ios::binary);
        while(fs) {
            record * temp = new record;
            std::getline(fs, temp->name);
            std::getline(fs, temp->email);
            std::getline(fs, temp->address);
            fs >> temp->phoneNo;
            if (!fs) {
                // Reading failed, delete the temporary and exit the loop
                delete temp;
                break;
            }
            std::getline(fs, dummy);
            recordCount++;

            if(head == NULL){
                head = temp;
                previous = temp;
                tail = temp;
            } else {
                previous->next = temp;
                previous = temp;
                tail = temp;
            }

        }

您的代码可以通过使用智能指针来确保 temp 永远不会泄漏,即使抛出异常也不会泄漏。

我将向您解释为什么会出现此问题以及如何避免。

这是一个典型的问题,在评论中提到了数千次,上面也是“molbdnilo”。

您不得使用 while (fs.eof())

我会向你解释为什么。顺便说一句,它只会发生,因为你在最后一行的末尾有一个新行。

让我们看看会发生什么:

  1. 变量“temp”被分配了一个
  2. 文件已打开
  3. do-循环开始
  4. 您通过 未格式化 输入函数 std::getline 读取姓名、电子邮件、地址。此函数将吃掉尾随的白色 space '\n'(但不会将其处理为读取变量
  5. 您使用格式化输入函数 >> 来读取 phone 数字(这不是一个好主意。无论如何)。格式化输入函数将在白色 space 处停止,这里是最后一行末尾的 '\n'。它不会消耗'\n'。这仍在流中并等待输入。
  6. 您将 std::getline 与虚拟对象一起使用,以从流中读取仍然存在的 '\n'。流还是可以的。到目前为止一切顺利。该文件也不在 EOF。我们可以阅读所有内容。所以,很好。
  7. do loop 结束。你说:while(!fs.eof())。但是如上所述:还没有EOF。一切都很好,现在仍然很好。循环将继续。
  8. 再次回到循环的开始
  9. std::getline(fs, temp->name); 将被调用。现在而不是以前,我们得到一个 EOF。因为我们试图阅读,现在没有什么可读的了。 “temp->name”将被设置为一个空字符串。现在,输入流处于 EOF 状态。 10 所有进一步的读取都不会执行任何操作,因为流处于 EOF 中。从现在开始,变量将不会被修改。

这就是为什么 name 为空而其他数据仍然存在的原因 运行。

为了快速修复,您可以编写

void list::readFile(std::string fileName) {
    fstream fs;
    string dummy = "";
    string firstline;
    record* previous = new record;
    record* temp = new record;
    int recordCount = 0;
    fs.open(fileName, ios::in | ios::binary);
    if (fs) 
    while (std::getline(fs, dummy)) {
        temp->name = dummy;
        std::getline(fs, temp->email);
        std::getline(fs, temp->address);
        fs >> temp->phoneNo;
        std::getline(fs, dummy);
        recordCount++;

        if (head == NULL) {
            head = temp;
            previous = temp;
            tail = temp;
        }
        else {
            previous->next = temp;
            previous = temp;
            tail = temp;
        }

    } 
    // } else {
    //     cout << "there's no record in the file yet." << endl;
    // }

    cout << head->name << endl;
    cout << head->address << endl;
    cout << head->email << endl;
    cout << head->phoneNo << endl;
}

但这也不好。稍后我会展示更好的解决方案。