Several problems between tchar and std :: string

xiaoxiao2021-03-05  31

I often use the Std :: String class of the Standard Template Library (STL) in the C program, but I have encountered problems when using Unicode. When using a conventional C style string, I can use Tchar and _T macro, so it can be compiled for Unicode or ASCII, but I always found that this ASCII / Unicode combination is difficult to use with STL's String class. . do you have any good advice?

Naren J.

Yes, once you know how tchar and _t work, then this problem is simple. Basic thinking is that tchar is char, or Wchar_t, depending on _unicode's value:

// Abridged from tchar.h

#ifdef _unicode

Typedef wchar_t tchar;

#define __t (x) l ## x

#ELSE

Typedef char tchar;

#define __t (x) x

#ENDIF When you select a Unicode character set in the engineering settings, the compiler will compile using the _unicode definition. If you choose MBCS (multibly character set), the compiler will not be defined by _unicode definition. Everything depends on the value of _unicode. Similarly, each Windows API function using the character pointer will have a A (ASCII) and a W (Wide / Unicode) version, and the actual definition of these versions is also determined by the value of _unicode:

#ifdef unicode

#define createfile createfilew

#ELSE

#define CreateFile CreateFilea

#endif, _tprintf and _tscanf correspond to Printf and Scanf. All versions of "T" have replaced Chars using Tchars. So how do you apply the above to std :: string? Very simple. STL already has a WSTRING class defined using wide character (defined in the xstring header file). String and wstring are template classes defined using TypedEf, based on Basic_String, with it to create any character types of string classes. The following is STL definition String and WString:

// (from include / xstring)

Typedef Basic_String

Char_traits , allocator >

String;

Typedef Basic_String

Char_traits , allocator >>

WString; Template is parameterized by the potential character type (char or wchar_t), so for TCHAR versions, what to do is to use TCHAR to imitate the definition.

Typedef Basic_String

Char_traits ,

Allocator >>>

Tstring; now there is a TSTRING, which is based on tchar - that is, it either char, either Wchar_t, depending on the _unicoDe value. The above demonstrations are indicated by how the STL uses Basic_String to implement any type of string. Defining a new TypedEf is not the most effective way to solve this problem. A better way is based on String and WString to simply define TString, as follows: #ifdef _unicode

#define tstring wstring

#ELSE

#define Tstring String

#ndif This method is better because String and WString have defined String and WString, and why do you want to use templates to define a new and one of the same string classes? Temporarily call it tstring. You can use #define to define TString as string and wrstring, which avoids creating another template class (although today's compiler is very intelligent, if it discards the copy, I am not surprising). [Edit Update-2004/07/30: TypeDef does not create a new class, just introducing a limited range for a type, TypeDef will never define a new type]. Anyway, once you define TSTRING, you can encode like this:

Tstring s = _t ("Hello, World");

_tprintf (_t ("s =% s / n"), s.c_str ()); Basic_String :: c_str method Returns a constant pointer pointing to the potential character type; here, the character type either const char *, or Const Wchar_t *.

Figure 2 is a simple demonstration program illustrating the usage of TString. It writes "Hello, World" into a file and reports how many bytes written. I set up the project in order to generate the Debug version with Unicode and generate the Release version with MBCS. You can compile / generate and run the program separately, then compare results. Figure 3 shows the example of an example.

Figure 3 TSTRING running

By the way, MFC and ATL have now married so that they all use the same string implementation. The combined implementation uses a template class called CStringt, in a sense, its mechanism is similar to STL's Basic_String, with it to create a CSTRING class in accordance with any potential character type. Three string types are defined in the MFC contain file AFXSTR.H, as follows:

Typedef atl :: cstringt

Strtraitmfc > cstringw;

Typedef atl :: cstringt

Strtraitmfc > cstringa;

Typedef atl :: cstringt

Strtraitmfc > cstring; CStringw, CStringA and CString are what you expect: CString Wide characters, ASCII, and Tchar versions.

So, which one is better, STL is also cstirng? Both are very good, you can choose your favorite one. But there is a problem to consider: is why you want to link which library, and whether you are already using MFC / ATL. From the point of view of the coding, I prefer the two features of CString: One is to initialize CString whether it is using wide character or char, which can be easily initialized.

CSTRING S1 = "foo";

CSTRING S2 = _T ("bar"); these two initialization work normally because CString has made all necessary conversions. With STL strings, you must use _t () to initialize TString, because you can't initialize a WString via a char *, and vice versa.

Its second is that CString automatically converts the LPCTSTR, you can code like this:

CString S;

LPCTSTR LPSZ = S; On the other hand, the use of STL must explicitly call C_STR to complete this conversion. This is really a bit a bit of picky, some people will argue that this can better understand when to conversion. For example, using CString in a function of C style variable parameters may have trouble, like Printf:

Printf ("S =% S / N", S); // Error

Printf ("S =% S / N", (LPCTSTSTSTSTSTS); / / must not have a mandatory type conversion, resulting in some garbage results, because PrintF wants S is char *. I am sure that many readers have made this mistake. Preventing this disaster is an unquestionable reason for the STL designer without providing a conversion operator. But insist that you want to call C_STR. Generally speaking, I like to use STL guys to tend to be theory and learn, while RedMontonians (translator: refers to Microsoft) more attention to practical and scattered. Oh, no matter what, the practical difference between std :: string and cstring is negligible.

转载请注明原文地址:https://www.9cbs.com/read-35286.html

New Post(0)