C ++ LPSTR и проблемы со строками с нулевыми концами строк

я использую GetOpenFileName функция от Winapiи я применяю фильтр к диалогу выбора файла.

ЭТОТ работает отлично:

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

введите описание изображения здесь

-1

Решение

GetOpenFileName функция использует TCHAR, и TCHAR становятся WCHAR в случае UNICODE набор символов используется.

Вот пример:

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

Если вы хотите параметризовать lpstrFilter основанный на std::wstring Вы можете просто использовать wstring::c_str() получить LPCTSTR который const wchar* в случае UNICODE.

ВАЖНЫЙ: Проблема в том, что std::wstring конструктор, который принимает const wchar* предполагает, что ввод является строкой C. Строки C заканчиваются на «\ 0» и, таким образом, синтаксический анализ останавливается, когда он достигает символа «\ 0». Чтобы компенсировать это, вы должны использовать конструктор, который принимает два параметра указатель на массив символов и длину.
Вы также можете использовать string::push_back() метод для добавления NULL.

std::wstring sFilter = L"PDF Files";
sFilter.push_back('\0');
sFilter.append(L"*.pdf");
sFilter.push_back('\0');
0

Другие решения

С

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

ты звонишь std::string contructor, который завершает строку в первом \0,

Следующий код:

string mfilter = "Filter\0*.PDF\0";
cout << "string:" << mfilter << "   len: " << mfilter.length() << endl;

печать

string: Filter   len: 6

Строка строится только до первого \0 терминатор. У строки состоит только слово «Фильтр».

2

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

Это называется std::basic_string конструктор, который использует строка с нулевым символом в конце. Это прекратит синтаксический анализ строкового литерала в "Filter",

Попробуйте это вместо этого:

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

Это называется std::basic_string конструктор, который использует msgstr «первое число символов строки символов, на которые указывает s. s может содержать нулевые символы

Вы должны сами посчитать символы или написать код-обертку, если вы сталкиваетесь с этой проблемой чаще.


Связанные с: std::basic_string конструкторы.


Что касается вашей ошибки во время выполнения:

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

append() не имеет перегрузка для одного символьного типа. Вы, вероятно, бьете const CharT* s перегрузка с нулевым указателем.

Используйте либо append( 1, '\0' ) или же append( "", 1 ), любой из которых должен добавить нулевой байт.

0
По вопросам рекламы [email protected]