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

 

 


Tema destacado: Trabajando con las ramas de git (tercera parte)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Ayuda con lista enlazada
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Ayuda con lista enlazada  (Leído 1,893 veces)
agrichi

Desconectado Desconectado

Mensajes: 9


Ver Perfil
Ayuda con lista enlazada
« en: 24 Diciembre 2017, 10:30 am »

Hola!. Hice una lista simplemente enlazada y no me funciona en algunas partes.
No logro ver donde están los errores
Cuando ingreso un nodo al final de la lista (líneas 89 a 93), el programa se cuelga.
Cuando ingreso un dato que no existe para verlo (lineas 122 a 125), en lugar de mostrar el mensaje de que el dato no se encontró, también se cuelga.
Idem anterior cuando quiero eliminar un dato e ingreso uno que no existe (lineas 186 a 190)
Aquí está el código
Gracias!!

Código
  1. / Lista simplemente enlazada que permite ingresar el nombre y la edad de personas
  2. // Va ingresando los datos ordenados de menor a mayor según la edad de la persona
  3. // Ademas el programa permite mostrar los datos de todas las personas o de una en particular,
  4. // eliminar una determinada persona o a todas
  5.  
  6. #include <stdio.h>
  7. #include <conio.h>
  8. #include <stdlib.h>
  9.  
  10. struct nodo{
  11.        char nombre[40];
  12.        int edad;
  13. struct nodo *siguiente;
  14.           };
  15.  
  16. void IngresarUno(struct nodo **);
  17. void MostrarUno(struct nodo**);
  18. void MostrarTodos(struct nodo **);
  19. void EliminarUno(struct nodo **);
  20. void EliminarTodos(struct nodo **);
  21.  
  22. int main()
  23. {
  24. int opcion;
  25. struct nodo *p;
  26. p=NULL;
  27. do{
  28. system("cls");
  29. printf("Ingrese la opcion\n\n1:Ingresar datos de una persona\n\n2:Ver datos de una persona\n\n");
  30. printf("3:Mostrar todas las personas\n\n4:Borrar una persona\n\n5:Eliminar todas las personas\n\n6:Salir del programa\n\n");
  31. scanf("%d",&opcion);
  32. switch(opcion)
  33. {
  34. case 1:IngresarUno(&p);
  35.    break;
  36. case 2:MostrarUno(&p);
  37.    break;
  38. case 3:MostrarTodos(&p);
  39.    break;
  40. case 4:EliminarUno(&p);
  41.        break;
  42. case 5:EliminarTodos(&p);
  43.    break;  
  44. case 6:system("cls");
  45.    exit(0);
  46. }
  47.   }while((opcion>=1)&&(opcion<=6));
  48. system("cls");  
  49. printf("Opcion incorrecta\n\nEl programa terminara\n\n\n");
  50. return 0;
  51. }
  52.  
  53. void IngresarUno(struct nodo **principio)
  54. {
  55. system("cls");
  56. struct nodo *anterior,*actual,*nuevo;
  57. nuevo=(struct nodo *)malloc(sizeof(struct nodo));
  58. if(!nuevo)
  59. {
  60.  printf("Error al reservar memoria\n\n");
  61.  printf("Presione una tecla para salir\n\n");
  62.  getch();
  63.  exit(1);
  64.  }
  65. printf("Ingrese el nombre: ");
  66. fflush(stdin);
  67. gets(nuevo->nombre);
  68. printf("\n\nIngrese la edad: ");
  69. scanf("%d",&(nuevo->edad));
  70. if(!(*principio)) // Si no hay ningún nodo en la lista, creo el primero
  71. {
  72.  (*principio)=nuevo;
  73.  nuevo->siguiente=NULL;
  74. }
  75. else
  76. {
  77.  anterior=(*principio);
  78.  actual=(*principio);
  79.  while(((nuevo->edad)>(actual->edad))&&(actual)) //Mientras la edad del nodo nuevo sea mayor que la del nodo actual y mientras
  80.  {                                                //no haya llegado al final de la lista, me voy desplazando por la lista
  81.   anterior=actual;                                //actualizando los punteros para evaluar el siguiente nodo
  82.   actual=(actual->siguiente);                     //Cuando salga del while tendre el lugar donde tengo que ubicar el nuevo nodo, y
  83.  }                                                //puede ser al principio de la lista, al final, o entre dos nodos          
  84.  if(anterior==actual)  //Si el nuevo nodo va al principio de la lista, los punteros son iguales
  85.  {
  86.   (*principio)=nuevo;
  87.   (nuevo->siguiente)=actual;
  88.  }
  89.  else if(!actual) //Si llegue al final de la lista(el puntero actual apunta a NULL), entonces el elemento nuevo sera
  90.  {                //el último elemento de la lista
  91.   (anterior->siguiente)=nuevo;
  92.   (nuevo->siguiente)=NULL;
  93.  }
  94.  else //Si no es ninguno de los casos anteriores, entonces el nuevo elemento va entre otros dos
  95.  {  
  96.   (anterior->siguiente)=nuevo;
  97.   (nuevo->siguiente)=actual;
  98.  }
  99. }
  100. printf("\n\n\nPresione una tecla para salir\n\n\n");
  101. getch();
  102. return;
  103. }
  104.  
  105. void MostrarUno(struct nodo **principio)
  106. {
  107. struct nodo *actual;
  108. int a;
  109. actual=(*principio);
  110. system("cls");
  111. if(!(*principio))
  112. {
  113.  printf("Lista vacia\n\nPresione una tecla para salir\n\n\n");
  114.  getch();
  115. }
  116. else
  117. {
  118.  printf("Ingrese la edad a buscar: ");
  119.  scanf("%d",&a);
  120.  while((a!=(actual->edad))&&actual) //Mientras no coincida la edad que busco con la del nodo, actualizo el puntero para leer el siguiente
  121.   actual=actual->siguiente;
  122.  if(!actual) //Si llegué al final de la lista, entonces no encontré la edad buscada
  123.  {
  124.   printf("\nNo se encontró la edad buscada\n\nPresione una tecla para salir\n\n\n");
  125.   getch();
  126.  }
  127.  else
  128.  {
  129.   printf("\n\nLos datos son:\n\n\n");
  130.   printf("Nombre: ");
  131.   puts(actual->nombre);
  132.   printf("\nEdad: %d\n\n",actual->edad);
  133.   printf("Presione una tecla para salir\n\n\n");
  134.   getch();
  135.  }
  136. }
  137. return;
  138. }
  139.  
  140. void MostrarTodos(struct nodo **principio)
  141. {
  142. struct nodo *actual;
  143. actual=(*principio);
  144. system("cls");
  145. if(!(*principio))
  146. {
  147.  printf("Lista vacia\n\nPresione una tecla para salir\n\n\n");
  148.  getch();
  149. }
  150. else
  151. {
  152.  while(actual)
  153.  {
  154.   printf("Nombre: ");
  155.   puts(actual->nombre);
  156.   printf("\nEdad: %d\n\n\n",actual->edad);
  157.   actual=actual->siguiente;
  158.  }
  159.  printf("Presione una tecla para salir\n\n\n");
  160.  getch();
  161. }
  162. return;
  163. }
  164.  
  165. void EliminarUno(struct nodo **principio)
  166. {
  167. struct nodo *actual,*anterior;
  168. int a;
  169. system("cls");
  170. if(!(*principio))
  171. {
  172.  printf("Lista vacia\n\nPresione una tecla para salir\n\n\n");
  173.  getch();
  174. }
  175. else
  176. {
  177.  actual=(*principio);
  178.  anterior=(*principio);
  179.  printf("Ingrese la edad a eliminar: ");
  180.  scanf("%d",&a);
  181.  while((a!=(actual->edad))&&actual) //Mientras no coincida la edad que busco con la del nodo, actualizo el puntero para leer el siguiente
  182.  {
  183.   anterior=actual;
  184.   actual=actual->siguiente;
  185.  }
  186.  if(!actual) //Si llegué al final de la lista, entonces no encontré la edad buscada
  187.  {
  188.   printf("\nNo se encontró la edad buscada\n\nPresione una tecla para salir\n\n\n");
  189.   getch();
  190.  }
  191.  else if(anterior==actual)  //Si los punteros son iguales, entonces el nodo a eliminar es el primero
  192.  {
  193.   (*principio)=((*principio)->siguiente);
  194.   free(actual);
  195.   actual=NULL;
  196.   printf("\n\nPresione una tecla para salir\n\n\n");
  197.   getch();
  198.  }
  199.  else  // Si no es el primero, entonces es cualquiera de los demás
  200.  {
  201.   (anterior->siguiente)=(actual->siguiente);
  202.   free(actual);
  203.   actual=NULL;
  204.  }
  205. }
  206. return;
  207. }
  208.  
  209. void EliminarTodos(struct nodo **principio)
  210. {
  211. struct nodo *actual;
  212. system("cls");
  213. if(!(*principio))
  214. {
  215.  printf("Lista vacia\n\nPresione una tecla para salir\n\n\n");
  216.  getch();
  217. }
  218. else
  219. {
  220.  actual=(*principio);
  221.  while(actual)
  222.  {
  223.   (*principio)=((*principio)->siguiente);
  224.   free(actual);
  225.   actual=(*principio);
  226.  }
  227.  printf("La lista fue eliminada\n\n\nPresione una tecla para salir\n\n\n");
  228.  getch();
  229.  return;
  230. }
  231. }
  232.  
  233.  


