0

我想使用 逐行读取文本文件,istream_iterator但是当行中有空格时它会失败。

这是一个示例代码:

#include <fstream>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <string>

int main(int argc, char** argv)
{
  if (argc != 2) {
    std::cout << argv[0] << " <file-name>" << std::endl;
    return 10;
  }

  std::ifstream _in(argv[1]);
  if (!_in.good()) {
      std::cout << "error reading " << argv[1] << std::endl;
      return 20;
  }

  _in.unsetf(std::ios_base::skipws);

  std::istream_iterator<std::string> _ite(_in);
  std::istream_iterator<std::string> _end;
  std::string _s(*_ite);

  std::cout << "line read " << _s << std::endl;
}

例如,在这个输入文件中: 1;3.14;bla bla -3;0.923;let me go

读取的第一个字符串是1;3.14;bla

有没有办法做到这一点,还是我应该放弃并使用getline

4

2 回答 2

2
于 2019-08-15T06:32:30.487 回答
1

不,不要放弃。使用 C++ 方法。虽然我也会使用std::getline,但我认为它是 C 风格的。因此,我将把这个函数包装在一个代理类中。

我觉得你的想法很好,使用std::istream_iterator. 这是“更现代”的 C++ 做事方式。最大的优势是您可以使用istream_iteratorin 算法。

唯一要解决的问题是将“线”的抽象模型实现到类中。正如我将在下面展示的那样,这相当容易。

使用代理类是标准方法,您会在这里找到很多关于 SO 的示例。

请参见:

#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <iterator>
#include <algorithm>
#include <sstream>
#include <ios>


std::istringstream testFile{R"(Line1Word1 Line1Word2 Line1Word3 
Line2Word1 Line2Word2
Line3Word1 Line3Word2 Line3Word3  Line3Word4
Line4Word1 Line4Word2 Line4Word3
)"};

struct Line      // ! This is a proxy for the input_iterator and output iterator! 
{   
    // Input function. Read on line of text file and split it in columns
    friend std::istream& operator>>(std::istream& is, Line& line) {
        return std::getline(is, line.lineTemp ); 
    }

    // Output function. 
    friend std::ostream& operator<<(std::ostream& os, const Line& line) {
        return os <<  line.lineTemp; 
    }

    // cast to needed result
    operator std::string() const { return lineTemp; }  
    // Temporary Local storage for line
    std::string lineTemp{};  
};


int main()
{
    std::cout << "\n\nTest 1. Read all lines into a vector:\n";
    std::vector<std::string> allLines {std::istream_iterator<Line>(testFile),std::istream_iterator<Line>() };
    std::copy(allLines.begin(), allLines.end(), std::ostream_iterator<std::string>(std::cout, "\n"));

    std::cout << "\n\nTest 2: Display fist 2 in file\n";
    testFile.clear(); testFile.seekg(0,std::ios::beg);
    std::copy_n(std::istream_iterator<Line>(testFile),2,std::ostream_iterator<std::string>(std::cout, "\n"));

    testFile.clear(); testFile.seekg(0,std::ios::beg);
    std::cout << "\n\nTest 3: Number of lines in File\n"
        << std::distance(std::istream_iterator<Line>(testFile),std::istream_iterator<Line>());

    std::cout << "\n\nTest 4: Use iterator separately\n";
    testFile.clear(); testFile.seekg(0,std::ios::beg);
    // Define the iterator
    std::istream_iterator<Line> lineIterator(testFile);
    // Dereference iterator
    std::cout << *lineIterator << "\n";

    return 0;
}
于 2019-08-15T07:35:56.643 回答