Ошибка запуска программы
Есть задача заполнить матрицу натуральными числами от 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 шт):
Вариант 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;
}