Discussion:
Alternativas para scanf()
(demasiado antiguo para responder)
SuperLopez
2003-07-08 20:46:42 UTC
Permalink
Hola a todos:

Tengo el siguiente codigo:

-----------------flotante.c------------------------
#include <stdio.h>
#define MAX 999.99

int main()
{
float num1,num2,res;
res=0.0;

do{
printf("\n\nDime el primer operando (con decimales y <1000): ");
scanf("%f",&num1);
printf("Dime el segundo operando (con decimales y <1000): ");
scanf("%f",&num2);
}while((num1>MAX)&&(num1>MAX));

printf("\n\n%9.2f",num1);
printf("\n+%8.2f",num2);
printf("\n---------");
printf("\n%9.2f\n\n",res=num1+num2);

return 0;
}
----------------EOF---------------------------------

Como se puede apreciar realizo la lectura de los datos de
entrada con la funcion scanf().

¿Que podria utilizar en su lugar (dentro del estandar) para
verificar la correccion de los datos introducidos por teclado
(evitando asi las entradas "con malaleche")?

Muchas gracias de antemano

Saludos
J. L.
2003-07-08 21:34:12 UTC
Permalink
Post by SuperLopez
-----------------flotante.c------------------------
#include <stdio.h>
#define MAX 999.99
int main()
{
float num1,num2,res;
res=0.0;
do{
printf("\n\nDime el primer operando (con decimales y
<1000): "); scanf("%f",&num1);
"); scanf("%f",&num2);
}while((num1>MAX)&&(num1>MAX));
printf("\n\n%9.2f",num1);
printf("\n+%8.2f",num2);
printf("\n---------");
printf("\n%9.2f\n\n",res=num1+num2);
return 0;
}
----------------EOF---------------------------------
Como se puede apreciar realizo la lectura de los datos de
entrada con la funcion scanf().
¿Que podria utilizar en su lugar (dentro del estandar) para
verificar la correccion de los datos introducidos por teclado
(evitando asi las entradas "con malaleche")?
Con una combinacion de fgets() (pero hay que tener cuidado con los
desbordamientos del buffer) y strtod() (que permite el manejo de
errores).
Post by SuperLopez
Muchas gracias de antemano
Saludos
--
José L. Sánchez Garrido
SuperLopez
2003-07-09 13:08:34 UTC
Permalink
Hola, gracias por tu respuesta.
Si no es mucho pedir, ¿te importaria añadir algun ejemplo practico?

Saludos
Post by J. L.
Post by SuperLopez
-----------------flotante.c------------------------
#include <stdio.h>
#define MAX 999.99
int main()
{
float num1,num2,res;
res=0.0;
do{
printf("\n\nDime el primer operando (con decimales y
<1000): "); scanf("%f",&num1);
"); scanf("%f",&num2);
}while((num1>MAX)&&(num1>MAX));
printf("\n\n%9.2f",num1);
printf("\n+%8.2f",num2);
printf("\n---------");
printf("\n%9.2f\n\n",res=num1+num2);
return 0;
}
----------------EOF---------------------------------
Como se puede apreciar realizo la lectura de los datos de
entrada con la funcion scanf().
¿Que podria utilizar en su lugar (dentro del estandar) para
verificar la correccion de los datos introducidos por teclado
(evitando asi las entradas "con malaleche")?
Con una combinacion de fgets() (pero hay que tener cuidado con los
desbordamientos del buffer) y strtod() (que permite el manejo de
errores).
Post by SuperLopez
Muchas gracias de antemano
Saludos
J. L.
2003-07-09 16:20:50 UTC
Permalink
Post by SuperLopez
Hola, gracias por tu respuesta.
Si no es mucho pedir, ¿te importaria añadir algun ejemplo
practico?
Saludos
Post by J. L.
Con una combinacion de fgets() (pero hay que tener cuidado
con los
desbordamientos del buffer) y strtod() (que permite el manejo de
errores).
Post by SuperLopez
Muchas gracias de antemano
Saludos
A ver qu te parece el siguiente ejemplo:

-----------------flotante.c------------------------
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define MAX 999.99

int main(void){

char buffer[100], *res;
int test=0;
float num1,num2;

do {
printf("\n\nDime el primer operando "
"(con decimales y <1000): ");
fflush(stdout);
while(fgets(buffer, 100, stdin)!=NULL){
num1=strtod(buffer, &res);
if(num1 > MAX || errno == ERANGE){
fputs("El operando debe ser menor que 1000.\n", stderr);
fputs("Vuelve a intentarlo.\n", stderr);
break;
}
test=1;
break;
}
} while(test==0);

test=0;
do {
printf("\n\nDime el segundo operando "
"(con decimales y <1000): ");
fflush(stdout);
while(fgets(buffer, 100, stdin)!=NULL){
num2=strtod(buffer, &res);
if(num2 > MAX || errno == ERANGE){
fputs("El operando debe ser menor que 1000.\n", stderr);
fputs("Vuelve a intentarlo.\n", stderr);
break;
}
test=1;
break;
}
} while(test==0);

printf("\n\n%9.2f", num1);
printf("\n+%8.2f", num2);
printf("\n---------");
printf("\n%9.2f\n\n", num1 + num2);

return 0;
}

----------------EOF---------------------------------

Saludos
--
José L. Sánchez Garrido
Fernando Arbeiza
2003-07-09 16:45:35 UTC
Permalink
Post by SuperLopez
-----------------flotante.c------------------------
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define MAX 999.99
int main(void){
char buffer[100], *res;
int test=0;
float num1,num2;
do {
printf("\n\nDime el primer operando "
"(con decimales y <1000): ");
fflush(stdout);
while(fgets(buffer, 100, stdin)!=NULL){
/*
* Este while puede provocar un bucle infinito si se llega al final del
* fichero, ya que nunca cambiaría test.
*/

if (fgets(buffer, 100, stdin) == NULL) {
fputs("Error.\n", stderr);
exit(EXIT_FAILURE);
}

errno = 0; /* Si no, no puedes asegurar que ERANGE provenga de
la llamada a strtod */
Post by SuperLopez
num1 = strtod(buffer, &res);
if(num1 > MAX || errno == ERANGE){
fputs("El operando debe ser menor que 1000.\n", stderr);
fputs("Vuelve a intentarlo.\n", stderr);
break;
}
/* Comprobación de que se ha introducido un número */
if (buffer == res) {
fputs("El operando debe ser un número.\n", stderr);
fputs("Vuelve a intentarlo.\n", stderr);
break;
}
Post by SuperLopez
test=1;
break;
}
} while(test==0);
test=0;
do {
printf("\n\nDime el segundo operando "
"(con decimales y <1000): ");
fflush(stdout);
while(fgets(buffer, 100, stdin)!=NULL){
num2=strtod(buffer, &res);
if(num2 > MAX || errno == ERANGE){
fputs("El operando debe ser menor que 1000.\n", stderr);
fputs("Vuelve a intentarlo.\n", stderr);
break;
}
test=1;
break;
}
} while(test==0);
printf("\n\n%9.2f", num1);
printf("\n+%8.2f", num2);
printf("\n---------");
printf("\n%9.2f\n\n", num1 + num2);
return 0;
}
----------------EOF---------------------------------
Por cierto, ¿existe alguna ventaja que se me escape respecto a scanf,
aparte de la comprobación de desbordamiento?

Un saludo.
--
Fernando Arbeiza <URL: mailto:***@ono.com>
Crea tu propio Linux: <URL: http://www.escomposlinux.org/lfs-es>
Fernando Arbeiza
2003-07-09 17:57:38 UTC
Permalink
Post by Fernando Arbeiza
if (fgets(buffer, 100, stdin) == NULL) {
fputs("Error.\n", stderr);
exit(EXIT_FAILURE);
}
Estoy de acuerdo con tus observaciones... solo que en este lugar,
el codigo nunca se ejecuta. Debe ir al final del while().
¿Ein? Ahora sí que me he perdido. Si mueves el fgets, entonces
estarás haciendo el strtod antes de leer la línea. Creo que lo
reescribiré a ver si nos aclaramos los dos ;-)

