我想执行A * B + C之类的矩阵运算。从这样格式化的文件中读取矩阵:
1 3 4 5 0 1 0 6 0 0 1 7 2 7 0 1 * 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 * 1 2 3 4
我已经可以阅读矩阵和运算符,但我不知道如何执行运算。假设您拥有:A B + C,所以您必须首先执行(A B),然后我认为最好的策略是使此结果成为B,并最终执行B + C。我不确定如何重新分配B并以正确的顺序执行操作。为了简单起见,我暂时只考虑乘法。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MINA 2 /* if you need a constant, #define one (or more) */
#define MAXC 1024
struct m{
int **data;
size_t row, col;
};
void multiply(struct m *A, struct m *B)
{
int i, j, k;
struct m C;
C.data = malloc(sizeof(int) * A->row);
C.row = A->row;
C.col = B->col;
/*initialize C to 0*/
for ( j = 0; j < C.row; j++) /* for each row */
for ( k = 0; k < C.col; k++) /* for each col */
C.data[j][k] = 0; /* output int */
// 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][j] += A->data[i][k] * B->data[k][j];
//free(B->data);
*B = C;
}
void print_matrix(struct m *matrix)
{
int j, k;
for ( j = 0; j < matrix->row; j++) { /* for each row */
for ( k = 0; k < matrix->col; k++) /* for each col */
printf ("%4d", matrix->data[j][k]); /* output int */
putchar ('\n'); /* tidy up with '\n' */
free (matrix->data[j]); /* free row */
}
free (matrix->data); /* free pointers */
}
int main (int argc, char **argv)
{
struct m *matrix; /* pointer to array type */
size_t aidx = 0, maxa = MINA, /* matrix index, max no. allocated */
nrow = 0, ncol = 0, /* current row/col count */
maxrow = MINA, nop = 0; /* alloc'ed rows current array, no. op */
char buf[MAXC], /* buffer to hold each line */
op[MAXC]; /* array to hold operators */
int i;
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
/* allocate/validate maxa no. of matrix */
if (!(matrix = calloc (maxa, sizeof *matrix))) {
perror ("calloc-matrix");
return 1;
}
while (fgets (buf, MAXC, fp)) { /* read each line into buf */
int off = 0, n; /* offset from start of line, n for "%n" */
size_t tidx = 0; /* temporary array index */
char *p = buf; /* pointer to advance in sscanf */
int tmp[MAXC / 2 + 1]; /* temporary array, sized for max no. ints */
if (!isdigit(*buf)) { /* if 1st char non-digit, end of array */
op[nop++] = *buf; /* store operator */
if (nrow) /* if rows stored */
matrix[aidx++].row = nrow; /* set final number of rows */
nrow = ncol = 0; /* reset nrow/ncol counters */
maxrow = MINA; /* reset allocate rows */
continue; /* get next line of data */
}
if (aidx == maxa) { /* check if no. of structs need realloc */
void *atmp = realloc (matrix, 2 * maxa * sizeof *matrix); /* realloc */
if (!atmp) { /* validate */
perror ("realloc-matrix");
return 1;
}
matrix = atmp; /* assign new block to matrix */
/* set all new bytes zero (realloc doesn't initialize) */
memset (matrix + maxa, 0, maxa * sizeof *matrix);
maxa *= 2; /* update struct count */
}
/* read all integers in line into tmp array */
while (sscanf (p + off, "%d%n", &tmp[tidx], &n) == 1) {
off += n;
tidx++;
}
if (tidx) { /* if integers stored in tmp */
if (nrow == 0) { /* if first row in array */
/* allocate/validate maxrow pointers */
if (!(matrix[aidx].data = malloc (maxrow * sizeof *matrix[aidx].data))) {
perror ("malloc-matrix[aidx].data");
return 1;
}
matrix[aidx].col = tidx; /* fix no. cols on 1st row */
}
else if (nrow == maxrow) { /* realloc of row ptrs req'd? */
/* always realloc with temp ptr */
void *atmp = realloc (matrix[aidx].data, 2 * maxrow * sizeof *matrix[aidx].data);
if (!atmp) { /* validate every alloc/realloc */
perror ("realloc-matrix[aidx].data");
return 1;
}
matrix[aidx].data = atmp; /* assign realloced block to ptr */
maxrow *= 2; /* update maxrow to current alloc */
}
if (tidx != matrix[aidx].col) { /* validate no. of columns */
fprintf (stderr, "error: invalid number of columns " "matrix[%zu].data[%zu]\n", aidx, nrow);
return 1;
}
if (!(matrix[aidx].data[nrow] = /* allocate storagre for integers */
malloc (tidx * sizeof *matrix[aidx].data[nrow]))) {
perror ("malloc-matrix[aidx].data[nrow]");
return 1;
}
/* copy integers from tmp to row, increment row count */
memcpy (matrix[aidx].data[nrow++], tmp, tidx * sizeof *tmp);
}
} /*end of while (fgets (buf, MAXC, fp)) */
if (nrow) /* handle final array */
matrix[aidx++].row = nrow; /* set final number of rows */
if (fp != stdin) fclose (fp); /* close file if not stdin */
/*Printing the file */
for(i=0; i<aidx; i++){
print_matrix(&matrix[i]);
printf("%c\n",op[i]);
}
printf("=\n");
for(i=0; i<aidx; i++){
if(op[i] =='*')
multiply(&matrix[aidx],&matrix[aidx+1]);
}
print_matrix(&matrix[aidx-1]); /*Print the result */
free (matrix); /* free structs */
return 0;
}
答案 0 :(得分:0)
我的原始答案在内容上仍然是正确的,我将在结尾处加引号。现在问题更加清楚了。解决此问题的“幼稚”算法可能是:如果您只有乘法或总和,请读取文件并在其中放置一个列表:
完成后,对列表中的所有项目求和。用伪代码:
list = []
i = 0
op = +
for item in file {
if item is operator {
op = item
if op == + {
i++
}
} else if item is matrix {
if len(list) > i {
list[i] = list[i] op item
} else {
list[i] = item //auto append if i < len(list)
}
}
}
result = list[0]
for item in list[1:] {
result += item
}
请记住这一点:
如果我正确理解了您想知道的问题:应该将运算结果放在哪里,以及如何确定应该按什么顺序进行运算。因此,首先:您的想法是,在进行AB + C运算时,应将AB的结果放入B中,这还不错,但是,在执行类似的操作之前,您应该知道B不再用于其余的方程式中。考虑AB + B,现在,如果覆盖B,则会丢失它并且无法完成方程式。您需要一个变量关系图来执行该操作,如果有它,您不仅可以用操作的结果覆盖未使用的变量(通常,如果现在未使用则释放旧变量并分配一个新变量),还可以重用以后的操作结果,例如,如果必须执行ABC + AB,则可以看到重新计算AB没有任何意义。同样,第二个问题要求您构建操作树,我建议您使用LL(1) parser来构建操作树。