I want to print out the contents of a vector in C++, here is what I have:
#include
#include
#include
#include
overload operator<<:
template<typename OutStream, typename T>
OutStream& operator<< (OutStream& out, const vector<T>& v)
{
for (auto const& tmp : v)
out << tmp << " ";
out << endl;
return out;
}
Usage:
vector <int> test {1,2,3};
wcout << test; // or any output stream
This worked for me:
for (auto& i : name)
{
int r = 0;
for (int j = 0; j < name[r].size();j++)
{
std::cout << i[j];
}
r++;
std::cout << std::endl;
}
For people who want one-liners without loops:
I can't believe that noone has though of this, but perhaps it's because of the more C-like approach. Anyways, it is perfectly safe to do this without a loop, in a one-liner, ASSUMING that the std::vector<char>
is null-terminated:
std::vector<char> test { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\0' };
std::cout << test.data() << std::endl;
But I would wrap this in the ostream
operator, as @Zorawar suggested, just to be safe:
template <typename T>std::ostream& operator<< (std::ostream& out, std::vector<T>& v)
{
v.push_back('\0'); // safety-check!
out << v.data();
return out;
}
std::cout << test << std::endl; // will print 'Hello, world!'
We can achieve similar behaviour by using printf
instead:
fprintf(stdout, "%s\n", &test[0]); // will also print 'Hello, world!'
NOTE:
The overloaded ostream
operator needs to accept the vector as non-const. This might make the program insecure or introduce misusable code. Also, since null-character is appended, a reallocation of the std::vector
might occur. So using for-loops with iterators will likely be faster.
How about for_each
+ lambda expression:
#include <vector>
#include <algorithm>
...
std::vector<char> vec;
...
std::for_each(
vec.cbegin(),
vec.cend(),
[] (const char c) {std::cout << c << " ";}
);
...
Of course, a range-based for is the most elegant solution for this concrete task, but this one gives many other possibilities as well.
Explanation
The for_each
algorithm takes an input range and a callable object, calling this object on every element of the range. An input range is defined by two iterators. A callable object can be a function, a pointer to function, an object of a class which overloads () operator
or as in this case, a lambda expression. The parameter for this expression matches the type of the elements from vector.
The beauty of this implementation is the power you get from lambda expressions - you can use this approach for a lot more things than just printing the vector.
You can use an iterator:
std::vector<char> path;
// ...
for (std::vector<char>::const_iterator i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
If you want to modify the vector's contents in the for loop, then use iterator
rather than const_iterator
.
But there's lots more that can be said about this. If you just want an answer you can use, then you can stop here; otherwise, read on.
This is not another solution, but a supplement to the above iterator
solution. If you are using the C++11 standard (or later), then you can use the auto
keyword to help the readability:
for (auto i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
But the type of i
will be non-const (i.e., the compiler will use std::vector<char>::iterator
as the type of i
).
In this case, you might as well just use a typedef
, which also brings with it its own benefits (which I won't expound upon here):
typedef std::vector<char> Path; // 'Path' now a synonym for the vector
Path path;
// ...
for (Path::const_iterator i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
C++11 also introduced a type alias, which does the same job as a typedef and you may find more readable than using typedef:
using Path = std::vector<char>; // C++11 onwards only
Path path;
// ...
for (Path::const_iterator i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
You can, of course, use a integer type to record your position in the for
loop:
for(int i=0; i<path.size(); ++i)
std::cout << path[i] << ' ';
If you are going to do this, it's better to use the container's member types, if they are available and appropriate. std::vector
has a member type called size_type
for this job: it is the type returned by the size
method.
// Path typedef'd to std::vector<char>
for( Path::size_type i=0; i<path.size(); ++i)
std::cout << path[i] << ' ';
Why not just use this over the iterator
solution? For simple cases you might as well, but the point is that an iterator
is an object designed to do this job for more complicated objects where this solution is not going to be ideal.
See Jefffrey's solution. In C++11 (and later) you can use the new range-based for
loop, which looks like this:
for (auto i: path)
std::cout << i << ' ';
Since path
is a vector of items (explicitly std::vector<char>
), the object i
is of type of the item of the vector (i.e., explicitly, it is of type char
). The object i
has a value that is a copy of the actual item in the path
object. Thus, all changes to i
in the loop are not preserved in path
itself. Additionally, if you would like to enforce the fact that you don't want to be able to change the copied value of i
in the loop, you can force the type of i
to be const char
like this:
for (const auto i: path)
std::cout << i << ' ';
If you would like to modify the items in path
, you can use a reference:
for (auto& i: path)
std::cout << i << ' ';
and even if you don't want to modify path
, if the copying of objects is expensive you should use a const reference instead of copying by value:
for (const auto& i: path)
std::cout << i << ' ';
See Joshua's answer. You can use the STL algorithm std::copy
to copy the vector contents onto the output stream. This is an elegant solution if you are comfortable with it. Getting more familiar with STL algorithms should be encouraged, and they provide a lot of functionality that beginners may fall into reinventing themselves. Read Joshua's post for more info.
See Chris's answer, this is more a complement to the other answers since you will still need to implement one of the solutions above in the overloading. In his example he used a counter in a for
loop. For example, this is how you could quickly use Joshua's solution:
#include <iterator> // needed for std::ostram_iterator
template <typename T>
std::ostream& operator<< (std::ostream& out, const std::vector<T>& v) {
if ( !v.empty() ) {
out << '[';
std::copy (v.begin(), v.end(), std::ostream_iterator<T>(out, ", "));
out << "\b\b]";
}
return out;
}
Using any of the other solutions should be equally straightforward.
Any of the solutions presented here will work. It's up to you and the code on which one is the "best". Anything more detailed than this is probably best left for another question where the pros/cons can be properly evaluated; but as always user preference will always play a part: none of the solutions presented are wrong, but some will look nicer to each individual coder.
This is an expanded solution of an earlier one I posted. Since that post kept getting attention, I decided to expand on it and refer to the other excellent solutions that were posted here. My original post had a remark that mentioned that if you were intending on modifying your vector inside a for
loop then there are two methods provided by std::vector
to access elements: std::vector::operator[]
which does not do bounds checking, and std::vector::at
which does perform bounds checking. In other words, at
will throw if you try to access an element outside the vector and operator[]
wouldn't. I only added this comment, originally, for the sake of mentioning something that it might be useful to know of if anyone already didn't. And I see no difference now. Hence this addendum.
In C++11``
for (auto i = path.begin(); i != path.end(); ++i)
std::cout << *i << ' ';
for(int i=0; i<path.size(); ++i)
std::cout << path[i] << ' ';