矩阵乘法函数结果无法传递至主函数,代码及数组输入问题求助
问题分析与修复方案
你代码里存在两个核心问题:二维数组读取逻辑错误,以及矩阵乘法函数的参数传递和实现完全不符合需求,下面逐个解决:
一、二维数组输入的错误修正
你读取PGM文件和权重文件时,有多处致命错误:
- 数组越界:所有
A[28][28]、C[784][128]、E[128]的写法都越界了——C语言数组下标从0开始,比如float A[28][28]的有效范围是A[0][0]到A[27][27],越界访问会触发未定义行为。 - 读取逻辑混乱:
- 读PGM文件时,你用
while循环逐个读字符,然后嵌套双重循环把整个数组赋值为当前字符,这会导致所有元素被最后一个字符覆盖。正确的做法是按顺序逐个填充数组元素。 - 归一化步骤中,你错误地用
A[28][2]的值覆盖所有元素,应该对每个A[i][j]自身做/255.0的归一化。 - 读
W1.txt和B1.txt时,同样重复覆盖数组,没有正确读取全部数据。
- 读PGM文件时,你用
二、矩阵乘法结果传递的问题解决
你的矩阵乘法函数完全无法实现需求,问题包括:
- 参数类型错误:原函数
Matrix(float matA,float matB, float *matC)的参数不能接收数组,只是传了单个越界元素(比如B[784]是超出数组范围的)。需要传递数组首地址和矩阵维度。 - 内部逻辑全错:
- 内部定义的
double matA[a][b]用了未初始化的a、b、c,都是垃圾值,还和参数重名,完全无效。 - 矩阵乘法逻辑错误:矩阵乘法是行乘列累加,不是对应元素相乘;而且
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; }
关键说明
- PGM文件读取:正确处理了PGM文件的格式头(跳过注释、尺寸等信息),按顺序读取每个像素值,避免了数组覆盖问题。
- 矩阵乘法实现:通过传递数组首地址直接修改结果数组,实现了正确的行乘列累加逻辑,明确了矩阵维度(1x784 × 784x128)。
- 权重文件读取:假设
W1.txt和B1.txt是二进制存储的float数据,用fread批量读取效率更高;如果是文本格式,可替换为fscanf逐个读取。
内容的提问来源于stack exchange,提问作者EricACE
相关产品推荐
相关产品推荐

