elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado:


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Punteros y memoria dinamica
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Punteros y memoria dinamica  (Leído 2,525 veces)
bemone

Desconectado Desconectado

Mensajes: 74



Ver Perfil
Punteros y memoria dinamica
« en: 28 Agosto 2015, 19:11 pm »

Buenas tardes gente,

Estoy aprendiendo C y me estoy rompiendo el marote contra la pared bien fuerte.
Tengo una estructura Persona. La cual quiero manipularla dinamicamente a traves de la estructura Array (TDA) y me surgio un problema que desconozco a que se puede deber.

Si cargo el array desde el main() todo funciona perfecto. Cuando lo quiero cargar a traves de un metodo, se rompe todo.

He aqui el codigo:

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4.  
  5. typedef struct persona{
  6.    char *nombre;
  7.    int edad;
  8.    int sexo;
  9. }Persona;
  10.  
  11. typedef struct {
  12.    int size;
  13.    Persona vecPersona[];
  14. }Array;
  15.  
  16. Array* getArrayInstance(){
  17.    Array *vec;
  18.    vec = (Array*) malloc (sizeof(Persona));
  19.    vec->size = 0;
  20.    return vec;
  21. }
  22.  
  23. void push_back(Array ** vec, Persona tipito){
  24.    (*vec)->vecPersona[(*vec)->size] = tipito;
  25.    (*vec)->size++;
  26.    printf("%d-", (*vec)->size);
  27.    int newSize = (*vec)->size*2-(*vec)->size+1;
  28.    Array *tmp = realloc((*vec), newSize*sizeof(Persona));
  29.    if(tmp)
  30.        *vec = tmp;
  31.    else
  32.        (*vec)->size--;
  33. }
  34.  
  35. void mostrarPersonas(Array *vec){
  36.    int i;
  37.    printf("\n\n");
  38.    printf("%d", vec->size);
  39.    for(i=0; i<vec->size; i++){
  40.        printf("(%d) Nombre: %s - Edad: %d - Sexo: ", i, vec->vecPersona[i].nombre, vec->vecPersona[i].edad);
  41.        if(vec->vecPersona[i].sexo == 0)
  42.            printf("Masculino");
  43.        else
  44.            printf("Femenino");
  45.        printf("\n");
  46.    }
  47. }
  48.  
  49. void cargarPersonas(Array **vec){
  50.    int i, edad, random;
  51.    int cantPersonas = rand()%30+1;
  52.    Persona aux;
  53.    char **hombres = {"Ramiro","Pedro","Federico","Jose","Antonio","Pablo","Raul","Gustavo","Gonzalo","Airton"};
  54.    char **mujeres = {"Mariana","Jennifer","Luz","Roxana","Ana","Sol","Micaela","Romina","Melina","Camila"};
  55.    for(i=0; i<cantPersonas; i++){
  56.        edad = rand()%80+1;
  57.        aux.edad = edad;
  58.        if( (random = rand()%10) %2 == 0){ // hombres
  59.            aux.nombre = hombres[random];
  60.            aux.sexo = 0;
  61.        }
  62.        else{
  63.            aux.nombre = mujeres[random];
  64.            aux.sexo = 1;
  65.        }
  66.  
  67.        push_back(vec, aux);
  68.    }
  69. }
  70.  
  71.  
  72. int main()
  73. {
  74.    srand(time(NULL));
  75.    Array *vecPersonas = getArrayInstance();
  76.  
  77.    Persona aux;
  78.    aux.nombre="Cecilia";
  79.    aux.edad=27;
  80.    aux.sexo=0;
  81.    push_back(&vecPersonas, aux); // Esto anda
  82.    push_back(&vecPersonas, aux); // Esto anda
  83.    push_back(&vecPersonas, aux); // Esto anda
  84.    push_back(&vecPersonas, aux); // Esto anda
  85.    push_back(&vecPersonas, aux); // Esto anda
  86.    push_back(&vecPersonas, aux); // Esto anda
  87.  
  88.    //cargarPersonas(&vecPersonas); // Esto no
  89.    //printf("%d", vecPersonas->size);
  90.    mostrarPersonas(vecPersonas);
  91.  
  92.    return 0;
  93. }
  94.  
  95.  

 :-\ :-\


« Última modificación: 28 Agosto 2015, 19:25 pm por bemone » En línea

Odio los tipos de variable de Windows.
ivancea96


Desconectado Desconectado

Mensajes: 3.412


ASMático


Ver Perfil WWW
Re: Punteros y memoria dinamica
« Respuesta #1 en: 29 Agosto 2015, 01:20 am »

Código
  1. Array* getArrayInstance(){
  2.    Array *vec;
  3.    vec = (Array*) malloc (sizeof(Persona));
  4.    vec->size = 0;
  5.    return vec;
  6. }

(Array*) malloc(sizeof(Persona));

Si vas a crear un Array, entonces tendrás que poner sizeof(Array), puesto que Array tiene un tamaño de sizeof(Persona*) + sizeof(int) = 8 bytes, mientras que Persona tiene un tamaño de 12 bytes.


En línea

bemone

Desconectado Desconectado

Mensajes: 74



