我正在写矩阵乘法的C函数。它需要两个整数的二维数组。如果我知道输入数组的维数,我可以做到这一点,但我想做一个更通用的函数。如何使用尺寸未知的二维数组?
如何找到它们的尺寸,以及如何返回一个数组的时候,我不知道该产品的编译时间维度?
我正在写矩阵乘法的C函数。它需要两个整数的二维数组。如果我知道输入数组的维数,我可以做到这一点,但我想做一个更通用的函数。如何使用尺寸未知的二维数组?
如何找到它们的尺寸,以及如何返回一个数组的时候,我不知道该产品的编译时间维度?
你不能找出一个数组的大小如果你所有的是一个指针数组的开头。您将需要将数组的维度传递给函数。
您将需要传递数组的维数。然后你将不得不动态分配第三个数组来保存结果。一旦你计算出了结果矩阵,你可以返回一个指向它的指针。
尝试沿着这些线路,其中A是N×M的矩阵,B是一个米×P矩阵的东西:
int* matix_multiply(int* matrix_a, int* matrix_b, int n, m, int p){
int *result = (int *) malloc(sizeof(int) * a_rows * b_cols);
if(result == NULL)
exit(EXIT_FAILURE);
//loops to do the actual multiplication and store the results in result[i][j]
return result; //returns the result array
}
您是最好关闭你的阵列创建的矩阵结构。正如@大卫注意到的,在C中,你必须自己跟踪维度。语言中没有内置任何功能,可以安全地执行此操作。
有喜欢的strlen()的字符串功能(即:与\ 0结尾字符数组),但不喜欢的事情阵列和这样。跟踪这个最简单的方法是创建自己的抽象数据类型和辅助函数。
试试这个:
typedef struct matrix {
int **array;
int rows;
int cols;
} matrix_t;
int createMatrix(matrix_t* mtx) {
int i;
if (!mtx) {
printf("INVALID POINTER TO MATRIX");
return -1;
}
if ((mtx->rows == 0) || (mtx->cols == 0)) {
printf("Rows/columns cannot be zero!");
return -1;
}
int status = 0;
// allocate the array
mtx->array = (int **)calloc(mtx->rows,sizeof(int*));
if(mtx->array != NULL) {
// memory allocation succeeded
for(i = 0; i < mtx->rows; i++) {
if((mtx->array[i] = (int*)calloc(mtx->cols,sizeof(int))) == NULL) {
printf("Memory allocation error");
status = -1;
break;
} else {
// Allocation successful
}
}
} else {
printf("Memory allocation error!");
status = -1;
}
return status;
}
int destroyMatrix(matrix_t* mtx) {
// destroy the array
for(i = 0; i < mtx->rows; i++) {
if(mtx->array[i] != NULL) {
free(mtx->array[i]);
mtx->array[i] = NULL;
}
}
if(mtx->array) {
free(mtx->array);
mtx->array = NULL;
}
return 0;
}
现在,你可以创建一个新的矩阵结构,设置它的行/列值,调用createMatrix,和你设置:
matrix_t myMtx;
myMtx.array = NULL;
myMtx.rows = 3;
myMtx.cols = myMtx.cols; // Make it a square matrix
if(createMatrix(&myMtx) == 0) {
printf("Created matrix successfully");
} else {
printf("Failed to create matrix!");
}
这些功能还亲切检查内存分配是否失败,并在使用前检查所有指针以避免程序崩溃(即:SEGFAULT)。
祝你好运!
如果你采取这种方法,我至少会将rows&cols params传递给'createMatrix()',因为在你调用'createMatrix()'之前,你总是必须初始化它们。 –
不同的风格选择,它似乎。我更喜欢该结构是独立的,并且创建函数会执行相应的检查。当处理大的上下文变量时,保留函数原型更小,更可读,而不是冗长的,恕我直言。 – DevNull
是的,我想这是关于保持函数原型简短和甜蜜的好处。我从数据隐藏/封装的角度思考更多。 –
有在C.没有真正的二维数组只有数组的数组,这是不完全一样的东西。 (我知道我会被打这么说。原谅我。)
虽然差异似乎并不十分显著,它是。要使用数组,您不必在编译时知道它的维数。例如
double dot_product (double a[], double b[], int size);
/* an A-OK function */
但是你必须知道任何数组元素的大小。例如
void matrix_product (double a[][], double b[][], double result[][],
int a_rows, int a_cols, int b_cols);
/* Bad, would not compile. You are only permitted to say "double[N][]",
where N is known at compile time */
如果你想完全通用矩阵操作代码,你需要使用一个简单的一维数组,并计算索引列的行数和列数自己的。你也必须通过尺寸。
void matrix_product (double a[], double b[], double result[],
int a_rows, int a_cols, int b_cols) {
...
for (col = 0; col < a_cols; ++col) {
for (row = 0; row < a_rows; ++row) {
...
... a[row*a_cols + col] ...
...
在这个例子中,调用者分配result
,而不是乘法函数。
在你将要与他们一起尺寸封装矩阵某种形式的抽象矩阵数据类型的,像这样的一些更高级别:
struct matrix {
double* elements;
int rows, cols;
};
但这是一个整体“诺特尔故事。
我同意一个单一的数组就是要走的路。 Dogbert的答案显示了“其他”的方式。查看我的答案,了解如何在结构中进行封装的示例。 –
这个答案是总的矫枉过正,但这是我的struct
为基础的方法,其中。称为“一个完整的故事”。如果这是一个新程序(也就是说,你可以定义你的函数的输入/输出是什么样的),并且你打算用矩阵做很多工作,我会倾向于使用一个结构体来表示一个结构体矩阵,并传递指向该结构实例的指针。
下面的代码显示了一种可能的方法。请注意,这里有几个“技巧”。首先,数据全部存储在一个连续的块中 - 由于多种原因,这可能会提高性能。这种技术的一个潜在缺点是,调整矩阵的大小会变得很昂贵,因为您必须分配一个全新的实例并复制数据。但是如果你发现这是一个问题,你总是可以改变你的实现,假设你总是使用matrix_get()和matrix_set()函数来访问矩阵中的值。
此外,数据指针指向的矩阵结构和内存全部分配在一个malloc调用中。如果您使用这种技术,只需注意数据对齐问题。例如,如果您将数据更改为指向64位整数或双精度,则需要添加填充以确保所有内容均为8字节对齐。或者,只要将malloc
的数据指针作为new_matrix()
函数中的单独数组提供,前提是您记得将其释放到free_matrix()
中。
我已经作为练习留给OP来编写乘法函数。
#include <stdio.h>
#include <stdlib.h>
struct matrix
{
int rows;
int cols;
int * data;
};
struct matrix * new_matrix(int rows, int cols)
{
struct matrix * m = NULL;
/* Allocate a block of memory large enough to hold the matrix 'header' struct
* as well as all the row/column data */
m = malloc(sizeof(struct matrix) + (rows * cols * sizeof(int)));
if(m)
{
m->rows = rows;
m->cols = cols;
/* Some ugly pointer math to get to the first byte of data */
m->data = (int*) ((char *) m + sizeof(*m));
}
return m;
}
void free_matrix(struct matrix * m)
{
free(m);
}
int matrix_set(struct matrix * m, int row, int col, int val)
{
if(col >= m->cols || row >= m->rows)
return -1;
m->data[ m->cols * row + col ] = val;
return 0;
}
int matrix_get(struct matrix * m, int row, int col, int * val)
{
if(col >= m->cols || row >= m->rows)
return -1;
else
{
*val = m->data[ m->cols * row + col ];
return 0;
}
}
void print_matrix(struct matrix * m)
{
int r,c;
int val;
for(r = 0; r < m->rows; r++)
{
for(c = 0; c < m->cols; c++)
{
matrix_get(m, r, c, &val);
printf("%5d%s", val, c + 1 < m->cols ? "," : "");
}
printf("\n");
}
}
int main (int argc, char **argv)
{
int r,c;
struct matrix * m = new_matrix(5, 5);
for( r = 0; r < m->rows; r++)
{
for(c = 0; c < m->cols; c++)
{
matrix_set(m, r, c, (r +1)* 10 + c + 1);
}
}
print_matrix(m);
free_matrix(m);
return 0;
}
#include <stdio.h>
void foo(int *a, int m, int n)
{
for(int i=0; i<m; i++)
for(int j=0; j<n; j++)
printf("%d\n", *(a+i*n+j));
}
int main()
{
int a[][2] = {{1,2},{3,4}};
foo((int *)a,2,2);
return 0;
}
通常的2D阵列存储在行主要方式。 二维数组可以视为指向数组元素的指针数组。由于我们也通过了两个维度,因此我们可以相应地访问元素。
即使您可以尝试其他数据类型。下面我用了结构。
#include <stdio.h>
struct abc
{
int a;
float b;
char c;
};
void foo(struct abc *a, int m, int n)
{
for(int i=0; i<m; i++)
for(int j=0; j<n; j++)
printf("%d %f %c\n", (a+i*n+j)->a, (a+i*n+j)->b, (a+i*n+j)->c);
}
int main()
{
struct abc a[][2] = {{{1,1.0,'a'},{2,2.0,'b'}}, {{3,3.0,'c'},{4,4.0,'d'}}};
foo((struct abc *)a,2,2);
return 0;
}
希望它有帮助.... !!!!!
或者我是否需要将尺寸作为单独的参数传递? – Andreas
要知道的唯一方法是将数组维度作为参数传递给函数。 – Mahesh