矩阵运算从文件中读取输入

时间:2019-06-06 09:56:02

标签: c

我想执行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;
}

1 个答案:

答案 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来构建操作树。