Dev - C++ - ...Problema con scanf...

   
Vista:

...Problema con scanf...

Publicado por Ronald (3 intervenciones) el 04/11/2007 02:19:52
Saludos...

Tengo un problema con el scanf bastante raro. Hice este ejemplo (c++) facil de entender que muestra el problema:

#include <stdio.h>
int main()
{
char letra;
int num;
do{
scanf("%d", &num);
if(num > 0)
printf("%s\n", "es mayor a cero");
else
printf("%s\n", "no es mayor a cero");
scanf("%c", &letra);
}while(letra != '*');
return 1;
}

Lo que hace, lee un numero y dice si es mayor que cero o no. A continuacion lee un caracter, si el caracter leido es asterisco * entonces se termina el programa, sino vuelve a leer un numero.

Bastante simple, pero los reto a que lo prueben y veran que luego de leer el caracter vuelve a imprimir "es mayor a cero" o "no es mayor a cero". Osea que para cada numero ingresado muestra dos veces si es mayor a cero o no.

Este comportamiento es el problema pues para mi oficio necesito que la cantidad de salidas sea exacto pues esta la almacena en un archivo y luego verificada por otro programa.

Este programa funciona sin problemas usando el iostream, asi:

#include <iostream>
int main()
{
char letra;
int num;
do{
std::cin >> num;
if(num > 0)
std::cout << "es mayor a cero\n";
else
std::cout << "es mayor a cero\n";
std::cin >> letra;
}while(letra != '*');
return 1;
}

Pero necesito usar scanf por sus funciones de formateado al igual que printf.

Bueno si es que alguien se ha topado con este problema y llego con la solucion por favor responder a este post.

Nos vemos...
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

RE:...Problema con scanf...

Publicado por eduardo (26 intervenciones) el 04/11/2007 19:49:49
Eso no es raro pues es algo logico que el programa reaccione de esa manera
lo que sucede es lo siguiente:

scanf("%d", &num);
lee el numero y al pulsar enter el caracter '\n' queda en el bufer de entrada

continua...
scanf( "%c", &letra ); toma '\n' y continua con la sgte instruccion sin esperar el ingreso del caracter desde teclado ya que scanf() encontró '\n' en el bufer

}while(letra != '*'); esto es verdadero ya que '\n' != '*'

arriba de nuevo..
scanf("%d", &num);
aca te permite ingresar el numero lo que tu asumes ingresar caracter y por error ingresas un caracter con lo cual no se asigna nada a la variable num y esta sigue teniendo el valor anterior es por eso que se repite el mensaje

Para corregir eso limpia el bufer de entrada despues de leer num para q te permita leer letra.

#include <stdio.h>
int main()
{
char letra;
int num;
do{
printf( " Ingrese numero entero: " );
scanf( "%d", &num );
if(num > 0)
printf( " %s\n", "es mayor a cero" );
else
printf( " %s\n", "no es mayor a cero" );

fflush( stdin );
printf( " Pulse * para terminar: " );
scanf( "%c", &letra );
}while (letra != '*' );

return 1;
}
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:...Problema con scanf...

Publicado por Ronald (3 intervenciones) el 04/11/2007 23:22:18
Hola Eduardo.

La verdad tiene logica lo que tu dices. Habia leido sobre el buffer de la entrada estandar, pero no se me ocurrio como era que afectaba a mi codigo.

Intente exactamente lo que tu propones, pero el problema no se soluciona (letra sigue capturando el valor de '\n'). Ya lo comprobe ejecutando paso a paso y mirando el valor de letra.

Osea parece que no funciona el fflush(stdin). Lo has probado??

Nota: estoy utilizando el compilador gcc de linux... sera eso?

Bueno saludos...
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

una solucion

Publicado por Ronald (3 intervenciones) el 04/11/2007 23:35:31
Bueno como el fflush no funciona, una posible solucion seria leer dos veces un caracter. Ya se que no es una manera elegante de solucionar pero funciona.

El codigo quedaria asi:

