Ir ao conteúdo

Posts recomendados

Postado
//Programa de multiplicacao de 2 matrizes (A e B), gerando o resultado em uma matriz C
//Aloquei a matriz, a retornei via funcao e depois chamei desaloquei(free), 
//de acordo com o raciocinio falado aqui no site. porém recebo 'segmentation fault'.
//alguém pode me ajudar?


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

float **multiplicaMatriz(int linA, int colA, int linB, int colB);
void desalocaMatriz(float **C, int nlinhas);

int main(void)
{
   int linA, colA, linB, colB;
   float **C;
   int i;
   int j;
   
   printf("\n\nInforme o numero de linhas para a matriz A = ");
   scanf("%d", &linA);
   printf("\nInforme o numero de colunas para a matriz A = ");
   scanf("%d", &colA);
   printf("\nInforme o numero de linhas para a matriz B = ");
   scanf("%d", &linB);
   printf("\nInforme o numero de colunas para a matriz B = ");
   scanf("%d", &colB);
  

   if(colA != linB)
   {
        printf("\n\nATENCAO: O produto das matrizes informadas não eh possível!\n");
        printf("Isso acontece pois o numero de colunas da matriz A eh diferente do numero de linhas da matriz B.\n\n");
        exit(0);
   }

   C = multiplicaMatriz(linA, colA, linB, colB);
    for(i = 0; i < linA; i++)
    {
        for(j = 0; j < colB; j++)
        {
            printf("%f\n", C[i][j]);
        }
    }

    desalocaMatriz(C, linA);
    
    
    return 0;
}

float **multiplicaMatriz(int linA, int colA, int linB, int colB)
{
    int i;
    int x, y, a1, a2;
    float temp;
    float A[linA][colA];
    float B[linB][colB];
   // float C[linA][colB]; 
    float **C = (float **) malloc(sizeof(float *) * linA);

   

    // Gera matriz A
    printf("\n GERANDO MATRIZ A \n\n");
    for(x = 0;x < linA; x++)
    {
        for(y = 0;y < colA; y++)
        {
            printf("A[%d][%d] = ", x+1,y+1);
            A[x][y] = rand() % 15;
        }
    }
    
    // Gera matriz B
    printf("\n GERANDO MATRIZ B \n");
    for(x = 0;x < linB; x++)
    {
        for(y = 0;y < colB; y++)
        {
            printf("B[%d][%d] = ", x+1,y+1);
            //scanf("%f", &B[x][y]);
            B[x][y] = rand() % 15;
        }
    }

    // Imprime matriz A
    printf("\n MATRIZ A \n\n");
    for(x = 0; x < linA; x++)
    {
        for(y = 0; y < linA; y++)
        {
            if(y !=(colA - 1))
                printf("|%.2f \n", A[x][y]);
            else
                printf("|%.2f \n", A[x][y]);
        }
    }

    printf("\n\n");


    // Imprime matriz B
    printf("\n MATRIZ B \n\n");
    for(x = 0; x < linB; x++)
    {
        for(y = 0; y < linB; y++)
        {
            if(y !=(colB - 1))
                printf("|%.2f \n", B[x][y]);
            else
                printf("|%.2f \n", B[x][y]);
        }
    }
    
    for(a1 = 0; a1 < linA; a1++)
    {
        for(a2 = 0; a2 < colB; a2++)
        {
            temp=0.0;
            for(x = 0; x < colA; x++)
            {
                temp = temp+A[a1][x]*B[x][a2];
            }
            C[a1][a2] = temp;
        }
    }

    printf("\n \n");
    printf("\n MATRIZ C = A x B \n \n");

    for(x = 0; x < linA; x++)
    {
        for(y = 0; y < colB; y++)
        {
            if(y!=(colB-1))
            {
                printf("%.2f \t",C[x][y]);
            }
            else
            {
                printf("%.2f \n",C[x][y]);
            }
        }
    }

    /* Aloca matriz C */
     printf("Alocando matriz C");
     for(i = 0; i < linA; i++)
     {
        C[i] = (float *) malloc(sizeof(float) * colB);
     }

    return C;
}

void desalocaMatriz(float **C, int nlinhas)
{
     int i;
     
     for(i = 0; i < nlinhas; i++)
     {
         free(C[i]);
     } 
}

 

  • Curtir 1
Postado

@Pedro Fernandess    na linguagem c não se pode retornar uma matriz nem vetor nem string ,  mas pode retornar uma struct , caracteres e números ,  e na função multiplicaMatriz você alocou a matriz C no final depois de já ter inserido dados nela , e precisa alocar no início antes de armazenar qq dado nela .

  • Curtir 2
Postado
1 hora atrás, devair1010 disse:

na linguagem c não se pode retornar uma matriz nem vetor nem string

No caso é matriz dinâmica, ponteiro de ponteiro pra float, e a função retorna isso também, acaba apontando pro local de memória alocado pra C... Caso tivesse sido alocado 🤪

 

@Pedro Fernandess Na parte que você gera valores aleatórios pras matrizes A e B, faltou imprimir o valor gerado:

A[x][y] = rand() % 15;
printf("A[%d][%d] = %.2f\n", x+1,y+1, A[x][y]);

E não deu muito certo sua ideia de imprimir a matriz, acabou imprimindo cada elemento em uma linha, tente isso:

for(x = 0; x < linA; x++) {
    for(y = 0; y < linA; y++) {
        if(y !=(colA - 1))
            printf("|%6.2f", A[x][y]);
        else
            printf("|%6.2f", A[x][y]);
    }
    printf("|\n");
}

Como @devair1010 disse, você precisa alocar memória antes de usar...

 

Dá uma olhada:

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

float** multiplicaMatriz (int linA, int colA, int linB, int colB);
void desalocaMatriz (float** C, int nlinhas);

int main(void)
{
    srand(time(NULL));
    
    int linA, colA, linB, colB;
    float** C;
    int i;
    int j;
    
    printf("\n\nInforme o numero de linhas para a matriz A = ");
    scanf("%d", &linA);
    printf("\nInforme o numero de colunas para a matriz A = ");
    scanf("%d", &colA);
    printf("\nInforme o numero de linhas para a matriz B = ");
    scanf("%d", &linB);
    printf("\nInforme o numero de colunas para a matriz B = ");
    scanf("%d", &colB);
    
    
    if(colA != linB)
    {
        printf("\n\nATENCAO: O produto das matrizes informadas não eh possível!\n");
        printf("Isso acontece pois o numero de colunas da matriz A eh diferente do numero de linhas da matriz B.\n\n");
        exit(0);
    }
    
    C = multiplicaMatriz(linA, colA, linB, colB);
    for(i = 0; i < linA; i++)
    {
        for(j = 0; j < colB; j++)
        {
            printf("%f\n", C[i][j]);
        }
    }
    
    desalocaMatriz(C, linA);
    
    
    return 0;
}

float** multiplicaMatriz(int linA, int colA, int linB, int colB)
{
    int i;
    int x, y, a1, a2;
    float temp;
    float A[linA][colA];
    float B[linB][colB];
    // float C[linA][colB]; 
    float** C = (float**)malloc(sizeof(float*) * linA);
    /* Aloca matriz C */
    printf("Alocando matriz C");
    for(i = 0; i < linA; i++)
    {
        C[i] = (float*)malloc(sizeof(float) * colB);
    }
   

    // Gera matriz A
    printf("\n GERANDO MATRIZ A \n\n");
    for(x = 0;x < linA; x++)
    {
        for(y = 0;y < colA; y++)
        {
            A[x][y] = rand() % 15;
            printf("A[%d][%d] = %.2f\n", x+1,y+1, A[x][y]);
        }
    }
    
    // Gera matriz B
    printf("\n GERANDO MATRIZ B \n");
    for(x = 0;x < linB; x++)
    {
        for(y = 0;y < colB; y++)
        {
            B[x][y] = rand() % 15;
            printf("B[%d][%d] = %.2f\n", x+1,y+1, B[x][y]);
        }
    }

    // Imprime matriz A
    printf("\n MATRIZ A \n\n");
    for(x = 0; x < linA; x++)
    {
        for(y = 0; y < linA; y++)
        {
            if(y !=(colA - 1))
                printf("|%6.2f", A[x][y]);
            else
                printf("|%6.2f", A[x][y]);
        }
        printf("|\n");
    }

    // Imprime matriz B
    printf("\n MATRIZ B \n\n");
    for(x = 0; x < linB; x++)
    {
        for(y = 0; y < linB; y++)
        {
            if(y !=(colB-1 - 1))
                printf("|%6.2f", B[x][y]);
            else
                printf("|%6.2f", B[x][y]);
        }
        printf("|\n");
    }
    
    for(a1 = 0; a1 < linA; a1++)
    {
        for(a2 = 0; a2 < colB; a2++)
        {
            temp=0.0;
            for(x = 0; x < colA; x++)
            {
                temp = temp+A[a1][x]*B[x][a2];
            }
            C[a1][a2] = temp;
        }
    }
    
    printf("\n MATRIZ C = A x B \n \n");
    for(x = 0; x < linA; x++)
    {
        for(y = 0; y < colB; y++)
        {
            if(y!=(colB-1))
            {
                printf("|%6.2f",C[x][y]);
            }
            else
            {
                printf("|%6.2f",C[x][y]);
            }
        }
        printf("|\n");
    }
    
    printf("\n\n");

    return C;
}

void desalocaMatriz(float **C, int nlinhas)
{
    int i;
    
    for(i = 0; i < nlinhas; i++)
    {
        free(C[i]);
    } 
}

 

  • Curtir 1
  • Amei 1
Postado
Em 12/11/2021 às 17:43, Pedro Fernandess disse:
float **multiplicaMatriz(int linA, int colA, int linB, int colB);

 

Esse não é o forum de multiplicação de matrizes :) mas 
 

    A[M][N] x B[N][O] = C[MxO]

 

por definição para o produto existir

 

Escreva em torno dos dados. 

 

É mais simples de ler e programar assim:

 

typedef struct
{
    int   l;
    int   c;
    int** M; // M lxc

}   Matriz;

Matriz* apaga_matriz(Matriz* m);
Matriz* cria_matriz(int l, int c);
int     imp_matriz(Matriz* A, const char* msg);
Matriz* mult_matriz(Matriz* A, Matriz* B);

//https://www.clubedohardware.com.br/
//topic/1573213-segmentation-fault-retornar-matriz/

 

Sobre isso

 

19 horas atrás, Lucca Rodrigues disse:
void desalocaMatriz(float **C, int nlinhas)
{
    int i;
    
    for(i = 0; i < nlinhas; i++)
    {
        free(C[i]);
    } 
}

 

Não é uma boa maneira de escrever, e pode estar errado... Vai depender de como foi criada a matriz.

depois do loop deve chamar free(*C) e  ainda invalidar o ponteiro onde chamou desalocaMatriz. Por isso é melhor criar uma estrutura e passar o endereço dela. Não dá pra saber se no seu caso *C é estática ou não.

  • Curtir 1
  • Obrigado 1
Postado

Um exemplo mais seguro

 

Escrevendo em torno dos dados do exemplo

 

typedef struct
{
    int     l;
    int     c;
    float** M;  // M lxc

} Matriz;

 

Assim fica mais seguro definir a Matriz, alocar memória, liberar ponteiros e fazer as contas...

 

Assim temos

 

Matriz* apaga_matriz(Matriz* m);
Matriz* cria_matriz(int l, int c);
Matriz* gera_matriz(int l, int c);
int     imp_matriz(Matriz* A, const char* msg);
Matriz* mult_matriz(Matriz* A, Matriz* B);

 

E é mais fácil de ler e escrever código em termos dos dados. Esse é o conceito de encapsulamento.

 

Multiplicar duas matrizes gera outra, então é mais fácil ler o óbvio:

 

    Matriz* produto = mult_matriz(uma, outra);

 

e entender que é o produto de duas matrizes e que gera uma terceira....

 

