[C] Paso de arreglos bidimensionales a funciones. (?)

Iniciado por oblivionxor, 19 Febrero 2013, 17:29 PM

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

oblivionxor

Hola que tal. Lo que pasa es que en este codigo:

/*Asignacion de valores en arreglos bidimensionales*/
#include <stdio.h>

/*Prototipos de funciones*/
void imprimir_arreglo( const int a[2][3] );

/*Inicia la ejecucion del programa*/
int main()
{
  int arreglo1[2][3] = { { 1, 2, 3 },
                         { 4, 5, 6 } };                         
  int arreglo2[2][3] = { 1, 2, 3, 4, 5 };
  int arreglo3[2][3] = { { 1, 2 }, { 4 } };
 
  printf( "Los valores en el arreglo 1 de 2 filas y 3 columnas son:\n" );
  imprimir_arreglo( arreglo1 );
 
  printf( "Los valores en el arreglo 2 de 2 filas y 3 columnas son:\n" );
  imprimir_arreglo( arreglo2 );
 
  printf( "Los valores en el arreglo 3 de 2 filas y 3 columnas son:\n" );
  imprimir_arreglo( arreglo3 );
 
  return 0;
}  /*Fin de main*/

/*Definiciones de funciones*/
void imprimir_arreglo( const int a[2][3] )
{
  int i;  /*Contador filas*/
  int j;  /*Contador columnas*/
 
  for (i = 0; i <=1; i++)
  {
    for (j = 0; j <= 2; j++)
    {
      printf( "%d ", a[i][j] );
    }
   
    printf( "\n" );
  }
} /*Fin de funcion imprime_arreglo*/


Cuando compilo de esa manera me da estos errores mi compilador:
Citar
ArreglosBidimensionales.c: In function 'main':
ArreglosBidimensionales.c:16:3: warning: passing argument 1 of 'imprimir_arreglo' from incompatible pointer type [enabled by default]
ArreglosBidimensionales.c:5:6: note: expected 'const int (*)[3]' but argument is of type 'int (*)[3]'
ArreglosBidimensionales.c:19:3: warning: passing argument 1 of 'imprimir_arreglo' from incompatible pointer type [enabled by default]
ArreglosBidimensionales.c:5:6: note: expected 'const int (*)[3]' but argument is of type 'int (*)[3]'
ArreglosBidimensionales.c:22:3: warning: passing argument 1 of 'imprimir_arreglo' from incompatible pointer type [enabled by default]
ArreglosBidimensionales.c:5:6: note: expected 'const int (*)[3]' but argument is of type 'int (*)[3]'

Pero cuando compilo quitandole el calificador de tipo const al prototipo y definicion de funciones es decir asi:

/*Prototipos de funciones*/
void imprimir_arreglo( int a[2][3] );

.......

