簡體   English   中英

C ++ LPSTR和零終止字符串的字符串故障

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM