Jak sformatować ciąg jako numer telefonu w C #

163

Mam ciąg "1112224444" to numer telefonu. Chcę sformatować jako 111-222-4444 przed zapisaniem go w pliku. Jest na kablu danych i wolałbym móc to zrobić bez przypisywania nowego zmienna.

Myślałem:

String.Format("{0:###-###-####}", i["MyPhone"].ToString() );

ale to chyba nie pomaga.

** AKTUALIZACJA **

Dobrze. Poszedłem z tym rozwiązaniem

Convert.ToInt64(i["Customer Phone"]).ToString("###-###-#### ####")

Teraz robi się pomieszane, gdy rozszerzenie ma mniej niż 4 cyfry. Wypełni liczby z prawej strony. więc

1112224444 333  becomes

11-221-244 3334

Jakieś pomysły?

Brian G.
źródło
5
Należy pamiętać, że nie wszędzie istnieją 10-cyfrowe numery telefonów lub format 111-222-4444.
Dour High Arch,
To się nie powiedzie w przypadku numerów telefonów zaczynających się od 0
dzień
Należy określić, czy są to tylko numery północnoamerykańskie, czy nie.
Armstrongest
OSTRZEŻENIE: Cały wątek zakłada numery telefonów w Ameryce Północnej. Skorzystaj z biblioteki obsługującej numery międzynarodowe. nuget.org/packages/libphonenumber-csharp
Sean Anderson

Odpowiedzi:

204

Pamiętaj, że ta odpowiedź działa z numerycznymi typami danych (int, long). Jeśli zaczynasz od ciągu, musisz najpierw przekonwertować go na liczbę. Weź również pod uwagę, że musisz sprawdzić, czy początkowy ciąg ma co najmniej 10 znaków długości.

Z dobrej strony pełnej przykładów:

String.Format("{0:(###) ###-####}", 8005551212);

    This will output "(800) 555-1212".

Chociaż wyrażenie regularne może działać jeszcze lepiej, pamiętaj o starym cytacie z programowania:

Niektórzy ludzie w obliczu problemu myślą „Wiem, użyję wyrażeń regularnych”. Teraz mają dwa problemy.
- Jamie Zawinski, w comp.lang.emacs

Sean
źródło
Co się stanie, powiedzmy, jeśli w numerze telefonu brakuje kilku cyfr - na przykład tylko „800555”? czy istnieje sposób, aby wyświetlić tylko to, co tam jest?
VoodooChild
11
To zła implementacja, ponieważ jeśli numer kierunkowy zaczyna się od 0105555555 lub czegoś podobnego, w końcu otrzymujesz (01) 555-5555 zamiast (010) 555-5555. Powodem jest to, że jeśli przekonwertujesz numer telefonu na liczbę, zero z przodu jest postrzegane jako nic, a po sformatowaniu pierwsze 0 zostanie usunięte.
Paul Mendoza
3
@Paul Przeczytaj definicję problemu: „Mam ciąg znaków” 1112224444 'to jest numer telefonu. Chcę sformatować jako 111-222-4444 przed zapisaniem go w pliku ”.
Sean
39
To nie zadziała, jeśli Twój numer telefonu jest ciągiem, zgodnie z pytaniami, chyba że najpierw przekonwertujesz go na wartość liczbową.
JustinStolle
4
Wiem, że to tylko powtórzenie powyższego komentarza, ale ta odpowiedź nie odpowiedziała na pytanie. Jak sformatować ciąg do określonego formatu, w tym przypadku formatu numeru telefonu.
dyslexicanaboko
168

Wolę używać wyrażeń regularnych:

Regex.Replace("1112224444", @"(\d{3})(\d{3})(\d{4})", "$1-$2-$3");
Ryan Duffield
źródło
4
Przypuszczam, że to zadziała, ale format .ToString () jest łatwiejszy do odczytania i powinien działać lepiej.
Joel Coehoorn
14
Jeśli mam już do czynienia ze sznurkiem, jak powiedział plakat, rzucanie go na długi iz powrotem wydaje się głupie.
Ryan Duffield
Może w końcu tego właśnie potrzebuję. poradzi sobie lepiej z rozszerzeniem
Brian G,
5
+1 za zachowanie numeru jako ciągu (biorąc pod uwagę, że często numery telefonów używane w automatycznych systemach SMS muszą być przechowywane w formacie +44)
Ed James,
3
Pracuję z różnymi formatami (np. (111) 222-4444, 111.222.4444 itp.), Ale potrzebuję ich znormalizowania do (111) 222-4444. Chciałem też zabezpieczyć się przed niepełnymi liczbami i użyłem notacji {n, m} . (I przepraszam za formatowanie, ale niektóre formaty MD nie działają dla mnie). // Remove non-digit characters var phoneDigits = Regex.Replace(crewMember.CellPhone, "[^\\d]", string.Empty); // Format the digits var phone = Regex.Replace(phoneDigits, @"(\d{1,3})(\d{0,3})(\d{0,4})", " ($1) $2-$3");
Craig Boland
47

Będziesz musiał rozbić go na podciągi. Chociaż można to zrobić bez dodatkowych zmiennych, nie byłoby to szczególnie przyjemne. Oto jedno potencjalne rozwiązanie:

string phone = i["MyPhone"].ToString();
string area = phone.Substring(0, 3);
string major = phone.Substring(3, 3);
string minor = phone.Substring(6);
string formatted = string.Format("{0}-{1}-{2}", area, major, minor);
Jon Skeet
źródło
Jon, czy na pewno zrobienie trzech podciągów jest lepsze niż użycie string.format?
Pradeep
Używam również String.Format - ale jak sugerujesz osiągnięcie wyniku bez użycia String.Format?
Jon Skeet,
2
Zapakowałem to w if (phone.Length == 10)stan.
Zack Peterson
Plus jeden - jedna mała uwaga: ten format nie wygląda tak, jakby zawierał nawiasy wokół numeru kierunkowego, może źle go czytam.
Mark Rogers
1
@MarkRogers: Pytanie brzmi „Chcę sformatować jako 111-222-4444” - nie ma tam żadnych nawiasów.
Jon Skeet
28

Proponuję to jako czyste rozwiązanie dla numerów w USA.

public static string PhoneNumber(string value)
{ 
    if (string.IsNullOrEmpty(value)) return string.Empty;
    value = new System.Text.RegularExpressions.Regex(@"\D")
        .Replace(value, string.Empty);
    value = value.TrimStart('1');
    if (value.Length == 7)
        return Convert.ToInt64(value).ToString("###-####");
    if (value.Length == 10)
        return Convert.ToInt64(value).ToString("###-###-####");
    if (value.Length > 10)
        return Convert.ToInt64(value)
            .ToString("###-###-#### " + new String('#', (value.Length - 10)));
    return value;
}
Jerry Nixon
źródło
1
To zadziałało dla mnie, z wyjątkiem tego, że musiałem najpierw dodać czek, aby upewnić się, że wartość telefonu nie była NULL lub biała spacja.
Caverman
1
To zadziałało po wszystkich powyższych, które wypróbowałem
Eliotjse,
22

O ile wiem, nie możesz tego zrobić za pomocą string.Format ... sam musiałbyś sobie z tym poradzić. Możesz po prostu usunąć wszystkie znaki nienumeryczne, a następnie zrobić coś takiego:

string.Format("({0}) {1}-{2}",
     phoneNumber.Substring(0, 3),
     phoneNumber.Substring(3, 3),
     phoneNumber.Substring(6));

Zakłada się, że dane zostały wprowadzone poprawnie, co można sprawdzić za pomocą wyrażeń regularnych.

mattruma
źródło
4
I zakłada numer telefonu
chris
19

To powinno działać:

String.Format("{0:(###)###-####}", Convert.ToInt64("1112224444"));

LUB w twoim przypadku:

String.Format("{0:###-###-####}", Convert.ToInt64("1112224444"));
Vivek Shenoy
źródło
3
1 mały problem, jeśli używam 01213456789 jego marek (12) 345-6789 ... jakieś rozwiązanie ...?
Sangram Nandkhile
5
To najlepsze rozwiązanie. Wiodące zero jest dyskusyjne w odniesieniu do amerykańskich numerów telefonów, ponieważ nie ma amerykańskich numerów kierunkowych zaczynających się od zera lub jedynki.
JB,
Mały problem, jeśli wypróbowałem 12345678, formatuje (1) 234-5678 ... Ale potrzebuję (123) 456-78. Czy jest na to jakieś rozwiązanie? Dzięki
Kavitha P.,
14

