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

 

 


Tema destacado: Security Series.XSS. [Cross Site Scripting]


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


Desconectado Desconectado

Mensajes: 1.603



Ver Perfil
Re: Problema basico con listas en C
« Respuesta #10 en: 14 Abril 2016, 16:42 pm »

Muy buenas. Muchas gracias, me alegro que mis aportaciones te sirvan.

typedef, que supongo que no sabes que es, sirve para crear alias de tipos de datos. De forma simple
Código
  1. typedef int entero;
ahora escribir entero es como si escribieramos int por lo que
Código
  1. entero num;
es lo mismo que escribir
Código
  1. int num;

Del mismo modo se pueden crear datos de tipo puntero
Código
  1. typedef int *puntero_a_int
ahora puntero_a_int se ha convertido en un int *
por lo que el siguiente fragmento es válido
Código
  1. typedef int *puntero_a_int;
  2. int a = 3;
  3. puntero_a_int = &a;

Ahora al código
Código
  1. typedef struct nodo_t {
  2.    int valor;
  3.    struct nodo_t* siguiente;
  4. } nodo, *pila;

lo que hace es crear un nodo básico en el empleo de listas y pilas:
Código
  1. struct nodo_t {
  2.    int valor;
  3.    struct nodo_t* siguiente;
  4. }

Podría trabajar solo con eso, sustituyendo lo que en el código aparece como nodo por struct nodo_t y lista por struct nodo_t * pero creando esos dos alias el código queda más comprensible a simple vista.

Básicamente lista y nodo son casi lo mismo, uno es un puntero y el otro la estructura. Si sigues el código verás que con esos alias el código es más fácil de seguir.

Para ver como quedaría de la otra forma haz una copia del código y sustituye lista por struct nodo_t* y nodo por struct nodo_t y verás la diferencia.


En línea

HardForo

Desconectado Desconectado

Mensajes: 219


HardForo.com


Ver Perfil WWW
Re: Problema basico con listas en C
« Respuesta #11 en: 14 Abril 2016, 18:54 pm »

@MAFUS:  nuevamente gracias..... la verdad es que pensaba que typedef era un alias de struct porque siempre lo vi en ese contexto, aprendí un par de cosas más (mil gracias)

He intentado re-escribir el programa original con lo que me has enseñado pero sigo sin poder usar el doble puntero:

Código
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3.  
  4.  
  5. typedef struct nodo_t {
  6. int value;
  7. struct nodo_t* next;
  8. } node, *lista, **listaPTR;
  9.  
  10.  
  11. lista new_node(int value){
  12. node * n = (node *) malloc(sizeof(node));
  13. n->value = value;
  14. n->next = NULL;
  15. return n;
  16. }
  17.  
  18. lista new_lista(){
  19. return NULL;
  20. }
  21.  
  22.  
  23. void print_list(lista head){
  24. node *prev;
  25.  
  26. prev =  head;
  27. while (prev)
  28. {
  29. printf("%d\n", prev->value);
  30. prev = prev->next;
  31. }
  32. }
  33.  
  34.  
  35. void push(lista list, int value)
  36. {
  37. node *e,*prev,*n;
  38. int v;
  39.  
  40. // camino hasta el final de la list (poco eficiente, mejor tener puntero al final)
  41. e = list;
  42. while (e){
  43. prev = e;
  44. e = e->next;
  45. }
  46.  
  47. // creo nodo
  48. n = new_node(value);
  49.  
  50. if (list == NULL)
  51. {
  52. list = n;
  53. //printf("Elem: %d\n",list->value);
  54. //printf("Elementos: %d\n",count(list));
  55. }
  56. else
  57. // inserto al final
  58. prev->next = n;
  59. }
  60.  
  61.  
  62. int main() {  
  63.  
  64.  
  65. lista l = new_lista();
  66.  
  67. push(l,20);
  68. push(l,40);
  69.  
  70. print_list(l);
  71.  
  72. }
  73.  

He intentado estos reemplazos:

Código
  1. void push(listaPTR listp, int value)   // aqui
  2. {
  3. node *e,*prev,*n;
  4. int v;
  5.  
  6. e = &listp;  // aqui
  7.  


Pero no me funciona...... y realmente necesito entender en que estoy fallando en mi intento y verlo funcionar ya que estoy muy novato.


Nuevamente gracias!


« Última modificación: 14 Abril 2016, 18:57 pm por boctulus » En línea

HardForo:  foro de Hardware y programación

Se buscan Mods y colaboradores *
MAFUS


Desconectado Desconectado

Mensajes: 1.603



Ver Perfil
Re: Problema basico con listas en C
« Respuesta #12 en: 14 Abril 2016, 20:19 pm »

Son fallos básicos de punteros pero a los que se pierde rápidamente la pista cuándo no se está acostumbrado. Con práctica los irás solucionando.

Tienes razón al escribir
Código:
void push(listaPTR listp, int value)
pues necesitas variar la dirección contenida en lista si esta apunta a NULL, pero fallas cuándo escribes
Código:
e = &listp;
por el hecho de que ahora e apunta a la dirección de listp.

*** Dando una vuelta de tuerca al tratamiento de la memoria en C ***
listp debe considerarse una variable local de la función push por lo que obtener su dirección no hará que apuntes a la lista original sino a una parte de la pila de la función a la que estás.
Lo que debes obtener es el valor que hay guardado en listp que será la dirección en la que se guarda la lista.
Sé que es complicado dicho así, pero si lo llegas a entender se acabarán los problemas con los punteros. Como regla nemotécnica piensa en que vas a sacar un asterisco a tu puntero. Algo así:
Tu tienes **listaPTR
Dentro tienes *lista
Como ves hay que quitarse un asterisco de encima para obtener *lista.
En el código
Código:
node *e
haces un puntero a node. Es lo mismo que hacer
Código:
lista e
ya que node * es lo mismo que lista.
Ahora viene cuando sacamos un asterisco **listaPTR. Para ello, durante la asignación cogemos ese asterisco, lo sacamos de **listaPTR y lo dejamos a su izquierda. En código queda así:
Código:
e = *list
Ahora los dos objetos son del mismo tipo y se respeta la igualdad.

Bien. Pasemos a los argumentos de llamada de la función push.
Hemos creado nuestra lista, l, y su tipo es *lista pero el argumento espera que le entreguemos la dirección de memoria donde se guarda ésta. Otra vez podemos hacer uso de una regla nemotécnica: debemos pensar que queremos incluir un asterisco a esa variable y para ello cogemos y, ni cortos ni perezosos, se lo escribimos a mano con el símbolo & a su izquierda. De hecho & parece como si quisiéramos escribir un asterisco de forma rápida y sin levantar el lápiz del papel.
En código queda así:
Código:
push(&l,20);
Así *lista con un asterisco más digievoluciona a **listaPTR.

Tu código funcional quedaría de la siguiente forma:
Código
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3.  
  4.  
  5. typedef struct nodo_t {
  6.    int value;
  7.    struct nodo_t* next;
  8. } node, *lista, **listaPTR;
  9.  
  10.  
  11. lista new_node(int value){
  12.    node * n = (node *) malloc(sizeof(node));
  13.    n->value = value;
  14.    n->next = NULL;
  15.    return n;
  16. }
  17.  
  18. lista new_lista(){
  19.    return NULL;
  20. }
  21.  
  22.  
  23. void print_list(lista head){
  24.    node *prev;
  25.  
  26.    prev =  head;
  27.    while (prev)
  28.    {
  29.        printf("%d\n", prev->value);
  30.        prev = prev->next;
  31.    }
  32. }
  33.  
  34.  
  35. void push(listaPTR list, int value)
  36. {
  37.    node *e,*prev,*n;
  38.    int v; /* v no se usa */
  39.  
  40.    // camino hasta el final de la list (poco eficiente, mejor tener puntero al final)
  41.    e = *list;
  42.    while (e){
  43.        prev = e;
  44.        e = e->next;
  45.    }
  46.  
  47.    // creo nodo
  48.    n = new_node(value);
  49.  
  50.    if (*list == NULL)
  51.    {
  52.        *list = n;
  53.        //printf("Elem: %d\n",list->value);
  54.        //printf("Elementos: %d\n",count(list));
  55.    }
  56.    else
  57.        // inserto al final
  58.        prev->next = n;
  59. }
  60.  
  61.  
  62. int main() {
  63.    lista l = new_lista();
  64.    push(&l,20);
  65.    push(&l,40);
  66.    print_list(l);
  67. }
En línea

HardForo

Desconectado Desconectado

Mensajes: 219


HardForo.com


Ver Perfil WWW
Re: Problema basico con listas en C
« Respuesta #13 en: 14 Abril 2016, 20:33 pm »

Me funcionó perfecto y lo entendí  ;-)

Como conclusión adicional saco que:

Código
  1. pp = &p;  
  2. *pp = p;

Muchisisisimas gracias!


PD: como lista es lo mismo que *nodo, hice unos cambios minimos en el typedef struct:

Código:
typedef struct node_t {
int value;
struct node_t* next;
} nodo, *nodoP, *lista, **nodoPP, **listaP;

« Última modificación: 14 Abril 2016, 21:04 pm por boctulus » En línea

HardForo:  foro de Hardware y programación

Se buscan Mods y colaboradores *
MAFUS


Desconectado Desconectado

Mensajes: 1.603



Ver Perfil
Re: Problema basico con listas en C
« Respuesta #14 en: 14 Abril 2016, 21:51 pm »

Muy bien, veo que lo has entendido.
Ahora recuerda que es mala práctica abusar de typedef, y más si typedef esconde detrás punteros. Debe usarse para esclarecer el código, no ofuscarlo. Muchas veces es mejor, para un tercero, saber que un tipo de dato es un puntero; a no ser que sea intención tuya una ocultación expresa de los interiores del tipo de dato en cuestión, simulando a lo que se hace con la programación orientada a objetos.
En línea

Páginas: 1 [2] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Problema con Listas
Java
HadesDark 2 2,585 Último mensaje 9 Noviembre 2007, 22:00 pm
por Ragnarok
Ayuda Acerca De Listas y Listas Circulares (Revienta Memoria :S)
Programación C/C++
Gerik 0 6,030 Último mensaje 12 Septiembre 2010, 01:49 am
por Gerik
Problema con listas enlazadas.
Programación C/C++
samur88 9 5,245 Último mensaje 4 Diciembre 2010, 19:18 pm
por EddyC
algo basico super basico pero que no me sale
Programación C/C++
Freelancer 6 4,526 Último mensaje 22 Septiembre 2011, 03:25 am
por Freelancer
Problema con listas en Python (Resuelto)
Scripting
MA40 2 6,603 Último mensaje 6 Abril 2012, 12:32 pm
por MA40
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines