Wie schreibe ich den ersten Buchstaben des Vor- und Nachnamens in C # groß?

141

Gibt es eine einfache Möglichkeit, den ersten Buchstaben einer Zeichenfolge groß zu schreiben und den Rest zu senken? Gibt es eine eingebaute Methode oder muss ich meine eigene erstellen?

Mike Roosa
quelle
3
Ich weiß nichts über Ihre spezielle Anwendung, aber ich denke, eine allgemeine Warnung ist fällig: Programmierer sollten diese Methode nicht ohne weiteres auf echte Namen anwenden. Ich denke, der alte John MacDonald wäre verärgert über diese Methode, die seinen Namen verstümmelt, ganz zu schweigen von Ee Cummings, Glockenhaken, Danah Boyd, with 行 弘, Leuten mit einem "von" im Nachnamen, Leuten mit dem Nachnamen "O'Doyle" usw. usw. usw. Die meisten Namen haben nicht das Format "First Last" mit dieser Großschreibung (und in Großbuchstaben). Ich empfehle kalzumeus.com/2010/06/17/… zu
Nick
@ Nick ist absolut richtig. Sie können nicht einmal davon ausgehen, dass Kleinbuchstaben gefolgt von Großbuchstaben falsch sind - irische Namen tun Dinge wie "Ó hAirt". Angenommen, für jede Konvention, die Sie sich vorstellen können, gibt es eine Kultur / Sprache, die Sie überraschen wird.
James Moore

Antworten:

259

TextInfo.ToTitleCase()Großschreibung des ersten Zeichens in jedem Token einer Zeichenfolge.
Wenn es nicht erforderlich ist, das Akronym Uppercasing beizubehalten, sollten Sie einschließen ToLower().

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

Wenn CurrentCulture nicht verfügbar ist, verwenden Sie:

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

Eine detaillierte Beschreibung finden Sie im MSDN-Link .

ageektrapped
quelle
24
Eine Sache, die hier zu beachten ist, ist, dass es nicht funktioniert, wenn die Zeichenfolge nur Großbuchstaben enthält. Es denkt, dass alle Kappen ein Akronym sind.
Mike Roosa
9
Was ich bei vielen davon gesehen habe, ist, dass man sich nicht auf sie verlassen kann. Es würde nicht funktionieren, wenn der Name so etwas wie McCain ist oder wenn Sie anfangen, mehr ausländische Namen zu treffen.
Mike Wills
25
@roosa - einfache Lösung für diesen ToTitleCase (val.ToLower ())
Simon_Weaver
+1 Ich wusste, dass es bereits in der FCL sein musste, und Google brachte mich hierher = D
Gideon
13
Im Gegensatz zu Nathans Antwort unten erhalte ich leider die Fehlermeldung "Für das nicht statische Feld, die Methode oder die Eigenschaft ist eine Objektreferenz erforderlich .......".
Dan W
117
CultureInfo.CurrentCulture.TextInfo.ToTitleCase("hello world");
Nathan Baulch
quelle
Aww Schnappschuss! Gute Antwort. Ich vergesse immer das Globalisierungsmaterial.
Michael Haren
Tolle Lösung! In VB.Net:sItem = Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(sItem.ToLower) 'first char upper case
Nasenbaer
Sie müssen die Kultur jedes einzelnen Namens erkennen , nicht die aktuelle Kultur. Dies funktioniert nicht für Namen.
James Moore
1
Da dies auf das verlässt sich CurrentCulture, wie können wir sicher sein , dass es keine Kultur, die dies anders behandelt?
Rudey
30
String test = "HELLO HOW ARE YOU";
string s = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(test);

Der obige Code funktioniert nicht .....

Geben Sie also den folgenden Code ein, indem Sie ihn in einen niedrigeren Wert konvertieren, und wenden Sie dann die Funktion an

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

Es gibt einige Fälle, CultureInfo.CurrentCulture.TextInfo.ToTitleCasedie nicht behandelt werden können, zum Beispiel den Apostroph '.

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

Ein regulärer Ausdruck kann auch verwendet werden \b[a-zA-Z], um das Startzeichen eines Wortes nach einer Wortgrenze zu identifizieren. \bDann müssen wir die Übereinstimmung dank der folgenden Regex.Replace(string input,string pattern,MatchEvaluator evaluator)Methode nur durch ihre Großbuchstabenäquivalenz ersetzen :

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

