2

I'm trying to handle an exception to avoid my program crash if double.Parse(string) tries parsing invalid values (such as strings instead of numbers). Here's what I've got:

do
{
    //asking customer the amount of shirts he would like to buy any shirts they want.
    numbershirtString = Console.ReadLine(); // customer types in amount of shirts they want.
    numbershirts = double.Parse(numbershirtString);

    keepLooping = true;

    if (numbershirts < 10)
    {
        Console.WriteLine("You would be buying " + numbershirts + " shirts");
        keepLooping = false;
    }

    if (numbershirts > 10)
    {
        Console.WriteLine("You cannot order more than 10 shirts. Please try again.");
        keepLooping = true;
    }

} while (keepLooping);

I would appreciate your help. Thank you in advance!

Pac0
  • 21,465
  • 8
  • 65
  • 74

3 Answers3

1

Use double.TryParse() instead. It returns true of false depending on the outcome:

double val;
bool success = double.TryParse("red", out val);
if(success)
{
    // val contains a parsed value
}
else
{
    // could not parse
}
uncoder
  • 1,818
  • 1
  • 17
  • 20
0

Maybe this is a little advanced for you, but if you are feeling in a clever mood, you can define a class that handles the parsing of user input. That way you can keep that logic separated from your main program (see separation of concerns).

public class UserEntry
{
    private readonly string _originalValue;

    public UserEntry(string input)
    {
        _originalValue = input;
    }

    public bool IsInt
    {
        get
        {
            return int.TryParse(_originalValue, out var dummy);
        }           
    }

    public int ToInt()
    {
        return ToInt(default(int));
    }

    public int ToInt(int defaultValue)
    {
        int result;

        bool ok = int.TryParse(_originalValue, out result);
        return ok ? result : defaultValue;
    }

    public override string ToString()
    {
        return _originalValue;
    }

    static public implicit operator UserEntry(string input)
    {
        return new UserEntry(input);
    }

    static public implicit operator Int32(UserEntry input)
    {
        return input.ToInt();
    }
}

If we use implicit conversion operators it makes things very simple. For example, all of these are now legal:

UserEntry entry = Console.ReadLine();
if (!entry.IsInt) continue;
if (entry < 10) return entry;

If we apply this to your example, it shortens your code a bit, and arguably makes it a bit clearer as well.

public class Program
{
    private const int MaximumOrder = 10;

    public static void Main()
    {
        var n = AskForNumberOfShirts();
        Console.WriteLine("OK, I'll order {0} shirts.", n);
    }

    public static int AskForNumberOfShirts()
    {
        while (true)
        {
            Console.WriteLine("Enter the number of shirts to order:");
            UserEntry entry = Console.ReadLine();
            if (!entry.IsInt)
            {
                Console.WriteLine("You entered an invalid number.");
                continue;
            }
            if (entry > MaximumOrder)
            {
                Console.WriteLine("{0} is too many! Please enter {1} or fewer.", entry, MaximumOrder);
                continue;
            }
            return entry;
        }
    }
}

Notes:

  1. I doubt you can order half a shirt, so I am using an int instead of a double to store the number of shirts.
  2. I refactored the logic branches to use opportunistic return, a.ka. Guard Pattern. See this article for why I do this.
  3. I extracted the constant value 10 to its own symbol, MaximumOrder. This should get you a couple points on the assignment.

Output:

Enter the number of shirts to order:
22
22 is too many! Please enter 10 or fewer.
Enter the number of shirts to order:
sdlfkj
You entered an invalid number.
Enter the number of shirts to order:
9
OK, I'll order 9 shirts.

Working example on DotNetFiddle

John Wu
  • 50,556
  • 8
  • 44
  • 80
0

To handle an exception, in C# like similar in other languages, you can use the try..catch block. Look at the simplest syntax:

try
{
    //Try to run some code.
}
catch
{
    //Do something if anything excepted.
}

If you're interested to retrieve which exception breaked the code:

try
{
    //Try to run some code.
}
catch (Exception ex)
{
    //Do something ex was thrown.
}

If you change the type of ex to something inheriting the base class Exception you'll handle only all the exception of that type:

try
{
    //Try to run some code.
}
catch (StackOverflowException ex)
{
    //Do something ex was thrown because you overflowed the stack.
}

But instead of talking about try..catch block which you can find out more about on Google, I suggest you to use the method double.TryParse(string, out double). Its syntax is a little bit different than double.Parse, but effectively it does the same in a different way. It returns true if your input is valid, else it returns false, whereas in the first parameter you have just to pass your string input and in the second one is required an output reference to the result variable:

double x = 0;
string number = "125.3";
if (double.TryParse(number, out x))
    Console.WriteLine("Your number is " + x.ToString());
else
    Console.WriteLine("Your input isn't valid");
Davide Cannizzo
  • 2,826
  • 1
  • 29
  • 31