Analizowanie ciągów liczbowych na .NET

Wszystkie typy liczbowe mają dwie statyczne metody analizowania i ParseTryParse, których można użyć do przekonwertowania ciągu reprezentacji liczby na typ liczbowy. Te metody umożliwiają analizowanie ciągów wytwarzanych przy użyciu ciągów formatu udokumentowanych w standardowych ciągach formatu liczbowego i ciągach niestandardowego formatu liczbowego. Domyślnie metody i mogą Parse pomyślnie TryParse konwertować ciągi zawierające całkowite cyfry dziesiętne tylko na wartości całkowite. Mogą pomyślnie konwertować ciągi zawierające całkowite i ułamkowe cyfry dziesiętne, separatory grup i separator dziesiętny na wartości zmiennoprzecinkowe. Metoda Parse zgłasza wyjątek, jeśli operacja zakończy się niepowodzeniem, natomiast metoda zwraca TryParse wartość false.

Dostawcy analizowania i formatowania

Zazwyczaj reprezentacje ciągów wartości liczbowych różnią się w zależności od kultury. Elementy ciągów liczbowych, takie jak symbole walut, separatory grup (lub tysiące) i separatory dziesiętne, różnią się w zależności od kultury. Metody analizy niejawnie lub jawnie używają dostawcy formatu, który rozpoznaje te odmiany specyficzne dla kultury. Jeśli w wywołaniu Parse metody lub TryParse nie określono żadnego dostawcy formatu, używany jest dostawca formatu skojarzony z bieżącą kulturą ( NumberFormatInfoNumberFormatInfo.CurrentInfo obiektem zwracanym przez właściwość ).

Dostawca formatu jest reprezentowany przez implementację IFormatProvider . Ten interfejs ma jeden członek, GetFormat metodę, której pojedynczy parametr Type jest obiektem reprezentującym typ do sformatowania. Ta metoda zwraca obiekt , który dostarcza informacje o formatowaniu. Program .NET obsługuje następujące dwie implementacje IFormatProvider analizowania ciągów liczbowych:

Poniższy przykład próbuje przekonwertować każdy ciąg w tablicy na wartość Double . Najpierw podejmuje próbę analizy ciągu przy użyciu dostawcy formatu, który odzwierciedla konwencje kultury angielskiej (Stany Zjednoczone). Jeśli ta operacja zgłasza FormatExceptionwyjątek , próbuje ująć ciąg w analizę przy użyciu dostawcy formatu, który odzwierciedla konwencje kultury francuskiej (Francja).

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      string[] values = { "1,304.16", "$1,456.78", "1,094", "152",
                          "123,45 €", "1 304,16", "Ae9f" };
      double number;
      CultureInfo culture = null;

      foreach (string value in values) {
         try {
            culture = CultureInfo.CreateSpecificCulture("en-US");
            number = Double.Parse(value, culture);
            Console.WriteLine("{0}: {1} --> {2}", culture.Name, value, number);
         }
         catch (FormatException) {
            Console.WriteLine("{0}: Unable to parse '{1}'.",
                              culture.Name, value);
            culture = CultureInfo.CreateSpecificCulture("fr-FR");
            try {
               number = Double.Parse(value, culture);
               Console.WriteLine("{0}: {1} --> {2}", culture.Name, value, number);
            }
            catch (FormatException) {
               Console.WriteLine("{0}: Unable to parse '{1}'.",
                                 culture.Name, value);
            }
         }
         Console.WriteLine();
      }
   }
}
// The example displays the following output:
//    en-US: 1,304.16 --> 1304.16
//
//    en-US: Unable to parse '$1,456.78'.
//    fr-FR: Unable to parse '$1,456.78'.
//
//    en-US: 1,094 --> 1094
//
//    en-US: 152 --> 152
//
//    en-US: Unable to parse '123,45 €'.
//    fr-FR: Unable to parse '123,45 €'.
//
//    en-US: Unable to parse '1 304,16'.
//    fr-FR: 1 304,16 --> 1304.16
//
//    en-US: Unable to parse 'Ae9f'.
//    fr-FR: Unable to parse 'Ae9f'.
Imports System.Globalization

Module Example
    Public Sub Main()
        Dim values() As String = {"1,304.16", "$1,456.78", "1,094", "152",
                                   "123,45 €", "1 304,16", "Ae9f"}
        Dim number As Double
        Dim culture As CultureInfo = Nothing

        For Each value As String In values
            Try
                culture = CultureInfo.CreateSpecificCulture("en-US")
                number = Double.Parse(value, culture)
                Console.WriteLine("{0}: {1} --> {2}", culture.Name, value, number)
            Catch e As FormatException
                Console.WriteLine("{0}: Unable to parse '{1}'.",
                                  culture.Name, value)
                culture = CultureInfo.CreateSpecificCulture("fr-FR")
                Try
                    number = Double.Parse(value, culture)
                    Console.WriteLine("{0}: {1} --> {2}", culture.Name, value, number)
                Catch ex As FormatException
                    Console.WriteLine("{0}: Unable to parse '{1}'.",
                                      culture.Name, value)
                End Try
            End Try
            Console.WriteLine()
        Next
    End Sub
End Module
' The example displays the following output:
'    en-US: 1,304.16 --> 1304.16
'    
'    en-US: Unable to parse '$1,456.78'.
'    fr-FR: Unable to parse '$1,456.78'.
'    
'    en-US: 1,094 --> 1094
'    
'    en-US: 152 --> 152
'    
'    en-US: Unable to parse '123,45 €'.
'    fr-FR: Unable to parse '123,45 €'.
'    
'    en-US: Unable to parse '1 304,16'.
'    fr-FR: 1 304,16 --> 1304.16
'    
'    en-US: Unable to parse 'Ae9f'.
'    fr-FR: Unable to parse 'Ae9f'.

Analiza składniowa i wartości NumberStyles

Elementy stylu (takie jak biały znak, separatory grup i separator dziesiętny NumberStyles ), które może obsłużyć operacja analizy, są definiowane przez wartość wyliczenia. Domyślnie ciągi reprezentujące NumberStyles.Integer wartości całkowite są analizowane przy użyciu wartości , która zezwala tylko na cyfry numeryczne, wiodące i końcowe białe znaki oraz znak wiodący. NumberStyles.Float Ciągi reprezentujące wartości zmiennoprzecinkowe są analizowane przy użyciu kombinacji wartości i NumberStyles.AllowThousands . Ten styl złożony zezwala na cyfry dziesiętne wraz z wiodącym i na końcowych znak odstępu, znakiem wiodącym, separatorem dziesiętnym, separatorem grupy i wykładnikiem. Wywołując przeciążenie Parse metody lub TryParseNumberStylesNumberStyles , która zawiera parametr typu i ustawiając co najmniej jedną flagę, można kontrolować elementy stylu, które mogą być obecne w ciągu, aby operacja analizy zakończyła się pomyślnie.

Na przykład ciąg zawierający separator grupy nie może zostać przekonwertowany na wartość Int32 przy użyciu Int32.Parse(String) metody . Jednak konwersja powiedzie się, jeśli użyjemy NumberStyles.AllowThousands flagi , jak pokazano w poniższym przykładzie.

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      string value = "1,304";
      int number;
      IFormatProvider provider = CultureInfo.CreateSpecificCulture("en-US");
      if (Int32.TryParse(value, out number))
         Console.WriteLine("{0} --> {1}", value, number);
      else
         Console.WriteLine("Unable to convert '{0}'", value);

      if (Int32.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands,
                        provider, out number))
         Console.WriteLine("{0} --> {1}", value, number);
      else
         Console.WriteLine("Unable to convert '{0}'", value);
   }
}
// The example displays the following output:
//       Unable to convert '1,304'
//       1,304 --> 1304
Imports System.Globalization

Module Example
    Public Sub Main()
        Dim value As String = "1,304"
        Dim number As Integer
        Dim provider As IFormatProvider = CultureInfo.CreateSpecificCulture("en-US")
        If Int32.TryParse(value, number) Then
            Console.WriteLine("{0} --> {1}", value, number)
        Else
            Console.WriteLine("Unable to convert '{0}'", value)
        End If

        If Int32.TryParse(value, NumberStyles.Integer Or NumberStyles.AllowThousands,
                          provider, number) Then
            Console.WriteLine("{0} --> {1}", value, number)
        Else
            Console.WriteLine("Unable to convert '{0}'", value)
        End If
    End Sub
End Module
' The example displays the following output:
'       Unable to convert '1,304'
'       1,304 --> 1304

Ostrzeżenie

Operacja analizy zawsze używa konwencji formatowania określonej kultury. Jeśli nie określisz kultury przez przekazanie CultureInfo obiektu lub NumberFormatInfo , zostanie użyta kultura skojarzona z bieżącym wątkiem.

W poniższej tabeli wymieniono elementy członkowskie NumberStyles wyliczenia i opisano ich wpływ na operację analizowania.

Wartość wyliczenia NumberStyles Wpływ na ciąg do analizy
NumberStyles.None Dozwolone są tylko cyfry numeryczne.
NumberStyles.AllowDecimalPoint Separator dziesiętny i cyfry ułamkowe są dozwolone. W przypadku wartości całkowitych tylko zero jest dozwolone jako cyfra ułamkowa. Prawidłowe separatory dziesiętne są określane przez właściwość NumberFormatInfo.NumberDecimalSeparator lub NumberFormatInfo.CurrencyDecimalSeparator .
NumberStyles.AllowExponent Znak "e" lub "E" może służyć do wskazywania notacji wykładniczej. Aby NumberStyles uzyskać dodatkowe informacje, zobacz .
NumberStyles.AllowLeadingWhite Wiodące białe miejsce jest dozwolone.
NumberStyles.AllowTrailingWhite Dozwolone jest końcowe białe miejsce.
NumberStyles.AllowLeadingSign Znak dodatni lub ujemny może poprzedzać cyfry numeryczne.
NumberStyles.AllowTrailingSign Po cyfrach liczbowych może być znak dodatni lub ujemny.
NumberStyles.AllowParentheses Nawiasy mogą służyć do wskazywania wartości ujemnych.
NumberStyles.AllowThousands Separator grupy jest dozwolony. Znak separatora grupy jest określany przez właściwość NumberFormatInfo.NumberGroupSeparator lub NumberFormatInfo.CurrencyGroupSeparator .
NumberStyles.AllowCurrencySymbol Symbol waluty jest dozwolony. Symbol waluty jest definiowany przez właściwość NumberFormatInfo.CurrencySymbol .
NumberStyles.AllowHexSpecifier Ciąg do analizy jest interpretowany jako liczba szesnastkowa. Może zawierać cyfry szesnastkowe 0–9, A–F i a–f. Tej flagi można używać tylko do analizowania wartości całkowitych.

Ponadto wyliczenie NumberStyles zawiera następujące style złożone, które obejmują wiele NumberStyles flag.

Złożona wartość NumberStyles Obejmuje członków
NumberStyles.Integer Obejmuje style NumberStyles.AllowLeadingWhite, NumberStyles.AllowTrailingWhitei NumberStyles.AllowLeadingSign . Jest to domyślny styl używany do analizowania wartości całkowitych.
NumberStyles.Number Obejmuje style NumberStyles.AllowLeadingWhite, NumberStyles.AllowTrailingWhite, NumberStyles.AllowLeadingSign, NumberStyles.AllowTrailingSign, NumberStyles.AllowDecimalPointi NumberStyles.AllowThousands .
NumberStyles.Float Obejmuje style NumberStyles.AllowLeadingWhite, NumberStyles.AllowTrailingWhite, NumberStyles.AllowLeadingSign, NumberStyles.AllowDecimalPointi NumberStyles.AllowExponent .
NumberStyles.Currency Obejmuje wszystkie style z wyjątkiem NumberStyles.AllowExponent i NumberStyles.AllowHexSpecifier.
NumberStyles.Any Obejmuje wszystkie style z wyjątkiem NumberStyles.AllowHexSpecifier.
NumberStyles.HexNumber Obejmuje style NumberStyles.AllowLeadingWhite, NumberStyles.AllowTrailingWhitei NumberStyles.AllowHexSpecifier .

