目前,我最好的解决方案是: Is there a C++ iterator that can iterate over a file line by line? 但我希望有一个更好的,不涉及创建我自己的迭代器类或实现std :: string的代理。
P.S。这是一个学校作业,这里的挑战是使用标准功能和算法的组合解决问题,但我不知道如何去解决它
答案 0 :(得分:6)
ifstream input("somefile")
if (!input) { /* Handle error */ }
//MyDataType needs to implement an operator>>
std::vector<MyDataType> res;
std::istream_iterator<MyDataType> first(input);
std::istream_iterator<MyDataType> last;
std::copy(first,last, std::back_inserter(res));
//etc..
您的输入操作符可能是这样的:
std::istream& operator>>(std::istream &in,MyDataType & out)
{
std::string str;
std::getline(in,str);
//Do something with str without using loops
return in;
}
这里有很多循环(你不想使用goto
,不是吗?),但它们都隐藏在std::copy
和std::getline
答案 1 :(得分:0)
这只是一个玩具。
它包含一个基于Generator的方式来压缩文件(我觉得很容易写),还有一个半工作的适配器,可以将Generators转换为迭代器。
此上下文中的生成器是一个带有lambda的仿函数,并将该lambda传递给迭代的东西并返回true,或返回false。这是一个非常短的循环:
while( gen( [&]( std::string line ) {
// code using line goes here
} ) ); // <- notice that this is an empty while loop that does stuff
但是你不能使用它。 (这个设计的灵感来自python生成器,我真的觉得它比C ++迭代器更自然地解决了很多种问题,包括从文件中读取)。
adpator使用此生成器并使其成为迭代器,因此您可以将其传递给for_each
。
关键在于你的问题本身是无用的,所以不要做一些明显的事情(转到或直接在istream迭代器上使用for_each
),我建议搞乱一些迟钝和不同的东西。 :)
Line生成器非常简短:
struct LineGenerator {
LineGenerator(std::ostream& os_):os(&os_) {}
std::ostream* os;
template<typename F>
bool operator()(F&& func) {
std::string s;
bool bRet = std::getline( *os, s );
if (!bRet) return false;
std::forward<F>(func)(s);
return true;
}
};
另一方面,适配器非常混乱:(并且没有经过测试)
template<typename Generator>
struct generator_iterator {
typedef generator_iterator<Generator> my_type;
typedef typename std::decay< decltype( std::declval<Generator>()() ) >::type value_type;
Generator g;
bool bDone;
value_type val;
generator_iterator( Generator g_ ):g(g_), bDone(false) {
next();
}
generator_iterator(): bDone(true) {}
private:
void next() {
if (bDone) return;
bDone = g(val);
}
public:
generator_iterator& operator++() {
next();
return *this;
}
value_type operator*() {
return val;
}
const value_type operator*() const {
return val;
}
value_type* operator->() {
return &val;
}
value_type const* operator->() const {
return &val;
}
bool operator==( my_type const& o ) {
if (bDone != o.bDone) return false;
if (!bDone && !o.bDone) return true;
return false;
}
};
template<typename Generator>
generator_iterator<Generator> make_gen_it( Generator&& g ) {
return generator_iterator<Generator>( std::forward<Generator>(g) );
}
template<typename Generator>
generator_iterator<Generator> make_end_gen_it() {
return generator_iterator<Generator>();
}
我希望这有趣!