How do I print a vector of chars using fmt?

2.7k Views Asked by At

I have a const std::vector<char> - not null-terminated. I want to print it using the fmt library, without making a copy of the vector.

I would have hoped that specifying the precision would suffice, but the fmt documentation says that :

Note that a C string must be null-terminated even if precision is specified.

Well, mine isn't. Must I make a copy and pad it with \0, or is there something else I can do?

3

There are 3 best solutions below

2
einpoklum On BEST ANSWER

tl;dr: std::cout << fmt::format("{}", fmt::string_view{v.data(), v.size()});


So, fmt accepts two kinds of "strings":

  • C-style - just a pointer, must be null-terminated.
  • std::string-like - data + length.

Since C++17, C++ officially has the reference-type, std::string-like string view class, which could refer to your vector-of-chars. (without copying anything) - and fmt can print these. Problem is, you may not be in C++17. But fmt itself also has to face this problem internally, so it's actually got you covered - in whatever version of the standard you can get fmt itself to compile, in particular C++14:

const std::vector<char> v;
fmt::string_view sv(v.data(), v.size());
auto str = fmt::format("{}", sv);
std::cout << str;

Thanks @eerorika for making me think of string views.

0
eerorika On

If you could upgrade to C++17, then you could use a strig view argument instead of pointer to char:

const std::vector<char> v;
std::string_view sv(v.data(), v.size());
fmt::format("{}", sv);
1
rturrado On

What about using fmt::join?

Returns a view that formats range with elements separated by sep.

[Demo]

#include <fmt/ranges.h>
#include <vector>

int main() {
    std::vector<char> v{'a', 'b', 'c'};
    fmt::print("{}", fmt::join(v, ""));
}

// Outputs:
//
//   abc