[C] Devolver array bidimensional mediante una función

Iniciado por crawler!, 23 Junio 2013, 23:02 PM

0 Miembros y 2 Visitantes están viendo este tema.

crawler!

¿es posible? Y si lo es, ¿cómo se hace? Soy bastante novato y me vendria bien una ayudita  ;D Saludos!

amchacon

No es posible devolver un array bidimensional (bueno en realidad hay un truquillo para hacerlo usando memoria dinámica pero no vale la pena).

Lo que se suele hacer es pasar el array a la funcion:

Código (cpp) [Seleccionar]
void Funcion(int Matriz[5][5])
{

  // ...

}


La matriz conservará los cambios al finalizar la función ;)
Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar

crawler!

#2
Gracias por responder amchacon!

Quieres decir que cuando le pasas un array como parámetro se pasa automáticamente por referencia ¿no? ¿Así de simple? ¿no es necesario usar punteros ni nada? Yo habia pensado en utilizar

void Matriz(int *[10]);

void Matriz(int (*m)[10]) {
     (modificación de la matriz)
}

int main()
. . .
int mat[10][10];
Matriz(mat);
. . .


¿Existe alguna diferencia entre usar este código y usar el que me has dicho? A ver si me puedes aclarar esto por que el tema de los punteros no me acaba de quedar claro.

Saludos.

ThePinkPanther

#3
#include <iostream>
#include <vector>
#define longz 10
using namespace std;
void Matriz(int (*m)[10]) {

for(int i=0;i<10;i++)
for(int j=0;j<10;j++)
{
   cout<<m[i][j];
}


}


int main()
{
int mat[10][10];
for(int i=0;i<10;i++)
for(int j=0;j<10;j++)
{
   mat[i][j]=j;
}
Matriz(mat);
}



Así anda. :P
y de la otra forma tambien, no se si existe una diferencia .
aunque no es necesario usar punteros,directamente se pasa por referencia , podes usar el modificador const para que no se modifique el array, si es que vas a realizar solo operaciones de lectura

crawler!

Ese code no es de C++? De todos modos he utilizado el método que me ha dicho emchacon y funciona tal como deseaba :) Sólo queria saber si en este caso, cuando se trata de arrays, hay alguna diferencia entre utilitzar punteros o no, ya que diria que sólo es útil cuando trabajas con tipos de datos que se envian por valor, p.e. ints, chars, etc. Pero el problema está solucionado ;)

ecfisa

Hola  crawler!.

Citar¿Existe alguna diferencia entre usar este código y usar el que me has dicho?

Ambas formas son equivalentes:

// mat como arreglo de arreglos de 3 enteros
void cargar1(int mat[][3], int rows)
{
  int c , r;
  for(r = 0; r < rows; r++)
    for(c = 0;c < 3; c++)
      mat[r][c] = c + r;

}

// mat como puntero a un arreglo de tres enteros
void cargar2(int (*mat)[3], int rows)
{
  int c, r;
  for(r = 0; r < rows; r++)
    for(c = 0;c < 3 ;c++)
      mat[r][c] = c + r;
}


Otra forma de pasar el arreglo bidimensional por referencia (accediendo como C/C++ lo almacenan en memoria) es:


// mat como puntero al primer elemento del arreglo
void cargar3(int *mat, int cols, int rows)
{
int c, r;
  for(r = 0; r < rows; r++)
    for(c = 0; c < cols; c++)
      mat[r * cols + c] = r + c;
}


Saludos :)

ThePinkPanther

Cita de: ecfisa en 24 Junio 2013, 03:03 AM


Otra forma de pasar el arreglo bidimensional por referencia (accediendo como C/C++ lo almacenan en memoria) es:


// mat como puntero al primer elemento del arreglo
void cargar3(int *mat, int cols, int rows)
{
int c, r;
  for(r = 0; r < rows; r++)
    for(c = 0; c < cols; c++)
      mat[r * cols + c] = r + c;
}




esto es unidimensional.

ecfisa

Citaresto es unidimensional.

Hola ThePinkPanther.

La forma de acceso dentro de la función es lineal, pero el argumento enviado es un arreglo bidimensional y a eso me refiero en el mensaje anterior: 
CitarOtra forma de pasar el arreglo bidimensional por referencia ...


Como ejemplo, este código incrementa en uno cada elemento de un arreglo declarado como bidimensional y de ese modo es enviado a la función como argumento:

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

void load(int *mat, int, int);
void show(int mat[][3], int);

int main(int argc, char* argv[])
{
  int mat[3][3] = {{0,1,2}, {3,4,5}, {6,7,8}};
  load(mat, 3, 3);
  show(mat, 3);
  getchar();
  return 0;
}

void load(int *mat, int cols, int rows)
{
int c, r;
for(r = 0; r < rows; r++)
   for(c = 0; c < cols; c++)
     mat[r * cols + c] += 1;
}

void show(int mat[][3], int rows)
{
  int c, r;
  for(r = 0; r < rows; r++){
    for(c = 0; c < 3; c++)
      printf("%d ",mat[r][c]);
    printf("\n");
  }
}


Es decir, el modo de acceso que se utilice dentro de la función no altera el caracter bidimensional de la declaración del arreglo.

Saludos. :)

crawler!

Muchas gracias ecfisa!! A mi también me había quedado la duda de si en el tercer ejemplo mat se declaraba como un array unidimensional, pues yo creía que siempre era necesario indicar la longitud de los arrays (a partir del 1ero). Además al compilar recibes el siguiente warning "passing arg 1 of 'Function' from incompatible pointer type" pero supongo que mientras funcione bien... :D

ecfisa

#9
Hola crawler!.

Si estas compilando el ejemplo bajo C++, tendrías que agregar:
Código (c++) [Seleccionar]

 ...
 load((int*)mat, 3, 3);

Reemplazar por los header files correspondientes y los printf por cout (si no se me escapa algo mas...).

Saludos. :)