【发布时间】: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成为矩阵对象。您可以为数据分配一个缓冲区,并在释放原始缓冲区后将其交换为原始对象 -
结构矩阵非常小。考虑按值而不是指针传递