【发布时间】:2019-07-10 09:49:50
【问题描述】:
我正在尝试将存储在一个文件中的两个矩阵相乘:
1 2 2 3 * -4 1 1 0我最初不知道每个矩阵的维数是多少。但我让用户定义它,否则将采用默认值100。
int maxc = argc > 2 ? atoi(argv[2]) * atoi(argv[2]) : 100;
我已经可以正确执行计算,但我注意到如果我输入维度argv[2] = "2" 以便maxc = 8,(对于本示例来说应该足够了),读取或打印文件时会产生错误.但是如果我输入 argv[2] = "3" 这个例子一切正常。由于maxc 用于在此处分配内存:matrix = malloc(maxc * sizeof *matrix),我怀疑问题可能出在该行。我也应该为size_t row; size_t col; 分配内存吗?
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#define MAXNOP 50 /*Max number of operations allowed */
#define MAXNMATR 20 /*Max number of matrices */
struct m {
size_t row;
size_t col;
double *data;
};
struct m multiply(struct m *A, struct m *B);
void f(double x);
void print_matrix(struct m *A);
void read_file(int maxc, FILE *fp);
void scalar_product(double scalar, struct m *B);
void calculate(struct m *matrix, int nop, int id, char *op);
int main(int argc, char *argv[]) {
FILE *file = argc > 1 ? fopen(argv[1], "rb") : stdin;
/* define max dimension of a matrix */
int maxc = argc > 2 ? atoi(argv[2]) * atoi(argv[2]) : 100;
read_file(maxc, file);
return 0;
}
void read_file(int maxc, FILE *fp) {
struct m *matrix;
int id = 0; /* id of a matrix */
size_t ncol, nrow; /* No of columns of a matrix*/
ncol = nrow = 0;
int nop = 0; /*No of operators*/
int off = 0;
int i;
int n;
double *d;
char buf[2 * maxc]; /*to store each lines of file */
char *p = buf;
char op[MAXNOP];
for (i = 0; i < MAXNOP; i++)
op[i] = '?';
if (!(matrix = malloc(maxc * sizeof *matrix))) {
perror("malloc-matrix");
exit(1);
}
/* Read file line by line */
while (fgets(buf, maxc, fp)) {
if (nrow == 0) {
/* allocate/validate max no. of matrix */
d = matrix[id].data = malloc(sizeof(double) * MAXNMATR);
}
/* check if line contains operator */
if ((!isdigit(*buf) && buf[1] =='\n')) {
op[nop++] = *buf;
matrix[id].col = ncol;
matrix[id].row = nrow;
nrow = ncol = 0;
id++;
continue;
} else {
/* read integers in a line into d */
while (sscanf(p + off, "%lf%n", d, &n) == 1) {
d++;
if (nrow == 0)
ncol++;
off += n;
}
nrow++;
off = 0;
}
} /*end of while fgets cycle */
/* Assign last matrix No of columns and rows */
matrix[id].col = ncol;
matrix[id].row = nrow;
/* Printing the matrices and operations */
for (i = 0; i <= id; i++) {
if (op[i] == '*' || op[i] == '-' || op[i] =='+') {
print_matrix(&matrix[i]);
if (op[i-1] != 'i')
printf("%c\n", op[i]);
else
continue;
} else
if (op[i] == '?') {
print_matrix(&matrix[i]);
}
}
calculate(matrix, nop, id, op);
}
void calculate(struct m *matrix, int nop, int id, char *op) {
int i;
for (i = 0; i <= nop; i += 2) {
if (op[i] == '*' && op[i+1] == '?') {
if (matrix[i].row == 1 && matrix[i].col == 1)
scalar_product(matrix[i].data[0], &matrix[i + 1]); //Multiplication of Scalar per matrix
else {
matrix[i + 1] = multiply(&matrix[i], &matrix[i + 1]);
matrix[i + 2] = multiply(&matrix[i + 1], &matrix[i + 2]);
}
break;
}
}
printf("=\n");
print_matrix(&matrix[id]); /* Print the result */
free(matrix);
}
struct m multiply(struct m *A, struct m *B) {
size_t i, j, k;
struct m C;
C.data = malloc(sizeof(double) * A->row * B->col);
C.row = A->row;
C.col = B->col;
for (i = 0; i < C.row; i++)
for (j= 0 ; j < C.col; j++)
C.data[i * C.col + j] = 0;
// Multiplying matrix A and B and storing in C.
for (i = 0; i < A->row; ++i)
for (j = 0; j < B->col; ++j)
for (k = 0; k < A->col; ++k)
C.data[i * C.col + j] += A->data[i * A->col + k] * B->data[k * B->col + j];
return C;
}
void f(double x) {
double i, f = modf(x, &i);
if (f < .00001)
printf("%.f ", i);
else
printf("%f ", x);
}
/* printing a Matrix */
void print_matrix(struct m *A) {
size_t i, j;
double *tmp = A->data;
for (i = 0; i < A->row; i++) {
for (j = 0; j < A->col; j++) {
f(*(tmp++));
}
putchar('\n');
}
}
void scalar_product(double scalar, struct m *B) {
size_t i, j;
for (i = 0; i < B->row; i++)
for (j = 0; j < B->col; j++)
B->data[i * B->col + j] = scalar * B->data[i * B->col + j];
}
预期结果是这样的:https://ideone.com/Z7UtiR
此处argv[2] 未被读取,因此有足够的内存来存储所有数据。
【问题讨论】:
-
如果您只是在调试器中逐行执行代码,这应该很容易弄清楚。并且知道
fgets是如何工作的。
标签: c malloc out-of-memory