domingo, 14 de agosto de 2011

Estructura de Datos - Agenda con listas ligadas C/C++

En este ejemplo se muestra el manejo de memoria dinámica en C/C++ con listas simples. Dentro del código podemos observar los procesos básicos de la estructura de datos: creación, eliminación, impresión y búsqueda.

En el compilador g++ en GNU/linux nos dice que el uso de la función gets() para leer cadenas de texto es peligroso, por lo tanto las cadenas las tomamos con scanf("%*c%[^\n]", nodo->cadena) que seria equivalente.(leer directamente una cadena con %s con scanf solo nos guarda la cadena hasta que encuentre un espacio, por eso usamos "%*c%[^\n]" , para indicar que guarde hasta que el usuario teclee un Enter.


#include "stdio.h"
#include "stdlib.h"
#include "string.h"

struct agenda
{
      int tel;
      char nombre[30];
      struct agenda *siguiente;
}*inicio = NULL, *nodo = NULL;

void menu();
void agregar_contacto();
void eliminar_contacto();
int listar();
void mostrar_lista();

int main(int argc, char *argv[]){
      
      int opcion = 0;
      
      do
      {    
          menu();  
          fflush(stdin);                     
          scanf("%d", &opcion);         
          
          switch(opcion)
          {
             case 1:
                   agregar_contacto();
                   break;
             case 2:
                   eliminar_contacto();
                   break;
             case 3:
                   mostrar_lista();
                   break;   
             case 4:
                   exit(0); 
                   break;         
             default:
                   printf("\n\a  Error! Opcion invalida...\n\n"); 
                   break;                 
          }  
      
      }while(opcion != 4);
       
      return EXIT_SUCCESS;
}

void menu()
{      
      printf("Seleccione una opcion: \n");
      printf("\t1.Agregar contacto\n");
      printf("\t2.Eliminar contacto\n");
      printf("\t3.Mostrar lista de contactos\n");
      printf("\t4.Salir\n");
      printf("OPCION: ");      
}

void agregar_contacto()
{     
      fflush(stdin);
      struct agenda *aux = NULL;
      nodo = (struct agenda*)malloc(sizeof(struct agenda));
          
      printf("\tNombre: ");      
      scanf("%*c%[^\n]",nodo-> nombre);
      printf("\tTelefono: ");
      if(scanf("%d", &nodo->tel) != 1)
      {
            printf("\n\tError! numero de telefono  \n\n");
            free(nodo);            
            return;   
      }    
      
      if(inicio == NULL)
      {
            inicio=nodo;
            nodo->siguiente = NULL;
      }
      else
      {
            aux = inicio;
            while(aux->siguiente != NULL)
            {
                  aux = aux->siguiente;
            }
            aux->siguiente = nodo;
            nodo->siguiente = NULL;
      }      
      
      return;
}

void eliminar_contacto()
{     
      if(inicio == NULL)
      {
            printf("\nUsted no ha agregado ningun contacto\n\n"); 
            return;          
      }
      
      fflush(stdin);      
      
      struct agenda *aux;      
      int maximo = 0, objetivo = 0, contador = 0;
      bool flag = false;
       
      printf("Ingrese el numero de contacto que desea eliminar: \n");
      maximo = listar();
      
      printf("\n\tELIMINAR: ");
      if(scanf("%d", &objetivo) != 1 || objetivo > maximo || objetivo < 1)
      {
            printf("\n\tError! ha ingresado una opcion invalida \n\n");
            return;
      } 
           
      nodo = inicio;      
      while(!flag)
      {
            contador++;
            if(contador == objetivo ) flag = true;
            else nodo=nodo->siguiente;            
      }      
      
      /* proceso de eliminacion */
       
      if(nodo == inicio)  //si es el primero
      {
            inicio = nodo->siguiente;
            free(nodo);
      }
      else
      {
            aux = inicio;
            while(aux->siguiente != nodo)
            {
                  aux = aux->siguiente;
            }
            aux->siguiente = nodo->siguiente;
            free(nodo);
      }
    
    
}

int listar()
{
      struct agenda *aux = NULL;
      int contador = 0;
            
      for(aux=inicio;aux!=NULL;aux=aux->siguiente)
      {           
            contador++;      
            printf("\t %d.%s \n", contador, aux->nombre);                    
      }
      
      return contador;   
}
void mostrar_lista()
{
      if(inicio == NULL)
      {
            printf("\nUsted no ha agregado ningun contacto\n\n"); 
            return;          
      }
      
      fflush(stdout);
      struct agenda *aux = NULL;
            
      for(aux=inicio;aux!=NULL;aux=aux->siguiente)
      {                 
            printf("-> Nombre: %s\n",aux->nombre);           
            printf("   Telefono: %d\n\n", aux->tel);
            
      }      
}

5 comentarios:

  1. Gets es peligroso pero scanf no es mejor. El problema es que no hay forma de especificar el tamaño del buffer.

    La alternativa correcta es usar fgets que te permite poner un límite. Algo como:

    #define MAXLINE 20
    char oneword_str[MAXLINE];
    c = fgets(oneword_str, MAXLINE, stdin);

    Es mejor evitar scanf siempre que se pueda. Pero para ejercicios como los que tienes acá está bien ya que el ejercicio es más bien de listas.

    Si no usas el system("clear") es probable que tu programa compile y corra en Windows también.

    ResponderEliminar
  2. oye me pudes ayudar con una agenda a si como esta pero en c++
    responde xf

    ResponderEliminar
  3. Hola y muchas gracias por el material.
    Quería saber si podrías explicar en la definición de la estructura agenda al cerrar las llaves inmediatamente va *inicio = NULL..
    ---
    struct agenda
    {
    int tel;
    char nombre[30];
    struct agenda *siguiente;
    }*inicio = NULL, *nodo = NULL;
    ---
    Esta última parte me es difícil de comprender. Si es una declaración a parte o una continuación de la declaración de la estructura agenda.
    Muchas gracias.

    ResponderEliminar