(Consulta) Problema con un arreglo dinamico

Iniciado por palacio29, 31 Mayo 2019, 01:04 AM

0 Miembros y 1 Visitante están viendo este tema.

palacio29

Tengo el siguiente ejercicio que no se que es lo que esta fallando.  :huh:
Tengo una estructura  en la cual tengo:

- Una variable int que carga el legajo de un alumno (un numero cualquiera)
- Un puntero char, en donde se va a guardar el nombre del alumno (Ejemplo Juan)
- Un unsigned char en donde se guarda el codigo de una materia. (Ejemplo CATEGORIA B).

En el main lo que hago es cargar un arreglo estatico de esta estructura.
Lo que tengo que hacer con la funcion filtrar es crear un arreglo dinamico que cree e incluya los valores del arreglo estatico que tengan la categoria B.
No se cual es el error, pensaba que era algo de memoria dinamica que estaba fallando, pero puse una memoria grande e igualmente el programa falla.

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#define T 3
struct s_alumno
{
    unsigned int leg;
    char*nombre;
    unsigned char cod_car;
};
typedef struct s_alumno t_alumno;
t_alumno* filtrar(t_alumno arr[T],char cod_car);
void IMPRIMIR(t_alumno*);

int main()
{
    t_alumno arr[T];
    int i=0;
    char letra;
    t_alumno* listado=NULL;
    arr[0].nombre="Fabian";
    arr[1].nombre="Pablo";
    arr[2].nombre="Manuel";
    while(i<T)
    {
        printf("\nCARGAR NUMERO LEGAJO:\n ");
        scanf("%d",&arr[i].leg);
        printf("CARGAR CODIGO CARRERA\n");
        letra=getche();
        arr[i].cod_car=letra;
        i++;
    }
    printf("\n");
    printf("El nombre cargado es %s - CODIGO DE CARRERA: %c\n",arr[0].nombre,arr[0].cod_car);
    printf("El nombre cargado es %s - CODIGO DE CARRERA: %c\n",arr[1].nombre,arr[1].cod_car);
    printf("El nombre cargado es %s - CODIGO DE CARRERA: %c\n",arr[2].nombre,arr[2].cod_car);
    listado=filtrar(arr,'B');
    IMPRIMIR(listado);

    return 0;
}


t_alumno* filtrar(t_alumno arr[T],char cod_car)
{
    int i=0,j=0,fin=0;
    t_alumno*lista=NULL;
    lista=malloc(sizeof(struct s_alumno));
    while(i<T)
    {
        if((cod_car)==arr[i].cod_car)
        {
            (lista+j)->leg=arr[i].leg;
            strcpy((lista+j)->nombre,arr[i].nombre);
            (lista+j)->cod_car=arr[i].cod_car;
            j++;
           lista=realloc(lista,(j+1)*sizeof(struct s_alumno));
        }
        i++;
    }
    (lista+j)->leg=0;
    printf("\nTERMINO EL FILTRADO\n");
    return lista;

}

void IMPRIMIR(t_alumno* listado)

{
int i=0;
printf ("\nIMPRESION DEL ARREGLO\n");
while(listado[i].leg!=0)
{
     printf("NOMBRE: %s - CODIGO DE CARREA: %c\n",(listado+i)->nombre,(listado+i)->cod_car);
     i++;
}
}

K-YreX

Varias cosas... Primero sobre los nombres. Al usar cadenas literales no estás reservando memoria en cada <struct> para guardar los nombres. Lo que estás haciendo es que los punteros del <struct> apunten a la dirección de memoria en la que se encuentran esas cadenas almacenadas desde antes de la ejecución del programa.
Entonces a la hora de crear la nueva lista con el filtro, no puedes copiar los nombres usando <strcpy()> puesto que tampoco estás reservando memoria para estos. Lo único que puedes hacer es hacer que los punteros a <char> de las nuevas <struct> apunten a las mismas cadenas literales.

Ahora sobre el <realloc()>. Si no reservas memoria con <malloc()> (cosa que no deberías hacer) lo único que tienes es un puntero a <t_alumno>. Entonces para "insertar" un nuevo <t_alumno> tendrás que hacer el <realloc()> antes, no después.

Para saber cuántos <t_alumno> hay en el filtro yo usaría otro parámetro por referencia para contabilizarlos y así no tener que poner el último <leg> a 0.

t_alumno* filtrar(t_alumno *arr, char cod_car, size_t *num_filtrados){
t_alumno *filtro = NULL; // tenemos un array vacio
*num_filtrados = 0;

for(size_t i = 0; i < SIZE; ++i){
if(arr[i].cod_car == cod_car){ // si son iguales...
(*num_filtrados)++; // ...tenemos un elemento mas en el filtro...
filtro = (t_alumno*) realloc(filtro, *num_filtrados * sizeof(t_alumno)); // ...y reservamos memoria para introducirlo
filtro[*num_filtrados-1].leg = arr[i].leg;
filtro[*num_filtrados-1].nombre = arr[i].nombre; // hacemos que apunte al mismo sitio que arr[i].nombre, no copiamos la cadena porque no hay memoria
filtro[*num_filtrados-1].cod_car = arr[i].cod_car;
}
}
printf("\nTERMINO EL FILTRADO\n");
return filtro;
}
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;