C ++ LPSTR和带有零终止字符串的字符串问题

时间:2015-12-10 11:53:12

标签: c++ string winapi stdstring getopenfilename

我使用GetOpenFileName中的Winapi功能,并且我将过滤器应用于选择文件对话框。

这个完美无缺:

LPSTR mfilter = "Filter\0*.PDF\0";
ofn.lpstrFilter = mfilter;

if(GetOpenFileName(&ofn)){
...

enter image description here

失败(对话框已打开但未应用过滤器):

string mfilter = "Filter\0*.PDF\0";
ofn.lpstrFilter = mfilter.c_str();

if(GetOpenFileName(&ofn)){
...

enter image description here

我需要使用std:string,因为我通过参数获取文件扩展名,这种类型有助于连接,但我遇到了不兼容问题......

如果按预期工作,这将是我的代码(IT FAILS与前面的示例相同):

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

enter image description here

3 个答案:

答案 0 :(得分:2)

使用

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终结符之前构建。该字符串是否仅由单词&#34; Filter&#34;。

组成

答案 1 :(得分:0)

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

如果您想根据lpstrFilterstd::wstring进行参数化,只需使用wstring::c_str()获取LPCTSTR const wchar*,以便 UNICODE 即可。

重要提示:问题是,std::wstring的{​​{1}}构造函数假设输入是C字符串。 C字符串是&#39; \ 0&#39;终止,因此解析在到达&#39; \ 0&#39;字符。为了弥补这一点,您需要使用构造函数,它将两个参数作为指向char数组的指针和一个长度。 您还可以使用const wchar*方法追加NULL。

string::push_back()

答案 2 :(得分:0)

string mfilter = "Filter\0*.PDF\0";

这会调用使用以空字符结尾的字符串std::basic_string构造函数。它将停止在"Filter"解析字符串文字。

试试这个:

string mfilter( "Filter\0*.PDF", 13 ); // need double null at end

这会调用std::basic_string构造函数,该构造函数使用“s指向的字符串的第一个计数字符。 s可以包含空字符。”

您必须自己计算字符数,或者在更频繁地遇到此问题时编写包装器代码。

相关:std::basic_string constructors

至于你的运行时错误:

string mf;
mf.append("Filter")
.append('\0')
.append("*.pdf")
.append('\0');

append() does not have an overload for a single character type。您可能正在使用空指针进行const CharT* s重载。

使用append( 1, '\0' )append( "", 1 ),其中任何一个都应附加一个空字节。