martes, 9 de febrero de 2010

Crear matrices dinámicas con c y c++

Bien, ahí va el código en c++ de como crear una matriz dinamicamente.

#include
using namespace std;

int main()
{
    int i,j,f,c;

    cout << "Introduce el numero de filas" << endl;
    cin >> f;
    cout << "Introduce el numero de columnas" << endl;
    cin >> c;

    // creamos la matriz !
    double **M = new double* [f];
    for (i = 0; i < f; i++)
        M[i] = new double[c];

    // Comprobamos
    if (!M)
    {
        cout << "No se puede reservar el espacio" << endl;
        return 1;
    }

    cout << "Introduzca la matriz" << endl;
    for (i = 0; i < f; i++)
        for (j = 0; j < c; j++)
            cin >> M[i][j];

    cout << "Mostrar la matriz" << endl;
    for (i = 0; i < f; i++)
    {
        for (j = 0; j < c; j++)
            cout << M[i][j] << " ";
        cout << endl;
    }
    delete [] M;

    return 0;
}

En C, como no existe "new" ni "delete" hay que utilizar las funciones "malloc()" y "free()", sustituyendo:

double  *a = new double;      // si solo queremos uno.
double  *b = new double[x];   // donde x es el nºde elementos que queremos
double **c = new double* [x]; // x puntero a puntero. (varios)
por
double  *a = (double*)malloc(sizeof(double));
double  *b = (double*)malloc(sizeof(double) * x);
double **c = (double**)malloc(sizeof(double*) * x);

y para el "delete", que usariamos:

delete a;
delete [] b;

lo cambiamos por:

free(a);
free(b);

En estos ejemplos he usando datos de tipo "double", pero acordaros que podria ser de cualquier tipo como por ejemplo "int", "short"...

Para no complicar las cosas solo he comprobado que se a podido reservar memoria para el vector principal (bloque de memoria de f elementos, que son punteros que "apuntaran" al primer elemento de los bloques de c elementos), y no he puesto nada para comprobar si se han podido crear los demas.

Como seguramente no hayáis entendido nada de lo ultimo que puse entre paréntesis, por lo que os lo muestro gráficamente usando de ejemplo una matriz de 3 filas y 4 columnas.


*Es posible que haya fallos, correcciones o algún tipo de errata que debiera modificar así que si ves alguna avísame. Gracias
Comparte o puntua esta publicación ▼

14 comentarios:

Yoban Rodriguez dijo...

una duda, en este programa se puede utilizar estructuras/registros???

Anónimo dijo...

David aca encontre la página que le falta a todos los libros de C++ hasta donde yo he visto... Gracias por el aporte muy bueno

Anónimo dijo...

Me sirvió mucho tu explicación, muchas gracias por compartir tu conocimiento, saludos

pavel anselmo alvarez carrillo dijo...

Amigo, una pregunta si tienes oportunidad de ayudarme.

Estoy intentanto hacer una matriz dinámica mediante un método que se encuentra en otro archivo y le paso la matriz para que me quenere el espacio en memoria pero no está funcionando, cada vez que acceso algun espacio en memoria me genera un error de "default null assignment".

Supongo que el espacio que se está asignando se pierde. El código sería así:

allocate.c
————————————————————————————————————
matriz(double **m, r, c)
{
m = (double **) malloc ( r * sizeof(double*) );

for(i=0; i<r; i**)
{
m[i] = (double *) malloc (col * sizeof(double) );
}

}


principal.c
————————————————————————————————————

#include “allocate.c”

double **mi_matriz;
int i;

void main()
{
matriz(mi_matriz, 5, 4);

for(i=0; i<r; i**)
{
free( matriz[i] ); // aquí me muestra el error cuando i=0;
}
free( matriz );


}

David Gonzalez dijo...

Hola pavel, he realizado unas pequeñas correcciones para que el código que me pasaste funcione, el principal problema seria que le la función matriz recibe un puntero a double** lo que seria double***

luego te pongo en otro comentario otra manera que puede que sea mas sencilla.

Saludos

//allocate.c
//————————————————————————————————————

void matriz(double ***m, int r, int c)
{
*m = (double **) malloc ( r * sizeof(double*) );
int i;
for(i = 0; i < r; i++)
{
(*m)[i] = (double *) malloc (i * sizeof(double) );
}
}


//principal.c
//————————————————————————————————————

//#include “allocate.c”

double **mi_matriz;
int i;

int main()
{
int r = 5, c = 4;
matriz(&mi_matriz, r, c);

for(i = 0; i < r; i++)
{
free((void*)mi_matriz[i] );
}
free((void*)mi_matriz );
}

David Gonzalez dijo...

Pavel: Mira esta otra manera de hacer lo mismo, ahora la función retorna la dirección de la matriz...

Espero que te ayude. Saludos

//allocate.c
//————————————————————————————————————

double** matriz(int r, int c)
{
double **m = (double **) malloc ( r * sizeof(double*) );
int i;
for(i = 0; i < r; i++)
{
m[i] = (double *) malloc (i * sizeof(double) );
}

return m;
}


//principal.c
//————————————————————————————————————

//#include “allocate.c”

double **mi_matriz;
int i;

int main()
{
int r = 5, c = 4;
mi_matriz = matriz(r, c);

for(i = 0; i < r; i++)
{
free((void*)mi_matriz[i] );
}
free((void*)mi_matriz );
}

pavel anselmo alvarez carrillo dijo...

Hola David
Utilicé el segundo ejemplo que me comentas y está funcionando.
Te agradezco mucho la ayuda, por cierto tu explicación inicial de matrices dinámicas es muy buena.

Saludos!!

Anónimo dijo...

Buenas David como se programaría un método para insertar un elemento en esa matriz

pavel anselmo alvarez carrillo dijo...

Hola Anónimo, particularmente que necesitas hacer?, porque a simple vista parecería que no se justifica un método para insertar un elemento en la matriz, si estamos hablando de asiganar valores a los elementos de la matriz.

Yo usaria la sentencia así mi_matriz[ i ][ j ] = valor;
mi_matriz[0][0]=1;
mi_matriz[0][1]=3;
...
mi_matriz[n][m]=2;

Anónimo dijo...

buena la explicacion

Alfonso Aguilar dijo...

Buenas, lo primero muchas gracias por el gran post, llevo muy poco en esto del C++ y de la programacion en general y me costaba encontrar algun sitio donde lo explicaran bien. Pero ahora mi problema es que no se como devolver el puntero doble que pertence a una clase para que pueda usarlo en otra. Para probar cree este minicodigo pero me da el error al ejecutarlo de segmentation fault 11, alguna sugerencia??

#include

using namespace std;

class pdoble
{

public:
pdoble(int fil, int col){
int **M = new int*[fil];
for(int i =0;i<fil;i++){
M[i] = new int[col];
}
for (int i = 0; i < fil; i++){
for (int j = 0; j < col; j++){
M[i][j]=1;
}
}


}
int& getM(){
return **M;
}


private:
int fil, col;
int **M;
};

int main(){

pdoble aap(2,2);
int *P;
*P=aap.getM();
cout<<P<<endl;

}

David Gonzalez dijo...

Hola Alfonso.

El principal problema era que creabas una nueva variable int **M dentro del constructor (no usabas el int **M de la clase).
por otro lado he corregido el método getM para que retorne la matriz correctamente y el metodo main para que funcione. Actualmente lo que hace el programa es mostrar la dirección de la matriz. Para acceder a un elemento solo habría que hacer P[fila][columna].


#include

using namespace std;

class pdoble
{

public:
pdoble(int fil, int col)
{
M = new int*[fil];
cout<<M<<endl;
for(int i =0; i<fil; i++)
{
M[i] = new int[col];
}
for (int i = 0; i < fil; i++)
{
for (int j = 0; j < col; j++)
{
M[i][j]=1;
}
}


}

int** getM()
{
return M;
}


private:
int fil, col;
int **M;
};

int main()
{
pdoble aap(2,2);
int **P;
P=aap.getM();
cout<<P<<endl;
}

Alfonso Aguilar dijo...

Fenómeno. Muchísimas gracias, ahora ya entiendo el problema.

Ariel cardenas dijo...

Buenas.. intento hacer un metodo en c++ que me agregue un elemento en una posicion.... utilizando punteros...
este es el metodo que he hecho, pero solo puedo agregar elementos en la primera fila...
agradeceria que alguien me ayude...
void insertarPosicion(int posX, int posY, int dato){
if (posX==0 and posY==0){
primerNodo= new NodoMatriz(dato);
size_fila++;
size_colum++;
}else{
int cont_filas=0;
int cont_colum=0;
NodoMatriz* recorre_filas=primerNodo;
while (cont_filasdown;
cont_filas++;
}
NodoMatriz* recorre_colum= recorre_filas;
while(cont_columnext;
cont_colum++;
}
if (posX>size_fila-1){
recorre_colum->down= new NodoMatriz(dato);
size_fila++;

}else{
recorre_colum->next= new NodoMatriz(dato);
size_colum++;
}
}
}

Publicar un comentario