6. a – Matrices Genéricas

Una matriz genérica en el contexto de programación en C se refiere a una estructura de datos bidimensional que puede contener elementos de cualquier tipo, en contraste con una matriz específica que está limitada a un tipo de datos particular. En C, no existe un tipo de datos nativo que permita crear matrices completamente genéricas, pero se pueden simular utilizando punteros y asignación dinámica de memoria.

Inicialización: Se asigna memoria dinámicamente para la matriz y sus elementos individuales. Esto se hace mediante el uso de funciones como malloc().

  1. Acceso a elementos: Los elementos de la matriz genérica se acceden a través de punteros a void. Estos punteros deben ser convertidos al tipo de datos deseado antes de poder operar con ellos.
  2. Liberación de memoria: Después de haber terminado de usar la matriz genérica, es importante liberar la memoria asignada utilizando funciones como free().

En resumen, una matriz genérica en C es una estructura de datos flexible que permite almacenar elementos de diferentes tipos en una matriz bidimensional, utilizando punteros a void y asignación dinámica de memoria. Esto puede ser útil en situaciones donde se necesita trabajar con datos heterogéneos o cuando el tipo de datos no está determinado de antemano.

  • Cuando se tiene doble asterisco es la cantidad de des-referencias que tengo que hacer para llegar a la variable del elemento.
  • Los punteros a void no se pueden desreferenciar.
  • Desde void ** no puedo acceder pero si puedo acceder desde int **.
  • Cuando creo tipo de dato void, en realidad estoy reservando memoria en bytes y luego puedo guardar lo que yo quiera. Puede ser una estructura, un entero, un flotante, etc.
  • Desde un doble puntero a void puedo hacer aritmética de puntero porque apunta a un puntero a void. Pero desde un puntero a void no puedo hacer aritmética de puntero porque no se a que tipo de dato apunta.

Lo primero que hago es crear la matriz con malloc y hago la cantidad de filas por el sizeof del tipo de dato.

Esto lo hago:

void ** mat = malloc ( cantFilas * sizeof(void*)); // reservo memoria para todas los punteros a void de filas. if(!mat) { return NULL; }

Y luego hago para cada vector en un ciclo for. Este ciclo for lo tengo que recorrer desde i hasta ult. Estos los debo calcular. i va a ser el inicio ( mat ) y ult va a ser desde mat+cantFilas -1.

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

void ** crearMatriz ( size_t cantFilas, size_t cantColumnas, size_t tamElem);
void destruirMatriz ( void** mat, size_t filas);
int sumarDiagPrincipal ( int ** mat, size_t cols);
void cargarMatriz (int ** mat, size_t filas, size_t columnas);
void mostrarMatriz (int ** mat, size_t filas, size_t columnas);
int main()
{
    int filas = 4;
    int columnas =4;
    int ** matriz = (int**)crearMatriz(filas, columnas, sizeof(int));
    if(!matriz)
    {
        puts("Sin Memoria");
        return 0;
    }

    cargarMatriz(matriz,filas,columnas);
    mostrarMatriz(matriz,filas,columnas);

    int acum = sumarDiagPrincipal(matriz,columnas);
    printf("Suma diagonal: %d \n", acum);
    destruirMatriz((void**)matriz, filas);
    return 0;

}



void ** crearMatriz ( size_t cantFilas, size_t cantColumnas, size_t tamElem)
{
    //tamElem esta en bytes
    void ** mat = malloc ( cantFilas * sizeof(void*));
    // reservo memoria para todas los punteros a void de filas.
    if(!mat)
    {
        return NULL;
    }
    void **ult = mat + cantFilas -1;
    for (void ** i = mat; i<=ult; i++)
    {
        *i = malloc(cantColumnas * tamElem);
        if(!*i)
        {
            for(void** j=mat; j<i; j++)
            {
                free(*j);
            }
            free(mat); // si hago solo free de mat libera la primer columna y el resto no.
            return NULL;
        }

    }
    return mat;
}


void destruirMatriz ( void** mat, size_t filas)
{
    void** ult = mat + (filas -1);
    for( void ** i = mat ; i<=ult; i++)
        free(*i);
    free(mat);
}



void cargarMatriz (int ** mat, size_t filas, size_t columnas)
{
    for(int i = 0; i <filas; i++)
        for(int j=0; j<columnas; j++)
            mat[i][j]=i*4+j+1;

}



int sumarDiagPrincipal ( int ** mat, size_t cols)
{
    int sum =0;
    for(int i =0; i<cols; i++)
        sum+= mat[i][i];
    return sum;

}


void mostrarMatriz (int ** mat, size_t filas, size_t columnas)
{
    for(int i = 0; i <filas; i++)
    {
        for(int j=0; j<columnas; j++)
            printf("%d \t", mat[i][j]);
        printf("\n");
    }
}