Обратный регистр всех буквенных символов в строке C #

Каков самый простой способ изменить регистр всех буквенных символов в строке C #? Например, «aBc1 $;» должен стать "AbC1 $;" Я мог бы легко написать метод, который делает это, но я надеюсь, что вызов библиотеки, о котором я не знаю, упростил бы это. Я также хотел бы избежать списка всех известных буквенных символов и сравнения каждого символа с тем, что находится в списке. Может быть, это можно сделать с помощью регулярных выражений, но я их не очень хорошо знаю. Спасибо.

Спасибо за помощь. Я создал для этого метод расширения строки, который в основном вдохновлен решением Энтони Пеграма, но без LINQ. Я думаю, что это обеспечивает хороший баланс между удобочитаемостью и производительностью. Вот что я придумал.

public static string SwapCase(this string source) {
    char[] caseSwappedChars = new char[source.Length];
    for(int i = 0; i < caseSwappedChars.Length; i++) {
        char c = source[i];
        if(char.IsLetter(c)) {
            caseSwappedChars[i] =
                char.IsUpper(c) ? char.ToLower(c) : char.ToUpper(c);
        } else {
            caseSwappedChars[i] = c;
        }
    }
    return new string(caseSwappedChars);
}

person still_dreaming_1    schedule 10.09.2010    source источник
comment
Примечание: некоторые примечания к интернационализации в моем ответе.   -  person ErikE    schedule 10.09.2010


Ответы (9)


Вы можете сделать это в строке с LINQ. Один способ:

string input = "aBc1$";
string reversedCase = new string(
    input.Select(c => char.IsLetter(c) ? (char.IsUpper(c) ?
                      char.ToLower(c) : char.ToUpper(c)) : c).ToArray());
person Anthony Pegram    schedule 10.09.2010

Если вас не волнует интернационализация:

string input = "aBc1$@[\\]^_{|{~";
Encoding enc = new System.Text.ASCIIEncoding();
byte[] b = enc.GetBytes(input);
for (int i = input.Length - 1; i >= 0; i -= 1) {
   if ((b[i] & 0xdf) >= 65 && (b[i] & 0xdf) <= 90) { //check if alpha
      b[i] ^= 0x20; // then XOR the correct bit to change case
   }
}
Console.WriteLine(input);
Console.WriteLine(enc.GetString(b));

Если, с другой стороны, вы ДЕЙСТВИТЕЛЬНО заботитесь об интернационализации, вы захотите передать CultureInfo.InvariantCulture функциям ToUpper () и ToLower () ...

person ErikE    schedule 10.09.2010
comment
Это хороший трюк с XOR, о котором многие не знают. Любая буква XOR с 32 (0x20) приведет к обратному регистру. - person Kibbee; 10.09.2010
comment
@Kibbee, спасибо за объяснение. Я, наверное, должен был написать в своем посте. Во всяком случае, этот трюк работает только с обычными старыми символами ASCII ... - person ErikE; 10.09.2010

Вы могли бы сделать это по-старому, если не знаете LINQ.

static string InvertCasing(string s)
{
    char[] c = s.ToCharArray();
    char[] cUpper = s.ToUpper().ToCharArray();
    char[] cLower = s.ToLower().ToCharArray();

    for (int i = 0; i < c.Length; i++)
    {
        if (c[i] == cUpper[i])
        {
            c[i] = cLower[i];
        }
        else
        {
            c[i] = cUpper[i];
        }
    }

    return new string(c);
}
person Michael Covelli    schedule 10.09.2010

Вот подход с регулярным выражением:

string input = "aBcdefGhI123jKLMo$";
string result = Regex.Replace(input, "[a-zA-Z]",
                            m => Char.IsUpper(m.Value[0]) ?
                                 Char.ToLower(m.Value[0]).ToString() :
                                 Char.ToUpper(m.Value[0]).ToString());
Console.WriteLine("Original: " + input);
Console.WriteLine("Modified: " + result);

Вы можете использовать Char.Parse(m.Value) как альтернативу m.Value[0]. Также не забывайте использовать вместо них методы ToUpperInvariant и ToLowerInvariant. Для получения дополнительной информации см. Этот вопрос: В C # что такое разница между ToUpper () и ToUpperInvariant ()?

person Ahmad Mageed    schedule 10.09.2010

Вчера мне задали аналогичный вопрос, и мой ответ такой:

public static partial class StringExtensions {
    public static String InvertCase(this String t) {
        Func<char, String> selector=
            c => (char.IsUpper(c)?char.ToLower(c):char.ToUpper(c)).ToString();

        return t.Select(selector).Aggregate(String.Concat);
    }
}

Вы можете легко изменить сигнатуру метода, добавив параметр типа CultureInfo, и использовать его с такими методами, как char.ToUpper, для требований глобализации.

person Ken Kin    schedule 14.10.2013

Немного быстрее, чем некоторые другие методы, перечисленные здесь, и это приятно, потому что использует арифметику Char!

    var line = "someStringToSwapCase";

    var charArr = new char[line.Length];

    for (int i = 0; i < line.Length; i++)
    {
        if (line[i] >= 65 && line[i] <= 90)
        {
            charArr[i] = (char)(line[i] + 32);
        }
        else if (line[i] >= 97 && line[i] <= 122)
        {
            charArr[i] = (char)(line[i] - 32);
        }
        else
        {
            charArr[i] = line[i];
        }
    }

    var res = new String(charArr);
person Faris Zacina    schedule 28.06.2014

Я сделал метод расширения для строк, который делает именно это!

public static class InvertStringExtension
{
    public static string Invert(this string s)
    {
        char[] chars = s.ToCharArray();
        for (int i = 0; i < chars.Length; i++)
            chars[i] = chars[i].Invert();

        return new string(chars);
    }
}

public static class InvertCharExtension
{
    public static char Invert(this char c)
    {
        if (!char.IsLetter(c))
            return c;

        return char.IsUpper(c) ? char.ToLower(c) : char.ToUpper(c);
    }
}

Использовать

var hello = "hELLO wORLD";
var helloInverted = hello.Invert();

// helloInverted == "Hello World"
person Snargledorf    schedule 19.01.2017

Это поможет вам больше ... потому что здесь я не использовал функцию напрямую.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Practice
{
    class Program
    {
        static void Main(string[] args)
        {
            char[] new_str = new char[50];
            string str;
            int ch;
            Console.Write("Enter String : ");
            str = Console.ReadLine();

            for (int i = 0; i < str.Length; i++)
            {
                ch = (int)str[i];
                if (ch > 64 && ch < 91)
                {
                    ch = ch + 32;
                    new_str[i] = Convert.ToChar(ch);
                }
                else
                {
                    ch = ch - 32;
                    new_str[i] = Convert.ToChar(ch);
                }
            }
            Console.Write(new_str);

            Console.ReadKey();
        }
    }
}

Я уверен, что это сработает и для вас .. Спасибо.

person Unknown_Coder    schedule 17.04.2017

Код ниже выполняет только 2 вызова функций для каждой буквы. Вместо проверки наличия IsLetter мы просто применяем верхний / нижний регистр, если необходимо.

    string result="";
    foreach (var item in S)
        {
        if (char.ToLower(item) != item )
            result+= char.ToLower(item);
        else
            result+= char.ToUpper(item);
        }

Также можно (хотя и менее читабельно) создать дополнительную переменную и установить для нее значение char.ToLower (item) перед проверкой, заменив один вызов функции на одну дополнительную переменную, следующим образом:

    string result="";
    foreach (var item in S)
        {
        var temp=char.ToLower(item);
        if (temp != item )
            result+= temp;
        else
            result+= char.ToUpper(item);
        }
person Zuabros    schedule 15.09.2020