Ver Perfil
Re: Punteros y memoria dinamica
« Respuesta #2 en: 29 Agosto 2015, 01:57 am »

Código
  1. Array* getArrayInstance(){
  2.    Array *vec;
  3.    vec = (Array*) malloc (sizeof(Persona));
  4.    vec->size = 0;
  5.    return vec;
  6. }

(Array*) malloc(sizeof(Persona));

Si vas a crear un Array, entonces tendrás que poner sizeof(Array), puesto que Array tiene un tamaño de sizeof(Persona*) + sizeof(int) = 8 bytes, mientras que Persona tiene un tamaño de 12 bytes.

Perdon, creo que me exprese mal.
Quiero un Array dinamico dentro de una estructura.
Lo que me decis vos es para crear un array de Array.
En línea

Odio los tipos de variable de Windows.
ivancea96


Desconectado Desconectado

Mensajes: 3.412


ASMático


Ver Perfil WWW
Re: Punteros y memoria dinamica
« Respuesta #3 en: 29 Agosto 2015, 02:58 am »

No, es correcto. Pon malloc(sizeof(Array)), puesto que estás reservando memoria del tamaño de Array.

Otra cosa importante: en vez de:
Código
  1. Persona vecPersona[];
pon:
Código
  1. Persona *vecPersona;
Puesto que es un puntero.

Además, tienes otros errores como, en push_back:

Código
  1. int newSize = (*vec)->size*2-(*vec)->size+1;

No sé qué pretendes sacar con esa ecuación. Al principio, siendo size=1, haces un realloc((*vec)->vecPersona, 0). Y ya luego, valores altos. Eso debería quedar:

Código
  1. int newSize = (*vec)->size+1;

En fin, he reconstruido esa función:
Código
  1. void push_back(Array ** vec, Persona tipito){
  2. int newSize = (*vec)->size+1;
  3. Persona *tmp = realloc((*vec)->vecPersona, newSize*sizeof(Persona));
  4. if(tmp){
  5. (*vec)->vecPersona = tmp;
  6. (*vec)->vecPersona[(*vec)->size] = tipito;
  7. (*vec)->size++;
  8. }
  9.    printf("%d-", (*vec)->size);
  10. }

Además, inicialicé el contenido de vecPersona en getArrayInstance:
Código
  1. Array* getArrayInstance(){
  2.    Array *vec;
  3.    vec = (Array*) malloc (sizeof(Array));
  4. vec->vecPersona = 0;
  5.    vec->size = 0;
  6.    return vec;
  7. }

Y otro tema muy importante:

Código
  1. char *hombres[] = {"Carlos", "Pablo"};
No puedes poner un doble puntero para ser inicializado de ese modo.


Además, en push_back te recomiendo poner:

Código
  1. (*vec)->vecPersona[(*vec)->size].nombre = (char*) malloc((strlen(tipito.nombre)+1)*sizeof(char));
  2. strcpy((*vec)->vecPersona[(*vec)->size].nombre, tipito.nombre);

Copiar las cadenas, no copiar los punteros, puesto que si se libera la memoria de uno de ellos, todos los demás perderán lso datos, y podrán tirar errores.

Claro que si vas a hacer un método "pop", tendrás que recordar liberarlos.

Bueno, este es el código completo, por si quieres ver qué se cambió más claramente:

Para strlen y strcpy, la librería <string.h>

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <time.h>
  5.  
  6. typedef struct persona{
  7.    char *nombre;
  8.    int edad;
  9.    int sexo;
  10. }Persona;
  11.  
  12. typedef struct {
  13.    int size;
  14.    Persona *vecPersona;
  15. }Array;
  16.  
  17. Array* getArrayInstance(){
  18.    Array *vec;
  19.    vec = (Array*) malloc (sizeof(Array));
  20. vec->vecPersona = 0;
  21.    vec->size = 0;
  22.    return vec;
  23. }
  24.  
  25. void push_back(Array ** vec, Persona tipito){
  26. int newSize = (*vec)->size+1;
  27. Persona *tmp = realloc((*vec)->vecPersona, newSize*sizeof(Persona));
  28. if(tmp){
  29. (*vec)->vecPersona = tmp;
  30. (*vec)->vecPersona[(*vec)->size] = tipito;
  31. (*vec)->vecPersona[(*vec)->size].nombre = (char*) malloc((strlen(tipito.nombre)+1)*sizeof(char));
  32. strcpy((*vec)->vecPersona[(*vec)->size].nombre, tipito.nombre);
  33. (*vec)->size++;
  34. }
  35. }
  36.  
  37. void mostrarPersonas(Array *vec){
  38.    int i;
  39.    printf("\n\n");
  40.    for(i=0; i<vec->size; i++){
  41.        printf("(%d) Nombre: %s - Edad: %d - Sexo: ", i, vec->vecPersona[i].nombre, vec->vecPersona[i].edad);
  42.        if(vec->vecPersona[i].sexo == 0)
  43.            printf("Masculino");
  44.        else
  45.            printf("Femenino");
  46.        printf("\n");
  47.    }
  48. }
  49.  
  50. void cargarPersonas(Array **vec){
  51.    int i, edad, random;
  52.    int cantPersonas = rand()%30+1;
  53.    Persona aux;
  54.    char *hombres[] = {"Ramiro","Pedro","Federico","Jose","Antonio","Pablo","Raul","Gustavo","Gonzalo","Airton"};
  55.    char *mujeres[] = {"Mariana","Jennifer","Luz","Roxana","Ana","Sol","Micaela","Romina","Melina","Camila"};
  56.    for(i=0; i<cantPersonas; i++){
  57.        edad = rand()%80+1;
  58.        aux.edad = edad;
  59.        if( (random = rand()%10) %2 == 0){ // hombres
  60.            aux.nombre = hombres[random];
  61.            aux.sexo = 0;
  62.        }
  63.        else{
  64.            aux.nombre = mujeres[random];
  65.            aux.sexo = 1;
  66.        }
  67.  
  68.        push_back(vec, aux);
  69.    }
  70. }
  71.  
  72.  
  73. int main()
  74. {
  75.    srand(time(NULL));
  76.    Array *vecPersonas = getArrayInstance();
  77.    cargarPersonas(&vecPersonas); // Esto no
  78.    printf("%d", vecPersonas->size);
  79.    mostrarPersonas(vecPersonas);
  80.  
  81.    return 0;
  82. }
