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

 

 


Tema destacado: Introducción a Git (Primera Parte)


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

Desconectado Desconectado

Mensajes: 105


Ver Perfil
[C] Apuntadores a estructuras
« en: 4 Octubre 2013, 18:25 pm »

Hola, estoy construyendo una lista de numeros pero al compilar me da error por el operador ->, alguien nota el error?
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. typedef struct st_num //Plantilla para numero aleatorio.
  4. {
  5.    int rand_num;
  6.    struct st_num *ptr_next;
  7. }st_num;
  8.  
  9. typedef struct
  10. {
  11.    st_num *head;
  12.    st_num *last;
  13.  
  14. }fila;
  15.  
  16. int main()
  17. {
  18.    int i;
  19.    int respuesta_num; //Dato tecleado por usuario
  20.    char key_buff[40];
  21.    st_num *nodo;
  22.    menu_principal(); //Borrar pantalla y desplegar texto
  23.    scanf("%d",&respuesta_num);
  24.    gets(key_buff); //limpiar buffer
  25.    fila->head = NULL;
  26.    fila->last = NULL;
  27.  
  28.    for(i=0;i<respuesta_num;i++)
  29.    {
  30.        nodo = (st_num *) malloc(sizeof(st_num)); //Direccion de bloque creado
  31.        nodo->rand_num = rand()%100+1;
  32.            if(i=0) //Edicion de primer elemento
  33.            {
  34.                fila->head = nodo;
  35.                fila->last = nodo;
  36.                nodo->ptr_next = NULL;
  37.            }
  38.            if(nodo->ptr_next != NULL)
  39.            {
  40.                nodo ->ptr_next = fila->head;
  41.            }
  42.        fila->head = nodo;
  43.        printf("%d\n",nodo->ptr_next);
  44.    }
  45. }
  46.  


En línea

rir3760


Desconectado Desconectado

Mensajes: 1.639


Ver Perfil
Re: [C] Apuntadores a estructuras
« Respuesta #1 en: 4 Octubre 2013, 18:43 pm »

El error se debe en parte a la declaración:
Código
  1. typedef struct
  2. {
  3.   st_num *head;
  4.   st_num *last;
  5. }fila;
Con ella no estas declarando una variable sino un alias o nombre alternativo "fila". Para declarar una variable con ese nombre debes cambiar la linea eliminando la palabra reservada "typedef":
Código
  1. struct
  2. {
  3.   st_num *head;
  4.   st_num *last;
  5. }fila;
Y como es una variable y no un puntero debes cambiar en tu programa todas las instancias de "fila->" por "fila.".

También hay otros errores como:
Código
  1. if(i=0) //Edicion de primer elemento
Ahí estas utilizando el operador de asignación "=" cuando debería ser el de comparación "==".

Un saludo


En línea

C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language
edr89

Desconectado Desconectado

Mensajes: 105


Ver Perfil
Re: [C] Apuntadores a estructuras
« Respuesta #2 en: 4 Octubre 2013, 19:04 pm »

Como debo hacer para poder usar el operador flecha? no sirve con estructuras?

tendria que declarar:
Código
  1. typedef fila *nodo NODO
y entonces puedo usar
Código
  1. NODO->head;
:huh:

he cambiado los operadores por puntos y compila aunque al terminar el programa regresa el numero que ha tecleado el usuario.
En línea

eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: [C] Apuntadores a estructuras
« Respuesta #3 en: 4 Octubre 2013, 19:18 pm »

Como debo hacer para poder usar el operador flecha? no sirve con estructuras?

tendria que declarar:
Código
  1. typedef fila *nodo NODO

Esa línea no tiene ningún sentido.

Si tu tienes:

Código
  1. struct
  2. {
  3.   st_num *head;
  4.   st_num *last;
  5. }fila;

No puedes crear nuevas instancias de la estructura, ya que la estructura no tiene nombre. Para poder crear instancias nuevas tienes que darle un nombre a la estructura:

