Copying Non Null-Terminated Unsigned Char Array to Std::String

Copying non null-terminated unsigned char array to std::string

std::string has a constructor that takes a pair of iterators and unsigned char can be converted (in an implementation defined manner) to char so this works. There is no need for a reinterpret_cast.

unsigned char u_array[4] = { 'a', 's', 'd', 'f' };

#include <string>
#include <iostream>
#include <ostream>

int main()
{
std::string str( u_array, u_array + sizeof u_array / sizeof u_array[0] );
std::cout << str << std::endl;
return 0;
}

Of course an "array size" template function is more robust than the sizeof calculation.

Copy contents of non null terminated char array into another char array

You want to memcpy

memcpy(history[index].input, inputBuffer, sizeof(inputBuffer)*sizeof(inputBuffer[0]));

C++ conversion from unsigned char to std::string

To append a character you have to use the following overloaded method append

basic_string& append(size_type n, charT c);

For example

stroutput.append(1, characters[0]);
stroutput.append(1, characters[1]);

Otherwise use method push_back or the operator +=. For example

stroutput += characters[0];
stroutput += characters[1];

If you want to append the whole array or its part then you can write

stroutput.append( reinterpret_cast<char *>( characters ), sizeof( characters ) );

stroutput.append( reinterpret_cast<char *>( characters ), n );

where n is the number of characters of the array to append.

C++ non null terminated char array outputting

If you want to put exactly maxbytes bytes, use write method

stream.write(buffer, maxbytes);

If you can have less bytes in buffer, how do you know how many of them your buffer contains? If '\0' marks buffer end, you can write:

stream.write(buffer, std::find(buffer, buffer+maxbytes, '\0') - buffer);

Create std::string from std::span of unsigned char

You want:

auto ucharspan_to_stdstring(std::span<unsigned char const> input_array) -> std::string {
return std::string(input_array.begin(), input_array.end());
}

string, like other stand library containers, is constructible from an appropriate iterator pair - and this is such a pair. Since these are random access iterators, this will do a single allocation, etc.

Note that I changed from span<T> const& to span<T const>, for two reasons. First, you're not mutating the contents of the span, so the inner type needs to be const... similar to how you took a T const*, not a T*. Second, you should take spans by value because they're cheap to copy (unless you very specifically need the identity of the span, which you don't here).

It may be better to do a reinterpret_cast so that you can use the (char const*, size_t) constructor - this one ensures a single memcpy for the eventual write. But you'd have to time it to see if it's worthwhile.

string size after converting const unsigned char[] to std::string

case 1: input is not explicitly null-terminated, and likely those global arrays are placed in memory sequentially, so you get at least 48 bytes without zeros, finally it finds some zero 8 bytes ahead, so total is 56.

case 2: here you give it explicit length, and that's the correct way to do things in case of null terminator absence.

case 3: similar to case 1, but just starts from array 3, and takes same extra 8 bytes until null terminator found somewhere.

Solutions: either add null terminators (zero byte) or use variant with explicit length specification.

Are char arrays guaranteed to be null terminated?

It is allowed to initialize a char array with a string if the array is at least large enough to hold all of the characters in the string besides the null terminator.

This is detailed in section 6.7.9p14 of the C standard:

An array of character type may be initialized by a character string
literal or UTF−8 string literal, optionally enclosed in braces.
Successive bytes of the string literal (including the terminating null
character if there is room or if the array is of unknown size)
initialize the elements of the array.

However, this also means that you can't treat the array as a string since it's not null terminated. So as written, since you're not performing any string operations on b, your code is fine.

What you can't do is initialize with a string that's too long, i.e.:

char b[2] = "hello";

As this gives more initializers than can fit in the array and is a constraint violation. Section 6.7.9p2 states this as follows:

No initializer shall attempt to provide a value for an object not contained within the entity
being initialized.

If you were to declare and initialize the array like this:

char b[] = "hi"; 

Then b would be an array of size 3, which is large enough to hold the two characters in the string constant plus the terminating null byte, making b a string.

To summarize:

If the array has a fixed size:

  • If the string constant used to initialize it is shorter than the array, the array will contain the characters in the string with successive elements set to 0, so the array will contain a string.
  • If the array is exactly large enough to contain the elements of the string but not the null terminator, the array will contain the characters in the string without the null terminator, meaning the array is not a string.
  • If the string constant (not counting the null terminator) is longer than the array, this is a constraint violation which triggers undefined behavior

If the array does not have an explicit size, the array will be sized to hold the string constant plus the terminating null byte.

How do I convert an unsigned char array into a string in C?

A string (char array) in C is a sequencial sequence of chars terminated by a sentianal character (the null terminator: '\0')

This means that if you have a byte of the value 0x00 anywhere in your array, it has thusly terminated the "string" potentially before the end of the sequence. In your example if you converted your data array into a string the end of it would be the first element:

data[]{00, EB, 23, EC, FF, etc... };

Now if you want to make a string out of the values of the data in here, you can do that with sprintf(), for example:

unsigned char val = 00;
data[0] = val;
char dump[5] = {0};

sprintf(dump, "%02x", data[0]);

Now you have a string with the value "00" in it, You can make it fancer with something like:

sprintf(dump, "0x%02x", data[0]);

So that it has "0x00" to show it off as hex data.

You could loop something like this to give the full string... but keep in mind that the printable string needs to be at least 2x+1 the size of the data string (2x for ASCII and +1 for null), and you have to fill the new string in steps. Example:

unsigned char data[5] = {0x00, 0x12, 0xB3, 0xFF, 0xF0};
char printstr[11] = {00};

for(int x = 0; x < 5; x++)
sprintf(printstr+(x*2), "%02x", data[x]);
printstr[10] = '\0';

Now printstr has "0012b3fff0"

Put bytes from unsigned char array to std::string using memcpy() function

Since we're just constructing the string, there is a std::string constructor that takes two iterators:

template< class InputIt >
basic_string( InputIt first, InputIt last,
const Allocator& alloc = Allocator() );

which we can provide:

std::string newString(&bytes[startIndex], &bytes[startIndex] + length);

If we're not constructing the string and are instead assigning to an existing one, you should still prefer to use assign(). That is precisely what that function is for:

oldString.assign(&bytes[startIndex], &bytes[startIndex] + length);

But if you really insist on memcpy() for some reason, then you need to make sure that the string actually has sufficient data to be copied into. And then just copy into it using &str[0] as the destination address:

oldString.resize(length); // make sure we have enough space!
memcpy(&oldString[0], &bytes[startIndex], length);

Pre-C++11 there is technically no guarantee that strings are stored in memory contiguously, though in practice this was done anyway.



Related Topics



Leave a reply



Submit