Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
West Wind WebSurge - Rest Client and Http Load Testing for Windows

Returning a proper case string in .Net


:P
On this page:

 

Ok, this is a simple one I ran across today after I was scavenging through my code trying to find a proper case converter I’d written a while back. Turns out there’s a much easier way using the TextInfo class:

 

public static string ProperCase(string Input)

{

      return System.Threading.Thread.CurrentThread.

             CurrentCulture.TextInfo.ToTitleCase(Input);

}

 

This has the additional advantage that it is culture aware since some countries don’t upper and lower the same way we do.

 

Who’d thunk this is available? FWIW, various Text formatting commands don’t live on the string class itself. I often use RegEx (for replacements especially), StringBuilder and now TextInfo for many string tasks. It’d sure would be nice if some of this was better cross referenced in the docs.

 

Apparently I’m not the only one who hasn’t found this one – I found at least 10 different snippets/articles that do this manually as well. This once again shows that knowing the BCL is what it’s all about – it’s probably in there if you can only find it <g>.


The Voices of Reason


 

Scott Mitchell
April 14, 2004

# re: Returning a proper case string in .Net

It's too bad that they didn't make this a method of the String class, as it could just delegate the functionality to the TextInfo.ToTitleCase() method...

Dale Rainsford
June 02, 2004

# re: Returning a proper case string in .Net

Be careful when using this method. If you have the word all in uppercase it does not proper case, it leaves it in uppercase. The help mentions that implementation is subject to change.


Craig
December 08, 2004

# re: Returning a proper case string in .Net

this solves the upper case issue

public static string ProperCase(string Input)

{

return System.Threading.Thread.CurrentThread.

CurrentCulture.TextInfo.ToTitleCase(Input.ToLower() );

}


Stephen
February 15, 2005

# re: Returning a proper case string in .Net

Thank you for your comments and solution for strings in all uppercase. That was driving me nuts and this was the only place I found a comment about it.

Matt
February 17, 2005

# re: Returning a proper case string in .Net

As per Stephen's comments above, thanks for the fix for the uppercase thing. Thought I was doing something stupid!

kkc
March 08, 2005

# Returning a proper case string in .Net

Private Function ProperCase(ByVal strValue As String) As String
Try
ProperCase = StrConv(strValue, VbStrConv.ProperCase)
Catch ex As System.Exception
'Error hadler goes here
End Try
End Function


kkc
March 08, 2005

# Returning a proper case string in .Net

Private Function ProperCase(ByVal strValue As String) As String
Try
ProperCase = StrConv(strValue, VbStrConv.ProperCase)
Catch ex As System.Exception
'Error hadler goes here
End Try
End Function


Joe
February 07, 2006

# re: Returning a proper case string in .Net

This works well for title case, but how about proper case? It doesn't properly capitalize O'Conner or McDonald (at least on my machine). If I am mistaken, please post your correction. I would appreciate it.

Joe
February 07, 2006

# re: Returning a proper case string in .Net

Sorry, here's a correwction to my previous post.

public static string ProperCase(string Input)
{
return System.Threading.Thread.CurrentThread.
CurrentCulture.TextInfo.ToTitleCase(Input);

}

works well for title case, but doesn't capitalize O'Conner or McDonald correctly.

I'm trying to avoid things like StrConv and rely on the Framework and not on VB6-style implementations.

fwsteal
September 12, 2006

# re: Returning a proper case string in .Net

i used it as such to list the contents of a directory and drop the file extension:

row[0] = ProperCase(info.Name);

public static string ProperCase(string Input)
{
char[] trimChars = { '.', 'a', 's', 'p', 'x' };
return System.Threading.Thread.CurrentThread.
CurrentCulture.TextInfo.ToTitleCase(Input.TrimEnd(trimChars));
}


Stacey
January 31, 2007

# re: Returning a proper case string in .Net

