Jump to content
Fórum Script Brasil
  • 0

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


Yunus
 Share

Question

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 to comment
Share on other sites

6 answers to this question

Recommended Posts

  • 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.

Edited by vangodp
Link to comment
Share on other 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 to comment
Share on other 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 to comment
Share on other 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.

Edited by vangodp
Link to comment
Share on other 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 to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share



  • Forum Statistics

    • Total Topics
      149.6k
    • Total Posts
      646.2k
×
×
  • Create New...