如何在C ++中将PWSTR转换为字符串?

时间:2011-09-16 16:58:52

标签: c++ windows

我有以下代码:

// Fetch Local App Data folder path.
PWSTR localAppData = (PWSTR) malloc(128);
SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &localAppData);

// Find out the absolute path to chrome.exe
stringstream ss;
ss << localAppData << "/Google/Chrome/Application/chrome.exe";

stringstreamer .str()的结果是008F6788/Google/Chrome/Application/chrome.exe,这是错误的。

我似乎无法使用stringstreamer,因为类型不兼容而无法使用strcat或wcsncat。

如何将此PWSTR转换为字符串?

5 个答案:

答案 0 :(得分:29)

1。育!

Microsoft says

typedef wchar_t* LPWSTR, *PWSTR;

所以让我们从你的测试用例中得到那个可怕的废话,并且失去C垃圾:

// Fetch Local App Data folder path.
wchar_t* localAppData = new wchar_t[128];
SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &localAppData);

stringstream ss;
ss << localAppData << "/Google/Chrome/Application/chrome.exe";

delete[] localAppData;

2。警告!

这里有一个严重的缺陷。

SHGetKnownFolderPath实际上设置了指向它的指针的值,指向 it 分配的内存。你的代码有内存泄漏,我的上一个代码片段错误地释放了内存。

让我们通过阅读the documentation

来解决这个问题
  

ppszPath [out]

Type: PWSTR*
     

当此方法返回时,包含指向以null结尾的Unicode字符串的指针的地址,该字符串指定已知文件夹的路径。调用进程负责通过调用CoTaskMemFree释放不再需要的资源。返回的路径不包括尾部反斜杠。例如,返回“C:\ Users”而不是“C:\ Users \”。

// Fetch Local App Data folder path.
wchar_t* localAppData = 0;
SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &localAppData);

stringstream ss;
ss << localAppData << "/Google/Chrome/Application/chrome.exe";

CoTaskMemFree(static_cast<void*>(localAppData));

现在,关于节目。


3。宽字符

您的代码的语法问题是localAppData是wchar_t,但正常stringstream适用于char

幸运的是,有一个名为wstringstream的宽字符变种使用wchar_t代替。

(请注意,这意味着您的文字也必须使用wchar_t字符串文字前缀从L构建。)

现在最后的代码:

// Fetch Local App Data folder path.
wchar_t* localAppData = 0;
SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &localAppData);

wstringstream ss;
ss << localAppData << L"/Google/Chrome/Application/chrome.exe";

CoTaskMemFree(static_cast<void*>(localAppData));

答案 1 :(得分:4)

PWSTR是指向宽字符串的指针。你需要

// Fetch Local App Data folder path.
PWSTR localAppData = (PWSTR) malloc(128);
SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &localAppData);

wstringstream ss;
ss << localAppData << L"/Google/Chrome/Application/chrome.exe";

此外,malloc参数表示要分配的字节数,因此您要分配一个只能容纳64个宽字符(包括NULL字符)的缓冲区。您可能希望使用malloc( 128 * sizeof(wchar_t) )

修改
来自SHGetKnownFolderPath

的文档
  

ppszPath 当此方法返回时,包含指向以null结尾的Unicode字符串的指针的地址,该字符串指定已知文件夹的路径。调用进程负责在调用CoTaskMemFree

后不再需要时释放此资源

所以你不应该为函数的最后一个参数分配任何内存。

wchar_t *localAppData = NULL;
::SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &localAppData);

wstringstream ss;
ss << localAppData << L"/Google/Chrome/Application/chrome.exe";
::CoTaskMemFree(localAppData);

答案 2 :(得分:3)

我喜欢 Praetorina的 Praetorian的回答只是使用宽字符串流,但如果你想转换:

char str[128];
wcstombs(str, localAppData, 128);

还有另一种功能反过来:

wchar_t wstr[128];
mbstowcs(wstr, "Hello World", 128);

答案 3 :(得分:1)

您不能将宽字符串“强制转换”为字符串。原因(除了2字节单位VS. 1字节单位问题)是这个“演员”是不明确的。

什么是源编码?什么是目的地编码?在这种情况下,源代码编码可能是Unicode(shell扩展可能会返回随机废话,没有任何保证,如果他们不使用Unicode,他们会执行有效的X到Unicode转换)。目标编码很可能是ASCII,尽管技术上必须匹配系统的当前代码页。

如果您想要进行有损的Unicode到ASCII转换,可以使用WideCharToMultiByte()

答案 4 :(得分:0)

如果你不喜欢widechar并且想要ansi字符串,请尝试使用wcstombs或WideCharToMultiByte。

要调用SHGetKnownFolderPath,您不需要自己分配内存,这会导致内存泄漏。