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 span
s 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 char
s 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
Sqlite3_Exec() Callback Function Clarification
Gsl::Not_Null<T*> VS. Std::Reference_Wrapper<T> VS. T&
"Proper" Way to Store Binary Data with C++/Stl
How to Use New Std::Byte Type in Places Where Old-Style Unsigned Char Is Needed
How to Add Element by Element of Two Stl Vectors
How Do Static Variables in Lambda Function Objects Work
Disabling G++'s Return-Value Optimisation
Is It True That There Is No Need to Learn C Because C++ Contains Everything
Llvm Ir Back to Human-Readable Source Language
C++ Implicit Conversion (Signed + Unsigned)
What Is Activation Record in the Context of C and C++
How to Use the _Attribute_((Visibility("Default")))
Ad Hoc Polymorphism and Heterogeneous Containers with Value Semantics
How to Execute a Piece of Code Only Once
Is 'Bool' a Basic Datatype in C++
How to Speed Up Matrix Multiplication in C++
Manual for Cross-Compiling a C++ Application from Linux to Windows