我正在尝试编写一个C程序来计算MN,其中M是一个方阵,N是一个整数。但是,每次我输入N的值后,它都会崩溃。有人能识别出它的问题吗?我想这是关于指针的问题,但我不明白需要对它们做什么修改。任何帮助都将非常感激。
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
double *multiply(int M, double **A, double **B) {
double **C = (double **)malloc(M * sizeof(double));
for (int i = 0; i < M; i++) {
C[i] = (double *)malloc(M * sizeof(double));
}
for (int i = 0; i < M; i++) {
for (int j = 0; j < M; j++) {
for (int k = 0; k < M; k++) {
C[i][j] += A[i][k] * B[k][j];
}
}
}
return *C;
}
void arrcpy(int M, double **A, double **B) {
for (int i = 0; i < M; i++) {
for (int j = 0; j < M; j++) {
A[i][j] = B[i][j];
}
}
return;
}
int main() {
int i, j, N, M;
printf("M = ");
scanf("%d", &M);
double **R = (double **)malloc(M * sizeof(double));
for (i = 0; i < M; i++) {
R[i] = (double *)malloc(M * sizeof(double));
}
for (i = 0; i < M; i++) {
for (j = 0; j < M; j++) {
printf("R[%d][%d] = ", i, j);
scanf("%lf", &R[i][j]);
}
}
printf("N = ");
scanf("%d", &N);
double **C;
arrcpy(M, C, R);
for (i = 1; i < N; i++) {
*C = multiply(M, C, R);
}
for (i = 0; i < M; i++) {
for (j = 0; j < M; j++) {
printf("%lf ", C[i][j]);
}
printf("\n");
}
return 0;
}
4条答案
按热度按时间dba5bblo1#
在我看来,最好的方法是实现fast exponentiation algorithm,如下面的代码所示。
显示的代码允许您使用特殊类型的矩阵,每个矩阵只需要一个
malloc()
调用(我不会用代码中的问题来打扰你,这些问题已经在其他答案中得到了回答)矩阵(我提供了m_rows
和m_cols
字段,以便能够保存矩形矩阵,而实现的重点是要解决的问题,其是矩阵幂提升)存储在存储器的单个块中,所述存储器的单个块包括用于struct matrix
本身、行阵列的指针以及行本身的空间(应该没有对准问题,因为所有的块都已经使用指针算法被适当地寻址)。它通过移动两个适当类型的指针将指针初始化到适当的位置(一个double
指针用于移动到下一单元以初始化单元,而另一个double *
指针用于移动到下一行,用于初始化指向行的指针)* 提供程序函数 * 的集合(所有前缀为prov_
的)允许您使用相同的例程以多种不同的方式初始化矩阵。如果提供NULL
作为提供程序,则不会执行单元格初始化(例如在矩阵乘法中,初始化是由乘积例程完成的)。学习它,因为它非常快。我已经实现了矩阵创建例程(对返回值的单个free()调用就足以释放整个矩阵)和用于添加、初始化的操作(以多种方式(从一个文件、从一个数组、从一个
FILE *
流,......其中有些在程序中没有使用,但是无论如何都是为了说明使用提示而提供的),因此您可能会将其用作参考实现。示例代码使用了一个样本矩阵,并测试了特征多项式应用于矩阵时会产生零矩阵。对于测试用例,使用快速取幂的方法没有用,因为我们需要使用从0到4的所有幂,但无论如何都要使用mat_pow()
例程来演示它是如何工作的。yeotifhr2#
@tshiono给出的答案已经指出了OP代码中的一些问题,比如
C
未初始化使用、错误的动态分配等。这个答案将建议一种替代的内存分配方法。
OP使用的方法是一个M个指针的数组,其中每个指针指向一个M个双精度数组。这种方法要求首先通过一个
malloc
调用分配M个指针的数组,然后为每个双精度数组分配一个malloc
循环。也就是说,M+1个malloc
调用用于单个矩阵。通过将矩阵变量声明为一个指向M个double的数组的指针,可以将其简化为一个
malloc
。同样,释放此类型的对象将只需要一次
free
调用,而不是M+1次调用。另一个好处是矩阵将存储在一个连续的内存块中。这允许使用
memcpy
复制矩阵,而不是编写自定义函数。这可能类似于:
在上面的代码中,乘法的结果以
T
结尾,然后复制到C
以供下一次循环迭代,这有点烦人。我们可以通过更改以下内容来避免这种情况:至
有点复杂,但它避免了循环内的
memcpy
。uqxowvwt3#
请尝试以下操作:
arrcpy(M,C,R)
,其中矩阵C尚未分配。double **R = malloc(M * sizeof(double))
应该是double **R = malloc(M * sizeof(double *))
,尽管前者恰好可以工作。fgets()
和sscanf()
而不是scanf()
,以便对不规则输入具有鲁棒性。0qx6xfy64#