C矩阵结构



我正在学习C,并且很难确定我在做错了什么,因为我会遇到细分错误。我正在尝试初始化一个矩阵结构,该矩阵结构包含带有实际数据的2D数组的指针。然后用数组中的数据填充它。

#include "base.h" 
struct Matrix {
    int rows; // number of rows
    int cols; // number of columns
    double** data; // a pointer to an array of n_rows pointers to rows
};
typedef struct Matrix Matrix;
Matrix* make_matrix(int n_rows, int n_cols) {
    struct Matrix matrix;
    matrix.rows = n_rows;
    matrix.cols = n_cols;
    matrix.data = (double**)malloc(sizeof(double*) * n_rows);
    for(int x = 0; x < n_rows; x++){
        matrix.data[x] = (double*)calloc(n_cols, sizeof(double));
    }
    struct Matrix *m;
    m = &matrix;
    return m;
}
Matrix* copy_matrix(double* data, int n_rows, int n_cols) {
    struct Matrix *matrix = make_matrix(n_rows, n_cols);
    for(int x = 0; x < n_rows; x++) {
        for(int y = 0; y < n_cols; y++) {
            matrix->data[x][y] = data[x+y];
        }
    }
    return matrix;
}
void print_matrix(Matrix* m) {
    for(int x = 0; x < m->rows; x++) {
        for(int y = 0; y < m->cols; y++) {
            printf("%f", m->data[x][y]);
        }
    }
}
void matrix_test(void) {
    double a[] = { 
        1, 2, 3, 
        4, 5, 6, 
        7, 8, 9 };
    Matrix* m1 = copy_matrix(a, 3, 3);
    print_matrix(m1);
}
int main(void) {
    base_init();
    base_set_memory_check(true);
    matrix_test();
    return 0;
}

另外,除分段故障触发错误外,还有什么要更改的更好?

欢迎来到C。

1)您无法将指针返回到函数的本地变量。(与make_matrix()中的错误有关)

2)没有明显的方法可以在C中定义"多维"数组,除非已知行并固定在编译时,否则您可以方便地访问data[x][y]之类的元素。(并且您的矩阵维度在编译时不知道。)

让我们分开处理。

求解1),您想在make_matrix()中做的是:

Matrix* make_matrix(int n_rows, int n_cols) {
    struct Matrix* pmatrix = malloc(sizeof(struct Matrix));
    pmatrix->rows = n_rows;
    pmatrix->cols = n_cols;
    ...
    ...
    return pmatrix;
}

但是,仅此一个就无法修复错误。数据需要存储在cols * rows元素的一个大数组中,您需要指定如何找到每个项目而不是data[x][y]

为了解决2),您的矩阵结构定义应为

struct Matrix {
    int rows; // number of rows
    int cols; // number of columns
    double* data; // <- note that this is a pointer to one dim array
};

,内部make_matrix()

pmatrix->data = malloc(sizeof(double)*n_rows*n_cols);

您现在需要全部。

复制相同维度和格式的矩阵,

Matrix* copy_matrix(double* data, int n_rows, int n_cols) {
    struct Matrix *matrix = make_matrix(n_rows, n_cols);
    for(int i = 0; i < n_rows*n_cols; i++)
        matrix->data[i] = data[i];
    return matrix;
}

(我将此功能命名为dup_matrix(),而不是copy_matrix(),因为它实际上创建了一个新实例)

最后,如果要在[x] [y]上访问元素,则应将位置明确计算为data[x*cols + y],因此printf()行变为

printf("%f ", m->data[x*(m->cols) + y]);

当然,您需要正确检查malloc()的返回是否错误并正确清理。

谢谢您的回答,我学会了失败的地方。为了完整,工作代码看起来像这样:

#include "base.h"
struct Matrix {
    int rows; // number of rows
    int cols; // number of columns
    double** data; // a pointer to an array of n_rows pointers to rows; a row is an array of n_cols doubles 
};
typedef struct Matrix Matrix;
Matrix* make_matrix(int n_rows, int n_cols) {
    struct Matrix* matrix = malloc(sizeof(Matrix));
    matrix->rows = n_rows;
    matrix->cols = n_cols;
    double** data = malloc(sizeof(double*) * n_rows); 
    for(int x = 0; x < n_rows; x++){
        data[x] = calloc(n_cols, sizeof(double));
    }
    matrix->data = data;
    return matrix;
}
Matrix* copy_matrix(double* data, int n_rows, int n_cols) {
    struct Matrix *matrix = make_matrix(n_rows, n_cols);
    for(int x = 0; x < n_rows; x++) {
        for(int y = 0; y < n_cols; y++) {
            matrix->data[x][y] = data[n_cols*x+y];
        }
    }
    return matrix;    
}
void print_matrix(Matrix* m) {
    for(int x = 0; x < m->rows; x++) {
        printf("%s", "n");
        for(int y = 0; y < m->cols; y++) {
            printf("%ft", m->data[x][y]);
        }
    }
}
void matrix_test(void) {   
    double a[] = { 
        1, 2, 3, 
        4, 5, 6, 
        7, 8, 9,
        10,11,12
        };
    Matrix* m1 = copy_matrix(a, 4, 3);
    print_matrix(m1);
}
int main(void) {
    base_init();
    base_set_memory_check(true);
    matrix_test();
    return 0;
}

如果要做出更多改进或伤害您的惯例,请告诉我。

以下:

Matrix* make_matrix(int n_rows, int n_cols) {
    struct Matrix matrix;

matrix声明为函数make_matrix()中的局部变量。在该函数的末尾,您要接收该局部变量的地址,出于某种原因将其存储在指针中,然后返回该指针。因此,您正在返回指向函数堆栈中位置的指针。但是该功能刚刚返回,因此该位置现在无效。

而不是struct Matrix matrix;,您需要执行Matrix* m = malloc( sizeof( Matrix ) );(如果您的编译器不允许使用,请尝试Matrix* m; m = malloc( sizeof( Matrix ) );),然后按照以下方式填充结构:m->rows = n_rows;等。

相关内容

  • 没有找到相关文章

最新更新