Это код, который я использовал бы для копирования квадратных субматриц из одной матрицы в отдельную матрицу:
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
enum { MAX_MATRIX_SIZE = 10 };
struct matrix
{
char name;
float mValues[MAX_MATRIX_SIZE][MAX_MATRIX_SIZE];
int nrows;
int ncols;
};
typedef struct matrix Matrix;
static void matrixDisplay(const Matrix *mat);
static int matrixExtractSubMatrix(Matrix *m2, const Matrix *m1, char name,
int r0, int c0, int size);
int main(void)
{
Matrix matA =
{
.name = 'A', .nrows = 4, .ncols = 4,
.mValues =
{
{ 1, 2, 3, 4, }, { 5, 6, 7, 8, },
{ 9, 1, 2, 3, }, { 4, 5, 6, 7, },
},
};
matrixDisplay(&matA);
Matrix matB;
for (int i = 0; i < matA.nrows - 2 + 1; i++)
{
for (int j = 0; j < matA.ncols - 2 + 1; j++)
{
if (matrixExtractSubMatrix(&matB, &matA, 'B', i, j, 2) != 0)
fprintf(stderr, "Failed to extract sub-matrix\n");
matrixDisplay(&matB);
}
}
return 0;
}
static void matrixDisplay(const Matrix *mat)
{
printf("\nMatrix %c (%dx%d):\n", mat->name, mat->nrows, mat->ncols);
for (int i = 0; i < mat->nrows; i++)
{
printf("Row: %d:", i);
for (int j = 0; j < mat->ncols; j++)
printf(" %8.2f", mat->mValues[i][j]);
printf("\n");
}
}
static int matrixExtractSubMatrix(Matrix *m2, const Matrix *m1, char name,
int r0, int c0, int size)
{
assert(m2 != NULL && m1 != NULL);
assert(r0 >= 0 && r0 + size <= m1->nrows);
assert(c0 >= 0 && c0 + size <= m1->ncols);
if ((r0 < 0 || r0 + size > m1->nrows) ||
(c0 < 0 || c0 + size > m1->ncols))
return -1;
m2->name = name;
m2->nrows = size;
m2->ncols = size;
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
m2->mValues[i][j] = m1->mValues[r0 + i][c0 + j];
}
return 0;
}
В этом нет ничего примечательного. Это позволяет избежать копирования 412 байт в стек путем передачи структуры матрицы в качестве указателя, а не копирования всей структуры. Все функции static
, кроме main()
. Если функции должны быть видны за пределами этого файла, они должны быть объявлены в заголовке. Там нет заголовка, поэтому нет никаких функций (кроме main()
), которые должны быть видны за пределами этого файла. Размерность массива в структуре Matrix
(первоначально struct matrix
, но для удобства typedef'd to Matrix
) теперь является константой перечисления, поэтому ее можно использовать в коде для обозначения максимального размера массива в структура.
Я исключил ввод файла и функцию определителя; матрица жестко закодирована.
Тестовый код печатает все нерасширяющие подматрицы 2x2:
Matrix A (4x4):
Row: 0: 1.00 2.00 3.00 4.00
Row: 1: 5.00 6.00 7.00 8.00
Row: 2: 9.00 1.00 2.00 3.00
Row: 3: 4.00 5.00 6.00 7.00
Matrix B (2x2):
Row: 0: 1.00 2.00
Row: 1: 5.00 6.00
Matrix B (2x2):
Row: 0: 2.00 3.00
Row: 1: 6.00 7.00
Matrix B (2x2):
Row: 0: 3.00 4.00
Row: 1: 7.00 8.00
Matrix B (2x2):
Row: 0: 5.00 6.00
Row: 1: 9.00 1.00
Matrix B (2x2):
Row: 0: 6.00 7.00
Row: 1: 1.00 2.00
Matrix B (2x2):
Row: 0: 7.00 8.00
Row: 1: 2.00 3.00
Matrix B (2x2):
Row: 0: 9.00 1.00
Row: 1: 4.00 5.00
Matrix B (2x2):
Row: 0: 1.00 2.00
Row: 1: 5.00 6.00
Matrix B (2x2):
Row: 0: 2.00 3.00
Row: 1: 6.00 7.00
Можно было бы переименовать это как matrixExtractSquareSubMatrix()
и создать другое функция matrixExtractSubMatrix()
, которая сообщает отдельно, сколько строк и столбцов нужно скопировать:
int matrixExtractSubMatrix(Matrix *m2, const Matrix *m1, char name,
int r0, int c0, int ncols, int nrows);
Затем можно написать matrixExtractSquareSubMatrix()
как встроенную функцию, чтобы вызвать matrixExtractSubMatrix()
, передав аргумент size
дважды.
Я не уверен, что создание таких подматриц будет эффективным, но это дополнительная проблема по сравнению с «правильной».