Musnazril Mustaq Khan
Musnazril Mustaq Khan

Reputation: 29

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

I have a std::string array which I need to convert to an unsigned char array so that I can use this array with third-party library which only accepts unsigned char array.

let say my array is

std::string array[3];
array[0] = "a105b";
array[1] = "c258e"
array[2] = "ff587";

I need to transfer this array into:

unsigned char cArray[3][5];

I can do hardwire the unsigned char as below:

unsigned char cArray[3][5] = {"a105b", "c258e", "ff587"};

but I was unable to find a way to do it using C++ code to transfer the data from the std::string array to the unsigned char array.

Upvotes: 2

Views: 853

Answers (3)

jxh
jxh

Reputation: 70492

You are not permitted to assign to a plain array. You cannot define your own assignment operator for the plain array, because C++ does not allow overload of the assignment operator except as a non-static member function of a class.

One workaround may be to define an overload for a shift operator, and give a similar syntax to an input stream.

template <unsigned N>
void operator >> (std::string s, unsigned char (&a)[N]) {
    auto n = (s.size() < N) ? s.size() + 1 : N;
    std::copy_n(s.c_str(), n, a);
}

/*...*/
    unsigned char cArray[3][5];
    array[0] >> cArray[0];
    array[1] >> cArray[1];
    array[2] >> cArray[2];

Upvotes: 0

Pepijn Kramer
Pepijn Kramer

Reputation: 13075

In code it could look like this:

#include <array>
#include <algorithm>
#include <cstring>
#include <string>

template<typename to_type, size_t buf_size, size_t number_of_strings>
void to_array(const std::array<std::string, number_of_strings>& input, 
              to_type (&output)[number_of_strings][buf_size])   
{
    for (std::size_t n = 0; n < number_of_strings; ++n)
    {
        const auto input_str = input[n].c_str();
        // for input string include trailing 0 on input so add one to length
        const auto copy_len = std::min(input[n].length()+1, buf_size); 
        std::memcpy(output[n], input_str, copy_len);
    }
}

int main()
{
    std::array<std::string, 3> input_array{ "a105b", "c258e", "ff587" };
    unsigned char c_array[3][6];
    to_array<unsigned char, 6>(input_array, c_array);

    return 0;
}

It showed me again that 'c' style arrays are not nice to work with. You can't return them from a function (like you can with std::array). So you have to pass the output array as parameter to the conversion function too.

Upvotes: 1

Ted Lyngmo
Ted Lyngmo

Reputation: 117851

You could make a function that loops through the two arrays and copies from one to the other.

Example:

#include <algorithm>
#include <iostream>
#include <string>

template<size_t R, size_t N>
void foo(const std::string(&src)[R], unsigned char(&dest)[R][N]) {

    // both `src` and `dest` must be arrays with `R` rows
    // `N` is how many unsigned chars each inner array in `dest` has

    for(size_t idx = 0; idx < R; ++idx) {
        // Copy from `src[idx]` to `dest[idx]`
        // Copy at most `N` chars but no more than the length of the string + 1
        // for the null terminator:
        std::copy_n(src[idx].c_str(), std::min(N, src[idx].size() + 1), dest[idx]);

        // Add the below line if the arrays in cArray are supposed to
        // be null terminated strings:
        //dest[idx][N - 1] = '\0';
    }
}

int main() {
    std::string array[3];

    array[0] = "a105b";
    array[1] = "c258e";
    array[2] = "ff587";

    unsigned char cArray[3][5];

    foo(array, cArray);
}

I can do hardwire the unsigned char as below

unsigned char cArray[3][5] = {"a105b", "c258e", "ff587"};

No, that's not valid in C++. You would have to make the inner array [6] in C++:

unsigned char cArray[3][6] = {"a105b", "c258e", "ff587"};

Upvotes: 2

Related Questions