【问题标题】:How to transpose a matrix and return pointer?如何转置矩阵并返回指针?
【发布时间】:2022-01-20 22:35:42
【问题描述】:

我必须做这个练习:给定一个矩阵,编写一个函数来转置该矩阵。它必须返回一个指向该矩阵的指针。

这些是关键点: (1) 编写矩阵构造函数。

(2) 借助矩阵构造函数创建函数。

(3) 转置矩阵。

(4) 打印矩阵。

(5) 释放分配的内存。

(6) 关闭文件。

(暂时,让我们忽略步骤 4、5 和 6)

(1) 和 (2) 矩阵构造函数非常简单,因为它需要 3 个参数:“指向矩阵的指针”、“行”和“列”。这是我的代码:

void matrix_constructor(struct matrix* mat, size_t rows, size_t cols) {
    mat->rows = rows; mat->cols = cols; 
    mat->data = calloc(rows * cols, sizeof(double)); 
}

它有效。

(3)(这是关键点)。 这是我的代码:

struct matrix* mat_transpose(const struct matrix* mat) {
    struct matrix* out;

错误位于此处。这是一个警告(绿色曲线):调试器警告我我正在使用未初始化的内存。但我已经在接下来的几行中对其进行了初始化。为什么我有这个警告?这个警告阻止我运行程序;这很奇怪,因为可以忽略警告,对吧?

    out->rows = mat->cols; 
    out->cols = mat->rows; 
    out->data = mat->data; 
    for (size_t r = 0; r < out->rows; ++r) {
        for (size_t c = 0; c < out->cols; ++c) {
            out->data[r * out->cols + c] = mat->data[r * mat->rows + c]; 
        }
    }
    return out; 
}

.....

这是可重现的例子:

矩阵.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h> 
#include <stdio.h>
struct matrix {
    size_t rows, cols;
    double* data;
};
extern struct matrix* mat_transpose(const struct matrix* mat);

矩阵.c

#include "matrix.h"

struct matrix* mat_transpose(const struct matrix* mat) {
    struct matrix* out; 
    out->rows = mat->cols; 
    out->cols = mat->rows; 
    out->data = mat->data; 
    for (size_t r = 0; r < out->rows; ++r) {
        for (size_t c = 0; c < out->cols; ++c) {
            out->data[r * out->cols + c] = mat->data[r * mat->rows + c]; 
        }
    }
    return out; 
} 

.....

总结一下:

为什么我会收到此警告?能否详细解释一下?

编辑: 我已经编辑了matrix_transpose function 并且它有效。代码如下:

struct matrix* mat_transpose(const struct matrix* mat) {
    struct matrix* out = calloc(mat->rows * mat->cols, sizeof(double));
    if (out == NULL) {
        return NULL; 
    }
    out->rows = mat->cols; 
    out->cols = mat->rows; 
    out->data = mat->data; 
    for (size_t r = 0; r < out->rows; ++r) {
        for (size_t c = 0; c < out->cols; ++c) {
            out->data[r * out->cols + c] = mat->data[r * mat->rows + c]; 
        }
    }
    return out; 
}

现在,mat_fprint 函数:

void matrix_fprint(const struct matrix *m, FILE *f) {
    size_t rows = m->rows; 
    size_t cols = m->cols; 
    double* data = m->data; 

    for (size_t r = 0; r < rows; ++r) {
        for (size_t c = 0; c < cols; ++c) {
            double value = 0; 
            value = data[r * cols + c]; 
            fprintf(f, "%.4f", value); 
        }
    }
}

它没有错误;但是当我编译它时,在文件中我什么都看不到(只有一行代码,但不是整个矩阵)我不知道为什么。

编辑 2:我添加了 \t 和 \n 并且得到了相同的结果

void matrix_fprint(const struct matrix *m, FILE *f) {
    size_t rows = m->rows; 
    size_t cols = m->cols; 
    double* data = m->data; 

    for (size_t r = 0; r < rows; ++r) {
        for (size_t c = 0; c < cols; ++c) {
            double value = 0; 
            value = data[r * cols + c]; 
            fprintf(f, "%.4f\t", value); 
        }
        fprintf(f, "\n"); 
        
    }
    
}

文件上的输出是一样的。

第三次编辑: 希望这是最后一个可重现的例子。

// matrix.h 

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h> 
#include <stdio.h>
struct matrix {
    size_t rows, cols;
    double* data;
};
extern struct matrix* mat_transpose(const struct matrix* mat);

// matrix.c


#include "matrix.h"

void matrix_constructor(struct matrix* mat, size_t rows, size_t cols) {
    mat->rows = rows; mat->cols = cols;
    mat->data = calloc(rows * cols, sizeof(double));
}

