Sam Johnson
Sam Johnson

Reputation: 15

Method always returning 0

I'm trying to call a method (ChooseDecoration) using the (DisplayMessage) method and that will return a value of either 1,2 or something else but right now the method just returns 0 everytime as far as I can tell.

I have tried various ways like getting the decoration value inside the DisplayMessage method but the program specs require a separate method to find these.

namespace ConsoleApp6
{
public class ChristmasCard : ChristmasCardTesting
{
    static void Main()
    {
        ToAndFrom();
        double decorate = ChooseDecoration();

        DisplayMessage(decorate);
        Console.ReadLine();
    }

    public static void ToAndFrom()
    {
        Console.WriteLine("Please enter who you are sending the card to");
        string to = Console.ReadLine();
        Console.WriteLine("Please enter who it is from");
        string from = Console.ReadLine();

    }
    public static void SetBorderCharacter()
    {

    }
     static double ChooseDecoration()
    {
        Console.WriteLine("Please Choose decoration 1 or 2 ");
       double decoration = Convert.ToDouble(Console.Read());
        return decoration;

    }
    public static void DisplayMessage(double decoration)
    {

        if (decoration == 1)
        {
            ChristmasCardTesting.SantaA();
        }
        else if (decoration == 2)
        {

            ChristmasCardTesting.SantaB();
        }
       // else
        //    ChristmasCardTesting.SantaA();

    }
    public static void DoPromt()
    {

    }
    public static void AddMessage()
    {

    }
    public static void ClearMessage()
    {

    }




}

public class ChristmasCardTesting
{

    public static void SantaA()
    {
        Console.WriteLine(@" ||::|:|| .--------, ");
        Console.WriteLine(@" |:||:|:| |_______ / .-. ");
        Console.WriteLine(@" ||::|:|| .'` ___ `'. \|('v')|/ ");
        Console.WriteLine(@" \\\/\///: .'` `'. ;____`( )'____ ");
        Console.WriteLine(@" \====/ './ o o \|~ ^' '^ // ");
        Console.WriteLine(@" \\// | ())) . | Season's \ ");
        Console.WriteLine(@" || \ `.__.' /| // ");
        Console.WriteLine(@" || _{``-.___.-'\| Greetings \ ");
        Console.WriteLine(@" || _.' `-.____.- '`| ___ // ");
        Console.WriteLine(@" ||` __ \ |___/ \_______\ ");
        Console.WriteLine(@" .' || (__) \ \| / ");
        Console.WriteLine(@" / `\/ __ vvvvv'\___/ ");
        Console.WriteLine(@" | | (__) | ");
        Console.WriteLine(@" \___/\ / ");
        Console.WriteLine(@" || | .___. | ");
        Console.WriteLine(@" || | | | ");
        Console.WriteLine(@" ||.-' | '-. ");
        Console.WriteLine(@" || | ) ");
        Console.WriteLine(@" || ----------'---------' ");
        Console.ReadLine();


    }
    public static void SantaB()
    {
        Console.WriteLine(@" ");
        Console.WriteLine(@" .------, ");
        Console.WriteLine(@" .\/. |______| ");
        Console.WriteLine(@" _\_}{_/_ _|_Ll___|_ ");
        Console.WriteLine(@" / }{ \ [__________] .\/. ");
        Console.WriteLine(@" '/\' / \ _\_\/_/_ ");
        Console.WriteLine(@" () o o () / /\ \ ");
        Console.WriteLine(@" \ ~~~ . / '/\' ");
        Console.WriteLine(@" _\/ \ '...' / \/_ ");
        Console.WriteLine(@" \\ {`------'} // ");
        Console.WriteLine(@" \\ /`---/',`\\ // ");
        Console.WriteLine(@" \/' o | |\ \`// ");
        Console.WriteLine(@" /' | | \/ /\ ");
        Console.WriteLine(@" __,. -- ~~ ~| o `\| |~ ~~ -- . __ ");
        Console.WriteLine(@" | | ");
        Console.WriteLine(@" \ o / ");
        Console.WriteLine(@" `._ _.' ");
        Console.WriteLine(@" ^~- . - ~^ ");
        Console.WriteLine(@" ");
        Console.ReadLine();
    }


}
}

Upvotes: 0

Views: 108

Answers (2)

Rufus L
Rufus L

Reputation: 37060

You should use caution when using the Console.Read method, since it only reads the next key from the standard input stream, but blocks until the user presses Enter. Any additional characters after the first one are then returned by subsequent calls to Console.Read.

Take a look at the following example:

Console.WriteLine("Enter 1 or 2: ");
int i = Console.Read(); // Here the user types: 12[Enter]
// The value of 'i' is now 49 (the ASCII value of 1)

// Later we do this:
Console.WriteLine("Enter 3 or 4:");
int j = Console.Read();
// The value of 'j' is now 50 (the ASCII value of 2), and the code keeps running!
// There is no pause to wait for user input, since there was already some in the cache

What you should do instead

There are two more common ways to get input from the user: Console.ReadLine(), which returns the entire string the user entered (after they press 'Enter'), or Console.ReadKey(), which returns a ConsoleKeyInfo representation of the key they pressed.

You can use ReadLine with your code exactly the way it is, and that might be best:

double decoration = Convert.ToDouble(Console.ReadLine());

But, if you don't want them to have to press 'Enter', you can do the following, which gets the string representation of the next character the user types by calling ToString() on the KeyChar property of the ConsoleKeyInfo object:

double decoration = Convert.ToDouble(Console.ReadKey().KeyChar.ToString());

Add some validation

But what happens if the user enters a string that can't be converted to a double? In that case, Convert.ToDouble will throw an exception. To avoid this, we can use double.TryParse, which returns true if the conversion is successful and sets an out parameter to the converted value. Now we can do something like this, to check if the input is valid:

double decoration;

if (!double.TryParse(Console.ReadLine(), out decoration))
{
    Console.WriteLine("The value you entered is not a valid double.");
}

But we now have to ask them to input it again, right? And if it fails again... well, we need a loop for this:

double decoration;

while (!double.TryParse(Console.ReadLine(), out decoration))
{
    Console.WriteLine("The value you entered is not a valid double.");
    Console.Write("Please Choose decoration 1 or 2: ");
}

Now it will continue looping until the user enters a valid double.


Make the code reusable

Ok, great, now we have a way to validate the input, but do we really want to write that loop code every time we need to get a double from the user? A better idea might be to create a method that does it for us, which takes in a string prompt to display to the user, and returns the correct type. We can even add some "bounds" arguments, to enforce the number is between a min and max value:

/// <summary>
/// Gets a strongly typed (double) value from the Console
/// </summary>
/// <param name="prompt">The initial message to display to the user</param>
/// <returns>User input converted to a double</returns>
public static double GetDoubleFromUser(string prompt = "Enter a number: ", 
    double minValue = double.MinValue, double maxValue = double.MaxValue)
{
    double value;

    // Write the prompt text and get input from user
    Console.Write(prompt);

    while (!double.TryParse(Console.ReadLine(), out value)
           || value < minValue || value > maxValue)
    {
        // If input can't be converted to a double, keep trying
        Console.WriteLine("ERROR: Invalid value!");
        Console.Write(prompt);
    }

    // Return converted input value
    return value;
}

Now, with this code, all we need to do is:

double decoration = GetDoubleFromUser("Please Choose decoration 1 or 2: ", 1, 2);

Upvotes: 3

Marc Gravell
Marc Gravell

Reputation: 1063884

Console.Read returns an int, but that isn't the numeric key - it is that char value, or -1 for EOF. So: the problem isn't that it is returning zero. The problem is that it is returning the ASCII value of the key. You need to convert. For example:

int i = Console.Read();
if(i < 0) return 0;
char c = (char)i;
return (int)(c - '0');

Upvotes: 7

Related Questions