[C con Clase] Leer el salto de linea con scanf

Steven R. Davidson vze266ft en verizon.net
Jue Mar 13 22:22:00 CET 2008


Hola Sergio,

Sergio Hernández wrote:

> ¡Hola!
>  
> Estoy haciendo un programa con un menú y para leer las diferentes 
> opciones ("strings") utilizao la función scanf() pero me surge el 
> problema de que la función no me coge el esalto de línea y entonces este 
> es leido por el siguiente scanf().
>  

Esto no debería ocurrir. La función 'scanf()', por defecto, lee 
caracteres hasta encontrarse con un espacio blanco: ' ', '\t', '\r', 
'\n', '\v', o '\f'. Al leer caracteres, el espacio blanco, que sirve 
como separador, es leído, extraído, pero descartado.

Lo que sí puede ocurrir es que previamente hayas usado 'scanf()' para 
leer una cadena para ser interpretada como un número. En este caso, al 
leer cualquier carácter no perteneciente a la representación de un 
número, la lectura y conversión se detiene sin extraer tal carácter. Por 
lo tanto, éste se queda en el canal de entrada esperando su extracción. 
Por ejemplo,

int nNumero;
char szNombre[128];

scanf( "%d", &nNumero );
scanf( "%s", szNombre );

El usuario escribe: 32[ENTER]Sergio[ENTER]
Obtendríamos,

canal de entrada <- "32\nSergio\n"

En la primera lectura:

canal de entrada <- "\nSergio\n"
nNumero <- 32

En la segunda:

canal de entrada <- "Sergio\n"
nNumero <- 32
szNombre <- "\0"

En este caso, podrías extraer el próximo carácter '\n' con 'getchar()'. 
Por ejemplo,

scanf( "%d", &nNumero );
getchar();
scanf( "%s", szNombre );

> Para solucionar esto he encontrado dos opciones pero no me gustan nada y 
> por eso pido ayuda para ver si alguien puede solucionarme el problema.
>  
> 1.- Utilizar la función gets, pero no quiero usar esta alternativa dado 
> que la función no es segura y está desaconsejado su uso.

Efectivamente, no es aconsejable, pero en su lugar puedes usar 
'fgets()'. Esta función es casi igual a 'gets()'. La característica que 
te interesa es que guarda el carácter de fin-de-línea, '\n', en la cadena.

> 2.- Hacer un getchar() después del scanf() pero me parece una "guarrada"
>  

Entiendo. Otra solución es consultar el siguiente carácter para tomar 
una decisión. Por ejemplo,

int c = getchar();

if( '\n' != c || EOF != c )
{
   // Cualquier otro carácter: devolución
   ungetc( c );
}
// Si es '\n', no hacer nada: descartar


Otra posibilidad es leer cadenas de caracteres y luego procesarlas tú 
mismo. Esto es especialmente conveniente si estamos leyendo números. 
Podemos extraer la cadena hasta un separador (un espacio blanco) y luego 
averiguar cuáles caracteres nos interesa y cuáles no.


Espero que esto te ayude.

Steven







Más información sobre la lista de distribución Cconclase