代码之家  ›  专栏  ›  技术社区  ›  shuttle87 Bhargav Boda

二维STL向量C++的迭代

  •  10
  • shuttle87 Bhargav Boda  · 技术社区  · 15 年前

    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. 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.

    因此,我尝试的第一件事就是迭代并打印所有元素,但是这并不能编译:

    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!

    5 回复  |  直到 12 年前
        1
  •  15
  •   Sam Miller    15 年前

    你需要使用 const_iterator 如果 vector 是常量引用。此外,输出 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 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;
        }
    }
    
        2
  •  12
  •   Peter Alexander    15 年前

    二维 vector 被宣布 const 所以你需要使用 const_iterator 而不是 iterator .

    你也不应该重复引用 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; 
             } 
        } 
    
    } 
    
        3
  •  4
  •   Philipp    15 年前

    const 对象返回 const_iterators , so simply replace iterator 通过 const_iterator 到处都是。This also prevents unwanted modifications of the vectors.

    This is the combination of Sam's and Mathieu's suggestions:

    #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;
    }
    
        4
  •  3
  •   Petter    12 年前

    约翰,你建议使用lambda,但是如果C++ 11可用,我更喜欢。

    for (auto& row : movement) {
         for (auto& elem : row) {
            std::cout << elem;
         }
    }
    
        5
  •  0
  •   John    15 年前

    天啊, 任何东西 is better than that mess of 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));
    }
    

    或者,

    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),

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