C字符串到宽C字符串赋值

时间:2012-11-15 19:59:34

标签: c++ string cstring

我对C字符串和宽C字符串有点困惑。为了这个问题,假设我使用的是Microsoft Visual Studio 2010 Professional。如果我的任何信息不正确,请告诉我。

我有一个带有const wchar_t *成员的结构,用于存储名称。

struct A
{
    const wchar_t* name;
};

当我为对象'a'分配名称时:

int main()
{
    A a;

    const wchar_t* w_name = L"Tom";
    a.name = w_name;

    return 0;
}

这只是将w_name指向的内存地址复制到a.name中。现在,w_name和a.name都是宽字符指针,指向内存中的相同地址。

如果我是对的,那么我想知道如何应对这种情况。我正在使用tinyxml2从XML属性读取C字符串。

tinyxml2::XMLElement* pElement;
// ...
const char* name = pElement->Attribute("name");

收到我的C字符串后,我将其转换为宽字符串,如下所示:

size_t newsize = strlen(name) + 1;
wchar_t * wcName = new wchar_t[newsize];
size_t convertedChars = 0;
mbstowcs_s(&convertedChars, wcName, newsize, name, _TRUNCATE);

a.name = wcName;

delete[] wcName;

如果到目前为止我是正确的,那么行:

 a.name = wcName;

只是将数组wcName的第一个字符的内存地址复制到a.name中。但是,我在分配这个指针后直接删除了wcName,这会使它指向垃圾。

如何将C字符串转换为宽字符C字符串,然后将其分配给a.name?

3 个答案:

答案 0 :(得分:3)

最简单的方法可能是让你name变量管理内存。反过来,这可以通过将其声明为

来轻松完成
std::wstring name;

这些人没有独立内容和对象变异的概念,即你不能真正制作单个字符const并使整个对象const阻止它被分配到。

答案 1 :(得分:1)

可以在使用std::wstring时执行此操作,而不依赖于额外的临时转换缓冲区分配和销毁。除非您过分关注堆碎片或在有限的系统(即Windows Phone)上,否则不是非常重要。它只需要在正面进行一些设置。让标准库为您管理内存(稍微轻推)。

class A
{
   ...
   std::wstring a;
};


// Convert the string (I'm assuming it is UTF8) to wide char
int wlen = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, NULL);
if (wlen > 0)
{
    // reserve space. std::wstring gives us the terminator slot
    // for free, so don't include that. MB2WC above returns the
    // length *including* the terminator.
    a.resize(wlen-1);
    MultiByteToWideChar(CP_UTF8, 0, name, -1, &a[0], wlen);
}
else
{   // no conversion available/possible.
    a.clear();
}

在一个完整的附注中,你可以构建TinyXML以使用标准库和std::string而不是char *,这对你来说并没有多大帮助,但是稍后可能会为您节省以后的strlen()来电。

答案 2 :(得分:0)

正如您正确提到的那样a.name只是一个指针,它不会假设任何已分配的字符串存储空间。您必须使用new或静态/作用域数组手动管理它。

要摆脱这些无聊的事情,只需使用一个可用的字符串类:来自ATL的CStringW(易于使用,但特定于MS)或来自STL的std::wstring(C ++标准,但不是那么容易要转换自char*):

#include <atlstr.h>

// Conversion ANSI -> Wide is automatic
const CStringW name(pElement->Attribute("name"));    

不幸的是,std::wstring使用char*并不容易。 请在此处查看转化功能:How to convert std::string to LPCWSTR in C++ (Unicode)