jueves, 20 de enero de 2011

Agenda con estructuras - Programación C

Hoy volvemos con otro ejercicio de programación en C en el cual veremos cómo trabajar con estructuras. A la hora de realizar este ejercicio, tendremos en cuenta también las lecciones aprendidas sobre reserva dinámica de memoria.

Ejercicio:
Programar una agenda con alumnos en la que se guardarán los siguientes datos: nombre, apellido y edad.

El programa debe:

  • Preguntar de cuantos alumnos va a ser la agenda y según la respuesta se deberá reservar ese espacio de manera dinámica.
  • Leer los datos de los alumnos.
  • Mostrar en pantalla todos los datos de los alumnos.
Para ver la solución sigue leyendo:


/******   Inicio programa ******/


#include <stdio.h>

#include <stdlib.h>


typedef struct {

       char *nombre;

       char *apellido;

       int edad;

       }struct_alum;


int reservaMemoria (struct_alum **alu,int num);

void leerAlumno(char **alu);

void listarDatos(struct_alum *alu,int num);


main()

{
      int num,i;

      char str[10];

      struct_alum *alu;


      printf("Cuantos alumnos van a entrar en tu agenda?: ");

      gets(str);

      sscanf(str,"%d",&num);

      reservaMemoria(&alu,num);


      printf("\nLectura de datos de los alumnos\n");

      printf("-------------------------------\n\n");


      for (i=0;i<num;i++)

       {
           printf("\n");

           printf("Datos del alumno %d: \n",i+1);

           printf("Nombre: ");

           leerAlumno(&alu[i].nombre);

           printf("Apellido: ");

           leerAlumno(&alu[i].apellido);

           printf("Edad: ");

           gets(str);

           sscanf(str,"%d",&alu[i].edad);
       }

      listarDatos(alu,num);

      getchar();

}

int reservaMemoria (struct_alum **alu,int num)

{

    *alu=(struct_alum *)malloc(sizeof(struct_alum)*num);

    if (*alu==NULL)

       printf("Error reservando memoria\n");

    else

       printf("Reserva de memoria realizada\n");

}

void leerAlumno(char **alu)

{

     char str[30];


     gets(str);

     *alu=(char *)malloc(strlen(str)+1);

     strcpy(*alu,str);

}

void listarDatos(struct_alum *alu,int num)

{

     int i;


     printf("\nListado de datos de los alumnos\n");

     printf("-------------------------------\n\n");


     for (i=0;i<num;i++)

     {

         printf("\n");

         printf("Datos del alumno %d: \n",i+1);

         printf("Nombre: %s\n",alu[i].nombre);

         printf("Apellido: %s\n",alu[i].apellido);

         printf("Edad: %d\n\n",alu[i].edad);

     }

}

/******   Fin programa******/

4 comentarios:

  1. Utilizar gets() es peligroso: http://totaki.com/poesiabinaria/2010/04/por-que-no-debemos-utilizar-gets/

    De todas formas estás limitando la entrada de datos a 30 caracteres, aunque por el uso de gets() depende de dónde le de el punto al SO de reservarte la memoria que puedas meter más de 30 caracteres o haya una violación de segmento.

    ResponderEliminar
  2. Gracias por tu aportación Gaspar.

    ResponderEliminar
  3. La función gets() no sólo es peligrosa por la violación de segmento que comenta Gaspar, es peligrosa sencillamente porque si se controla el error de desbordamiento de buffer se puede inyectar un shellcode y ganar control de ejecución sobre tu programa. La violación de segmento es lo mejor que puede pasar, al menos el sistema operativo detiene tu programa porque detecta que se está comportando como no debería.

    Otra función peligrosa que usas es strcpy(). No controla el número de caracteres que copia, lo que puede (y suele) suponer un fallo de seguridad, por lo mismo que antes. Usa strncpy() / memcpy().

    Lo mismo se aplica para strcmp() - strncmp().

    C es un lenguaje peligroso si no conoce bien, conviene documentarse antes sobre las funciones que JAMÁS deberían usarse. El 70% de los fallos de seguridad se deben a errores de esta índole.

    ResponderEliminar
  4. Gracias de nuevo por vuestras aportaciones.

    Enriquecen, y mucho, los artículos publicados.

    Saludos.

    ResponderEliminar

Deja tu opinión realizando un comentario interesante. Cualquier intento de Spam no será admitido.