Come posso scrivere in maiuscolo la prima lettera di nome e cognome in C #?


141

C'è un modo semplice per scrivere in maiuscolo la prima lettera di una stringa e abbassarne il resto? Esiste un metodo integrato o devo crearne uno mio?


3
Non so nulla della tua particolare applicazione, ma penso che sia dovuto un avvertimento generale: i programmatori non dovrebbero applicare questo metodo volenti o nolenti ai nomi reali. Penso che il vecchio John MacDonald sarebbe sconvolto da questo metodo alterando il suo nome, per non parlare di ee cummings, campanacci, danah boyd, 松本 行 弘, persone con un "von" nel cognome, persone con il cognome "O'Doyle" , ecc., ecc., ecc. La maggior parte dei nomi non ha il formato "Primo Cognome" con la maiuscola (e in caratteri maiuscoli); Consiglio di leggere kalzumeus.com/2010/06/17/…
Nick,

@ Nick ha assolutamente ragione. Non puoi nemmeno supporre che le lettere minuscole seguite da lettere maiuscole siano sbagliate: i nomi irlandesi fanno cose come "Ó hAirt". Supponiamo che per qualsiasi convenzione che ti venga in mente, ci sarà una cultura / lingua che ti sorprenderà.
James Moore,

Risposte:


259

TextInfo.ToTitleCase()mette in maiuscolo il primo carattere in ogni token di una stringa.
Se non è necessario mantenere Acronimo in maiuscolo, è necessario includere ToLower().

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

Se CurrentCulture non è disponibile, utilizzare:

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

Vedere il collegamento MSDN per una descrizione dettagliata.


24
Una cosa da notare qui è che non funziona se la stringa è tutta maiuscola. Pensa che tutte le maiuscole siano un acronimo.
Mike Roosa,

9
La cosa che ho visto con molti di questi è che non puoi fare affidamento su di essi. Non funzionerebbe se il nome è qualcosa come McCain o se inizi a colpire più nomi stranieri.
Mike Wills,

25
@roosa - soluzione semplice per quel ToTitleCase (val.ToLower ())
Simon_Weaver,

+1 Sapevo che doveva essere già nella FCL, e google mi ha portato qui = D
Gideon

13
A differenza della seguente risposta di Nathan, ricevo un errore: "Un riferimento all'oggetto è richiesto per il campo, il metodo o la proprietà non statici ......." sfortunatamente.
Dan W,

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

Aww snap! Buona risposta. Mi dimentico sempre delle cose sulla globalizzazione.
Michael Haren,

Ottima soluzione! In VB.Net:sItem = Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(sItem.ToLower) 'first char upper case
Nasenbaer,

È necessario rilevare la cultura di ogni singolo nome , non la cultura corrente. Questo non funziona per i nomi.
James Moore,

1
Dal momento che questo si basa sul CurrentCulture, come possiamo essere sicuri che non esiste cultura che la gestisca diversamente?
Rudey,

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

Il codice sopra non funzionerà .....

quindi inserisci il codice seguente convertendolo in basso quindi applica la funzione

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

15

Ci sono alcuni casi che CultureInfo.CurrentCulture.TextInfo.ToTitleCasenon possono essere gestiti, ad esempio: l'apostrofo '.

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

Un regex può anche essere usato \b[a-zA-Z]per identificare il carattere iniziale di una parola dopo un confine di parola \b, quindi dobbiamo semplicemente sostituire la corrispondenza con la sua equivalenza maiuscola grazie al Regex.Replace(string input,string pattern,MatchEvaluator evaluator)metodo:

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

Il regex può essere regolato se necessario, ad esempio, se vogliamo gestire i casi MacDonalde McFryil regex diventa:(?<=\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

Se abbiamo bisogno di gestire più prefissi abbiamo solo bisogno di modificare il gruppo (?:mc|mac), ad esempio per aggiungere prefissi francesi du, de: (?:mc|mac|du|de).

Infine, possiamo renderci conto che questa regex corrisponderà anche al caso MacDonald'Sdell'ultimo, 'squindi dobbiamo gestirla nella regex con uno sguardo negativo dietro (?<!'s\b). Alla fine abbiamo:

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 Sto lottando per trovare un modo per gestire i numeri romani alla fine del nome; Vorrei renderli tutti maiuscoli: John Smith III. Lo sguardo negativo interferirebbe con questo?
Matt

