dcsimg
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 12 of 12

Thread: A guideline for coding with strings in Windows

Threaded View

  1. #1
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,177

    A guideline for coding with strings in Windows

    Here's what you can do to to write programs that ports cleanly between ANSI and UNICODE. Many questions on this forum are due to the fact that folks have trouble understanding the difference between a char* and a wchar_t* string and how to write code that can cleanly compile under ANSI (MBCS) or UNICODE or how to convert between the two.

    The following are some guidelines that I've found useful:

    1) Understand that C++ projects created with VC++ 2005 and above default to UNICODE, instead of ANSI (MBCS).

    2) Don't write code that hardcodes string with just quotes (i.e " ")
    Code:
    "my string literal that isn't portable between ansi and unicode"
    3) Do use the _T("") macro for string literals. The following will happily switch between ANSI (mbcs) and UNICODE:
    Code:
    _T("my string literal that is portable between ansi and unicode")
    4) Don't use char* in your code. If you need a pointer to a string, use LPTSTR or LPCTSTR instead (this makes it 'character' portable).

    5) Don't declare buffers as
    Code:
    char buffer[MAX_PATH];
    6) Do declare string buffers as
    Code:
    #include <tchar.h>
    TCHAR buffer[MAX_PATH];
    7) Do use a string class instead of using a raw string buffer. Use std::string or std::wstring. To make this work in ANSI or UNICODE, use the old trick of type defining it as a Tstring
    Code:
    // The following STL components are available in either wchar_t or char forms.
    #ifndef _TSTRING  
      #ifdef _UNICODE 
        #define Tstring std::wstring 
        #define Tstringstream std::wstringstream 
        #define Tfstream std::wfstream 
        #define Tiostream std::wiostream 
      #else // #ifdef _UNICODE 
        #define Tstring std::string 
        #define Tstringstream std::stringstream 
        #define Tfstream std::fstream 
        #define Tiostream std::iostream 
      #endif // #ifdef _UNICODE 
      #define _TSTRING
    #endif // #ifndef _TSTRING
    8) Do use CString rather over Tstring. CString isn't just for MFC anymore. If you are using a compiler newer than VC6, Microsoft has redefined MFC's CString class so you don't need to include MFC to use it anymore. Just include <atlstr.h> in your non-MFC project. P.S. this negates 7) above - it's called progress.

    9) Don't use the old runtime library string functions such as sprintf or sprintf_s.

    10) Use the TCHAR (and new safe) equivalents, such as:
    Code:
    _stprintf_s
    _stscanf_s
    etc.
    11) Do use the String Conversion Macros. When converting from ANSI (MBCS) to UNICODE or UNICODE to ANSI (MBCS) or either to/from BSTR, leverage these macros.

    Conversion Key
    Code:
    SourceType/DestinationType  Description  
    A      ANSI character string.
    W     Unicode character string.
    T       Generic character string (equivalent to W when _UNICODE
            is defined, equivalent to A otherwise).
    OLE  OLE character string.
    Here's an incomplete list:
    Code:
    T2A     // When you need to convert a generic string (either ANSI or UNICODE) and always make it ANSI.
    T2W    // Same as above except it always makes it UNICODE.
    A2T     // When the string is ANSI and you need to make it a generic string
    W2T    // When the string is UNICODE and you need to make it a generic string
    OLE2T // From a BSTR to a generic string
    T2OLE // From a generic string to a BSTR
    Note: In VC6, the conversion macros did stacked based allocations during the conversion process. As such they didn't handle large strings very well. In the newer compilers, the conversion macros are smarter and allocate small strings on the stack and larger strings on the heap. But don't worry about freeing memory allocated for the conversion, because the macros will do the right thing and free any allocated memory.

    12) Do use CComBSTR or _bstr_t when working with BSTRs and COM. These classes are slick and take care of the drugery of COM string allocation and freeing. As a bonus these classes can do the correct string conversions as well.

    13) If you are writing code using VC2005 and above and the code is compiled for UNICODE and the code will never be run under ANSI, you can hardcode your string literals with L"" instead of _T(""). I should mention that it's still okay to use _T("").

    Lastly consider this programming mindset: Allow any string manipulation within your program to be generic based (in other words, write in T or generic string), and convert any string inputs or outputs as needed. For example if I need to call some methods that pass me an ANSI string, I want to immediately convert it to a T (using the A2T macro) so I can work with it in the rest of the program. Similarly, if I need to call a function that only takes a wchar*, I simply convert from the generic T (using the T2W macro) inline as I make the call.

    This allows all internal program manipulation to be in ANSI or UNICODE (based on the build settings) and the programmer only has to explicitly convert when receiving data from/to the outside. Note: Windows api's that take string generally do not need to be converted (because the appropriate xxxA or xxxW versions will automatically get called).

    A final comment. If your program has a UI or uses Windows api's and is targeted to run under NT (Win2K, XP, Vista, etc.), consider building your application as UNICODE. Understand if you build your program as ANSI (MCBS), every call you make to an Windows api (that takes a string) will undergo a string conversion. This is because the xxxA api's just internally converts everything to UNICODE and then calls the xxxW api version.

    Comments? Suggestions?
    Last edited by Arjay; May 23rd, 2008 at 03:07 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width




On-Demand Webinars (sponsored)