/*Definiciones de funciones*/
void imprimir_arreglo( int a[2][3] )
{

Si puedo compilar correctamente.

Por que pasa eso? Por que en arreglos unidimensionales si puedo compilar con el calificador const y en los bidimensionales no? Alguien me puede ayudar con esta duda?
Por cierto uso el compilador GNU GCC.
Agradecimientos por adelantado.

Sputnik_

#1
en c++ funciona  :xD
saludos  
Las personas lo suficientemente locas como para pensar que pueden cambiar el mundo son las que lo cambian.

leosansan

Ya te lo está diciendo el compilador: espera un const int y tú le mandas un int. Lo que quiere decir que tienes mal tipificadaos los arreglos, que deberían ser:

Citar
....................................................................
 const int arreglo1[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };                      

 const int arreglo2[2][3] = { 1, 2, 3, 4, 5 };
 
 const int arreglo3[2][3] = { { 1, 2 }, { 4 } };
  .......................................................................

Saluditos!.

oblivionxor

leosansan pero por que cuando declaro arreglos unidimensionales, aunque no los declare como const, si puedo compilar correctamente cuando paso los arreglos a parametros const de una funcion?
Asi mira:

#include <stdio.h>

void intenta_modificar_arreglo( const int b[] );

/* Inicia la ejecucion */
int main()
{
int a[] = { 1, 2, 10 };

intenta_modificar_arreglo( a );

printf( "%d %d %d\n", a[0], a[1], a[2] );

return 0;
} /* Fin de main */

/*------------------Definicion de funciones-----------------------*/
void intenta_modificar_arreglo( const int b[] )
{
b[0] /= 2;
b[1] /= 2;
b[2] /= 2;
} /* Fin de funcion intenta_modificar_arreglo */

Que es lo que pasa, por que en arreglos unidimensionales si se puede evadir la declaracion const y en los bidimensionales no?? Esa es mi duda???

leosansan

#4
Cita de: oblivionxor en 19 Febrero 2013, 19:34 PM
.......................... Esa es mi duda???

Y me has creado otra a mí. Espero que alguien como rir o afín nos saque de la duda. :o
por cierto, para mantener el paralelismo con el bidimensional he usado:
Código (cpp) [Seleccionar]
#include <stdio.h>

void intenta_modificar_arreglo( const int b[3] );

/* Inicia la ejecucion */
int main()
{
int a[3] = { 1, 2, 10 };

intenta_modificar_arreglo( a );


return 0;
} /* Fin de main */

/*------------------Definicion de funciones-----------------------*/
void intenta_modificar_arreglo( const int b[3] )
{
int j;
for (j = 0; j <= 2; j++)
   {
     printf( "%d ", b[j] );
   }

} /* Fin de funcion intenta_modificar_arreglo */


Pero no "cantan" ahora los warnings :o :o

Saluditos!.

oblivionxor

Si espero que nos saquen de la duda :c ojala y sean tan amables de aclararnoslo.

amchacon

En C++ tira perfecto, creo que tiene que ver con las limitaciones de C y la pila.

Puedes crearlo dinámicamente y entonces si te irá:

/*Asignacion de valores en arreglos bidimensionales*/
#include <stdio.h>
#include <stdlib.h>

/*Prototipos de funciones*/
void imprimir_arreglo( const int** a);

/*Inicia la ejecucion del programa*/
int main()
{
 int i = 0;
 int** arreglo1 = (int**)malloc(3*sizeof(int*));
 
 for (i = 0; i < 3;i++)
       arreglo1[i] = (int*)malloc(2*sizeof(int));

 //int** arreglo2[2][3] = { {1, 2, 3},{ 4, 5, 6 }};
 //int** arreglo3[2][3] = { { 1, 2 }, { 4 } };

 printf( "Los valores en el arreglo 1 de 2 filas y 3 columnas son:\n" );
 imprimir_arreglo((const int**) arreglo1 );

 printf( "Los valores en el arreglo 2 de 2 filas y 3 columnas son:\n" );
 //imprimir_arreglo( arreglo2 );

 printf( "Los valores en el arreglo 3 de 2 filas y 3 columnas son:\n" );
 //imprimir_arreglo( arreglo3 );

 return 0;
}  /*Fin de main*/

/*Definiciones de funciones*/
void imprimir_arreglo( const int** a)
{
 int i;  /*Contador filas*/
 int j;  /*Contador columnas*/

 for (i = 0; i <=1; i++)
 {
   for (j = 0; j <= 2; j++)
   {
     printf( "%d ", a[i][j] );
   }

   printf( "\n" );
 }
} /*Fin de funcion imprime_arreglo*/
Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar

BatchianoISpyxolo

Te pego una práctica que hice hará 2 meses o así para que veas más o menos el manejo de arrays bidimensionales en C.

/*

FIC - 2º GRADO - Algortimos
Practica 4
Maquina donde se han testado los algoritmos:
Equipo portatil personal. Intel(R) Core(TM) i3 CPU M 370 @ 2.40GHz x64

*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <limits.h>
#include <math.h>
#include "lista.h"

typedef int ** matriz;

// algoritmo de prim
lista prim(matriz m, int tam) {
    int min, i, j, r, k=0;
    arista a;
    lista l;
    int *masProximo = (int *) malloc(tam*sizeof(int));
    int *distanciaMinima = (int *) malloc(tam*sizeof(int));
    crear_lista(&l);
    distanciaMinima[0] = -1;
    for(i = 1; i < tam; i++) {
        masProximo[i] = 0;
        distanciaMinima[i] = m[i][0];
    }
    for (r=1; r<tam; r++) { /* bucle voraz */
        min = INT_MAX;
        for (j=1;j<tam;j++) {
            if (0<=distanciaMinima[j] && distanciaMinima[j]<min) {
                min = distanciaMinima[j];
                k = j;
            }
        }
a.x = masProximo[k]; a.y = k; a.peso = min;
insertar(a,&l);
distanciaMinima[k] = -1;
for (j=1;j<tam;j++) {
if (m[j][k] < distanciaMinima[j]) {
distanciaMinima[j] = m[j][k];
masProximo[j] = k;
}
}
    }
    free(masProximo);
    free(distanciaMinima);
    return l;
}

// crea una matriz
matriz crear_matriz(int n) {
    int i;
    matriz aux;
    if ((aux = (int **) malloc(n*sizeof(int *))) == NULL)
        return NULL;
    for (i=0; i<n; i++)
        if ((aux[i] = (int *) malloc(n*sizeof(int))) == NULL)
            return NULL;
    return aux;
}

// genera la matriz del primer ejemplo
matriz matriz_primer_ejemplo() {
int i,j;
matriz m = (matriz)crear_matriz(5);
m[0][1] = 1; m[0][2] = 8; m[0][3] = 4; m[0][4] = 7;
m[1][2] = 2; m[1][3] = 6; m[1][4] = 5;
m[2][3] = 9; m[2][4] = 5;
m[3][4] = 3;
for (i=0; i<5; i++)
for (j=0; j<=i; j++)
if (i==j)
m[i][j] = 0;
else
m[i][j] = m[j][i];
return m;
}

// genera la matriz del segundo ejemplo
matriz matriz_segundo_ejemplo() {
int i,j;
matriz m = (matriz)crear_matriz(4);
m[0][1] = 1; m[0][2] = 4; m[0][3] = 7;
m[1][2] = 2; m[1][3] = 8;
m[2][3] = 3;
for (i=0; i<4; i++)
for (j=0; j<=i; j++)
if (i==j)
m[i][j] = 0;
else
m[i][j] = m[j][i];

return m;
}

// genera la matriz del tercer ejemplo
matriz matriz_tercer_ejemplo() {
int i,j;
matriz m = (matriz)crear_matriz(7);
m[0][1] = 7; m[0][2] = 99; m[0][3] = 5; m[0][4] = 99; m[0][5] = 99; m[0][6] = 99;
m[1][2] = 8; m[1][3] = 9; m[1][4] = 7; m[1][5] = 99; m[1][6] = 99;
m[2][3] = 99; m[2][4] = 5; m[2][5] = 99; m[2][6] = 99;
m[3][4] = 15; m[3][5] = 6; m[3][6] = 99;
m[4][5] = 8; m[4][6] = 9;
m[5][6] = 11;
for (i=0; i<7; i++)
for (j=0; j<=i; j++)
if (i==j)
m[i][j] = 0;
else
m[i][j] = m[j][i];
return m;
}

void inicializar_matriz(matriz m, int n) {
    /* Crea un grafo completo no dirigido con pesos aleatorios entre 1 y n */
    int i, j;
    for (i=0; i<n; i++)
        for (j=i+1; j<n; j++)
            m[i][j] = rand() % n + 1;
    for (i=0; i<n; i++)
        for (j=0; j<=i; j++)
            if (i==j)
                m[i][j] = 0;
            else
                m[i][j] = m[j][i];
}

void liberar_matriz(matriz m, int n) {
    int i;
    for (i=0; i<n; i++)
        free(m[i]);
    free(m);
}

void solucion(lista l) {

    pnodo it = primera(l);
    int peso_total = 0;
    printf("Aristas: ");
    while (it != NULL) {
        printf("(%d, %d) ", it->elemento.x, it->elemento.y);
        peso_total += it->elemento.peso;
        it = siguiente(it);
    }
    printf("\nPeso total minimo: %d\n", peso_total);
    eliminar_lista(&l);
}

void test () {
printf("\n- test para probar el correcto funcionamiento del algoritmo -\n\n");
matriz m = matriz_primer_ejemplo();
matriz n = matriz_segundo_ejemplo();
matriz o = matriz_tercer_ejemplo();
printf("Primer ejemplo.\n");
solucion(prim(m,5));
printf("\nSegundo ejemplo.\n");
solucion(prim(n,4));
printf("\nTercer ejemplo.\n");
solucion(prim(o,7));
printf("\n");
liberar_matriz(m,5);
liberar_matriz(n,4);
liberar_matriz(o,7);
}

double microsegundos() {
struct timeval t;
if (gettimeofday(&t, NULL) < 0 )
return 0.0;
return (t.tv_usec + t.tv_sec * 1000000.0);
}

double obtener_tiempo(int N, int *umbral){
#define ITER 1000
int i;
double t1, t2, t3, t4, t5, t6, t;
matriz M = crear_matriz(N);
inicializar_matriz(M,N);
t1 = microsegundos();
prim(M,N);
t2 = microsegundos();
t = t2-t1;
liberar_matriz(M,N);
*umbral = 0; // t < 500us
if (t<500) {
*umbral = 1; // t >= 500us
matriz A = crear_matriz(N);
// t3 = tiempo de inicializacion + tiempo prim
for (i=1; i<=ITER; i++) {
t1 = microsegundos();
inicializar_matriz(A,N);
prim(A,N);
t2 = microsegundos();
t3 += (t2-t1);
}
// t6 = tiempo de inicializacion
for (i=1; i<=ITER; i++) {
t4 = microsegundos();
inicializar_matriz(A,N);
t5 = microsegundos();
t6 += (t5-t4);
}
t = (t3-t6) / ITER;
liberar_matriz(A,N);
}
return (t<0 ? -t : t);
}

void medicion_tiempos() {

#define REPS 6
int n, N, it; // variables para control de bucles y parámetros de entrada
int umbral; // umbral de tiempo de ejecucion (500 us) { 1 = Supera umbral, 0 = No supera umbral }
double t; // tiempo de ejecucion
double h, g, f; // valores para acotar

printf("- Medicion de tiempos del algoritmo -\n\n");

printf("-> h(n) = cota subestimada\n");
printf("-> g(n) = cota ajustada\n");
printf("-> f(n) = cota sobrestimada\n");
printf("\n-------------------------------------------------------------------------\n");
printf("\n%9s%13s%13s%13s%13s%10s\n","n", "t(n)", "t(n)/h(n)", "t(n)/g(n)", "t(n)/f(n)", "Umbral"); // encabezado

n = 16;
for (it=1; it<=REPS; it++) {
n = n*2-1;
N = (int)sqrt(n);
t = obtener_tiempo(N, &umbral);
h = t / pow(N*N, 1.8); // t(n)/h(n)
g = t / pow(N*N, 2); // t(n)/g(n)
f = t / pow(N*N, 2.2); // t(n)/f(n)
printf("%9d%13.6f%12.6f%13.6f%13.6f%8d\n", N*N, t, h, g, f, umbral);
}
printf("\n-------------------------------------------------------------------------\n");

}

int main () {

printf("\nPractica 4: Analisis del algortimo de Prim.\n");
test();
medicion_tiempos();

}
Puede que desees aprender a programar desde 0: www.espascal.es

rir3760

Por partes.

Cita de: oblivionxor en 19 Febrero 2013, 17:29 PMPor que en arreglos unidimensionales si puedo compilar con el calificador const
Primero porque las funciones no ven en ningún momento un array, cuando de declara una función en la forma:
int fn(int a[]);

/* O */

int fn(int a[N]);

Esta se procesa como si la declaración fuera:
int fn(int *a);
Es por ello que no puede obtenerse el tamaño del array pasado como argumento y tampoco importa indicar el numero de elementos de este, la función simplemente recibe un puntero: la dirección en memoria de su primer elemento.

Segundo por que a una función que espere como argumento un puntero a objeto constante (tipo "const T *") puede pasarse un puntero sin el calificador const (tipo "T *") sin ningún problema: la conversión implícita de un tipo a otro ("T *" ==> "const T *") se aplica de forma transparente salvo una excepción.

Un ejemplo para explicar de una forma mas clara los dos puntos anteriores:
#include <stdio.h>
#include <stdlib.h>

int suma(const int *valor, size_t num_elem);

int main(void)
{
   int valor[] = {1, 2, 3};
   size_t num_elem = sizeof valor / sizeof valor[0];
   
   printf("Suma == %d\n", suma(valor, num_elem));
   
   return EXIT_SUCCESS;
}

int suma(const int *valor, size_t num_elem)
{
   size_t i;
   int total;
   
   total = 0;
   for (i = 0; i < num_elem; i++)
      total += valor[i];
   
   return total;
}


Cita de: oblivionxor en 19 Febrero 2013, 17:29 PMy en los bidimensionales no?
Porque la excepción son los "arrays bidimensionales".

Aquí un paréntesis: C no tiene punteros "dobles", "triples", etc. como tampoco arrays "unidimensionales", "bidimensionales", etc. solo tiene punteros y arrays. Que el tipo apuntado sea también un puntero o el elemento del array un array es otra historia.

Cuando se pasa un array de arrays como argumento de una función esta recibe la dirección de su primer elemento, si el tipo del array es "T [N][M]" la función recibe un puntero de tipo "T (*)[M]".

Y aquí la conversión implícita "T *" ==> "const T *" falla porque el calificador const no se aplica al array, se aplica a sus elementos. Es por ello que tu compilador genera el mensaje de tipos distintos:
CitarArreglosBidimensionales.c:5:6: note: expected 'const int (*)[3]' but argument is of type 'int (*)[3]'

La única solución es declarar al array utilizando const o bien realizar la conversión explicita en la llamada a función.

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

oblivionxor

Wow rir quedo todo superclaro! Muchisimas gracias por tu respuesta! Saludos.