You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

矩阵乘法函数结果无法传递至主函数,代码及数组输入问题求助

问题分析与修复方案

你代码里存在两个核心问题:二维数组读取逻辑错误,以及矩阵乘法函数的参数传递和实现完全不符合需求,下面逐个解决:

一、二维数组输入的错误修正

你读取PGM文件和权重文件时,有多处致命错误:

  • 数组越界:所有A[28][28]、C[784][128]、E[128]的写法都越界了——C语言数组下标从0开始,比如float A[28][28]的有效范围是A[0][0]到A[27][27],越界访问会触发未定义行为。
  • 读取逻辑混乱:
    1. 读PGM文件时,你用while循环逐个读字符,然后嵌套双重循环把整个数组赋值为当前字符,这会导致所有元素被最后一个字符覆盖。正确的做法是按顺序逐个填充数组元素。
    2. 归一化步骤中,你错误地用A[28][2]的值覆盖所有元素,应该对每个A[i][j]自身做/255.0的归一化。
    3. 读W1.txt和B1.txt时,同样重复覆盖数组,没有正确读取全部数据。

二、矩阵乘法结果传递的问题解决

你的矩阵乘法函数完全无法实现需求,问题包括:

  • 参数类型错误:原函数Matrix(float matA,float matB, float *matC)的参数不能接收数组,只是传了单个越界元素(比如B[784]是超出数组范围的)。需要传递数组首地址和矩阵维度。
  • 内部逻辑全错:
    1. 内部定义的double matA[a][b]用了未初始化的a、b、c,都是垃圾值,还和参数重名,完全无效。
    2. 矩阵乘法逻辑错误:矩阵乘法是行乘列累加,不是对应元素相乘;而且while(count < a*c)没有递增count,会无限循环。
  • 调用方式错误:Matrix是void类型,不能赋值给D[128],而且传递的参数不是数组地址,是越界元素。

修正后的完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 矩阵乘法:一维数组A(1x784) 乘 二维数组B(784x128),结果存入一维数组C(1x128)
void MatrixMultiply(const float *A, const float B[784][128], float *C) {
    int i, j;
    // 初始化结果数组为0
    memset(C, 0, sizeof(float) * 128);
    // 矩阵乘法:行A 乘 列B,累加
    for (i = 0; i < 128; i++) {
        for (j = 0; j < 784; j++) {
            C[i] += A[j] * B[j][i];
        }
    }
}

int main(int argc, char* argv[]) {
    char filename[100];
    float A[28][28];
    FILE *fp;

    printf("please input filenames: ");
    scanf("%s", filename);
    fp = fopen(filename, "rb");
    if (fp == NULL) {
        printf("invalid file.\n");
        return 1; // 文件打开失败直接退出
    }

    // 跳过PGM文件头(兼容P5格式,处理注释、尺寸、最大灰度值)
    char skip[100];
    // 跳过格式标识P5
    fgets(skip, sizeof(skip), fp);
    // 跳过注释行
    while (fgetc(fp) == '#') {
        fgets(skip, sizeof(skip), fp);
    }
    fseek(fp, -1, SEEK_CUR); // 回退到注释行前的有效字符
    // 读取图像尺寸(这里固定28x28,也可动态适配)
    int width, height, max_val;
    fscanf(fp, "%d %d %d", &width, &height, &max_val);
    fgetc(fp); // 跳过换行符

    // 读取像素数据到二维数组
    int i, j;
    for (i = 0; i < 28; i++) {
        for (j = 0; j < 28; j++) {
            unsigned char pixel = fgetc(fp);
            A[i][j] = (float)pixel;
        }
    }
    fclose(fp);

    // 归一化到0-1区间
    for (i = 0; i < 28; i++) {
        for (j = 0; j < 28; j++) {
            A[i][j] /= 255.0f;
        }
    }

    // 转换为一维数组B(784元素)
    float B[784];
    int k = 0;
    for (i = 0; i < 28; i++) {
        for (j = 0; j < 28; j++) {
            B[k++] = A[i][j];
        }
    }

    // 读取权重矩阵W1(784x128),假设为二进制存储的float数据
    FILE *W = fopen("W1.txt", "rb");
    if (W == NULL) {
        printf("Failed to open W1.txt\n");
        return 1;
    }
    float C[784][128];
    fread(C, sizeof(float), 784*128, W);
    fclose(W);

    // 执行矩阵乘法,结果存入D(128元素)
    float D[128];
    MatrixMultiply(B, C, D);

    // 读取偏置B1(128元素)
    FILE *B1 = fopen("B1.txt", "rb");
    if (B1 == NULL) {
        printf("Failed to open B1.txt\n");
        return 1;
    }
    float E[128];
    fread(E, sizeof(float), 128, B1);
    fclose(B1);

    // 计算输出F = D + E
    float F[128];
    for (i = 0; i < 128; i++) {
        F[i] = D[i] + E[i];
        // 可选:打印结果验证
        // printf("F[%d] = %.4f\n", i, F[i]);
    }

    return 0;
}

关键说明

  1. PGM文件读取:正确处理了PGM文件的格式头(跳过注释、尺寸等信息),按顺序读取每个像素值,避免了数组覆盖问题。
  2. 矩阵乘法实现:通过传递数组首地址直接修改结果数组,实现了正确的行乘列累加逻辑,明确了矩阵维度(1x784 × 784x128)。
  3. 权重文件读取:假设W1.txt和B1.txt是二进制存储的float数据,用fread批量读取效率更高;如果是文本格式,可替换为fscanf逐个读取。

内容的提问来源于stack exchange,提问作者EricACE

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 20:15:29