6

我正在用 C++ 开发一个小型 Win32 应用程序。我很久以前就研究过C++基础知识,所以现在我完全被C++中的字符串弄糊涂了。没有WCHARTCHAR只有charString。经过一番调查,我决定不使用TCHAR.

我认为我的问题非常简单,但我找不到如何在 C++ 中操作字符串的明确指南。受过去几年 PHP 编码的影响,我期待一些简单的字符串操作,但错了!

简单地说,我需要的只是将新数据放入字符串中。

    WCHAR* cs = L"\0";
    swprintf( cs, "NEW DATA" );

这是我的第一次尝试。在调试我的应用程序时,我调查过 swprintf 仅将前 2 个字符放入我的 cs var。我已经通过这种方式解决了我的问题:

    WCHAR cs[1000];
    swprintf( cs, "NEW DATA" );

但通常这个技巧可能会失败,因为在我的情况下,新数据不是常量值而是另一个变量,它可能比 1000 字符长更宽。我的代码是这样的:

    WCHAR cs[1000];
    WCHAR* nd1;
    WCHAR* nd2;
    wcscpy(nd1, L"Some value");
    wcscpy(nd2, L"Another value"); // Actually these vars stores the path for user selected folder
    swprintf( cs, "The paths are %s and %s", nd1, nd2);

在这种情况下,nd1 和 nd2 的总字符数可能大于 1000 个字符,因此关键数据将丢失。

问题是如何将我需要的所有数据复制到以这种方式声明的 WCHAR 字符串WCHAR* wchar_var;而不丢失任何内容?

PS 因为我是俄罗斯人,所以问题可能不清楚。现在让我谈谈这一点,我将尝试更清楚和更复杂地解释我的问题。

4

3 回答 3

7

在现代 Windows 编程中,可以忽略TCHAR并使用wchar_t( WCHAR) 和 Unicode UTF-16。

TCHAR是过去的模型,当您想要拥有一个单一的代码库并生成 ANSI/MBCS 和 Unicode 版本时,会更改一些预处理器开关,例如_UNICODEUNICODE。)

在任何情况下,您都应该使用 C++ 和方便的字符串类来简化您的代码。您可以使用ATL::CString(对应CStringW于 Unicode 构建,这是自 VS2005 以来的默认设置)或 STL 的std::wstring.

使用CString,您可以执行以下操作:

CString str1 = L"Some value";
CString str2 = L"Another value";
CString cs;
cs.Format(L"The paths are %s and %s", str1.GetString(), str2.GetString());

CString还提供了适当的重载operator+来连接字符串(因此您不必计算结果字符串的总长度,为目标字符串动态分配缓冲区或检查现有缓冲区大小,调用wcscpy,,wcscat不要忘记释放缓冲区, ETC。)

并且您可以简单地将 的实例传递CString给期望const wchar_t*( LPCWSTR/PCWSTR) 参数的 Win32 API,因为CString它提供了一个隐式转换运算符到const wchar_t*.

于 2012-11-13T11:58:03.717 回答
2

当你使用 aWCHAR*时,你正在调用未定义的行为,因为你有一个指针,但没有让它指向任何有效的东西。您需要找出结果字符串的长度并为字符串动态分配空间。例如:

WCHAR* cs;
WCHAR* nd1;
WCHAR* nd2;

nd1 = new WCHAR[lstrlen(L"Some value") + 1]; // +1 for the null terminator
nd2 = new WCHAR[lstrlen(L"Another value") + 1];
cs = new WCHAR[lstrlen(L"The paths are  and ") + lstrlen(nd1) + lstrlen(nd2) + 1];

wcscpy(nd1, L"Some value");
wcscpy(nd2, L"Another value"); // Actually these vars stores the path for user selected folder
swprintf( cs, L"The paths are %s and %s", nd1, nd2);

delete[] nd1;
delete[] nd2;
delete[] cs;

但这是非常丑陋且容易出错的。如前所述,您应该std::wstring改用如下内容:

std::wstring cs;
std::wstring nd1;
std::wstring nd2;

nd1 = L"Some value";
nd2 = L"Another value";
cs = std::wstring(L"The paths are ") + nd1 + L" and " + nd2;
于 2012-11-13T11:57:50.650 回答
1

建议使用 ATLCStringW类而不是 raw WCHAR,这样更方便。CString是动态分配的 C 字符串的包装器。它将在每次操作后适当地管理字符串长度和分配的内存缓冲区,因此您不会关心它。

典型用法:

#include <atlstr.h>

CStringW s;
s.Format(L"The paths are %s and %s", L"Some value", L"Another value");
const WCHAR* wstr = s.GetString(); // To pass to some API that need WCHAR

或者

#include <atlstr.h>

CStringW s(L"The paths are ");
s += L"Some value";
s += L" and ";
s += L"Another value";
const WCHAR* wstr = s.GetString(); // To pass to some API that need WCHAR
于 2012-11-13T12:10:49.363 回答