Click here to Skip to main content
15,885,278 members
Articles / Programming Languages / C#
Alternative
Tip/Trick

How to Toggle String Case in .NET

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
17 Feb 2011CPOL1 min read 7.4K   2   1
Couldn't resist: The following is a rewrite of Alternative 9, ToggleCaseHA()This is an unmanaged version which does direct manipulation of the input stringunsafe static string ToggleCaseUnmanaged(string str){ fixed(char* p = str) { for(int i=str.Length-1;i!=-1;--i)...
Couldn't resist: The following is a rewrite of Alternative 9, ToggleCaseHA()

This is an unmanaged version which does direct manipulation of the input string

C#
unsafe static string ToggleCaseUnmanaged(string str)
{
    fixed(char* p = str)
    {
        for(int i=str.Length-1;i!=-1;--i)
        {
            char ch = p[i];
            char foo = (char)(ch & ~0x20);
            if((foo >= 0x41 && foo <= 0x5a) || (foo >= 0xc0 && foo<=0xde && foo != 0xd7))
            {
                p[i] = (char)(ch ^ 0x20);
            }
            else if((foo == 0xdf || ch>0xff) && char.IsLetter(ch))
            {
                p[i] = char.IsLower(ch) ? char.ToUpper(ch) : ch;
            }
        }
    }

    return str;
}


WARNING: This version will change the SOURCE string instead of creating a copy.

Using test phrase 4 available on http://webinfocentral.com/resources/toggleCaseAlgorithm.aspx[^] with 100.000 iterations:

ToggleCaseHA: 165,4507 milliseconds
ToggleCaseByCeChode: 117,3497 milliseconds
ToggleCaseUnmanaged: 67,367 milliseconds

----------------------------------------
Dear Michael,

Thanks for sharing this code snippet. There is minor bug in the code: when working w/Unicode string it does not toggle Lower to Upper (fixed in the following version, see Listing 1.).

Also, there is no need for return string as you already passed it as parameter ByRef and your code modifies it in that way that return value is the same as the value of the string passed as parameter. In production version the function could be void, but in this test version I've used return value for the duration in us.

In terms of performance: when tested on a standard ASCII your version appeared to be a speed champion in our "League of Best Toggle Case Algorithms" :) , but tested on Unicode string it demonstrated performance similar to the algorithm submitted by Henry Ayoola (you could refer to the test page and try the Unicode Test Phrase 2, for example, or enter your own).

Have a great day.
Kind regards,
Alex Bell

Listing 1. Class Library
//**************************************************************************************
// Module           :   ToggleCase.cs
// Description      :   Fast Algorithm to toggle the string case: Upper/Lower
// Note:            :   Using Unsafe code (C#)
//**************************************************************************************
// Developed by     :   Michael B. Hansen, Denmark
// Modified by      :   Alexander Bell, USA
// Date             :   Feb 17 2011
//**************************************************************************************
//// Reference
// http://www.codeproject.com/Tips/158876/How-to-Toggle-String-Case-in-NET.aspx
//// Test site
// http://localhost:11334/WebInfoCentral/RESOURCES/ToggleCaseAlgorithm.aspx
//**************************************************************************************
using System;

namespace ToggleStringCase 
{
    public static class ToggleCase
    {
        /// <summary>
        /// Toggle Case Algorithm using unsafe code (C#)
        /// Performance benchmark
        /// </summary>
        /// <param name="str">string</param>
        /// <returns>string: duration, us</returns>
        unsafe public static string ToggleCaseUnmanagedByMBH(string str)
        {

            DateTime dt = DateTime.Now;
            // using 100001 iterations
            for (int j = 0; j < 100001; j++)
            {
                fixed (char* p = str)
                {
                    for (int i = str.Length - 1; i != -1; --i)
                    {
                        char ch = p[i];
                        char foo = (char)(ch & ~0x20);
                        if ((foo >= 0x41 && foo <= 0x5a) || 
                            (foo >= 0xc0 && foo <= 0xde && foo != 0xd7))
                        {
                            p[i] = (char)(ch ^ 0x20);
                        }
                        else if ((foo == 0xdf || ch > 0xff) && char.IsLetter(ch))
                        {
                            // MOD Alex Bell
                            //p[i] = char.IsLower(ch) ? char.ToUpper(ch) : ch;
                            p[i] = char.IsLower(ch) ? char.ToUpper(ch) : char.ToLower(ch);
                        }
                    }
                }
            }

            // function return duration in us (microseconds)
            TimeSpan ts = DateTime.Now - dt;
            double dur = (double)ts.Milliseconds / 100;
            
            // MOD Alex Bell
            //return str;
            return dur.ToString() + " us";
        }
    }
}
//**************************************************************************************


Listing 2: Calling Function (Button Click event)

C#
protected void Button7_Click(object sender, EventArgs e)
{
    string s = txtBox.Text;
    Label7.Text = ToggleCase.ToggleCaseUnmanagedByMBH(s);
    txtBox.Text = s;
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Founder CWAIN
Denmark Denmark
I have a MCPD .NET 3.5 EAD and a Bsc in computer science, organizational theory and economics.
After more than 24 years working as professional system engineer, I founded the independent consultant agency CWAIN.

Comments and Discussions

 
GeneralAS FYI: It seems like the site does not allow to run unsafe ... Pin
DrABELL17-Feb-11 17:57
DrABELL17-Feb-11 17:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.