HiveBrain v1.2.0
Get Started
← Back to all entries
snippetcppCritical

How do I print out the contents of a vector?

Submitted by: @import:stackoverflow-api··
0
Viewed 0 times
howcontentstheprintvectorout

Problem

How do I print out the contents of a std::vector to the screen?

A solution that implements the following operator<< would be nice as well:

template
std::ostream & operator & x)
{
  // ... What can I write here?
}


Here is what I have so far, without a separate function:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

int main()
{
    ifstream file("maze.txt");
    if (file) {
        vector vec(istreambuf_iterator(file), (istreambuf_iterator()));
        vector path;
        int x = 17;
        char entrance = vec.at(16);
        char firstsquare = vec.at(x);
        if (entrance == 'S') { 
            path.push_back(entrance); 
        }
        for (x = 17; isalpha(firstsquare); x++) {
            path.push_back(firstsquare);
        }
        for (int i = 0; i < path.size(); i++) {
            cout << path[i] << " ";
        }
        cout << endl;
        return 0;
    }
}

Solution

If you have a C++11 compiler, I would suggest using a range-based for-loop (see below); or else use an iterator. But you have several options, all of which I will explain in what follows.
Range-based for-loop (C++11)

In C++11 (and later) you can use the new range-based for-loop, which looks like this:

std::vector path;
// ...
for (char i: path)
    std::cout << i << ' ';


The type char in the for-loop statement should be the type of the elements of the vector path and not an integer indexing type. In other words, since path is of type std::vector, the type that should appear in the range-based for-loop is char. However, you will likely often see the explicit type replaced with the auto placeholder type:

for (auto i: path)
    std::cout << i << ' ';


Regardless of whether you use the explicit type or the auto keyword, 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:

std::vector path{'a', 'b', 'c'};

for (auto i: path) {
    i = '_'; // 'i' is a copy of the element in 'path', so although
             // we can change 'i' here perfectly fine, the elements
             // of 'path' have not changed
    std::cout << i << ' '; // will print: "_ _ _"
}

for (auto i: path) {
    std::cout << i << ' '; // will print: "a b c"
}


If you would like to proscribe being able to change this copied value of i in the for-loop as well, you can force the type of i to be const char like this:

for (const auto i: path) {
    i = '_'; // this will now produce a compiler error
    std::cout << i << ' ';
}


If you would like to modify the items in path so that those changes persist in path outside of the for-loop, then you can use a reference like so:

for (auto& i: path) {
    i = '_'; // changes to 'i' will now also change the
             // element in 'path' itself to that value
    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 << ' ';


Iterators

Before C++11 the canonical solution would have been to use an iterator, and that is still perfectly acceptable. They are used as follows:

std::vector path;
// ...
for (std::vector::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.
Supplement: typedef / type alias (C++11) / auto (C++11)

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 << ' ';


Here the type of i will be non-const (i.e., the compiler will use std::vector::iterator as the type of i). This is because we called the begin method, so the compiler deduced the type for i from that. If we call the cbegin method instead ("c" for const), then i will be a std::vector::const_iterator:

for (auto i = path.cbegin(); i != path.cend(); ++i) {
    *i = '_'; // will produce a compiler error
    std::cout << *i << ' ';
}


If you're not comfortable with the compiler deducing types, then in C++11 you can use a type alias to avoid having to type the vector out all the time (a good habit to get into):

using Path = std::vector; // C++11 onwards only
Path path; // 'Path' is an alias for std::vector
// ...
for (Path::const_iterator i = path.begin(); i != path.end(); ++i)
    std::cout << *i << ' ';


If you do not have access to a C++11 compiler (or don't like the type alias syntax for whatever reason), then you can use the more traditional typedef:

typedef std::vector Path; // 'Path' now a synonym for std::vector
Path path;
// ...
for (Path::const_iterator i = path.begin(); i != path.end(); ++i)
    std::cout << *i << ' ';


Side note:

At this point, you may or may not have come across iterators before, and you may or may not have heard that iterators are what you are "supposed" to use, and may be wondering why. The answer is not easy to appreciate, but, in brief, the idea is that iterators are an abstraction that shield you from the details of the operation.

It is convenient to have an object (the iterator) that does the operation you want (like sequential access) rather than you writing the details yourself (the "details" being the code that does the actual accessing of the elements of the vector). You should notice that in the for-loop you are only ever asking the iterator to return you a value (*i, where i is the iterator) -- you are never interacting with path directly itself. The logic goes like this: you create an iterator and give it the object you want to loop over (`ite

Code Snippets

std::vector<char> path;
// ...
for (char i: path)
    std::cout << i << ' ';
for (auto i: path)
    std::cout << i << ' ';
std::vector<char> path{'a', 'b', 'c'};

for (auto i: path) {
    i = '_'; // 'i' is a copy of the element in 'path', so although
             // we can change 'i' here perfectly fine, the elements
             // of 'path' have not changed
    std::cout << i << ' '; // will print: "_ _ _"
}

for (auto i: path) {
    std::cout << i << ' '; // will print: "a b c"
}
for (const auto i: path) {
    i = '_'; // this will now produce a compiler error
    std::cout << i << ' ';
}
for (auto& i: path) {
    i = '_'; // changes to 'i' will now also change the
             // element in 'path' itself to that value
    std::cout << i << ' ';
}

Context

Stack Overflow Q#10750057, score: 556

Revisions (0)

No revisions yet.