Click here to Skip to main content
Click here to Skip to main content

How to reverese a string in C#/.NET with almost one line of code using P/Invoke

By , 4 Jan 2013
 

Introduction 

This short article shows how to use an exported function from the Microsoft Visual C Run-Time Library wich is almost available on any Windows System starting Windows 95 to the latest Windows 8 to reverse a string in C# within a single line of code.

Background 

At times we need to reverese a string in .NET for particular reasons. In general developers code their own functions and classes holding some sort of class/function pair to accomplish this task, unless there is no ready to use code or external library/assembly available. But the implementation itself can heavily differ in code quality, speed and size, depending on the developers skills and generated code by the compiler. Keep in your mind, that there are many more compilers beside the broadly used Microsoft compilers, who can generate IL code and they can differ in optimization and other variables which finally can affect the applications performance. By using the Microsoft Visual C Run-Time Library functions _strrev() and/or _wcsrev() we can quickly reverse a string within a single line of code. These functions can easily be imported and used by a .NET project using the .NET Framework's Interop techniques. CodeProject has a lot of great articles on the Interop topic, so there is no need to explain what .NET Interop in detail is. By using these two Microsoft supplied functions, there are some major advantages over external third-party libraries: 

  • The Microsoft Visual C Run-Time Library is available without exception on any Windows system starting from Windows 95 to the latest Windows 8, covering the 32- and 64 bit variants. The library itself is de-facto an integral part of the Windows system and many Windows applications itself depend on its existence to work properly.
  • The functions are very well documented and very stable, so they can be safely used in any project without exceptions. Beside the fact that there are different version available and possibly installed on a system, the input and output data is ALWAYS the same on any library version.
  • The library code is maintained by Microsoft and any bugfixes will be available on any Windows systems with new or update releases of the Microsoft Visual C Run-Time Library.
  • The code runs pretty fast. Fast means here that the implementation code, the code inside the library, is written in plain C and the only thing to marshal between the library and the managed application is the string (in fact the string pointer) itself. This can make the reversing operation on even large strings very fast.

Using the code   

Using the code is pretty straightforward and the C# signatures can easily be imported to any .NET language like e.g. VB.NET by simply translating them into their language counterparts. The project files hold a simple C# Visual Studio 2008 file format Forms expample project that shows you a simple application with basic commented code on how to use these two functions. Lets have a look at the code now:

The very first thing we have to do is to import the System.Runtime.InteropServices namespace into our project in order to be able to use the Interop mechanism and use the two functions in our project:

using System.Runtime.InteropServices;      

Now we can declare our import functions signatures inside a class in our project. They have to look like this:

/*  Original documentation for _strrev, _wcsrev, _mbsrev, _mbsrev_l 
 *  on the Micdrosoft MSDN Libary pages: 
 *  http://msdn.microsoft.com/en-us/library/9hby7w40%28v=vs.80%29.aspx
 */

// UNICODE variant
[DllImport("msvcrt.dll",
    CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.LPWStr)]
public static extern string _wcsrev(
    [MarshalAs(UnmanagedType.LPWStr)]
    [In] string str);

// ANSI variant
[DllImport("msvcrt.dll",
    CharSet = CharSet.Ansi)]
[return: MarshalAs(UnmanagedType.LPStr)]
public static extern string _strrev(
    [MarshalAs(UnmanagedType.LPStr)]
    [In] string str);

That's it! Now they can be used like any C# function within your code: Here is a short example to show you how:

public partial class Form1 : Form
{
    /*  Original documentation for _strrev, _wcsrev, _mbsrev, _mbsrev_l 
     *  on the Micdrosoft MSDN Libary pages: 
     *  http://msdn.microsoft.com/en-us/library/9hby7w40%28v=vs.80%29.aspx
     */

    // UNICODE variant
    [DllImport("msvcrt.dll",
        CharSet = CharSet.Unicode)]
    [return: MarshalAs(UnmanagedType.LPWStr)]
    public static extern string _wcsrev(
        [MarshalAs(UnmanagedType.LPWStr)]
        [In] string str);

