CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 19
  1. #1
    Join Date
    Oct 2011
    Posts
    12

    Please don't cringe

    Now, I know, you didn't think neanderthals still existed, but you may be persuaded otherwise after reading this. So, I need to create a program that will take a letter and give the corresponding number from a phone keypad. For example, I enter a b or c, and it gives me 2...and so on. I figured I could use a switch statement. However, I soon realized the whole (can't convert string to bool), so my question is...how do I take the string input and match it to each of the cases? You don;t have to tell me how to do it, just give a hint or two. As usual, you're all very helpful and I appreciate any response. (I realize there is probably a lot of other things wrong with the code, but I'll take it one step at a time).



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

    namespace ConsoleApplication1
    {
    class Program
    {
    static void Main(string[] args)
    {
    string option;


    while (option)
    {
    DisplayMenu();
    option = (Console.ReadLine());

    switch (option)
    {
    case "a,b,c":
    Console.WriteLine("2");
    break;

    case "d,e,f":
    Console.WriteLine("3");
    break;

    case "g,h,i":
    Console.WriteLine("4");
    break;

    case "j,k,l":
    Console.WriteLine("5");
    break;

    case "m,n,o":
    Console.WriteLine("6");
    break;

    case "p,q,r,s":
    Console.WriteLine("7");
    break;

    case "t,u,v":
    Console.WriteLine("8");
    break;
    case "w,x,y,z":
    Console.WriteLine("9");
    break;
    }
    }
    }



    static void DisplayMenu()
    {
    Console.WriteLine("Enter a letter:");

    }

    }
    }

  2. #2
    Join Date
    Dec 2011
    Posts
    61

    Re: Please don't cringe

    case "a":
    case "b":
    case "c":
    Console.WriteLine("1");
    break;

  3. #3
    Join Date
    Oct 2011
    Posts
    12

    Re: Please don't cringe

    Quote Originally Posted by Silent Sojourner View Post
    case "a":
    case "b":
    case "c":
    Console.WriteLine("1");
    break;
    Thank you! I've made those changes, now I just gotta figure out how to take the user input and match it to each case...

  4. #4
    Join Date
    Oct 2011
    Posts
    12

    Re: Please don't cringe

    Maybe I should convert the string to an int?

  5. #5
    Join Date
    Feb 2011
    Location
    United States
    Posts
    1,016

    Re: Please don't cringe

    My preference is to do data encoding in variables to separate data entry from logical execution.

    I'd use a Dictionary<string, int> to perform this conversion like this:

    Code:
    static Dictionary<string, int> numberMap;
    
    public static void Main(string[] args)
    {
        //EDIT: ----------->WARNING!!!!!<---------------
        //EDIT: THERE IS AN ERROR IN THIS SUBROUTINE; SEE MY LATER POST FOR CORRECTION
        for(int i = 0; i < numberMap; i++)
        {
            //Initialize the dictionary
            numberMap = new Dictionary<string, int>() { 
                { "a", 2 },
                { "a", 2 },
                { "c", 2 },
                { "d", 2 },
                { "e", 2 },
                { "f", 2 },
                //... and so sorth
                { "z", 9 } };
        }
    }
    
    public static mapToNumber(string letter)
    {
        return numberMap[letter];
    }
    This has the advantage of returning in O(1) time [instead of the potentially O(n) of the switch statement; although in some cases switch's may be optimized to O(1) by the compiler by generating a jump table [see link]].
    Last edited by BioPhysEngr; December 2nd, 2011 at 03:10 AM. Reason: write a note that there is an error in the subroutine
    Best Regards,

    BioPhysEngr
    http://blog.biophysengr.net
    --
    All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.

  6. #6
    Join Date
    Jun 2011
    Location
    .NET4.0 / VS 2010
    Posts
    70

    Re: Please don't cringe

    Hmmm like your code BioPhysEngr I always seem to learn something new from all your post

    I am curious on why you have a for loop when creating the dictionary?

    I also wanted to ask would my approach to the problem have been different in a bad way or just in a design way?

    Code:
                string userInput = "";
                string[] letterNumber = new string[]{" ", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
    
                Console.Write("Please enter a letter: ");
                userInput = Console.ReadLine();
    
                for (int i = 0; i < letterNumber.Length; i++)
                {
                    if (letterNumber[i].Contains(userInput))
                    {
                        Console.WriteLine(i);
                        break;
                    }
                }
    
                Console.Write("\nPress any key to continue...");
                Console.ReadKey();
    I'm gonna take a guess and say that code could probably lag behind in a larger scale operation vs the dictionary? I am gonna do some research on the dictionary as in my previous self taught attempts I never really looked at it but it does seem like a helpful function.

  7. #7
    Join Date
    Feb 2011
    Location
    United States
    Posts
    1,016

    Re: Please don't cringe

    Quote Originally Posted by Ubiquitous View Post
    I am curious on why you have a for loop when creating the dictionary?
    D'oh! There's no reason at all; I must have gotten distracted when I was replying. Actually, the loop doesn't even make syntactical sense (i < numberMap makes no sense). Good catch! (EDIT: Actually there were a few more minor syntax errors in the Main method...! >__< Fixed now.)

    The method should read:
    Code:
    public static void Main(string[] args)
    {
            //Initialize the dictionary
            numberMap = new Dictionary<string, int>() { 
                { "a", 2 },
                { "b", 2 },
                { "c", 2 },
                { "d", 3 },
                { "e", 3 },
                { "f", 3 },
                //... and so forth
                { "z", 9 } };
    }
    The primary advantage of Dictionary<,> (MSDN link) is that it allows for O(1) average time for search, insertion and deletion (constant time no matter how many elements are in the dictionary). Dictionary<,> is actually just the C# generics way of defining a hash table (link on Wikipedia), which might be a more familiar concept.

    I think I would prefer the switch method or the Dictionary<,> method to your solution (though there is nothing incorrect about your solution). Using both switch or Dictionary<,>, it will probably require O(1) time to run the method [as I mentioned, switch can be optimized to O(1) automatically by the compiler in some cases]). The solution you propose requires scanning through the array until you find the match, which requires O(n) time where n is the number of element in the array. For small values of n, your way might be faster for some overhead reasons, but for large values of n the Dictionary method will almost certainly yield superior performance.
    Last edited by BioPhysEngr; December 2nd, 2011 at 03:12 AM.
    Best Regards,

    BioPhysEngr
    http://blog.biophysengr.net
    --
    All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.

  8. #8
    Join Date
    Feb 2011
    Location
    United States
    Posts
    1,016

    Re: Please don't cringe

    Quote Originally Posted by JohnYossarian View Post
    I've made those changes, now I just gotta figure out how to take the user input and match it to each case...
    Sorry, I missed this originally. To query the user for input on the console, check for valid input and convert the letter to a number do:

    Code:
    public static int requestInputAndConvertToNumber()
    {
    
        string input = null;
        while(true)
        {
            //Prompt user
            Console.Write("Enter  number: ");
        
            //Get input from the user
            input = Console.ReadLine();  //Also ReadKey might be useful
        
            //Check to see if this input is in the dictionary; if so store the numerical value
            // in result
            int result = 0;
            bool inDictionary = numberMap.TryGetValue(input, out result);
            if( !inDictionary )
            {
                //Complain
                Console.WriteLine("Hey!  That number wasn't valid!");
                continue;  //Restart the loop to try again
            }
        
            //Otherwise return the result (the corresponding integer)
            return result;
        }
    }
    Hopefully no bugs this time. :-)

    Does that make sense? If not, push back!
    Best Regards,

    BioPhysEngr
    http://blog.biophysengr.net
    --
    All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.

  9. #9
    Join Date
    Feb 2008
    Posts
    108

    Re: Please don't cringe

    BPE, I share your aversion to goto, but I have a similar aversion to 'continue'. I have never used it, since it is easily avoided.
    Assuming your code is correct (I haven't tested it), I have rewritten the function to avoid the 'continue'.
    Code:
    public static int requestInputAndConvertToNumber()
    {
    
        string input = null;
        int result = 0;
        bool LoopFinished = false;
    
        while(!LoopFinished)
        {
            //Prompt user
            Console.Write("Enter  number: ");
        
            //Get input from the user
            input = Console.ReadLine();  //Also ReadKey might be useful
        
            //Check to see if this input is in the dictionary; if so store the numerical value
            // in result
            bool inDictionary = numberMap.TryGetValue(input, out result);
            if( !inDictionary )
            {
                //Complain
                Console.WriteLine("Hey!  That number wasn't valid!");
            }
        
            else
    	{
    	   LoopFinished = true;	   
    	} 
           //Otherwise return the result (the corresponding integer)
     
        }
           return result;
    }
    Developing using:
    .NET3.5 / VS 2010

  10. #10
    Join Date
    Feb 2011
    Location
    United States
    Posts
    1,016

    Re: Please don't cringe

    BPE, I share your aversion to goto, but I have a similar aversion to 'continue', since it is easily avoided.
    I think, perhaps, that you ought re-consider your aversion. The objection to goto isn't that it's unnecessary (though it is), but rather that it leads to unmaintainable code. When a programmer uses goto, understanding what happens next in the program requires the programmer already know (or look up) where the label is. Humans are bad at that. Therefore, use of goto leads to the production of hard-to-read and hard-to-maintain code.

    By contrast, the flow control statements break and continue have fixed interpretations. They always means "stop processing this loop" and "stop processing, for this iteration". They simply mark the end of an iteration (or a loop). For this reason, they are primary tools used in structured programming.

    While you are correct that you can avoid it by using if { ... } else { ... }, I would argue that my construct is more readable because the if { ... } else { ... } clause if unnecessarily verbose. When you should use if { ... } else { ... } is when you are processing some data and need to differentially process based on some condition and then keep processing it.
    Best Regards,

    BioPhysEngr
    http://blog.biophysengr.net
    --
    All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.

  11. #11
    Join Date
    Feb 2008
    Posts
    108

    Re: Please don't cringe

    BPE, I have programmed using coding standards that strictly forbade the use of goto, continue and multiple returns from a function. I didn't write the standards, but I agreed with them and followed them. I remember going to a convention where a debugger company was demonstrating their debugger they had for sale. Which example did they use to demonstrate the debugger? -A block of code that contained a 'continue' statement. I thought to myself, if they had just not used the 'continue' statement, they wouldn't have had to use a debugger. Also, a lot of coders today violate the prohibition of multiple returns from functions. This practice makes code more difficult to maintain. The rules were made for a reason - to prevent people from writing code that is difficult to maintain.
    Developing using:
    .NET3.5 / VS 2010

  12. #12
    Join Date
    Feb 2011
    Location
    United States
    Posts
    1,016

    Re: Please don't cringe

    I guess I am merely at variance with those who forbid continue and multiple returns then. The rationale is not clearly laid out beyond appeal to authority. The interpretation of continue and return -- "no further need to process this; move on" -- have fixed interpretations (unlike goto) that can simply code and make functions more communicative. I don't see any reason to recommend against their use.

    As a specific example, however, how would you code a recursive factorial function:

    Code:
    public static int factorial(int n)
    {
        //Base case
        if( n < 1 )
            return 1;
    
        return n*factorial(n-1);
    }
    It's not clear to me that saving the return value to a result variable using if { ... } else { ... } and then returning result would do anything other than add verbosity.

    Or how about a parsing example wherein you want to ignore blank lines:

    Code:
    StreamReader r = new StreamReader(path);
    while( !r.EndOfStream) 
    {
        string line = r.ReadLine();
        
        //Skip empty lines
        if( string.IsNullOrWhitespace(line) )
            continue;
    
        //...Downstream processing here...
    }
    You'd actually wrap the entire interior loop indented under else? To my mind, the ugliness and verbosity caused by not using continue appropriately is a heavy cost to readability.

    Also: Do others have any useful comments? If my viewpoint is a minority one, I would be glad to hear the rationale for why it is flawed.
    Last edited by BioPhysEngr; December 2nd, 2011 at 11:33 PM.
    Best Regards,

    BioPhysEngr
    http://blog.biophysengr.net
    --
    All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.

  13. #13
    Join Date
    Feb 2008
    Posts
    108

    Re: Please don't cringe

    No, you are not in the minority. If you make it a popularity contest, of course you will win.
    People like to take the easy way out and don't care about who has to maintain their code later.
    If you had to maintain code other people had hacked together, you would wish they had followed a coding standard.
    Developing using:
    .NET3.5 / VS 2010

  14. #14
    Join Date
    Oct 2003
    Location
    .NET2.0 / VS2005 Developer
    Posts
    7,104

    Re: Please don't cringe

    Coders should be flexible enough to code to whatever standards are required of them: do as youre told, earn your money, with it do as you want

    Here are no wrongs and rights with goto/continue/break/return - just use them as and when and as not asked. Oh and stop arguing about it; there are better things to do with your life
    "it's a fax from your dog, Mr Dansworth. It looks like your cat" - Gary Larson...DW1: Data Walkthroughs 1.1...DW2: Data Walkthroughs 2.0...DDS: The DataSet Designer Surface...ANO: ADO.NET2 Orientation...DAN: Deeper ADO.NET...DNU...PQ

  15. #15
    Join Date
    Oct 2011
    Posts
    12

    Re: Please don't cringe

    Quote Originally Posted by BioPhysEngr View Post
    Sorry, I missed this originally. To query the user for input on the console, check for valid input and convert the letter to a number do:

    Code:
    public static int requestInputAndConvertToNumber()
    {
    
        string input = null;
        while(true)
        {
            //Prompt user
            Console.Write("Enter  number: ");
        
            //Get input from the user
            input = Console.ReadLine();  //Also ReadKey might be useful
        
            //Check to see if this input is in the dictionary; if so store the numerical value
            // in result
            int result = 0;
            bool inDictionary = numberMap.TryGetValue(input, out result);
            if( !inDictionary )
            {
                //Complain
                Console.WriteLine("Hey!  That number wasn't valid!");
                continue;  //Restart the loop to try again
            }
        
            //Otherwise return the result (the corresponding integer)
            return result;
        }
    }
    Hopefully no bugs this time. :-)

    Does that make sense? If not, push back!
    The posts so far have been invaluable, thank you. I am still very much a beginner and have turned to this forum among other places to learn. Thus, some of the terms/concepts I am still trying to grasp. I have tried to interpret what you've posted and came up with this:

    Code:
    namespace keyPad
    {
        class Program
        {
    
            public static void Main(string[] args)
            {
                //Initialize the dictionary
                numberMap = new Dictionary<string, int>()
            { 
                { "a", 2 },
                { "b", 2 },
                { "c", 2 },
                { "d", 3 },
                { "e", 3 },
                { "f", 3 },
                { "g", 4 },
                { "h", 4 },
                { "i", 4 },
                { "j", 5 },
                { "k", 5 },
                { "l", 5 },
                { "m", 6 },
                { "n", 6 },
                { "o", 6 },
                { "p", 7 },
                { "q", 7 },
                { "r", 7 },
                { "s", 7 },
                { "t", 8 },
                { "u", 8 },
                { "v", 8 },
                { "w", 2 },
                { "x", 2 },
                { "y", 2 },
                { "z", 9 }};
    
            }
    
            public static int requestInputAndConvertToNumber()
            {
    
                string input = null;
                while (true)
                {
                    //Prompt user
                    Console.Write("Enter  number: ");
    
                    //Get input from the user
                    input = Console.ReadLine();  //Also ReadKey might be useful
    
                    //Check to see if this input is in the dictionary; if so store the numerical value
                    // in result
                    int result = 0;
                    bool inDictionary = numberMap.TryGetValue(input, out result);
                    if (!inDictionary)
                    {
                        //Complain
                        Console.WriteLine("Hey!  That number wasn't valid!");
                        continue;  //Restart the loop to try again
                    }
    
                    //Otherwise return the result (the corresponding integer)
                    return result;
                }
            }
            
    
    
    
            }
        }
    Is this interpretation correct? Don't cringe when I ask this: numberMap is listed as not existing in this context? I know it's something blatant that should be obvious.

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured