Comment mettre en majuscule la première lettre du prénom et du nom en C #?


141

Existe-t-il un moyen simple de mettre en majuscule la première lettre d'une chaîne et de réduire le reste? Existe-t-il une méthode intégrée ou dois-je créer la mienne?


3
Je ne sais rien de votre application particulière, mais je pense qu'un avertissement général est dû: les programmeurs ne devraient pas appliquer cette méthode bon gré mal gré à de vrais noms. Je pense que le vieux John MacDonald serait contrarié par cette méthode de malformation de son nom, sans parler des ee cummings, des crochets de cloche, danah boyd, 松本 行 弘, les gens avec un "von" dans le nom de famille, les gens avec le nom de famille "O'Doyle" , etc., etc., etc. La plupart des noms ne sont pas du format «First Last» avec cette majuscule (et en caractères majuscules); Je recommande de lire kalzumeus.com/2010/06/17/…
Nick le

@Nick a tout à fait raison. Vous ne pouvez même pas supposer que les minuscules suivies de majuscules sont erronées - les noms irlandais font des choses comme "Ó hAirt". Supposons que pour toute convention à laquelle vous pouvez penser par cœur, il y aura une culture / langue qui vous surprendra.
James Moore du

Réponses:


259

TextInfo.ToTitleCase()met en majuscule le premier caractère de chaque jeton d'une chaîne.
S'il n'est pas nécessaire de conserver l'acronyme en majuscules, vous devez inclure ToLower().

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

Si CurrentCulture n'est pas disponible, utilisez:

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

Voir le lien MSDN pour une description détaillée.


24
Une chose à noter ici est que cela ne fonctionne pas si la chaîne est entièrement en majuscules. Il pense que toutes les majuscules est un acronyme.
Mike Roosa

9
Ce que j'ai vu avec beaucoup d'entre eux, c'est que vous ne pouvez pas compter sur eux. Cela ne fonctionnerait pas si le nom est quelque chose comme McCain ou si vous commencez à frapper plus de noms étrangers.
Mike Wills le

25
@roosa - solution facile pour ce ToTitleCase (val.ToLower ())
Simon_Weaver

+1 Je savais qu'il devait déjà être dans la FCL, et Google m'a amené ici = D
gideon

13
Contrairement à la réponse de Nathan ci-dessous, j'obtiens une erreur: "Une référence d'objet est requise pour le champ, la méthode ou la propriété non statique ......." malheureusement.
Dan W du

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

Aww snap! Bonne réponse. J'oublie toujours les trucs de la mondialisation.
Michael Haren

Excellente solution! Dans VB.Net:sItem = Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(sItem.ToLower) 'first char upper case
Nasenbaer

Vous devez détecter la culture de chaque nom individuel , pas la culture actuelle. Cela ne fonctionne pas pour les noms.
James Moore

1
Puisque cela repose sur le CurrentCulture, comment pouvons-nous être sûrs qu'il n'y a pas de culture qui gère cela différemment?
Rudey

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

Le code ci-dessus ne fonctionnera pas .....

alors mettez le code ci-dessous en convertissant en bas puis appliquez la fonction

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

15

Certains cas CultureInfo.CurrentCulture.TextInfo.ToTitleCasene peuvent pas gérer, par exemple: l'apostrophe '.

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

Une regex peut également être utilisée \b[a-zA-Z]pour identifier le caractère de départ d'un mot après une limite de mot \b, il suffit alors de remplacer la correspondance par son équivalence en majuscules grâce à la Regex.Replace(string input,string pattern,MatchEvaluator evaluator)méthode:

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

Le regex peut être ajusté si nécessaire, par exemple, si nous voulons gérer les cas MacDonaldet McFry, le regex devient:(?<=\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

Si nous devons gérer plusieurs préfixes nous ne devons modifier le groupe (?:mc|mac), par exemple pour ajouter des préfixes français du, de: (?:mc|mac|du|de).

Enfin, nous pouvons réaliser que cette expression régulière correspondra également à la casse MacDonald'Sde la dernière 's, nous devons donc la gérer dans l' expression régulière avec un regard négatif derrière (?<!'s\b). À la fin, nous avons:

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 J'ai du mal à trouver un moyen de gérer les chiffres romains à la fin du nom; J'aimerais les mettre tous en majuscules: John Smith III. Le regard négatif en arrière interférerait-il avec cela?
Matt

