Porque evitar el uso de la función "gets"

Responder
Mensaje
Autor
Avatar de Usuario
rir3760
Mensajes: 7553
Registrado: 01/10/2004 11:00 pm
Ubicación: Mexico

Porque evitar el uso de la función "gets"

#1 Mensaje por rir3760 » 26/07/2012 3:18 pm

Se debe evitar el uso de la función "gets" porque es la única realmente peligrosa en la biblioteca estándar de C. Dado un programa como este:

Código: Seleccionar todo

#include <stdio.h>
#include <stdlib.h>

#define NUM_CHARS  80

int main(void)
{
   char nombre[NUM_CHARS];
   
   printf("Indica tu nombre: ");
   fflush(stdout);
   if (gets(nombre) == NULL)
      return EXIT_FAILURE;
      
   printf("Hola %s!\n", nombre);
   
   return EXIT_SUCCESS;
}
La función "gets" al ejecutarse la llamada:

Código: Seleccionar todo

gets(nombre)
Tomara de la entrada estándar todos los caracteres que componen una linea de texto sin importar su numero y tratara de almacenarlos a partir de la dirección indicada. Si se sobrepasa la capacidad del contenedor ello resulta en comportamiento no definido (cualquier cosa puede pasar, por ejemplo en MS Windows el usual mensaje de error indicando que la aplicación debe cerrarse).

----

La solución es remplazar el uso de "gets" por fgets, esta ultima tiene la ventaja de aceptar, como segundo argumento, el numero máximo de caracteres a almacenar. El programa anterior corregido:

Código: Seleccionar todo

#include <stdio.h>
#include <stdlib.h>

#define NUM_CHARS  80

int main(void)
{
   char nombre[NUM_CHARS];
   
   printf("Indica tu nombre: ");
   fflush(stdout);
   if (fgets(nombre, NUM_CHARS, stdin) == NULL)
      return EXIT_FAILURE;

   printf("Hola %s!\n", nombre);
   
   return EXIT_SUCCESS;
}
La función "fgets" recibe tres argumentos: el primero es la dirección en memoria donde se almacenaran los caracteres, el segundo el numero de estos (incluyendo el '\n' y el '\0') y el tercero de donde se tomaran ("stdin" es la entrada estándar).

----

Una diferencia importante entre "gets" y "fgets" es que esta ultima no descarta el carácter de avance de linea (el '\n'), este se almacena como parte de la cadena. Para obtener un comportamiento idéntico debemos descartar ese carácter para lo cual hay varias opciones:

A) Mediante un bucle encontramos el '\0' en la cadena, verificamos el carácter anterior y lo eliminamos si es el avance de linea.

B) Utilizando la función "strlen" (prototipo en <string.h>) obtenemos la longitud de la cadena, verificamos el carácter anterior y lo eliminamos si es el avance de linea.

C) Buscamos directamente el avance de linea mediante la función "strchr" (prototipo en <string.h>), si este existe lo eliminamos sustituyéndolo con un '\0'.

Un programa de ejemplo utilizando la primera aproximación:

Código: Seleccionar todo

#include <stdio.h>
#include <stdlib.h>

#define NUM_CHARS  80

char *usr_fgets(char *cad, int num_chars, FILE *entrada);

int main(void)
{
   char nombre[NUM_CHARS];
   
   printf("Indica tu nombre: ");
   fflush(stdout);
   if (usr_fgets(nombre, NUM_CHARS, stdin) == NULL)
      return EXIT_FAILURE;
   
   printf("Hola %s!\n", nombre);
   
   return EXIT_SUCCESS;
}

char *usr_fgets(char *cad, int num_chars, FILE *entrada)
{
   int i;
   
   if (fgets(cad, num_chars, entrada) == NULL)
      return NULL;
   
   /* Buscamos y eliminamos (si existe) el caracter '\n' */
   for (i = 0; cad[i] != '\0'; i++)
      ;
   if (i > 0 && cad[i - 1] == '\n')
      cad[i - 1] = '\0';
   
   return cad;
}
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

Anastacius
Mensajes: 41
Registrado: 26/10/2013 5:13 am

Gracias

#2 Mensaje por Anastacius » 30/10/2013 8:37 am

No se si se puede comentar aqui, si no se puede, pido cierren el mensaje mio...

Agradezco mucho esto, yo estaba teniendo un error por dicha funcion, el cual corregi simplemente agrandando el arreglo, pero es mejor cambiar a fgets de ahora en adelante...

Muchas gracias por tu servicio fiel en esta comunidad
Programacion en C - HTML - Batch -
Aprendiendo : Java...

Responder

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado