当存在空单元格时,用于 c++ 的 Tsv 文件解析器会突然结束

Tsv file parser for c++ ends abruptly when empty cell is present

本文关键字:文件 结束 突然 Tsv 单元格 存在 c++ 用于      更新时间:2023-10-16

我正在尝试解析 .tsv 文件并将行的每个单元格的值存储在结构中。每一行构成结构并追加到列表中。如果单元格为空,则getline while 循环突然结束

.tsv 文件如下所示:

No Name Age Grade
1   Andy 17   A
2   Drew 16   B
3   Brad 17   B
4   Cam       A
5   Sam  18   B

示例代码

std::ifstream tsvFile(filePath);
if (!tsvFile.good()) return;
for (std::string line; std::getline(tsvFile, line); )
{
  example item;
  tsvFile >> example.s_no >> example.name >> example.age >> example.grade;
  tsv_list.push_back(item);
}
tsvFile.close();

遍历所有行,不会突然停止。有没有更好的方法来逐行解析 tsv 并添加特定的制表符分隔符?我尝试使用line但值似乎不正确。每次循环访问时,打印line都会给我一个整数,而不是整行。

这是从文件中读取记录的典型示例。

我们将选择一种面向对象的方法,并将所有数据放入一个结构中,并且,由于结构应该知道如何读取和写入其数据,因此添加提取器和插入器操作器。

提取器将读取一整行,然后将数据放入结构成员中。如果出现错误,可以使用默认值。

主要情况下,我们只需定义 Roster 的向量并使用范围构造函数,在变量定义期间读取完整的输入文件。

之后,我们打印结果。

#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <vector>
#include <iterator>
// Test Data. Same as reading from file
std::istringstream testFile(R"#(1   Andy 17   A
2   Drew 16   B
3   Brad 17   B
4   Cam       A
5   Sam  18   B
)#");

struct Roster
{
    // Roster Data
    size_t No{};    std::string Name{}; size_t Age{};   char Grade{};
    // Extractor operator >> for Roster
    friend std::istream& operator >> (std::istream& is, Roster& r) {
        std::string line{};             // Here we will store the read line
        std::getline(is, line);         // Read complete line
        std::istringstream iss(line);   // Copy to a istringstream for extraction
        if (!(iss >> r.No >> r.Name >> r.Age >> r.Grade)) {     // Extract
            // In case of error: Reset all values
            r.No = 0; r.Name = "ERROR"; r.Age = 0; r.Grade = '#';
        };
        return is;
    }
    // Inserter operator << . Print space delimited data
    friend std::ostream& operator << (std::ostream& os, const Roster& r) {
        return os << r.No << ' ' << r.Name << ' ' << r.Age << ' ' << r.Grade;
    }
};
int main()
{
    // Read complete CSV
    std::vector<Roster> roster{ std::istream_iterator<Roster>(testFile), std::istream_iterator<Roster>() };
    // Copy all data to output
    std::copy(roster.begin(), roster.end(), std::ostream_iterator<Roster>(std::cout, "n"));
    return 0;
}