Самый чистый способ преобразовать ненулевую завершающую строку c в завершающую строку c

У меня есть некоторые унаследованные функции, которые возвращают ненулевые завершающие строки.

struct legacy {
    char a[4];  //not null terminated
    char b[20]; //not null terminated 
};

Я много раздаю эти массивы символов и мне нужен чистый способ конвертировать их в null terminated.

На данный момент это то, что я делал:

legacy foo;
std::string a(foo.a, sizeof(foo.a));
std::string b(foo.b, sizeof(foo.b));
bar(foo.a.c_str(), foo.b.c_str());

Есть ли более чистый способ, которым я могу использовать классы и шаблоны, чтобы уменьшить этот код до чего-то вроде...

legacy foo;
bar(make_null_terminated(foo.a), make_null_terminated(foo.b));

3 ответа

Решение

Нечто подобное должно сделать:

struct make_null_terminated {
    template <size_t sz>
    make_null_terminated(char (&lit)[sz]) : str(lit, sz) {}
    operator const char* () const { return str.c_str(); }
private:
    std::string str;
}

Это позволит вам использовать его так, как вы хотите.

РЕДАКТИРОВАТЬ После редактирования тегов я избавился от std::begin а также std::endl,

Вы можете просто:

std::string a(std::begin(foo.a), std::end(foo.a));

Самый чистый способ, который я могу придумать, - это использовать конструктор итератора std::string, указатель является своего рода итератором.

bar(std::string(std::begin(foo.a), std::end(foo.a)).c_str(),
    std::string(std::begin(foo.b), std::end(foo.b)).c_str()); 

что тут происходит?

  1. создайте строку, скопировав байты в foo.a и добавив конечный ноль (это инкапсулировано в std::string)

  2. То же самое для foo.b

  3. вызовите метод c_str() для временных строк, чтобы получить указатель на завершенную нулем c-строку внутри.

  4. панель вызовов

  5. уничтожить временные строки

Другие вопросы по тегам