преобразовать std :: string в LPCSTR с конечным или начальным '\ 0' - PullRequest
2 голосов
/ 08 октября 2010

Как я могу преобразовать std :: string в LPCSTR, сохранив символы \ 0?

Я хочу использовать результат в OPENFILENAME.lpstrFilter, который требует, чтобы фильтр содержал '\ 0' в качестве разделителей.

std :: string.c_str (), кажется, обрезает и обрезает '\ 0'

Заранее спасибо!

==========================

(Как правильно добавить комментарий к ответам, например ответное сообщение на форуме?)

Прочитав ваши комментарии, я дважды проверил этот фрагмент:

std::string filter = "Terrain Configuration (*.tcfg)\0*.tcfg\0\0";
const char* f1 = "Terrain Configuration (*.tcfg)\0*.tcfg\0\0";
const char* f2 = filter.c_str();
for(int i = 0; i < 50; i++)
{
 char c1 = *(f1 + i); // works
 char c2 = *(f2 + i); // doesn't work. beyond the first \0, it's garbage.
}

Я ошибаюсь, как работает c_str () или LPCSTR?

Ответы [ 4 ]

6 голосов
/ 08 октября 2010

C_STR не удаляет символы NUL.Ошибка, вероятно, в том, как вы строите STD :: string.

5 голосов
/ 08 октября 2010

Вообще говоря, std :: string правильно обрабатывает внедренные символы '\ 0'.

Тем не менее, при взаимодействии с const char * необходимо соблюдать особую осторожность.

В этом случае проблема уже возникает во время построения строки с:

std::string filter = "Terrain Configuration (*.tcfg)\0*.tcfg\0\0"; // wrong

Здесь вы создаете std :: string из const char *. Поскольку конструктор не знает, сколько символов использовать для построения std :: string, он останавливается на первом «\ 0».

Можно копировать символы один за другим, но есть и лучший способ: использовать конструктор, требующий двух итераторов для массива char, один с началом и один с концом:

const char filter_[] = "Terrain Configuration (*.tcfg)\0*.tcfg\0\0"; 
std::string filter(filter_, filter_ + sizeof(filter_));

Это выглядит ужасно, но, надеюсь, вы не будете делать это часто в своем коде.

Обновление: или с соответствующими определениями шаблонов begin () и end () (согласно комментарию Джеймса Канзе):

const char filter_[] = "Terrain Configuration (*.tcfg)\0*.tcfg\0\0"; 
std::string filter(begin(filter_), end(filter_));
2 голосов
/ 08 октября 2010

length() вашего string - это то, что вам нужно, чтобы убедиться, что все символы включены, при условии, что он был правильно сконструирован в первую очередь для включения встроенных \0 символов.

Для LPCSTR, действительного, пока cString находится в области действия:

#include <boost/scoped_array.hpp>
#include <string>
#include <algorithm>

string source("mystring");
boost::scoped_array<char> cString(new char[source.length() + 1]);

std::copy(source.begin(), source.end(), cString.get());
cString[source.length()] = 0;

LPCSTR rawStr = cString.get();

Без scoped_array:

#include <string>
#include <algorithm>

string source("mystring");
LPSTR rawStr = new char[source.length() + 1];

std::copy(source.begin(), source.end(), rawStr);
rawStr[source.length()] = 0;

// do the work here

delete[] rawStr;
* * 1013 EDIT: В вашем filter init конструктор string включает в себя данные только до первого \0 символа. Это имеет смысл - как иначе было бы не остановить копирование данных, когда все, что у них есть, это const char *? Попробуйте это с:
const char f3[] = "Terrain Configuration (*.tcfg)\0*.tcfg\0\0";
std::string filter(f3, sizeof(f3));
1 голос
/ 08 октября 2010

Это зависит от дальнейшего жизненного цикла std :: string.

Например, вы можете добавить нулевой терминал вручную:

std::string test("init");
test += '\0';

Это приводит к увеличению длины на единицу. Или просто создайте другой экземпляр std :: string с добавленным нулем

...