/***************/
while (1) {
printf("\n\nDime el primer operando (con decimales y <1000): ");
fflush(stdout);

if (fgets(buffer, 100, stdin) == NULL) {
fputs("Error.\n", stderr);
exit(EXIT_FAILURE);
}

errno = 0;
num1 = strtod(buffer, &res);
if((num1 <= MAX) && (errno == 0) && (buffer != res)) { break; }

fputs("Vuelve a intentarlo.\n", stderr);
}
/***************/

Aunque igual lo he liado un poco más.

Un saludo.
--
Fernando Arbeiza <URL: mailto:***@ono.com>
Crea tu propio Linux: <URL: http://www.escomposlinux.org/lfs-es>
J. L.
2003-07-09 18:14:37 UTC
Permalink
Post by Fernando Arbeiza
Post by Fernando Arbeiza
if (fgets(buffer, 100, stdin) == NULL) {
fputs("Error.\n", stderr);
exit(EXIT_FAILURE);
}
Estoy de acuerdo con tus observaciones... solo que en este
lugar, el codigo nunca se ejecuta. Debe ir al final del
while().
¿Ein? Ahora sí que me he perdido. Si mueves el fgets, entonces
estarás haciendo el strtod antes de leer la línea. Creo que lo
reescribiré a ver si nos aclaramos los dos ;-)
No, que el que andaba perdido era yo :-(. No me di cuenta de que
el if() que proponias era en substitucion del while() que yo
tenia.
Post by Fernando Arbeiza
/***************/
while (1) {
printf("\n\nDime el primer operando (con decimales y
<1000): "); fflush(stdout);
if (fgets(buffer, 100, stdin) == NULL) {
fputs("Error.\n", stderr);
exit(EXIT_FAILURE);
}
errno = 0;
num1 = strtod(buffer, &res);
if((num1 <= MAX) && (errno == 0) && (buffer != res)) {
break; }
fputs("Vuelve a intentarlo.\n", stderr);
}
/***************/
Aunque igual lo he liado un poco más.
Pero es que esto de la interaccion con el exterior es un engorro
:-)
Post by Fernando Arbeiza
Un saludo.
Saludos
--
José L. Sánchez Garrido
Fernando Arbeiza
2003-07-09 18:19:17 UTC
Permalink
Post by J. L.
No, que el que andaba perdido era yo :-(. No me di cuenta de que
el if() que proponias era en substitucion del while() que yo
tenia.
O fallo de mi explicación, pero no nos vamos a pegar por eso.
Post by J. L.
Pero es que esto de la interaccion con el exterior es un engorro
:-)
Ten cuidado, frases como esas te acaban convirtiendo en un ermitaño ;-P

Un saludo.
--
Fernando Arbeiza <URL: mailto:***@ono.com>
Crea tu propio Linux: <URL: http://www.escomposlinux.org/lfs-es>
SuperLopez
2003-07-09 21:52:20 UTC
Permalink
Hola

Muchas gracias a los dos por vuestras respuestas. Algo asi era lo que
buscaba pero no conseguia hacer funcionar strtod().

Saludos
Fernando Arbeiza
2003-07-08 22:19:02 UTC
Permalink
Hola:

¿Por qué no utilizas el valor devuelto por scanf? (si es que he
entendido bien tu duda):

On 8 Jul 2003 13:46:42 -0700, SuperLopez <***@hotmail.com> wrote:

#include <stdlib.h>

/* ... */
Post by SuperLopez
do {
printf("\n\nDime el primer operando (con decimales y <1000): ");
fflush(stdout);
if (scanf("%f", &num1) < 1) {
fputs("Error en los datos\n", stderr);
exit(EXIT_FAILURE);
}
Post by SuperLopez
printf("Dime el segundo operando (con decimales y <1000): ");
fflush(stdout);
if (scanf("%f", &num2) < 1) {
fputs("Error en los datos\n", stderr);
exit(EXIT_FAILURE);
}
} while((num1 > MAX) && (num2 > MAX));

