什么是TCHAR
字符串,如LPTSTR
和LPCTSTR
我怎么能与这些工作?当我在Visual Studio中创建新项目时,它将为我创建以下代码:
#include <tchar.h>
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
例如,如何连接所有命令行参数?
如果要打开第一个命令行参数给定名称的文件,该怎么办?在Windows API定义“A”和它的许多功能,如“W”的版本CreateFile
,CreateFileA
和CreateFileW
; 那么这些之间有什么区别,我应该使用哪一个?
首先让我说,您最好不要TCHAR
用于新的Windows项目,而应直接使用Unicode。关于实际答案:
我们需要了解的第一件事是字符集如何在Visual Studio中工作。项目属性页面具有一个选择使用的字符集的选项:
根据您选择的三个选项中的哪一个,许多定义都会更改以适应所选的字符集。主要分为三类:字符串,来自的字符串例程tchar.h
和API函数:
TCHAR = char
使用ANSI编码,其中您将系统的标准8位代码页用于字符串。所有tchar.h
字符串例程都使用基本char
版本。所有与字符串一起使用的API函数都将使用API函数的“ A”版本。TCHAR = wchar_t
使用UTF-16编码。所有tchar.h
字符串例程都使用wchar_t
版本。所有与字符串一起使用的API函数都将使用API函数的“ W”版本。TCHAR = char
使用某些多字节编码方案,“多字节”对应于。所有tchar.h
字符串例程都使用多字节字符集版本。所有与字符串一起使用的API函数都将使用API函数的“ A”版本。相关阅读:关于Visual Studio 2010中的“字符集”选项
该tchar.h
标题是使用通用名称为在字符串中使用C字符串操作,即切换到给定字符集的正确功能的帮手。例如,_tcscat
将切换为strcat
(未设置),wcscat
(unicode)或_mbscat
(mbcs)。_tcslen
将切换为strlen
(未设置),wcslen
(unicode)或strlen
(mbcs)。
通过将所有_txxx
符号定义为可评估正确功能的宏来进行切换,具体取决于编译器的切换。
其背后的想法是,您可以使用from而不是常规字符串函数from来使用与编码无关的类型TCHAR
(或_TCHAR
)和对它们进行编码的不可知函数。tchar.h
string.h
同样,_tmain
被定义为main
或wmain
。另请参见:C ++中_tmain()和main()有什么区别?
_T(..)
定义了一个辅助宏,用于获取正确类型的字符串文字("regular literals"
或)L"wchar_t literals"
。
请参阅此处提到的警告:TCHAR是否仍然有用?-dan04的答案
_tmain
例子对于问题中的main的示例,以下代码将所有作为命令行参数传递的字符串连接在一起。
int _tmain(int argc, _TCHAR *argv[])
{
TCHAR szCommandLine[1024];
if (argc < 2) return 0;
_tcscpy(szCommandLine, argv[1]);
for (int i = 2; i < argc; ++i)
{
_tcscat(szCommandLine, _T(" "));
_tcscat(szCommandLine, argv[i]);
}
/* szCommandLine now contains the command line arguments */
return 0;
}
(省略了错误检查)此代码适用于字符集的所有三种情况,因为在我们使用过的所有地方TCHAR
,tchar.h
字符串函数都_T
适用于字符串文字。_T(..)
编写此类程序时,忘记用字符串文字包围是编译器错误的常见原因TCHAR
。如果我们还没有做完所有这些事情,那么切换字符集将导致代码在运行时无法编译,或者更糟糕的是编译但行为异常。
在字符串上工作的Windows API函数(例如CreateFile
和)GetCurrentDirectory
在Windows标头中作为宏(如tchar.h
宏)切换为“ A”版或“ W”版实现。例如,CreateFile
是CreateFileA
为ANSI和MBCS和CreateFileW
Unicode定义的宏。
每当您在代码中使用平面形式(不带“ A”或“ W”)时,实际调用的函数将根据所选字符集进行切换。您可以通过使用显式的“ A”或“ W”名称来强制使用特定版本。
结论是,除非应始终引用特定版本,否则应始终使用非限定名称,而与字符集选项无关。
对于问题中的示例,我们要在其中打开第一个参数给出的文件:
int _tmain(int argc, _TCHAR *argv[])
{
if (argc < 2) return 1;
HANDLE hFile = CreateFile(argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
/* Read from file and do other stuff */
...
CloseHandle(hFile);
return 0;
}
(省略了错误检查)请注意,在此示例中,我们不需要使用任何TCHAR
特定的东西,因为宏定义已经为我们解决了这一问题。
我们已经看到了如何使用tchar.h
例程来使用C样式字符串操作来与TCHAR
s一起工作,但是如果我们可以利用C ++string
来与之一起工作,那将是很好的。
我的建议最重要的是不要使用TCHAR
,而是直接使用Unicode,请参阅“结论”部分,但是如果您想使用TCHAR
它,可以执行以下操作。
为了使用TCHAR
,我们要的是一个实例std::basic_string
使用TCHAR
。你可以做到这一点typedef
荷兰国际集团自己tstring
:
typedef std::basic_string<TCHAR> tstring;
对于字符串文字,请不要忘记使用_T
。
您还需要使用的正确版本cin
和cout
。您可以使用引用来实现tcin
和tcout
:
#if defined(_UNICODE)
std::wistream &tcin = wcin;
std::wostream &tcout = wcout;
#else
std::istream &tcin = cin;
std::ostream &tcout = cout;
#end
这应该使您几乎可以做任何事情。偶尔会有例外,例如std::to_string
和std::to_wstring
,您可以找到类似的解决方法。
这个答案(希望如此)详细说明了什么TCHAR
是它,以及如何与Visual Studio和Windows标头结合使用。但是,我们还应该怀疑是否要使用它。
我的建议是直接对所有新的Windows程序使用Unicode,并且根本不要使用Unicode TCHAR
!
其他人也给出相同的建议:TCHAR是否仍然有用?
要在创建新项目后使用Unicode,请首先确保将字符集设置为Unicode。然后,#include <tchar.h>
从您的源文件(或从中stdafx.h
)删除。修复的任何TCHAR
或_TCHAR
到wchar_t
和_tmain
到wmain
:
int wmain(int argc, wchar_t *argv[])
对于非控制台项目,Windows应用程序的入口点是WinMain
并且将在TCHAR
-jargon中显示为
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
并且应该成为
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
此后,仅使用wchar_t
字符串和/或std::wstring
s。
sizeof(szMyString)
使用TCHAR
数组(字符串)时编写时要小心,因为对于ANSI,这是字符和字节的大小;对于Unicode,这只是字节的大小,字符数最多为一半;对于MBCS,这是最大字符数。字节大小和字符数可以相等或可以不相等。Unicode和MBCS都可以使用多个TCHAR
来编码单个字符。TCHAR
东西和固定的东西混在一起char
或wchar_t
很烦人;您必须使用正确的代码页将字符串从一个转换为另一个!在一般情况下,简单的副本将不起作用。_UNICODE
与和之间会有细微的差别UNICODE
。请参阅为什么同时使用UNICODE和_UNICODE?一个很好的补充答案是:Windows上的MBCS和UTF-8之间的区别
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句