    // ANSI variant
    [DllImport("msvcrt.dll",
        CharSet = CharSet.Ansi)]
    [return: MarshalAs(UnmanagedType.LPStr)]
    public static extern string _strrev(
        [MarshalAs(UnmanagedType.LPStr)]
        [In] string str);
 
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        this.Close();
    }

    private void button2_Click(object sender, EventArgs e)
    {
        // make sure you pass in a valid string
        // passing a null will lead to a System.AccessViolationException exception
        if (string.IsNullOrEmpty(this.textBox1.Text.Trim()) == true)
        {
            MessageBox.Show("The original string cant be empty. Please set the original text first!",
                this.Text,
                MessageBoxButtons.OK,
                MessageBoxIcon.Exclamation);

            return;
        }

        try
        {
            //we are using the UNICODE variant, since all strings in .NET are UNICODE by default
            this.textBox2.Text = _wcsrev(textBox1.Text);
        }
        catch (Exception err)
        {
            MessageBox.Show("Error reversing string: " + err.Message,
                this.Text,
                MessageBoxButtons.OK,
                MessageBoxIcon.Error);
        }
    }
}

Important to know

Please make sure that you pass in a valid string as the functions parameter and not a null. Passing in something like "" or a string.Empty (both are the same at runtime) is perfectly fine, but passing in a null as parameter will definitely lead to a System.AccessViolationException kind of exception and crash your application if you dont handle the exception inside a try/catch block.

History 

  • 03/01/13 - Initial release
  • 04/01/13 - Changed topic text to make it more fit the approach technique

External links  

Original documentation for _strrev, _wcsrev, _mbsrev, _mbsrev_l:
http://msdn.microsoft.com/en-us/library/9hby7w40%28v=vs.80%29.aspx.

License

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

About the Author

Kerem Guemruekcue
Software Developer (Senior)
Germany Germany
Member
I am a former developer from germany who has worked on a broad range of IT technologies and software/hardware related tasks regarding Microsoft Windows and Linux systems. My primary focus and field of application was the development of system software/hardware, troubleshooting on software/hardware, designing and teaching how to write code and build working systems, but i am not tied to anything special at all. Currently i am developing in C, C++, C# and a little in Assembly if there is need for it. Beside that there are lots of other languages and stuff, but nothing really worth to be menitioned here. In my spare time i try to be as much as i can with my family, i love sports and reading. I also try to contribute code and solutions and help wherever i can.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralRe: Why notmemberAlois Kraus4 Jan '13 - 4:01 
Because it is wrong.
 
UTF-16 allows compound unicode chars which span several chars. You know that there are characters which have a value >0xffff (e.g. some chinese chars). If you simply reverse the char array these then you end up with invalid unicode chars.
A more serious thing if you have accent chars in the string the reversed string will now have an accent char pointing to the wrong char.
 
John Skeet has a nice article online about this and other commond failures: http://msmvps.com/blogs/jon_skeet/archive/2009/11/02/omg-ponies-aka-humanity-epic-fail.aspx[^]
 
Yours,
Alois Kraus
GeneralRe: Why notmemberKerem Guemruekcue4 Jan '13 - 4:13 
Interesting information,...
 
-----------------------
Beste Grüsse / Best regards / Votre bien devoue
Kerem Gümrükcü
-----------------------
"This reply is provided as is, without warranty express or implied."
GeneralRe: Why notmemberJon Andersson4 Jan '13 - 4:23 
Interesting!
I guess you need to check that when reversing.
 
Found this solution http://code.logos.com/blog/2008/10/how_to_reverse_a_unicode_string_in_c.html[^]
GeneralRe: Why notmemberAndreas Gieriet5 Jan '13 - 11:22 
Even I knew about this - I did not think of it Frown | :-(
See also my comment: After all, I vote for Microsoft.VisualBasic.Strings.StrReverse(...)[^].
Cheers
Andi
GeneralThat looks like a lot more than "one line of code"memberPIEBALDconsult3 Jan '13 - 14:42 
How about retitling it to indicate "how to use P/Invoke to call a Windows string reverse function"?
GeneralRe: That looks like a lot more than "one line of code"memberKerem Guemruekcue3 Jan '13 - 17:08 
Hi,
 
yes, this could be also an option to name the article.
 
best
 
K.
 
-----------------------
Beste Grüsse / Best regards / Votre bien devoue
Kerem Gümrükcü
-----------------------
"This reply is provided as is, without warranty express or implied."
QuestionNice onememberRobert Slaney3 Jan '13 - 13:46 
Could use an extension method to hide the implementation
 
public static class StringExtension
{
    // Insert exports here

    public static string Reverse( this string value )
    {
        if ( value == null || value.Length == 1 )
            return value;
 
        return _wcsrev(value);
    }
}

AnswerRe: Nice onememberKerem Guemruekcue3 Jan '13 - 17:11 
Thank you. Extension methods are a good way to use this.
 
-----------------------
Beste Grüsse / Best regards / Votre bien devoue
Kerem Gümrükcü
-----------------------
"This reply is provided as is, without warranty express or implied."

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

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 4 Jan 2013
Article Copyright 2013 by Kerem Guemruekcue
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid