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 )
,两者都应附加一个空字节。
我正在使用 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 )
,两者都应附加一个空字节。