Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copy null terminated char array to std::string respecting buffer length

Maybe it's just the lack of coffee, but I'm trying to create a std::string from a null-terminated char array with a known maximum length and I don't know, how to do it.

auto s = std::string(buffer, sizeof(buffer));

.. was my favorite candidate but since C++ strings are not null-terminated this command will copy sizeof(buffer) bytes regardless of any contained '\0'.

auto s = std::string(buffer);

.. copies from buffer until \0 is found. This is almost what I want but I can't trust the receive buffer so I'd like to provide a maximum length.

Of course, I can now integrate strnlen() like this:

auto s = std::string(buffer, strnlen(buffer, sizeof(buffer)));

But that seems dirty - it traverses the buffer twice and I have to deal with C-artifacts like string.h and strnlen() (and it's ugly).

How would I do this in modern C++?

like image 662
frans Avatar asked May 04 '16 08:05

frans


People also ask

Does std :: string size include null terminator?

Actually, as of C++11 std::string is guaranteed to be null terminated. Specifically, s[s. size()] will always be '\0' .

How do you make a char array null-terminated?

A C-style string is a null (denoted by \0 ) terminated char array. The null occurs after the last character of the string. For an initialization using double quotes, "...", the compiler will insert the null .

Does char array size include null terminator?

If you will use the array as a string, it must include the terminating null character. The terminating null character is part of the array and must be included in its size.

Is char * Always null-terminated?

char arrays are not automatically NULL terminated, only string literals, e.g. char *myArr = "string literal"; , and some string char pointers returned from stdlib string methods.


Video Answer


2 Answers

Something like this could work in a single pass..

auto eos = false;
std::string s;
std::copy_if(buffer, buffer + sizeof(buffer), std::back_inserter(s),
  [&eos](auto v) {
    if (!eos) {
      if (v) {
        return true;
      }
      eos = true;
    }
    return false;
  });
like image 26
Nim Avatar answered Sep 27 '22 17:09

Nim


const char* end = std::find(buffer, buffer + sizeof(buffer), '\0');
std::string s(buffer, end);
like image 92
John Zwinck Avatar answered Sep 27 '22 17:09

John Zwinck