En línea

do-while


Desconectado Desconectado

Mensajes: 1.276


¿Habra que sacarla de paseo?


Ver Perfil
Re: Ayuda con lista enlazada
« Respuesta #1 en: 24 Diciembre 2017, 12:22 pm »

Lo primero es agradecerte el uso de nombres de variable que describen el uso que les vas a dar. Es una buena costumbre, no la pierdas.

He visto algún problema con la lógica:
Línea 79:
Código
  1. while(((nuevo->edad)>(actual->edad))&&(actual))
  2.  
En la primera condición de la expresión lógica estás desreferenciando actual, que puede ser NULL. Tienes que cambiar el orden:
Código
  1. while((actual && (nuevo->edad)>(actual->edad)))
  2.  
Así si actual es NULL la condición falla directamente, la segunda parte de la expresión no se evaluaría y no tendrías problemas por desreferenciar un puntero NULL. Por si alguien no lo sabe o no se acuerda, las condiciones de una expresión lógica se evalúan de izquierda a derecha, si en un y falla una de las condiciones la expresión se evalúa automáticamente a false (en C cero) y el resto de condiciones se ignoran, con o pasa lo contrario, si la condición que está a la izquierda es verdad directamente se evalua a true (en C no cero) y el resto no se evalúa.

En la línea 120 está sucediendo lo mismo, tienes que cambiar el orden de las condiciones de la expresión lógica. Además, ya no porque esté mal, lo tienes bien, pero si por la posibilidad de ahorrar ciclos, sabiendo que las edades están ordenadas de menor a mayor, si en lugar de comprobar si la edad del nodo actual es distinta de la edad solicitada compruebas que sea menor, sabrás que el dato que buscas está en una posición más avanzada de la lista, y si la edad del nodo actual es mayor sabrás que directamente la edad que buscas no está en la lista, así que cambiaría ese distinto por un edad_actual < edad_que_buscas (después tendrás que retocar algo el código para saber si se ha salido del bucle por no haberse encontrado (nodo nulo o edad_actual > edad_que_buscas) o porque se ha encontrado la edad.

En la línea 181 también tienes que cambiar el orden de las condiciones y aplicaría los cambios del párrafo anterior.

Más allá de lo dicho no veo ningún error por el que el programa se tenga que quedar colgado (luego le volveré a echar un ojo por si he pasado algo por alto).

¡Saludos!

Por cierto, échale un ojo a este enlace:
https://foro.elhacker.net/programacion_cc/lo_que_no_hay_que_hacer_en_cc_nivel_basico-t277729.0.html

conio.h es una librería que sólo he visto implementada en compiladores de Borland. Su uso no es nada recomendable (no forma parte del estandar de C).

fflush está diseñada para que funcione sobre flujos de salida. Su uso sobre stdin queda indefinido.

Los datos se leen de la entrada estandar después de haber pulsado intro. Ésto deja un salto de línea al final de la entrada. Si utilizas scanf/fscanf ese salto de línea queda en el buffer de entrada. Para limpiar la entrada y evitar el uso de fflush sobre stdin puedes usar el siguiente código:
Código
  1. scanf(lo que sea)
  2. while(getchar() != '\n'); //leemos datos de la entrada hasta encontrar un salto de linea y asi la dejamos limpia.
  3.  
Lo anterior deberías de hacerlo siempre que sepas que has acabado de leer los datos de una línea del buffer de entrada para evitar que quede "basura". Por ejemplo:
Código:
Introduce un entero:
> El usuario escribe "12 abcd culo\n";
Leemos el entero.
En el buffer de entrada queda "abcd culo\n"
Leemos datos de la entrada hasta encontrar el salto de línea.
La entrada ha quedado lista para poder leer los datos que queramos sin que la basura introducida nos moleste.

Las funciones gets/fgets también leen el salto de línea, así que no hay que limpiar nada después de usarlas (si has leído el enlace anterior sabrás porque no es recomendable el uso de gets y porqué deberías de utilizar fgets sobre stdin, sino lee post ya).

Lo mismo se puede aplicar a la situación en la que esperas a que el usuario pulse intro para continuar:
Código
  1. printf("Pulsar intro para continuar...");
  2. while(getchar() != '\n'); //evitamos el uso de getch, que es una funcion exclusiva de conio.h
  3.  


« Última modificación: 24 Diciembre 2017, 12:45 pm por do-while » En línea

- Doctor, confundo los números y los colores.
- Vaya marrón.
- ¿Marrón? ¡Por el culo te la hinco!
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
ayuda...Lista doblemente enlazada
Java
goll9d 2 3,797 Último mensaje 22 Enero 2012, 04:50 am
por goll9d
ayuda con lista doblemente enlazada
Programación C/C++
gibi77 3 3,914 Último mensaje 7 Marzo 2012, 07:47 am
por nirvguy
Ayuda con lista enlazada
Java
netca 2 3,346 Último mensaje 20 Abril 2012, 16:11 pm
por adwind
Ayuda Lista Enlazada
Programación C/C++
robluis 5 5,742 Último mensaje 9 Mayo 2012, 03:49 am
por botella
Ayuda con lista doblemente enlazada
Programación C/C++
falconez 2 9,294 Último mensaje 16 Diciembre 2013, 01:35 am
por falconez
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines