C'de dizeleri karşılaştırma#

Dizeleri iki sorudan birini yanıtlamak için karşılaştırırsınız: "Bu iki dize eşit mi?" veya "Bu dizeler sıralanırken hangi sırada yerleştirilmelidir?"

Bu iki soru, dize karşılaştırmalarını etkileyen faktörlerle karmaşıktır:

  • Sıralı veya dilsel karşılaştırma seçebilirsiniz.
  • Servis talebinin önemli olup olmadığını seçebilirsiniz.
  • Kültüre özgü karşılaştırmalar seçebilirsiniz.
  • Dil karşılaştırmaları kültüre ve platforma bağımlıdır.

Numaralandırma System.StringComparison alanları şu seçenekleri gösterir:

  • CurrentCulture: Kültüre duyarlı sıralama kurallarını ve geçerli kültürü kullanarak dizeleri karşılaştırın.
  • CurrentCultureIgnoreCase: Kültüre duyarlı sıralama kurallarını, geçerli kültürü kullanarak ve karşılaştırılan dizelerin büyük/küçük harf durumunu yoksayarak dizeleri karşılaştırın.
  • InvariantCulture: Kültüre duyarlı sıralama kurallarını ve sabit kültürü kullanarak dizeleri karşılaştırın.
  • InvariantCultureIgnoreCase: Kültüre duyarlı sıralama kurallarını, sabit kültürü kullanarak ve karşılaştırılan dizelerin büyük/küçük harflerini yoksayarak dizeleri karşılaştırın.
  • Sıralı: Sıralı (ikili) sıralama kurallarını kullanarak dizeleri karşılaştırın.
  • OrdinalIgnoreCase: Sıralı (ikili) sıralama kurallarını kullanarak dizeleri karşılaştırın ve karşılaştırılan dizelerin durumunu yoksayın.

Not

Bu makaledeki C# örnekleri Try.NET satır içi kod çalıştırıcısında ve oyun alanında çalıştırılır. Etkileşimli bir pencerede örnek çalıştırmak için Çalıştır düğmesini seçin. Kodu yürüttkten sonra yeniden Çalıştır'ı seçerek kodu değiştirebilir ve değiştirilen kodu çalıştırabilirsiniz. Değiştirilen kod etkileşimli pencerede çalışır veya derleme başarısız olursa, etkileşimli pencerede tüm C# derleyicisi hata iletileri görüntülenir.

Dizeleri karşılaştırdığınızda, aralarında bir sıra tanımlarsınız. Karşılaştırmalar, bir dizi dizeyi sıralamak için kullanılır. Sıra bilinen bir sırada olduğunda, hem yazılım hem de insanlar için arama yapmak daha kolaydır. Diğer karşılaştırmalar dizelerin aynı olup olmadığını denetleyebilir. Bu eşitlik denetimleri eşitliğe benzer, ancak büyük/küçük harf farklılıkları gibi bazı farklılıklar yoksayılabilir.

Varsayılan sıralı karşılaştırmalar

Varsayılan olarak, en yaygın işlemler:

string root = @"C:\users";
string root2 = @"C:\Users";

bool result = root.Equals(root2);
Console.WriteLine($"Ordinal comparison: <{root}> and <{root2}> are {(result ? "equal." : "not equal.")}");

result = root.Equals(root2, StringComparison.Ordinal);
Console.WriteLine($"Ordinal comparison: <{root}> and <{root2}> are {(result ? "equal." : "not equal.")}");

Console.WriteLine($"Using == says that <{root}> and <{root2}> are {(root == root2 ? "equal" : "not equal")}");

Varsayılan sıralı karşılaştırma, dizeleri karşılaştırırken dil kurallarını dikkate almaz. İki dizedeki her Char nesnenin ikili değerini karşılaştırır. Sonuç olarak, varsayılan sıralı karşılaştırma da büyük/küçük harfe duyarlıdır.

ve ile String.Equals eşitlik testi ve ==!= işleçleri, ve Compare(String, String) yöntemlerini kullanarak dize karşılaştırmasından String.CompareTo farklıdır. Tümü büyük/küçük harfe duyarlı bir karşılaştırma gerçekleştirir. Ancak, eşitlik testleri sıralı bir karşılaştırma gerçekleştirirken ve CompareToCompare yöntemleri geçerli kültürü kullanarak kültüre duyarlı bir dil karşılaştırması gerçekleştirir. Gerçekleştirilecek karşılaştırma türünü açıkça belirten bir aşırı yükleme çağırarak kodunuzun amacını net hale getirin.

Büyük/küçük harfe duyarlı olmayan sıralı karşılaştırmalar

yöntemi, String.Equals(String, StringComparison) büyük/küçük harfe duyarsız sıralı karşılaştırma için değerini StringComparison.OrdinalIgnoreCase belirtmenizi StringComparison sağlar. Bağımsız değişken için StringComparison değerini belirtirseniz büyük/küçük harfe duyarsız sıralı karşılaştırma gerçekleştiren statik String.Compare(String, String, StringComparison) bir StringComparison.OrdinalIgnoreCase yöntem de vardır. Bu karşılaştırmalar aşağıdaki kodda gösterilmiştir:

string root = @"C:\users";
string root2 = @"C:\Users";

bool result = root.Equals(root2, StringComparison.OrdinalIgnoreCase);
bool areEqual = String.Equals(root, root2, StringComparison.OrdinalIgnoreCase);
int comparison = String.Compare(root, root2, comparisonType: StringComparison.OrdinalIgnoreCase);

Console.WriteLine($"Ordinal ignore case: <{root}> and <{root2}> are {(result ? "equal." : "not equal.")}");
Console.WriteLine($"Ordinal static ignore case: <{root}> and <{root2}> are {(areEqual ? "equal." : "not equal.")}");
if (comparison < 0)
    Console.WriteLine($"<{root}> is less than <{root2}>");
else if (comparison > 0)
    Console.WriteLine($"<{root}> is greater than <{root2}>");
else
    Console.WriteLine($"<{root}> and <{root2}> are equivalent in order");

Bu yöntemler, büyük/küçük harfe duyarsız sıralı karşılaştırma gerçekleştirirken sabit kültürün büyük/küçük harf kurallarını kullanır.

Dil karşılaştırmaları

Birçok dize karşılaştırma yöntemi (örneğinString.StartsWith), girişlerini sıralamak için varsayılan olarak geçerli kültür için dil kuralları kullanır. Bu dil karşılaştırması bazen "sözcük sıralama düzeni" olarak adlandırılır. Dil karşılaştırması yaptığınızda, bazı nonalfanumerik Unicode karakterlerine özel ağırlıklar atanmış olabilir. Örneğin, "-" kısa çizgisinde küçük bir ağırlık atanmış olabilir, böylece "ortak çalışma" ve "coop" sıralama düzeninde yan yana görünür. Bazı yazdırılmayan denetim karakterleri yoksayılabilir. Ayrıca, bazı Unicode karakterleri bir örnek dizisiyle Char eşdeğer olabilir. Aşağıdaki örnekte almancada "sokakta dans ediyorlar", "ss" (U+0073 U+0073) ile bir dizede 'ß' (U+00DF) ifadesi kullanılır. Dilbilimsel olarak (Windows'ta), "ss" hem "en-US" hem de "de-DE" kültürlerinde Almanca Esszet: 'ß' karakterine eşittir.

string first = "Sie tanzen auf der Straße.";
string second = "Sie tanzen auf der Strasse.";

Console.WriteLine($"First sentence is <{first}>");
Console.WriteLine($"Second sentence is <{second}>");

bool equal = String.Equals(first, second, StringComparison.InvariantCulture);
Console.WriteLine($"The two strings {(equal == true ? "are" : "are not")} equal.");
showComparison(first, second);

string word = "coop";
string words = "co-op";
string other = "cop";

showComparison(word, words);
showComparison(word, other);
showComparison(words, other);
void showComparison(string one, string two)
{
    int compareLinguistic = String.Compare(one, two, StringComparison.InvariantCulture);
    int compareOrdinal = String.Compare(one, two, StringComparison.Ordinal);
    if (compareLinguistic < 0)
        Console.WriteLine($"<{one}> is less than <{two}> using invariant culture");
    else if (compareLinguistic > 0)
        Console.WriteLine($"<{one}> is greater than <{two}> using invariant culture");
    else
        Console.WriteLine($"<{one}> and <{two}> are equivalent in order using invariant culture");
    if (compareOrdinal < 0)
        Console.WriteLine($"<{one}> is less than <{two}> using ordinal comparison");
    else if (compareOrdinal > 0)
        Console.WriteLine($"<{one}> is greater than <{two}> using ordinal comparison");
    else
        Console.WriteLine($"<{one}> and <{two}> are equivalent in order using ordinal comparison");
}

Windows'ta, .NET 5'ten önce, dil karşılaştırmasından sıralı karşılaştırmaya geçiş yaptığınızda "cop", "coop" ve "co-op" sıralama düzeni değişir. İki Almanca cümle de farklı karşılaştırma türleri kullanılarak farklı karşılaştırılır. .NET 5'in öncesinde .NET genelleştirme API'leri Ulusal Dil Desteği (NLS) kitaplıklarını kullanıyordu. .NET 5 ve sonraki sürümlerinde,.NET genelleştirme API'leri Unicode (ICU) kitaplıkları için Uluslararası Bileşenler kullanır ve bu da ile birleşmektedir. DESTEKLENEN tüm işletim sistemlerinde NET'in genelleştirme davranışı.

Belirli kültürleri kullanan karşılaştırmalar

Aşağıdaki örnek, en-US ve de-DE kültürleri için nesneleri depolar CultureInfo . Karşılaştırmalar, kültüre özgü bir karşılaştırma sağlamak için bir CultureInfo nesne kullanılarak gerçekleştirilir. Kullanılan kültür dil karşılaştırmalarını etkiler. Aşağıdaki örnek, "en-US" kültürü ve "de-DE" kültürünü kullanarak iki Almanca cümleyi karşılaştırmanın sonuçlarını gösterir:

string first = "Sie tanzen auf der Straße.";
string second = "Sie tanzen auf der Strasse.";

Console.WriteLine($"First sentence is <{first}>");
Console.WriteLine($"Second sentence is <{second}>");

var en = new System.Globalization.CultureInfo("en-US");

// For culture-sensitive comparisons, use the String.Compare
// overload that takes a StringComparison value.
int i = String.Compare(first, second, en, System.Globalization.CompareOptions.None);
Console.WriteLine($"Comparing in {en.Name} returns {i}.");

var de = new System.Globalization.CultureInfo("de-DE");
i = String.Compare(first, second, de, System.Globalization.CompareOptions.None);
Console.WriteLine($"Comparing in {de.Name} returns {i}.");

bool b = String.Equals(first, second, StringComparison.CurrentCulture);
Console.WriteLine($"The two strings {(b ? "are" : "are not")} equal.");

string word = "coop";
string words = "co-op";
string other = "cop";

showComparison(word, words, en);
showComparison(word, other, en);
showComparison(words, other, en);
void showComparison(string one, string two, System.Globalization.CultureInfo culture)
{
    int compareLinguistic = String.Compare(one, two, en, System.Globalization.CompareOptions.None);
    int compareOrdinal = String.Compare(one, two, StringComparison.Ordinal);
    if (compareLinguistic < 0)
        Console.WriteLine($"<{one}> is less than <{two}> using en-US culture");
    else if (compareLinguistic > 0)
        Console.WriteLine($"<{one}> is greater than <{two}> using en-US culture");
    else
        Console.WriteLine($"<{one}> and <{two}> are equivalent in order using en-US culture");
    if (compareOrdinal < 0)
        Console.WriteLine($"<{one}> is less than <{two}> using ordinal comparison");
    else if (compareOrdinal > 0)
        Console.WriteLine($"<{one}> is greater than <{two}> using ordinal comparison");
    else
        Console.WriteLine($"<{one}> and <{two}> are equivalent in order using ordinal comparison");
}

Kültüre duyarlı karşılaştırmalar genellikle kullanıcılara göre dize girişlerini karşılaştırmak ve sıralamak için kullanılır ve diğer dize girişi kullanıcılara göre yapılır. Bu dizelerin karakterleri ve sıralama kuralları, kullanıcının bilgisayarının yerel ayarına bağlı olarak değişebilir. Aynı karakterleri içeren dizeler bile geçerli iş parçacığının kültürüne bağlı olarak farklı sıralanabilir.

Dizilerdeki dizeleri dilsel sıralama ve arama

Aşağıdaki örneklerde, geçerli kültüre bağımlı bir dil karşılaştırması kullanarak dizideki dizeleri sıralama ve arama işlemleri gösterilmektedir. Parametre alan System.StringComparer statik Array yöntemleri kullanırsınız.

Aşağıdaki örnek, geçerli kültürü kullanarak bir dize dizisinin nasıl sıralanacağını gösterir:

string[] lines = new string[]
{
    @"c:\public\textfile.txt",
    @"c:\public\textFile.TXT",
    @"c:\public\Text.txt",
    @"c:\public\testfile2.txt"
};

Console.WriteLine("Non-sorted order:");
foreach (string s in lines)
{
    Console.WriteLine($"   {s}");
}

Console.WriteLine("\n\rSorted order:");

// Specify Ordinal to demonstrate the different behavior.
Array.Sort(lines, StringComparer.CurrentCulture);

foreach (string s in lines)
{
    Console.WriteLine($"   {s}");
}

Dizi sıralandıktan sonra, ikili arama kullanarak girdileri arayabilirsiniz. İkili arama, koleksiyonun hangi yarısının aranan dizeyi içereceğini belirlemek için koleksiyonun ortasında başlar. Sonraki her karşılaştırma, koleksiyonun kalan bölümünü yarıya böler. Dizi, kullanılarak StringComparer.CurrentCulturesıralanır. Yerel işlev ShowWhere , dizenin bulunduğu yerle ilgili bilgileri görüntüler. Dize bulunamazsa, döndürülen değer bulunursa nerede olacağını gösterir.

string[] lines = new string[]
{
    @"c:\public\textfile.txt",
    @"c:\public\textFile.TXT",
    @"c:\public\Text.txt",
    @"c:\public\testfile2.txt"
};
Array.Sort(lines, StringComparer.CurrentCulture);

string searchString = @"c:\public\TEXTFILE.TXT";
Console.WriteLine($"Binary search for <{searchString}>");
int result = Array.BinarySearch(lines, searchString, StringComparer.CurrentCulture);
ShowWhere<string>(lines, result);

Console.WriteLine($"{(result > 0 ? "Found" : "Did not find")} {searchString}");

void ShowWhere<T>(T[] array, int index)
{
    if (index < 0)
    {
        index = ~index;

        Console.Write("Not found. Sorts between: ");

        if (index == 0)
            Console.Write("beginning of sequence and ");
        else
            Console.Write($"{array[index - 1]} and ");

        if (index == array.Length)
            Console.WriteLine("end of sequence.");
        else
            Console.WriteLine($"{array[index]}.");
    }
    else
    {
        Console.WriteLine($"Found at index {index}.");
    }
}

Koleksiyonlarda sıralı sıralama ve arama

Aşağıdaki kod, dizeleri depolamak için koleksiyon sınıfını kullanır System.Collections.Generic.List<T> . Dizeler yöntemi kullanılarak List<T>.Sort sıralanır. Bu yöntem, iki dizeyi karşılaştıran ve sıralayan bir temsilciye ihtiyaç duyar. yöntemi bu String.CompareTo karşılaştırma işlevini sağlar. Örneği çalıştırın ve sırayı gözlemleyin. Bu sıralama işlemi sıralı büyük/küçük harfe duyarlı bir sıralama kullanır. Farklı karşılaştırma kuralları belirtmek için statik String.Compare yöntemleri kullanırsınız.

List<string> lines = new List<string>
{
    @"c:\public\textfile.txt",
    @"c:\public\textFile.TXT",
    @"c:\public\Text.txt",
    @"c:\public\testfile2.txt"
};

Console.WriteLine("Non-sorted order:");
foreach (string s in lines)
{
    Console.WriteLine($"   {s}");
}

Console.WriteLine("\n\rSorted order:");

lines.Sort((left, right) => left.CompareTo(right));
foreach (string s in lines)
{
    Console.WriteLine($"   {s}");
}

Sıralandıktan sonra, dize listesi ikili arama kullanılarak aranabilir. Aşağıdaki örnek, aynı karşılaştırma işlevini kullanarak sıralanmış listede nasıl arama yapılacağını gösterir. Yerel işlev ShowWhere aranan metnin nerede olduğunu veya olacağını gösterir:

List<string> lines = new List<string>
{
    @"c:\public\textfile.txt",
    @"c:\public\textFile.TXT",
    @"c:\public\Text.txt",
    @"c:\public\testfile2.txt"
};
lines.Sort((left, right) => left.CompareTo(right));

string searchString = @"c:\public\TEXTFILE.TXT";
Console.WriteLine($"Binary search for <{searchString}>");
int result = lines.BinarySearch(searchString);
ShowWhere<string>(lines, result);

Console.WriteLine($"{(result > 0 ? "Found" : "Did not find")} {searchString}");

void ShowWhere<T>(IList<T> collection, int index)
{
    if (index < 0)
    {
        index = ~index;

        Console.Write("Not found. Sorts between: ");

        if (index == 0)
            Console.Write("beginning of sequence and ");
        else
            Console.Write($"{collection[index - 1]} and ");

        if (index == collection.Count)
            Console.WriteLine("end of sequence.");
        else
            Console.WriteLine($"{collection[index]}.");
    }
    else
    {
        Console.WriteLine($"Found at index {index}.");
    }
}

Sıralama ve arama için her zaman aynı karşılaştırma türünü kullandığınızdan emin olun. Sıralama ve arama için farklı karşılaştırma türlerinin kullanılması beklenmeyen sonuçlara neden olur.

, ve System.Collections.Generic.List<T> gibi System.Collections.HashtableSystem.Collections.Generic.Dictionary<TKey,TValue>koleksiyon sınıflarının, öğelerin veya anahtarların türü olduğunda parametre System.StringComparer alan oluşturucuları vardırstring. Genel olarak, mümkün olduğunda bu oluşturucuları kullanmalı ve veya StringComparer.OrdinalIgnoreCasebelirtmelisinizStringComparer.Ordinal.

Ayrıca bkz.