Самый чистый способ перебора 2D-контейнера в C ++ - PullRequest
1 голос
/ 13 февраля 2020

Скажем, у меня есть функция, которая берет начальный и конечный итераторы из 2D-контейнера. Я хотел бы получить размеры контейнера, а затем перебрать элементы, используя формат, указанный ниже:

template <typename It>
void func(It st, It en) {
  int rows = ... , cols = ... ;
  for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
      // get container's index somehow using indices
    }
  }
}

int main() {
  int arr[2][3] = {{0, 1, 2}, {3, 4, 5}};
  func(arr, arr + 2 * 3);
}

Возможно ли добиться этого с помощью итераторов?

Ответы [ 3 ]

0 голосов
/ 13 февраля 2020
#include<iostream>
#include<iterator>
template <typename It>
void func(It st, It en) {

    while (st!=en) {

        auto it1 = std::begin(*st);
        auto it2 = std::end(*st++);
        while (it1 != it2) {

            *(it1++)=8;
        }
    }
}


int main() {

    int arr[2][3] ={{1,3,1},{1,30,10}};

    func(std::begin(arr), std::end(arr) );

    for(int i{};i<2;++i){
        for(int j{}; j<3;++j){
            std::cout<<arr[i][j]<<" ";
        }
        std::cout<<"\n";
    }
}

До C ++ 17 используйте

func<decltype(std::begin(arr))>(std::begin(arr), std::end(arr));
0 голосов
/ 13 февраля 2020

Скажем, у меня есть функция, которая берет начальный и конечный итераторы из 2D-контейнера.

Вот первая проблема. В опубликованном фрагменте есть такие строки:

int arr[2][3] = {{0, 1, 2}, {3, 4, 5}};
func(arr, arr + 2 * 3);
//            ^^^^^^^   

Хотя arr обычно называют многомерным или двумерным массивом, на самом деле это массив из 2 массивов из 3 целых чисел. Его размер не 6 (= 2x3), но 2.

Если вы хотите использовать два итератора в сигнатуре функции, вы можете переписать ваш забавный c следующим образом:

// This would print out the elements
template <typename RandomIt>
void func(RandomIt first, RandomIt last)
{
    // Iterates through the rows
    for (auto row = first; row < last; ++row)
    {
        // Loops through each row
        for (auto const& el : *row)
        {
            std::cout << ' ' << el;
        }
        std::cout << '\n';
    }
}

int main()
{
    int arr[2][3] = {{0, 1, 2}, {3, 4, 5}};
    func(std::cbegin(arr), std::cend(arr));
    std::cout << '\n';

    std::vector<std::vector<int>> b {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
    func(b.cbegin(), b.cend());
}

Я хотел бы получить размеры контейнера

Есть несколько способов сделать это sh.

Если вы ограничивая себя простыми массивами, вы можете просто изменить сигнатуру функции и использовать правильные аргументы шаблона и передать массив по ссылке:

template <class T, std::size_t Rows, std::size_t Cols>
void func(T const (&arr)[Rows][Cols]) { /* ... */ }

Стандартная библиотека предлагает различные бесплатные функции, которые могут помочь в написании более общих слов. такие функции, как std::size.

template <class M>
void func(M const& m)
{
    for (size_t i{}; i < std::size(m); ++i)
    {
        for (size_t j{}; j < std::size(m[i]); ++j)
        {
            std::cout << ' ' << m[i][j];
        }
        std::cout << '\n';
    }
}

В общем, вы можете создать свой собственный класс, моделирующий 2D-контейнер, и методы записи, возвращающие правильное количество строк или столбцов.

0 голосов
/ 13 февраля 2020

Я рад, что меня исправили (и я уверен, что так и будет), но я думаю, что ответ будет только в том случае, если вы создадите свой собственный итератор. Вы можете получить close-i sh, выполнив что-то вроде этого, однако параметр 'nrows' в шаблоне все еще должен быть указан.

template <uint32_t nrows, uint32_t ncols, typename It>
void func(It st[nrows][ncols]) {
  // int rows = ... , cols = ... ;
  for (int i = 0; i < nrows; i++) {
    for (int j = 0; j < ncols; j++) {
      // get container's index somehow using indices
      std::cout << st[i][j] << ' ';
    }
    std::cout << '\n';
  }
}

int main()
{
  int arr[2][3] = {{0, 1, 2}, {3, 4, 5}};
  func<2>(arr);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...