Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: etcheverrypablol en 8 Marzo 2016, 02:26 am



Título: Evitar leer el salto de línea cuando leemos cadenas en C
Publicado por: etcheverrypablol en 8 Marzo 2016, 02:26 am
Me da cosa hacer tantas preguntas en este foro, averiguo en Internet sobre el tema, pero no se me está haciendo fácil conseguir las respuetas. De ahí que consulto por aquí, encuentro que es un lugar muy activo donde hay personas que están interesados en ayudar y de esa forma aprenden también.

Vuelvo con un tema de las más tontos, pero no le encuentro una solución. El problema se le debe presentar indudablemente a todo aquel que se incia en C. De hecho en este foro Littlehorse se encargó de hacer una lista de las cosas que no debemos hacer en C como novatos.

El problema que se presenta cuando usamos el scanf y queremos leer varias cadenas de caracteres.

Pongo el siguiente ejemplo que encontré en Internet: http://www.carlospes.com/curso_de_lenguaje_c/01_11_la_funcion_fflush.php
EJEMPLO:
Si nosotros escribimos este código:

Código
  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5.   char a, b, c;
  6.  
  7.   printf( "Introduzca primer caracter: " );
  8.   scanf( "%c", &a );
  9.   printf( "Introduzca segundo caracter: " );
  10.   scanf( "%c", &b );
  11.   printf( "Introduzca tercer caracter: " );
  12.   scanf( "%c", &c );
  13.   printf( "Los valores son: %c, %c, %c ", a, b, c );
  14.  
  15.   return 0;
  16. }
  17.  
vamos a ver que nos muestra por pantalla esto:
         
         Introduzca primer caracter: f 
         Introduzca segundo caracter: Introduzca tercer caracter: h
         Los valores son: f,
         , h


Vemos que por pantalla los mensajes no aparecen como queremos. En el ejemplo se comenta que una solución para que no ocurra eso es usando la función fflush. Dejando el código así:

Código
  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5.   char a, b, c;
  6.  
  7.   printf( "Introduzca primer caracter: " );
  8.   scanf( "%c", &a );
  9.   printf( "Introduzca segundo caracter: " );
  10.   fflush( stdin );
  11.   scanf( "%c", &b );
  12.   printf( "Introduzca tercer caracter: " );
  13.   fflush( stdin );
  14.   scanf( "%c", &c );
  15.   printf( "Los valores son: %c, %c, %c ", a, b, c );
  16.  
  17.   return 0;
  18. }
  19.  

Ahora bien, yo compile este programa en mi pc y no me funcionó. Me siguen apareciendo mal los mensajes. Alguno de ustedes que está en el tema, hace uso de la función fflush o qué hacen en este caso? Me debería haber funcionado la función fflush?

Me gustaría hacer uso de otra función como lo es fgets, pero veo que tampoco consigo la solución. Estoy lidiando con la lectura del salto de línea.


Título: Re: Evitar leer el salto de línea cuando leemos cadenas en C
Publicado por: ivancea96 en 8 Marzo 2016, 16:55 pm
Si bien suele funcionar fflush en búferes de entrada, evita usarlo, pues no hay un comportamiento definido para este caso. fflush sirve para forzar y vaciar los búferes de salida.

La mejor opción es que leas una línea completa. Si tiene 1 solo caracter (a parte del salto de línea), habrás logrado tu caracter.
Si se mete por teclado varios caractere, puedes descartar el resto e ignorarlos.
Si se mete por teclado una cadena vacía ("\r\n" o "\n"), puedes volver a pedir la entrada.

Otra opción, es que coloques scanf(" %c", &c); (nótese el espacio antes del %c), para que scanf ignore caracteres en blanco antes del caracter a leer.


Título: Re: Evitar leer el salto de línea cuando leemos cadenas en C
Publicado por: mester en 8 Marzo 2016, 17:23 pm
Es la primera vez en la vida que veo que a un scanf le afecte el salto de línea. La verdad es que sólo me había pasado con fgets, y como solución fue esta:
Código
  1. char cadena[20];
  2. fgets(cadena, 20, stdin);
  3. cadena[strlen(cadena) - 1] = '\0';
  4.  

De esta manera no se imprime el salto de línea.


Título: Re: Evitar leer el salto de línea cuando leemos cadenas en C
Publicado por: MAFUS en 8 Marzo 2016, 20:10 pm
Para vaciar el buffer del teclado después de un scanf puedes usar la siguiente línea de código
Código
  1. while(getchar() != '\n');


Título: Re: Evitar leer el salto de línea cuando leemos cadenas en C
Publicado por: etcheverrypablol en 8 Marzo 2016, 21:08 pm
Hola ivancea96, definiticamente voy a evitar usarlo para estos casos. Leí sobre el scanf(" %c", &c) y una de las formas que encontré de solucionar el problema es colocando scanf( "%*c %c", &b ); dejando el código así:

Código
  1. #include <stdio.h>
  2. int main(int argc, char const *argv[])
  3. {
  4.   char a,b,c;
  5.  
  6.   printf( "Introduzca primer caracter: " );
  7.   scanf( "%c", &a );
  8.   printf( "Introduzca segundo caracter: " );  
  9.   scanf( "%*c %c", &b );
  10.   printf( "Introduzca tercer caracter: " );
  11.   scanf( "%*c %c", &c );
  12.   printf( "Los valores son: %c, %c, %c \n", a, b, c );
  13. return 0;
  14. }
  15.  
Lo que hacemos en la novena y onceaba línea es primero leer con "%*c" el caracter de salto de línea que quedó en el buffer de haber leído la entrada anterior del teclado (lo que queda al apretar Enter) y luego leemos el caracter ingresado.

MAFUS, había leido también sobre tu método, es la primer forma que encontré para soluciónar el problema y funciona muy bien para este caso. El código quedó así:

Código
  1. #include <stdio.h>
  2. int main()
  3. {
  4.   char a, b, c;
  5.  
  6.   printf( "Introduzca primer caracter: " );
  7.   scanf( "%c", &a );
  8.   printf( "Introduzca segundo caracter: " );
  9. while(getchar()!='\n');
  10.  
  11.   scanf( "%c", &b );
  12.   printf( "Introduzca tercer caracter: " );
  13. while(getchar()!='\n');
  14.   scanf( "%c", &c );
  15.   printf( "Los valores son: %c, %c, %c \n", a, b, c );
  16.  
  17.   return 0;
  18. }
  19.  

Aún no termino de entender como es que funciona getchar, ese while sin una sentencia o bloque de código a ejecutar me cayó muy raro jaja.
Veo que en C hay muchísimas maneras para resolver un mismo problema!

mester también había leído sobre lo que comentaste, en su momento usaré ese método.

Muchas gracias nuevamente a todos.

Saludos!


Título: Re: Evitar leer el salto de línea cuando leemos cadenas en C
Publicado por: MAFUS en 8 Marzo 2016, 22:22 pm
La función while en este caso lo que hace es ir tomando caracteres del buffer del teclado y a cada repetición no hace nada, que es lo que marca el punto y coma.

La instrucción se irá repitiendo hasta que recoja el carácter '\n' (lo habrá sacado del buffer) y según la condición, como el carácter devuelto por getchar() será igual a '\n' se va a parar la repetición del while y el programa continuará con el buffer de teclado vacío.


Título: Re: Evitar leer el salto de línea cuando leemos cadenas en C
Publicado por: etcheverrypablol en 9 Marzo 2016, 01:10 am
Perfecto, ahora entiendo cómo es que funciona. Creo que lo voy a usar bastante jaja.