Antony Mouse
Antony Mouse

Reputation: 31

How could I convert a string variable to a double in C#

I am trying to convert a string variable to a double.

So far I have tried Convert.ToDouble()

string userAge;

Console.WriteLine("What is your age?");
Console.ReadLine();

Convert.ToDouble(userAge);

and when I tried to do operations on userAge it shows this error:

Program.cs(23,27): error CS0019: Operator '/' cannot be applied to operands of type 'string' and 'double' [/home/ccuser/workspace/csharp-working-with-numbers-arithmetic-operators-csharp/e3-workspace.csproj]
Program.cs(29,28): error CS0029: Cannot implicitly convert type 'string' to 'double' [/home/ccuser/workspace/csharp-working-with-numbers-arithmetic-operators-csharp/e3-workspace.csproj]
Program.cs(17,24): error CS0165: Use of unassigned local variable 'userAge' [/home/ccuser/workspace/csharp-working-with-numbers-arithmetic-operators-csharp/e3-workspace.csproj]

The build failed. Fix the build errors and run again.

Any suggestions?

Upvotes: 2

Views: 3119

Answers (2)

Rufus L
Rufus L

Reputation: 37020

To begin with, you need to assign the result of those method calls (to get the user input and then convert the string to a doulbe) to some variables so you can use them later in the code:

Console.WriteLine("What is your age?");
string input = Console.ReadLine();
double age = Convert.ToDouble(input);

But now we see there is a problem - if the user enters a non-numeric input, we'll get a FormatException.

Luckily there's a better method we can use for parsing strings to doubles: double.TryParse. This method takes in a string (the input), and an out parameter that it will set to the converted value on success (or the default value of 0 on failure). And the best thing is that it returns a bool that indicates if it was successful or not, so we can use it as a condition for a loop:

Console.Write("What is your age? ");
string userAge = Console.ReadLine();
double age;

while (!double.TryParse(userAge, out age))
{
    Console.ForegroundColor = ConsoleColor.Red;
    Console.WriteLine("Invalid input, please try again.");
    Console.ResetColor();
    Console.Write("What is your age? ");
    userAge = Console.ReadLine();
}

// Now 'age' is the converted value entered by the user

Now we have a solution that will loop until the user enters a valid number. But that's a fair amount of code. What if we have to get another number from them? Probably it would be better to extract this into a method that takes in a string (to use as a prompt) and which returns the strongly-typed double result:

public static double GetDoubleFromUser(string prompt)
{
    bool isValid = true;
    double result;

    do
    {
        if (!isValid)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("Invalid input, please try again.");
            Console.ResetColor();
        }
        else isValid = false;

        Console.Write(prompt);
    } while (!double.TryParse(Console.ReadLine(), out result));

    return result;
}

Now our main code is much more simple:

double userAge = GetDoubleFromUser("What is your age? ");
double userWeight = GetDoubleFromUser("What is your weight? ");

Now, if we want to get a little fancier, we can include an optional 'validator' argument, which is a function that takes in a double and returns a bool, which we can use to further validate the result and force the user to enter a valid number.

For example, what if we want them to choose a number from 1 to 10? We don't want to have to setup a loop again for this further validation, so let's pass a Func<double, bool> to the method so it can do the validation for us!

For example:

public static double GetDoubleFromUser(string prompt, Func<double, bool> validator = null)
{
    bool isValid = true;
    double result;

    do
    {
        if (!isValid)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("Invalid input, please try again.");
            Console.ResetColor();
        }
        else isValid = false;

        Console.Write(prompt);
    } while (!double.TryParse(Console.ReadLine(), out result) &&
             (validator == null || !validator.Invoke(result)));

    return result;
}

Now we can pass in whatever validation we want to do on the input to the method! This would look something like the line of code below, and the method will not return until the user enters a valid number that's greater than or equal to 1 and less than or equal to 10:

double number = GetDoubleFromUser("Choose a number from 1 to 10: ", 
    x => x >= 1 && x <= 10);

Upvotes: 2

ADyson
ADyson

Reputation: 61784

You aren't assigning the result of your Convert call to a variable, you're just throwing it away. Convert doesn't alter the type of the existing variable (because, apart from other considerations, you simply can't do that in a strongly-typed language), instead it produces a new variable for you to use in your maths.

The error is, I presume without seeing the relevant code, because you tried to use userAge in your calculations which, as I've just explained, is still a string.

Also, to go back a step, you've never actually assigned the result of the ReadLine operation to the userAge variable in the first place.

This:

Console.WriteLine("What is your age?");
string userAge = Console.ReadLine();
double age = Convert.ToDouble(userAge);

would make more sense. And then use age in your calculations afterwards.

Upvotes: 0

Related Questions