Как реализовать переменную размерную матрицу (int) в C? Для уточнения я должен иметь возможность добавлять строки и столбцы в соответствии с фактами ситуации (внутри предложения if).Матрица с переменным размером в C
Спасибо, Vi.
Как реализовать переменную размерную матрицу (int) в C? Для уточнения я должен иметь возможность добавлять строки и столбцы в соответствии с фактами ситуации (внутри предложения if).Матрица с переменным размером в C
Спасибо, Vi.
Вы можете написать интерфейс для разделения компонентов многократного использования. Основным решением, которое вы должны принять, является реализация разреженной или плотной схемы размещения.
Предполагая плотную схему, объект может быть
в matrix.h
#include <stdio.h>
typedef struct matrix {
int nrows, ncols, *data;
} matrix;
matrix* allocate(matrix *mat, int nrows, int ncols);
int *cell(const matrix *mat, int row, int col);
matrix *addrow(matrix *mat);
matrix *addcol(matrix *mat);
matrix *print(FILE *f, matrix *mat);
в matrix.c
#include "matrix.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
matrix* allocate(matrix *mat, int nrows, int ncols)
{
assert(nrows > 0 && ncols > 0);
mat->nrows = nrows;
mat->ncols = ncols;
mat->data = malloc(sizeof(int) * nrows * ncols);
return mat;
}
int *cell(const matrix *mat, int row, int col)
{
assert(row >= 0 && row < mat->nrows);
assert(col >= 0 && col < mat->ncols);
return mat->data + row * mat->ncols + col;
}
matrix *addrow(matrix *mat)
{
mat->nrows++;
mat->data = realloc(mat->data, sizeof(int) * mat->nrows * mat->ncols);
return mat;
}
/* adding a column it's an expensive operation */
matrix *addcol(matrix *mat)
{
mat->ncols++;
mat->data = realloc(mat->data, sizeof(int) * mat->nrows * mat->ncols);
/* shift rows' elements, to make room for last column */
for (int r = mat->nrows - 1; r > 0; --r)
{
int *dest = mat->data + r * mat->ncols,
*orig = mat->data + r * (mat->ncols - 1);
memmove(dest, orig, sizeof(int) * (mat->ncols - 1));
}
return mat;
}
matrix *print(FILE *f, matrix *mat)
{
for (int r = 0; r < mat->nrows; ++r)
{
for (int c = 0; c < mat->ncols; ++c)
fprintf(f, "%4d ", *cell(mat, r, c));
fprintf(f, "\n");
}
return mat;
}
int main_matrix(int argc, char **argv)
{
matrix m;
allocate(&m, 3, 5);
for (int r = 0; r < m.nrows; ++r)
for (int c = 0; c < m.ncols; ++c)
*cell(&m, r, c) = 35;
print(stdout, &m);
fprintf(stdout, "\n");
addrow(&m);
for (int c = 0; c < m.ncols; ++c)
*cell(&m, m.nrows - 1, c) = 45;
print(stdout, &m);
fprintf(stdout, "\n");
addcol(&m);
for (int r = 0; r < m.nrows; ++r)
*cell(&m, r, m.ncols - 1) = 46;
print(stdout, &m);
fprintf(stdout, "\n");
// remember to free memory
free(m.data);
return argc;
}
тест выход:
35 35 35 35 35
35 35 35 35 35
35 35 35 35 35
35 35 35 35 35
35 35 35 35 35
35 35 35 35 35
45 45 45 45 45
35 35 35 35 35 46
35 35 35 35 35 46
35 35 35 35 35 46
45 45 45 45 45 46
Просто потому, что C не поддерживает языковую поддержку объектно-ориентированных идей, таких как инкапсуляция и скрытие информации, не означает, что вы не можете использовать их в своем коде; вам просто нужно усердно работать, чтобы ввести их в действие.
Это было слишком долго, так как я написал C, чтобы быть более конкретным, но Eric Roberts в Стэнфорде преподавал несколько отличных методик в курсе программирования C. Я бы рекомендовал вам заглянуть в них.
Идея состоит в том, что вам нужно будет восстановить память для матрицы нового размера, скопировать в нее старые элементы, инициализировать новые значения, очистить старую память и назначить новую матрицу указательной переменной , Если вы спрячете все это в методе, клиенты вашего кода просто назовут его и не будут беспокоиться о магии, которую вы делаете под ней. Вам не придется повторять сложности в нескольких местах. Вы просто назовете один метод и сделаете это.
Как только вы знаете размер, вам нужно выделить достаточно места на куче для размещения такого размера. Вы можете выделить место в куче malloc
или calloc
.
Например:
#include <stdio.h>
#include <stdlib.h>
void set_value(int * matrix, int row, int col, int value);
int get_value(int * matrix, int row, int col);
int main() {
int rows = 5; /* arbitrary */
int cols = 3; /* arbitrary */
int * matrix = (int *) calloc(rows * cols, sizeof(int));
if (matrix == NULL) {
printf("Error with allocation!\n");
return -1;
}
set_value(matrix, 0, 0, 5);
set_value(matrix, 0, 1, 2);
set_value(matrix, 4, 2, 1);
printf("%d\n", get_value(matrix, 0, 0));
printf("%d\n", get_value(matrix, 0, 1));
printf("%d\n", get_value(matrix, 4, 2));
free(matrix);
return 0;
}
void set_value(int * matrix, int row, int col, int value) {
*(matrix + col * sizeof(int) + row) = value;
}
int get_value(int * matrix, int row, int col) {
return *(matrix + col * sizeof(int) + row);
}
Просто убедитесь, что вы всегда проверить, что вызов malloc
или calloc
работал, и что вы всегда освободить память позже free
.
Если вам когда-либо понадобится изменить размер матрицы, вам придется либо использовать realloc
, либо запросить больше места на куче, скопировать ваши значения и освободить более старую память.
Я надеваю Когда я начинаю, я знаю размер. Я бы добавил поэтапные строки и столбцы в соответствии с условными предложениями. –
я думаю, что вы можете создать буфер динамической памяти выделения «таНос»
Добро пожаловать в SO! Отвечая на вопросы, старайтесь быть конкретными и включайте код, где сможете. – lnafziger
Как я вижу, вы не хотите, чтобы объявить, как: int arr[5][5]
;
Вы можете использовать мои malloc
и realloc
. Например, чтобы создать 2D массив динамически:
int nrows;
int ncolumns;
scanf("%d %d", &nrows, &ncolumns);
int **arr = malloc(nrows * sizeof(int *));
for(i = 0; i < nrows; i++)
arr[i] = malloc(ncolumns * sizeof(int));
Тогда к realloc
, если вы хотите изменить размер. Преимущество использования realloc заключается в том, что он автоматически позаботится о копировании значений из исходных мест памяти в новое место в случае, если он не может расширить память в том же регионе.
Обратите внимание, что здесь его для 2D-массива. Если вы хотите изменить сам размер или если вы хотите иметь возможность изменять размеры, вы можете скомпоновать аналогично вышеизложенному с другой функцией для каждого из таких случаев. Опять же, это будет выглядеть немного уродливо. Но нет такого элегантного способа делать такие вещи в C.
Я только что написал ... Надеюсь, он сработает.
int **matrix;
int m=10;
int n=10;
int i,j;
matrix = (int)** malloc (m*sizeof(int*));
for(i=0;i<m;i++){
matrix[i]= (int)* malloc (n*sizeof(int));
for(j=0;j<n;j++)
matrix[i][j] = (10.0*rand());
}
free(matrix);
большая утечка памяти при освобождении только 'matrix' –
Спасибо, очень, я понимаю свою ошибку! –