Ir para conteúdo
Fórum Script Brasil
  • 0

Construir matriz n*n através de função


Yunus

Pergunta

Preciso criar uma matriz N*N através de função, tenho três arquivos "main.c" "cabecalho.h" e "funcoes.c", como passar a matriz como parametro para a função? A seguir o código

main.c:

#include<stdio.h>
#include "cabecalho.h"

void main ()
{
	int **tabuleiro;
  	int n;
  
  	printf("Insira o tamanho do tabuleiro e a quantidade de rainhas (N): ");
    scanf("%i", &n);  	
    construirMatriz(tabuleiro, n);
}

cabecalho.h:

#ifndef CABECALHO_H_INCLUDED
#define CABECALHO_H_INCLUDED
#include "funcoes.c"

/**ALOCA A MATRIZ DINAMICAMENTE DE TAMANHO N*N*/
void construirMatriz(int tabuleiro[][], int n);

#endif // CABECALHO_H_INCLUDED

funcoes.c:

#include<stdio.h>
#include "cabecalho.h"

void construirMatriz(int tabuleiro[][], int n)
{
	tabuleiro = (int **) malloc (n * sizeof(int*));
    for (i = 0; i < n, i++)
    	tabuleiro[i] = (int *) malloc (n * sizeof(int));
}

esse é o erro:

funcoes.c:4:26: error: array type has incomplete element type
 void construirMatriz(int tabuleiro[][], int n)

Acredito ser na forma como estou passando a matriz para as funções.
                          ^
 

Link para o comentário
Compartilhar em outros sites

6 respostass a esta questão

Posts Recomendados

  • 0

em vez de
void construirMatriz(int tabuleiro[][], int n)
use
void construirMatriz(int **tabuleiro, int n)
tanto no prototipo como na implementação.

Não se esqueça de liberar a memória. no final de antes de sair de main.

Editado por vangodp
Link para o comentário
Compartilhar em outros sites

  • 0

Sim claro, você esta passando um ponteiro duplo, a função malloc reserva o espaço no heap e faz com que esse ponteiro aponte a esse espaço, e você deverá liberar antes de sair de main ou haverá fuga de memória.

 

Porem eu faria algo como isso:

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

void** callstore ( unsigned int rows, unsigned int cols, unsigned int size ) {
    unsigned int i;
    void** matrix = NULL;
    matrix = ( void** ) malloc ( size * rows * cols );
    
    for ( i = 0; i < rows; i++ ) {
        * ( matrix + i ) = ( void* ) malloc ( size * cols );
    }
    
    return matrix;
}

void freeMemory ( int** matrix, int linhas ) {
    int i;
    
    for ( i = 0; i < linhas; i++ ) {
        free ( * ( matrix + i ) );
    }
    
    free ( matrix );
}

int main (){
    unsigned int N = 10;
    
    //reserva
    int** matriz = (int**)callstore( N, N, sizeof(int) ); //função generica de reserva de memoria. Reserva N*N para inteiros

    
    matriz[0][0] = 10;
    matriz[9][9] = 20;
    
    printf("%d\n", matriz[0][0]);
    printf("%d\n", matriz[9][9]);

    
    //libera
    freeMemory( matriz, N);
   
    getchar();
    return 0;
}

 

Link para o comentário
Compartilhar em outros sites

  • 0

Bom dia!

Apenas para corrigir alguns pontos da resposta do vangodp:

1) Para que fosse possível receber o ponteiro na função e alocá-lo, precisamos passar o endereço do ponteiro. Assim, apesar de estranho, a função deveria ter 3 asteriscos:

void construirMatriz(int ***tabuleiro, int n)

E a chamada deveria ser:

construirMatriz(&tabuleiro, n);

 Também seria necessário fazer algumas alterações no código porém como o vangodp sugeriu é muito melhor! Assim não compensa ficar fazendo código que não será utilizado... :-)

2) Existe um problema na alocação.

Por ser um ponteiro de duas dimensões, devemos primeiro alocar o bastante para n ponteiros de 1 dimensão, ou seja, (void *).

Segue agora o código corrigido:

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

void** callstore ( unsigned int rows, unsigned int cols, unsigned int size ) {
    unsigned int i;
    void** matrix = NULL;
    matrix = (void **) malloc( rows * sizeof(void *) );    
    for ( i = 0; i < rows; i++ ) {
        * ( matrix + i ) = ( void* ) malloc ( size * cols );
    }
    
    return matrix;
}

void freeMemory ( void** matrix, int linhas ) {
    int i;
    
    for ( i = 0; i < linhas; i++ ) {
        free ( * ( matrix + i ) );
    }
    
    free ( matrix );
}

int main (){
    unsigned int N = 10;
    
    //reserva
    int** matriz = (int**)callstore( N, N, sizeof(int) ); //função generica de reserva de memoria. Reserva N*N para inteiros

    
    matriz[0][0] = 10;
    matriz[9][9] = 20;
    
    printf("%d\n", matriz[0][0]);
    printf("%d\n", matriz[9][9]);

    
    //libera
    freeMemory( (void **)matriz, N);
   
    getchar();
    return 0;
}

 

Link para o comentário
Compartilhar em outros sites

  • 0

Tudo isso é uma grande estupidez. Vamos falar a nível técnico... por muitas dimensões que acharem que tem um array a memória sempre será "unidimensional". Não há nada mais fácil que fazer:

int linhas = 10;
int colunas = 10;
int **matrix = (int**)malloc( sizeof int * linhas * colunas );

 

Como podem ver são poucas linhas, não há necessidade de usar funções estúpidas para esse trabalho >_<.

Mas se querem continuar por esse caminho existem varias formas de faze-lo:
Como disse O comentário anterior sim devemos usar ponteiro triplo, isso adiciona uma capa de complexidade maior:

int matrixAlloc ( int ***matrix, int nlinhas, int nColunas ) {
    int i;
    int estado;
    
    //Metodo de reserva classica
    *matrix = malloc ( nlinhas * sizeof ( int ) );
    
    if ( matrix != NULL ) {
        i = 0;
        
        while ( i < nlinhas ) {
            ( *matrix ) [i] = malloc ( nColunas * sizeof ( int ) );
            
            if ( ( *matrix ) [i] != NULL )
                estado = 1;
            else
                estado = 0;
                
            i++;
        }
    } else
        estado = 0;
        
    return estado;
}

 

Porem como falei usar laços para reservar memória o único que você ganha é um "pedaço de memória fragmentado", porem se usar a forma descrita ao principio, todas as casas ficam adjacentes, que traduzido ao bom PT BR se traduz em eficiência.
Então acho bem melhor usar int **matrix = (int**)malloc( sizeof int * linhas * colunas ), mas se quiser outras formas:
 

void* matrixAlloc2 ( int nlinhas, int nColunas ) {
    return malloc ( sizeof ( int[nlinhas][nColunas] ) );
}

Na qual você pode usar da seguinte forma dentro de main:

int ( *m2 ) [y] = matrixAlloc2 ( x, y );

 

A vantagem de usar o malloc hackeado para criar todas as casinhas de forma adjacentes é que você pode usar um simples free(m2) como se de um array se tratasse pois todas as casas como falei estão adjuntas uma a outra, não há necessidade nem de usar laços para liberar essa porção de memória.

Por isso a linha...

    matrix = (void **) malloc( rows * sizeof(void *) ); 

que diz @Marcelo Utikawa da Fonseca estava da forma:

matrix = ( void** ) malloc ( size * rows * cols );


porque tinha copiado essa linha de outra linha semelhante ao sistema que mostrei ao principio. trata-se de fazer uma função genérica para reserva de memória, porem pouco viável conforme meu parecer.

Sobre a função levar um ponteiro triplo é correto, já adicionei ela ai para quem quer usar. é só invocar ela ai tipo:

 

int matrixAlloc ( int ***matrix, int nlinhas, int nColunas ) {
    int i;
    int estado;
    
    //Metodo de reserva classica
    *matrix = malloc ( nlinhas * sizeof ( int ) );
    
    if ( matrix != NULL ) {
        i = 0;
        
        while ( i < nlinhas ) {
            ( *matrix ) [i] = malloc ( nColunas * sizeof ( int ) );
            
            if ( ( *matrix ) [i] != NULL )
                estado = 1;
            else
                estado = 0;
                
            i++;
        }
    } else
        estado = 0;
        
    return estado;
}
int main(){
	int **m1 = NULL;
    int x = 3, y = 3;
    matrixAlloc ( &m1, x, y );
...

 

Acho que é tudo. Ou sei lá... sou meio doido mesmo.

Editado por vangodp
Link para o comentário
Compartilhar em outros sites

  • 0

Perfeito @vangodp . Concordo totalmente com a colocação, alocar tudo de uma só vez é muito melhor mesmo. A única questão é que, nesse caso, teria que ser acesso em apenas 1 dimensão. Não poderia ser feito matriz[x][y]. Deveria ser: matriz [x * linhas + y].

Mas seria até mais rápido o acesso visto que seria um acesso direto à posição desejada, não leitura de um endereço (para carregar o endereço das colunas) para depois ir na posição do valor.

Eu só comentei pois, se for alocar tudo de uma vez, não deve existir o loop com alocações para as colunas já que toda a memória já foi alocada.

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152k
    • Posts
      651,7k
×
×
  • Criar Novo...