如何在C#中将大写的名字和姓氏大写?


141

有没有一种简单的方法可以大写字符串的第一个字母并降低其余的字母?是否有内置方法或需要自己制作?


3
我对您的特定应用程序一无所知,但我认为应该发出一般警告:程序员不应将这种方法随意地应用于实名。我认为老约翰·麦克唐纳(John MacDonald)会打乱他的名字,更不用说ee cummings,铃铛钩,danah boyd,松本行弘,姓有“ von”的人,姓是“ O'Doyle”的人等等。等等。大多数名称的格式都不是首字母大写(且大写的字符);我建议阅读kalzumeus.com/2010/06/17/…–
尼克(Nick)

@尼克是绝对正确的。您甚至不能假设小写字母后跟大写字母是错误的-爱尔兰名称的用法类似于“ÓhAirt”。假设对于任何约定,您都可以想到,那么就会有一种文化/语言会让您感到惊讶。
詹姆斯·摩尔

Answers:


259

TextInfo.ToTitleCase()将字符串的每个标记中的第一个字符大写。
如果不需要维护首字母缩写词大写,则应包括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
这里要注意的一件事是,如果字符串全为大写字母,则该字符串不起作用。它认为所有大写字母都是首字母缩写。
Mike Roosa

9
我看到的很多东西是您不能依靠它们。如果名称像麦凯恩(McCain)或您开始使用更多外国名称,那将是行不通的。
Mike Wills

25
@roosa-轻松解决该ToTitleCase(val.ToLower())
Simon_Weaver,2009年

+1我知道它必须已经在FCL中,并且google将我带到这里= D
gideon 2010年

13
与下面的Nathan答案不同,我得到一个错误:“不幸的是,非静态字段,方法或属性......需要对象引用。”
丹W

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

糟糕!好答案。我总是忘记全球化的东西。
Michael Haren's

很好的解决方案!在VB.Net中:sItem = Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(sItem.ToLower) 'first char upper case
Nasenbaer

您需要检测每个个人名称的区域性,而不是当前区域性。这不适用于名称。
詹姆斯·摩尔

1
由于这依赖于CurrentCulture,我们如何确定没有文化来对此进行不同的处理?
2014年

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

正则表达式可以根据需要,进行调整,例如,如果我们要处理MacDonaldMcFry案件的正则表达式变为:(?<=\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我正在努力寻找一种在名称末尾处理罗马数字的方法;我想将它们全部大写:John Smith III。负面的后视会干扰这一点吗?
马特

像往常一样,我终于能够回答自己的问题。我添加了一个可选的组来匹配罗马数字(将变为大写)。这是我现在使用的完整正则表达式:(?<= \ b(?:mc | mac)?)[a-zA-Z](?<!'s \ b)(?: ii | iii | iv | v | vi | vii | viii | ix)?
马特

您的情况是一种特殊情况,答案中的正则表达式将每个名称(姓氏)视为输入字符串(测试输入字符串具有多个名称)中的孤立词,因此它没有“名称结尾”的概念。如果您将输入字符串当作一个单独的名称,则可以为regex加上一个简单的条件以处理您的情况:\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())
polkduran

7

Mc和Mac是全美通用的姓氏前缀,还有其他一些姓氏。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

最直接的选择是使用.NET中提供的ToTitleCase函数,该函数在大多数情况下应使用该名称。作为edg指出的那样,有些名称将不起作用,但是这些名称很少见,因此,除非您针对的是这样的名称很普遍的文化,否则不必担心太多。

但是,如果您不使用.NET语言,则取决于输入的样子-如果您的名字和姓氏有两个单独的字段,则可以使用以下方式将大写的首字母大写子字符串。

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

但是,如果在同一字符串中为您提供了多个名称,那么您需要知道如何获取信息并相应地进行拆分。因此,如果您得到一个像“ John Doe”的名字,您将根据空格字符分割字符串。如果采用“ Doe,John”之类的格式,则需要根据逗号进行拆分。但是,一旦将其拆分,就可以应用前面显示的代码。


3

CultureInfo.CurrentCulture.TextInfo.ToTitleCase(“我的名字”);

返回〜我的名字

但是,像前面提到的McFly这样的名称仍然存在问题。


3
麦克弗里!Konichiwa,Fugitsusan先生
Ian Boyd

@David C尝试用null替换空间!像string.replace('','')
Chintan 2012年

3

我使用自己的方法来解决此问题:

例如,短语:“ hello world。您好,这是stackoverflow世界。” 将是“ Hello World。这是Stackoverflow世界。”。正则表达式\ 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
为什么在调用ToTitleCase之前不对输入字符串调用ToLower?
安迪·罗斯

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)是更具可读性的恕我直言。
Hosam Aly

恕我直言,相比起,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/...
迈克尔·哈伦
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.