Boo
Boo

Reputation: 343

Validating multiple user input in console application

I'm pretty new to C# and am wondering how I'd go about validating user input to meet the following requirements:

What's the most efficient way of doing this considering i will have multiple user input to validate in the same sort of way.

decimal balance;
Console.Write("Starting Balance: $");
while (!decimal.TryParse(Console.ReadLine(), out balance))
{
    Console.Write("Please enter a valid decimal value: $");
}

EDITED BELOW

How about this?

decimal balance;
Console.Write("Starting Balance: $");
while(true)
{
    if (!decimal.TryParse(Console.ReadLine(), out balance))                
        Console.Write("Please enter a valid decimal value: $");
    else if (balance < 1 || balance > 100)
        Console.Write("Please enter an amount between 1 and 100: ");
    else
        break;                
}
Console.WriteLine("Balance entered is: " + balance.ToString("n"));

return val; line gave me an error so i left it out but the above seems to work?

Upvotes: 0

Views: 4588

Answers (2)

Jcl
Jcl

Reputation: 28272

I'd try something like:

decimal GetUserInput(string inputQuery, decimal min, decimal max)
{
  Console.Write(inputQuery);
  decimal val;
  while(true)
  {
    if(!decimal.TryParse(Console.ReadLine(), out val))
      Console.Write("Please enter a valid decimal value: $");
    else if(val < min || val > max)
      Console.Write("Please enter an amount between " + min + " and " + max + ": $");
    else // the value is a decimal AND it's correct
      break;
  } 
  return val;
}

Then use it like:

var startingBalance = GetUserInput("Starting Balance: $", 1, 100000);
var endingBalance = GetUserInput("Ending Balance: $", 1, 100000);
//...

If your min and max are fixed, then you could not pass them as arguments and use a fixed check. And you could also avoid having the query : $ passed in if needed, but I'll leave that to you

Update

The reason why the return val line was giving you an error was because you were inlining it (probably in a void returning function). What I was doing was making a function since you specified it needed to be reusable.

So in your program, you need to make a separate function... your program would look something like this:

class Program
{
    // We're declaring this function static so you can use it without an instance of the class
    // This is a function, so it can be called multiple times, with different arguments
    static decimal GetUserInput(string inputQuery, decimal min, decimal max)
    {
      // Write the argument "inputQuery" to console
      Console.Write(inputQuery);
      decimal val;

      // Loop indefinitely
      while(true)
      {
        // Read from console into a decimal "val"
        if(!decimal.TryParse(Console.ReadLine(), out val))
          // It was not a correct decimal, so write the prompt
          Console.Write("Please enter a valid decimal value: $");
        // It was a correct decimal
        else if(val < min || val > max)
          // But not in range, so write a different prompt
          Console.Write("Please enter an amount between " + min + " and " + max + ": $");
        // It was a decimal and within range
        else
          // so we break the infinite loop and exit after the "}"
          break;

        // If we have got to this point (we didn't hit the "break"),
        // it was either not a decimal or it wasn't within range, 
        // so it'll loop again and ask for a value from console again.
        // The prompt was already written above (in the "ifs")

      } 
      // We got out of the while(true){} loop, so it means we hit "break"
      // above, and that means "val" contains a correct value (decimal and
      // within range), so we return it to the caller
      return val;
    }

    static void Main()
    {
      // Your original code went here, but see how my function is *outside* function Main()

      // You use my function (GetUserInput) here:
      var startingBalance = GetUserInput("Starting Balance: $", 1, 100000);
      var endingBalance = GetUserInput("Ending Balance: $", 1, 100000);

      // Then with the returned values (stored in "startingBalance"
      // and "endBalance"), you can do what you want:
      Console.WriteLine("Starting balance was: " + startingBalance.ToString("n"));
    }
}

I've made a fiddle with the whole program so you can test online and make changes: https://dotnetfiddle.net/HiwwIP

Upvotes: 1

mcy
mcy

Reputation: 1268

If I were you, I would do such:

        bool isInvalid, isOutOfRange;
        decimal balance = 0;
        isOutOfRange = true;
        do
        {
            string input = Console.ReadLine();
            isInvalid = !Decimal.TryParse(input, out balance);
            if (!isInvalid)
            {
                // use balance<=1 if 1 should not be included
                // use balance>=1000000 if 1000000 should not be included
                isOutOfRange = (balance < 1 || balance > 1000000);
            }
            if (isInvalid)
            {
                Console.WriteLine("Please enter a valid decimal value: $");
            }
            else if (isOutOfRange)
            {
                Console.WriteLine("Please enter value between 1 and 1000000: $");
            }

        } while (isInvalid || isOutOfRange);
        Console.WriteLine("{0}, That is a valid value!", balance.ToString());
        Console.ReadKey();

Of course you can shortcut by eliminating bool definitions and directly calling functions instead; but I wrote in detail for clarity as you indicated that you are "pretty new".

Upvotes: 0

Related Questions