Código
  1. struct fila
  2. {
  3.   st_num *head;
  4.   st_num *last;
  5. };

Entonces ahora ya si puedes hacer:

Código
  1. typedef struct fila NODO;

Aunque si lo que quieres es definir un tipo para el puntero tendría que ser:

Código
  1. typedef struct fila* NODO;

Con esto usar los nodos es tan sencillo como:

Código
  1.  
  2. NODO nodo; // has declarado una variable, llamada nodo, que es un puntero a una estructura de tipo fila.
  3.  
  4. nodo->head = NULL;
  5. nodo->last = NULL;

Tu piensa que el operador flecha sirve para acceder al contenido de los punteros... si no tienes punteros no tiene sentido el operador flecha. Con esto mismo también te digo que a veces es mejor evitar el uso de memoria dinámica...
En línea

edr89

Desconectado Desconectado

Mensajes: 105


Ver Perfil
Re: [C] Apuntadores a estructuras
« Respuesta #4 en: 4 Octubre 2013, 20:47 pm »

Tu piensa que el operador flecha sirve para acceder al contenido de los punteros... si no tienes punteros no tiene sentido el operador flecha. Con esto mismo también te digo que a veces es mejor evitar el uso de memoria dinámica...

Entiendo, la cuestion es que debo trabajar con memoria dinamica porque es el tema que estamos viendo, el programa corre bien al generar e imprimir los numeros pero despues de preguntar por el numero natural (linea 53) truena. Lo que quiero hacer es eliminar datos mayores .

Código
  1. typedef struct st_num //Plantilla para numero aleatorio.
  2. {
  3.   int rand_num;
  4.   struct st_num *ptr_next;
  5. }st_num;
  6.  
  7. struct
  8. {
  9.   st_num *head;
  10.   st_num *last;
  11.  
  12. }fila;
  13.  
  14. void menu_principal();
  15. void menu_principal()
  16. {
  17.    system("CLS");
  18.    puts("Generador de numeros aleatorios\n\n");
  19.    printf("Escribe el numero de datos a generar: ");
  20. }
  21.  
  22. int main()
  23. {
  24.   int i;
  25.   int respuesta_num; //Dato tecleado por usuario
  26.   char key_buff[40];
  27.   st_num *nodo;
  28.   st_num *nodo_aux;
  29.   menu_principal(); //Borrar pantalla y desplegar texto
  30.   scanf("%d",&respuesta_num);
  31.   gets(key_buff); //limpiar buffer
  32.   fila.head = NULL;
  33.   fila.last = NULL;
  34.  
  35.   for(i=0;i<respuesta_num;i++)
  36.   {
  37.       nodo = (st_num *) malloc(sizeof(st_num)); //Se crea bloque
  38.       nodo->rand_num = rand()%100+1;           //Se asigna numero
  39.           if(i==0)                             //Condicion para primer elemento
  40.           {
  41.               fila.head = nodo;
  42.               fila.last = nodo;
  43.               nodo->ptr_next = NULL;
  44.           }
  45.           if(nodo->ptr_next != NULL)
  46.           {
  47.               nodo ->ptr_next = fila.head;
  48.           }
  49.       fila.head = nodo;
  50.       printf("%d\n",nodo->rand_num);
  51.   }
  52.   printf("Ahora escribe un numero natural menor a 100: ");
  53.   scanf("%d",&respuesta_num);
  54.   gets(key_buff);
  55.   while(nodo->ptr_next!=NULL)
  56.   {
  57.       if((nodo->rand_num>respuesta_num)&&nodo==fila.head)
  58.       {
  59.           fila.head = (fila.head)->ptr_next;
  60.           free(nodo);
  61.           nodo = fila.head;
  62.       }
  63.       else if(nodo->rand_num>respuesta_num)
  64.       {
  65.           nodo_aux = nodo->ptr_next;
  66.           free(nodo);
  67.           nodo = nodo_aux;
  68.       }
  69.       nodo = nodo->ptr_next;
  70.   }
  71.    //Imprimir nueva lista...
  72. }
  73.  
En línea

rir3760


Desconectado Desconectado

Mensajes: 1.639


Ver Perfil
Re: [C] Apuntadores a estructuras
« Respuesta #5 en: 5 Octubre 2013, 17:33 pm »

Algo que falta en tu programa es la inclusión de los encabezados <stdio.h> y <stdlib.h>.

El primer error importante se encuentra en el bucle donde creas la lista con números aleatorios:
Código
  1. for (i = 0; i < respuesta_num; i++){
  2.   nodo = (st_num *) malloc(sizeof(st_num));
  3.  
  4.   nodo->rand_num = rand() % 100 + 1;
  5.   if (i == 0){
  6.      fila.head = nodo;
  7.      fila.last = nodo;
  8.      nodo->ptr_next = NULL;
  9.   }
  10.   if (nodo->ptr_next != NULL){ /* <== */
  11.      nodo ->ptr_next = fila.head;
  12.   }
  13.   fila.head = nodo;
  14.   printf ("%d\n", nodo->rand_num);
  15. }
Al reservar memoria con malloc el contenido del bloque es "no definido", puede ser cualquier valor incluyendo NULL (0 en contexto de punteros). En otras palabras no hay garantías de que el campo "ptr_next" en los nodos después del primero se ajuste correctamente.

Ese bucle se debe cambiar a:
Código
  1.   for (i = 0; i < respuesta_num; i++){
  2.      nodo = malloc(sizeof *nodo);
  3.      nodo->rand_num = rand() % 100 + 1;
  4.  
  5.      if (i == 0){
  6.         fila.last = nodo;
  7.         nodo->ptr_next = NULL;
  8.      }else
  9.         nodo ->ptr_next = fila.head;
  10.      fila.head = nodo;
  11.      printf ("%d\n", nodo->rand_num);
  12.   }

En cuanto al bloque donde se eliminan los elementos mayores al indicado este tiene varios errores graves ya que el programa va a reventar con una lista vacía y también si la lista contiene un solo nodo y este debe eliminarse. Otro detalle ahí es que no verificas si se debe eliminar el primer nodo.

Una forma de eliminar todos los nodos cuyo valor sea mayor que el indicado es utilizando un puntero de tipo "st_num **p" con la ventaja de que este permite evitar el caso especial del primer nodo. Tu programa con los cambios:
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. typedef struct st_num {
  5.   int rand_num;
  6.   struct st_num *ptr_next;
  7. } st_num;
  8.  
  9. struct {
  10.   st_num *head;
  11.   st_num *last;
  12.  
  13. } fila;
  14.  
  15. void menu_principal(void);
  16.  
  17. int main(void)
  18. {
  19.   int i;
  20.   int respuesta_num;
  21.   char key_buff[40];
  22.   st_num *nodo;
  23.   st_num **p;
  24.  
  25.   menu_principal();
  26.   scanf("%d", &respuesta_num);
  27.   gets(key_buff);
  28.  
  29.   for (i = 0; i < respuesta_num; i++){
  30.      nodo = malloc(sizeof *nodo);
  31.      nodo->rand_num = 1 + rand() % 2;
  32.  
  33.      if (i == 0){
  34.         fila.last = nodo;
  35.         nodo->ptr_next = NULL;
  36.      }else
  37.         nodo ->ptr_next = fila.head;
  38.      fila.head = nodo;
  39.   }
  40.  
  41.   i = 0;
  42.   for (nodo = fila.head; nodo != NULL; nodo = nodo->ptr_next, i++)
  43.      printf(" %d", nodo->rand_num);
  44.   printf(" (%d)\n", i);
  45.  
  46.   printf("Ahora escribe un numero natural menor a 100: ");
  47.   scanf("%d", &respuesta_num);
  48.   gets(key_buff);
  49.  
  50.   /* Eliminamos todos los nodos mayores que "respuesta_num" */
  51.   p = &fila.head;
  52.   while (*p != NULL)
  53.      if ((*p)->rand_num > respuesta_num){ /* Eliminar actual */
  54.         nodo = *p;
  55.         *p = (*p)->ptr_next;
  56.         free(nodo);
  57.      }else /* Siguiente nodo */
  58.         p = &(*p)->ptr_next;
  59.   /* Ajustamos el valor del campo fila.last */
  60.   if (fila.head == NULL)
  61.      fila.last = NULL;
  62.   else {
  63.      fila.last = fila.head;
  64.      while (fila.last->ptr_next != NULL)
  65.         fila.last = fila.last->ptr_next;
  66.   }
  67.  
  68.   i = 0;
  69.   for (nodo = fila.head; nodo != NULL; nodo = nodo->ptr_next, i++)
  70.      printf(" %d", nodo->rand_num);
  71.   printf(" (%d)\n", i);
  72.  
  73.   return 0;
  74. }
  75.  
  76. void menu_principal(void)
  77. {
  78.   system ("CLS");
  79.   puts ("Generador de numeros aleatorios\n\n");
  80.   printf ("Escribe el numero de datos a generar: ");
  81. }

Por ultimo deberías evitar el uso de la función gets, mas información en la pagina |Lo que no hay que hacer en C/C++. Nivel basico|.

Un saludo
En línea

C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language
edr89

Desconectado Desconectado

Mensajes: 105


Ver Perfil
Re: [C] Apuntadores a estructuras
« Respuesta #6 en: 6 Octubre 2013, 01:17 am »

edito:
he reescrito a una nueva version, la finalidad es la misma
el primer código que hice me termino disgustando.

Lo compilé y aparentemente no truena todo corre como debe, me ayudan a detectar posibles fallas?


Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. struct lista
  4. {
  5.    char ch;
  6.    struct lista *next_rec;
  7. };
  8. typedef struct lista LIST;
  9. typedef LIST *LISTPTR;
  10.  
  11. LISTPTR add_to_list( char, LISTPTR );
  12. void show_list(void);
  13. void free_memory_list(void);
  14. void borrar_mayores(int respuesta,int natural);
  15.  
  16. LISTPTR first = NULL;
  17.  
  18. int main(void)
  19. {
  20.    LISTPTR rec_addr;
  21.    int i=0;
  22.    int respuesta, natural;
  23.    rec_addr = add_to_list(rand()%100+1, (LISTPTR)NULL);
  24.    first = rec_addr;
  25.    puts("Numeros aleatorios\n");
  26.    //Imprimir menu principal
  27.    //Input total de datos
  28.    respuesta = input_error();
  29.    while(i++<(respuesta-1))
  30.    {
  31.        rec_addr = add_to_list(rand()%100+1,rec_addr);
  32.    }
  33.    show_list();
  34.  
  35.    //Numero natural
  36.    printf("Escribe un natural menor a 100: ");
  37.    natural = input_error();
  38.    rec_addr = first;
  39.    borrar_mayores(respuesta,natural);
  40.    show_list();
  41.    getch();
  42.    free_memory_list();
  43.    return(0);
  44.    //completar funcion main
  45. }
  46.  
  47. LISTPTR add_to_list(char ch, LISTPTR prev_rec)
  48. {
  49.    LISTPTR new_rec = NULL;
  50.    new_rec = (LISTPTR) malloc(sizeof(LIST));
  51.    if(!new_rec)
  52.    {
  53.        printf("Error al reservar memoria");
  54.        exit(1);
  55.    }
  56.    new_rec->ch = ch;
  57.    new_rec->next_rec = NULL;
  58.    if(prev_rec)
  59.    {
  60.        prev_rec->next_rec = new_rec;
  61.    }
  62.    return(new_rec);
  63. }
  64.  
  65. void borrar_mayores(int respuesta,int natural)
  66. {
  67.    LISTPTR new_rec = first;
  68.    LISTPTR aux = new_rec;
  69.    if(new_rec->next_rec==NULL)
  70.    {
  71.        if(new_rec->ch>natural)
  72.        {
  73.            free(new_rec);
  74.            first=NULL;
  75.            printf("\n\nLa nueva lista no tiene datos. ");
  76.            getch();
  77.            exit(0);
  78.        }
  79.    }
  80.    while(new_rec==first)
  81.    {
  82.        if(new_rec->ch>natural)
  83.        {
  84.            first = new_rec->next_rec;
  85.            free(new_rec);
  86.            new_rec = first;
  87.            aux = first;
  88.        }
  89.        else
  90.        {
  91.            aux = new_rec;
  92.            new_rec = new_rec->next_rec;
  93.        }
  94.    }
  95.    while(new_rec->next_rec!=NULL)
  96.    {
  97.  
  98.        if(new_rec->ch>natural)
  99.        {
  100.            aux->next_rec=new_rec->next_rec;
  101.            free(new_rec);
  102.            new_rec = aux->next_rec;
  103.  
  104.        }
  105.        else
  106.        {
  107.            aux = new_rec;
  108.            new_rec = new_rec->next_rec;
  109.        }
  110.    }
  111. }
  112.  
  113. void show_list()
  114. {
  115.    LISTPTR cur_ptr;
  116.    int counter = 1;
  117.    printf("Rec addr  Position  Data  Next rec addr\n\n");
  118.    cur_ptr = first;
  119.    while(cur_ptr)
  120.    {
  121.        printf("  %x   ",cur_ptr);
  122.        printf("     %2i       %d",counter++,cur_ptr->ch);
  123.        printf("      %x   \n",cur_ptr->next_rec);
  124.        cur_ptr = cur_ptr->next_rec;
  125.    }
  126. }
  127.  
  128. void free_memory_list()
  129. {
  130.    LISTPTR cur_ptr,next_rec;
  131.    cur_ptr = first;
  132.    while (cur_ptr)
  133.    {
  134.        next_rec = cur_ptr->next_rec;
  135.        free(cur_ptr);
  136.        cur_ptr = next_rec;
  137.    }
  138. }
  139.  
  140. int input_error(void)
  141. {
  142.    int respuesta;
  143.    char key_buff[50];
  144.    printf("Escribe el numero de datos a generar: ");
  145.    while((scanf("%d",&respuesta) != 1)||respuesta==0) //en caso de ñ
  146.        {
  147.            while (getchar() != '\n');
  148.            printf ("\nDato no valido intenta de nuevo: ");
  149.        }
  150.    gets(key_buff);
  151.    return respuesta;
  152. }
  153.  

Saludos!
« Última modificación: 6 Octubre 2013, 10:06 am por edr89 » En línea

rir3760


Desconectado Desconectado

Mensajes: 1.639


Ver Perfil
Re: [C] Apuntadores a estructuras
« Respuesta #7 en: 6 Octubre 2013, 18:28 pm »

* Faltan los prototipos de la funciones "input_error" y "getch", si bien técnicamente no son errores se recomienda declarar toda función antes de su uso. En tu caso la solución es colocar el prototipo de "input_error" y la inclusión del encabezado conio al principio del programa.

* Cuando se desea imprimir un puntero se debe convertir este explícitamente al tipo "void *" y utilizar el especificador de formato "%p" con printf, estas dos sentencias en la función show_list:
Código
  1. printf("  %x   ", cur_ptr);
  2. /* ... */
  3. printf("      %x   \n", cur_ptr->next_rec);
Hay que sustituirlas por:
Código
  1. printf("  %p   ", (void *) cur_ptr);
  2. /* ... */
  3. printf("      %p   \n", (void *) cur_ptr->next_rec);

* En la función main debes utilizar nombres mas claros, en lugar de "rec_addr" y "add_to_list" los nombres "last" y "add_after" indican mejor el uso de la variable y función. Ahí la sentencia:
Código
  1. rec_addr = first;
Hay que eliminarla ya que el valor de "rec_addr" no se utiliza en el resto de la función.

* La función "input_error" siempre imprime el texto "Escribe el numero de datos a generar" y seria mejor reescribirla desde cero.

* Si ejecutas el programa varias veces te darás cuenta de que la eliminación de los nodos con un valor mayor al indicado no funciona correctamente.

Un saludo
En línea

C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language
edr89

Desconectado Desconectado

Mensajes: 105


Ver Perfil
Re: [C] Apuntadores a estructuras
« Respuesta #8 en: 6 Octubre 2013, 21:24 pm »

edito:
ya tengo la version final, la funcion que borra los elementos es la adaptación del primero código al segundo  ;D

Código
  1. void borrar_mayores(int natural)
  2. {
  3.    LISTPTR *p;
  4.    LISTPTR aux;
  5.    p=&first;
  6.    if(first->next_rec==NULL)
  7.    {
  8.        if ((*p)->ch> natural)
  9.        { /* Eliminar elemento unico de lista */
  10.            aux = first;
  11.            first = NULL;
  12.            *p = NULL;
  13.            free(aux);
  14.        }
  15.    }
  16.    while (*p != NULL)
  17.    {
  18.        if ((*p)->ch> natural)
  19.        { /* Eliminar actual */
  20.            aux = *p;
  21.            *p = (*p)->next_rec;
  22.            free(aux);
  23.        }
  24.        else /* Siguiente nodo */
  25.        {
  26.            p = &(*p)->next_rec;
  27.        }
  28.  
  29.    }
  30. }
« Última modificación: 7 Octubre 2013, 01:22 am por edr89 » En línea

rir3760


Desconectado Desconectado

Mensajes: 1.639


Ver Perfil
Re: [C] Apuntadores a estructuras
« Respuesta #9 en: 7 Octubre 2013, 18:35 pm »

ya tengo la version final, la funcion que borra los elementos es la adaptación del primero código al segundo
En esa función no necesitas de dos bloques ya que el segundo puede (y va) a procesar todos los nodos, a eso me refería con el comentario sobre evitar casos especiales.

Con solo el bloque necesario (el segundo) la función se reduce a:
Código
  1. void borrar_mayores(int natural)
  2. {
  3.   LISTPTR *p;
  4.   LISTPTR aux;
  5.  
  6.   p = &first;
  7.   while (*p != NULL)
  8.      if ((*p)->ch > natural){
  9.         aux = *p;
  10.         *p = (*p)->next_rec;
  11.         free(aux);
  12.      }else
  13.         p = &(*p)->next_rec;
  14. }

Un saludo
En línea

C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language
Páginas: [1] 2 Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Ayudenme con apuntadores sii?
Programación C/C++
thapitufa 1 1,981 Último mensaje 2 Diciembre 2012, 06:42 am
por x64core
Problema con apuntadores!!!!!!
Programación C/C++
7hongo7 7 4,254 Último mensaje 5 Julio 2013, 10:16 am
por kmilinh0
Problema con estructuras y apuntadores
Programación C/C++
angelihsahn 2 2,280 Último mensaje 31 Agosto 2013, 12:27 pm
por lanun
[C] Introduccion a estructuras y apuntadores
Programación C/C++
edr89 5 2,929 Último mensaje 15 Septiembre 2013, 02:39 am
por edr89
Struct y apuntadores
Programación C/C++
Cas980 1 1,680 Último mensaje 3 Abril 2014, 05:22 am
por rir3760
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines