为什么 getline() 不读取行中的最后一个 int 值?

Why does getline() not read the last int value in the line?

我有一个包含书籍列表的文件。每本书有 4 个变量,用制表符分隔。

变量是

大约有 400 本书条目。

我已经设法编写了一个函数,将每个输入读取到一个数组并将其保存到一本书中 object。

void loadFile() {
  
    std::ifstream inputFile("books");
    std::string bookArray[4];
    std::string line;
    Book book;
    while (getline(inputFile, line)) {
        size_t field2 = 0;
        size_t field1 = line.find("\t");
        for (int i = 0; i <= 3; i++) {
            size_t field1 = line.find("\t" , field2);
            if (field1 != std::string::npos) {
                std::string str2 = line.substr(field2, field1 - field2);
                bookArray[i] = str2;
            }
            field2 = field1 + 1;
        }
        
        book.setTitle(bookArray[0]);
        book.setAuthor(bookArray[1]);
        book.setIsbn(bookArray[2]);
        book.setQty(stoi(bookArray[3]));
  std::cout << "Book:   " <<book.getTitle <<'\t'<< book.getQty<< " records.\n";
}

但该函数似乎无法获取每行末尾的数量。除了数量之外,其他一切似乎都很好。我找不到函数有什么问题。

我试过使用'\t'定界符参数实现相同的getline()函数,如下所示:

while(getline(input, line, '\t')) {

输出只读了第一行的标题就停在那里。我知道第一个功能有效。
为什么它不获取 qty 值?

书籍文件格式如下:

A First Look at Graph Theory    Clark John; Holton Derek Allan  9788170234630   5
A Practical Approach To Data Structures And Algorithms  Sanjay Pahuja   9788122420678   7
A Practical Approach to High-Performance Computing  Sergei Kurgalin; Sergei Borzunov    9783030275587   6
A Practical Guide to UNIX for Mac OS X Users    Mark G. Sobell; Peter Seebach   9780321629982   5
A River Marc Martin 9781452162256   4

这里是菜鸟,如果我的代码很笨拙,我深表歉意。

原因是在数量之后的行尾(可能)没有制表符。因此,当您第 4 次调用 line.find("\t", field2) 时,它 returns string::npos 并且您不会在 bookArray[3]

中存储任何内容

最好的解决办法可能是用 if:

放一个 else
    } else {
        std::string str2 = line.substr(field2, std::string::npos);
        bookArray[i] = str2;
        break;  // there can be no more fields on the line

请注意,如果一行中的字段少于 4 个,bookArray 中未找到字段的元素将不会被触及(因此将继续具有上一行的值)

解释了为什么您的代码无法解析 qty 值。

作为替代解决方案,我建议使用 std::istringstream 来解析每个 linestd::getline(),让它为您处理搜索和拆分 1 ,例如:

void loadFile() {
  
    std::ifstream inputFile("books");
    std::string bookArray[4];
    std::string line;
    Book book;

    while (std::getline(inputFile, line)) {
        std::istringstream iss(line);
        for(int i = 0; i < 4; ++i) {
            std::getline(iss, bookArray[i], '\t');
        }

        book.setTitle(bookArray[0]);
        book.setAuthor(bookArray[1]);
        book.setIsbn(bookArray[2]);
        book.setQty(stoi(bookArray[3]));

        std::cout << "Book:   " << book.getTitle << '\t' << book.getQty << " records.\n";
    }
}

1: 当然还有 many different ways 来标记分隔符上的字符串。

或者,让 istringstream 为您处理 qtyint 的转换,无需手动调用 std::stoi()

void loadFile() {
  
    std::ifstream inputFile("books");
    std::string bookArray[3];
    int qty;
    std::string line;
    Book book;

    while (std::getline(inputFile, line)) {
        std::istringstream iss(line);
        for(int i = 0; i < 3; ++i) {
            std::getline(iss, bookArray[i], '\t');
        }
        iss >> qty;

        book.setTitle(bookArray[0]);
        book.setAuthor(bookArray[1]);
        book.setIsbn(bookArray[2]);
        book.setQty(qty);

        std::cout << "Book:   " << book.getTitle << '\t' << book.getQty << " records.\n";
    }
}