Analizowanie ciągów liczbowych na .NET
Wszystkie typy liczbowe mają dwie statyczne metody analizowania i Parse
TryParse
, 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:
Obiekt CultureInfo , którego CultureInfo.GetFormat metoda zwraca obiekt NumberFormatInfo , który dostarcza informacje o formatowaniu specyficzne dla kultury.
Obiekt NumberFormatInfo , którego NumberFormatInfo.GetFormat metoda zwraca samą siebie.
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 TryParse
NumberStylesNumberStyles , 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.
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 '১২৩৪৫'.