Função retornar Matriz- Problema [RESOLVIDO]

1. Função retornar Matriz- Problema [RESOLVIDO]

Marco Brainiac
mbrainiac

(usa Debian)

Enviado em 23/02/2016 - 09:15h

Olá,
Estou tendo problemas para retornar uma Matriz de uma Função, ela traz retornos absurdos:

//Soma de 2 matrizes
#include<stdio.h>
int N=2, M=4;

int retvet(){
int vet[N][M], i, j;
for( i=0; i<N; i++){
for( j=0; j<M; j++){
printf("entre com Vetor[%d][%d] : ",i,j);
scanf(" %d",&vet[i][j]);

}
}

return vet[N][M];
}

int main()
{
int i,j, vet1[N][M], vet2[N][M], soma[N][M];

vet1[N][M] = retvet();
printf("\n");
vet2[N][M] = retvet();


for(i=0; i<N; i++){
for(j=0; j<M; j++){
soma[i][j] = vet1[i][j] + vet2[i][j];

}
}

printf("\n");
for(i=0; i<N; i++){
for(j=0; j<M; j++){
printf("soma[%d][%d] = %d ", i,j,soma[i][j]);


}
printf("\n");

}
return 0;

}


Saída =================================>
mbrainiac@hotpc:~/Área de trabalho/C_programas/Estruturas$ ./somaMatrizes2.x
entre com Vetor[0][0] : 1
entre com Vetor[0][1] : 1
entre com Vetor[0][2] : 1
entre com Vetor[0][3] : 1
entre com Vetor[1][0] : 1
entre com Vetor[1][1] : 1
entre com Vetor[1][2] : 1
entre com Vetor[1][3] : 1

entre com Vetor[0][0] : 2
entre com Vetor[0][1] : 2
entre com Vetor[0][2] : 2
entre com Vetor[0][3] : 2
entre com Vetor[1][0] : 2
entre com Vetor[1][1] : 2
entre com Vetor[1][2] : 2
entre com Vetor[1][3] : 2

soma[0][0] = -1080115424 soma[0][1] = -1217363968 soma[0][2] = -1080115019 soma[0][3] = 1860244504
soma[1][0] = 1997460080 soma[1][1] = -1217457494 soma[1][2] = 1995463008 soma[1][3] = 134513117


  


2. MELHOR RESPOSTA

Ednux
ednux

(usa Arch Linux)

Enviado em 23/02/2016 - 11:36h

Reescrevi o seu código. Estava com muitos erros e difícil de entender.
Basicamente é o seguinte, você não pode alterar endereços constantes como " vet1[N][M] = retvet(); "
Essa forma de declaração cria uma matriz estática: int vet1[N][M];
Para realmente retornar uma matriz você teria que usar alocação dinâmica e depois libera-la.
Lembre-se do tipo de dado no retorno de uma função, se for uma matriz o prototipo seria assim: int **retorna_matriz();
Mas aconselho fortemente você a estudar ponteiros antes de usar alocação dinâmica.

O melhor exemplo que posso te dar agora é passagem por referência, dessa forma você consegue utilizar uma matriz dentro de uma função sem precisar se preocupar com ponteiros ainda.

#include <stdio.h>
#define L 2
#define C 4

//Exemplo com passagem por referência
void recebe_vetor(int matriz[L][C]) {
int i, j;

for(i=0;i<L;i++) {
for(j=0;j<C;j++) {
printf("entre com Vetor[%d][%d]: ",i,j);
scanf("%d",&matriz[i][j]);
}
}
}

int main(void) {
int matriz_A[L][C],matriz_B[L][C], soma[L][C];
int i, j;

printf("Matriz A\n");
recebe_vetor(matriz_A);

printf("\nMatriz B\n");
recebe_vetor(matriz_B);

printf("\nSoma\n");

for(i=0;i<L;i++) {
for(j=0;j<C;j++) {
soma[i][j] = matriz_A[i][j] + matriz_B[i][j];
printf("soma[%d][%d] = %d\n",i,j,soma[i][j]);
}
}

return 0;
}


3. Re: Função retornar Matriz- Problema [RESOLVIDO]

Rafael Marinho de Araújo
RafaelMA

(usa Manjaro Linux)

Enviado em 23/02/2016 - 12:08h

Concordo com o ednux, a melhor forma de tratar a situação e passar a matriz por referência


4. Re: Função retornar Matriz- Problema

Paulo
paulo1205

(usa Ubuntu)

Enviado em 23/02/2016 - 13:09h

RafaelMA escreveu:

Concordo com o ednux, a melhor forma de tratar a situação e passar a matriz por referência


Essa abordagem somente dá certo, no entanto, se todas as matrizes tiverem o mesmo tamanho. Se se quiser trabalhar com matrizes de dimensões diferentes, isso não funciona.

Note porém que o exemplo mostrado não passa as matrizes por referência, mas tão-somente uma referência para a primeira linha de cada matriz!

