2016-02-26 3 views
0

Я использую GetPrivateProfileStringA для чтения некоторых вещей из файла .ini. У меня есть другой класс, где я сохраняю вещи вместе со строковым массивом. Я должен использовать его так, чтобы получить правильную строку в массив ControlAlt:C++ - Использование GetPrivateProfileString без буфера

char buffer[24]; 
GetPrivateProfileStringA("CONTROLS", 
    "ShiftUpAlt", 
    "LeftThumb", 
    buffer, 
    (DWORD)24, 
    "./Gears.ini"); 
scriptControl->ControlAlt[ScriptControls::ControlType::ShiftUp] = buffer; 

Я попытался положить его непосредственно, например, так:

GetPrivateProfileStringA("CONTROLS", 
    "ShiftUpAlt", 
    "LeftThumb", 
    (LPSTR)scriptControl->ControlAlt[ScriptControls::ControlType::ShiftUp], 
    (DWORD)24, 
    "./Gears.ini"); 

Но тогда значение в ControlAlt является LPSTR, который позже дает осложнения при сравнении с соответствующей строкой. Есть ли способ не использовать буфер для этого?

ControlAlt определяются как std::string ControlAlt[SIZEOF_ControlType];

+0

Каков тип 'scriptControl-> ControlAlt [ScriptControls :: ControlType :: ShiftUp]'? – MikeCAT

+0

Вы понимаете разницу между указателем и массивом? – IInspectable

+0

ControlAlt [] - это строковый массив. Кроме того, как насчет указателей? scriptControl - это указатель, но ControlAlt - это просто массив строк. – ikt

ответ

1

GetPrivateProfileStringA требует буфера, чтобы написать классический C-стиль '\0' -завершённой строки в и std::string не таком буфер, хотя, как вы заметили, строка C-стиль может преобразуется в std::string.

В частности, GetPrivateProfileStringA ожидает char * (в терминах API Windows), указывающий на записываемый буфер и длину этого буфера. std::string не предоставляет этого - в лучшем случае он предоставляет аксессуар c_str(), который возвращает const char * (LPCSTR в терминах API Windows) - указатель на буфер только для чтения. const -ness данных буфера является довольно хорошим показателем того, что его изменение является плохой идеей и, скорее всего, приведет к неопределенному поведению.

C++ '98 говорит: «Программа не должна изменять ни одного из символов в этой последовательности». Тем не менее, реализация, соответствующая более новым стандартам, может быть более склонна мириться с бизнесом обезьян: resize(), чтобы сделать буфер достаточно большим, затем используйте &foo[0], чтобы получить char *, который не является const (или просто const_cast), защита от data()), пусть GetPrivateProfileStringA напишите в буфер, затем обрезайте std::string по адресу '\0', куда бы он ни приземлился. Это все равно не позволяет вам передать std::string непосредственно функции, ожидающей указателя буфера, хотя, поскольку они не одно и то же - это просто дает вам возможность избежать копирования лишнего времени из буфера.

+0

А, я понимаю, почему сейчас, спасибо за объяснение. Я думаю, что я буду придерживаться решения с буфером, потому что, когда мне захотелось пойти, похоже, это довольно опасно? По крайней мере, это то, что я понял из [этого] (http://stackoverflow.com/questions/2880248/stdstring-resize-and-stdstring-length). Полагаю, я могу просто повторно использовать этот буфер, не очистив его? Или я должен заполнить весь буфер до \ 0, чтобы убедиться, что он не содержит старые данные? – ikt

+0

Вы можете, конечно, повторно использовать его. Старые данные или другой мусор в буфере не должны теоретически быть проблемой, так как ничто за конечным '' \ 0'' не считается частью значения строки при конвертировании, а 'GetPrivateProfileString' всегда записывает завершающий' '\ 0 ' '. –

+0

Очистка буфера после этого рекомендуется, если он обрабатывает конфиденциальную информацию, но использует ['SecureZeroMemory'] (https://msdn.microsoft.com/en-us/library/windows/desktop/aa366877 (v = vs.85) .aspx) вместо 'memset',' bzero' или вашего собственного цикла. Это связано с тем, что если оптимизирующий компилятор замечает, что память освобождается и не читается после перезаписывания, она, скорее всего, решит, что переписывание является бессмысленным [«мертвым хранилищем»] (https://en.wikipedia.org/wiki/Dead_store) и удалите его. –