Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Console I/O For this lab, you will create a DLL in C# (NOT an executable program

ID: 3815422 • Letter: C

Question

Console I/O

For this lab, you will create a DLL in C# (NOT an executable program) for generating menus in console applications. Your DLL will have methods that prompt the user for a valid byte, short, int, float, double, decimal, or long AND will return the input as the proper data type (which means you need to parse the input). These numeric prompts should also allow you to dictate a range of acceptable values depending on your current needs (ex. Between 1 and 10, pick door 1 or 2 or 3, enter your year of birth, etc). Your DLL will also have methods that prompt for a string, a single char, or a bool (typically for Yes/No questions). All your methods should handle exceptions and bad input (such as alpha characters for numbers, numbers outside the bounds of the range, and empty responses for strings when input is required) by informing the user the input was bad and looping through the prompt until a valid input is given. Each menu function that is public will return the proper data type and ONLY valid values. You will be provided with a class containing a defined namespace, class name, and method stubs. You are NOT allowed to change the names or signatures of the namespace, class, or methods. Your job is to fill in the methods to meet the requirements described above. You are allowed to add any helper methods or additional functionality. However, only the functionality listed in this document will be tested and graded.

(5 points) PromptForBool prompts for a bool, allowing a message to be dictated by the calling program. This function then returns the bool.

(8 points) PromptForByte prompts for a byte, allowing a message and range to be dictated by the calling program. This function then returns the byte.

(8 points) PromptForChar prompts for a char, allowing a message and range to be dictated by the calling program. This function then returns the char.

(8 points) PromptForDecimal prompts for a decimal, allowing a message and range to be dictated by the calling program. This function then returns the decimal.

(8 points) PromptForDouble prompts for a double, allowing a message and range to be dictated by the calling program. This function then returns the double.

(8 points) PromptForFloat prompts for a float, allowing a message and range to be dictated by the calling program. This function then returns the float.

(5 points) PromptForInput prompts for a string, allowing a message to be dictated by the calling program. This function then returns the string.

(8 points) PromptForInt prompts for an int, allowing a message and range to be dictated by the calling program. This function then returns the int.

(8 points) PromptForLong prompts for a long, allowing a message and range to be dictated by the calling program. This function then returns the long.

(10 points) PromptForMenuSelection generates a menu from a collection of strings, allowing the calling program to optionally include a quit option. The normal options are numbered starting at 1, with 0 reserved for quit.

(8 points) PromptForShort prompts for a short, allowing a message and range to be dictated by the calling program. This function then returns the short.

(16 points) The DLL functions handle exceptions gracefully, validate input, and loop until a valid input is given.

Here are the methods:

using System;
using System.Collections.Generic;

namespace CSC160_ConsoleMenu
{
public static class CIO
{
public static int PromptForMenuSelection(IEnumerable<string> options, bool withQuit)
{
throw new NotImplementedException();
}

public static bool PromptForBool(string message, string trueString, string falseString)
{
throw new NotImplementedException();
}

public static byte PromptForByte(string message, byte min, byte max)
{
throw new NotImplementedException();
}

public static short PromptForShort(string message, short min, short max)
{
throw new NotImplementedException();
}

public static int PromptForInt(string message, int min, int max)
{
throw new NotImplementedException();
}

public static long PromptForLong(string message, long min, long max)
{
throw new NotImplementedException();
}

public static float PromptForFloat(string message, float min, float max)
{
throw new NotImplementedException();
}

public static double PromptForDouble(string message, double min, double max)
{
throw new NotImplementedException();
}

public static decimal PromptForDecimal(string message, decimal min, decimal max)
{
throw new NotImplementedException();
}

public static string PromptForInput(string message, bool allowEmpty)
{
throw new NotImplementedException();
}

public static char PromptForChar(string message, char min, char max)
{
throw new NotImplementedException();
}
}
}