Quando usado como declaração de um argumento de função, a dimensão mais interna da matriz é desconsiderada, e a variável se comporta como um ponteiro para elementos que são arrays. Por exemplo, as quatro declarações de funções abaixo são absolutamente equivalentes do ponto de vista do compilador.

// f1, f2, f3 e f4 recebem argumento do tipo “ponteiro para
// array com 20 elementos inteiros”.
void f1(int mat[10][20]);
void f2(int mat[20][20]);
void f3(int mat[][20]);
void f4(int (*mat)[20]);

void g(void){
int m10_20[10][20];
int m20_20[20][20];

f1(m10_20); // OK, mas não pela razão aparentemente óbvia
f1(m20_20); // OK, ainda que à primeira vista não pareça
f2(m10_20); // OK, ainda que à primeira vista não pareça
f2(m20_20); // OK, mas não pela razão aparentemente óbvia
f3(m10_20); // OK, (lembrando que “[]” é sinônimo de “(*)” em declarações)
f3(m20_20); // OK, (idem)
f4(m10_20); // OK: referência para a primeira linha (como também acabou sendo acima)
f4(m20_20); // OK: idem
}


Essas equivalências se explicam pelo decaimento normal de arrays, quando usados como rvalues (i.e. qualquer operação exceto a declaração e a aplicação de sizeof ou &), para ponteiros.


Se você quiser realmente passar um array por referência, tem de deixar isso explícito.

// Argumento de f é do tipo “ponteiro para [array com 10 elementos
// do tipo (array com 20 elementos inteiros)]”. Além da declaração,
// mostro também como usar.
void f(int (*p_mat10_20)[10][20]){
for(int l=0; l<10; ++l)
for(int c=0; c<20; ++c)
(*p_mat10_20)[l][c]=l+c;
// Note que eu tenho de derreferenciar o ponteiro para obter
// a matriz sobre a qual se aplicam os índices.
}

void g(void){
int m10_20[10][20];
int m20_20[20][20];
int box[5][10][20];

f(&m10_20); // OK, mas note a presença do operador “&”.
f(&m20_20); // ERRO: tipo de ponteiro incompatível.
f(m10_20); // ERRO: ponteiro para linha de 20 ints, não ponteiro para matriz de 10×20 ints.
f(box); // OK, mas acede apenas ao primeiro nível de profundidade da caixa (i.e. “&box[0]”).
}



(Créditos para o EnzoFerber, que me ensinou, aqui neste fórum, há cerca de dois anos, a ler direito este tipo de coisa.)


5. Re: Função retornar Matriz- Problema [RESOLVIDO]

Marco Brainiac
mbrainiac

(usa Debian)

Enviado em 24/02/2016 - 10:55h

Muito obrigado pessoal, estou analisando toda a ajuda


6. Re: Função retornar Matriz- Problema [RESOLVIDO]

Marco Brainiac
mbrainiac

(usa Debian)

Enviado em 24/02/2016 - 10:57h

paulo1205 escreveu:

RafaelMA escreveu:

Concordo com o ednux, a melhor forma de tratar a situação e passar a matriz por referência


Essa abordagem somente dá certo, no entanto, se todas as matrizes tiverem o mesmo tamanho. Se se quiser trabalhar com matrizes de dimensões diferentes, isso não funciona.

Note porém que o exemplo mostrado não passa as matrizes por referência, mas tão-somente uma referência para a primeira linha de cada matriz!

Quando usado como declaração de um argumento de função, a dimensão mais interna da matriz é desconsiderada, e a variável se comporta como um ponteiro para elementos que são arrays. Por exemplo, as quatro declarações de funções abaixo são absolutamente equivalentes do ponto de vista do compilador.

// f1, f2, f3 e f4 recebem argumento do tipo “ponteiro para
// array com 20 elementos inteiros”.
void f1(int mat[10][20]);
void f2(int mat[20][20]);
void f3(int mat[][20]);
void f4(int (*mat)[20]);

void g(void){
int m10_20[10][20];
int m20_20[20][20];

f1(m10_20); // OK, mas não pela razão aparentemente óbvia
f1(m20_20); // OK, ainda que à primeira vista não pareça
f2(m10_20); // OK, ainda que à primeira vista não pareça
f2(m20_20); // OK, mas não pela razão aparentemente óbvia
f3(m10_20); // OK, (lembrando que “[]” é sinônimo de “(*)” em declarações)
f3(m20_20); // OK, (idem)
f4(m10_20); // OK: referência para a primeira linha (como também acabou sendo acima)
f4(m20_20); // OK: idem
}


Essas equivalências se explicam pelo decaimento normal de arrays, quando usados como rvalues (i.e. qualquer operação exceto a declaração e a aplicação de sizeof ou &), para ponteiros.


Se você quiser realmente passar um array por referência, tem de deixar isso explícito.

// Argumento de f é do tipo “ponteiro para [array com 10 elementos
// do tipo (array com 20 elementos inteiros)]”. Além da declaração,
// mostro também como usar.
void f(int (*p_mat10_20)[10][20]){
for(int l=0; l<10; ++l)
for(int c=0; c<20; ++c)
(*p_mat10_20)[l][c]=l+c;
// Note que eu tenho de derreferenciar o ponteiro para obter
// a matriz sobre a qual se aplicam os índices.
}

void g(void){
int m10_20[10][20];
int m20_20[20][20];
int box[5][10][20];

f(&m10_20); // OK, mas note a presença do operador “&”.
f(&m20_20); // ERRO: tipo de ponteiro incompatível.
f(m10_20); // ERRO: ponteiro para linha de 20 ints, não ponteiro para matriz de 10×20 ints.
f(box); // OK, mas acede apenas ao primeiro nível de profundidade da caixa (i.e. “&box[0]”).
}



(Créditos para o EnzoFerber, que me ensinou, aqui neste fórum, há cerca de dois anos, a ler direito este tipo de coisa.)


Muito obrigado vai me ajudar bastante


7. Re: Função retornar Matriz- Problema [RESOLVIDO]

Marco Brainiac
mbrainiac

(usa Debian)

Enviado em 24/02/2016 - 10:59h

ednux escreveu:

Reescrevi o seu código. Estava com muitos erros e difícil de entender.
Basicamente é o seguinte, você não pode alterar endereços constantes como " vet1[N][M] = retvet(); "
Essa forma de declaração cria uma matriz estática: int vet1[N][M];
Para realmente retornar uma matriz você teria que usar alocação dinâmica e depois libera-la.
Lembre-se do tipo de dado no retorno de uma função, se for uma matriz o prototipo seria assim: int **retorna_matriz();
Mas aconselho fortemente você a estudar ponteiros antes de usar alocação dinâmica.

O melhor exemplo que posso te dar agora é passagem por referência, dessa forma você consegue utilizar uma matriz dentro de uma função sem precisar se preocupar com ponteiros ainda.

#include <stdio.h>
#define L 2
#define C 4

//Exemplo com passagem por referência
void recebe_vetor(int matriz[L][C]) {
int i, j;

for(i=0;i<L;i++) {
for(j=0;j<C;j++) {
printf("entre com Vetor[%d][%d]: ",i,j);
scanf("%d",&matriz[i][j]);
}
}
}

int main(void) {
int matriz_A[L][C],matriz_B[L][C], soma[L][C];
int i, j;

printf("Matriz A\n");
recebe_vetor(matriz_A);

printf("\nMatriz B\n");
recebe_vetor(matriz_B);

printf("\nSoma\n");

for(i=0;i<L;i++) {
for(j=0;j<C;j++) {
soma[i][j] = matriz_A[i][j] + matriz_B[i][j];
printf("soma[%d][%d] = %d\n",i,j,soma[i][j]);
}
}

return 0;
}


Obrigado, está clareando para mim


8. Re: Função retornar Matriz- Problema [RESOLVIDO]

Perfil removido
removido

(usa Nenhuma)

Enviado em 24/02/2016 - 12:01h

Uma outra possibilidade é trabalhar com vetor unidimensional e fazer ele se comportar como bidimensional.

Seja m uma matriz 4 x 4 cujos elementos são identificados por índices ij. Por exemplo: ao invés de se declarar m[4][4], que é m[i][j], declara-se m[16] que possui o mesmo tamanho.

m[16] tem espaço de armazenamento que varia de m[0] a m[15]. Não se usa m[16].

Para fazer a coisa funcionar você usa uma expressão matemática que trabalha com valores de 0 a 3. com a expressão m[4*i+j]:

0*4+0 = 0
0*4+1 = 1
0*4+2 = 2
0*4+3 = 3

1*4+0 = 4
1*4+1 = 5
1*4+2 = 6
1*4+3 = 7

2*4+0 = 8
2*4+1 = 9
2*4+2 = 10
2*4+3 = 11

3*4+0 = 12
3*4+1 = 13
3*4+2 = 14
3*4+3 = 15

e fechamos a matriz. Isto também é bom para se usar com alocação dinâmica feita com malloc() ou calloc().

Além de se usar esta expressão, outra possibilidade é usar código inline ou criar uma espécie de macro com a pré-diretiva #define.

----------------------------------------------------------------------------------------------------------------
http://24.media.tumblr.com/tumblr_m62bwpSi291qdlh1io1_250.gif

# apt-get purge systemd (não é prá digitar isso!)

Encryption works. Properly implemented strong crypto systems are one of the few things that you can rely on. Unfortunately, endpoint security is so terrifically weak that NSA can frequently find ways around it. — Edward Snowden



9. Re: Função retornar Matriz- Problema [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 24/02/2016 - 13:59h

O que eu acho engraçado é a frequência com que a “melhor resposta” vai para uma resposta incompleta ou errônea...






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts