• Duda con bucle "for" en C

 #444494  por Baal_30
 30 May 2014, 00:27
Hola, estoy siguiendo unos tutoriales, y en uno de ellos, se usa esta función :

void comparar(int filas, int columnas, int **m1, int **m2){
int i,j,aux=0;

for(i=0;i<filas && aux == 0;i++){
for(j=0;j<columnas && aux == 0;j++){
if (m1[j] != m2[j]){
aux = 1;

}
}
}
if (aux == 0){
printf("Ambas matrices son iguales.\n");
}
else{
printf("Ambas matrices no son iguales.\n");
}
}

Y al quedarme mirándola... No entiendo cuando se dará el caso del segundo "if", ya que si aux es == 0, el blucle for no dejaría de repetirse nunca, y para que dejara de repetirse, aux tendría que ser != 0, y en ese caso se iría al "else" de abajo, ¿no? Estoy bastante mareado, no se si es porque estoy cansado, pero eso que tenía más o menos claro, ahora no se ni por donde cogerlo. Espero haberme explicado con claridad.

Gracias de antemano y buenas noches :)
 #444524  por Baal_30
 30 May 2014, 09:25
Si, si m1[j] != m2[j] entonces aux es 1, y ahí se saldría y se iría directamente al "else" ¿no? Porque mientras siga siendo m1 igual a m2, aux será siempre 0, y con ello seguirá el bucle, o eso es lo que entiendo yo.
 #444526  por NvK
 30 May 2014, 09:46
cambie void por bool en la funcion... realmente no comprendo en su totalidad sobre que código quiere comparar o lo que quiere hacer.
¿Podria ser mas especifico?, e idente por favor asi entendemos todos...
for(i=0;i<filas && aux == 0;i++){
  for(j=0;j<columnas && aux == 0;j++){
    if (m1[i][j] != m2[i][j]){
      //printf("Ambas matrices son iguales.\n");
      return 1;
    }
  }
}
return 0
Edito: si compara el numero de filas podria hacer m1[j] != m2[j] en vez de (m1[j] != m2[j])
 #444534  por Baal_30
 30 May 2014, 14:45
Si el código que he compartido está correcto y funciona, lo que no entiendo es el por qué.
 #444539  por NvK
 30 May 2014, 15:36
Todavía no comprendo del todo sobre que es aplicable así que tratare de ser lo más "analitico" posible:
imaginemos que tenemos 3 filas y 4 columnas(sistema 3x4) el primer bucle i++ correra el numero de filas(es decir 3) al caer en el segundo bucle j++(que correra 4 columnas * fila) el primer valor del array bidimensional m1[j] (supongamos que hay un valor de 0x30) comparara el valor del segundo array bidimensional es decir m2[j] que tendra las mismas filas y columnas en ese momento, también hay que mensionar que al ser de dos dimensiones guarda 2 tipos de datos simultaneamente lo que es muy útil en video juegos(por ejemplo) para crear matrizes de niveles, al ser !=(distinto que) decimos que lo que buscara es que si alguna no es igual(o ambos arreglos) la función de por terminado su trabajo...
en pocas palabras:
m1[0][0]= 0x1;
m1[1][0]= 0x2;
m1[0][1]= 0x3;

m2[0][0]= 0x1;
m2[1][0]= 0x2;
m2[0][1]= 0x4; // Aqui se terminaria la funcion dentro de los bucles, es distinto a m1
recuerda también que los arrays de más de una dimension no son de memoria contigua, dime si he sido claro.
 #444545  por Baal_30
 30 May 2014, 17:06
No se si me explico bien.

El "if" ese, dice que si m1 y m2 son diferentes, aux es igual a 1, entonces se saldría se saldría del bucle y se iría directamente al "else". ¿Cierto?
Hasta ahí todo bien, pero si da que m1 y m2 son iguales, aux será SIEMPRE 0 ¿Si o no? Entonces, mientras aux sea 0, el bucle "for" no dejará nunca de correr. ¿No?

