C++ reading from file using std - c++

I'm trying to read from file, and I know how to do that:
#include <iostream>
#include <iterator>
#include <fstream>
#include <vector>
using namespace std;
int main()
{
std::string filename = "data.txt";
std::ifstream from(filename);
std::vector<int> values((std::istream_iterator<int>(from)), std::istream_iterator<int>());
return 0;
}
My question is how to do the same thing in functional way:
int fromfile(std::string filename, std::vector<int> &values)
{
...
return 0;
}
The native way doesn't work:
int fromfile(std::string filename, std::vector<int> &values)
{
std::ifstream from(filename);
values((std::istream_iterator<int>(from)), std::istream_iterator<int>());
return 0;
}

Your functional way doesn't work because you're trying to use a constructor on an already constructed object - so it looks like you're trying to invoke operator() on your vector, which does not exist. However, vector does have an assign member function that does the same thing, without the need for extra parens:
int fromfile(std::string filename, std::vector<int> &values)
{
std::ifstream from(filename);
values.assign(std::istream_iterator<int>(from), std::istream_iterator<int>());
return 0;
}
Although the real functional way probably looks like this (C++11) - use the function to return the vector:
std::vector<int> fromfile(std::string filename)
{
std::ifstream from(filename)
return {std::istream_iterator<int>(from), std::istream_iterator<int>{}};
}
As is having an int return is somewhat useless if you just have return 0...

Notwithstanding the answer Barry has given to you, the other way to do this with algorithm is to call std::copy:
std::copy(std::istream_iterator<int>(from), std::istream_iterator<int>(),
std::back_inserter(values));

Related

How do I display the contents of a std::vector of my own datatype and display the name on the console using std::copy?

I would like to display the contents of the std::vector<User> using std::copy in a similar way to how I've achieved it through std::for_each in the code below.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
class User {
private:
std::string m_sName;
public:
User(std::string sName):m_sName(sName) {}
std::string GetName()const {
return m_sName;
}
};
int main()
{
std::vector<User> vectNames;
vectNames.emplace_back("Jack");
vectNames.emplace_back("George");
vectNames.emplace_back("Jose");
//How can I get std::copy to do what the std::for_each is doing?
std::copy(vectNames.begin(), vectNames.end(), std::ostream_iterator<User>(std::cout, "\n"));
//The following line is what I really would like std::copy to do.
std::for_each(vectNames.begin(), vectNames.end(), [](const User &user) {std::cout << user.GetName() << "\n"; });
}
You can simply overload the ostream operator:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
class User {
private:
std::string m_sName;
public:
User(std::string sName):m_sName(sName) {}
std::string GetName()const {
return m_sName;
}
void print(std::ostream& where) const
{ where << m_sName; }
};
/// Overloaded ostream operator
std::ostream& operator<< (std::ostream& out, const User& user)
{
user.print(out);
return out;
}
int main()
{
std::vector<User> vectNames;
vectNames.emplace_back("Jack");
vectNames.emplace_back("George");
vectNames.emplace_back("Jose");
std::copy(vectNames.begin(), vectNames.end(), std::ostream_iterator<User>(std::cout, "\n"));
}
In general I always have an overloaded ostream as part of classes that store and output information.
Because of your comment I am a new programmer and am experimenting with different ideas, I'm posting this answer as an alternative approach which also shows some algorithm that you might enthusiastic about.
I think that std::copy isn't the right tool if what you want to do is both
calling a member function on the objects in a collection, and only after that
copying/printing them to screen
One, and maybe the best, approach is the one in the atru's answer, which basically solves only point 2 with std::copy (and this is something you already knew how to do it, based on your question), and point 1 by overloading <<, which makes the trick.
The alternative I propose is based on the idea that "calling a member function on every object of a collection" is actually a transform operation of that collection. std::transform, however, just like std::copy acts on iterators, not on ranges, so they cannot be easily composed with one another.
Here comes Boost, with boost::copy and boost::adaptors::transformed which allow you to do this:
boost::copy(
vectNames | transformed([](auto const& x){ return x.GetName(); }),
std::ostream_iterator<std::string>(std::cout, "\n")
);
where vectNames is "piped into" transformed, which applies the lambda on every element of the collection, resulting in a new temporary collection, which is the argument to boost::copy. If you were to use std::copy, you would have to store the temporary somewhere, e.g. in temp, before passing to std::copy its iterators temp.begin() and temp.end().
The full example is below. I hope it will give you some insight in different, more functional, approaches.
#include <functional>
#include <iostream>
#include <vector>
#include <string>
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/copy.hpp>
class User {
private:
std::string m_sName;
public:
User(std::string sName):m_sName(sName) {}
std::string GetName()const {
return m_sName;
}
};
int main()
{
std::vector<User> vectNames;
vectNames.emplace_back("Jack");
vectNames.emplace_back("George");
vectNames.emplace_back("Jose");
using boost::adaptors::transformed;
boost::copy(
vectNames | transformed([](auto const& x){ return x.GetName(); }),
std::ostream_iterator<std::string>(std::cout, "\n")
);
}

Extracting a class member from a vector of class instances (as a new vector)

I have a class/structure as follows:
struct MyStruct {
std::string member_one;
std::string member_two;
};
I create a vector of MyStruct, std::vector<MyStruct> of some length N with the members set to custom values:
std::vector<MyStruct> my_struct_vect(10);
// initialize class instances
Now I want to extract the first member memberOne into a new vector. I can do so as follows:
std::vector<std::string> member_one_vect(my_struct_vect.size());
for (size_t i = 0; i < my_struct_vect.size(); ++i) {
member_one_vect[i] = my_struct_vect[i].member_one;
}
My question is, is there a quicker/more elegant/cleaner way of doing this without having to write the custom loop every time? In Python for example, I could do this quite easily with comprehensions. I'm not expecting something similar in C++, but am wondering if there is some way to simplify this nonetheless.
Update
Thanks to the great responses on using std::transform and boost::adaptors::transformed. These are very useful, but in order to be compact it's worth noting they rely on lambda functions which were introduced in C++11 (it's possible to use them without, but this requires defining a separate helper function).
So for bonus points, are there any ways to do this in a compact way in C++03?
You could use std::transform:
#include <algorithm> // Necessary for std::transform()
// ...
std::vector<std::string> member_one_vect(my_struct_vect.size());
std::transform(
my_struct_vect.begin(), my_struct_vect.end(), member_one_vect.begin(),
[] (MyStruct const& ms)
{
return ms.member_one;
});
Here is how the full code would look like:
#include <vector>
#include <string>
#include <algorithm>
struct MyStruct {
std::string member_one;
std::string member_two;
};
int main()
{
std::vector<MyStruct> my_struct_vect(10);
// Initialize my_struct_vect...
std::vector<std::string> member_one_vect(my_struct_vect.size());
std::transform(
my_struct_vect.begin(), my_struct_vect.end(), member_one_vect.begin(),
[] (MyStruct const& ms)
{
return ms.member_one;
});
// Do something with member_one_vect...
}
Here is a live example.
You can use algorithms.
std::vector<std::string> member_one_vect(my_struct_vect.size());
std::transform(my_struct_vect.begin(), my_struct_vect.end(),
member_one_vect.begin(),
[](const MyStruct& m) { return m.member_one; });
Also, you can use boost::adaptors::transformed.
#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/copy.hpp>
std::vector<std::string> member_one_vect(my_struct_vect.size());
std::function<std::string(const MyStruct&)> transform =
[] (const MyStruct& m) { return m.member_one; };
boost::copy(my_struct_vect | boost::adaptors::transformed(transform),
member_one_vect.begin());

find strings in vector with equal_to function object

