简体   繁体   English

迭代二维STL向量c ++

[英]Iterating over 2-dimensional STL vector c++

I'm currently trying to print out a history of movements for players in a game I am working on. 我正在尝试打印我正在制作的游戏中玩家的动作历史。 At the end of each round every player has moved some amount in the positive or negative direction and this gets recorded as an int in the movement vector. 在每轮结束时,每个玩家都在正方向或负方向上移动了一些数量,并将其记录为运动矢量中的int。 Eventually I'm wanting to plot the directions moved vs time for each player but I'm having trouble extracting the data out of the 2d vector. 最终我想要为每个玩家绘制移动方向与时间的关系,但是我无法从2d向量中提取数据。

So the first thing I tried was to just iterate and print all the elements, however this doesn't compile: 所以我尝试的第一件事就是迭代并打印所有元素,但是这不能编译:

void output_movement(const std::vector< std::vector<int> > & movement){

    std::vector< std::vector<int> >::iterator row;
    std::vector<int>::iterator col;
    for (row = movement.begin(); row != movement.end(); ++row) {
         for (col = row->begin(); col != row->end(); ++col) {
            std::cout << **col;
         }
    }

}

The compiler gives this error message which I don't really understand: 编译器提供此错误消息,我不太明白:

hg_competition.cpp:45: error: no match for ‘operator=’ in ‘row = ((const std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >*)money_movement)->std::vector<_Tp, _Alloc>::begin [with _Tp = std::vector<int, std::allocator<int> >, _Alloc = std::allocator<std::vector<int, std::allocator<int> > >]()’
/usr/include/c++/4.4/bits/stl_iterator.h:669: note: candidates are: __gnu_cxx::__normal_iterator<std::vector<int, std::allocator<int> >*, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > >& __gnu_cxx::__normal_iterator<std::vector<int, std::allocator<int> >*, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > >::operator=(const __gnu_cxx::__normal_iterator<std::vector<int, std::allocator<int> >*, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > >&)

Any help is greatly appreciated! 任何帮助是极大的赞赏!

You need to use a const_iterator if the vector is a const reference. 如果vector是const引用,则需要使用const_iterator Also, to output col you only need to dereference it once. 此外,要输出col您只需要取消引用一次。

void output_movement(const std::vector< std::vector<int> > & movement){

    std::vector< std::vector<int> >::const_iterator row;
    std::vector<int>::const_iterator col;
    for (row = movement.begin(); row != movement.end(); ++row) {
         for (col = row->begin(); col != row->end(); ++col) {
            std::cout << *col;
         }
    }
}

Edit: using typedefs will make your code more readable 编辑:使用typedef将使您的代码更具可读性

typedef std::vector<int> Vector;
typedef std::vector<Vector> DoubleVector;

void output_movement(
    const DoubleVector& movement
)
{
    for (DoubleVector::const_iterator row = movement.begin(); row != movement.end(); ++row) {
         for (Vector::const_iterator col = row->begin(); col != row->end(); ++col) {
            std::cout << *col;
         }
         std::cout << std::endl;
    }
}

The 2D vector is declared const , so you need to use const_iterator instead of iterator . 2D vector声明为const ,因此您需要使用const_iterator而不是iterator

You also shouldn't doubly dereference col . 你也不应该加倍取消引用col It is an iterator, so you only need to dereference once. 它是一个迭代器,所以你只需要解除引用一次。

void output_movement(const std::vector< std::vector<int> > & movement){ 

    std::vector< std::vector<int> >::const_iterator row; 
    std::vector<int>::const_iterator col; 
    for (row = movement.begin(); row != movement.end(); ++row) { 
         for (col = row->begin(); col != row->end(); ++col) { 
            std::cout << *col; 
         } 
    } 

} 

const objects return const_iterators , so simply replace iterator by const_iterator everywhere. const对象返回const_iterators ,因此只需用const_iterator替换iterator This also prevents unwanted modifications of the vectors. 这也可以防止不需要的载体修饰。

This is the combination of Sam's and Mathieu's suggestions: 这是Sam和Mathieu的建议的结合:

#include <ostream>
#include <vector>

typedef std::vector<int> Vector;
typedef std::vector<Vector> DoubleVector;


template<typename Char, typename Traits>
std::basic_ostream<Char, Traits>&
operator<<(std::basic_ostream<Char, Traits>& stream,
           const DoubleVector& movement) {
    for (DoubleVector::const_iterator row = movement.begin(); row != movement.end(); ++row) {
         for (Vector::const_iterator col = row->begin(); col != row->end(); ++col) {
            stream << *col;
         }
    }
return stream;
}

John, you suggested using lambdas, but if C++11 is available, I'd prefer 约翰,你建议使用lambdas,但如果C ++ 11可用,我更喜欢

for (auto& row : movement) {
     for (auto& elem : row) {
        std::cout << elem;
     }
}

Omg, anything is better than that mess of for loops. 妈呀, 什么是比那些乱七八糟更好for循环。 Here some alternatives. 这里有一些选择。 Choose whichever you like. 选择你喜欢的任何一个。

typedef vector<int> VI;
typedef vector<VI> VVI;


namespace std {
    ostream& operator<<(ostream& o, const VI& v) {
        copy (v.begin(), v.end(), ostream_iterator<int>(cout));
        return o;
    }
}
void output_movement (const VVI& m) {
    copy (m.begin (), m.end (), ostream_iterator<const VI&>(cout));
}

or, 要么,

void output_movement (const VVI & m) {
    for_each (m.begin(), m.end(), [](const VI& v){ 
                for_each (v.begin(), v.end(), [](int i){ cout << i; });
                });
}

or, my personal preference (boost/foreach.hpp), 或者,我个人的偏好(boost / foreach.hpp),

void output_movement (const VVI & m) {
    foreach (const VI& v, m)
        foreach (int i, v)
            cout << i;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM