文章目录

    • 题目
    • 参考答案
    • 解题思路
    • 错点
    • 无函数做法

题目

编写程序计算两个矩阵的乘积,请将以下代码复制到codeblocks中,将multiply函数补充完整,程序运行正确后将所有代码(包括题目中给出的代码)复制到答题区内运行并提交。
#include <stdio.h>
#define M 3
#define S 4
#define N 2

void multiply(int A[M][S], int B[S][N], int C[M][N])
{

}

int main()
{
int i, j;
int A[M][S], B[S][N], C[M][N];
printf(“Please input A:\n”);
for (i = 0; i < M; i ++)
for (j = 0; j < S; j ++)
scanf("%d", &A[i][j]);
printf(“Please input B:\n”);
for (i = 0; i < S; i ++)
for (j = 0; j < N; j ++)
scanf("%d", &B[i][j]);
multiply(A,B,C);
printf(“C=\n”);
for (i = 0; i < M; i ++){
for (j = 0; j < N; j ++)
printf("%d “, C[i][j]);
printf(”\n");
}
return 0;
}
程序运行示例:
Please input A:
1 2 3 4
5 6 7 8
4 7 9 2
Please input B:
2 6
4 8
4 6
3 9
C=
34 76
86 192
78 152

参考答案

#include <stdio.h>
#define M 3
#define S 4
#define N 2

void multiply(int A[M][S], int B[S][N], int C[M][N])
{
    int i, j, k;
    for (i = 0; i < M; i++) //用于控制C和A的行标
    {
        for (j = 0; j < N; j++) //用于控制C和B的列标
        {
            for (k = 0; k < S; k++)  //用于控制A的列标和B的行标
            {
                C[i][j] += A[i][k] * B[k][j];
            }
        }
    }
}
int main()
{
    int i, j;
    int A[M][S], B[S][N], C[M][N] = {0}; //必须对C数组进行初始化
    printf("Please input A:\n");
    for (i = 0; i < M; i++)
        for (j = 0; j < S; j++)  //输入A数组
            scanf_s("%d", &A[i][j]);
    printf("Please input B:\n");
    for (i = 0; i < S; i++)
        for (j = 0; j < N; j++)  //输入B数组
            scanf_s("%d", &B[i][j]);
    multiply(A, B, C);  //调用函数
    printf("C=\n");
    for (i = 0; i < M; i++)
    {
        for (j = 0; j < N; j++)
            printf("%d ", C[i][j]);  //以矩阵的形式输出C数组
        printf("\n");
    }
    return 0;
}

解题思路

只需要写出计算C数组的前三个式子就可发现规律:

  • C[0][0]= A[0][0] * B[0][0] + A[0][1] * B[1][0] + A[0][2] * B[2][0] + A[0][3] * B[3][0]
  • C[0][1]= A[0][0] * B[0][1] + A[0][1] * B[1][1] + A[0][2] * B[2][1] + A[0][3] * B[3][1]
  • C[1][0]= A[1][0] * B[0][0] + A[1][1] * B[1][0] + A[1][2] * B[2][0] + A[1][3] * B[3][0]
    则可以发现:C和A的行标同时变化,C和B的列标同时变化,A的列标和B的行标同时变化。
    在计算过程中:最先进行循环的是A列标和B行标的变化,所以该循环放在最里面,而外层的两个循环可用于控制C的行列标运动。
    (上述为先算C数组每一行的做法,也可以改变循环的过程,先算第一列,再算第二列)

错点

在写这道题的过程中,我遇到的问题有两个:

  1. 在编写函数时,若未找对规律,容易发生数组下标越界的问题,虽然会有数值写入C数组中,但是数值错误,且会有运行错误,如下:
void multiply(int A[M][S], int B[S][N], int C[M][N])
{
    int i, j, k;
    for (i = 0; i < S; i++)
    {
        for (j = 0; j < N; j++)
        {
            for (k = 0; k < M; k++)
            {
                C[i][j] = A[i][k] + B[k][j];
            }
        }
    }
}

如上,存在逻辑错误,会将C[M][N]以C[S][N]的形式来计算,而A和B也会有同样的错误,在VS2019中会有变量堆栈被破坏之类的错误。

Run-Time Check Failure #2 - Stack around the variable 'B' was corrupted.

  1. 数组C未初始化引起的答案错误:
C=
-858993426 -858993384
-858993374 -858993268  //出现的值全部为随机值
-858993382 -858993308

起初会认为是函数的问题,但并非如此。
细节虽小,但很重要!!!

无函数做法

#include <stdio.h>
#define M 3
#define S 4
#define N 2

int main()
{
    int i, j, k;
    int A[M][S], B[S][N], C[M][N] = {0};  //初始化很重要
    printf("Please input A:\n");
    for (i = 0; i < M; i++)
        for (j = 0; j < S; j++)
            scanf_s("%d", &A[i][j]);
    printf("Please input B:\n");
    for (i = 0; i < S; i++)
        for (j = 0; j < N; j++)
            scanf_s("%d", &B[i][j]);
    for (i = 0; i < M; i++)
    {
        for (j = 0; j < N; j++)
        {
            for (k = 0; k < S; k++)
            {
                C[i][j] += A[i][k] * B[k][j];
            }
        }
    }
    printf("C=\n");
    for (i = 0; i < M; i++) {
        for (j = 0; j < N; j++)
            printf("%d ", C[i][j]);
        printf("\n");
    }
    return 0;
}


更多推荐

编写程序计算两个矩阵的乘积,请将以下代码复制到codeblocks中,将multiply函数补充完整,程序运行正确后将所有代码(包括题目中给出的代码)复制到答题