![](/img/trans.png)
[英]What are the problems of a zero-terminated string that length-prefixed strings overcome?
[英]C++ LPSTR and string trouble with zero-terminated strings
我正在使用Winapi
GetOpenFileName
函數,並且正在將過濾器應用於選擇文件對話框。
這完美地工作:
LPSTR mfilter = "Filter\0*.PDF\0";
ofn.lpstrFilter = mfilter;
if(GetOpenFileName(&ofn)){
...
此失敗(對話框打開,但不應用任何過濾器):
string mfilter = "Filter\0*.PDF\0";
ofn.lpstrFilter = mfilter.c_str();
if(GetOpenFileName(&ofn)){
...
我需要使用std:string
因為我通過參數獲取文件擴展名,這種類型有助於串聯,但是我遇到了不兼容的問題...
如果它按預期工作,這將是我的代碼(它與前面的示例失敗):
const char * ext = &(4:); //Ampersand parameter (from CA Plex) It contains "PDF"
string mfilter = "Filter\0*." + ext + "\0"; //Final string: Filter\0*.PDF\0;
ofn.lpstrFilter = mfilter.c_str();
使用此方法時,出現運行時異常:
string mf;
mf.append("Filter")
.append('\0')
.append("*.pdf")
.append('\0');
ofn.lpstrFilter = mf.c_str();
用
string mfilter = "Filter\0*.PDF\0";
您正在調用std::string
構造函數,該構造函數在第一個\\0
處終止字符串。
如下代碼:
string mfilter = "Filter\0*.PDF\0";
cout << "string:" << mfilter << " len: " << mfilter.length() << endl;
版畫
string: Filter len: 6
僅在第一個\\0
終止符之前構造字符串。 字符串是否僅由單詞“ Filter”組成。
GetOpenFileName
函數使用TCHAR,如果使用UNICODE字符集,則TCHAR變為WCHAR。
這是一個例子:
std::wstring getOpenFileName(HWND hWnd, const std::wstring& sFilter)
{
wchar_t buffer[MAX_PATH] = L"";
OPENFILENAMEW ofn = {0};
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hWnd;
ofn.lpstrFilter = sFilter.c_str();
ofn.nFilterIndex = 1;
ofn.lpstrFile = buffer;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
if( !::GetOpenFileNameW( &ofn ) )
return L"";
return buffer;
}
如果要基於std::wstring
參數化lpstrFilter
,則可以使用wstring::c_str()
來獲取LPCTSTR
,對於UNICODE而言,它是const wchar*
。
重要說明:問題在於,采用const wchar*
的std::wstring
構造const wchar*
假定輸入為C字符串。 C字符串以'\\ 0'終止,因此在到達'\\ 0'字符時停止解析。 為了彌補這一點,您需要使用帶有兩個參數的構造函數,即指向char數組的指針和一個length 。 您也可以使用string::push_back()
方法附加NULL。
std::wstring sFilter = L"PDF Files";
sFilter.push_back('\0');
sFilter.append(L"*.pdf");
sFilter.push_back('\0');
string mfilter = "Filter\0*.PDF\0";
這將調用std::basic_string
構造函數,該構造函數使用以null終止的string 。 它將停止在"Filter"
處解析字符串文字。
嘗試以下一項:
string mfilter( "Filter\0*.PDF", 13 ); // need double null at end
這將調用std::basic_string
構造函數, 該構造函數使用“由s指向的字符串的第一個計數字符可以包含空字符 。”
如果您經常遇到此問題,則必須自己計算字符,或者編寫包裝代碼。
相關: std::basic_string
構造函數 。
至於您的運行時錯誤:
string mf;
mf.append("Filter")
.append('\0')
.append("*.pdf")
.append('\0');
append()
對於單個字符類型沒有重載 。 您可能使用空指針擊中了const CharT* s
重載。
使用append( 1, '\\0' )
或append( "", 1 )
中的任何一個,都應追加一個空字節。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.