Der Regex kann bei Bedarf angepasst werden, zum Beispiel, wenn wir die MacDonaldund McFryFälle behandeln möchten, aus denen der Regex wird:(?<=\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

Wenn wir mehr Präfixe verarbeiten müssen, müssen wir nur die Gruppe ändern (?:mc|mac), um beispielsweise französische Präfixe hinzuzufügen du, de: (?:mc|mac|du|de).

Schließlich können wir erkennen, dass dieser Regex auch mit dem MacDonald'Sletzten übereinstimmt, 'ssodass wir ihn im Regex mit einem negativen Blick nach hinten behandeln müssen (?<!'s\b). Am Ende haben wir:

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
quelle
@polkduran Ich habe Mühe, einen Weg zu finden, mit römischen Ziffern am Ende des Namens umzugehen. Ich möchte sie alle in Großbuchstaben schreiben: John Smith III. Würde der negative Rückblick dies stören?
Matt
Wie immer konnte ich endlich meine eigene Frage beantworten. Ich habe eine optionale Gruppe hinzugefügt, die den römischen Ziffern entspricht (die in Großbuchstaben geschrieben werden). Hier ist der vollständige reguläre Ausdruck, den ich jetzt verwende: (? <= \ B (?: Mc | mac)?) [A-zA-Z] (? <! 'S \ b) (?: Ii | iii | iv | v | vi | vii | viii | ix)?
Matt
Ihr Fall ist ein besonderer Fall. Der reguläre Ausdruck in der Antwort behandelt jeden Namen (Nachnamen) als isoliertes Wort in der Eingabezeichenfolge (die Testeingabezeichenfolge hat mehrere Namen), sodass der Begriff "Ende des Namens" nicht verwendet wird. . Wenn Sie die Eingabezeichenfolge als einen einzelnen Namen behandeln, können Sie dem regulären Ausdruck eine einfache Bedingung voranstellen, um Ihren Fall zu behandeln: \b[ivxlcdm]+$|Sie haben es also \b[ivxlcdm]+$|(?<=\b(?:mc|mac)?)[a-zA-Z](?<!'s\b). Alle Endwörter eines Namens mit einem nicht strengen römischen Zahlenformat ( ivxlcdm) werden in Großbuchstaben geschrieben . Sie können jedoch einige unerwünschte Ergebnisse haben, zum Beispiel wird 'Li' zu 'LI'
polkduran
Interessant. Ich denke, Ihre Hinzufügung ist in Bezug auf die Struktur wahrscheinlich korrekter, aber ich stimme zu ... Ich denke, es wird einige Probleme geben, die Sie angegeben haben. In meiner obigen Lösung habe ich die Suffixe bis "ix" fest codiert, was in meinem Fall funktioniert, aber ich erkenne, dass dies möglicherweise nicht für jeden geeignet ist.
Matt
1
@ Si8, hast du es getestet? Regex.Replace("JOHN DOE".ToLower(), @"(?<=\b(?:mc|mac)?)[a-zA-Z](?<!'s\b)", m => m.Value.ToUpper())
Polkduran
7

Mc und Mac sind in den USA gebräuchliche Familiennamenpräfixe, und es gibt andere. TextInfo.ToTitleCase behandelt diese Fälle nicht und sollte nicht für diesen Zweck verwendet werden. So mache ich das:

    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;
    }
Jamie Ide
quelle
4

Die direkteste Option ist die Verwendung der in .NET verfügbaren ToTitleCase- Funktion, die sich die meiste Zeit um den Namen kümmern sollte. Wie edg hervorhob , gibt es einige Namen, für die es nicht funktioniert, aber diese sind ziemlich selten. Wenn Sie also nicht auf eine Kultur abzielen, in der solche Namen häufig vorkommen, ist es nicht notwendig, dass Sie sich zu viele Sorgen machen müssen.

Wenn Sie jedoch nicht mit einer .NET-Sprache arbeiten, hängt dies davon ab, wie die Eingabe aussieht. Wenn Sie zwei separate Felder für den Vor- und Nachnamen haben, können Sie einfach den ersten Buchstaben groß schreiben und den Rest mit verwenden Teilzeichenfolgen.

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

Wenn Sie jedoch mehrere Namen als Teil derselben Zeichenfolge erhalten, müssen Sie wissen, wie Sie die Informationen erhalten, und sie entsprechend aufteilen . Wenn Sie also einen Namen wie "John Doe" erhalten, teilen Sie die Zeichenfolge basierend auf dem Leerzeichen. Wenn es in einem Format wie "Doe, John" vorliegt, müssen Sie es anhand des Kommas aufteilen. Sobald Sie es jedoch aufgeteilt haben, wenden Sie einfach den zuvor gezeigten Code an.

rjzii
quelle
3

CultureInfo.CurrentCulture.TextInfo.ToTitleCase ("mein Name");

gibt ~ Mein Name zurück

Das Problem besteht jedoch weiterhin bei Namen wie McFly, wie bereits erwähnt.

David C.
quelle
3
McFry! Konichiwa, Mr. Fugitsu-san
Ian Boyd
@ David C Versuchen Sie, Leerzeichen durch Null zu ersetzen !! wie string.replace ('', '')
Chintan
3

Ich benutze meine eigene Methode, um dies zu beheben:

Zum Beispiel der Satz: "Hallo Welt. Hallo, das ist die Stackoverflow-Welt." wird "Hallo Welt. Hallo, das ist die Stackoverflow-Welt." sein. Regex \ b (Wortanfang) \ w (erster Charakter des Wortes) macht den Trick.

/// <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;
}
Ton Snoei
quelle
2

Die Vorschläge zur Verwendung von ToTitleCase funktionieren nicht für Zeichenfolgen, die alle in Großbuchstaben geschrieben sind. Sie müssen also ToUpper für das erste Zeichen und ToLower für die verbleibenden Zeichen aufrufen.

Tundey
quelle
6
Rufen Sie ToLower in der Eingabezeichenfolge auf, bevor Sie ToTitleCase aufrufen.
Andy Rose
2

Diese Klasse macht den Trick. Sie können dem statischen String-Array _prefixes neue Präfixe hinzufügen .

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();
        }
}
Eddie Velasquez
quelle
1

