我有以下代码:
// 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由于types不兼容。
我如何将这个PWSTRstring?
微软说 :
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;
这里有一个严重的缺陷。
SHGetKnownFolderPath
实际上设置你指定给它的指针的值,指向它分配的内存。 你的代码有一个内存泄漏,我的最后一个片段错误地微妙地释放内存。
我们通过阅读文档来解决这个问题:
ppszPath [out]
Type: PWSTR*
当此方法返回时,包含指向已知文件夹路径的以空字符结尾的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));
现在,在展会上。
你的代码的语法问题是localAppData是一个wchar_t
,但是正常的stringstream
在char
工作。
幸运的是,有一个名为wstringstream
的宽字符变体,它使用wchar_t
。
(请注意,这意味着您的文字必须使用L
字符串文字前缀也由wchar_t
s构建。)
现在最后的代码是:
// 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));
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当此方法返回时,包含指向已知文件夹路径的以空字符结尾的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字节单位VS. 1字节单位问题除外)是这个“cast”是不明确的。
什么是源编码? 什么是目的地编码? 在这种情况下,源编码可能是Unicode(外壳扩展可能会返回随机废话,没有任何保证,如果他们不使用Unicode,他们执行有效的X到Unicode转换)。 目标编码很可能是ASCII,尽管它在技术上必须与系统的当前代码页匹配。
如果你想要一个有损Unicode到ASCII的转换,你可以使用WideCharToMultiByte()
。
我喜欢Praetorina的 Praetorian的答案,只是使用宽字符串流,但如果你想转换:
char str[128]; wcstombs(str, localAppData, 128);
还有另一个功能也是相反的:
wchar_t wstr[128]; mbstowcs(wstr, "Hello World", 128);
如果你不喜欢widechar,并且想要ansi字符串,请尝试使用wcstombs或WideCharToMultiByte。
要调用SHGetKnownFolderPath,你不需要自己分配内存,这会导致内存泄漏。