Comme d'habitude, j'ai finalement pu répondre à ma propre question. J'ai ajouté un groupe facultatif pour faire correspondre les chiffres romains (qui seront en majuscules). Voici la regex complète que j'utilise maintenant: (? <= \ B (?: Mc | mac)?) [A-zA-Z] (? <! 'S \ b) (?: ii | iii | iv | v | vi | vii | viii | ix)?
Matt

Votre cas est spécial, l'expression régulière dans la réponse traite chaque nom (nom de famille) comme un mot isolé dans la chaîne d'entrée (la chaîne d'entrée de test a plusieurs noms) donc elle n'a pas la notion de `` fin du nom '' . Si vous traitez la chaîne d'entrée comme un nom unique, vous pouvez préfixer l'expression régulière avec une condition simple pour traiter votre cas: \b[ivxlcdm]+$|c'est ainsi \b[ivxlcdm]+$|(?<=\b(?:mc|mac)?)[a-zA-Z](?<!'s\b). Il mettra en majuscules tous les mots de fin d'un nom ayant un format de chiffres romains non strict ( ivxlcdm). Vous pouvez cependant avoir des résultats indésirables, par exemple 'Li' deviendra 'LI'
polkduran

Intéressant. Je pense que votre ajout est probablement plus correct concernant la structure, mais je suis d'accord ... Je pense qu'il y aura des problèmes que vous avez soulevés. Dans ma solution ci-dessus, j'ai codé en dur les suffixes jusqu'à "ix" qui fonctionnera dans mon cas, mais je reconnais que peut ne pas convenir à tout le monde.
Matt

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

7

Mc et Mac sont des préfixes de nom de famille courants aux États-Unis, et il y en a d'autres. TextInfo.ToTitleCase ne gère pas ces cas et ne doit pas être utilisé à cette fin. Voici comment je fais:

    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'option la plus directe sera d'utiliser la fonction ToTitleCase qui est disponible dans .NET qui devrait prendre soin du nom la plupart du temps. Comme edg l'a souligné, il y a certains noms pour lesquels cela ne fonctionnera pas, mais ils sont assez rares, donc à moins que vous ne cibliez une culture où de tels noms sont courants, il n'est pas nécessaire de vous inquiéter trop.

Cependant, si vous ne travaillez pas avec une langue .NET, cela dépend de ce à quoi ressemble l'entrée - si vous avez deux champs séparés pour le prénom et le nom, vous pouvez simplement mettre en majuscule la première lettre en bas du reste en utilisant sous-chaînes.

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

Cependant, si plusieurs noms vous sont fournis dans la même chaîne, vous devez savoir comment vous obtenez les informations et les diviser en conséquence. Donc, si vous obtenez un nom comme "John Doe", vous divisez la chaîne en fonction du caractère d'espace. S'il est dans un format tel que "Doe, John", vous devrez le diviser en fonction de la virgule. Cependant, une fois que vous l'avez séparé, appliquez simplement le code indiqué précédemment.


3

CultureInfo.CurrentCulture.TextInfo.ToTitleCase ("mon nom");

renvoie ~ Mon nom

Mais le problème existe toujours avec des noms comme McFly comme indiqué précédemment.


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

@David C Essayez de remplacer l'espace par null !! like string.replace ('', '')
Chintan

3

J'utilise ma propre méthode pour résoudre ce problème:

Par exemple, la phrase: "bonjour le monde. Bonjour c'est le monde stackoverflow." sera "Hello World. Hello This Is The Stackoverflow World.". Regex \ b (début d'un mot) \ w (premier caractère du mot) fera l'affaire.

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

Les suggestions d'utilisation de ToTitleCase ne fonctionneront pas pour les chaînes qui sont toutes en majuscules. Vous devrez donc appeler ToUpper sur le premier caractère et ToLower sur les caractères restants.


6
Pourquoi ne pas appeler ToLower sur la chaîne d'entrée avant d'appeler ToTitleCase?
Andy Rose

2

Cette classe fait l'affaire. Vous pouvez ajouter de nouveaux préfixes au tableau de chaînes statiques _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

Si vous utilisez vS2k8, vous pouvez utiliser une méthode d'extension pour l'ajouter à la 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)est plus lisible à mon humble avis.
Hosam Aly le

À mon humble avis input.FirstLetterToUpper()est certainement plus lisible par rapport Char.ToUpper(input[0]) + input.Substring(1), mais moins transparente
Michael

0

Pour contourner certains des problèmes / problèmes qui ont été mis en évidence, je suggérerais de convertir d'abord la chaîne en minuscules, puis d'appeler la méthode ToTitleCase. Vous pouvez ensuite utiliser IndexOf ("Mc") ou IndexOf ("O \ '") pour déterminer les cas spéciaux qui nécessitent une attention plus spécifique.

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

J'aime cette façon:

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

Tiré de cet article MSDN .


0

J'espère que cela vous aide.

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

Comme indiqué par edg, vous aurez besoin d'un algorithme plus complexe pour gérer les noms spéciaux (c'est probablement pourquoi de nombreux endroits forcent tout en majuscules).

Quelque chose comme ce c # non testé devrait gérer le cas simple que vous avez demandé:

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

Oubliez ça - utilisez la classe de globalisation stackoverflow.com/questions/72831/…
Michael Haren
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.