Re: copying from an input stream into a string
glen stark wrote:
Hi everyone.
I'm in the position that I have an input stream, start_pos, and end_pos,
and I'd like to copy the contents of the stream from start_pos to end_pos
into a string.
I can think of a number of ways to do this, but I don't like any of
them. What do you think is the most elegant way to do this?
Thanks,
Try this:
http://www.linux-projects.org/listing/cpp_solutions/20.5/main.cpp
Below is the code:
#include <string>
#include <iterator>
#include <iostream>
#include <algorithm>
#include <vector>
namespace mystd {
template<class Cont> class back_insert_iterator;
/*
* Base class for all the back_insert_iterator's. It requires
* a back_insert_iterator class as template argument.
*/
template<class Cont, class Derived = back_insert_iterator<Cont> >
class back_insert_iterator_base : public
std::iterator<std::output_iterator_tag, void, void, void, void> {
protected:
Cont& container;
explicit back_insert_iterator_base(Cont& c) : container(c) { }
public:
typedef Cont container_type;
Derived& operator=(typename container_type::const_reference v) {
container.push_back(v);
return *(static_cast<Derived*> (this));
}
Derived& operator++() {
return *(static_cast<Derived*> (this));
}
Derived& operator++(int) {
return *(static_cast<Derived*> (this));
}
Derived& operator*() {
return *(static_cast<Derived*> (this));
}
};
/*
* Generic back_insert_iterator for any container
*/
template<class Cont>
class back_insert_iterator : public back_insert_iterator_base<Cont> {
public:
explicit back_insert_iterator(Cont& c) :
back_insert_iterator_base<Cont> (c) { }
using back_insert_iterator_base<Cont>::operator =;
};
/*
* Specialized class for a basic_string's:
* this class adds one more operator=() implementing string concatenation
*/
template<class Ch, class Tr, class A>
class back_insert_iterator<std::basic_string<Ch, Tr, A> > : public
back_insert_iterator_base<std::basic_string<Ch, Tr, A> > {
public:
explicit back_insert_iterator(std::basic_string<Ch, Tr, A>& c) :
back_insert_iterator_base<std::basic_string<Ch, Tr, A> > (c) { }
using back_insert_iterator_base<std::basic_string<Ch, Tr, A>
::operator =;
back_insert_iterator& operator=(const std::basic_string<Ch, Tr, A> &
s) {
back_insert_iterator_base<std::basic_string<Ch, Tr, A>
::container.append(s);
return *this;
}
};
/*
* This is convenience function. It returns a back insert iterator
* for a container without requiring us to specify any template argument.
*/
template <class Cont> back_insert_iterator<Cont> back_inserter(Cont& c) {
return back_insert_iterator<Cont > (c);
}
}
int main(int argc, char** argv) {
// Two examples
using namespace std;
typedef basic_string<char> String;
vector<String > v;
copy(std::istream_iterator<String > (std::cin),
std::istream_iterator<String > (), mystd::back_inserter(v));
String s;
copy(v.begin(), v.end(), mystd::back_inserter(s));
cout << s;
return 0;
}