Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: David8 en 2 Abril 2014, 18:23 pm



Título: Entrada de datos con fgets()
Publicado por: David8 en 2 Abril 2014, 18:23 pm
Imaginemos que tenemos un un array como:

   char cadena[10];

Entonces usamos la función fgets para leer una cadena de caracteres como:

   fgets(cadena, 10, stdin);

E introducimos menos de 9 caracteres por lo que automáticamente se nos pone un '\n' al final del array, en la posición cadena[9] en el ejemplo.
Entonces si usamos:

   if(cadena[strlen(cadena)-1] == '\n'{
      cadena[strlen(cadena)-1] = '\0'
   }

obtenemos la cadena sin la impresión de una nueva línea (es decir que el cursor se situa justo después del último caracter.

Lo que no entiendo de todo es es que si introducimos por ejemplo HOLA el array quedaría como:

   H O L A  \0 _ _ _ _ \n

y al usar la anterior instrucción para quitar el '\n' tendríamos:
   
   H O L A  \0 _ _ _ _ \0

¿Cómo es posible tener dos '\0'?

Muchas gracias.


Título: Re: Entrada de datos con fgets()
Publicado por: rir3760 en 2 Abril 2014, 19:44 pm
El detalle es: los caracteres '\n' y '\0' no se almacenan en las ultimas posiciones del array sino justo después del texto ingresado. Siguiendo tu ejemplo al introducir "Hola" los caracteres en el array son:
Código:
0  1  2  3  4  5  6  7  8  9
H  o  l  a \n \0
A continuación strlen te devuelve el numero de caracteres sin contar el '\0', en este caso son cinco y la asignación sobrescribe el carácter '\n' con un '\0' resultando en:
Código:
0  1  2  3  4  5  6  7  8  9
H  o  l  a \0 \0
Con ello el primer '\0' marca el final de la cadena.

Un saludo


Título: Re: Entrada de datos con fgets()
Publicado por: noele1995 en 2 Abril 2014, 20:33 pm
¿Cómo es posible tener dos '\0'?

Un array de tipo char en realidad no es mas que un array de bytes, pero para el uso de cadenas de texto el primer \0 es lo que marca el final de la cadena, no influye en que en otra posicion del array haya otro.


Título: Re: Entrada de datos con fgets()
Publicado por: Yoel Alejandro en 2 Abril 2014, 20:57 pm
No es que la cadena posea dos '\0', pues sólo el primero cuenta. Para poner un ejemplo imagínate que tienes:

'h' 'o' 'l' 'a' '\0' '\0' '\0' '\0' '\0'

entonces el primer '\0' encontrado marca el fin de la cadena, que es "hola" y su longitud es 4.

En el ejemplo que dices, si conviertes

'h' 'o' 'l' 'a' '\n' '\0'

en

'h' 'o' 'l' 'a' '\0' '\0'

entonces haces una cadena "más corta", y pasa de tener 5 caracteres a tener 4.

==========================
EDITO

Sólo por comentar, aunque no se si me estoy extendiendo en el tema. El código que propones se puede optimizar eliminando la sobrecarga por llamar dos veces a la función strlen() (aunque un usuario me dijo que los compiladores modernos saben cómo evitar este problema). Una manera es por supuesto depositar el valor de la longitud de la cadena en una variable intermedia:
Código
  1. int len = strlen(cadena);
  2. if(cadena[len-1] == '\n'{
  3.   cadena[len-1] = '\0'
  4. }
O incluso otra forma "autoconstruida", donde no se llama a ninguna función de biblioteca:
Código
  1. for ( i = 0; cadena[i] != '\0'; i++ )
  2.   if ( cadena[i] == '\n' ) cadena[i] = '\0';
o:
Código
  1. char c;
  2. int i = 0;
  3. while ( (c = cadena[i]) != '\n' && c != '\0' )
  4.   i++;
  5. if ( c == '\n' ) cadena[i] = '\0';
  6.  


Título: Re: Entrada de datos con fgets()
Publicado por: David8 en 3 Abril 2014, 19:43 pm
Muchas gracias a todos, se resolvió notablemente mi duda  :D