Analiza składniowa i cyfry Unicode

Standard Unicode definiuje punkty kodu dla cyfr w różnych systemach pisania. Na przykład punkty kodu od U+0030 do U+0039 reprezentują podstawowe cyfry łaciński od 0 do 9, punkty kodu od U+09E6 do U+09EF reprezentują cyfry Od 0 do 9, a punkty kodu od U+FF10 do U+FF19 reprezentują cyfry Fullwidth od 0 do 9. Jednak jedyne cyfry liczbowe rozpoznawane przez metody analizy są podstawowymi cyframi łacińskimi 0–9 z punktami kodu od U+0030 do U+0039. Jeśli metoda analizy liczbowej jest przekazywana jako ciąg zawierający inne cyfry, metoda zgłasza wyjątek FormatException.

W poniższym przykładzie użyto metody Int32.Parse do analizowania ciągów, które składają się z cyfr w różnych systemach pisania. Jak widać w danych wyjściowych z przykładu, próba analizy podstawowych cyfr łacińskich kończy się powodzeniem, ale próba analizy cyfr Fullwidth, Arabski-Indykański i Eryka kończy się niepowodzeniem.

using System;

public class Example
{
   public static void Main()
   {
      string value;
      // Define a string of basic Latin digits 1-5.
      value = "\u0031\u0032\u0033\u0034\u0035";
      ParseDigits(value);

      // Define a string of Fullwidth digits 1-5.
      value = "\uFF11\uFF12\uFF13\uFF14\uFF15";
      ParseDigits(value);

      // Define a string of Arabic-Indic digits 1-5.
      value = "\u0661\u0662\u0663\u0664\u0665";
      ParseDigits(value);

      // Define a string of Bangla digits 1-5.
      value = "\u09e7\u09e8\u09e9\u09ea\u09eb";
      ParseDigits(value);
   }

   static void ParseDigits(string value)
   {
      try {
         int number = Int32.Parse(value);
         Console.WriteLine("'{0}' --> {1}", value, number);
      }
      catch (FormatException) {
         Console.WriteLine("Unable to parse '{0}'.", value);
      }
   }
}
// The example displays the following output:
//       '12345' --> 12345
//       Unable to parse '12345'.
//       Unable to parse '١٢٣٤٥'.
//       Unable to parse '১২৩৪৫'.
Module Example
    Public Sub Main()
        Dim value As String
        ' Define a string of basic Latin digits 1-5.
        value = ChrW(&h31) + ChrW(&h32) + ChrW(&h33) + ChrW(&h34) + ChrW(&h35)
        ParseDigits(value)

        ' Define a string of Fullwidth digits 1-5.
        value = ChrW(&hff11) + ChrW(&hff12) + ChrW(&hff13) + ChrW(&hff14) + ChrW(&hff15)
        ParseDigits(value)

        ' Define a string of Arabic-Indic digits 1-5.
        value = ChrW(&h661) + ChrW(&h662) + ChrW(&h663) + ChrW(&h664) + ChrW(&h665)
        ParseDigits(value)

        ' Define a string of Bangla digits 1-5.
        value = ChrW(&h09e7) + ChrW(&h09e8) + ChrW(&h09e9) + ChrW(&h09ea) + ChrW(&h09eb)
        ParseDigits(value)
    End Sub

    Sub ParseDigits(value As String)
        Try
            Dim number As Integer = Int32.Parse(value)
            Console.WriteLine("'{0}' --> {1}", value, number)
        Catch e As FormatException
            Console.WriteLine("Unable to parse '{0}'.", value)
        End Try
    End Sub
End Module
' The example displays the following output:
'       '12345' --> 12345
'       Unable to parse '12345'.
'       Unable to parse '١٢٣٤٥'.
'       Unable to parse '১২৩৪৫'.

Zobacz też