【问题标题】:conversion of Cstring to BYTECstring 到 BYTE 的转换
【发布时间】:2012-09-03 14:56:04
【问题描述】:

我正在使用 Visual Studio c++ 并希望将 Cstring 转换为 Byte。我已经编写了这段代码,但它在第二行给了我“数据”未定义的错误。

CString data = _T( "OK");
LPBYTE pByte = new BYTE[data.GetLength() + 1];
memcpy(pByte, (VOID*)LPCTSTR(data), data.GetLength());

我还需要将 LPBYTE 转换为 const char 以用于 strcmp 函数。我已经编写了代码,但我找不到它的问题。

const LPBYTE lpBuffer;
LPBYTE lpData = lpBuffer;
CString rcvValue(LPCSTR(lpBuffer));
const CHAR* cstr = (LPCSTR)rcvValue;
if (strcmp (cstr,("ABC")) == 0)
{
    ////
}

【问题讨论】:

  • 该代码是正确的(假设您后来考虑了尾随 0。请粘贴您遇到的真正错误。
  • 这段代码根本不正确。如果 CString 的基本类型是 'char',它就可以工作,但是如果启用了 Unicode,并且基本类型是 wchar_t,那么它就被破坏了。 GetLength 返回字符数(即 char 或 wchar_t 的数量),而不是分配用于保存字符串的字节数。

标签: c++ visual-studio-2010 mfc


【解决方案1】:

CString 类型是 CStringT 的模板特化,具体取决于它使用的字符集(CStringA 用于 ANSI,CStringW 用于 Unicode)。虽然您确保在使用 _T macro 从字符串文字构造时使用匹配的编码,但在将受控序列复制到缓冲区时未能考虑不同的大小要求。

以下代码修复了第一部分:

CString data = _T("OK");
size_t size_in_bytes = (data.GetLength() + 1) * sizeof(data::XCHAR);
std::vector<BYTE> buffer(size_in_bytes);
unsigned char const* first = static_cast<unsigned char*>(data.GetString());
unsigned char const* last = first + size_in_bytes;
std::copy(first, last, buffer.begin());

第二个问题是真正要求解决已解决的问题。 CStringT 类型已经提供了一个 CStringT::Compare 成员,可以使用:

const LPBYTE lpBuffer;
CString rcvValue(static_cast<char const*>(lpBuffer));
if (rcvValue.Compare(_T("ABC")) == 0)
{
    ////
}

一般建议:始终更喜欢使用与您的字符编码匹配的具体CStringT 特化,即CStringACStringW。代码将更易于阅读和推理,当您遇到需要帮助的问题时,您可以在 Stack Overflow 上发布问题,而无需解释您使用的编译器设置。

【讨论】:

    【解决方案2】:

    确保包含 atlstr.h 以提供 CString 的定义,如下所示:

    #include "stdafx.h"
    #include <Windows.h>
    #include <atlstr.h>
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        CString data = _T( "OK");
        LPBYTE pByte = new BYTE[data.GetLength() + 1];
        memcpy(pByte, (VOID*)LPCTSTR(data), data.GetLength());
        return 0;
    }
    

    【讨论】:

    • 不是我!我认为其他人对我们俩都投了反对票,至少是暂时的。
    • 看起来 pByte BYTE 数组如果启用 Unicode 将不够大,因为 CString 中的每个字符将占用 2 个 BYTEs 但 data.GetLength() 将返回字符数。
    【解决方案3】:

    我相当肯定 Jay 对于您的第一个问题是正确的。您需要包含正确的标题。

    对于您的第二个问题,您为什么希望该代码能够工作?让我们来看看您编写的代码实际上做了什么。

    1. 创建一个 char 指针 (char *) 而不对其进行初始化。这使得 lpData/lpBuffer 指向内存中的随机位置。
    2. 创建一个 CString 并用这个随机指针初始化它。
    3. 从 CString 中提取缓冲区并将其与字符串文字进行比较。

    请记住,CString 包含随机垃圾,您希望这段代码能做什么? (除了可怕的崩溃?=))

    我还想指出,您在处理字符串时需要更加一致。您是否计划同时支持基于 char 和 wchar_t 的字符串,正如您在第一部分中使用 TCHAR 所暗示的那样?你想使用 C 风格的字符串还是想使用像 CString 这样的对象?如果您想使用 CString,只需使用 CString 提供的比较函数。不用担心 strcmp。

    【讨论】:

      【解决方案4】:

      可能你没有包含关键标题

          #include <afx.h>
      
          int main()
          {                   
              CString data = _T( "OK");
              LPBYTE pByte = new BYTE[data.GetLength() + 1];
              memcpy(pByte, (VOID*)LPCTSTR(data), data.GetLength());
      
              return 0;
          }
      

      这段代码运行良好。

      【讨论】:

      • 这会抛出AccessViolationException
      • @gok:C++ 中没有AccessViolationException,如果有,代码不会引发它。它仍然无法考虑CString(可能是charwchar_t)使用的字符类型的大小要求,但这会导致字符串被截断。行为仍然定义明确。
      【解决方案5】:

      你应该使用

       CString ss = "123ABC";
      
       BYTE* bp = (BYTE*)ss.GetBuffer(ss.GetLength());
      
       BYTE expected[16] ; 
      
       CopyMemory(expected,bp,sizeof(expected));
      

      仅使用“=”是行不通的。

      【讨论】:

      • 不,这行不通,原因有很多。在拨打GetBuffer()时,您还需要稍后拨打ReleaseBuffer()(或朋友)。但无论如何你都不需要可变指针,所以只需调用GetString()。该代码也未能考虑 Unicode 字符编码。 CString 可以存储编码为 UTF-16 的字符(这是 Visual Studio 多年来的默认设置),即每个代码单元 2 个字节。您的代码只是截断此类字符串。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多