Come sempre, sono stato finalmente in grado di rispondere alla mia domanda. Ho aggiunto un gruppo opzionale per abbinare i numeri romani (che diventeranno maiuscoli). Ecco la regex completa che sto usando ora: (? <= \ B (?: Mc | mac)?) [A-zA-Z] (? <! 'S \ b) (?: ii | iii | iv | v | VI | VII | viii | ix)?
Matt

Il tuo caso è speciale, la regex nella risposta considera ogni nome (cognome) come una parola isolata nella stringa di input (la stringa di input di test ha diversi nomi) quindi non ha la nozione di "end of the name" . Se trattate la stringa di input come un singolo nome, potete aggiungere il prefisso alla regex con una semplice condizione per gestire il vostro caso: \b[ivxlcdm]+$|così avete \b[ivxlcdm]+$|(?<=\b(?:mc|mac)?)[a-zA-Z](?<!'s\b). Rende maiuscole tutte le parole finali di un nome che ha un formato numerico romano non rigoroso ( ivxlcdm). Potresti avere comunque dei risultati indesiderati, ad esempio 'Li' diventerà 'LI'
polkduran,

Interessante. Penso che la tua aggiunta sia probabilmente più corretta per quanto riguarda la struttura, ma sono d'accordo ... Penso che ci saranno alcuni problemi che hai dichiarato. Nella mia soluzione sopra, ho codificato i suffissi fino a "ix" che funzionerà nel mio caso, ma riconosco che potrebbe non essere adatto a tutti.
Matt,

1
@ Si8, l'hai provato? Regex.Replace("JOHN DOE".ToLower(), @"(?<=\b(?:mc|mac)?)[a-zA-Z](?<!'s\b)", m => m.Value.ToUpper())
polkduran,

7

Mc e Mac sono prefissi dei cognomi comuni negli Stati Uniti, e ce ne sono altri. TextInfo.ToTitleCase non gestisce questi casi e non dovrebbe essere utilizzato per questo scopo. Ecco come lo sto facendo:

    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

L'opzione più diretta sarà quella di utilizzare la funzione ToTitleCase disponibile in .NET che dovrebbe occuparsi del nome per la maggior parte del tempo. Come ha sottolineato edg , ci sono alcuni nomi per cui non funzionerà, ma questi sono abbastanza rari, quindi a meno che tu non stia prendendo di mira una cultura in cui tali nomi sono comuni, non è necessario qualcosa di cui devi preoccuparti troppo.

Tuttavia, se non stai lavorando con una lingua .NET, dipende dall'aspetto dell'input: se hai due campi separati per il nome e il cognome, puoi solo mettere in maiuscolo la prima lettera per abbassare il resto usando sottostringhe.

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

Tuttavia, se ti vengono forniti più nomi come parte della stessa stringa, devi sapere come stai ottenendo le informazioni e dividerle di conseguenza. Quindi, se stai ottenendo un nome come "John Doe", dividi la stringa in base al carattere dello spazio. Se è in un formato come "Doe, John" dovrai dividerlo in base alla virgola. Tuttavia, una volta diviso, basta applicare il codice mostrato in precedenza.


3

CultureInfo.CurrentCulture.TextInfo.ToTitleCase ("il mio nome");

restituisce ~ My Name

Ma il problema esiste ancora con nomi come McFly, come affermato in precedenza.


3
McFry! Konichiwa, sig. Fugitsu-san
Ian Boyd,

@David C Prova a sostituire lo spazio con null !! like string.replace ('', '')
Chintan,

3

Uso il mio metodo per risolvere il problema:

Ad esempio la frase: "ciao mondo. Ciao questo è il mondo dello stackoverflow". sarà "Hello World. Hello This Is The Stackoverflow World". Regex \ b (inizio di una parola) \ w (primo carattere della parola) farà il trucco.

/// <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

I suggerimenti per usare ToTitleCase non funzioneranno con stringhe tutte in maiuscolo. Quindi dovrai chiamare ToUpper sul primo personaggio e ToLower sui personaggi rimanenti.


6
Perché non chiamare ToLower sulla stringa di input prima di chiamare ToTitleCase?
Andy Rose,

2

Questa classe fa il trucco. È possibile aggiungere nuovi prefissi all'array di stringhe statiche _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

Se si utilizza vS2k8, è possibile utilizzare un metodo di estensione per aggiungerlo alla classe 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)è più leggibile IMHO.
Hosam Aly,

IMHO input.FirstLetterToUpper()è sicuramente più leggibile vs. Char.ToUpper(input[0]) + input.Substring(1), ma meno trasparente
Michael,

0

Per ovviare ad alcuni dei problemi / problemi che sono stati ben evidenziati, suggerirei prima di convertire la stringa in minuscolo e poi di chiamare il metodo ToTitleCase. È quindi possibile utilizzare IndexOf ("Mc") o IndexOf ("O \ '") per determinare casi speciali che richiedono un'attenzione più specifica.

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

Mi piace così:

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

Tratto da questo articolo MSDN .


0

Spero che questo ti aiuti.

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

Come indicato da edg, avrai bisogno di un algoritmo più complesso per gestire nomi speciali (questo è probabilmente il motivo per cui molti posti impongono tutto in maiuscolo).

Qualcosa di simile a questo c # non testato dovrebbe gestire il semplice caso richiesto:

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

Dimentica questo: usa la classe di globalizzazione stackoverflow.com/questions/72831/…
Michael Haren,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.