2010-06-28 74 views
10

Tôi hiện đang cố gắng in ra một lịch sử chuyển động cho người chơi trong trò chơi tôi đang làm việc. Vào cuối mỗi vòng mỗi người chơi đã di chuyển một số lượng theo hướng tích cực hoặc tiêu cực và điều này được ghi lại như là một int trong vector chuyển động. Cuối cùng tôi muốn âm mưu các hướng di chuyển vs thời gian cho mỗi người chơi nhưng tôi đang gặp khó khăn khi trích xuất dữ liệu ra khỏi vector 2d.Lặp lại vector STL 2 chiều C++

Vì vậy, điều đầu tiên tôi đã cố gắng là để chỉ lặp và in tất cả các yếu tố, tuy nhiên điều này không biên dịch:

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

} 

Trình biên dịch cho thông điệp này lỗi mà tôi không thực sự hiểu:

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

Bất kỳ trợ giúp nào được đánh giá cao!

Trả lời

14

Bạn cần sử dụng const_iterator nếu tham chiếu vector là tham chiếu const. Ngoài ra, để xuất col bạn chỉ cần dereference nó một lần.

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

Chỉnh sửa: sử dụng typedefs sẽ làm cho mã của bạn dễ đọc hơn

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; 
    } 
} 
+1

Tôi cho rằng nếu bạn định viết lại mã e, nó có thể là đáng giá để cũng đặt đúng 'hàng' và' col' khai báo trong vòng lặp 'for' cho phạm vi thích hợp. –

+0

Ngoài ra nó có lẽ sẽ có thêm một chút C++ - giống như nếu 'output_movement' được gọi là' operator << '. – Philipp

+0

@Matthieu Tôi đã cập nhật câu trả lời của mình để bao gồm đề xuất của bạn. –

4

const đối tượng trả về const_iterators, vì vậy, chỉ cần thay thế iterator bởi const_iterator ở mọi nơi. Điều này cũng ngăn ngừa những sửa đổi không mong muốn của các vectơ.

Đây là sự kết hợp của lời đề nghị Mathieu của Sam và:

#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; 
} 
12

2D vector được khai báo const, vì vậy bạn cần phải sử dụng const_iterator thay vì iterator.

Bạn cũng không nên gấp đôi dereference col. Nó là một iterator, vì vậy bạn chỉ cần dereference một lần.

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

} 
0

Omg, bất cứ điều gì là tốt hơn so với mớ hỗn độn của for vòng. Dưới đây là một số lựa chọn thay thế. Chọn bất cứ điều gì bạn thích.

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)); 
} 

hay,

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; }); 
       }); 
} 

hay, sở thích cá nhân của tôi (tăng/foreach.hpp),

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

John, bạn đề nghị sử dụng lambdas, nhưng nếu C++ 11 là có sẵn, tôi muốn

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

+1 cho các vòng lặp dựa trên phạm vi sạch - mặc dù không cần '&', có ở đó không? –

+0

Cơ đốc giáo: Vâng, có! Nếu không, mỗi hàng sẽ được sao chép và lặp lại. Tham chiếu thứ hai không quan trọng. – Petter

+0

Ben: Ồ, điều đó: vâng, chắc chắn. Nhưng sau đó bạn cũng có thể viết 'const auto &' để chắc chắn rằng bạn không vô tình thay đổi 'row's hoặc' elem'ents của bạn, không? –

Các vấn đề liên quan