C语言从stdin txt文件读取不同行列、数据类型矩阵的问题求助
问题分析与解决方案
一、现有代码的错误点
- 变量
i未初始化:定义int i后没有赋值为0,初始值为栈内存的随机垃圾值,第一次访问input[i]就属于越界访问,触发未定义行为。 - 重复调用
scanf:while判断条件中已经调用一次scanf读取了一个值,循环体内又调用一次scanf,每次循环会直接丢弃第一次读取的值,仅保留第二次的读取结果。 - 未处理分隔符:输入的数字之间用逗号分隔,
%lf格式符仅能识别数字和空白字符,遇到逗号就会匹配失败,导致后续所有读取操作失效。
二、基础读取逻辑修复
你可以先运行以下测试代码验证读取逻辑,已经适配逗号分隔的输入格式:
#include <stdio.h> int main() { double input[100]; int i = 0; // 格式符前面的空格跳过所有空白,%*c跳过读取到数字后的逗号/换行等分隔符 while (i < 100 && scanf(" %lf%*c", &input[i]) == 1) { printf("%.2lf \n", input[i]); i++; } return 0; }
三、未知行列矩阵的完整实现方案
核心思路
- 逐行读取输入内容,拆分每行的数字元素,第一行拆分出的元素数量即为矩阵列数
- 使用动态内存分配存储矩阵元素,通过
realloc动态扩展数组容量,适配任意大小的矩阵 - 每成功读取一行,行数累加,最终返回动态分配的矩阵数组、行数、列数
完整函数实现
#include <stdio.h> #include <stdlib.h> #include <string.h> // 返回值:0 读取成功,-1 读取失败 // out_mat: 输出参数,返回动态分配的一维矩阵数组(行优先存储) // out_rows: 输出参数,返回矩阵行数 // out_cols: 输出参数,返回矩阵列数 int readMatrix(double **out_mat, int *out_rows, int *out_cols) { char *line = NULL; size_t line_buf_size = 0; ssize_t line_len; double *mat = NULL; int rows = 0, cols = 0, total_elems = 0, cap = 0; const int BLOCK_SIZE = 64; // 每次扩容的元素数量 while ((line_len = getline(&line, &line_buf_size, stdin)) != -1) { char *ptr = line; int line_elems = 0; double val; int offset; // 拆分当前行的所有数字 while (sscanf(ptr, " %lf%n", &val, &offset) == 1) { // 数组容量不足则扩容 if (total_elems >= cap) { cap += BLOCK_SIZE; double *tmp = realloc(mat, cap * sizeof(double)); if (!tmp) { free(mat); free(line); return -1; } mat = tmp; } mat[total_elems++] = val; line_elems++; ptr += offset; // 跳过逗号分隔符 while (*ptr == ',' || *ptr == ' ' || *ptr == '\t') ptr++; } if (line_elems == 0) continue; // 跳过空行 // 第一行确定列数 if (rows == 0) { cols = line_elems; } else if (line_elems != cols) { // 行列数不匹配,非法矩阵 free(mat); free(line); return -1; } rows++; } free(line); if (rows == 0 || cols == 0) { free(mat); return -1; } *out_mat = mat; *out_rows = rows; *out_cols = cols; return 0; } // 使用示例 int main() { double *mat; int rows, cols; if (readMatrix(&mat, &rows, &cols) == 0) { printf("读取成功,矩阵行数:%d,列数:%d\n", rows, cols); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { printf("%.2lf ", mat[i * cols + j]); } printf("\n"); } free(mat); // 使用完释放内存 } else { printf("读取失败\n"); } return 0; }
四、后续功能实现提示
- 矩阵转置:可以新分配一个
cols * rows大小的数组,将原数组i*cols + j位置的元素赋值到新数组j*rows + i位置即可 - 矩阵乘法:若A矩阵为m行k列,B矩阵为k行n列,结果C矩阵为m行n列,
C[i][j] = sum(A[i][t] * B[t][j]),t从0到k-1,按行优先索引转换即可计算。
内容的提问来源于stack exchange,提问作者celo
相关产品推荐
相关产品推荐