Jeśli możesz uzyskać i["MyPhone"]jako plik long, możesz użyć long.ToString()metody, aby go sformatować:

Convert.ToLong(i["MyPhone"]).ToString("###-###-####");

Zobacz stronę MSDN dotyczącą ciągów formatujących liczb .

Uważaj, aby użyć long zamiast int: int może się przepełnić.

Joel Coehoorn
źródło
1
Problem polega na tym, że liczba jest dłuższa niż 10 znaków (tj. Zawiera rozszerzenie). Skutkuje to bardzo dziwną reprezentacją, w której 212-555-1212 x1234 wychodzi jako2125551-212-1234.
Michael Blackburn
5
static string FormatPhoneNumber( string phoneNumber ) {

   if ( String.IsNullOrEmpty(phoneNumber) )
      return phoneNumber;

   Regex phoneParser = null;
   string format     = "";

   switch( phoneNumber.Length ) {

      case 5 :
         phoneParser = new Regex(@"(\d{3})(\d{2})");
         format      = "$1 $2";
       break;

      case 6 :
         phoneParser = new Regex(@"(\d{2})(\d{2})(\d{2})");
         format      = "$1 $2 $3";
       break;

      case 7 :
         phoneParser = new Regex(@"(\d{3})(\d{2})(\d{2})");
         format      = "$1 $2 $3";
       break;

      case 8 :
         phoneParser = new Regex(@"(\d{4})(\d{2})(\d{2})");
         format      = "$1 $2 $3";
       break;

      case 9 :
         phoneParser = new Regex(@"(\d{4})(\d{3})(\d{2})(\d{2})");
         format      = "$1 $2 $3 $4";
       break;

      case 10 :
         phoneParser = new Regex(@"(\d{3})(\d{3})(\d{2})(\d{2})");
         format      = "$1 $2 $3 $4";
       break;

      case 11 :
         phoneParser = new Regex(@"(\d{4})(\d{3})(\d{2})(\d{2})");
         format      = "$1 $2 $3 $4";
       break;

      default:
        return phoneNumber;

   }//switch

   return phoneParser.Replace( phoneNumber, format );

}//FormatPhoneNumber

    enter code here
podkreślać
źródło
wejście: 1234567890 wyjście: 123 456 78 90 nie działa
MC9000
5

Jeśli szukasz numeru telefonu (w USA) do konwersji w czasie rzeczywistym. Sugeruję użycie tego rozszerzenia. Ta metoda działa doskonale bez wpisywania liczb od tyłu. Wydaje się, że String.Formatrozwiązanie działa wstecz. Po prostu zastosuj to rozszerzenie do swojego ciągu.

public static string PhoneNumberFormatter(this string value)
{
    value = new Regex(@"\D").Replace(value, string.Empty);
    value = value.TrimStart('1');

    if (value.Length == 0)
        value = string.Empty;
    else if (value.Length < 3)
        value = string.Format("({0})", value.Substring(0, value.Length));
    else if (value.Length < 7)
        value = string.Format("({0}) {1}", value.Substring(0, 3), value.Substring(3, value.Length - 3));
    else if (value.Length < 11)
        value = string.Format("({0}) {1}-{2}", value.Substring(0, 3), value.Substring(3, 3), value.Substring(6));
    else if (value.Length > 10)
    {
        value = value.Remove(value.Length - 1, 1);
        value = string.Format("({0}) {1}-{2}", value.Substring(0, 3), value.Substring(3, 3), value.Substring(6));
    }
    return value;
}
James Copeland
źródło
Działa idealnie do ruchu do przodu. Ale wracając, utknie w pierwszym formacie (###).
Schwagmister
@Schwagmister Dobry chwyt. Zostało to poprawione i refaktoryzowałem kod do rozszerzenia do ogólnego użytku.
James Copeland,
4

Możesz także spróbować tego:

  public string GetFormattedPhoneNumber(string phone)
        {
            if (phone != null && phone.Trim().Length == 10)
                return string.Format("({0}) {1}-{2}", phone.Substring(0, 3), phone.Substring(3, 3), phone.Substring(6, 4));
                return phone;
        }

Wynik:

wprowadź opis obrazu tutaj

atik sarker
źródło
1
Należy pamiętać, że różne kraje mają różne formaty i długości numerów telefonów i ludzie nie będą mogli ich wprowadzić.
Neme
Jak użyłbym tego z Html.DisplayFor (model => model.PhoneNumber)?
JustJohn,
Użyłem tego i wymyśliłem, jak go używać na wyświetlaczu Razor Page. Umieściłem go w bloku @functions {} u góry strony. Następnie pozbyłem się pomocnika @ Html.DisplayFor i po prostu odwołałem się do funkcji: ................. @GetFormattedPhoneNumber (Model.Courses_New.CurrentContactPhone) Udało mi się!
JustJohn,
4

Możesz znaleźć się w sytuacji, w której użytkownicy próbują wprowadzać numery telefonów z różnego rodzaju separatorami między numerem kierunkowym a głównym blokiem numerycznym (np. Spacje, myślniki, kropki itp.). usuń wszystkie znaki, które nie są liczbami, aby móc wysterylizować dane wejściowe, z którymi pracujesz. Najłatwiej to zrobić za pomocą wyrażenia RegEx.

string formattedPhoneNumber = new System.Text.RegularExpressions.Regex(@"\D")
    .Replace(originalPhoneNumber, string.Empty);

Wtedy odpowiedź, którą podałeś, powinna działać w większości przypadków.

Aby odpowiedzieć na to, co masz na temat problemu z numerem wewnętrznym, możesz usunąć wszystko, co jest dłuższe niż oczekiwana długość dziesięciu (w przypadku zwykłego numeru telefonu), i dodać to na końcu, używając

formattedPhoneNumber = Convert.ToInt64(formattedPhoneNumber)
     .ToString("###-###-#### " + new String('#', (value.Length - 10)));

Będziesz chciał sprawdzić `` jeśli '', aby określić, czy długość danych wejściowych jest większa niż 10, zanim to zrobisz, jeśli nie, po prostu użyj:

formattedPhoneNumber = Convert.ToInt64(value).ToString("###-###-####");
Victor Johnson
źródło
3
Function FormatPhoneNumber(ByVal myNumber As String)
    Dim mynewNumber As String
    mynewNumber = ""
    myNumber = myNumber.Replace("(", "").Replace(")", "").Replace("-", "")
    If myNumber.Length < 10 Then
        mynewNumber = myNumber
    ElseIf myNumber.Length = 10 Then
        mynewNumber = "(" & myNumber.Substring(0, 3) & ") " &
                myNumber.Substring(3, 3) & "-" & myNumber.Substring(6, 3)
    ElseIf myNumber.Length > 10 Then
        mynewNumber = "(" & myNumber.Substring(0, 3) & ") " &
                myNumber.Substring(3, 3) & "-" & myNumber.Substring(6, 3) & " " &
                myNumber.Substring(10)
    End If
    Return mynewNumber
End Function
sth
źródło
Zagłosowano, ale ... To jest odpowiedź vb.net, a pytanie brzmi c #
wejście: 1234567890 wyjście: (123) 456-789 Nie działa!
MC9000
3
        string phoneNum;
        string phoneFormat = "0#-###-###-####";
        phoneNum = Convert.ToInt64("011234567891").ToString(phoneFormat);
nirav gandhi
źródło
2

Spróbuj tego

string result;
if ( (!string.IsNullOrEmpty(phoneNumber)) && (phoneNumber.Length >= 10 ) )
    result = string.Format("{0:(###)###-"+new string('#',phoneNumber.Length-6)+"}",
    Convert.ToInt64(phoneNumber)
    );
else
    result = phoneNumber;
return result;

Twoje zdrowie.

Humberto Moreno
źródło
2

Użyj funkcji Dopasuj w wyrażeniu regularnym, aby podzielić, a następnie wyślij sformatowany ciąg z match.groups

Regex regex = new Regex(@"(?<first3chr>\d{3})(?<next3chr>\d{3})(?<next4chr>\d{4})");
Match match = regex.Match(phone);
if (match.Success) return "(" + match.Groups["first3chr"].ToString() + ")" + " " + 
  match.Groups["next3chr"].ToString() + "-" + match.Groups["next4chr"].ToString();
Sathyajith Bhat
źródło
2

Poniższe działania będą działać bez użycia wyrażeń regularnych

string primaryContactNumber = !string.IsNullOrEmpty(formData.Profile.Phone) ? String.Format("{0:###-###-####}", long.Parse(formData.Profile.Phone)) : "";

Jeśli nie użyjemy long.Parse, string.format nie będzie działać.

Rama Krshna Ila
źródło
1
public string phoneformat(string phnumber)
{
String phone=phnumber;
string countrycode = phone.Substring(0, 3); 
string Areacode = phone.Substring(3, 3); 
string number = phone.Substring(6,phone.Length); 

phnumber="("+countrycode+")" +Areacode+"-" +number ;

return phnumber;
}

Wynik będzie: 001-568-895623

Mak
źródło
1

Użyj poniższego linku dla C # http://www.beansoftware.com/NET-Tutorials/format-string-phone-number.aspx

Najłatwiejszym sposobem formatowania jest użycie Regex.

private string FormatPhoneNumber(string phoneNum)
{
  string phoneFormat = "(###) ###-#### x####";

  Regex regexObj = new Regex(@"[^\d]");
  phoneNum = regexObj.Replace(phoneNum, "");
  if (phoneNum.Length > 0)
  {
    phoneNum = Convert.ToInt64(phoneNum).ToString(phoneFormat);
  }
  return phoneNum;
}

Podaj swój numer telefonu jako ciąg 2021231234 do 15 znaków.

FormatPhoneNumber(string phoneNum)

Innym podejściem byłoby użycie podłańcucha

private string PhoneFormat(string phoneNum)
    {
      int max = 15, min = 10;
      string areaCode = phoneNum.Substring(0, 3);
      string mid = phoneNum.Substring(3, 3);
      string lastFour = phoneNum.Substring(6, 4);
      string extension = phoneNum.Substring(10, phoneNum.Length - min);
      if (phoneNum.Length == min)
      {
        return $"({areaCode}) {mid}-{lastFour}";
      }
      else if (phoneNum.Length > min && phoneNum.Length <= max)
      {
        return $"({areaCode}) {mid}-{lastFour} x{extension}";
      }
      return phoneNum;
    }
Mohammed Hossen
źródło
0

Aby rozwiązać problem z rozszerzeniem, wykonaj następujące czynności:

string formatString = "###-###-#### ####";
returnValue = Convert.ToInt64(phoneNumber)
                     .ToString(formatString.Substring(0,phoneNumber.Length+3))
                     .Trim();
Larry Smithmier
źródło
0

Nie żeby wskrzesić starego pytania, ale doszedłem do wniosku, że mogę zaoferować przynajmniej nieco łatwiejszą w użyciu metodę, jeśli konfiguracja będzie nieco bardziej skomplikowana.

Więc jeśli utworzymy nowy niestandardowy program formatujący, możemy użyć prostszego formatowania string.Formatbez konieczności konwertowania naszego numeru telefonu nalong

Więc najpierw utwórzmy niestandardowy program formatujący:

using System;
using System.Globalization;
using System.Text;

namespace System
{
    /// <summary>
    ///     A formatter that will apply a format to a string of numeric values.
    /// </summary>
    /// <example>
    ///     The following example converts a string of numbers and inserts dashes between them.
    ///     <code>
    /// public class Example
    /// {
    ///      public static void Main()
    ///      {          
    ///          string stringValue = "123456789";
    ///  
    ///          Console.WriteLine(String.Format(new NumericStringFormatter(),
    ///                                          "{0} (formatted: {0:###-##-####})",stringValue));
    ///      }
    ///  }
    ///  //  The example displays the following output:
    ///  //      123456789 (formatted: 123-45-6789)
    ///  </code>
    /// </example>
    public class NumericStringFormatter : IFormatProvider, ICustomFormatter
    {
        /// <summary>
        ///     Converts the value of a specified object to an equivalent string representation using specified format and
        ///     culture-specific formatting information.
        /// </summary>
        /// <param name="format">A format string containing formatting specifications.</param>
        /// <param name="arg">An object to format.</param>
        /// <param name="formatProvider">An object that supplies format information about the current instance.</param>
        /// <returns>
        ///     The string representation of the value of <paramref name="arg" />, formatted as specified by
        ///     <paramref name="format" /> and <paramref name="formatProvider" />.
        /// </returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public string Format(string format, object arg, IFormatProvider formatProvider)
        {
            var strArg = arg as string;

            //  If the arg is not a string then determine if it can be handled by another formatter
            if (strArg == null)
            {
                try
                {
                    return HandleOtherFormats(format, arg);
                }
                catch (FormatException e)
                {
                    throw new FormatException(string.Format("The format of '{0}' is invalid.", format), e);
                }
            }

            // If the format is not set then determine if it can be handled by another formatter
            if (string.IsNullOrEmpty(format))
            {
                try
                {
                    return HandleOtherFormats(format, arg);
                }
                catch (FormatException e)
                {
                    throw new FormatException(string.Format("The format of '{0}' is invalid.", format), e);
                }
            }
            var sb = new StringBuilder();
            var i = 0;

            foreach (var c in format)
            {
                if (c == '#')
                {
                    if (i < strArg.Length)
                    {
                        sb.Append(strArg[i]);
                    }
                    i++;
                }
                else
                {
                    sb.Append(c);
                }
            }

            return sb.ToString();
        }

        /// <summary>
        ///     Returns an object that provides formatting services for the specified type.
        /// </summary>
        /// <param name="formatType">An object that specifies the type of format object to return.</param>
        /// <returns>
        ///     An instance of the object specified by <paramref name="formatType" />, if the
        ///     <see cref="T:System.IFormatProvider" /> implementation can supply that type of object; otherwise, null.
        /// </returns>
        public object GetFormat(Type formatType)
        {
            // Determine whether custom formatting object is requested. 
            return formatType == typeof(ICustomFormatter) ? this : null;
        }

        private string HandleOtherFormats(string format, object arg)
        {
            if (arg is IFormattable)
                return ((IFormattable)arg).ToString(format, CultureInfo.CurrentCulture);
            else if (arg != null)
                return arg.ToString();
            else
                return string.Empty;
        }
    }
}

Więc jeśli chcesz tego użyć, zrób coś takiego:

String.Format(new NumericStringFormatter(),"{0:###-###-####}", i["MyPhone"].ToString());

Kilka innych rzeczy do przemyślenia:

W tej chwili, jeśli określiłeś dłuższy program formatujący niż ciąg do formatowania, po prostu zignoruje dodatkowe znaki #. Na przykład thisString.Format(new NumericStringFormatter(),"{0:###-###-####}", "12345"); dałoby 123-45-, więc możesz chcieć, aby pobierał jakiś możliwy znak wypełniacza w konstruktorze.

Nie zapewniłem również sposobu na uniknięcie znaku #, więc gdybyś chciał uwzględnić to w swoim ciągu wyjściowym, nie byłbyś w stanie tak, jak jest teraz.

Powodem, dla którego wolę tę metodę od Regex, jest to, że często mam wymagania, aby pozwolić użytkownikom na samodzielne określanie formatu i znacznie łatwiej jest mi wyjaśnić, jak używać tego formatu, niż próbować nauczyć użytkownika wyrażenia regularnego.

Również nazwa klasy jest trochę myląca, ponieważ w rzeczywistości działa przy formatowaniu dowolnego ciągu, o ile chcesz zachować go w tej samej kolejności i po prostu wstawić do niego znaki.

Kent Cooper
źródło
0

Możesz spróbować {0: (000) 000 - ####}, jeśli liczba docelowa zaczyna się od 0.

Alice Guo
źródło
0

Oto inny sposób na zrobienie tego.

public string formatPhoneNumber(string _phoneNum)
{
    string phoneNum = _phoneNum;
    if (phoneNum == null)
        phoneNum = "";
    phoneNum = phoneNum.PadRight(10 - phoneNum.Length);
    phoneNum = phoneNum.Insert(0, "(").Insert(4,") ").Insert(9,"-");
    return phoneNum;
}
Neil Garcia
źródło