Reputation: 15
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
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
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