struct matrix* mat_transpose(const struct matrix* mat) {
    // allocate the matrix structure
    struct matrix* out = calloc(sizeof(*out), 1);
    if (out == NULL) {
        return NULL;
    }
    // construct the transposed matrix with rows and cols arguments swapped
    matrix_constructor(out, mat->cols, mat->rows);
    if (out->data == NULL) {
        free(out);
        return NULL;
    }
    // set the transposed data
    for (size_t r = 0; r < mat->rows; ++r) {
        for (size_t c = 0; c < mat->cols; ++c) {
            out->data[c * out->rows + r] = mat->data[r * mat->rows + c];
        }
    }
    return out;
}

void matrix_fprint(const struct matrix *m, FILE *f) {
    size_t rows = m->rows; 
    size_t cols = m->cols; 
    double* data = m->data; 

    for (size_t r = 0; r < rows; ++r) {
        for (size_t c = 0; c < cols; ++c) {
            double value = 0; 
            value = data[r * cols + c]; 
            fprintf(f, "%.4f\t", value); 
        }
        fprintf(f, "\n"); 
        
    }
    
}



void matrix_destructor(struct matrix* mat) {
    free(mat->data); 
}



int main(void) {
    struct matrix A; 
    matrix_constructor(&A, 2, 3); 
    A.data[0] = 4.5678; A.data[1] = 78.9876; A.data[2] = 67.9876; 
    A.data[3] = 4.7896; A.data[4] = 2.6789; A.data[5] = 1.1122;
    
    mat_transpose(&A); 
    FILE* f = fopen("matrix transpose.txt", "w"); 
    matrix_fprint(&A, f); 

    matrix_destructor(&A); 
    fclose(f); 
    return 0; 
} 

问题是当我编译代码时,我在文件中读取了原始矩阵(矩阵 A),而不是转置矩阵。

假设:这可能会发生,因为当matrix_transpose 返回值时,它没有分配给任何结构变量。

但是,例如,当我尝试创建 struct matrix B 时,它就无法正常工作。为什么?

【问题讨论】:

  • struct matrix* out; 问问自己,out 指向哪里?
  • 为什么? 你刚刚声明了它,所以你确定它是未初始化的。您需要为其分配一个指向已分配矩阵的有效内存地址。
  • 您需要为out 执行malloc 和matrix_constructor。
  • 您实际上并不需要 out 成为矩阵对象。您可以为数据分配一个缓冲区,并在释放原始缓冲区后将其交换为原始对象
  • 结构矩阵非常小。考虑按值而不是指针传递

标签: c matrix transpose


【解决方案1】:
struct matrix* out; 

这不会初始化一个矩阵,它会将一个指针初始化为一个矩阵。由于指针尚未初始化,它当前指向内存中的某个任意地址。 (这可能是你不拥有的内存!)

这就是编译器给你警告的原因;你(可能)正在编辑你不拥有的内存!

如果要为矩阵分配空间,可以使用malloc from #include &lt;stdlib.h&gt;。

【讨论】:

  • “[I]t 将 指针 初始化为矩阵”具有误导性。这是一个指针变量的定义,但没有没有初始化。变量的值将是indeterminate,应该被视为垃圾。它可能等于NULL,也可能不等于。像这样取消引用无效指针会导致未定义的行为,这通常会导致崩溃,但不能保证。
  • 在大多数情况下,此类未初始化的数据包含垃圾值,有时您可能很幸运能从中得到零。绝对不能保证:您可能会在一次运行中获得零,而在下一次运行中获得垃圾。
  • 是的,没错,那是糟糕的措辞。感谢您清理它。
  • 最好将措辞改为define或create,因为initialize意味着“加载了一些(有效)数据”。它也清除了你一句话“它初始化一个指针”然后“指针还没有被初始化”的冲突。
【解决方案2】:

您需要同时分配matrix 结构和矩阵数据。您可以为此使用matrix_constructor:

struct matrix *mat_transpose(const struct matrix *mat) {
    // allocate the matrix structure
    struct matrix *out = calloc(sizeof(*out), 1);
    if (out == NULL) {
        return NULL; 
    }
    // construct the transposed matrix with rows and cols arguments swapped
    matrix_constructor(out, mat->cols, mat->rows);
    if (out->data == NULL) {
        free(out);
        return NULL;
    }
    // set the transposed data
    for (size_t r = 0; r < mat->rows; ++r) {
        for (size_t c = 0; c < mat->cols; ++c) {
            out->data[c * out->rows + r] = mat->data[r * mat->rows + c]; 
        }
    }
    return out; 
}

【讨论】:

    【解决方案3】:
    1. 在矩阵构造函数的帮助下创建函数

    您的意思可能是“在矩阵构造函数 FUNCTION 的帮助下创建 MATRIX”。


    给定一个矩阵,编写一个函数来转置该矩阵。它必须 返回一个指向该矩阵的指针。

    这是错误的表述和不清楚。有没有第二个矩阵?

    【讨论】:

      猜你喜欢
      • 2020-08-04
      • 2019-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多