to handle " Mc " and " O' " :

        private string properCase(string Input) 
        {
            string output;
            output = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(Input.ToLower());
            output = output.Substring(0,2).CompareTo("Mc") == 0 ? "Mc" + properCase(output.Substring(2)) : output;
            output = output.Substring(0,2).CompareTo("O'") == 0 ? "O'" + properCase(output.Substring(2)) : output;
            return output;
        }

sgt13echo
October 02, 2007

# re: Returning a proper case string in .Net

I am trying this and if I have a string like
"1234 WEST AVE. TAMPA BAY FL 33510"

The result is:
1234 West Ave. Tampa Bay Fl 33510"

Notice the "FL" now is "Fl'

I thought this would resolve it, but unfortunately it didn't, any help?

output = output.Substring(0, 2).CompareTo("FL") == 0 ? "FL" + properCase(output.Substring(2)) : output;

dsmerchek
October 09, 2007

# re: Returning a proper case string in .Net

shouldn't
output = output.Substring(0, 2).CompareTo("FL") == 0 ? "FL" + properCase(output.Substring(2)) : output;
be
output = output.Substring(0, 2).CompareTo("Fl") == 0 ? "FL" + properCase(output.Substring(2)) : output;

DotNetKicks.com
March 27, 2008

# Returning a proper case string in .Net

You've been kicked (a good thing) - Trackback from DotNetKicks.com

Patrick
September 10, 2008

# re: Returning a proper case string in .Net

Stacey,

Awesome Solution! Recursive call to the method. Brilliant!!!

string output;
output = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(value.ToLower());
output = output.Substring(0, 2).CompareTo("Mc") == 0 ? "Mc" + ProperCase(output.Substring(2)) : output;
output = output.Substring(0, 2).CompareTo("O'") == 0 ? "O'" + ProperCase(output.Substring(2)) : output;
return output;

Thanks!!

Brett
November 05, 2008

# re: Returning a proper case string in .Net

The only problem with Stacey's solution is that it will only work when MC or O' is the first word in the string.

In other words, "JOHN MCLOVIN" will be "John Mclovin"

To get "John McLovin", looks like we need to split the post ToTitleCase output and handle the words separately.

Vikram Karumbaiah
April 16, 2009

# re: Returning a proper case string in .Net

This should solve the problem with names starting with Mc and O' as well as ending with 's

        /// <summary>
        /// Capitalize the first character of all words in the given string
        /// </summary>
        /// <param name="textToformat">Text to format as string</param>
        /// <returns>Returns the formatted text</returns>
        public static string InitCap(string textToformat)
        {
            // Got this code from http://www.windowsdevcenter.com/pub/a/oreilly/windows/news/csharp_0101.html
            string pattern = @"\w+|\W+";
            string result = "";
            Boolean capitalizeNext = true;
            foreach (Match m in Regex.Matches(textToformat, pattern))
            {
                // get the matched string
                string x = m.ToString().ToLower();

                // if the first char is lower case
                if (char.IsLower(x[0]) && capitalizeNext)
                {
                    // capitalize it
                    x = char.ToUpper(x[0]) + x.Substring(1, x.Length - 1);                    
                }

                // Check if the word starts with Mc
                if (x[0] == 'M' && x[1] == 'c' && !String.IsNullOrEmpty(x[2].ToString()))
                {
                    // Capitalize the letter after Mc
                    x = "Mc" + char.ToUpper(x[2]) + x.Substring(3, x.Length - 3);

                }

                if (capitalizeNext == false)
                    capitalizeNext = true;
                
                // if the apostrophe is at the end i.e. Andrew's
                // then do not capitalize the next letter
                if (x[0].ToString() == "'" && m.NextMatch().ToString().Length == 1)
                {
                    capitalizeNext = false;
                }

                // collect all text
                result += x;
            }
            return result;
        }

Monty
July 11, 2009

# re: Returning a proper case string in .Net

Thanks Vikram, good stuff there! Besides the O'Whatevers and McWhatevers, what I like about yours over the StrConv() method is that a value like "52nd Street" does not become "52Nd Street". Thanks.

(Of course, is it any surprise a good algorithm for this would come from a place named "O'Reilly"? ;-)

Mark Kamoski
October 05, 2009

# re: Returning a proper case string in .Net

Vikram --

You may need to allow for names like...

D'AGOSTINO >>> D'Agostino

...etc.

Just a thought.

HTH.

Thank you.

-- Mark Kamoski

Mark Kamoski
October 05, 2009

# re: Returning a proper case string in .Net

Vikram --

I think you need to change from this...

if (x[0] == 'M' && x[1] == 'c' && !String.IsNullOrEmpty(x[2].ToString()))

...to this...

if (x[0] == 'M' && x.Length > 1 && x[1] == 'c' && !String.IsNullOrEmpty(x[2].ToString()))

...to allow for input that is a string containing a single-character that is the letter "M".

HTH.

Thank you.

-- Mark Kamoski

Mark Kamoski
October 05, 2009

# re: Returning a proper case string in .Net


All --

FWIW, I tweaked the code a bit to suit my needs, which may help others.

/// <summary>
/// This method will capitalize the first character of all words in the given string.
/// </summary>
/// <param name="textToformat">Text to format as string.</param>
/// <param name="addPeriodAfterSingleLetter">Add a period if desired.</param>
/// <returns>Returns the formatted text.</returns>
public static string GetNameProperCasing(string textToformat, bool addPeriodAfterSingleLetter)
{
    //This code is modified from the http://www.windowsdevcenter.com/pub/a/oreilly/windows/news/csharp_0101.html link and related posts.

    string pattern = @"\w+|\W+";
    string result = "";
    Boolean capitalizeNext = true;

    foreach (Match m in Regex.Matches(textToformat, pattern))
    {
        // get the matched string
        string x = m.ToString().ToLower();

        // if the first char is lower case
        if (char.IsLower(x[0]) && capitalizeNext)
        {
            // capitalize it
            x = char.ToUpper(x[0]) + x.Substring(1, x.Length - 1);
        }

        // Check if the word starts with Mc
        //if (x[0] == 'M' && x[1] == 'c' && !String.IsNullOrEmpty(x[2].ToString()))
        if (x[0] == 'M' && x.Length > 1 && x[1] == 'c' && !String.IsNullOrEmpty(x[2].ToString()))
        {
            // Capitalize the letter after Mc
            x = "Mc" + char.ToUpper(x[2]) + x.Substring(3, x.Length - 3);
        }

        if (capitalizeNext == false)
            capitalizeNext = true;

        // if the apostrophe is at the end i.e. Andrew's
        // then do not capitalize the next letter
        if (x[0].ToString() == "'" && m.NextMatch().ToString().Length == 1)
        {
            capitalizeNext = false;
        }

        // collect all text
        result += x;
    }

    if ((addPeriodAfterSingleLetter) && (result.Length == 1))
    {
        result = result + ".";
    }

    return result;
}


HTH.

Thank you.

-- Mark Kamoski

Roy Cotton
October 02, 2010

# re: Returning a proper case string in .Net

Wow I can't once again, one line of code will save me lots of work/time on my project, Keep it simple. Thanks rgc

dingo99
October 20, 2010

# re: Returning a proper case string in .Net

grrr! guys is it that hard?!! below fails on "mc";

if (x[0] == 'M' && x.Length > 1 && x[1] == 'c' && !String.IsNullOrEmpty(x[2].ToString()))

so clearly it needs to be x.Length > 2.

Same principal can be used for Mac, although there seems to be no definitive pattern, ie MacDonald, but not Macy or Mackie, MacPherson or Macpherson.
ok forget Mac, DiPi, de Jong, gotta love the english language!

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024