【问题标题】:Visual C++, wchar_t* command-line arguments cannot be compared?Visual C++, wchar_t* 命令行参数不能比较?
【发布时间】:2012-07-11 08:25:17
【问题描述】:

我在尝试根据哪个字符串 argv[1] 等于来实现某个分配时遇到了一些麻烦。

int _tmain(int argc, _TCHAR* argv[]) //wchar_t
{   
    if (argc != 2)
        exit(1);

    if (argv[1] == L"-foo")
        printf("Success!\n");

    wprintf(argv[1]);
    printf("\n");

    system("pause");
    return 0;
}

如果我使用参数“-foo”运行可执行文件,我会收到以下输出:

-foo

应该是:

Success!
-foo

字符串正是我想要的样子,但 if 条件仍然为假。使用 == 运算符,wchar_t 字符串是否根本无法比较?如果是这样,我该如何正确比较它们?

【问题讨论】:

标签: c++ visual-c++ if-statement comparison wchar-t


【解决方案1】:

没关系,明白了。

if (wcscmp(argv[1], L"-foo") == 0)

【讨论】:

  • 其实你的解决方案是错误的,应该是_tcscmp()而不是wcscmp,因为你使用的是_TCHAR。更正了。
  • @Hans Passant:你能解释一下为什么取消我的更改吗?我真的很好奇,因为我认为将 _tmain 和其他一切设置为条件编译为 ANSI 与 Unicode 然后放入 Unicode 或 ANSI 是一个非常坏习惯 - 特定代码 OP 的方式。因此,鉴于问题的上下文(使用_tmain_TCHAR),我很好奇其基本原理是什么。谢谢。
  • @0xc0 - TCHAR 是过时的,没有任何运行版本的 Windows 不是其核心的 Unicode。 _tmain 由项目模板生成。
  • @HansPassant:我明白了,但我坚持认为,除非为了完整性将代码更改为 wmain,否则将特定于字符的函数与依赖于编译时定义的函数混合是一个坏习惯.仅仅因为核心是 Unicode 并不意味着没有很多纯 ANSI 代码。
【解决方案2】:

初步说明:鉴于问题本身的上下文,此答案中的 UnicodeUnicode 字符指的是 UCS-2(最高 XP)和UTF-16(从 XP 开始)编码,可与 宽字符wchar_tWCHAR 和 Win32 API 上下文中的其他术语互换使用。 Unicode 标准提供了多种编码,例如 UTF-8、UTF-16 和 UTF-32 来编码相同数量的字符——标准的不同化身具有不同的范围。 代理代码点用于从基本多语言平面 (BMP) 中转义,大约是前 64K 代码点,因此编码的内容超过了 16 位字符和每个代码点一个字符的编码范围。 代理扩展是为 Unicode 2.0 标准开发的,该标准是在 NT 4.0 发布的那一年通过的,但是几年后第一个“支持 Unicode”的 Windows 版本 NT 3.51,已发布。 最初的标准没有考虑比 BMP 更多的字符,这就是为什么 Unicode 字符宽字符 现在甚至被用作 Unicode 在 Win32 API 上下文中,虽然这是不准确的。

回答您提出的基本问题:

wchar_t 字符串是否根本无法使用 "==" 运算符?

不,它们不是,“ANSI”字符串也不是,即使用char 类型作为基础。请记住,C 字符串(基于wchar_tchar是一个指针。这意味着对于==,您正在比较两个绝对不相等的指针值。毕竟,一个是文字字符串(即在您的程序映像中),而另一个分配在堆上的某个位置。所以他们绝对是两个不同的实体。

如果您想使用 ==,您必须使用诸如 C++ 之类的 STL 类 std::string(或 std::basic_string<_TCHAR>)或(在 Windows 上)ATL 类 CString(或者更确切地说是 @ 987654335@)。这些类有时称为智能字符串类,并使用覆盖operator==() 的C++ 工具。但是,您应该记住,语义因实现而异,因此并非每个智能字符串类都会比较字符串内容。有些人可能只是比较 this 的相等性(即它是否是同一个实例),而另一些人可能会自行比较字符串内容不区分大小写或区分大小写。

要比较 C 字符串,您可以使用以下函数:

  • 对于“ANSI”字符 (char) 字符串:strcmp_stricmp(以及“计数”变体:_strncmp_strnicmp……还有更多)
  • 对于 Unicode 字符 (wchar_t) 字符串:wcscmp_wcsicmp(以及“计数”变体:_wcsncmp_wcsnicmp……还有更多)
  • 对于可变字符“类型”(TCHAR) 字符串:_tcscmp_tcsicmp(以及“计数”变体:_tcsncmp_tcsnicmp……还有更多)

你可以记住这些前缀:

  • str -> 字符串
  • wcs -> 宽字符串
  • tcs -> T 字符串

旁注:对于#include <tchar.h>windows.h,宏TEXT_T 是等效的,用于声明一个字符串文字,根据构建时的定义,它可以是“ANSI”或Unicode。 _TCHARTCHAR 显然也是如此,而后者似乎在 Win32 API 上下文中受到青睐。

因此,Unicode 版本会将_T("something") 扩展为L"something",而“ANSI”版本会将其扩展为"something"

至于 TCHAR,请考虑通读以下中提出的论点:Is TCHAR still relevant?rubenvb 指出)有支持和反对使用 TCHAR/_TCHAR 的有效观点,您应该做出决定并坚持与它 - 即保持一致

【讨论】:

  • wchar_t 不是 Unicode,尽管 MS 希望你相信。
  • @rubenvb:我不知道你甚至想用那个断言说什么,也不知道它如何证明反对票是合理的,但无论如何。 “Unicode”和术语“Unicode 字符”,尽管其他人希望您相信,但在 Win32 API 上下文中指的是宽字符,特别是指变体 wchar_t(编译器定义)和WCHAR(标头定义)。这里使用的 Unicode 编码是 UTF-16 并且曾经是 UCS-2,这一事实超出了大多数人想知道或需要知道的范围,而且与此答案无关。
  • Unicode 有几种编码,我很清楚这一点。只有一种编码是 Endianess-neutral (UTF-8),还有一种较旧的编码(和 UTF-16 的子集)称为 UCS-2,这是 Microsoft 最初从 Windows NT 开始使用的,使用 16 位字符类型(限于 BMP)。从 XP 开始,他们转向了 UTF-16。与 UTF-16 不同,UCS-2 没有允许您编码超过前 64K 个字符 (BMP) 的代码点。另一方面,UTF-16 和 UTF-32 具有与 UTF-8 类似的代码点,以允许比 BMP 提供的字符更多。
  • Unicode wchar_t 只是一个挑剔的人。 _TCHARstd::base_string 是错误的。而且您错过了不使用愚蠢的TCHAR 业务的建议。
  • @rubenvb:TCHAR 被一致使用并没有什么可笑的。我仍然必须自己维护代码,由于多种原因不能移动到较新版本的 VS(主要是因为运行时库)并被编译为 ANSI。但是,该代码的一部分将在以后重用,因此使用TCHAR 是一种非常谨慎的方法。 如果 OP 用wmain 发布了这个问题,我会做出相应的回答。在问题TCHAR 的上下文中是正确的。还有你指的错误是什么?您至少可以解释批评,因为它并不明显
猜你喜欢
  • 2011-04-08
  • 1970-01-01
  • 1970-01-01
  • 2022-10-23
  • 2015-02-16
  • 1970-01-01
  • 1970-01-01
  • 2012-06-05
  • 1970-01-01
相关资源
最近更新 更多