segunda-feira, 31 de agosto de 2015

Operações com matrizes de inteiros em linguagem C

          Nesta primeira postagem, apresentarei meu código feito em linguagem C, projetado para reconhecer arquivos em .txt contendo matrizes e, em posse delas, realizar as operações: encontrar o maior elemento, determinar a matriz transposta, realizar o produto entre duas matrizes e, por fim, calcular o determinante de uma matriz através da Regra de Laplace.
          Com essa atividade de programação, solicitada em meu curso de Laboratório de Estruturas de Dados e Algoritmos (CES-11), pude fortalecer a minha habilidade para pensar e implementar soluções para problemas através de caminhos recursivos; além disso, foi possível recordar as aplicações de alocação dinâmica de matrizes, quebra de problemas em funções e, por fim, operações com arquivos.

Veja, a seguir, um vídeo demonstrativo da execução de meu programa:



Segue, abaixo, todo o código produzido, "LAB1.c":

#include <stdio.h>
#include <stdlib.h>

typedef int *vetor;
typedef vetor *matriz;

int testador(matriz M, int n, int i, int j, int max){
    //testa os elementos da matriz M e os compara com o maior obtido ate entao (max), retornando o maior inteiro
    //n: ordem da matriz
    //i e j: parametros de cada elemento da matriz (elemento M[i][j])
        //percorre as linhas da esquerda para a direita:
    if(i < n-1){
        if(M[i][j] > max)
            return testador(M, n, i+1, j, M[i][j]);
            return testador(M, n, i+1, j, max);
    }
        //quando chega ao final de uma linha (M[i][j] = M[n-1][j]):
    else if((i == n-1) && (j < n-1)){
        if(M[i][j] > max)
            return testador (M, n, 0, j+1, M[i][j]);
            return testador (M, n, 0, j+1, max);
    }
        //quando chega ao final da matriz (M[i][j] = M[n-1][n-1]):
    else{
        if(M[i][j] > max)
            return M[i][j];
        else
            return max;
    }
}//func. testador()

int retornarMaiorElemento(matriz M, int n){
    int max = M[0][0];
        //os parametros i e j da func. testador comecam zerados
    return testador (M, n, 0, 0, max);
}//FUNC. retornarMaiorElemento()

void DeixarMatrizPronta(matriz A, int n, int i){
    //A FUNC. alocarMatriz() aloca o vetor de ponteiros, que eh apontado por **A;
    //A func. DeixarMatrizPronta() alocara, entao, a matriz em si, apontada pelos ponteiros do vetor:
    if (i <= n-1){
        A[i] = (int *) malloc (n * sizeof (int));
        DeixarMatrizPronta (A, n, i+1);
    }
}//func. DeixarMatrizPronta()

matriz alocarMatriz(int n){
    matriz A;
    A = (vetor *) malloc (n * sizeof (vetor));
    DeixarMatrizPronta (A, n, 0);
    return A;
}//FUNC. alocarMatriz()

void desalocacao(matriz A, int n, int i){
    //desalocara as linhas da matriz, comecando pela ultima
    if (i >= 0){
        free(A[i]);
        desalocacao(A, n, i-1);
    }
}//func. desalocacao()

void desalocarMatriz(matriz A, int n){
    //desalocara o vetor de ponteiros
    desalocacao (A, n, n-1);
    free(A);
}//FUNC. desalocarMatriz()

void transpor (matriz M, matriz A, int n, int i, int j){
    A[j][i] = M[i][j];
    if (i < n-1)
        i++;
    else if((i == n-1) && (j < n-1)){
        i = 0;
        j++;
    }
    else if((i == n-1) && (j==n-1))
        return;
    transpor(M, A, n, i, j);

}//func. transpor()

matriz criarTransposta(matriz M, int n){
    matriz T;
    T = alocarMatriz (n);
    transpor(M, T, n, 0, 0);
    return T;
}//FUNC. criarTransposta()

void ZerarMatriz(matriz A, int i, int j, int n){
    //func. com o objetivo de zerar a matriz A para poder receber o produto das matrizes M1 e M2
    A[i][j] = 0;
    if(i < n-1)
        i++;
    else if((i == n-1) && (j < n-1)){
        i = 0;
        j++;
    }
    else if((i == n-1) && (j == n-1))
        return;
    ZerarMatriz(A, i, j, n);
}//func. ZerarMatriz()

void efetuarProduto(matriz P, matriz M1, matriz M2, int i, int j, int k, int n){
    //O algoritmo segue o procedimento escrito como nos somatorios:
    P[i][k] += M1[i][j] * M2[j][k];
    if(j < n-1)
        j++;
    else if((j == n-1) && (k < n-1)){
        j = 0;
        k++;
    }
    else if((j == n-1) && (k == n-1) && (i < n-1)){
        j = 0;
        k = 0;
        i++;
    }
    else if((j == n-1) && (k == n-1) && (i == n-1)){
        return;
    }
    efetuarProduto (P, M1, M2, i, j, k, n);
}//func. efetuarProduto()

