2011-09-16 27 views
4

我有以下代碼:如何將PWSTR轉換爲C++中的字符串?

// 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投射到字符串?

+0

看到我的答案,一種方式之間轉換多字節和寬字符,反之亦然。參見安德烈的另一種方式。請參閱Praetorian或Tomalak Geret'kal,瞭解您應該做什麼。 – AJG85

回答

25

喔!

微軟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實際設置您指定給它的指針的值指向分配的內存。你的代碼有內存泄漏,而我的最後一段代碼錯誤地微妙地釋放了內存。

讓我們修復通過讀取the documentation

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)); 

,與節目。


3.寬字符

的語法問題與你的代碼是LOCALAPPDATA是wchar_t,但正常stringstream S於char工作。

幸運的是,有一個稱爲wstringstream的寬字符變體,它使用wchar_t代替。

(請注意,這意味着你的文字將被建造出來的wchar_t S,也使用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)); 
+0

+1,但不會有一個'wchar_t'數組比一個向量好一點?另外'MAX_PATH'可能值得一提。沒關係,很好的編輯和對'CoTaskFreeMem'的好眼光# – AJG85

+1

@ AJG85:在我的答案中沒有載體。 'SHGetKnownFolderPath'爲你分配。 –

+0

我現在如何將wstringstream轉換爲字符串?實際上,我對c_str感興趣,因爲我使用'stat'的結果,並且可以從字符串獲取c_str。 – Tower

3

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個寬字符(包括空字符)。您可能需要使用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); 
+0

這也會失敗。你需要在字符串前加'L',如'L「...」'。 –

+0

你不需要在那裏的寬字符串? –

+0

@AndréCaron哎呀,這就是我不會先嚐試它的原因!固定。 – Praetorian

1

您不能將一個寬字符的字符串「轉換」爲字符串。原因(2字節單位VS. 1字節單位問題除外)是這個「cast」會不明確。

什麼是源編碼?目的地編碼是什麼?在這種情況下,源編碼很可能是Unicode(外殼擴展可能會返回隨機垃圾,如果他們沒有使用Unicode,則無法保證它們執行了有效的X到Unicode轉換)。目的地編碼可能是ASCII,儘管它在技術上必須與系統當前的代碼頁匹配。

如果您想要進行有損Unicode到ASCII轉換,您可以使用WideCharToMultiByte()

+0

大多數其他答案與人們在Google上搜索該主題時想要的內容無關...謝謝。 – cb88

1

我喜歡 Praetorina的 禁的只是用寬字符串流的答案,但如果你想轉換:

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

還有另一個功能,去周圍的其他方法太:

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

感謝您謀殺我的用戶名:-) – Praetorian

+1

弗洛伊德滑?令人驚訝的是兩個字母交換可以做什麼;-P – AJG85

0

如果您不喜歡widechar並且想要ansi字符串嚴重,請嘗試使用wcstombs或WideCharToMultiByte。

要調用SHGetKnownFolderPath,你不需要自己分配內存,它會導致內存泄漏。

相關問題