Loops infinitos en input erroneos

Iniciado por RyogiShiki, 31 Marzo 2011, 00:04 AM

0 Miembros y 3 Visitantes están viendo este tema.

RyogiShiki

Hola que tal.

Pues me surgió esta duda, digamos que quiero pedir un dato entero, y necesito que sea entero entonces hago lo siguiente:

Código (cpp) [Seleccionar]
int number
cin >> number;


para comprobar si es un entero puedo hacerlo con:

Código (cpp) [Seleccionar]
if(cin.fail())

y lo puedo detectar sin problemas si lo que se ha ingresado no es un entero, el problema viene cuando por ejemplo en un menu con un loop while hago dicha comprobación (pongo un code de ejemplo que no necesariamente es de un menu, mi idea esta basada en ejemplos para exponer el problema general):

Código (cpp) [Seleccionar]
while(/*condicion*/){
   cin >> number;
   if(cin.fail()){/*ERROR*/}
}


Pero allí está el problema, no importa que ciclo use (for, do-while, while, nisiquiera un asqueroso loop formado con un goto) Si la entrada no es la esperada el programa entrará a un loop infinito donde se presenta lo contenido en el condicional if.

Este problema de loop infinito es muy común cuando se ingresan datos aun programa que no son los que el programa esperaba. Me preguntaba si existía una forma para evitar entrar en estos molestos loops.

Y no necesarimente se presenta cuando la lectura y/o validación de datos está dentro de un loop.

Gracias


Akai

#1
El problema, creo que es porque el flag fail se establece si se produce un error de lógica interna en el stream.

Prueba con good negado (good está establecido si no hay ningún fallo, y cae si se presenta algún fallo) en vez de fail (que únicamente aparece con errores de lógica interna del stream)
Código (cpp) [Seleccionar]
if(!cin.good())

EDIT:

Añado, otra alternativa es usar badbit en vez de fail. Badbit comprueba los fallos en la operación de entrada / salida. good negado los comprueba todos (fail, badbit, eofbit), pero si no te interesa tanta información, usar únicamente badbit si no me equivoco debido al sueño en estos momentos debería darte la solución.

Samael.Black

#2
Cita de: gankutsuo en 31 Marzo 2011, 00:04 AM
Hola que tal.

Pues me surgió esta duda, digamos que quiero pedir un dato entero, y necesito que sea entero entonces hago lo siguiente:

Código (cpp) [Seleccionar]
int number
cin >> number;


para comprobar si es un entero puedo hacerlo con:

Código (cpp) [Seleccionar]
if(cin.fail())

y lo puedo detectar sin problemas si lo que se ha ingresado no es un entero, el problema viene cuando por ejemplo en un menu con un loop while hago dicha comprobación (pongo un code de ejemplo que no necesariamente es de un menu, mi idea esta basada en ejemplos para exponer el problema general):

Código (cpp) [Seleccionar]
while(/*condicion*/){
   cin >> number;
   if(cin.fail()){/*ERROR*/}
}


Pero allí está el problema, no importa que ciclo use (for, do-while, while, nisiquiera un asqueroso loop formado con un goto) Si la entrada no es la esperada el programa entrará a un loop infinito donde se presenta lo contenido en el condicional if.

Este problema de loop infinito es muy común cuando se ingresan datos aun programa que no son los que el programa esperaba. Me preguntaba si existía una forma para evitar entrar en estos molestos loops.

Y no necesarimente se presenta cuando la lectura y/o validación de datos está dentro de un loop.

Gracias

Yo cuando estuve aprendiendo a programar (aun no aprendo bien)... me tope con eso... lo que yo hacia para evitarlo... era crear una variable char (la cual almacenaría el numero introducido por el usuario) y le daba un carácter de 0 a esta variable (algo asi char variable[2] = "0"; ) entonces usando la funciona atoi(variable) transformaba el carácter introducido por el usuario a un numero... y ya nunca mas me volvió a pasar eso... claro no se si sea muy practico... hacer esto... pero me funciono después buscare otras soluciones...

Pd: en caso de que el usuario introduce un carácter o cadena de caracteres... este por la función atoi... automáticamente tendría el valor de 0... (osea siempre manejarías números aunque se introdujeran caracteres)...

mauriciodelos

#3
Probaste creando un int (c) o un bool (c++) y con un do while?

Digo...


Código (cpp) [Seleccionar]

bool error;

do
{
   error=false;

   cin >> number;
   if(cin.fail()){error=true;}


}while(error==true;)


Al empezar el bucle declararías la variable error como falsa para que no se genere un bucle infinito.
El fanatismo es la máxima estupidez humana.

RyogiShiki

Que puedo decir:

@Akai: gracias por la rápida respuesta! pero debo decir que nada de esto me ha servido, no negar cin.good ni usando los bits, ni limpiando con cin.clear nada ha funcionado. Gracias igual por la colaboración, si se te ocurre algo más bien puedes compartirlo.

@mauriciodelos: esto tampoco ha funcionado me lleva al loop infinito siempre

@Samael.Black: esta parece ser la solución más viable, habia pensado en algo parecido antes de escribir este tema pero en mi mente todavía persistia la idea de la existencia de un método diferente para realizar esta tarea.

Gracias a todos! Ya saben, si surge algo avisen porfa!

Saludos


Akai

#5
Tal como te dijo samael, leer como cadena y luego extraer el número (de la forma que sea) parece ser la opción más viable. Es un tema que se ha tratado últimamente por aquí:

Entre otras: leer un char[] y usar sprintf o usar sstreams (string streams)

http://foro.elhacker.net/programacion_cc/referencia_de_un_char_en_una_funcionakai_pasate_por_favor_que_modificadoxd-t322721.0.html

EDIT: en realidad, en vez de sprintf, sería scanf, con sprintf escribes en la cadena, con scanf lees.

RyogiShiki

Cita de: Akai en  1 Abril 2011, 11:01 AM
Tal como te dijo samael, leer como cadena y luego extraer el número (de la forma que sea) parece ser la opción más viable. Es un tema que se ha tratado últimamente por aquí:

Entre otras: leer un char[] y usar sprintf o usar sstreams (string streams)

http://foro.elhacker.net/programacion_cc/referencia_de_un_char_en_una_funcionakai_pasate_por_favor_que_modificadoxd-t322721.0.html

Bien gracias por la respuesta! habia visto el hilo, pero no lo habia leido en detalle.

Saludos


Akai

Corrijo,
Cita de: Akai en  1 Abril 2011, 11:01 AM
Entre otras: leer un char[] y usar sprintf o usar sstreams (string streams)

NO, sprintf NO, quería decir scanf. sprintf te imprime algo en una cadena, lo que tu quieres es leer de la cadena.

PD: he creído conveniente avisar del cambio añadiendo una respuesta al tema.