如何在C中实现可变大小矩阵(int)?为了澄清,我必须能够根据情况的事实添加行和列(在if子句中)。
谢谢,Vi。
答案 0 :(得分:3)
您可以编写一个可重用的组件,将接口与实现分开。 您应该采取的主要决策是实现稀疏或密集的分配模式。
假设密集模式,对象可能是
在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
答案 1 :(得分:2)
我认为你不想声明: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中没有优雅的方法来做这些事情。
答案 2 :(得分:1)
仅仅因为C没有语言支持面向对象的想法,如封装和信息隐藏,并不意味着你不能在你的代码中使用它们;你只需要更加努力地使它们生效。
自从我写C更具体以来,已经太久了,但斯坦福大学的Eric Roberts在C语言课程中教授了一些很棒的技巧。我建议你调查它们。
这个想法是你必须为新大小的矩阵重新存储内存,将旧元素复制到其中,初始化新值,清理旧内存,并将新矩阵分配给指针变量。如果你在一个方法中隐藏所有这些,你的代码的客户只会调用它而不用担心你在下面做的魔法。您不必在几个地方重复复杂性。你只需要调用一种方法并完成它。
答案 3 :(得分:1)
一旦知道了大小,就必须在堆上分配足够的空间以容纳该大小。您可以使用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
或在堆上请求更多空间,复制值并释放旧内存。
答案 4 :(得分:0)
我认为您可以使用动态内存分配“malloc”
创建缓冲区答案 5 :(得分:-2)
我刚刚写完了...希望它能奏效。
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);