c# Alpha Telephone Number Translator

旧时模样 提交于 2019-12-31 05:47:09

问题


I have a homework assignment where the program will accept any phone number in the format similar to 555-GET-FOOD. The task is to map the alphabetic letters to numbers and translate the number to its numeric equivalent.
For example: A, B, C = 2; D, E, F = 3; etc...

We have not covered Classes or creating maps at this point so these would not be viable solutions. This chapter does cover the enum so I am working to solve using an Enumerated type. I have a method set up to validate the data (ensure the correct # of characters and the hyphens are in the correct place) and this does work correctly. I have another method set up to remove the hyphens and also uses the ToUpper() method and this also works correctly, so the foreach loop I have set up us using the number after these two methods have already finished.

I have also set up a method to run after the conversion takes place to add the hyphens back in and this also works.

I have tried several ways to get is to work and have left them in commented out on the chance they might be what I need to use, for my attempt with the switch statement I only set up with the letter A for now, and plan to finish the remaining letters if I am able to get this to work. I think the one my issues is the foreach loop is using a char type and the switch is using an int. Seems to be the same issue when trying the code inside the foreach loop but I am not sure how to fix so any suggestions are appreciated.

public enum AlphaNumber
{ 
    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=8, T=8, U=8, V=9, W=9, X=9, Y=9, Z=9
}
 private void UpdatePhone(AlphaNumber phone)
    {
        switch (phone)
        {
            case AlphaNumber.A:
           //return AlphaNumber.(int[])Enum.GetValues(typeof(AlphaNumber));
           //return (Enum.GetValues(typeof(AlphaNumber)));
           //   (int)ValueType;
                Enum.GetValues(typeof(AlphaNumber));
                break;                   
        }
private void translateButton_Click(object sender, EventArgs e)
    {
        numberLabel.Text = "";//Clear the numberLabel
        //Get a trimmed copy of the user's input.  
        string input = numberTextBox.Text.Trim();

        if (IsValidFormat(input))
        {
            Unformat(ref input);

            foreach (char ch in input)
            {
                if (char.IsLetter(ch))//                    {
                    ch = (char)Enums.AlphaNumber.Active;
                    //ch = (char)Enum.GetValues(typeof(AlphaNumber));
                    //ch = Enum.TryParse(AlphaNumber);
                   // ch = AlphaNumber.(int[])Enum.GetValues(typeof(AlphaNumber));
                    //UpdatePhone(ch);
                   MessageBox.Show("Character is char");                    }
            }

            TelephoneFormat(ref input);    
            numberLabel.Text = input;

I am open to any suggestions and appreciate any help provided. Where I need help is inside the foreach loop, I am looking at each value and if it is a letter I want to get the value from the enum values and replace the char with the number value.


回答1:


Drop the enum and the switch, and instead do a lookup against a map. I have created a .NET Fiddle that demonstrates this working as desired here.

But if using a Dictionary<char, char> is for some odd reason out of question, then I suppose you could use this version -- in which I use the enum. It is just a lot more work and the more moving parts you have the harder it is to maintain.

In C# the type enum inherits from int by default, but you can specify various other numeric types -- like byte or long, etc... One of the key takeaways is the concept of boxing/unboxing and casting/converting from one type to another. If you have an enum defined as enum Foo { Bar = 63 } and you try to cast it to a char what would you expect to get?

This actually would result in the char ? -- take a look at the ASCII table and the find the DEC for 63 and look at what it maps to for the Char column.

The issue is fixed with this crazy complicated mess:

    public enum AlphaNumber
    { 
        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=8, T=8, U=8, V=9, W=9, X=9, Y=9, Z=9
    }

    public static class PhoneNumber
    {
        public static char ParseInput(char input)
        {
            if (input == '-' || char.IsDigit(input))
            {
                return input;
            }

            if (char.IsLetter(input))
            {
                var num = (AlphaNumber)(Enum.Parse(typeof(AlphaNumber), (char.IsLower(input) ? char.ToUpperInvariant(input) : input).ToString()));
                return ((int)num).ToString()[0];
            }

            return '\0';
        }
    }



回答2:


While "map" (implemented as Dictionary in C#/.Net) is probably best choice for this problem, basic math is enough for such simple transformation:

 Console.WriteLine(String.Join("",  // combine characters back to string
       "555-GET-FOOD" //value
          .ToUpperInvariant() // carefully converting to avoid Turkish I problems
          .Select(c=> (c>='A' && c<='Z') ? // only tweak A-Z range
             Math.Min((c-'A')/3+2,9).ToString()[0] : c)))



回答3:


It looks like you did attempt to use TryParse:

//ch = Enum.TryParse(AlphaNumber);

That is the method that you probably want to use. But there are a number of problems with it in that form, which probably gave you errors as you mentioned.

The parameters this method expects are a string (which matches the enumerated constant, or name from the enum) and an out parameter of the type of the enum you want to parse. The method return a bool.

If the TryParse is successful then the method returns TRUE with the corresponding value from the enum set in the out parameter.

This code should allow you to get the result you want as an int using your variable ch as a string for the input to parse:

AlphaNumber parsedCh;
int? chValue = null;

if (Enum.TryParse(ch.ToString().ToUpper(), out parsedCh)) 
{
    chValue = (int)parsedCh;
    Console.WriteLine(chValue); 
}



回答4:


using System;

public class Program
{
    public static void Main()
    {
        Console.WriteLine(AlphaPhoneToNumber("555-GET-FOOD"));
    }

    public static string AlphaPhoneToNumber(string val){
        //strings are immutable so let's get the array version of the value
        var phoneNumberArr = val.ToCharArray();
        for(int i = 0; i < val.Length; i++){
            phoneNumberArr[i] = AlphaPhoneCharToNumber(phoneNumberArr[i]);
        }
        return new string(phoneNumberArr);
    }

    public static char AlphaPhoneCharToNumber(char val){
        switch(val){
            case 'A':
            case 'B':
            case 'C':
                return '2';
            case 'D':
            case 'E':
            case 'F':
                return '3';
            case 'G':
            case 'H':
            case 'I':
                return '4';
            case 'J':
            case 'K':
            case 'L':
                return '5';
            case 'M':
            case 'N':
            case 'O':
                return '6';
            case 'P':
            case 'Q':
            case 'R':
                return '7';
            case 'S':
            case 'T':
            case 'U':
                return '8';
            case 'V':
            case 'W':
            case 'X':
            case 'Y':
            case 'Z':
                return '9';
            default: return val;

        }
    }
}

and here's how to do it without switch:

public static char AlphaPhoneCharToNumber2(char val){
    // All three arrays are of exact same length
    var ualphas = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
    var lalphas = "abcdefghijklmnopqrstuvwxyz".ToCharArray();
    var numval =  "22233344455566677788899999".ToCharArray();
    // thus I will loop up to the max length of one of the arrays
    // remember they are all the same length
    for(int i = 0; i < ualphas.Length; i++){
        //I will check if the value is in one of the alphabet
        //arrays at the current index
        //if there is a match I will assign it the number value
        //at the same index
        // MATCH UPPER?         MATCH LOWER?              RETURN NUMBER
        if(ualphas[i] == val || lalphas[i] == val) return numval[i];
    }
    // ELSE RETURN THE ORIGINAL VALUE
    return val;
}



回答5:


Here are some options for simple logic to process phone numbers as described. Note that while a novel approach, using an Enum to map letters to integer values somewhat complicates the process more than it needed to be.

Even though other methods exist for specifically mapping alpha-numeric phone numbers (think Regex) if you do ever need to iterate or process using Enum Names and Values then I hope you find these algorithms useful.

A dictionary would have been far simpler as a mapping construct to process from.

Regex where the LetterNumber mapping is defined in the expression would have been superior again.

/// <summary>
/// Iterates through the characters in a phone number converting letters to digits.
/// </summary>
/// <remarks>Uses StringBuilder to build the output iteratively, this method does not attempt to validate the number passed in</remarks>
/// <see cref="LetterNumber"/>
/// <param name="str">Phone number to parse</param>
/// <returns>Phone number output where letters have been parsed into their digit values</returns>
private string ParsePhoneNumber_StringBuilder(string str)
{
    StringBuilder output = new StringBuilder();
    foreach (char ch in str.ToCharArray())
    {
        // Convert each letter to it's numeric value as defined in the LetterNumber enum
        // Dashes are not letters so they will get passed through
        if (char.IsLetter(ch))
        {
            if (Enum.IsDefined(typeof(LetterNumber), ch.ToString()))
            {
                LetterNumber letterNumber = (LetterNumber)Enum.Parse(typeof(LetterNumber), ch.ToString(), true);
                output.Append((int)letterNumber);
            }
        }
        else
            output.Append(ch);
    }
    return output.ToString();
}

/// <summary>
/// Uses Linq to parse the characters in a phone number converting letters to digits.
/// </summary>
/// <remarks>This method does not attempt to validate the number passed in</remarks>
/// <see cref="LetterNumber"/>
/// <param name="str">Phone number to parse</param>
/// <returns>Phone number output where letters have been parsed into their digit values</returns>
private string ParsePhoneNumber_Linq(string str)
{
    return String.Join("", str.Select(c => char.IsLetter(c) ? ((int)((LetterNumber)Enum.Parse(typeof(LetterNumber), c.ToString(), true))).ToString() : c.ToString()));
}

/// <summary>
/// Iterates through the LetterNumber values and replaces values found in the passed in phone number.
/// </summary>
/// <remarks>Iterates through Enum Names and applied String.Replace</remarks>
/// <see cref="LetterNumber"/>
/// <param name="str">Phone number to parse</param>
/// <returns>Phone number output where letters have been parsed into their digit values</returns>
private string ParsePhoneNumber_Replacement(string str)
{
    str = str.ToUpper(); // we will compare all letters in upper case
    foreach (string letter in Enum.GetNames(typeof(LetterNumber)))
        str = str.Replace(letter.ToUpper(), ((int)((LetterNumber)Enum.Parse(typeof(LetterNumber), letter))).ToString());
    return str;
}


来源:https://stackoverflow.com/questions/35931403/c-sharp-alpha-telephone-number-translator

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!