Aracılığıyla paylaş


.NET'te sayısal dizeleri ayrıştırma

Tüm sayısal türlerin, bir sayının dize gösterimini sayısal bir türe dönüştürmek için kullanabileceğiniz Parse ve TryParseolmak üzere iki statik ayrıştırma yöntemi vardır. Bu yöntemler, Standart Sayısal Biçim Dizeleri ve Özel Sayısal Biçim Dizeleribelgelenmiş biçim dizelerini kullanarak oluşturulan dizeleri ayrıştırmanızı sağlar. Varsayılan olarak, Parse ve TryParse yöntemleri, tamsayı ondalık basamakları içeren dizeleri yalnızca tamsayı değerlerine başarıyla dönüştürebilir. İntegral ve kesirli ondalık basamaklar, grup ayırıcıları ve ondalık ayırıcı içeren dizeleri kayan nokta değerlerine başarıyla dönüştürebilirler. Parse yöntemi, işlem başarısız olursa bir özel durum oluştururken, TryParse yöntemi falsedöndürür.

Uyarı

.NET 7'den başlayarak, .NET'teki sayısal türler System.IParsable<TSelf> ve IParsable<TSelf>.Parse yöntemlerini tanımlayan IParsable<TSelf>.TryParse arabirimini de uygular.

Ayrıştırma ve biçim formatı sağlayıcıları

Genellikle, sayısal değerlerin dize gösterimleri kültüre göre farklılık gösterir. Para birimi simgeleri, grup (veya binler) ayırıcıları ve ondalık ayırıcılar gibi sayısal dizelerin öğelerinin tümü kültüre göre farklılık gösterir. Ayrıştırma yöntemleri örtük olarak veya açıkça bu kültüre özgü varyasyonları tanıyan bir biçim sağlayıcısı kullanır. Parse veya TryParse yöntemine yapılan bir çağrıda biçim sağlayıcısı belirtilmezse, geçerli kültürle ilişkili biçim sağlayıcısı (NumberFormatInfo özelliği tarafından döndürülen NumberFormatInfo.CurrentInfo nesnesi) kullanılır.

Biçim sağlayıcısı bir IFormatProvider uygulamasıyla temsil edilir. Bu arabirim, tek parametresi biçimlendirilecek türü temsil eden bir GetFormat nesnesi olan Type yöntemi olan tek bir üyeye sahiptir. Bu yöntem, biçimlendirme bilgileri sağlayan nesneyi döndürür. .NET, sayısal dizeleri ayrıştırma için aşağıdaki iki IFormatProvider uygulamasını destekler:

