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

C++ LPSTR and string trouble with zero-terminated strings

我正在使用 Winapi 中的 GetOpenFileName 函数,并且正在将过滤器应用于 select 文件对话框。

这个 完美运行:

LPSTR mfilter = "Filter[=10=]*.PDF[=10=]";
ofn.lpstrFilter = mfilter;

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

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

string mfilter = "Filter[=11=]*.PDF[=11=]";
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[=12=]*." + ext + "[=12=]"; //Final string: Filter[=12=]*.PDF[=12=];
ofn.lpstrFilter = mfilter.c_str();

当我使用此方法时,出现运行时异常:

string mf;
mf.append("Filter")
.append('[=13=]')
.append("*.pdf")
.append('[=13=]');

ofn.lpstrFilter = mf.c_str();

string mfilter = "Filter[=10=]*.PDF[=10=]";

您正在调用 std::string 构造器,它在第一个 [=14=].

处终止字符串

以下代码:

string mfilter = "Filter[=11=]*.PDF[=11=]";
cout << "string:" << mfilter << "   len: " << mfilter.length() << endl;

打印

string: Filter   len: 6

字符串只构建到第一个 [=14=] 终止符。字符串是否只由单词 "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 在 [= 的情况下是 const wchar* 29=]统一码。

重要提示: 问题是采用 const wchar*std::wstring 构造函数假定输入是 C 字符串。 C 字符串以 '\0' 终止,因此当它到达 '\0' 字符时解析停止。为了弥补这一点,您需要使用带有两个参数的 构造函数,一个指向 char 数组的指针和一个长度 。 您还可以使用 string::push_back() 方法来附加 NULL。

std::wstring sFilter = L"PDF Files";
sFilter.push_back('[=11=]');
sFilter.append(L"*.pdf");
sFilter.push_back('[=11=]');
string mfilter = "Filter[=10=]*.PDF[=10=]";

这会调用一个 std::basic_string 构造函数,该构造函数使用 以 null 结尾的字符串 。它将停止解析 "Filter".

处的字符串文字

试试这个:

string mfilter( "Filter[=11=]*.PDF", 13 ); // need double null at end

这会调用一个使用 "the first count characters of character string pointed to by s. s can contain null characters."

std::basic_string 构造函数

你要么自己统计字符数,要么遇到这个问题多写wrapper代码


相关:std::basic_string constructors.


至于你的运行时错误:

string mf;
mf.append("Filter")
.append('[=12=]')
.append("*.pdf")
.append('[=12=]');

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

使用 append( 1, '[=19=]' )append( "", 1 ),两者都应附加一个空字节。