Un saludo.
--
Fernando Arbeiza <URL: mailto:***@ono.com>
Crea tu propio Linux: <URL: http://www.escomposlinux.org/lfs-es>
Fernando Arbeiza
2003-07-09 15:02:35 UTC
Permalink
Mi duda es, ¿como puedo controlar la entrada del usuario para que sea
la esperada?
Mi respuesta es: no puedes controlar la entrada del usuario ;-P Ahora en
serio, lo que puedes hacer es dar la coña al usuario hasta que se
introduzca bien el número. Para ello sólo tenías que modificar
ligeramente lo que te expuse (más atento la próxima vez ;-).

A ver que te parece:

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

/* ... */

do {
int valores;

printf("\n\nDime el primer operando (con decimales y <1000): ");
fflush(stdout);
valores = scanf("%f", &num1);
if (valores < 0) {
fputs("Error en los datos\n", stderr);
exit(EXIT_FAILURE);
} else if (valores < 1) {
continue;
}
} while (num1 > MAX);

do {
int valores;

printf("\n\nDime el segundo operando (con decimales y <1000): ");
fflush(stdout);
valores = scanf("%f", &num2);
if (valores < 0) {
fputs("Error en los datos\n", stderr);
exit(EXIT_FAILURE);
} else if (valores < 1) {
continue;
}
} while (num2 > MAX);
/**************************/

Ya, ya sé que es un poco largo, pero no veo una forma más sencilla de
hacerlo.

Un saludo.
--
Fernando Arbeiza <URL: mailto:***@ono.com>
Crea tu propio Linux: <URL: http://www.escomposlinux.org/lfs-es>
SuperLopez
2003-07-09 21:50:05 UTC
Permalink
Post by Fernando Arbeiza
Mi respuesta es: no puedes controlar la entrada del usuario ;-P Ahora en
serio, lo que puedes hacer es dar la coña al usuario hasta que se
introduzca bien el número. Para ello sólo tenías que modificar
ligeramente lo que te expuse (más atento la próxima vez ;-).
Lo primero que hice al leer tu respuesta fue estudiarla y probarla pero
no controla la posibilidad de que el usuario tuviera malaleche y introdujera,
por ejemplo, un carácter. Es evidente que no puedes atar al usuario a la silla
pero..¿y cortarle un dedo por cada entrada erronea???....es broma...jaja

Agradezco tus respuestas :-)

Saludos
Fernando Arbeiza
2003-07-09 22:22:11 UTC
Permalink
Post by SuperLopez
Lo primero que hice al leer tu respuesta fue estudiarla y probarla pero
no controla la posibilidad de que el usuario tuviera malaleche y introdujera,
por ejemplo, un carácter.
Pues tienes razón, soy un cazurro. continue lleva al final del bucle, no
al principio; luego se evalúa la condición y sale.

Al principio, modifiqué el código, y puse algo como esto:

/*********************/
int valores;

do {
printf("\n\nDime el primer operando (con decimales y <1000): ");
fflush(stdout);
valores = scanf("%f", &num1);
if (valores < 0) {
fputs("Error en los datos\n", stderr);
exit(EXIT_FAILURE);
}
} while ((valores < 1) || (num1 > MAX));
/*********************/

Pero después de comprobarlo (por si la había vuelto a cagar), he
comprobado en mis propias carnes por qué no debes utilizar scanf (por lo
menos para este caso). Si lo pruebas, intenta introducir un carácter en
lugar de un número y verás. Después, lee esto y entenderás el porqué:

<URL: http://www.eskimo.com/~scs/C-faq/q12.19.html>

Lo que ya hacen dos cagadas por mi parte :-( Así que mejor utiliza
strtod como (muy sensatamente) te dijo J.L. en el otro sub-hilo. Por lo
menos, hemos aprendido donde y por qué no utilizar scanf.
Post by SuperLopez
Es evidente que no puedes atar al usuario a la silla pero..¿y cortarle
un dedo por cada entrada erronea???....es broma...jaja
Sí, pero ya necesitas un hardware específico. ¿Qué te parece si lo
patentamos a medias y nos forramos? ;-) Además, los robos y tarjetas
tragadas en los cajeros automáticos se reducirían muuuuucho.

Un saludo.
--
Fernando Arbeiza <URL: mailto:***@ono.com>
Crea tu propio Linux: <URL: http://www.escomposlinux.org/lfs-es>
Loading...