如何使用 istream_iterator 从 ifstream 中读取带有空格的字符串?



我想使用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

当读取std::string时,它会读取,直到找到第一个空格字符。什么是空间字符是由流的std::locale定义的,更准确地说是它的std::ctype<char>面。您可以创建一个仅将’n’视为空间的std::ctype<char>分面,创建一个包含该分面的std::locale对象,imbue()具有相应std::locale的流,它应该可以工作。

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

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

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

使用代理类是标准方法,您会在这里找到很多关于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 << "nnTest 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 << "nnTest 2: Display fist 2 in filen";
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 << "nnTest 3: Number of lines in Filen"
<< std::distance(std::istream_iterator<Line>(testFile),std::istream_iterator<Line>());
std::cout << "nnTest 4: Use iterator separatelyn";
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;
}

最新更新