//Edito : Ah, a ver, en el caso de que sea m1 y m2 iguales, el bucle "for", no dejará de correr hasta que "i" o "j" llegue al número de "filas" o "columnas" ¿Verdad? Entonces ahí automáticamente se saldrá del bucle, y el aux se mantendría en 0, así que dará el mensaje de que son iguales. Si es así, creo que ya lo he entendido...
 #444549  por NvK
 30 May 2014, 17:28
Baal_30 escribió:No se si me explico bien.

El "if" ese, dice que si m1 y m2 son diferentes, aux es igual a 1, entonces se saldría se saldría del bucle y se iría directamente al "else". ¿Cierto?
Hasta ahí todo bien, pero si da que m1 y m2 son iguales, aux será SIEMPRE 0 ¿Si o no? Entonces, mientras aux sea 0, el bucle "for" no dejará nunca de correr. ¿No?

//Edito : Ah, a ver, en el caso de que sea m1 y m2 iguales, el bucle "for", no dejará de correr hasta que "i" o "j" llegue al número de "filas" o "columnas" ¿Verdad? Entonces ahí automáticamente se saldrá del bucle, y el aux se mantendría en 0, así que dará el mensaje de que son iguales. Si es así, creo que ya lo he entendido...
Por supuesto que no. En el código original no hay break o return que garantize que si el array es muy grande haya optimizacion(osea que se salga del bucle), de lo contrario recorrera todo y si en un futuro trabajas con punteros hacer eso daria consecuencias catastroficas...
El bucle correra siempre, no es optimo ni mucho menos seguro.
 #444552  por Baal_30
 30 May 2014, 17:49
Entonces, es una mala forma de hacer eso, ¿no?, Mira, te pego el código entero del ejercicio por si quieres ver para que era esa función. Lo he hecho como lo explican, no se si será la mejor forma para hacerlo. El ejercicio era para explicar las funciones y memoria dinámicas... Gracias.

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

int reservar(int filas, int columnas);
void introduce(int filas, int columnas, int **mat);
void comparar(int filas, int columnas, int **m1, int **m2);

int main(){
	
	int filas, columnas;
	int **m1;
	int **m2;
	
	printf("Introduce el numero de filas: ");
	scanf("%i",&filas);
	printf("Introduce el numero de columnas: ");
	scanf("%i",&columnas);
	
	m1 = reservar(filas,columnas);
	m2 = reservar(filas,columnas);
	
	introduce(filas,columnas,m1);
	introduce(filas,columnas,m2);
	
	comparar(filas,columnas,m1,m2);
	
	system("pause");
	return 0;
}

int reservar(int filas, int columnas){
	
	int i;
	int **mat;
	mat = (int**)malloc(filas*sizeof(int));
	if( mat == NULL ){
		printf("No se ha podido reservar memoria.\n");
		exit(1);
	}
	
	for(i=0;i<filas;i++){
		mat[i] = (int*)malloc(columnas*sizeof(int));
		if(mat[i] == NULL){
			printf("No se ha podido reservar memoria. \n");
			exit(1);
		}
	}
	
	return mat;
	
}

void introduce(int filas, int columnas, int **mat){
	int i,j;
	
	for(i=0;i<filas;i++){
		for(j=0;j<columnas;j++){
			printf("Introduce un valor para el elemento [%i][%i]: ",i,j);
			scanf("%i",&mat[i][j]);
		}
	}
}

void comparar(int filas, int columnas, int **m1, int **m2){
	int i,j,aux=0;
	
	for(i=0;i<filas && aux == 0;i++){
		for(j=0;j<columnas && aux == 0;j++){
			if (m1[i][j] != m2[i][j]){
				aux = 1;
				
			}
		}
	}
	if (aux == 0){
		printf("Ambas matrices son iguales.\n");
	}
	else{
		printf("Ambas matrices no son iguales.\n");
	}
}
 #444553  por NvK
 30 May 2014, 18:00
Hasta reservar vamos bien(aun que bien podria haber retorna el total de bloques y no el bloque en si, eso se pudo hacer desde el main..).
Introduce y Comparar estan mal, definitivamente...
Usa scanf lo que es muuuy peligroso(de hecho esta obsoleto) ya que se podria producir un desbordamiento, para evitar todo esto usa: fgets(mat[j], TAM_DEL_BUFFER, stdin); entonces
lo "agarra" de la entrada estandar y con un tamaño de buffer limitado.
Y comparar no es para nada optima ni segura haz esto:
bool comparar(int filas, int columnas, int **m1, int **m2){
    int i,j;
     
    for(i=0;i<filas;i++){
        for(j=0;j<columnas;j++){
            if (m1[i][j] != m2[i][j]){
                //printf("Ambas matrices no son iguales.\n");
                return 1;
            }
        }
    }
    //printf("Ambas matrices son iguales.\n");
    return 0;
}
 #444554  por Baal_30
 30 May 2014, 18:17
Joder pues vaya del tío que estoy aprendiendo, porque él lo hace todo así :/

Gracias por la ayuda NvK. Lo que ahora no entiendo es que tipo de función es "bool" (aún no la he aprendido) y tampoco se como funcionan los return :(

Y, puede que esté equivocado, pero, ¿no te falta un "else" para meter el return 0; ?

Gracias!
 #444555  por Pino1952
 30 May 2014, 18:24
Hola a todos.-
recuerda también que los arrays de más de una dimension no son de memoria contigua...
NvK me queda una duda con respecto a esta frase, entonces la imagen que pongo a continuación es incorrecta o te réferis a otra cosa.-



Saludos.-
Daniel
 #444556  por NvK
 30 May 2014, 18:28
jeje tranquilo todos empezemos desde 0. Mira las funciones en que en C que dicen void son las que no retornan ningun valor, en terminos menos formales, una vez que una funcion termina la aplicacion continua(hasta que termina el programa obviamente), si esa funcion retorna un valor puedes guardarlo en una variable o usarlo con algun fin...
entonces al declarar una funcion bool(verdadero o falso), al terminar puedes hacer algo así:
if ( comparar(filas,columnas,m1,m2) == 1 )
 printf("Ambas matrices no son iguales.\n");
else
 printf("Ambas matrices son iguales.\n");
osea aqui comparar retorna y en el caso de que sea 1 imprime el primer printf y si no el segundo.
 #444557  por NvK
 30 May 2014, 18:29
Pino1952 escribió:Hola a todos.-
recuerda también que los arrays de más de una dimension no son de memoria contigua...
NvK me queda una duda con respecto a esta frase, entonces la imagen que pongo a continuación es incorrecta o te réferis a otra cosa.-



Saludos.-
Daniel
Saludos daniel, mira los array bidimensionales trabajando con punteros no son de memoria contigua

EDITO: Es decir jamas pueden ser de memoria contigua por que dentro del modelo de memoria todo se separa en el heap, pero no sucede lo mismo con los arrays de 1 dimension.
 #444559  por NvK
 30 May 2014, 18:54
Perdon que haga doble post es que quería aclarar algo...
Un array bidimensional estatico si es de memoria contigua, pero uno que se declara dinamicamente no lo es.
Ejemplo:
char **p;
p= (char **)malloc(3 * sizeof(char *)); // un array de 3 indices de forma dinamica
//char *p[3] de forma estatica
p[0]= malloc(TAM_VALOR); /* ahora si ya se reserva memoria para el indice del array en si
con el tamaño deseado */
p[1]= malloc(TAM_VALOR);
p[2]= malloc(TAM_VALOR);
... // etc..
Lo pude hacer con un bucle pero para efectos de prueba así es mas entendible
y al hacerlo de forma dinamica la ventaja es que en un futuro lo puedes reagrandar con realloc.
Esto es una ventaja si tu aplicacion trabaja constatemente con valores impredecibles y que debes recalcular, pero recuerda siempre liberarar memoria si no las consecuencias en el sistema operativo podrían ser desastrosas...