2012-06-27 6 views
6

Todavía soy un principiante en la programación en lenguajes de programación de alto nivel, por lo que no sé si esta es una solución fácil, pero estoy contento de aprender de todos modos. He programado un pequeño programa de alarma en C# que permite al usuario ingresar cuántos segundos debe transcurrir para que suene la alarma. Funciona perfectamente, pero la entrada que el usuario debe dar tiene que ser un número. Cuando el usuario ingresa cualquier tipo de texto, el programa falla. Ahora, ¿cómo puedo evitar que los usuarios ingresen texto y llamen a una función o hagan otra cosa cuando el usuario lo hace, en lugar de que el programa simplemente se bloquee?¿Cómo prevenir ciertas formas de entrada al escribir métodos?

Este es el código que tengo ahora:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace Test 
{ 
    class Alarm 
    { 
     public static void play() 
     { 
      int sec; 
      sec = Convert.ToInt16(Console.ReadLine()); 

      for (int i = 0; i < seconds; ++i) 
      { 
       System.Threading.Thread.Sleep(1000); 
      } 

      for (int i = 0; i < 10; i++) 
      { 
       Console.Beep(); 
      } 
     } 
    } 
} 
+0

Bueno, la parte superior de la cabeza, se podría utilizar un '' try' catch' alrededor del convertido y manejar la excepción como usted quiera, por ejemplo pedirles que volver a introducir un valor. – user17753

+3

En una nota separada, 'int' es un' Int32' no un 'Int16'. 'short' es el alias de' Int16' –

+0

@JustinPihony No sabía nada de eso. Acepté todas las respuestas del pasado que me ayudaron. Gracias por el consejo. :) – DutchLearner

Respuesta

11

Usted debe completar una verificación antes de la conversión:

int sec; 

if (int.TryParse(Console.ReadLine(), out sec) 
{ 
    // this is valid continue 
} 
else 
{ 
    // show error highlighting that entry must be a number 
} 

int.TryParse devolverá un booleano destacar si la entrada es apta para su procesamiento a un int. También establecerá su variable sec en el valor si tiene éxito.

+0

Eso funcionó, ¡muchas gracias! Solo necesitaba poner todo en un ciclo while y hacer un valor booleano que evaluara si la función podría finalizar o no, y eso fue todo. : D – DutchLearner

1

se debe utilizar un método de prueba de análisis.

Algo como esto:

int number; 
    bool result = Int32.TryParse(Console.ReadLine(), out number); 

Si el resultado es verdadero, entonces se ha analizado correctamente, lo que significa que es un entero. Si no, ha fallado, lo que significa que no es un número entero.

A continuación, puede utilizar el número como el valor que se analizó como su int32.

0

reemplazar

sec = Convert.ToInt16(Console.ReadLine()); 

con

try { 
    sec = Convert.ToInt16(Console.ReadLine()); 
} 

catch(Exception e){ 
    Console.Writeline(" Enter numbers only"); 
} 
+6

¡NO !, TryParse está ahí por una razón, no use excepciones para el control normal del flujo. –

+0

@Scott: tiene razón. lanzar una excepción es más caro. Evítalo cuando puedas – codingbiz

+0

No estoy seguro del costo pero, elimina la declaración if – madhairsilence

7

Usted podría bucle indefinidamente hasta que el usuario introduce un número:

int number = 0; 
while(!Int32.TryParse(Console.ReadLine(), out number)) 
{ 
    Console.WriteLine("Please input a number."); 
} 

Int32.TryParse vuelve false si la conversión no, en vez de lanzar una excepción y si es exitoso devuelve el resultado i n el segundo parámetro out.

0

Lo que está tratando de hacer a menudo se llama Input Validation. En su caso, debe verificar que hayan ingresado un número antes de analizarlo. Int16 tiene una función TryParse que te ayudará.

1

La gente ya respondió aquí. Me encanta hacer eso como extension method para poder llamarlo en tantos lugares.

public static bool IsNumeric(this string theValue) 
{ 
    long retNum; 
    return long.TryParse(theValue, System.Globalization.NumberStyles.Integer, 
      System.Globalization.NumberFormatInfo.InvariantInfo, out retNum); 
} 

Entonces lo llamaré como esto

if(Console.ReadLine().IsNumeric()) 
{ 
    //The value is numeric. You can use it  
} 
0

Adición de una función separada que utiliza una instrucción try para capturar el error que se producen cuando su intento para convertir una cadena no válida a un entero.

int readInput() 
{ 
    int sec; 
    while(true) 
    { 
     try 
     { 
      sec = Convert.ToInt16(Console.ReadLine()); 
      return sec; 
     } 
     catch(Exception e) 
        { 
          Console.WriteLine("Enter an integer!"); 
        } 
    } 
    return 0; 
} 
+0

No quieres hacer esto ... El manejo de excepciones para formar parte del flujo de control es similar al uso de instrucciones goto no locales en todo tu código. – Blueberry

0

Si usted quiere hacer algo más elegante de mostrar un mensaje de error y pidiendo al usuario que vuelva a introducir los datos, podría intentar procesar cada pulsación de tecla como ocurre con Console.Readkey() y rechazarlas si el daría lugar a una cadena eso no es un numero

Hice algo así hace años en TurboPascal.

Se trata de un pseudocódigo escrito desde la memoria pero que debe llevarlo por el camino correcto. Si necesita tomar valores de coma flotante así como enteros, o números negativos y positivos, necesitará agregar más lógica para manejar esos casos.

string enteredText = ""; 
char key; 
bool done = false; 
while (!done) 
{ 
    key = Console.ReadKey(); 
    if (key is number) 
     enteredText += key; 
    else if (key is backspace) 
    { 
     //remove the last char from enteredText. Handle case where enteredText has length 0 
     Console.Write(backspace); 
    } 
    else if ((key is enter) && (enteredText.Length > 0)) 
     done = true; 
    else 
    { 
     // invalid char. 
     //MSDN says the char is echoed to the console so remove it 
     Console.Write(backspace); 
     //Beep at the user? 
    } 
} 
Cuestiones relacionadas