Як я можу писати великі літери імені та прізвища на C #?


141

Чи є простий спосіб написання великої літери першого рядка і опустити решту? Чи є вбудований метод або мені потрібно зробити свій власний?


3
Я нічого не знаю про вашу конкретну програму, але, думаю, загальне попередження: програмістам не слід застосовувати цей метод вольово-невольно до справжніх імен. Я думаю, що старий Джон Макдональд був би засмучений цим методом, маніпулюючи своїм ім'ям, не кажучи вже про ей Кеммінг, дзвіночки, данах бойд, 松本 行 弘, людей з прізвищем "фон", людей з прізвищем "О'Дойл" і т. д. і т. д. тощо. Більшість імен не мають формату "Перше останнє" з такою великою літери (і з великої літери); Рекомендую прочитати kalzumeus.com/2010/06/17/…
Нік

@Nick абсолютно прав. Ви навіть не можете припустити, що нижній регістр, у якому йде верхній регістр, є неправильним - ірландські назви роблять такі речі, як "A hAirt". Припустимо, що для будь-якої конвенції, яку ви можете придумати вгору, буде культура / мова, яка вас здивує.
Джеймс Мур

Відповіді:


259

TextInfo.ToTitleCase()використовує великі літери у кожному символі рядка.
Якщо немає потреби в підтримці Acronim Uppercasing, тоді слід включити ToLower().

string s = "JOHN DOE";
s = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(s.ToLower());
// Produces "John Doe"

Якщо CurrentCulture недоступна, використовуйте:

string s = "JOHN DOE";
s = new System.Globalization.CultureInfo("en-US", false).TextInfo.ToTitleCase(s.ToLower());

Дивіться MSDN Посилання для докладного опису.


24
Тут слід зауважити, що він не працює, якщо рядок є всіма великими літерами. Він вважає, що всі шапки - це абревіатура.
Майк Рооза

9
Те, що я бачив із багатьма з них, - це те, що ти не можеш покластися на них. Це не спрацює, якщо ім'я щось на кшталт Маккейна або якщо ви почнете вражати більше іноземних імен.
Майк Уіллз

25
@roosa - просте виправлення для ToTitleCase (val.ToLower ())
Simon_Weaver

+1 Я знав, що це вже повинно бути в FCL, і google привів мене сюди = D
gideon

13
На відміну від відповіді Натана нижче, я отримую помилку: "На жаль, потрібне посилання на об'єкт для нестатичного поля, методу чи властивості .......", на жаль.
Dan W

117
CultureInfo.CurrentCulture.TextInfo.ToTitleCase("hello world");

Aww оснастка! Хороша відповідь. Я завжди забуваю про речі глобалізації.
Майкл Харен

Чудове рішення! У VB.Net:sItem = Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(sItem.ToLower) 'first char upper case
Nasenbaer

Вам потрібно виявити культуру кожного окремого імені , а не сучасну культуру. Це не працює для імен.
Джеймс Мур

1
Оскільки це спирається на те CurrentCulture, як ми можемо бути впевнені, що немає культури, яка б вирішувала це по-різному?
Рудей

30
String test = "HELLO HOW ARE YOU";
string s = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(test);

Вищеописаний код не працює .....

тому покладіть наведений нижче код, перетворивши на нижчий, а потім застосуйте функцію

String test = "HELLO HOW ARE YOU";
string s = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(test.ToLower());

15

Є деякі випадки, з якими CultureInfo.CurrentCulture.TextInfo.ToTitleCaseне вдається впоратися, наприклад: апостроф '.

string input = CultureInfo.CurrentCulture.TextInfo.ToTitleCase("o'reilly, m'grego, d'angelo");
// input = O'reilly, M'grego, D'angelo

Регулярний вираз може також використовуватися , \b[a-zA-Z]щоб визначити початковий символ слова після того, як кордонів слова \b, то нам потрібно просто замінити матч на його верхньому завдяки випадку еквівалентності до Regex.Replace(string input,string pattern,MatchEvaluator evaluator)методу:

string input = "o'reilly, m'grego, d'angelo";
input = Regex.Replace(input.ToLower(), @"\b[a-zA-Z]", m => m.Value.ToUpper());
// input = O'Reilly, M'Grego, D'Angelo

Регулярний вираз може бути налаштоване при необхідності, наприклад, якщо ми хочемо , щоб обробляти MacDonaldі McFryвипадки регулярного виразу стає:(?<=\b(?:mc|mac)?)[a-zA-Z]

string input = "o'reilly, m'grego, d'angelo, macdonald's, mcfry";
input = Regex.Replace(input.ToLower(), @"(?<=\b(?:mc|mac)?)[a-zA-Z]", m => m.Value.ToUpper());
// input = O'Reilly, M'Grego, D'Angelo, MacDonald'S, McFry

Якщо нам потрібно обробити більше префіксів, нам потрібно лише змінити групу (?:mc|mac), наприклад додати французькі префікси du, de:(?:mc|mac|du|de) .

Нарешті, ми можемо зрозуміти, що цей регулярний вираз також буде відповідати випадку MacDonald'Sостаннього, 'sтому нам потрібно обробити його в регулярному виразі з негативним поглядом ззаду (?<!'s\b). Наприкінці ми маємо:

string input = "o'reilly, m'grego, d'angelo, macdonald's, mcfry";
input = Regex.Replace(input.ToLower(), @"(?<=\b(?:mc|mac)?)[a-zA-Z](?<!'s\b)", m => m.Value.ToUpper());
// input = O'Reilly, M'Grego, D'Angelo, MacDonald's, McFry

@polkduran Я намагаюся знайти спосіб розібратися з римськими цифрами в кінці назви; Я хотів би зробити їх великими літерами: Джон Сміт III. Чи заважатиме цьому негативний огляд?
Метт

Як завжди, я нарешті змогла відповісти на власне запитання. Я додав необов'язкову групу, щоб відповідати римським цифрам (які будуть мати верхній регістр). Ось повний регулярний вираз, який я зараз використовую: (? <= \ B (?: Mc | mac)?) [A-zA-Z] (? <! S \ b) (?: ii | iii | iv | v | vi | vii | viii | ix)?
Метт

Ваш випадок - особливий, регулярний вираз у відповіді трактує кожне ім’я (прізвище) як відокремлене слово у вхідному рядку (тестовий рядок має кілька імен), тому в ньому немає поняття "кінець імені" . Якщо ви ставитеся до вхідного рядка як до одного імені, ви можете встановити регулярний вираз з простою умовою, щоб вирішити ваш випадок: \b[ivxlcdm]+$|так у вас є \b[ivxlcdm]+$|(?<=\b(?:mc|mac)?)[a-zA-Z](?<!'s\b). Це зробить непомітними всі закінчувальні слова імені, що мають не строгий римський цифровий формат ( ivxlcdm). Однак у вас можуть бути деякі небажані результати, наприклад, "Li" стане "LI"
polkduran

Цікаво. Я думаю, що ваше доповнення, мабуть, більш правильне щодо структури, але я згоден ... Я думаю, що ви будете заявляти деякі проблеми. У своєму рішенні вище я жорстко кодував суфікси до "ix", які працюватимуть у моєму випадку, але я визнаю, що не підходить для всіх.
Метт

1
@ Si8, ти це випробував? Regex.Replace("JOHN DOE".ToLower(), @"(?<=\b(?:mc|mac)?)[a-zA-Z](?<!'s\b)", m => m.Value.ToUpper())
полкдуран

7

Мак і Мак - поширені префікси прізвища по всій території США, є й інші. TextInfo.ToTitleCase не обробляє ці випадки і не повинен використовуватися для цього. Ось як я це роблю:

    public static string ToTitleCase(string str)
    {
        string result = str;
        if (!string.IsNullOrEmpty(str))
        {
            var words = str.Split(' ');
            for (int index = 0; index < words.Length; index++)
            {
                var s = words[index];
                if (s.Length > 0)
                {
                    words[index] = s[0].ToString().ToUpper() + s.Substring(1);
                }
            }
            result = string.Join(" ", words);
        }
        return result;
    }


4

Найбільш прямим варіантом буде використання функції ToTitleCase , доступної в .NET, яка повинна піклуватися про ім'я більшу частину часу. Як ред зазначав , є деякі імена, для яких це не буде працювати, але вони досить рідкісні, тому, якщо ви не орієнтуєтесь на культуру, де такі імена є загальними, не потрібно щось, про що ви повинні занадто переживати.

Однак якщо ви не працюєте з мовою .NET, то це залежить від того, як виглядає вхід - якщо у вас є два окремих поля для імені та прізвища, ви можете просто з великої літери першою літерою зменшити іншу частину, використовуючи підрядки.

firstName = firstName.Substring(0, 1).ToUpper() + firstName.Substring(1).ToLower();
lastName = lastName.Substring(0, 1).ToUpper() + lastName.Substring(1).ToLower();

Однак якщо вам надано кілька імен як частину одного рядка, тоді вам потрібно знати, як ви отримуєте інформацію та розділяти її відповідно. Отже, якщо ви отримуєте ім'я типу "Джон Доу", ви розділите рядок на основі символу пробілу. Якщо він у такому форматі, як "Doe, John", вам потрібно буде розділити його на основі коми. Однак, як тільки ви розділите його, ви просто застосуйте код, показаний раніше.


3

CultureInfo.CurrentCulture.TextInfo.ToTitleCase ("моє ім'я");

повертається ~ Моє ім'я

Але проблема як і раніше, існує з такими іменами, як McFly.


3
Макфрі! Конічіва, містер Фугіцу-сан
Ян Бойд

@David C Спробуйте замінити простір на null !! як string.replace ('', '')
Чінтан

3

Я використовую власний метод, щоб виправити це:

Наприклад фраза: "привіт, світ. Привіт, це світ потокового потоку". буде "Привіт, світ. Привіт, це світ Стакковерф". " Regex \ b (початок слова) \ w (перший характер слова) зробить трюк.

/// <summary>
/// Makes each first letter of a word uppercase. The rest will be lowercase
/// </summary>
/// <param name="Phrase"></param>
/// <returns></returns>
public static string FormatWordsWithFirstCapital(string Phrase)
{
     MatchCollection Matches = Regex.Matches(Phrase, "\\b\\w");
     Phrase = Phrase.ToLower();
     foreach (Match Match in Matches)
         Phrase = Phrase.Remove(Match.Index, 1).Insert(Match.Index, Match.Value.ToUpper());

     return Phrase;
}

2

Пропозиції щодо використання ToTitleCase не працюватимуть для рядків, які є великим регістром. Тож вам доведеться зателефонувати ToUpper за першим символом та ToLower на інших символах.


6
Чому б не зателефонувати ToLower у рядок введення, перш ніж викликати ToTitleCase?
Енді Роуз

2

Цей клас робить трюк. Ви можете додати нові префікси до масиву статичних рядків _prefixes .

public static class StringExtensions
{
        public static string ToProperCase( this string original )
        {
            if( String.IsNullOrEmpty( original ) )
                return original;

            string result = _properNameRx.Replace( original.ToLower( CultureInfo.CurrentCulture ), HandleWord );
            return result;
        }

        public static string WordToProperCase( this string word )
        {
            if( String.IsNullOrEmpty( word ) )
                return word;

            if( word.Length > 1 )
                return Char.ToUpper( word[0], CultureInfo.CurrentCulture ) + word.Substring( 1 );

            return word.ToUpper( CultureInfo.CurrentCulture );
        }

        private static readonly Regex _properNameRx = new Regex( @"\b(\w+)\b" );
        private static readonly string[] _prefixes = {
                                                         "mc"
                                                     };

        private static string HandleWord( Match m )
        {
            string word = m.Groups[1].Value;

            foreach( string prefix in _prefixes )
            {
                if( word.StartsWith( prefix, StringComparison.CurrentCultureIgnoreCase ) )
                    return prefix.WordToProperCase() + word.Substring( prefix.Length ).WordToProperCase();
            }

            return word.WordToProperCase();
        }
}

1

Якщо ви використовуєте vS2k8, ви можете використовувати метод розширення, щоб додати його до класу String:

public static string FirstLetterToUpper(this String input)
{
    return input = input.Substring(0, 1).ToUpper() + 
       input.Substring(1, input.Length - 1);
}

9
Char.ToUpper(input[0]) + input.Substring(1)є більш читаним IMHO.
Хосам Алі

ІМХО input.FirstLetterToUpper(), звичайно , більш читабельним проти Char.ToUpper(input[0]) + input.Substring(1), але менш прозорим
Michael

0

Щоб вирішити деякі проблеми / проблеми, які були висвітлені, я б запропонував перетворити рядок у нижній регістр, а потім зателефонувати в метод ToTitleCase. Потім ви можете використовувати IndexOf ("Mc") або IndexOf ("O \" ") для визначення спеціальних випадків, які потребують більш конкретної уваги.

inputString = inputString.ToLower();
inputString = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(inputString);
int indexOfMc = inputString.IndexOf(" Mc");
if(indexOfMc  > 0)
{
   inputString.Substring(0, indexOfMc + 3) + inputString[indexOfMc + 3].ToString().ToUpper() + inputString.Substring(indexOfMc + 4);
}

0

Мені подобається такий спосіб:

using System.Globalization;
...
TextInfo myTi = new CultureInfo("en-Us",false).TextInfo;
string raw = "THIS IS ALL CAPS";
string firstCapOnly = myTi.ToTitleCase(raw.ToLower());

Піднято з цієї статті MSDN .


0

Сподіваюся, це вам допоможе.

String fName = "firstname";
String lName = "lastname";
String capitalizedFName = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(fName);
String capitalizedLName = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(lName);

0
 public static string ConvertToCaptilize(string input)
        {
            if (!string.IsNullOrEmpty(input))
            {
                string[] arrUserInput = input.Split(' ');


                // Initialize a string builder object for the output
                StringBuilder sbOutPut = new StringBuilder();


                // Loop thru each character in the string array
                foreach (string str in arrUserInput)
                {
                    if (!string.IsNullOrEmpty(str))
                    {
                        var charArray = str.ToCharArray();
                        int k = 0;
                        foreach (var cr in charArray)
                        {
                            char c;
                            c = k == 0 ? char.ToUpper(cr) : char.ToLower(cr);
                            sbOutPut.Append(c);
                            k++;
                        }


                    }
                    sbOutPut.Append(" ");
                }
                return sbOutPut.ToString();
            }
            return string.Empty;

        }

-1

Як зазначено в edg, вам знадобиться більш складний алгоритм для обробки спеціальних імен (це, мабуть, тому багато місць примушують все до верхнього регістру).

Щось подібне до цього неперевіреного c # має обробляти простий випадок, який ви запитували:

public string SentenceCase(string input)
{
    return input(0, 1).ToUpper + input.Substring(1).ToLower;
}

Забудьте про це - використовуйте клас глобалізації stackoverflow.com/questions/72831/…
Майкл Харен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.