Ошибка запуска программы

Есть задача заполнить матрицу натуральными числами от 1 до [n][m] по спирали, начинающейся в левом верхнем углу и закручивающейся по часовой стрелке. Был написан следующий код, который не запускается, но при этом не выдает ошибок компиляции в VS Code. Есть подозрение, что что-то не так с инициализацией двумерного массива или имеются проблемы при работе с ним.

#include <stdio.h>
#include <random>

using namespace std;
int main(int argc, char const *argv[]){
int n = 7;
int m = 9;
int count = 0;

int matrixs[m][n];
for (int z = 0; z < n; z++)
{
    if(z % 2 == 0)
    {
        for (int j = n-1; j < n; j++)
        { 
            for (int i = 0; i < m; i++)
            {
            matrixs[i][j] = count;
            count++;
            }
        }
        for (int i = m-1; i < m; i++)
        { 
            for (int j = 0; j < n; j++)
            {
            matrixs[i][j] = count;
            count++;
            }
        }
    }
    else {
        for (int i = n-1; i < m; i++)
        { 
            for (int j = 0; j < n; j--)
            {
            matrixs[i][j] = count;
            count++;
            }
        }
        for (int j = n-1; j < n; j++)
        { 
            for (int i = 0; i < m; j--)
            {
            matrixs[i][j] = count;
            count++;
            }
        }
    }
}


for (int i = 0; i < m; i++)
{
    for (int j = 0; j < n; j++)
    {
        printf("%d ", matrixs[i][j]);
    }
    printf("\n");
}

return 0;}

Ответы (1 шт):

Автор решения: NunOfIt

Вариант 1 (пояснение):

Это исправленная версия вашего алгоритма. Идея у вас в целом была правильная, пройтись циклом сначала слева направо, потом сверху вниз, потом справа налево и снизу вверх, но вот имплементация подкачала.

Во первых, условие вашего главного цикла, как и чётность z, никак вас к желаемой цели не приближают. В данном случае лучше использовать count как условие, т.е. цикл идёт пока count меньше максимального его значения, и добавить переменную key, которая бы переключала программу с прохода вправо и вниз, к проходу влево и вверх.

Во вторых, вам нужна некая переменная (shift), в которой бы хранился сдвиг. Сначала же змейка идёт по внешенму кругу, потом все значения уменьшаются на единицу и она идёт по внутреннему кругу и т.д.

Ну и начальные и предельные значения i и j у вас выставленны неправильно.

Вариант 2 (пояснение):

Идея: использовать расположение двумерного массива в памяти компьютера, для упрощения задачи, т.е. к переходу от работы с матрицей к работе с массивом.

Пример:

Матрица:

1  2  3  4  5  6  7  8  9
28 29 30 31 32 33 34 35 10
27 48 49 50 51 52 53 36 11
26 47 60 61 62 63 54 37 12
25 46 59 58 57 56 55 38 13
24 45 44 43 42 41 40 39 14
23 22 21 20 19 18 17 16 15

Запись матрицы в памяти компьютера:

1 2 3 4 5 6 7 8 9 | 28 29 30 31 32 33 34 35 10 | 27 48 49 50 51 52 53 36 11 | 26 47 60 61 62 63 54 37 12 | 25 46 59 58 57 56 55 38 13 | 24 45 44 43 42 41 40 39 14 | 23 22 21 20 19 18 17 16 15

Можно заметить, что у нас сначала идёт блок, в котором все значения идут подряд, а потом через M (кол-во столбцов), пока не дойдёт до упора, потом опять такой же блок но уже в обратном направлении и опять до упора. Единственное, тут нужно учесть, что на каждой итерации рамки начала и конца сужаются, как и окно в котором цифры идут по порядку.

#include <iostream>

template<size_t N, size_t M>
std::ostream& operator<<(std::ostream& out, const int (&arr)[N][M]) {
    for(size_t i = 0; i < N; ++i) {
        for(size_t j = 0; j < M; ++j)
            out << arr[i][j] << ' ';
        out << '\n';
    }
    return out;
}

template<size_t N, size_t M>
void fill(int (&arr)[N][M]) {
    int shift = 0;
    int count = 0;
    int max = N * M;
    bool key = true;

    for (int i, j; count < max; key = !key)
    {
        if(key) {
            // Проход от лев. вх. края до до прав. вх. края
            i = shift;
            for(j = shift; j < M - shift; ++j)
                arr[i][j] = ++count;
                
            // Проход от прав. вх. края до до прав. ниж. края
            j = M - shift - 1;
            for(i = shift + 1; i < N - shift; ++i)
                arr[i][j] = ++count;
        }
        else {
            // Проход от прав. ниж. края до до лев. ниж. края
            i = N - shift - 1;
            for(j = M - shift - 2; j >= shift; --j)
                arr[i][j] = ++count;
                
            // Проход от лев. ниж. края до до лев. верх. края
            j = shift++;
            for(i = N - shift - 1; i >= shift; --i)
                arr[i][j] = ++count;
        }
    }
}

void fill(int* beg, int* end, size_t n, size_t m) {
    int* it;
    int count = 0;
    size_t width = m;

    it = --beg;
    for(; beg < end; it = beg, width -= 2) {
        // Прямой проход
        for(size_t i = 0; i < width; ++i) { *(++it) = ++count; }
        while(it < end) { *(it += m) = ++count; }
        beg += m + 1;

        if (beg >= end) { break; }

        // Обратный проход
        for(size_t i = 1; i < width; ++i) { *(--it) = ++count; }
        while(it > beg) { *(it -= m) = ++count; }
        end -= m + 1;
    }
}

int main() {
    const size_t N = 7, M = 9;

    // Вариант 1
    int arr1[N][M];
    (void) fill(arr1);
    std::cout << arr1 << "\n\n";

    // Вариант 2 
    int arr2[N][M];
    (void) fill(&arr2[0][0], &arr2[N - 1][M - 1], N, M);
    std::cout << arr2;
    return 0;
}
→ Ссылка