Problema con arreglo dinamico de estructura

Iniciado por palacio29, 15 Junio 2019, 00:48 AM

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

palacio29

Tengo que hacer un programa en el cual recibo por funcion un arreglo estatico de estructura y una letra.
Luego, tengo que crear un arreglo dinamico de estructura en el cual tengo que guardar los datos del arreglo estatico en el cual el codigo que tenga sea igual al pasado por parametro.
Luego, tengo que guardarlo en orden ascendente e imprimirlo por pantalla.
El problema es que en un momento del programa, creo que el problema esta en el while que esta entre la linea 51 y 64.

#include <stdio.h>
#include <stdlib.h>
#define T 3
struct s_alumno
{
    int leg;
    char*nombre;
    unsigned char cod_car
};
typedef struct s_alumno t_alumno;
t_alumno*filtrar(t_alumno[T],char cod_car);
int main()
{
    t_alumno arreglo[T];
    t_alumno*lista=NULL;
    int i=0;
    arreglo[0].leg=3;
    arreglo[1].leg=4;
    arreglo[2].leg=5;
    arreglo[0].nombre="Claudio";
    arreglo[1].nombre="Hernan";
    arreglo[2].nombre="Pablo";
    arreglo[0].cod_car='A';
    arreglo[1].cod_car='B';
    arreglo[2].cod_car='C';

    printf("Legajo: %d  - Nombre: %s - Codigo Carrera: %c\n",arreglo[0].leg,arreglo[0].nombre,arreglo[0].cod_car);
    printf("Legajo: %d  - Nombre: %s - Codigo Carrera: %c\n",arreglo[1].leg,arreglo[1].nombre,arreglo[1].cod_car);
    printf("Legajo: %d  - Nombre: %s - Codigo Carrera: %c\n",arreglo[2].leg,arreglo[2].nombre,arreglo[2].cod_car);

    lista=filtrar(arreglo,'B');

    while((lista+i)->leg!=0)
    {
        printf("Legajo: %d  - Nombre: %s - Codigo Carrera: %c\n",(lista+i)->leg,(lista+i)->nombre,(lista+i)->cod_car);
        i++;
    }

    return 0;
}
t_alumno*filtrar(t_alumno arreglo[T],char cod_car)
{

    t_alumno*nuevo=NULL;
    t_alumno aux;
    nuevo=malloc(sizeof(struct s_alumno));
    int i=0,j=0,k=0,maximo=0;
    char codigo;


    while(i<T)
    {
        if(arreglo[i].cod_car==cod_car)
        {
            (nuevo+k)->leg=arreglo[i].leg;
            (nuevo+k)->cod_car=arreglo[i].cod_car;
            strcpy((nuevo+k)->nombre,arreglo[i].nombre);
            printf("Legajo: %d  - Nombre: %s - Codigo Carrera: %c\n",(nuevo+k)->leg,(nuevo+k)->nombre,(nuevo+k)->cod_car);
            k++;
            nuevo=realloc(nuevo,(1+k)*sizeof(struct s_alumno));
        }
        i++;
    }
    (nuevo+k)->leg=0;
    printf("El legajo en el ultimo es %d",(nuevo+k)->leg);

            /// ORDENAR///
            for(maximo=0;(nuevo+maximo)->leg!=0;maximo++);
            printf("Maximo es %d",maximo);
            for(i=1;i<maximo;i++)
            {
                for(j=0;j<maximo-1;j++)
                {
                    aux=*(nuevo+j);
                    *(nuevo+j)=*(nuevo+j+1);
                    *(nuevo+j+1)=aux;
                }
            }


            return nuevo;

}

K-YreX

En ningún momento estás reservando memoria para <nombre> de ninguna instancia de la struct <s_alumno>. Lo único que haces en el <main> es hacer que el puntero a <nombre> apunte a una cadena literal que se encuentra en otra zona de memoria. Por lo tanto no puedes usar <strcpy()> ya que estás intentando copiar datos en una zona no permitida de memoria.

PD: Se agradecen nombres de variables más significativos que ayuden a seguir el programa con facilidad.
Código (cpp) [Seleccionar]

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

palacio29

Cita de: YreX-DwX en 15 Junio 2019, 02:25 AM
En ningún momento estás reservando memoria para <nombre> de ninguna instancia de la struct <s_alumno>. Lo único que haces en el <main> es hacer que el puntero a <nombre> apunte a una cadena literal que se encuentra en otra zona de memoria. Por lo tanto no puedes usar <strcpy()> ya que estás intentando copiar datos en una zona no permitida de memoria.

PD: Se agradecen nombres de variables más significativos que ayuden a seguir el programa con facilidad.

Disculpa por las variables, son horribles, ya lo se.
Y si quisiera asignar espacio en memoria para que funcione el strcpy que tendria que hacer?.
Porque la solucion que encontre es   (nuevo+k)->nombre=arreglo.nombre)

jmpesp

#3
Cita de: palacio29 en 15 Junio 2019, 00:48 AM
Tengo que hacer un programa en el cual recibo por funcion un arreglo estatico de estructura y una letra.
Luego, tengo que crear un arreglo dinamico de estructura en el cual tengo que guardar los datos del arreglo estatico en el cual el codigo que tenga sea igual al pasado por parametro.
Luego, tengo que guardarlo en orden ascendente e imprimirlo por pantalla.
El problema es que en un momento del programa, creo que el problema esta en el while que esta entre la linea 51 y 64.

Tal como dice el compañero, tu programa esta crasheando en strcpy() porque "nombre" es un "wild pointer" (puntero no inicializado, solo dios sabe hacia que region de la memoria apunta y que hay ahi).

Debes, o bien reemplazar el puntero por un array de tipo char con un tamano definido, o reservar memoria para almacenar el nombre en ese puntero en la heap utilizando malloc(), calloc() o realloc().

Te recomiendo que compiles tus programas con simbolos de depuracion (opcion -g en gcc) y utilices algun debugger para localizar este tipo de problemas.

Te vas a ahorrar mucho tiempo tratando de encontrar el problema en el codigo y con el debugger vas a localizar el problema al instante.

Por otra parte, no deberias usar strcpy().
Esta funcion copia la cadena de origen en la cadena de destino sin tener en cuenta el espacio disponible en el destino.

Si la cadena de origen es mas grande que el tama;o del buffer, este se desbordaria, lo cual podria corromper la memoria o ser manipulado intencionalmente para cambiar el flujo del programa.

Utiliza en su defecto strncpy() o memcpy().

La diferencia de estas dos funciones es que aceptan como parametro el tama;o del buffer y solo copian "lo que entre", de esta manera se evita el desborde.

arreglo[2].nombre="Pablo";

Haciendo esto el puntero "nombre" apunta hacia la cadena constante "Pablo".
Si haces eso tene en cuenta que no vas a poder modificar la cadena a la que apunta "nombre" ya que es una constante.



K-YreX

Cita de: palacio29 en 15 Junio 2019, 04:21 AM
Disculpa por las variables, son horribles, ya lo se.
Y si quisiera asignar espacio en memoria para que funcione el strcpy que tendria que hacer?.
Porque la solucion que encontre es   (nuevo+k)->nombre=arreglo.nombre)
Con esa solución que dices que has encontrado lo que haces es que el puntero <nombre> apunte a la misma cadena constante que apunta <arreglo>. Con esto ahorras reservas de memoria pero no estás "haciendo copias" del nombre, lo que estás haciendo es que los punteros apunten al mismo sitio.

Si lo quieres hacer con memoria dinámica tendrías que reservar memoria y cambiar las líneas 20-22 (que están haciendo que el puntero apunte al nombre) por <strncpy()> para copiar literalmente el contenido del <string> en el nuevo array dinámico que has creado.
Código (cpp) [Seleccionar]

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