I have following code:
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
#include <vector>
#include <functional>
using namespace std;
typedef istream_iterator<string> is_it;
typedef vector<string>::iterator v_str_it;
int main()
{
int i = 4;
ifstream ifstr("1.txt");
is_it ifstrm(ifstr);
is_it eof;
vector<string> v_str(ifstrm, eof);
v_str_it vsit = v_str.begin();
while( (vsit = find_if(vsit, v_str.end(),
bind2nd(equal_to<string>(), i ))) != v_str.end())
{
cout << *vsit << endl;
++vsit;
}
return 0;
}
As far as I understand in find_if(vsit, v_str.end(), bind2nd(equal_to<string>(), i ) i should use const char like "sometext" instead of int i. But how can i find words with length equal to 4 e.g. ? I'm confused and need some advice.
find_if will only return the first item in the sequence that satisfies the predicate.
For this you really want a lambda and if you are using C++11. This will look something like:
[](std::string const& x) { return x.size() == i; }
(Not sure of the exact syntax).
To create a "functor" which is the simplest here you might do:
struct CompareStringLength
{
int len_;
explicit CompareStringLength( int len ) : len_(len)
{
}
bool operator()(std::string const& str ) const
{
return str.size() == len_;
}
};
Within your vector you would now use std::find_if( v.begin(), v.end(), CompareStringLength(i) );
to get the first element. To find all of them there is no std::copy_if to copy them into another vector so you'd actually have to create a different predicate that returns the opposite and use remove_copy_if which does exist or write your own copy_if algorithm.

C++: Wrapping vector<char> with istream

I want to wrap a vector<char> with std::istream (so reading the vector would be done through the istream interface)
What's the way to do it?
You'd define a streambuf subclass wrapping the vector, and pass an instance of that to the istream constructor.
If the data does not change after construction, it is sufficient to set up the data pointers using streambuf::setg(); the default implementation for the other members does the right thing:
template<typename CharT, typename TraitsT = std::char_traits<CharT> >
class vectorwrapbuf : public std::basic_streambuf<CharT, TraitsT> {
public:
vectorwrapbuf(std::vector<CharT> &vec) {
setg(vec.data(), vec.data(), vec.data() + vec.size());
}
};
std::vector<char> data;
// ...
vectorwrapbuf<char> databuf(data)
std::istream is(&databuf);
If you need anything more advanced than that, override the streambuf::underflow method.
using Boost:
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/array.hpp>
using namespace boost::iostreams;
basic_array_source<char> input_source(&my_vector[0], my_vector.size());
stream<basic_array_source<char> > input_stream(input_source);
or even simpler:
#include <boost/interprocess/streams/bufferstream.hpp>
using namespace boost::interprocess;
bufferstream input_stream(&my_vector[0], my_vector.size());
Adapting the answer from Get an istream from a char* and assuming this is what you're trying to do:
// Forward declarations
std::vector<char> my_create_buffer();
void my_consume_buffer( std::istream & is );
// What you want to be able to write
std::vector<char> buffer = my_create_buffer();
my_consume_buffer( wrap_vector_as_istream(buffer) );
You can then create the wrap_vector_as_istream like this (untested though) :
#include <iostream>
#include <istream>
#include <streambuf>
#include <string>
struct wrap_vector_as_istream : std::streambuf
{
wrap_vector_as_istream(std::vector<char> & vec ) {
this->setg(&vec[0], &vec[0], &vec[0]+vec.size() );
}
};
One thing to be aware of though. The object you've created contains pointers into the vectors memory. So if you add or remove values to the vector while having this wrapper floating around, then you're heading for a crash.
(Oh and if you up vote me, please up vote the post I've adapted this from.)
You'd could get away with simply building a class that implements the >> operator like a stream, something like this:
template<class _ITy>
class RangeStreamLite
{
private:
_ITy Begin;
_ITy End;
_ITy Next;
public:
RangeStreamLite(_ITy begin, _ITy end) :
Begin(begin),
End(end),
Next(begin)
{
// Do nothing.
}
template<class _OTy>
RangeStreamLite& operator>>(_OTy& out)
{
out = *Next;
++Next;
return *this;
}
void reset()
{
Next = Begin;
}
};
This is a 'quick and dirty' solution, a 'stream lite', it isn't really a stream in the proper sense but it works when all you require is a superficial stream-like device. To properly create a custom stream is a little more complicated, and would require you to inherit from std::streambuf and implement the necessary features. Here are a few links worth a look:
Inheriting std::istream or equivalent
Deriving the C++ Stream Buffer
If you are fine with swapping your vector<char> you can use Boost Interprocess' vectorstream. Example:
#include <boost/interprocess/streams/vectorstream.hpp>
#include <vector>
#include <string>
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
static const char inp[] = "123 45 666";
vector<char> v(inp, inp + sizeof inp - 1);
using ivectorstream =
boost::interprocess::basic_ivectorstream<std::vector<char>>;
ivectorstream is;
is.swap_vector(v);
while (!is.eof()) {
int i = 0;
is >> i;
cout << i << '\n';
}
is.swap_vector(v);
cout << string(v.begin(), v.end()) << '\n';
return 0;
}
Alternatively, if you can't or don't want to mutate your vector<char>, you can use Boost Interprocess' bufferstream. With bufferstream, you don't have to swap your vector into it. Example:
#include <boost/interprocess/streams/bufferstream.hpp>
#include <vector>
#include <string>
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
static const char inp[] = "123 45 666";
vector<char> v(inp, inp + sizeof inp - 1);
boost::interprocess::ibufferstream is(v.data(), v.size());
while (!is.eof()) {
int i = 0;
is >> i;
cout << i << '\n';
}
return 0;
}
You will have to write a custom stream-implementation that inherits from istream. This can easily be done using Boost.Iostreams - all you'd have to do is implement a simple Source.

