матричные операции чтения ввода из файла - PullRequest
0 голосов
/ 06 июня 2019

Я бы хотел выполнить матричные операции, такие как 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 голосов
/ 06 июня 2019

Мой первоначальный ответ по-прежнему верен по содержанию, в конце я оставлю его цитируемым Теперь проблема более понятна. «Наивный» алгоритм для решения этой проблемы может состоять в том, чтобы, если у вас есть только умножения или суммы, прочитать файл и сохранить список, куда вы положили:

  • Если у вас есть знак *, умножьте операнды, сохранив только результат
  • Если у вас есть знак +, переходите к следующему пункту

Когда вы закончите, суммируйте все элементы в списке. В псевдокоде:

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) парсера .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...