嘿大家所以我正在使用指针制作矩阵乘数我已经撞到了墙。到目前为止,我已经做到了,现在已经遇到了障碍。
我的问题:在生成尺寸3x3或更大(2x2和1x1返回正确值)的矩阵时,生成的矩阵返回的值太大。
这是已编辑的代码:
#include <stdio.h>
#include <stdlib.h>
#include<conio.h>
void main() {
int i, j, k, m, n, p, q, m1_rows, m1_cols, m2_rows, m2_cols, mr_rows, mr_cols;
double **m1, **m2, **mr;
printf("Enter number of rows and columns of 1st matrix:");
scanf("%d%d",&m,&n);
printf("Enter number of rows and columns of 2nd matrix:");
scanf("%d%d",&p,&q);
if(n!=p) printf("Not possible");
else {
m1 = malloc(sizeof(double *) * m1_rows);
for(int i=0; i < m1_rows; i++) m1[i] = malloc(sizeof(double) * m1_cols);
m2 = malloc(sizeof(double *) * m2_rows);
for(int i=0; i < m2_rows; i++) m2[i] = malloc(sizeof(double) * m2_cols);
mr = malloc(sizeof(double *) * mr_rows);
for(int i=0; i < mr_rows; i++) mr[i] = malloc(sizeof(double) * mr_cols);
printf("Enter 1st matrix values:");
for(i=0;i<m1_rows;i++) {
for(j=0;j<m1_cols;j++) {
scanf("%d",(&m1[i][j]));
}
}
printf("Enter 2nd matrix values:\n");
for(i=0;i<m2_rows;i++) for(j=0;j<m2_cols;j++) scanf("%d",(*(m2+i)+j));
printf("First matrix is:\n");
for(i=0;i<m1_rows;i++) {
printf("\n");
for(j=0;j<m1_cols;j++) printf("%d\t",*(*(m1+i)+j)); }
printf("\nSecond matrix is:\n");
for(i=0;i<m2_rows;i++) {
printf("\n");
for(j=0;j<m2_cols;j++) printf("%d\t",*(*(m2+i)+j)); }
for(i=0;i<m1_rows;i++) {
for(j=0;j<m2_cols;j++) {
*(*(mr+i)+j) = 0;
}
}
}
getch();
return 0;
}
答案 0 :(得分:1)
主要问题是您尝试仅使用单个维度分配二维数据结构,但仍使用二维类型(指向指针的指针)。如果您更改代码以使用数组索引语法,例如
,那么您是多么错误*(m1+i)+j
将是
&m1[i][j]
使用数组索引语法,您应该看到您实际上没有分配第二个维度。你为它分配了空间,但它根本不起作用,因为二维数组的内存布局与使用指针指针的二维数组的布局不同。
为了进一步解释数组数组(所有数据都在一个连续的块中)和指向指针的指针之间的区别,请参见下图:
例如声明
double a[2][2];
内存布局为
+---------+---------+---------+---------+ | a[0][0] | a[0][1] | a[1][0] | a[1][1] | +---------+---------+---------+---------+
但如果你使用例如指向指针的指针:
double **a;
然后经过适当的分配,它看起来像这个
+------+------+-----+ | a[0] | a[1] | ... | +------+------+-----+ | | | V | +---------+---------+-----+ | | a[1][0] | a[1][1] | ... | | +---------+---------+-----+ V +---------+---------+-----+ | a[0][0] | a[0][1] | ... | +---------+---------+-----+
希望您现在应该了解为什么,在您的情况下,m1[x]
(对于任何x
)会导致undefined behavior,因为它是未初始化的指针。
这个问题的简单解决方案?只需做两个分配:一个用于&#34;行&#34;一个用于&#34;列&#34;。
像
m1 = malloc(sizeof(double *) * m1_rows);
for (int i = 0; i < m1_rows; ++i)
m1[i] = malloc(sizeof(double) * m1_columns);
答案 1 :(得分:0)
首先:
double
使用%f
。 %d
适用于int
。double
使用%lf
进行扫描。 %d
适用于int
。答案 2 :(得分:0)
1)变量m1_rows
,m1_cols
,m2_rows
,m2_cols
,mr_rows
和mr_cols
未初始化,但您使用它在内存分配期间。
2)对于双数据类型,请使用%f
或%lf
。 %d
用于int。
3)您没有执行任何矩阵乘法,因此需要执行矩阵乘法并打印结果。
4)为指针分配内存后,不要忘记释放指针。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, j, k, m, n, p, q, m1_rows, m1_cols, m2_rows, m2_cols, mr_rows, mr_cols;
double **m1, **m2, **mr;
printf("Enter number of rows and columns of 1st matrix:");
scanf("%d%d",&m,&n);
printf("Enter number of rows and columns of 2nd matrix:");
scanf("%d%d",&p,&q);
// m1_rows, m1_cols, m2_rows, m2_cols, mr_rows and mr_cols are not initialized, however you are using it during memory allocation
m1_rows = m;
m1_cols = n;
m2_rows = p;
m2_cols = q;
mr_rows = m;
mr_cols = q;
if(n!=p) printf("Not possible");
else
{
m1 = malloc(sizeof(double *) * m1_rows);
for(i=0; i < m1_rows; i++) m1[i] = malloc(sizeof(double) * m1_cols);
m2 = malloc(sizeof(double *) * m2_rows);
for(i=0; i < m2_rows; i++) m2[i] = malloc(sizeof(double) * m2_cols);
mr = malloc(sizeof(double *) * mr_rows);
for(i=0; i < mr_rows; i++) mr[i] = malloc(sizeof(double) * mr_cols);
printf("Enter 1st matrix values:");
for(i=0;i<m1_rows;i++)
{
for(j=0;j<m1_cols;j++)
{
scanf("%lf",&m1[i][j]);
}
}
printf("Enter 2nd matrix values:\n");
for(i=0;i<m2_rows;i++)
{
for(j=0;j<m2_cols;j++)
{
scanf("%lf",&m2[i][j]);
}
}
printf("First matrix is:\n");
for(i=0;i<m1_rows;i++)
{
printf("\n");
for(j=0;j<m1_cols;j++)
{
printf("%.2lf\t",*(*(m1+i)+j));
}
}
printf("\nSecond matrix is:\n");
for(i=0;i<m2_rows;i++)
{
printf("\n");
for(j=0;j<m2_cols;j++)
{
printf("%.2lf\t",*(*(m2+i)+j));
}
}
//Matrix multiplication
for(i=0;i<m1_rows;i++)
{
for(j=0;j<m2_cols;j++)
{
mr[i][j] = 0;
for(k=0;k<m1_cols;k++)
{
mr[i][j] = mr[i][j]+m1[i][k] * m2[k][j];
}
}
}
//Print the result
printf("\nResult matrix is:\n");
for(i=0;i<mr_rows;i++)
{
printf("\n");
for(j=0;j<mr_cols;j++)
{
printf("%.2lf\t",mr[i][j]);
}
}
//Free the allocated memory
for(i=0;i<m1_rows;i++)
{
free(m1[i]);
}
free(m1);
for(i=0;i<m2_rows;i++)
{
free(m2[i]);
}
free(m2);
for(i=0;i<mr_rows;i++)
{
free(mr[i]);
}
free(mr);
}
printf("\n");
return 0;
}
答案 3 :(得分:0)
这是一个快速尝试,展示了实现逻辑的方法。正如评论中所示,一个问题是代码中无数的单元化变量。如果可能,请勿以不同的名称复制变量 - 这只会打开其他可能的错误。如果您有疑问,请告诉我。 (我保留了你的指针等价:m1[i][j] = *(*(m1+i)+j)
只是为了表明它们是可以互换的):
#include <stdio.h>
#include <stdlib.h>
int main () {
int c, i = 0, j = 0, m = 0, n = 0, p = 0, q = 0;
double **m1, **m2, **mr;
printf ("Enter number of rows and columns of 1st matrix: ");
scanf ("%d %d", &m, &n);
do { c = getchar (); } while (c != '\n' && c != EOF); /* flush input buffer */
printf ("Enter number of rows and columns of 2nd matrix: ");
scanf ("%d %d", &p, &q);
do { c = getchar (); } while (c != '\n' && c != EOF); /* flush input buffer */
if (n != p)
printf ("Not possible\n");
else {
m1 = malloc (sizeof (double *) * m);
for (int i = 0; i < m; i++)
m1[i] = calloc (n, sizeof (double)); /* use calloc to 0 elements */
m2 = malloc (sizeof (double *) * p);
for (int i = 0; i < p; i++)
m2[i] = calloc (q, sizeof (double)); /* use calloc to 0 elements */
mr = malloc (sizeof (double *) * m);
for (int i = 0; i < m; i++)
mr[i] = calloc (q, sizeof (double)); /* use calloc to 0 elements */
printf ("Enter 1st matrix values:\n");
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
printf (" m1[%d][%d]: ", i, j);
scanf ("%lf", &m1[i][j]);
do { c = getchar (); } while (c != '\n' && c != EOF); /* flush input buffer */
}
}
printf ("Enter 2nd matrix values:\n");
for (i = 0; i < p; i++)
for (j = 0; j < q; j++) {
printf (" m1[%d][%d]: ", i, j);
scanf ("%lf", &(*(*(m2 + i))));
do { c = getchar (); } while (c != '\n' && c != EOF); /* flush input buffer */
}
printf ("\nFirst matrix is:\n");
for (i = 0; i < m; i++) {
printf ("\n");
for (j = 0; j < n; j++)
printf ("%lf\t", *(*(m1 + i) + j));
}
printf ("\n\nSecond matrix is:\n");
for (i = 0; i < p; i++) {
printf ("\n");
for (j = 0; j < q; j++)
printf ("%lf\t", *(*(m2 + i) + j));
}
printf ("\n");
/* THIS FREES NOTHING - allocate with calloc or use memset to 0 */
// for(i=0;i<m;i++) {
// for(j=0;j<q;j++) {
// *(*(mr+i)+j) = 0;
// }
// }
printf ("\nFree First matrix\n");
for (i = 0; i < m; i++) {
if (*(m1 + i))
free (*(m1 + i));
}
if (m1)
free (m1);
printf ("Free Second matrix\n");
for (i = 0; i < p; i++) {
if (*(m2 + i))
free (*(m2 + i));
}
if (m2)
free (m2);
printf ("Free Result matrix\n\n");
for (i = 0; i < m; i++) {
if (*(mr + i))
free (*(mr + i));
}
if (mr)
free (mr);
}
return 0;
}
<强>构建强>
注意:始终至少使用-Wall -Wextra
进行构建,以识别代码中的问题。
gcc -Wall -Wextra -Wno-sign-compare -Wno-long-long -std=c99 -o bin/badmtrx badmtrx.c
<强>输出:强>
$ ./bin/badmtrx
Enter number of rows and columns of 1st matrix: 1 3
Enter number of rows and columns of 2nd matrix: 3 1
Enter 1st matrix values:
m1[0][0]: 1
m1[0][1]: 2
m1[0][2]: 3
Enter 2nd matrix values:
m1[0][0]: 4
m1[1][0]: 5
m1[2][0]: 6
First matrix is:
1.000000 2.000000 3.000000
Second matrix is:
4.000000
5.000000
6.000000
Free First matrix
Free Second matrix
Free Result matrix
valgrind堆摘要:
==10711== HEAP SUMMARY:
==10711== in use at exit: 0 bytes in 0 blocks
==10711== total heap usage: 8 allocs, 8 frees, 96 bytes allocated
==10711==
==10711== All heap blocks were freed -- no leaks are possible
==10711==
==10711== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
--10711--
--10711-- used_suppression: 2 dl-hack3-cond-1
==10711==
==10711== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)