3

I want to use an iterator for a 2D array but I don't know how.

My purpose is to access the columns and not the rows.

I found out that to access the rows I can use this auto it=begin(arr); but I think it isn't the right way to do it, however it seems to work.

#include <iostream>
#include <iterator>

using namespace std;

int main(){
  int arr[3][3];
  for (int i=0;i!=3;i++)
    for (int j=0;j!=3;j++)
      arr[i][j]=rand()%9;

  for (int i=0;i!=3;i++)
    for (int j=0;j!=3;j++){
      cout<<arr[i][j]<<' ';
      if (j==2)
        cout<<'\n';
    }

  auto it=begin(arr);
  cout<<**it<<endl;

Is this correct?

Thanks in advance :D

anastaciu
  • 23,467
  • 7
  • 28
  • 53
  • Is there a reason you need an iterator? 2d arrays are "row based" so getting an iterator to the column will require writing a custom class to handle that. – NathanOliver Apr 28 '20 at 13:47
  • @NathanOliver i need an iterator to access the `arr[i+1][it++]` int after finding the max number in each column.. and that one is just a sample. – Seif Boukhatem Apr 28 '20 at 13:53

3 Answers3

1

If you want to iterate over a column, you can do something like:

for(auto it = std::begin(arr); it != std::end(arr); it++)
    cout << **it;

This will print the first column.

To iterate over the array in column order you would need somenthing like:

for (size_t i = 0; i < std::size(arr); i++) {
    for (auto it = std::begin(arr); it != std::end(arr); it++) {
        cout << *(*it + i) << " ";
    }
    cout << endl;
}

This will print the array in column order. Note that std::size is only available after C++17, you may need to use std=c++17 compiler flag.

Live demo

Two side notes:

  • You are missing a seed for your random engine:
  #include <time.h>
  //...
  srand(time(0)); //seed
  //...
anastaciu
  • 23,467
  • 7
  • 28
  • 53
  • This code has undefined behavior. You cannot legally iterate a 2d array with a pointer to the first element. That pointer only belongs to the first row and going to another row violates the pointer addition rules. Also note your accessing the entire array, not a column. – NathanOliver Apr 28 '20 at 13:57
  • The pointer addition rule is here: https://timsong-cpp.github.io/cppwp/expr.add#4.2 – NathanOliver Apr 28 '20 at 14:06
  • Okay. The code is still wrong though as now your print the second row, not column: https://wandbox.org/permlink/mN1kQ9a3K1Fn3BVT – NathanOliver Apr 28 '20 at 14:17
  • @NathanOliver, my take fro the OP is that he wants to access members inside the array with an iterator given by std::begin, not print the array in column order, so my answer has what he needs – anastaciu Apr 28 '20 at 14:36
  • Not sure how *my purpose is to access the columns and not the rows.* makes you think he needs a row but you are entitled to your opinion. – NathanOliver Apr 28 '20 at 14:38
  • @NathanOliver, I changed my answer entirely, posting an example of a column order access. – anastaciu Apr 28 '20 at 15:33
  • error: use of undeclared identifier ' error: no matching function for call to 'begin' error: no matching function for call to ‘begin(char [n][n])’ error: no matching function for call to 'end' error: no matching function for call to ‘end(char [n][n])’ i copied your your second loop mechanism and this is what i got. http://cpp.sh/47dyb <--- here is the code i copied from your online into another compiler. i get the same error using cpp.sh – NaturalDemon Aug 15 '20 at 17:16
  • 1
    @NaturalDemon `std::size` is only available with C++17 or later. – anastaciu Aug 15 '20 at 18:44
  • 1
    @anastaciu i found out later, thnx – NaturalDemon Aug 16 '20 at 10:32
1

Here's a simple pair of iterators that go in row-major and column-major order.

class row_iterator
{
    int (&arr)[3][3];
    std::size_t pos;
public:
    row_iterator(int (&arr)[3][3], std::size_t pos) : arr(arr), pos(pos) {}

    row_iterator& operator++() { ++pos; return *this; }
    row_iterator operator++(int) { auto that = *this; ++pos; return that; }
    int & operator*() { return arr[pos / 3][pos % 3]; }
    int * operator->() { return &arr[pos / 3][pos % 3]; }

    friend bool operator==(row_iterator lhs, row_iterator rhs) { return (lhs.arr == rhs.arr) && (lhs.pos == rhs.pos); }
    friend bool operator!=(row_iterator lhs, row_iterator rhs) { return !lhs == rhs; }
};

row_iterator row_begin(int (&arr)[3][3]) { return row_iterator(arr, 0); }
row_iterator row_end(int (&arr)[3][3]) { return row_iterator(arr, 9); }

class col_iterator
{
    int (&arr)[3][3];
    std::size_t pos;
public:
    col_iterator(int (&arr)[3][3], std::size_t pos) : arr(arr), pos(pos) {}

    col_iterator& operator++() { ++pos; return *this; }
    col_iteratoroperator++(int) { auto that = *this; ++pos; return that; }
    int & operator*() { return arr[pos % 3][pos / 3]; }
    int * operator->() { return &arr[pos % 3][pos / 3]; }

    friend bool operator==(col_iterator lhs, col_iterator rhs) { return (lhs.arr == rhs.arr) && (lhs.pos == rhs.pos); }
    friend bool operator!=(col_iterator lhs, col_iterator rhs) { return !lhs == rhs; }
};

col_iterator col_begin(int (&arr)[3][3]) { return col_iterator(arr, 0); }
col_iterator col_end(int (&arr)[3][3]) { return col_iterator(arr, 9); }
Caleth
  • 52,200
  • 2
  • 44
  • 75
0

You can just do pointer arithmatic to access the column.

cout<<"Column : "<<*(*it+1)<<endl;

Here, 1 is the column number.

Live example here : https://gcc.godbolt.org/z/WXKLCk

Sitesh
  • 1,816
  • 1
  • 18
  • 25