Explanation / Answer

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSC160_ConsoleMenu
{

    public static class CIO
    {
        /// <summary>
        /// Will display the prompt at the Console and check for the correct input allowed by the parser function
        /// </summary>
        /// <typeparam name="T">The type to return</typeparam>
        /// <param name="prompt">The question to ask at the Console</param>
        /// <param name="min">The minimum accepted value (if any)</param>
        /// <param name="max">The maximum accepted value (if any)</param>
        /// <param name="parser">The function called to validate the input</param>
        /// <returns>The value entered at the Console</returns>
        private static T PromptForGeneric<T>(string prompt, T? min, T? max, Func<string, T> parser) where T : struct, IComparable<T>
        {
            if (prompt == null)
            {
                throw new ArgumentException("The prompt cannot be empty.");
            }
            if (min != null)
            {
                if (max != null)
                {
                    T minTemp = (T)min;
                    if (minTemp.CompareTo((T)max) > 0)
                    {
                        throw new ArgumentException("min must be less than max");
                    }
                    else
                    {
                        // we good
                    }
                }
            }
            else
            {
                if (max != null)
                {
                    throw new ArgumentException("cannot specify a max without a min.");
                }
            }

            Console.WriteLine(prompt);
            bool isValid = false;
            T result = default(T);

            while (!isValid)
            {
                string input = Console.ReadLine();

                try
                {
                    // Will throw an exception if the parse fails, then we only need to check the bounds
                    result = parser(input);
                    if (min != null && result.CompareTo((T)min) < 0)
                    {
                        Console.WriteLine("Value is too low. Try again.");
                    }
                    else if (max != null && result.CompareTo((T)max) > 0)
                    {
                        Console.WriteLine("Value is too high. Try again.");
                    }
                    else
                    {
                        isValid = true;
                    }
                }
                catch (Exception)
                {
                    Console.WriteLine("Value is not a valid type. Try again.");
                }
            }
            return result;
        }

        /// <summary>
        /// Prompts the User for a bool
        /// </summary>
        /// <param name="message">The question to ask at the Console</param>
        /// <returns>The value entered at the Console</returns>
        public static bool PromptForBool(string message)
        {
            return PromptForGeneric(message, null, null, Convert.ToBoolean);
        }
      
        /// <summary>
        /// Prompts the User for a bool
        /// </summary>
        /// <param name="message">The question to ask at the Console</param>
        /// <param name="trueString">The string that equates to True</param>
        /// <param name="falseString">The string that equates to False</param>
        /// <returns>The value entered at the Console</returns>
        public static bool PromptForBool(string message, string trueString, string falseString)
        {
            Console.WriteLine(message);
            bool isValid = false;
            bool result = default(bool);

            while (!isValid)
            {
                string input = Console.ReadLine();

                try
                {
                    if (input.Equals(trueString))
                    {
                        result = true;
                        isValid = true;
                    }
                    else if (input.Equals(falseString))
                    {
                        result = false;
                        isValid = true;
                    }
                    else
                    {
                        Console.WriteLine("Response is not valid. Try again.");
                    }
                }
                catch (Exception)
                {
                    Console.WriteLine("Response is not valid. Try again.");
                }
            }
            return result;
        }

        /// <summary>
        /// Prompts the User for a byte
        /// </summary>
        /// <param name="message">The question to ask at the Console</param>
        /// <param name="min">The minimum accepted value (if any)</param>
        /// <param name="max">The maximum accepted value (if any)</param>
        /// <returns></returns>
        public static byte PromptForByte(string message, byte min, byte max)
        {
            return PromptForGeneric(message, min, max, Convert.ToByte);
        }

        /// <summary>
        /// Prompts the User for a char
        /// </summary>
        /// <param name="message">The question to ask at the Console</param>
        /// <param name="min">The minimum accepted value (if any)</param>
        /// <param name="max">The maximum accepted value (if any)</param>
        /// <returns>The value entered at the Console</returns>
        public static char PromptForChar(string message, char min, char max)
        {
            return PromptForGeneric(message, min, max, Convert.ToChar);
        }

        /// <summary>
        /// Prompts the User for a decimal
        /// </summary>
        /// <param name="message">The question to ask at the Console</param>
        /// <param name="min">The minimum accepted value (if any)</param>
        /// <param name="max">The maximum accepted value (if any)</param>
        /// <returns>The value entered at the Console</returns>
        public static decimal PromptForDecimal(string message, decimal min, decimal max)
        {
            return PromptForGeneric(message, min, max, Convert.ToDecimal);
        }

        /// <summary>
        /// Prompts the User for a double
        /// </summary>
        /// <param name="message">The question to ask at the Console</param>
        /// <param name="min">The minimum accepted value (if any)</param>
        /// <param name="max">The maximum accepted value (if any)</param>
        /// <returns>The value entered at the Console</returns>
        public static double PromptForDouble(string message, double min, double max)
        {
            return PromptForGeneric(message, min, max, Convert.ToDouble);
        }

        /// <summary>
        /// Prompts the User for a float
        /// </summary>
        /// <param name="message">The question to ask at the Console</param>
        /// <param name="min">The minimum accepted value (if any)</param>
        /// <param name="max">The maximum accepted value (if any)</param>
        /// <returns>The value entered at the Console</returns>
        public static float PromptForFloat(string message, float min, float max)
        {
            return PromptForGeneric(message, min, max, Convert.ToSingle);
        }

        /// <summary>
        /// Prompts the User for a string
        /// </summary>
        /// <param name="message">The question to ask at the Console</param>
        /// <param name="allowEmpty">If any empty string is acceptable</param>
        /// <returns>The value entered at the Console</returns>
        public static string PromptForInput(string message, bool allowEmpty)
        {
            Console.WriteLine(message);
            bool isValid = false;
            string result = default(string);

            while (!isValid)
            {
                result = Console.ReadLine();

                if (string.IsNullOrWhiteSpace(result))
                {
                    if (allowEmpty)
                    {
                        isValid = true;
                    }
                    else
                    {
                        Console.WriteLine("Response cannot be empty. Try again.");
                        isValid = false;
                    }
                }
                else
                {
                    isValid = true;
                }
            }
            return result;
        }

        /// <summary>
        /// Prompts the User for a float
        /// </summary>
        /// <param name="message">The question to ask at the Console</param>
        /// <param name="min">The minimum accepted value (if any)</param>
        /// <param name="max">The maximum accepted value (if any)</param>
        /// <returns>The value entered at the Console</returns>
        public static int PromptForInt(string message, int min, int max)
        {
            return PromptForGeneric(message, min, max, Convert.ToInt32);
        }

        /// <summary>
        /// Prompts the User for a long
        /// </summary>
        /// <param name="message">The question to ask at the Console</param>
        /// <param name="min">The minimum accepted value (if any)</param>
        /// <param name="max">The maximum accepted value (if any)</param>
        /// <returns>The value entered at the Console</returns>
        public static long PromptForLong(string message, long min, long max)
        {
            return PromptForGeneric(message, min, max, Convert.ToInt64);
        }

        /// <summary>
        /// Prompts the user to make a choice out of the specified options
        /// </summary>
        /// <param name="options">The set of strings that are options</param>
        /// <param name="withQuit">If option 0 should be set to Quit</param>
        /// <returns></returns>
        public static int PromptForMenuSelection(IEnumerable<string> options, bool withQuit)
        {
            int minMenuItem = (withQuit) ? 0 : 1;
            int maxMenuItem = options.Count();
            if (maxMenuItem == 0 /*|| minMenuItem > maxMenuItem */)
            {
                throw new ArgumentException("The list of options cannot be empty.");
            }

            if (withQuit)
            {
                Console.WriteLine("0: Quit");
            }
            for (int i = 0; i < maxMenuItem; i++)
            {
                Console.WriteLine((i + 1) + ": " + options.ElementAt(i));
            }
            int selection = PromptForInt("", minMenuItem, maxMenuItem);
            return selection;
        }

        /// <summary>
        /// Prompts the User for a short
        /// </summary>
        /// <param name="message">The question to ask at the Console</param>
        /// <param name="min">The minimum accepted value (if any)</param>
        /// <param name="max">The maximum accepted value (if any)</param>
        /// <returns>The value entered at the Console</returns>
        public static short PromptForShort(string message, short min, short max)
        {
            return PromptForGeneric(message, min, max, Convert.ToInt16);
        }
    }
}