【问题标题】:How to compare BSTR against a string in c/c++?如何将 BSTR 与 c/c++ 中的字符串进行比较?
【发布时间】:2011-04-11 16:12:25
【问题描述】:
wprintf(L"Selecting Audio Input Device: %s\n", 
                            varName.bstrVal);

if(0 == strcmp(varName.bstrVal, "IP Camera [JPEG/MJPEG]"))...

以上报道:

error C2664: 'strcmp' : cannot convert parameter 1 from 'BSTR' to 'const char *'

【问题讨论】:

    标签: c++ windows com activex


    【解决方案1】:

    您必须改用wcscmp

    if(0 == wcscmp(varName.bstrVal, L"IP Camera [JPEG/MJPEG]"))
    {
    }
    

    这是一个description of the BSTR data type,它有一个长度前缀和一个真正的字符串部分,它只是一个WCHAR 字符数组。它还有 2 个 NULL 终止符。

    唯一需要注意的是 BSTR 数据类型可以在字符串部分包含嵌入的 NULL,因此 wcscmp 仅在 BSTR 不包含嵌入的 NULL 的情况下有效(可能是大多数情况) .

    【讨论】:

    • 为什么有些函数的前缀是w,而有些函数的前缀是wc
    • @COMer:我不确定,但 wcs 代表宽字符串。
    • @COMer:我猜“str”被替换为“wcs”(例如 strcmp -> wcscmp,strdup -> wcsdup),但没有“str”的函数会在某处插入“w” (例如 printf -> wprintf, fopen -> _wfopen)。
    【解决方案2】:

    作为 C 运行时的更丰富的替代方案,您可以在 Win32 中使用 Unicode CompareString 或 CompareStringEx API。如果您没有要考虑的字符集问题,wcscmp 也可以。

    【讨论】:

      【解决方案3】:

      我的解决方案:

      static const std::wstring IPCamera = L"IP Camera [JPEG/MJPEG]";
      if (varName.bstrVal == IPCamera {
        //...
      

      【讨论】:

      • 尝试对我来说失败了。该示例缺少一个右括号,我对其进行了更正(它已编译),但逻辑并未将两个相同的字符串视为相等。
      【解决方案4】:

      这里的所有其他答案要么完全错误,要么部分不正确,因为它们忽略了BSTRstd::wstring 都可以包含多个嵌入的空字符这一事实。

      这意味着它们不应使用wcscmp() 进行比较,这将停止在任一字符串中遇到的第一个\0 上进行比较。

      以下是如何正确比较 BSTRstd::wstring

      // Windows.h defines min() and max() as macros
      #define NOMINMAX
      
      #include <Windows.h>
      #include <string>
      
      // std::string_literals namespace requires C++14,
      // but it is needed only to construct strings with
      // embedded nulls, not for the comparison itself
      using namespace std::string_literals;
      
      int wmain(int argc, wchar_t *argv[])
      {
          std::wstring    String1 = L"I am a happy BSTR \0with \0embedded \0null chars"s;
          std::wstring    Temp = L"I am a happy bstr \0with \0embedded \0NULL chars"s;
          BSTR            String2 = SysAllocStringLen(Temp.c_str(), Temp.size());
      
          if (String2 == nullptr) {
              return ERROR_OUTOFMEMORY;
          }
      
          // make sure not to create a security vulnerability by
          // reading past the end of either buffer when comparing
          const size_t MaxCount = std::min(String1.size(), static_cast<size_t>(SysStringLen(String2)));
      
          bool Equal = wcsncmp(String1.c_str(), String2, MaxCount) == 0;
      
          if (Equal) {
              wprintf(L"Strings are equal\n");
          } else {
              wprintf(L"Strings are NOT equal\n");
          }
      
          SysFreeString(String2);
      
          return 0;
      }
      

      请注意,该示例将打印“字符串不相等”,除非您将其更改为使用 _wcsnicmp() 进行不区分大小写的比较。

      【讨论】:

        【解决方案5】:

        我总是围绕 BSTR 构建 _bstr_t 包装器。它使事情变得更容易和更惯用:

        if(std::string("IP Camera [JPEG/MJPEG]") ==
                           static_cast<const char*>( _bstr_t(varName.bstrVal) )
        {
        }
        

        【讨论】:

        • 不是一个好主意:_bstr_t 构造函数在 varName.bstrVal 中创建字符串的全长副本。
        • 这也将 bstr 从 unicode 转换为 ANSI,这是不必要的,因为您可以首先与 unicode 文字进行比较。
        猜你喜欢
        • 2020-07-01
        • 2020-04-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-03
        • 1970-01-01
        • 1970-01-01
        • 2020-12-18
        相关资源
        最近更新 更多