En línea

geeke

Desconectado Desconectado

Mensajes: 93


Ver Perfil
Re: Punteros y memoria dinamica
« Respuesta #4 en: 30 Agosto 2015, 03:13 am »

Otra aproximación con la correspondiente liberación de memoria del array de estructuras y algunas que otras mejoras

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <time.h>
  5.  
  6. typedef struct Persona
  7. {
  8.    char *nombre;
  9.    int edad;
  10.    int sexo;
  11. } Persona;
  12.  
  13. typedef struct
  14. {
  15.    Persona *array;
  16.    size_t used;
  17.    size_t size;
  18. } Array;
  19.  
  20. void initArray(Array *a, size_t initialSize)
  21. {
  22.    a->array = (Persona*)calloc(initialSize , sizeof(Persona));
  23.    a->used = 0;
  24.    a->size = initialSize;
  25. }
  26.  
  27. void push_back(Array *a, Persona element)
  28. {
  29.    if (a->used == a->size)
  30.    {
  31.        a->size *= 2;
  32.        a->array = (Persona *)realloc(a->array, a->size * sizeof(Persona));
  33.        memset(&a->array[a->used],0,sizeof(Persona) * (a->size - a->used));
  34.    }
  35.    a->array[a->used].nombre = (char*)malloc(strlen(element.nombre) + 1);
  36.    strcpy(a->array[a->used].nombre, element.nombre);
  37.    a->array[a->used].edad = element.edad;
  38.    a->array[a->used].sexo = element.sexo;
  39.    a->used++;
  40. }
  41.  
  42. void freeArray(Array *a)
  43. {
  44.    int i;
  45.    for (i = 0; i < a->used; i++)
  46.    {
  47.        free(a->array[i].nombre);
  48.        a->array[i].nombre = NULL;
  49.    }
  50.    free(a->array);
  51.    a->array = NULL;
  52.  
  53.    a->used = 0;
  54.    a->size = 0;
  55. }
  56.  
  57. void cargarPersonas(Array * arr)
  58. {
  59.    int i, edad, random;
  60.    int TAM = rand() % 30 + 1;
  61.    Persona temp;
  62.  
  63.    char *hombres[] = {"Ramiro","Pedro","Federico","Jose","Antonio","Pablo","Raul","Gustavo","Gonzalo","Airton"};
  64.    char *mujeres[] = {"Mariana","Jennifer","Luz","Roxana","Ana","Sol","Micaela","Romina","Melina","Camila"};
  65.  
  66.    for ( i = 0; i < TAM; i++)
  67.    {
  68.        edad = rand() % 80 + 1;
  69.        temp.edad = edad;
  70.        if( (random = rand() % 10) % 2 == 0)
  71.        {
  72.            temp.nombre = hombres[random];
  73.            temp.sexo = 0;
  74.        }
  75.        else
  76.        {
  77.            temp.nombre = mujeres[random];
  78.            temp.sexo = 1;
  79.        }
  80.        push_back(arr, temp);
  81.    }
  82. }
  83.  
  84. void mostrarPersonas(Array *arr)
  85. {
  86.    int i;
  87.    for ( i = 0; i < arr->used; i++)
  88.    {
  89.        printf("(%d) Nombre: %s - Edad: %d - Sexo: ", i, arr->array[i].nombre, arr->array[i].edad);
  90.        if ( arr->array[i].sexo == 0)
  91.            printf("Masculino");
  92.        else
  93.            printf("Femenino");
  94.        printf("\n");
  95.    }
  96. }
  97.  
  98. int main(void)
  99. {
  100.    srand(time(NULL));
  101.    Array a;
  102.    initArray(&a, 5);
  103.  
  104.    cargarPersonas(&a);
  105.    mostrarPersonas(&a);
  106.  
  107.    freeArray(&a);
  108.    return 0;
  109. }
  110.  
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines