Преобразование строки в заголовок


300

У меня есть строка, которая содержит слова в смеси символов верхнего и нижнего регистра.

Например: string myData = "a Simple string";

Мне нужно преобразовать первый символ каждого слова (разделенных пробелами) в верхний регистр. Поэтому я хочу получить результат как:string myData ="A Simple String";

Есть ли простой способ сделать это? Я не хочу разбивать строку и делать преобразование (это будет моим последним средством). Также гарантируется, что строки на английском языке.


1
http://support.microsoft.com/kb/312890 - Как преобразовать строки в нижний, верхний или заглавный (правильный) регистр с помощью Visual C #
ttarchala

Ответы:


538

MSDN: TextInfo.ToTitleCase

Убедитесь, что вы включаете: using System.Globalization

string title = "war and peace";

TextInfo textInfo = new CultureInfo("en-US", false).TextInfo;

title = textInfo.ToTitleCase(title); 
Console.WriteLine(title) ; //War And Peace

//When text is ALL UPPERCASE...
title = "WAR AND PEACE" ;

title = textInfo.ToTitleCase(title); 
Console.WriteLine(title) ; //WAR AND PEACE

//You need to call ToLower to make it work
title = textInfo.ToTitleCase(title.ToLower()); 
Console.WriteLine(title) ; //War And Peace

37
Правда. Кроме того, если слово в верхнем регистре, оно не работает. Например: «Агент ФБР выстрелил в мою СОБАКУ» -> «Агент ФБР выстрелил в мою СОБАКУ». И это не касается "Макдональдса" и так далее.
Коби

5
@Kirschstein эта функция делает Conver эти слова в заголовке дела, несмотря на то, что они не должны быть на английском языке. Обратитесь к документации: Actual result: "War And Peace".
Коби

5
@simbolo - Я действительно упомянул об этом в комментарии ... Вы можете использовать что-то вроде text = Regex.Replace(text, @"(?<!\S)\p{Ll}", m => m.Value.ToUpper());, но это далеко не идеально. Например, он по-прежнему не обрабатывает кавычки или скобки - "(one two three)"-> "(one Two Three)". Возможно, вы захотите задать новый вопрос после того, как вы точно определите, что вы хотите делать с этими делами.
Коби

17
По какой-то причине, когда у меня есть «DR», он не становится «Dr», если я сначала не вызову .ToLower () перед вызовом ToTitleCase () ... Так что это то, что нужно остерегаться ...
Тод Томсон,

16
.ToLower () для ввода строки требуется, если вводимый текст в верхнем регистре
Puneet Ghanshani

137

Попробуй это:

string myText = "a Simple string";

string asTitleCase =
    System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.
    ToTitleCase(myText.ToLower());

Как уже указывалось, использование TextInfo.ToTitleCase может не дать вам точных результатов, которые вы хотите. Если вам нужно больше контроля над выводом, вы можете сделать что-то вроде этого:

IEnumerable<char> CharsToTitleCase(string s)
{
    bool newWord = true;
    foreach(char c in s)
    {
        if(newWord) { yield return Char.ToUpper(c); newWord = false; }
        else yield return Char.ToLower(c);
        if(c==' ') newWord = true;
    }
}

А затем используйте это так:

var asTitleCase = new string( CharsToTitleCase(myText).ToArray() );

1
Я пробовал несколько вариантов объекта TextInfo - никаких ошибок, но исходная строка (верхний регистр) никогда не обновлялась. Подключил этот метод и я очень благодарен.
JustSteve

6
@justSteve, из MSDN ( msdn.microsoft.com/en-us/library/… ): «Однако этот метод в настоящее время не обеспечивает надлежащий регистр для преобразования полностью прописного слова, такого как аббревиатура» - вам, вероятно, следует сначала просто ToLower () (я знаю, что он старый, но на тот случай, если кто-то еще наткнется на него и
удивится,

Доступно только для .NET Framework 4.7.2 <= ваша фреймворк <= .NET Core 2.0
Пол Горбас

70

Еще один вариант. Основываясь на нескольких советах, я сократил его до этого метода расширения, который отлично подходит для моих целей:

public static string ToTitleCase(this string s) =>
    CultureInfo.InvariantCulture.TextInfo.ToTitleCase(s.ToLower());

8
CultureInfo.InvariantCulture.TextInfo.ToTitleCase (s.ToLower ()); было бы лучше подходит на самом деле!
Пунит Гханшани

Доступно только для .NET Framework 4.7.2 <= ваша фреймворк <= .NET Core 2.0
Пол Горбас

Поскольку мы используем InvariantCulture для TitleCasing, вместо s.ToLower () следует использовать s.ToLowerInvariant ().
Vinigas

27

Лично я попробовал TextInfo.ToTitleCaseметод, но я не понимаю, почему он не работает, когда все символы в верхнем регистре.

Хотя мне нравится функция util, предоставляемая Winston Smith , позвольте мне предоставить функцию, которую я сейчас использую:

public static String TitleCaseString(String s)
{
    if (s == null) return s;

    String[] words = s.Split(' ');
    for (int i = 0; i < words.Length; i++)
    {
        if (words[i].Length == 0) continue;

        Char firstChar = Char.ToUpper(words[i][0]); 
        String rest = "";
        if (words[i].Length > 1)
        {
            rest = words[i].Substring(1).ToLower();
        }
        words[i] = firstChar + rest;
    }
    return String.Join(" ", words);
}

Игра с некоторыми тестовыми строками:

String ts1 = "Converting string to title case in C#";
String ts2 = "C";
String ts3 = "";
String ts4 = "   ";
String ts5 = null;

Console.Out.WriteLine(String.Format("|{0}|", TitleCaseString(ts1)));
Console.Out.WriteLine(String.Format("|{0}|", TitleCaseString(ts2)));
Console.Out.WriteLine(String.Format("|{0}|", TitleCaseString(ts3)));
Console.Out.WriteLine(String.Format("|{0}|", TitleCaseString(ts4)));
Console.Out.WriteLine(String.Format("|{0}|", TitleCaseString(ts5)));

Давать вывод :

|Converting String To Title Case In C#|
|C|
||
|   |
||

1
@harsh: «уродливое» решение, я бы сказал ... для меня не имеет смысла, что сначала нужно преобразовать всю строку в нижний регистр.
Луис Кихада

4
Это сделано намеренно, потому что, если вы попросите, скажем, «ЮНИСЕФ и благотворительность» указать название, вы не захотите менять его на «ЮНИСЕФ».
Кейси

4
Таким образом, вместо того, чтобы вызывать ToLower()всю строку, вы бы предпочли выполнить всю эту работу самостоятельно и вызывать одну и ту же функцию для каждого отдельного символа? Это не только уродливое решение, оно дает нулевую выгоду и даже займет больше времени, чем встроенная функция.
крильгар

3
rest = words[i].Substring(1).ToLower();
крильгар

1
@ruffin No. подстрока с одиночным начинается параметр INT в данном индексе, и возвращает все до конца строки.
крильгар

21

Недавно я нашел лучшее решение.

Если ваш текст содержит каждую букву в верхнем регистре, TextInfo не будет преобразовывать его в соответствующий регистр. Мы можем исправить это, используя функцию нижнего регистра внутри:

public static string ConvertTo_ProperCase(string text)
{
    TextInfo myTI = new CultureInfo("en-US", false).TextInfo;
    return myTI.ToTitleCase(text.ToLower());
}

Теперь это преобразует все, что входит в Propercase.


17
public static string PropCase(string strText)
{
    return new CultureInfo("en").TextInfo.ToTitleCase(strText.ToLower());
}

1
Мне нравится, что вы добавили ToLower до ToTitleCase, охватывает ситуацию, когда входной текст все заглавными буквами.
Джоэлк

7

Если кто-то заинтересован в решении для Compact Framework:

return String.Join(" ", thestring.Split(' ').Select(i => i.Substring(0, 1).ToUpper() + i.Substring(1).ToLower()).ToArray());

С интерполяцией строки: вернуть string.Join ("", text.Split ('') .Select (i => $ "{i.Substring (0, 1) .ToUpper ()} {i.Substring (1). ToLower ()} ") .ToArray ());
Тед

6

Вот решение этой проблемы ...

CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
TextInfo textInfo = cultureInfo.TextInfo;
string txt = textInfo.ToTitleCase(txt);

5

Используйте ToLower()сначала, чем CultureInfo.CurrentCulture.TextInfo.ToTitleCaseна результат, чтобы получить правильный вывод.

    //---------------------------------------------------------------
    // Get title case of a string (every word with leading upper case,
    //                             the rest is lower case)
    //    i.e: ABCD EFG -> Abcd Efg,
    //         john doe -> John Doe,
    //         miXEd CaSING - > Mixed Casing
    //---------------------------------------------------------------
    public static string ToTitleCase(string str)
    {
        return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(str.ToLower());
    }

3

Мне нужен был способ справиться со всеми заглавными словами, и мне понравилось решение Рикки А.Х., но я сделал шаг вперед, чтобы реализовать его как метод расширения. Это позволяет избежать необходимости создавать свой массив символов, а затем каждый раз явно вызывать для него ToArray - так что вы можете просто вызвать его в строке, например:

использование:

string newString = oldString.ToProper();

код:

public static class StringExtensions
{
    public static string ToProper(this string s)
    {
        return new string(s.CharsToTitleCase().ToArray());
    }

    public static IEnumerable<char> CharsToTitleCase(this string s)
    {
        bool newWord = true;
        foreach (char c in s)
        {
            if (newWord) { yield return Char.ToUpper(c); newWord = false; }
            else yield return Char.ToLower(c);
            if (c == ' ') newWord = true;
        }
    }

}

1
Просто добавили еще одно условие ИЛИ, если (c == '' || c == '\' ') ... иногда имена содержат апострофы (').
JSK

2

Это лучше понять, попробовав собственный код ...

Читать далее

http://www.stupidcodes.com/2014/04/convert-string-to-uppercase-proper-case.html

1) Преобразовать строку в верхний регистр

string lower = "converted from lowercase";
Console.WriteLine(lower.ToUpper());

2) Преобразовать строку в нижний регистр

string upper = "CONVERTED FROM UPPERCASE";
Console.WriteLine(upper.ToLower());

3) Преобразовать строку в TitleCase

    CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
    TextInfo textInfo = cultureInfo.TextInfo;
    string txt = textInfo.ToTitleCase(TextBox1.Text());

1

Вот реализация, символ за символом. Должен работать с "(Один Два Три)"

public static string ToInitcap(this string str)
{
    if (string.IsNullOrEmpty(str))
        return str;
    char[] charArray = new char[str.Length];
    bool newWord = true;
    for (int i = 0; i < str.Length; ++i)
    {
        Char currentChar = str[i];
        if (Char.IsLetter(currentChar))
        {
            if (newWord)
            {
                newWord = false;
                currentChar = Char.ToUpper(currentChar);
            }
            else
            {
                currentChar = Char.ToLower(currentChar);
            }
        }
        else if (Char.IsWhiteSpace(currentChar))
        {
            newWord = true;
        }
        charArray[i] = currentChar;
    }
    return new string(charArray);
}

1
String TitleCaseString(String s)
{
    if (s == null || s.Length == 0) return s;

    string[] splits = s.Split(' ');

    for (int i = 0; i < splits.Length; i++)
    {
        switch (splits[i].Length)
        {
            case 1:
                break;

            default:
                splits[i] = Char.ToUpper(splits[i][0]) + splits[i].Substring(1);
                break;
        }
    }

    return String.Join(" ", splits);
}

1

Вы можете напрямую изменить текст или строку на правильные, используя этот простой метод, после проверки на наличие нулевых или пустых значений строки для устранения ошибок:

public string textToProper(string text)
{
    string ProperText = string.Empty;
    if (!string.IsNullOrEmpty(text))
    {
        ProperText = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(text);
    }
    else
    {
        ProperText = string.Empty;
    }
    return ProperText;
}

0

Попробуй это:

using System.Globalization;
using System.Threading;
public void ToTitleCase(TextBox TextBoxName)
        {
            int TextLength = TextBoxName.Text.Length;
            if (TextLength == 1)
            {
                CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
                TextInfo textInfo = cultureInfo.TextInfo;
                TextBoxName.Text = textInfo.ToTitleCase(TextBoxName.Text);
                TextBoxName.SelectionStart = 1;
            }
            else if (TextLength > 1 && TextBoxName.SelectionStart < TextLength)
            {
                int x = TextBoxName.SelectionStart;
                CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
                TextInfo textInfo = cultureInfo.TextInfo;
                TextBoxName.Text = textInfo.ToTitleCase(TextBoxName.Text);
                TextBoxName.SelectionStart = x;
            }
            else if (TextLength > 1 && TextBoxName.SelectionStart >= TextLength)
            {
                CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
                TextInfo textInfo = cultureInfo.TextInfo;
                TextBoxName.Text = textInfo.ToTitleCase(TextBoxName.Text);
                TextBoxName.SelectionStart = TextLength;
            }
        }


Вызовите этот метод в событии TextChanged TextBox.


0

Я использовал вышеуказанные ссылки и полное решение:

Use Namespace System.Globalization;
string str="INFOA2Z means all information";

// Нужен результат типа «Infoa2z означает всю информацию»
// Нам нужно также преобразовать строку в нижний регистр, иначе она не будет работать должным образом.

TextInfo ProperCase= new CultureInfo("en-US", false).TextInfo;

str= ProperCase.ToTitleCase(str.toLower());

http://www.infoa2z.com/asp.net/change-string-to-proper-case-in-an-asp.net-using-c#


0

Это то, что я использую, и это работает в большинстве случаев, если пользователь не решит переопределить его, нажав Shift или Caps Lock. Как на клавиатурах Android и iOS.

Private Class ProperCaseHandler
    Private Const wordbreak As String = " ,.1234567890;/\-()#$%^&*€!~+=@"
    Private txtProperCase As TextBox

    Sub New(txt As TextBox)
        txtProperCase = txt
        AddHandler txt.KeyPress, AddressOf txtTextKeyDownProperCase
    End Sub

    Private Sub txtTextKeyDownProperCase(ByVal sender As System.Object, ByVal e As Windows.Forms.KeyPressEventArgs)
        Try
            If Control.IsKeyLocked(Keys.CapsLock) Or Control.ModifierKeys = Keys.Shift Then
                Exit Sub
            Else
                If txtProperCase.TextLength = 0 Then
                    e.KeyChar = e.KeyChar.ToString.ToUpper()
                    e.Handled = False
                Else
                    Dim lastChar As String = txtProperCase.Text.Substring(txtProperCase.SelectionStart - 1, 1)

                    If wordbreak.Contains(lastChar) = True Then
                        e.KeyChar = e.KeyChar.ToString.ToUpper()
                        e.Handled = False
                    End If
                End If

            End If

        Catch ex As Exception
            Exit Sub
        End Try
    End Sub
End Class

0

Для тех, кто хочет сделать это автоматически при нажатии клавиш, я сделал это с помощью следующего кода в vb.net на пользовательском элементе управления textbox - очевидно, вы также можете сделать это с помощью обычного textbox - но мне нравится возможность добавлять повторяющийся код для определенных элементов управления с помощью пользовательских элементов управления это соответствует концепции ООП.

Imports System.Windows.Forms
Imports System.Drawing
Imports System.ComponentModel

Public Class MyTextBox
    Inherits System.Windows.Forms.TextBox
    Private LastKeyIsNotAlpha As Boolean = True
    Protected Overrides Sub OnKeyPress(e As KeyPressEventArgs)
        If _ProperCasing Then
            Dim c As Char = e.KeyChar
            If Char.IsLetter(c) Then
                If LastKeyIsNotAlpha Then
                    e.KeyChar = Char.ToUpper(c)
                    LastKeyIsNotAlpha = False
                End If
            Else
                LastKeyIsNotAlpha = True
            End If
        End If
        MyBase.OnKeyPress(e)
End Sub
    Private _ProperCasing As Boolean = False
    <Category("Behavior"), Description("When Enabled ensures for automatic proper casing of string"), Browsable(True)>
    Public Property ProperCasing As Boolean
        Get
            Return _ProperCasing
        End Get
        Set(value As Boolean)
            _ProperCasing = value
        End Set
    End Property
End Class

0

Прекрасно работает даже в случае с верблюдом: «SomeText in YourPage»

public static class StringExtensions
{
    /// <summary>
    /// Title case example: 'Some Text In Your Page'.
    /// </summary>
    /// <param name="text">Support camel and title cases combinations: 'someText in YourPage'</param>
    public static string ToTitleCase(this string text)
    {
        if (string.IsNullOrEmpty(text))
        {
            return text;
        }
        var result = string.Empty;
        var splitedBySpace = text.Split(new[]{ ' ' }, StringSplitOptions.RemoveEmptyEntries);
        foreach (var sequence in splitedBySpace)
        {
            // let's check the letters. Sequence can contain even 2 words in camel case
            for (var i = 0; i < sequence.Length; i++)
            {
                var letter = sequence[i].ToString();
                // if the letter is Big or it was spaced so this is a start of another word
                if (letter == letter.ToUpper() || i == 0)
                {
                    // add a space between words
                    result += ' ';
                }
                result += i == 0 ? letter.ToUpper() : letter;
            }
        }            
        return result.Trim();
    }
}

0

Как метод расширения:

/// <summary>
//     Returns a copy of this string converted to `Title Case`.
/// </summary>
/// <param name="value">The string to convert.</param>
/// <returns>The `Title Case` equivalent of the current string.</returns>
public static string ToTitleCase(this string value)
{
    string result = string.Empty;

    for (int i = 0; i < value.Length; i++)
    {
        char p = i == 0 ? char.MinValue : value[i - 1];
        char c = value[i];

        result += char.IsLetter(c) && ((p is ' ') || p is char.MinValue) ? $"{char.ToUpper(c)}" : $"{char.ToLower(c)}";
    }

    return result;
}

Использование:

"kebab is DELICIOU's   ;d  c...".ToTitleCase();

Результат:

Kebab Is Deliciou's ;d C...


0

Альтернатива со ссылкой на Microsoft.VisualBasic(обрабатывает строчные буквы тоже):

string properCase = Strings.StrConv(str, VbStrConv.ProperCase);

0

Без использования TextInfo:

public static string TitleCase(this string text, char seperator = ' ') =>
  string.Join(seperator, text.Split(seperator).Select(word => new string(
    word.Select((letter, i) => i == 0 ? char.ToUpper(letter) : char.ToLower(letter)).ToArray())));

Он перебирает каждую букву в каждом слове, преобразуя его в верхний регистр, если это первая буква, иначе преобразуя его в нижний регистр.


-1

Я знаю, что это старый вопрос, но я искал то же самое для C, и я понял это, поэтому я решил опубликовать его, если кто-то другой ищет путь в C:

char proper(char string[]){  

int i = 0;

for(i=0; i<=25; i++)
{
    string[i] = tolower(string[i]);  //converts all character to lower case
    if(string[i-1] == ' ') //if character before is a space 
    {
        string[i] = toupper(string[i]); //converts characters after spaces to upper case
    }

}
    string[0] = toupper(string[0]); //converts first character to upper case


    return 0;
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.