views:

764

answers:

6

Oh, 2 things: 1) It is a console application. 2 ) I know it is in danish, but it doesn't really matter, its just an example of asking for some input. The text and variables does not matter.

Alright, consider this simple input: It could be any sort of input question really.

Console.WriteLine("Hvad er dit kundenummer: (Kun hele tal tilladt)");
string inputKnr = Console.ReadLine();
kundenummer = Convert.ToInt16(inputKnr);

Now, what if the customer types something wrong? Such as a letter. A try & catch would make sure the application does not break, but that is not the solution I want. I want it to say that you did it wrong, try again. Pretty classic right?

But what is the best way to solve this solution? I have thought of this:

bool fangetKundenummer = true;
while (fangetKundenummer)
{
Console.WriteLine("Hvad er dit kundenummer: (Kun hele tal tilladt)");
string inputKnr = Console.ReadLine();
try
{
    kundenummer = Convert.ToInt16(inputKnr);
    fangetKundenummer = false;
}
catch
{
    Console.WriteLine("Fejl. Prøv igen");
}
}

But it just doesn't seem like the right way to do it.

Also, just to mention it, this little application I am playing with has 4 input questions in a row. This would mean 4 times this nasty while() loop.

You could also write a function. Something like this (no reason to do it the right way, its just to illustrate a concept):

static void verifyInput()
{
    try
    {
        Console.WriteLine("question");
        input = Console.ReadLine();
        kundenummer = Convert.ToInt16(input)
    }
    catch
    {
        Console.WriteLine("Wrong. Do it over");
        verifyInput(); //start the function all over
    }
}

But you'd have to write a function for each and every input question, even though they might ask exactly for the same! (meaning perhaps all asking for an integer; but with a different question and variable).

This doesn't seem much better than the while() solution.

Does anyone have a clever idea?

+9  A: 

Use Int16.TryParse and the equivalents for other numeric types. All of these return a Boolean result to indicate success or failure for parsing, and take an out parameter which is set to the result of the parsing (or 0 in case of failure). In your case you may want to wrap the call in a method to keep prompting:

static Int16 PromptForInt16(string prompt)
{
    while (true)
    {
        Console.Write(prompt);
        Int16 result;
        if (Int16.TryParse(Console.ReadLine(), out result))
        {
            return result;
        }
        Console.WriteLine("Sorry, invalid number entered. Try again.");
    }
}
Jon Skeet
Not exactly a "clever idea" but the correct answer.
Ed Marty
A: 

But I am asking how to make a solution where the person gets asked the question again and again, until s/he enters something valid.

The 2 above solutions but doesn't seem like the most effective way to do it

CasperT
Jon Skeet's answer does keep prompting (while true)
GWLlosa
+3  A: 

You can use the TryParse pattern:

string s; // for "is not valid" message
short val; // final value
while(!short.TryParse(s=Console.ReadLine(), out val)) {
    Console.WriteLine(s + " is not valid...");
}
Marc Gravell
That will always write "0 is not valid" in the case of invalid input ;)(You need a temporary string variable, as far as I can see.)
Jon Skeet
A: 

I see now. Thanks guys!

CasperT
+1  A: 

Just for some variety, how about testing the string itself, instead of TryParse, which would require extra storage, and potentially an unneeded cast?

static void Main(string[] args)
{
    var isFalse = "t".IsInt();
    var isTrue = "123".IsInt();
    var isAlsoFalse = "123.1".IsInt();

}

static bool IsInt(this IEnumerable<char> s)
{
    return s.All(x => char.IsNumber(x));
}
Mark
Granted, this doesn't test the length of the string, but you could easily add a count to it. After a quick test, it is marginally faster (5%) than TryParse.
Mark