Aşağıdaki örnek, bir dizideki her dizeyi bir Double değerine dönüştürmeye çalışır. İlk olarak İngilizce (ABD) kültürünün kurallarını yansıtan bir biçim sağlayıcısı kullanarak dizeyi ayrıştırmaya çalışır. Bu işlem bir FormatExceptionoluşturursa, Fransızca (Fransa) kültürünün kurallarını yansıtan bir biçim sağlayıcısı kullanarak dizeyi ayrıştırmaya çalışır.

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($"{culture.Name}: {value} --> {number}");
         }
         catch (FormatException) {
            Console.WriteLine($"{culture.Name}: Unable to parse '{value}'.");
            culture = CultureInfo.CreateSpecificCulture("fr-FR");
            try {
               number = Double.Parse(value, culture);
               Console.WriteLine($"{culture.Name}: {value} --> {number}");
            }
            catch (FormatException) {
               Console.WriteLine($"{culture.Name}: Unable to parse '{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'.

Ayrıştırma ve NumberStyles Değerleri

Ayrıştırma işleminin işleyebileceği stil öğeleri (boşluk, grup ayırıcıları ve ondalık ayırıcı gibi) NumberStyles numaralandırma değeri tarafından tanımlanır. Varsayılan olarak, tamsayı değerlerini temsil eden dizeler yalnızca sayısal basamaklara, baştaki ve sondaki boşluklara ve baştaki işarete izin veren NumberStyles.Integer değeri kullanılarak ayrıştırılır. Kayan nokta değerlerini temsil eden dizeler, NumberStyles.Float ve NumberStyles.AllowThousands değerlerinin kombinasyonu kullanılarak analiz edilir; bu kompozit stil, ondalık basamakların yanı sıra, baştaki ve sondaki boşlukları, baştaki işareti, ondalık ayırıcıyı, grup ayırıcıyı ve üssü de kabul eder. Parse türünde bir parametre içeren TryParse veya NumberStyles yönteminin aşırı yüklemesini çağırarak ve bir veya daha fazla NumberStyles bayrağı ayarlayarak, ayrıştırma işleminin başarılı olması için dizede bulunabilecek stil öğelerini denetleyebilirsiniz.

Örneğin, grup ayırıcısı içeren bir dize, Int32 yöntemi kullanılarak Int32.Parse(String) bir değere dönüştürülemez. Ancak, aşağıdaki örnekte gösterildiği gibi NumberStyles.AllowThousands bayrağını kullanırsanız dönüştürme başarılı olur.

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($"{value} --> {number}");
      else
         Console.WriteLine($"Unable to convert '{value}'");

      if (Int32.TryParse(value, NumberStyles.Integer | NumberStyles.AllowThousands,
                        provider, out number))
         Console.WriteLine($"{value} --> {number}");
      else
         Console.WriteLine($"Unable to convert '{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

Uyarı

Ayrıştırma işlemi her zaman belirli bir kültürün biçimlendirme kurallarını kullanır. Eğer bir CultureInfo veya NumberFormatInfo nesnesi geçirerek bir kültür belirtmezseniz, mevcut iş parçacığına bağlı olan kültür kullanılır.

Aşağıdaki tabloda, NumberStyles numaralandırmasının üyeleri listelenir ve ayrıştırma işlemi üzerindeki etkisi açıklanır.

NumberStyles değeri Ayrıştırılacak dizeye olan etkisi
NumberStyles.None Yalnızca sayısal basamaklara izin verilir.
NumberStyles.AllowDecimalPoint Ondalık ayırıcı ve kesirli basamakların kullanılması izin verilir. Tamsayı değerleri için kesirli basamak olarak yalnızca sıfıra izin verilir. Geçerli ondalık ayırıcılar NumberFormatInfo.NumberDecimalSeparator veya NumberFormatInfo.CurrencyDecimalSeparator özelliği tarafından belirlenir.
NumberStyles.AllowExponent Üstel notasyonu belirtmek için "e" veya "E" karakteri kullanılabilir. Daha fazla bilgi için bkz. NumberStyles.
NumberStyles.AllowLeadingWhite Öndeki boşluklara izin verilir.
NumberStyles.AllowTrailingWhite Sondaki boşluklara izin verilir.
NumberStyles.AllowLeadingSign Sayısal basamakların önüne pozitif veya negatif bir işaret gelebilir.
NumberStyles.AllowTrailingSign Pozitif veya negatif bir işaret sayısal basamakları izleyebilir.
NumberStyles.AllowParentheses Negatif değerleri belirtmek için parantezler kullanılabilir.
NumberStyles.AllowThousands Grup ayırıcıya izin verilir. Grup ayırıcı karakteri, NumberFormatInfo.NumberGroupSeparator veya NumberFormatInfo.CurrencyGroupSeparator özelliği tarafından belirlenir.
NumberStyles.AllowCurrencySymbol Para birimi simgesine izin verilir. Para birimi simgesi NumberFormatInfo.CurrencySymbol özelliği tarafından tanımlanır.
NumberStyles.AllowHexSpecifier Ayrıştırılacak dize onaltılık bir sayı olarak yorumlanır. Onaltılık basamaklar 0-9, A-F ve a-f içerebilir. Bu bayrak yalnızca tamsayı değerlerini ayrıştırmak için kullanılabilir.
NumberStyles.AllowBinarySpecifier Ayrıştırılacak dize ikili sayı olarak yorumlanır. 0 ve 1 ikili basamaklarını içerebilir. Bu bayrak yalnızca tamsayı değerlerini ayrıştırmak için kullanılabilir.

Ayrıca, NumberStyles numaralandırması birden çok NumberStyles bayrağı içeren aşağıdaki bileşik stilleri sağlar.

Bileşik "NumberStyles" değeri Üyeleri içerir
NumberStyles.Integer NumberStyles.AllowLeadingWhite, NumberStyles.AllowTrailingWhiteve NumberStyles.AllowLeadingSign stillerini içerir. Bu, tamsayı değerlerini ayrıştırmak için kullanılan varsayılan stildir.
NumberStyles.Number NumberStyles.AllowLeadingWhite, NumberStyles.AllowTrailingWhite, NumberStyles.AllowLeadingSign, NumberStyles.AllowTrailingSign, NumberStyles.AllowDecimalPointve NumberStyles.AllowThousands stillerini içerir.
NumberStyles.Float NumberStyles.AllowLeadingWhite, NumberStyles.AllowTrailingWhite, NumberStyles.AllowLeadingSign, NumberStyles.AllowDecimalPointve NumberStyles.AllowExponent stillerini içerir.
NumberStyles.Currency NumberStyles.AllowExponent ve NumberStyles.AllowHexSpecifierdışındaki tüm stilleri içerir.
NumberStyles.Any NumberStyles.AllowHexSpecifierdışındaki tüm stilleri içerir.
NumberStyles.HexNumber NumberStyles.AllowLeadingWhite, NumberStyles.AllowTrailingWhiteve NumberStyles.AllowHexSpecifier stillerini içerir.
NumberStyles.BinaryNumber NumberStyles.AllowLeadingWhite, NumberStyles.AllowTrailingWhiteve NumberStyles.AllowBinarySpecifier stillerini içerir.

İkili ve onaltılık BigInteger'ları ayrıştırma

BigInteger'nin AllowHexSpecifier veya AllowBinarySpecifier bayraklarıyla ayrıştırıldığı zaman, giriş dizesi tam olarak uzunluğu kadar onaltılık/ikili sayı olarak yorumlanır. Örneğin, "11" ikili BigInteger olarak ayrıştırıldığında -1 sonucunu verir çünkü bu, tam olarak 2 basamaklı bir imzalı ikinin tamamlayıcı değeri olan 11 olarak yorumlanır. Pozitif bir sonuç istiyorsanız, 3 olarak ayrıştırılan "011" gibi bir baştaki 0 öğesini ekleyin.

Ayrıştırma ve Unicode Basamakları

Unicode standardı, çeşitli yazma sistemlerindeki basamaklar için kod noktalarını tanımlar. Örneğin, U+0030'dan U+0039'a kadar olan kod noktaları 0 ile 9 arasındaki temel Latin basamaklarını, U+09E6'dan U+09EF'ye kadar olan kod noktaları 0 ile 9 arasındaki Bangla basamaklarını ve U+FF10'dan U+FF19'a kadar olan kod noktaları 0 ile 9 arasındaki Tam Tuş basamaklarını temsil eder. Ancak, ayrıştırma yöntemleri tarafından tanınan tek sayısal basamaklar, U+0030 ile U+0039 arası kod noktaları içeren temel Latin basamakları 0-9'dur. Sayısal ayrıştırma yöntemine başka basamaklar içeren bir dize geçirilirse, yöntem bir FormatExceptionhatası fırlatır.

Aşağıdaki örnek, farklı yazma sistemlerindeki basamaklardan oluşan dizeleri ayrıştırmak için Int32.Parse yöntemini kullanır. Örnekte gösterildiği gibi, temel Latin basamaklarını ayrıştırma girişimi başarılı olur, ancak Fullwidth, Arapça-Hint ve Bangla basamaklarını ayrıştırma girişimi başarısız olur.

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($"'{value}' --> {number}");
      }
      catch (FormatException) {
         Console.WriteLine($"Unable to parse '{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 '১২৩৪৫'.

Ayrıca bkz.