113

I have a string of text (about 5-6 words mostly) that I need to convert.

Currently the text looks like:

THIS IS MY TEXT RIGHT NOW

I want to convert it to:

This Is My Text Right Now

I can loop through my collection of strings, but I am not sure how to go about performing this text modification.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mrblah
  • 99,669
  • 140
  • 310
  • 420
  • Related (not duplicate): *[Make first letter of a string upper case (with maximum performance)](https://stackoverflow.com/questions/4135317)* – Peter Mortensen Jun 10 '21 at 03:02

11 Answers11

259
string s = "THIS IS MY TEXT RIGHT NOW";

s = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(s.ToLower());
jspcal
  • 50,847
  • 7
  • 72
  • 76
  • 7
    Note that while this method will do what the questioner has asked, it's a naive algorithm that just capitalizes each word, without regard to what kind of word it is. It's not really "title case" since rules for title casing differ in different languages. It's not even correct for English. For instance, the title "about a boy" should be "About a Boy" in English, but this method would give "About A Boy". If you want *true* title case, you'll have to write your own method. – Ryan Lundy Dec 21 '09 at 23:43
  • 18
    I wouldn't call them jerks. The thing with "ToTitleCase" is that it's culture-dependent, hence it has to be in the System.Globalization namespace. Going through CurrentThread is just done to get the current Culture of the Thread (Be aware that this may cause different behavior if the user has a different Locale!). You could as well do "CultureInfo.InvariantCulture.TextInfo.ToTitleCase()", which may be better as InvariantCulture behaves the same on all cultures. Out of interest George: Where would you put a Culture-Specific String function? – Michael Stum Dec 21 '09 at 23:45
  • 3
    Also note the comments about ALL UPPERCASE strings: http://msdn.microsoft.com/en-us/library/system.globalization.textinfo.totitlecase.aspx – Michael Stum Dec 21 '09 at 23:46
88

I probably prefer to invoke the ToTitleCase from CultureInfo (System.Globalization) than Thread.CurrentThread (System.Threading):

string s = "THIS IS MY TEXT RIGHT NOW";
s = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(s.ToLower());

But it should be the same as jspcal's solution.

EDIT

Actually, those solutions are not the same: CurrentThread --calls--> CultureInfo!


System.Threading.Thread.CurrentThread.CurrentCulture

string s = "THIS IS MY TEXT RIGHT NOW";
s = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(s.ToLower());

IL_0000:  ldstr       "THIS IS MY TEXT RIGHT NOW"
IL_0005:  stloc.0     // s
IL_0006:  call        System.Threading.Thread.get_CurrentThread
IL_000B:  callvirt    System.Threading.Thread.get_CurrentCulture
IL_0010:  callvirt    System.Globalization.CultureInfo.get_TextInfo
IL_0015:  ldloc.0     // s
IL_0016:  callvirt    System.String.ToLower
IL_001B:  callvirt    System.Globalization.TextInfo.ToTitleCase
IL_0020:  stloc.0     // s

System.Globalization.CultureInfo.CurrentCulture

string s = "THIS IS MY TEXT RIGHT NOW";
s = System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(s.ToLower());

IL_0000:  ldstr       "THIS IS MY TEXT RIGHT NOW"
IL_0005:  stloc.0     // s
IL_0006:  call        System.Globalization.CultureInfo.get_CurrentCulture
IL_000B:  callvirt    System.Globalization.CultureInfo.get_TextInfo
IL_0010:  ldloc.0     // s
IL_0011:  callvirt    System.String.ToLower
IL_0016:  callvirt    System.Globalization.TextInfo.ToTitleCase
IL_001B:  stloc.0     // s

References:

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Filippo Vitale
  • 7,597
  • 3
  • 58
  • 64
18

There are a couple of ways to go about converting the first character of a string to upper case.

The first way is to create a method that simply caps the first character and appends the rest of the string using a substring:

public string UppercaseFirst(string s)
{
    return char.ToUpper(s[0]) + s.Substring(1);
}

The second way (which is slightly faster) is to split the string into a character array and then rebuild the string:

public string UppercaseFirst(string s)
{
    char[] a = s.ToCharArray();
    a[0] = char.ToUpper(a[0]);
    return new string(a);
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jamie Dixon
  • 53,019
  • 19
  • 125
  • 162
  • 1
    This solution doesn't exactly answer the question adequately. The title of the question is "Convert all first letter to upper case, rest lower for each word". However, this solution only capitalizes the first letter of the entire string. Therefore, this solution would convert "hello world" to "Hello world", rather than "Hello World". – brsfan Feb 28 '17 at 18:11
  • That's a good point. This solution could be completed if you used something like string[] words = s.Split(' '); and then call the above methods inside a foreach (word in words) loop, reconstructing the string... The other solutions seem more elegant. – Ryan D. Sep 21 '21 at 19:46
10

If you're using on a web page, you can also use CSS:

style="text-transform:capitalize;"

M.Eren Çelik
  • 155
  • 2
  • 9
  • 2
    Why CSS? When the question is asking for **c# asp.net regex** – Jay Feb 25 '15 at 10:41
  • 2
    The tag `ASP.NET` shows the OP is doing it on WEB. Of course this is not the answer of question because OP required the solution in `C#` but it solves the problem and can be an alternative solution. +1 – Muhammad Saqib Jul 30 '18 at 18:13
9

Untested but something like this should work:

var phrase = "THIS IS MY TEXT RIGHT NOW";
var rx = new System.Text.RegularExpressions.Regex(@"(?<=\w)\w");
var newString = rx.Replace(phrase,new MatchEvaluator(m=>m.Value.ToLowerInvariant()));

Essentially it says "preform a regex match on all occurrences of an alphanumeric character that follows another alphanumeric character and then replace it with a lowercase version of itself"

George Mauer
  • 117,483
  • 131
  • 382
  • 612
7

When building big tables, speed is a concern so Jamie Dixon's second function is best, but it doesn't completely work as is...

It fails to take all of the letters to lowercase, and it only capitalizes the first letter of the string, not the first letter of each word in the string... the below option fixes both issues:

    public string UppercaseFirstEach(string s)
    {
        char[] a = s.ToLower().ToCharArray();

        for (int i = 0; i < a.Count(); i++ )
        {
            a[i] = i == 0 || a[i-1] == ' ' ? char.ToUpper(a[i]) : a[i];

        }

        return new string(a);
    }

Although at this point, whether this is still the fastest option is uncertain. The Regex solution provided by George Mauer might be faster... someone who cares enough should test it.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Serj Sagan
  • 28,927
  • 17
  • 154
  • 183
2

I don't know if the solution below is more or less efficient than jspcal's answer, but I'm pretty sure it requires less object creation than Jamie's and George's.

string s = "THIS IS MY TEXT RIGHT NOW";
StringBuilder sb = new StringBuilder(s.Length);
bool capitalize = true;
foreach (char c in s) {
    sb.Append(capitalize ? Char.ToUpper(c) : Char.ToLower(c));
    capitalize = !Char.IsLetter(c);
}
return sb.ToString();
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ephemient
  • 198,619
  • 38
  • 280
  • 391
  • 2
    If we're concerned with object creation, why not do it in-place with a for loop indexing over s instead of using a StringBuilder? – jball Dec 21 '09 at 23:37
0

In addition to the first answer, remember to change string selectionstart index to the end of the word or you will get the reverse order of letters in the string.

s.SelectionStart = s.Length;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
zia khan
  • 361
  • 3
  • 14
0

Try this technique; It returns the desired result

CultureInfo.CurrentCulture.TextInfo.ToTitleCase(str.ToLower());

And don't forget to use System.Globalization.

Beyondo
  • 2,952
  • 1
  • 17
  • 42
0

This is one of the possible solutions you might be interested in. Traversing an array of characters from right to left and vice versa in one loop.

public static string WordsToCapitalLetter(string value)
{
    if (string.IsNullOrWhiteSpace(value))
    {
        throw new ArgumentException("value");
    }

    int inputValueCharLength = value.Length;
    var valueAsCharArray = value.ToCharArray();

    int min = 0;
    int max = inputValueCharLength - 1;

    while (max > min)
    {
        char left = value[min];
        char previousLeft = (min == 0) ? left : value[min - 1];

        char right = value[max];
        char nextRight = (max == inputValueCharLength - 1) ? right : value[max - 1];

        if (char.IsLetter(left) && !char.IsUpper(left) && char.IsWhiteSpace(previousLeft))
        {
            valueAsCharArray[min] = char.ToUpper(left);
        }

        if (char.IsLetter(right) && !char.IsUpper(right) && char.IsWhiteSpace(nextRight))
        {
            valueAsCharArray[max] = char.ToUpper(right);
        }

        min++;
        max--;
    }

    return new string(valueAsCharArray);
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
RShp
  • 1
0

jspcal's answer as a string extension.

File Program.cs

class Program
{
    static void Main(string[] args)
    {
        var myText = "MYTEXT";
        Console.WriteLine(myText.ToTitleCase()); //Mytext
    }
}

File StringExtensions.cs

using System;
public static class StringExtensions
{

    public static string ToTitleCase(this string str)
    {
        if (str == null)
            return null;

        return System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(str.ToLower());
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Joel Wiklund
  • 1,697
  • 2
  • 18
  • 24