Wenn Sie vS2k8 verwenden, können Sie es mithilfe einer Erweiterungsmethode zur String-Klasse hinzufügen:

public static string FirstLetterToUpper(this String input)
{
    return input = input.Substring(0, 1).ToUpper() + 
       input.Substring(1, input.Length - 1);
}
FlySwat
quelle
9
Char.ToUpper(input[0]) + input.Substring(1)ist meiner Meinung nach besser lesbar.
Hosam Aly
IMHO input.FirstLetterToUpper()ist sicherlich mehr lesbar gegen Char.ToUpper(input[0]) + input.Substring(1), aber weniger transparent
Michael
0

Um einige der Probleme zu umgehen, die hervorgehoben wurden, würde ich vorschlagen, die Zeichenfolge zuerst in Kleinbuchstaben umzuwandeln und dann die ToTitleCase-Methode aufzurufen. Sie können dann IndexOf ("Mc") oder IndexOf ("O \ '") verwenden, um Sonderfälle zu ermitteln, die besondere Aufmerksamkeit erfordern.

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);
}
Andy Rose
quelle
0

Ich mag diesen Weg:

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

Aus diesem MSDN-Artikel entnommen .

TrentVB
quelle
0

Hoffe das hilft dir.

String fName = "firstname";
String lName = "lastname";
String capitalizedFName = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(fName);
String capitalizedLName = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(lName);
Arun
quelle
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;

        }
Govind Singh Rawat
quelle
-1

Wie von edg angegeben, benötigen Sie einen komplexeren Algorithmus, um spezielle Namen zu verarbeiten (dies ist wahrscheinlich der Grund, warum viele Stellen alles in Großbuchstaben zwingen).

So etwas wie dieses ungetestete c # sollte den von Ihnen angeforderten einfachen Fall behandeln:

public string SentenceCase(string input)
{
    return input(0, 1).ToUpper + input.Substring(1).ToLower;
}
Michael Haren
quelle
Vergessen Sie dies - verwenden Sie die Globalisierungsklasse stackoverflow.com/questions/72831/…
Michael Haren