How do I use for_each to output to cout?

Is there a more straight-forward way to do this?
for_each(v_Numbers.begin(), v_Numbers.end(), bind1st(operator<<, cout));
Without an explicit for loop, if possible.
EDIT:
How to do this for std::cin with a std::vector if possible? (How to read n elements only)?
You could achieve this using std::copy into a std::ostream_iterator:
std::vector<int> v_Numbers; // suppose this is the type
// put numbers in
std::copy(v_Numbers.begin(), v_Numbers.end(),
std::ostream_iterator<int>(std::cout));
It would be even nicer if you add some suffix:
std::copy(v_Numbers.begin(), v_Numbers.end(),
std::ostream_iterator<int>(std::cout, "\n"));
This assumes that your container is a vector<int>, so you will have to replace that part with the appropriate type.
Edit regarding reading input:
Conversely, you can copy from a range of std::istream_iterator into a vector using std::back_inserter:
std::vector<int> v_Numbers;
std::copy(std::istream_iterator<int>(std::cin), std::istream_iterator<int>(),
std::back_inserter(v_Numbers));
If you want to read n elements only, look at this question.
Another option — Boost.Lambda.
for_each(v.begin(), v.end(), cout << boost::lambda::_1);
Yep, but you must use std::copy algorithm:
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::vector<int> a;
// fill a...
std::copy(a.begin(), a.end(), std::ostream_iterator<int>(std::cout));
}
yup, using lambda expression (C++ 11) we can inline printing of each element of a STL container to cout.
#include <iostream> // cout
#include <vector> // vector
#include <algorithm> // for_each
#include <iterator> // istream_iterator
using namespace std;
int main()
{
std::vector<int> v(10,2);
std::for_each(v.begin(), v.end(), [](int i)->void {std::cout << i <<endl;});
return 0;
}
For reading "n" values from cin to vector,
int main()
{
std::vector<int> v;
int elementsToRead;
cin>>elementsToRead; // Number of elements to copy
// Reading from istream
std::istream_iterator<int> ii2(std::cin);
std::copy_n(ii2, elementsToRead, std::back_inserter(v));
// printing updated vector
std::for_each(v.begin(), v.end(), [](int i)->void {cout << i <<endl;});
return 0;
}
(or) by using Lambda expression
std::for_each(std::istream_iterator<int>(cin),std::istream_iterator<int>(),[&v](int i)->void { v.push_back(i);});
To know more about Lambda expression # What is a lambda expression in C++11?
Not always appropriate in corporate code, but for the sake of enumerating options - if you really find other for_each / std::copy etc. solutions too verbose, you could write:
std::ostream& operator(std::ostream& os, const std::vector<My_Type>& v)
{
// pick one of the other implementations for here...
std::copy(std::istream_iterator<My_Type>(os), std::istream_iterator<My_Type>(),
std::back_inserter(v_Numbers));
}
It's much nicer if you're well-mannered (;-p) enough to only overload your specific instantiation of vector (which requires My_Type be more than a typedef to say int, though it's not hard to create a templated class to create new types wrapping an arbitrary type). Otherwise, if someone else does the same elsewhere in your translation unit, the streaming could become ambiguous.
I know the copy with the iterator is the optimal solution, but just to answer with for_each.
You could do:
#include <vector>
#include <algorithm>
#include <locale>
int main() {
using namespace std;
locale::global(locale(""));
wcout::imbue(locale());
vector<int> vec{1000,2000,3000,4000,5000};
for_each(vec.begin(), vec.end(), [](auto &x){wcout << x << endl;});
return 0;
}
But, for me, it's REALLY much more readable the simple for ...
#include <vector>
#include <locale>
int main() {
using namespace std;
locale::global(locale(""));
wcout::imbue(locale());
vector<int> vec{1000,2000,3000,4000,5000};
for(auto &v: vec) {
wcout << v << endl;
}
return 0;
}