2012-06-27 6 views
6

Wciąż jestem początkującym programistą w językach programowania wysokiego poziomu, więc nie wiem, czy jest to łatwe rozwiązanie, ale i tak się cieszę. Zaprogramowałem mały program alarmowy w języku C#, który pozwala użytkownikowi wprowadzić ile sekund alarm musi zgasnąć. Działa doskonale, ale dane wejściowe, które musi podać użytkownik, muszą być liczbą. Kiedy użytkownik wprowadza dowolną formę tekstu, program ulega awarii. Teraz, w jaki sposób mogę zapobiec temu, aby użytkownicy wprowadzali tekst i wywoływali funkcję lub robili coś innego, gdy robił to użytkownik, zamiast po prostu ulegał awarii?Jak zapobiegać niektórym formom wprowadzania danych podczas pisania metod?

Jest to kod mam teraz:

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

Cóż, z góry mojej głowy można użyć 'try'' catch' wokół konwertera i obsłużyć wyjątek, jak ci się podoba, na przykład poproś go o ponowne wprowadzenie wartości. – user17753

+3

W osobnej notatce "int" to "Int32", a nie "Int16". 'short' jest aliasem' Int16' –

+0

@JustinPihony Nawet o tym nie wiedziałem. Przyjąłem wszystkie odpowiedzi z przeszłości, które mi pomogły. Dzięki za wskazówkę. :) – DutchLearner

Odpowiedz

11

Należy wypełnić czek przed konwersją:

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 zwróci wartość logiczną podkreślając, czy wejście jest parsable do wew. Ustawi także zmienną sec na wartość, jeśli się powiedzie.

+0

To działało, dzięki pęczku! Musiałem tylko umieścić wszystko w pętli while i utworzyć wartość logiczną, która oceniła, czy funkcja mogła się zakończyć, czy nie, i to było to. : D – DutchLearner

1

Należy stosować metodę próba przetworzenia.

coś takiego:

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

Jeśli wynik jest prawdziwe, to z powodzeniem analizowany go, co oznacza, że ​​jest liczbą całkowitą. Jeśli nie, to się nie udało, co oznacza, że ​​nie jest liczbą całkowitą.

Można wtedy użyć liczby jako wartości, która została zanalizowana jako int32.

0

zastąpić

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

z

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

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

NIE !, TryParse jest tam z jakiegoś powodu, nie używaj wyjątków dla normalnej kontroli przepływu. –

+0

@Scott: ma rację. rzucanie wyjątku jest droższe. Unikaj tego, kiedy możesz – codingbiz

+0

nie jestem pewien co do kosztu, ale eliminuje dodatkowe, jeśli oświadczenie – madhairsilence

7

Mogłabyś pętli w nieskończoność, dopóki użytkownik wprowadza numer:

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

Int32.TryParse powraca false jeśli konwersja nie powiodła się, zamiast rzucania wyjątek i jeśli się powiedzie, zwraca wynik i n drugi parametr out.

0

To, co próbujesz zrobić, jest często nazywane Input Validation. W twoim przypadku musisz sprawdzić, czy wprowadzono numer przed analizą. Int16 ma funkcję TryParse, która ci pomoże.

1

Już tu odpowiedziano. Uwielbiam to zrobić jako extension method, dzięki czemu mogę go nazwać w wielu miejscach.

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

Wtedy nazwać jak ten

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

Dodawanie oddzielną funkcję, która korzysta oświadczenie próbować złapać błędzie produkować gdy próba tajnych nieprawidłowy ciąg do liczby całkowitej.

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

Nie chcesz tego robić ... Obsługa wyjątków jako część przepływu sterowania jest podobna do używania nielokalnych instrukcji goto w całym kodzie. – Blueberry

0

Jeśli chcesz zrobić coś bardziej eleganckie niż wyświetlanie komunikatu o błędzie i prosząc, aby użytkownik mógł ponownie wprowadzić dane, można spróbować przetwarzania każde naciśnięcie klawisza jak to się dzieje z Console.Readkey() i ich odrzucenie, jeśli spowodowałoby sznurku to nie jest liczba.

Zrobiłem coś takiego w tym roku w TurboPascal.

To jest pseudokod napisany z pamięci, ale powinien cię ustawić na właściwej ścieżce. Jeśli chcesz pobierać wartości zmiennoprzecinkowe, a także liczby całkowite lub ujemne i dodatnie, musisz dodać więcej logiki, aby obsłużyć te przypadki.

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? 
    } 
}