matriz calcularProduto(matriz M1, matriz M2, int n){
    matriz P;
    P = alocarMatriz(n);
    ZerarMatriz(P, 0, 0, n);
    efetuarProduto(P, M1, M2, 0, 0, 0, n);
    return P;
}//FUNC. calcularProduto()

void preencherMatriz(matriz X, matriz M, int j, int p, int q, int n){
    //preenche X com os valores de M tirando-se a linha 0 e a coluna j (da Regra de Laplace)
    if(p > 0){
        if(q < j)
            X[p-1][q] = M [p][q];
        else if(q > j)
            X[p-1][q-1] = M[p][q];
    }
    if(p < n-1)
        preencherMatriz(X, M, j, p+1, q, n);
    else if((p == n-1) && (q < n-1))
        preencherMatriz(X, M, j, 0, q+1, n);
    else if((p == n-1) && (q == n-1))
        return;
}//func. preencherMatriz()

int calcularDeterminante (matriz M, int n){
    //Regra de Laplace
    if(n==1)
        return M[0][0];
    else{
        int j, Det = 0, cofator;
        matriz X;
        X = alocarMatriz(n-1);
        for(j=0; j <= n-1; j++){
            //preencherMatriz eh a func. que torna X o Menor Complementar de A, de indices 0 e j:
            preencherMatriz(X, M, j, 0, 0, n);
            //O cofator eh definido pelo produto do det. do Menor Complementar (Det X) por (-1)^(0+j):
            if  (j%2 == 0)
                cofator = calcularDeterminante(X, n-1);
            else if (j%2 == 1)
                cofator = (-1) * calcularDeterminante(X, n-1);
            Det += M[0][j] * cofator;
        }
        desalocarMatriz(X, n-1);
        return Det;
    }
}//FUNC. calcularDeterminante()

int main(){
    FILE *f1, *f2;
    f1 = fopen("entrada.txt", "r");/*O arquivo "entrada.txt" sera criado pelo programa "Gerar matrizes pseudo-aleatorias.exe"*/
    f2 = fopen("saida.txt", "w");
    int i, j, k, Operacao, Ordem, Quantidade_de_operacoes;
    fscanf(f1, "%d", &Quantidade_de_operacoes);
    for(i=1; i<=Quantidade_de_operacoes; i++){
        fscanf(f1, "%d", &Operacao);
        fscanf(f1, "%d", &Ordem);
        switch(Operacao){
            case 1:{//FUNC. retornarMaiorElemento()
                matriz A;
                A = alocarMatriz(Ordem);
                for(j=0; j< Ordem; j++)
                    for(k=0; k< Ordem; k++)
                        fscanf(f1, " %d", &A[j][k]);
                fprintf(f2, "%3d\n\n",retornarMaiorElemento(A, Ordem));/*ja imprime direto o valor da FUNC.*/
                desalocarMatriz(A, Ordem);
            }break;
            case 2:{//FUNC. criarTransposta()
                matriz A, T;
                A = alocarMatriz(Ordem);
                for(j=0; j< Ordem; j++)
                    for(k=0; k< Ordem; k++)
                        fscanf(f1, "%d", &A[j][k]);
                T = criarTransposta(A, Ordem);/*T recebe os valores de At*/
                for(j=0; j < Ordem; j++){
                    for(k=0; k<Ordem; k++)
                        fprintf(f2, "%3d", T[j][k]);
                    fprintf(f2, "\n");
                }
                fprintf(f2, "\n");
                desalocarMatriz(A, Ordem);
                desalocarMatriz(T, Ordem);
            }break;
            case 3:{//FUNC. calcularProduto()
                matriz A, B, P;
                A = alocarMatriz(Ordem);
                B = alocarMatriz(Ordem);
                for(j=0; j< Ordem; j++)
                    for(k=0; k< Ordem; k++)
                        fscanf(f1, "%d", &A[j][k]);
                for(j=0; j< Ordem; j++)
                    for(k=0; k< Ordem; k++)
                        fscanf(f1, "%d", &B[j][k]);
                P = calcularProduto(A, B, Ordem);/*OBS: a FUNC. ja aloca espaco para P*/
                for(j=0; j < Ordem; j++)
                {
                    for(k=0; k<Ordem; k++)
                         fprintf(f2, "%6d", P[j][k]);
                    fprintf(f2, "\n");
                }
                fprintf(f2, "\n");
                desalocarMatriz(A, Ordem);
                desalocarMatriz(B, Ordem);
                desalocarMatriz(P, Ordem);
            }break;
            case 4:{//FUNC. calcularDeterminante
                matriz A;
                A = alocarMatriz(Ordem);
                for(j = 0; j < Ordem; j++)
                    for(k = 0; k < Ordem; k++)
                        fscanf(f1, "%d", &A[j][k]);
                fprintf(f2, " %d\n\n", calcularDeterminante(A, Ordem));/*ja imprime direto o valor da FUNC.*/
                desalocarMatriz(A, Ordem);
            }break;
        }
    }
    fclose(f1);
    fclose(f2);
    return 0;
}