Do programa original

 

    // Gera matriz A
    printf("\n GERANDO MATRIZ A \n\n");
    for(x = 0;x < linA; x++)
    {
        for(y = 0;y < colA; y++)
        {
            A[x][y] = rand() % 15;
            printf("A[%d][%d] = %.2f\n", x+1,y+1, A[x][y]);
        }
    }
    
    // Gera matriz B
    printf("\n GERANDO MATRIZ B \n");
    for(x = 0;x < linB; x++)
    {
        for(y = 0;y < colB; y++)
        {
            B[x][y] = rand() % 15;
            printf("B[%d][%d] = %.2f\n", x+1,y+1, B[x][y]);
        }
    }

 

Pode ser escrito apenas como

 

    Matriz* uma   = gera_matriz(3, 4);
    Matriz* outra = gera_matriz(4, 3);

 

Do programa original

 

    // Imprime matriz A
    printf("\n MATRIZ A \n\n");
    for (x = 0; x < linA; x++)
    {
        for (y = 0; y < linA; y++)
        {
            if (y != (colA - 1))
                printf("|%.2f \n", A[x][y]);
            else
                printf("|%.2f \n", A[x][y]);
        }
    }

    printf("\n\n");

    // Imprime matriz B
    printf("\n MATRIZ B \n\n");
    for (x = 0; x < linB; x++)
    {
        for (y = 0; y < linB; y++)
        {
            if (y != (colB - 1))
                printf("|%.2f \n", B[x][y]);
            else
                printf("|%.2f \n", B[x][y]);
        }
    }

 

É claro que o código está duplicado e que para mostrar uma matriz só falta o título então podia ser, para as matrizes acima e passando o título como parâmetro junto com o endereço de uma matriz:

 

    imp_matriz(uma, "A[3x4]");
    imp_matriz(outra, "B[4x3]");

 

Claro que se poderia usar sprintf() para ter um título genérico:

 

    char msg[80];
    sprintf(msg, "B[%dx%d]", outra->l, outra->c);
    imp_matriz(outra, msg);

 

E o resultado seria o mesmo

 

A[3x4]
    8.92   -6.73  -10.00   10.54
    0.24    4.73  -14.30  -10.40
   -0.38    6.43   -7.44   -5.04


B[4x3]
    9.91   -7.65   13.93
   -2.88   -8.83   -3.30
    0.60   -5.09   -5.54
    5.46    1.88   13.11

 

 

main() fica muito mais legível

 

int main(void)
{
    srand(211112);
    // cria duas matrizes prrenchidas aleatoriamente
    Matriz* uma   = gera_matriz(3, 4);
    Matriz* outra = gera_matriz(4, 3);
    // mostra as duas na tela
    imp_matriz(uma, "    A[3x4]");
    char msg[80];
    sprintf(msg, "    B[%dx%d]", outra->l, outra->c);
    imp_matriz(outra, msg);
    // multiplica e mostra
    Matriz* produto = mult_matriz(uma, outra);
    imp_matriz(produto, "    Produto C[3x3]");
    // apaga tudo
    uma = apaga_matriz(uma);
    outra = apaga_matriz(outra);
    produto = apaga_matriz(produto);

    return 0;
}

 

Um exemplo completo

 

A saída do exemplo

 

    A[3x4]
    8.92   -6.73  -10.00   10.54
    0.24    4.73  -14.30  -10.40
   -0.38    6.43   -7.44   -5.04


    B[4x3]
    9.91   -7.65   13.93
   -2.88   -8.83   -3.30
    0.60   -5.09   -5.54
    5.46    1.88   13.11


    Produto C[3x3]
  159.33   61.90  340.04
  -76.61    9.63  -69.39
  -54.27  -25.48  -51.37

 

O programa todo

 

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

int main(void)
{
    srand(211112);
    // cria duas matrizes prrenchidas aleatoriamente
    Matriz* uma   = gera_matriz(3, 4);
    Matriz* outra = gera_matriz(4, 3);
    // mostra as duas na tela
    imp_matriz(uma, "    A[3x4]");
    char msg[80];
    sprintf(msg, "    B[%dx%d]", outra->l, outra->c);
    imp_matriz(outra, msg);
    // multiplica e mostra
    Matriz* produto = mult_matriz(uma, outra);
    imp_matriz(produto, "    Produto C[3x3]");
    // apaga tudo
    uma = apaga_matriz(uma);
    outra = apaga_matriz(outra);
    produto = apaga_matriz(produto);

    return 0;
}

Matriz* apaga_matriz(Matriz* m)
{
    if (m == NULL) return NULL;
    for (int i = 0; i < m->l; i += 1) free(m->M[i]);
    free(m->M);
    free(m);
    return NULL;
}

Matriz* cria_matriz(int l, int c)
{
    if (l < 1) return NULL;
    if (c < 1) return NULL;
    Matriz* nv = (Matriz*)malloc(sizeof(Matriz));
    nv->l      = l;
    nv->c   = c;
    nv->M      = (float**)malloc(l * sizeof(float*));
    for (int i = 0; i < l; i += 1)
        nv->M[i] = (float*)malloc(c * sizeof(float));
    return nv;
}

Matriz* gera_matriz(int l, int c)
{
    Matriz* nv = cria_matriz(l, c);
    for (int i = 0; i < l; i += 1)
        for (int j = 0; j < c; j += 1)
            nv->M[i][j] =
                -15 + rand() % 30 + (rand() % 99 / 100.f);
    return nv;
}

int imp_matriz(Matriz* A, const char* msg)
{
    if (A == NULL) return -1;
    if (msg != NULL) printf("\n%s\n", msg);
    for (int i = 0; i <A->l; i += 1)
    {
        for (int j = 0; j<A->c; j += 1)
            printf("%8.2f", A->M[i][j]);
        printf("\n");
    }
    printf("\n");
    return 0;
}

Matriz* mult_matriz(Matriz* A, Matriz* B)
{
    // a[MxN] * b[NxO] = c[MxO]
    if (A->c != B->l) return NULL;
    Matriz* prod = cria_matriz(A->l, B->c);
    if (prod == NULL) return NULL;
    // calcula produto
    for (int l = 0; l < A->l; l++)
    {
        for (int c = 0; c < B->c; c++)
        {
            float temp = 0.0;
            for (int x = 0; x < A->c; x++)
                temp = temp + A->M[l][x] * B->M[x][c];
            prod->M[l][c] = temp;
        }
    }
    return prod;
}

 

O header f5.h tem as definições de dados e as funções

 

typedef struct
{
    int     l;
    int     c;
    float** M;  // M lxc

} Matriz;

Matriz* apaga_matriz(Matriz* m);
Matriz* cria_matriz(int l, int c);
Matriz* gera_matriz(int l, int c);
int     imp_matriz(Matriz* A, const char* msg);
Matriz* mult_matriz(Matriz* A, Matriz* B);

// https://www.clubedohardware.com.br/
// topic/1573213-segmentation-fault-retornar-matriz/

 

 

Sobre o programa original

 

float** multiplicaMatriz(int linA, int colA, int linB, int colB)
{
    int   i;
    int   x, y, a1, a2;
    float temp;
    float A[linA][colA];
    float B[linB][colB];

 

Isso não está no padrão: o tamanho de A e B tem que ser constante, conhecido em tempo de compilação. A outra opção seria usar VLA mas aqui se está usando alocação dinâmica. Sugiro esquecer isso e NUNCA usar. Escreva como eu mostrei: aloca uma área, retorna o endereço. Apaga uma área na ordem contrária do que foi alocado e invalida NA HORA o ponteiro. Faz a vida mais simples.

 

    for (x = 0; x < linA; x++)
    {
        for (y = 0; y < colA; y++)

 

NUNCA use isso. Declare as variáveis no for ou DENTRO do loop.

 

 

    printf("\nInforme o numero de colunas para a matriz A = ");
    scanf("%d", &colA);
    printf("\nInforme o numero de linhas para a matriz B = ");
    scanf("%d", &linB);
    printf("\nInforme o numero de colunas para a matriz B = ");
    scanf("%d", &colB);

 

Teste SEMPRE o retorno de scanf(). É ingênuo não testar. E evite scanf() para ler do teclado. Prefira fgets() e leia a linha toda.

 


 

21 horas atrás, Lucca Rodrigues disse:
int main(void)
{
    srand(time(NULL));

 

Não use time(NULL) para iniciar srand() em testes. Em geral não é isso o que se quer. Use uma semente conhecida e reproduzível...

  • Obrigado 1

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!