Matriz dinamica en C [RESUELTO]

Iniciado por andie13, 17 Diciembre 2016, 15:04 PM

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

andie13

Hola!
Quiero crear una matriz dinámica con funciones básicas.
Aquí solo hay una porción de código para guardar espacio, leer y escribir la matriz (soy consciente de que falta liberar la memoria y más cosas).
El caso es que no me funciona y creo que el fallo está en el modo de uso de punteros, pero no entiendo por qué. Si alguien me puede explicar por qué está mal, se lo agradezco mucho.
Gracias!

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

typedef struct{
   int filas;
   int columnas;
   int *datos;
}Matriz;

void CrearMatriz (Matriz *m, int f, int c){
   m=(Matriz*)malloc(sizeof(Matriz));
   
   f=m->filas;
   c=m->columnas;
   m->datos=(int*)malloc(f*c*sizeof(int));
   
   if (m==NULL || m->datos==NULL){    
       printf("Memoria insuficiente.\n");
       exit(1);
   }
}
void LeerMatriz(Matriz *m){
   int i=0,j=0;
   for(i=0; i<m->filas; i++)
   {
       for(j=0; j<m->columnas; j++)
       {              
           printf("Escriba o valor para M(%d,%d) = ",i+1,j+1);
           scanf("%d",*(m->datos + i+j));
       }
   }
}

void EscribirMatriz(Matriz *m){
   int i=0,j=0;
   
   printf("\n\tLa matriz es: "); /*RUTINA PARA IMPRIMIR*/
   for(i=0;i<m->filas;i++){
       printf("\n\t");
       for(j=0;j<m->columnas;j++){
           printf("  %d  ", *(m->datos+i)+j); //M[i][j]
           }
   }
}

void TransponerMatriz(Matriz *m){
   int i=0,j=0;
   
   printf("\n\n\tLa transpuesta es: ");/*IMPRIMIR MATRIZ TRANSPUESTA*/
   for(i=0;i<m->columnas;i++){
       printf("\n\t");
       for(j=0;j<m->filas;j++){
           printf("  %d  ", *(m->datos+i+j)); //M[j][i]
           }
   }
}
int main(){
   Matriz m;
     
   printf("Introduzca numero de filas: ");
   scanf("%d",&m.filas);
   printf("Introduzca numero de columnas: ");
   scanf("%d", &m.columnas);
   
   CrearMatriz(&m,m.filas,m.columnas);
   LerMatriz(&m);
   EscribirMatriz(&m);
   TransponerMatriz(&m);
   return 0;
}

ivancea96

Si no te compila, es por unas razones. Esas razones, te las dice el compilador en los errores. ¿Qué errores te da el compilador?

andie13

Perdón, me expresé mal.
Sí que me compila, lo que hace es que no funciona correctamente. Perdón por la mala expresión.
Yo creo que el error está en los scanf o algo parecido, porque el programa al ejecutarlo sí que me deja indicarle el número de filas y columnas y me pide una matriz del correspondiente tamaño.

Gracias por tomarte tu tiempo respondiéndome.

ivancea96

En ese caso, sé más específico con qué problema te da :P

De todos modos, mira esto:
scanf("%d",*(m->datos + i+j));

Para (i=0, j=2), será "m->datos + 2". Para (i=2, j=0), será "m->datos + 2". Es decir, lo mismo.

Tienes varias opciones. La más fácil sería tener una matriz de 2 dimensiones con un doble puntero (int**). Así, podrías acceder a los datos de esta forma: m->datos[0][2], sin necesidad de hacer operaciones manualmente.

Te redirijo aste post que encontré por Google: http://www.linuxhispano.net/2011/08/17/reservar-memoria-dinamica-para-una-matriz-en-c/
Ahí ves un código de ejemplo simple.

andie13

Gracias por la aportación  ;).
Aún así, he declarado el campo de la estructura con un vector de punteros **datos, y he cambiado el scanf que me has dicho, pero me da error justo al llegar a esa línea de código. No sé si es que te he entendido mal y no lo puse como me dijiste, o si se debe a otra cosa.
Muchas gracias!

void LeerMatriz(Matriz *m)
{
    int i=0,j=0;
    for(i=0; i<m->filas; i++)
    {
        for(j=0; j<m->columnas; j++)
        {               
            printf("Escriba o valor para M(%d,%d) = ",i+1,j+1);
            scanf("%d", m->datos[i][j]);
        }
    }
}

ivancea96

Bueno, hay que cambiar a un int**, y hay que hacer un par de cosas más.
En primer lugar, a la hora de crear la matriz, que es lo que pasé en el link. Primero, reservamos memoria para X punteros, que serán las columnas (o las filas, como sea). Luego, a cada uno de esos punteros le reservamos memoria para 1 file (o columna). Así, el pimer puntero dirige a un "array de columnas", y cada array de columnas es un array de celdas, una fila.
Echa un ojo al código de la url.

MAFUS

Si no has tocado crearMatriz y sigues con el código original tienes el problema de qur perderás la dirección adquirida con malloc cuando salgas de la función.

Como solo pasas un puntero, m, has de tener en cuenta de que pasas una copia de la dirección así, cuando la cambies con el uso de malloc, la dirección en main no habrá cambiado. Has adquirido la dirección y la habrás llenado pero la perderás.

Para solucionar esto usa un puntero a puntero,  así podrás pasar el puntero por referencia y podrás cambiarlo. O haces que la función regrese un puntero hacer un return al puntero creado con malloc. En este caso no hace falta que pases el puntero por los argumentos de la función.

andie13

Si elimino m=(Matriz*)malloc(sizeof(Matriz));
me funciona correctamente. ¿Debería de ejecutar algún bucle para guardar memoria o quitando eso llegaría? así no me da problema ninguno.
gracias por responder!

MAFUS

Déjalo así. Ahora funciona por la razón de que estás modificando un objeto que existe en main. Pero sí que deberás liberar la memoria de la variable datos, dentro de la estructura.