Float/Double type input validation in C#

2019-04-12 20:11发布

问题:

This is literally my first program I've ever written (started learning this past Monday); I am a total newbie.

My question is, how can I prevent exceptions from being thrown when a user enters an invalid character when the program prompts the user for fahreinheit or celsius entry (expecting a number)??? So for example, when a user enters "asfasd", the program throws an exception.

I did a lot of searching on the site before posting this, and I was successfully able to find other input validation questions, however, they were all concerning C and C++ and since I am such a newbie, I have a hard time with understanding those languages and how they relate to C#. Thank you. Please see code:

using System;


namespace Converter
{
class Program
{
    static void Main()
    {
        float? FahrenheitInput = null;
        double? CelsiusInput = null;
        float? KilogramInput = null;
        float? PoundsInput = null;
        int UserChoice = 0;
        do
        {

            Console.WriteLine("What would you like to convert? Enter the corresponding number.\n1. Fahrenheit to Celsius");
            Console.WriteLine("2. Celsius to Fahrenheit\n3. Pounds to Kilograms\n4. Kilograms to pounds\n5. Exit program");
            UserChoice = int.Parse(Console.ReadLine());
            switch (UserChoice)
            {
                case 1:
                    Console.WriteLine("Enter the temperature in Fahreinheit, number only:");
                    FahrenheitInput = float.Parse(Console.ReadLine());
                    Console.Clear();
                    Console.WriteLine(FahrenheitInput + " degrees fahrenheit in Celsius is " + Program.FahrenheitToCelsius(FahrenheitInput) + "\n\n");
                    break;
                case 2:
                    Console.WriteLine("Enter the temperature in Celsius, number only:");
                    CelsiusInput = double.Parse(Console.ReadLine());
                    Console.Clear();
                    Console.WriteLine(CelsiusInput + " degrees Celius in fahrenheit is " + Program.CelsiusToFahrenheit(CelsiusInput) + "\n\n");
                    break;
                case 5:
                    break;
                default:
                    Console.WriteLine("This is not a valid entry. Please enter 1, 2, 3, 4, or 5.");
                    break;

            }
        } while (UserChoice != 5);


    }
    public static float? FahrenheitToCelsius(float? INPUT)
    {
        return (INPUT - 32) * 5 / 9;
    }
    public static double? CelsiusToFahrenheit(double? INPUT)
    {
        return INPUT * 1.8 + 32;
    }
}

}

回答1:

You can either put it in Try-Catch block or use a while loop to validate the user input.

below is your code with a while loop which validates users input.

class Program
{
    static void Main(string[] args)
    {
        double FahrenheitInput = 0;
        double CelsiusInput = 0;
        double KilogramInput = 0;
        double PoundsInput = 0;
        int UserChoice = 0;
        do
        {

            Console.WriteLine("What would you like to convert? Enter the corresponding number.\n1. Fahrenheit to Celsius");
            Console.WriteLine("2. Celsius to Fahrenheit\n3. Pounds to Kilograms\n4. Kilograms to pounds\n5. Exit program");
            UserChoice = int.Parse(Console.ReadLine());
            switch (UserChoice)
            {
                case 1:
                    Console.WriteLine("Enter the temperature in Fahreinheit, number only:");
                    while (!double.TryParse(Console.ReadLine(), out FahrenheitInput))
                    {
                        Console.WriteLine("Invalid format, please input again!");
                    };
                    Console.Clear();
                    Console.WriteLine(FahrenheitInput + " degrees fahrenheit in Celsius is " + Program.FahrenheitToCelsius(FahrenheitInput) + "\n\n");
                    break;
                case 2:
                    Console.WriteLine("Enter the temperature in Celsius, number only:");
                    while (!double.TryParse(Console.ReadLine(), out CelsiusInput))
                    {
                        Console.WriteLine("Invalid format, please input again!");
                    };
                    Console.Clear();
                    Console.WriteLine(CelsiusInput + " degrees Celius in fahrenheit is " + Program.CelsiusToFahrenheit(CelsiusInput) + "\n\n");
                    break;
                case 5:
                    break;
                default:
                    Console.WriteLine("This is not a valid entry. Please enter 1, 2, 3, 4, or 5.");
                    break;

            }
        } while (UserChoice != 5);

    }
    public static double FahrenheitToCelsius(double INPUT)
    {
        return (INPUT - 32) * 5 / 9;
    }
    public static double CelsiusToFahrenheit(double INPUT)
    {
        return INPUT * 1.8 + 32;
    }
}


回答2:

TryParse is your good friend here. In most scenarios, you should favor using TryParse than Parse. In your example, you can do something like:

int validInt;
int.TryParse(Console.ReadLine(), out validInt);

float validFloat;
float.TryParse(Console.ReadLine(), out validFloat);

Parse vs. TryParse



回答3:

The easiest way, IMHO, to change the routine is to rewrite Parse into corresponding TryParse:

  // UserChoice = int.Parse(Console.ReadLine());
  UserChoice = int.TryParse(Console.ReadLine(), out UserChoice) ? UserChoice : -1;

...

A bit more complex (you have to convert float into float?)

  // FahrenheitInput = float.Parse(Console.ReadLine());
  float v;
  FahrenheitInput = float.TryParse(Console.ReadLine(), out v) ? (float?) v : null;

The same scheme for CelsiusInput

  // CelsiusInput = double.Parse(Console.ReadLine());
  double d;
  CelsiusInput = double.TryParse(Console.ReadLine(), out v) d (double?) d : null;

The underlying mechanic of the code is

  • We try to parse user input TryParse(Console.ReadLine()...
  • If parse succeeds (and thus TryParse returns true) we just return the out (parsed value).
  • If parse fails (and thus TryParse returns false) we return some special a value (-1 for UserChoice or null in case of FahrenheitInput or CelsiusInput)

P.S. in the first switch you have just case 1, case 2 and case 5; however, you've put "This is not a valid entry. Please enter 1, 2, 3, 4, or 5." in the error message. It seems, that you have to either implement case 3 and case 4 in the switch or edit the error message.



回答4:

Use int.TryParse instead of int.Parse and float.tryParse instead of float.Parse



回答5:

While all the answers provided seem to work, the question you asked was

how can I prevent exceptions from being thrown [..]

and I just want to point out that you do this by putting the part which throws the exception in an try-catch-block. What this does is it executes the code within try until an exception is beeing thrown and then passes this exceptions as a parameter to the catch-part where you can handle it:

EXAMPLE

do
{
    try
    {
         // the code you already have
    }
    catch (Exception ex)
    {
         Console.WriteLine("This is no valid input (" + ex.Message + ")! Try again...");
    }
} while (UserChoice != 5);

Of course preventing exceptions from beeing thrown at all in the first place is the better way (as all the other answers do suggest), but this approach works as well and ist more generic in case you run into a similar problem in the future. Using switch-case-statements for error-handling is quite common practice...