#include <iostream>

int main()
{
char letra;
int num;
do{
scanf("%d", &num);
if(num > 0)
printf("%s\n", "es mayor a cero");
else
printf("%s\n", "no es mayor a cero");

fflush( stdin );
printf( " Pulse * para terminar: " );
scanf("%c", &letra);
scanf("%c", &letra); //<--esto aumente
}while(letra != '*');
return 1;
}

Alguna otra sugerencia??

Saludos...
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:una solucion

Publicado por Gonzalo (2 intervenciones) el 12/11/2007 08:32:34
#include <stdio.h>

int main()
{
char letra;
int num;

do{

scanf("%d", &num);
fflush( stdin );

if(num > 0)
printf("%s\n", "es mayor a cero");
else
printf("%s\n", "no es mayor a cero");

printf( " Pulse * para terminar: " );
scanf("%c", &letra);
fflush( stdin );

}while(letra != '*');

return 1;
}
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:una solucion

Publicado por Miguel Santos M. (1 intervención) el 09/09/2012 20:05:36
Es un problema con scanf() ademas que tiene ese inconveniente, no logras controlarlo en ocaciones una solución que algunos autores sugieren:

#include <stdlib.h>


float cato;
char buff[6];


cato=atof(gets(buff)); // tomo el valor como char y lo transforma a float
estan para la conversion atol, atoi, atof, esto es convierte del caracter (ascii) a long. integer, float, y te evitas problemas del \n.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

...Problema con scanf...

Publicado por Alan (1 intervención) el 06/05/2017 12:08:59
Hola,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h> 
int main()
{
char letra;
int num;
do{
scanf("%d", &num);//Primer scanf 
if(num > 0)
printf("%s\n", "es mayor a cero");
else
printf("%s\n", "no es mayor a cero");
scanf("%c", &letra);//Segundo scanf
}while(letra != '*');
return 1;
}

el comportamiento del susodicho programa es el siguiente. El Primer scanf analizará el especificador de formato que le mandamos, que en este programa es %d, así que primero descartará cualquier espacio que haya en el buffer de entrada (en este caso, ninguno) y después intentará leer un valor entero desde el buffer de entrada. Como en este momento el buffer está vacío, la ejecución se detendrá, a la espera de que se introduzca un valor. Si escribimos 50 y presionamos Enter, en el buffer se tendrá algo así: 50\n.

En este momento, el Primer scanf leerá el '5' y el '0', que son caracteres válidos para un entero, y a continuación encontrará el '\n', que no es un caracter válido para un entero, así que terminará de leer, y asignará el valor 50 a num, dejando el buffer así: \n

El Segundo scanf , que tiene el especificador de formato %c, leerá lo que haya en el buffer y se encontrará directamente con un '\n' (justo el caracter que le indica que deje de leer), así que lo asignará a letra, y saltará a la siguiente instrucción, sin habernos dejado escribir nada.

Posteriormente, como '\n' != '*' se ejecutará el Primer scanf el cual esperará la introducción de un valor. Si escribimos '*' y presionamos Enter, en el buffer se tendrá algo así:*\n. En este momento, el Primer scanf leerá el '*' que no es un caracter válido para un entero, así que terminará de leer, y mantendrá el valor 50 en num, dejando el buffer así:* \n

Cuando se ejecute el Segundo scanf , que tiene el especificador de formato %c, leerá lo que haya en el buffer y se encontrará directamente con un '*' así que lo asignará a letra dejando el buffer así:\n.

Por ende, como '*' != '*' es falso se ejecutará la línea 14.

Pues bien, la solución a su problema podría ser escribir en el Segundo scanf la cadena de control " %c" , es decir, añadir un espacio justo antes del caracter %. La razón de esto la encontrará en la página que abre el siguiente link :http://decsai.ugr.es/~jfv/ed1/c/cdrom/cap3/lec34.htm

En el video que he adjuntado podrás ver mediante la depuración del código lo explicado y algo más.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar