Robert Kwiatkowski
Robert Kwiatkowski

Reputation: 461

How to convert std::array to std::string

I have a small trouble in converting std::array to std::string. I have something like that:

std::stringstream message;
message << 12345 << '\0' << '\0'
        << '\0' << "SOMETHING IMPORTANT" << '\0';

Next I'm using boost::asio::io::socket to send the message.str() My server is receiving the message and saving it to std::array<char, 1024>, but the problem is that I can't extract just the "SOMETHING IMPORTANT". I've tried to use std::array.begin() which returns only 12345, I also tried std::array.data() which returns my data + a lot of junk. I believe it's not a hard task, but I got stuck on it.

Upvotes: 2

Views: 1956

Answers (2)

Dc_Neo
Dc_Neo

Reputation: 131

well, recently i tried to pass some pic data in one process to another, I have tested them below: Suppose you have data like this std::array<char, 6*1024*1024> curImg = xxxx, you just need to do this: std::string picdata(std::begin(curImg.data()), std::end(curImg.data())); you will get your picdata, then you can convert it to CV::MAT , like this cv::Mat yuv422Img(height, width,CV_8UC2, (unsigned char*)picdata.c_str());.

Upvotes: 0

sehe
sehe

Reputation: 392893

What you are looking for is parsing.

In the literal sense of your question title, you would convert an array to string like this:

 std::array<char, 1024> buf;
 std::string value(buf.data(), bytes_transferred);

Where bytes_transferred is the known size of the data in the buffer (so you don't have to rely on buf.size(), which would always be 1024).

However, since you're basically parsing from a stream, you can use one:

 std::stringstream ss;
 ss.write(buf.data(), bytes_transferred);

And then you can use the stream as you would normally:

 unsigned n;
 ss >> n;

Or

 std::string important;
 std::getline(ss, 1024, '\0');

Real Parsing

To take it to another level you might use a proper parser to convert the access of your buffer. E.g. using Boost Spirit:

Live On Compiler Explorer

#include <array>
#include <boost/asio.hpp>
#include <boost/fusion/adapted.hpp>
#include <boost/spirit/home/x3.hpp>
#include <iomanip>
#include <sstream>
namespace x3 = boost::spirit::x3;

int main() {
    std::array<char, 1024> buf;
    size_t bytes_transferred;
    static constexpr char NUL = '\0';

    {
        std::stringstream message;
        message << 12345 << NUL << NUL << NUL << "SOMETHING IMPORTANT" << NUL
                << "trailing";

        // emulating the asio read:
        message.read(buf.data(), buf.size());
        bytes_transferred = message.gcount();
    }

    // now we can do the desired parsing:
    unsigned value;
    std::string important;

    auto bound_attributes = std::tie(value, important);
    auto f = begin(buf), l = f + bytes_transferred;

    if (x3::parse(f, l,
                  x3::uint_ >> NUL >> NUL >> NUL >> *~x3::char_(NUL) >> NUL,
                  bound_attributes)) {
        std::cout << "Sucessfully parsed message: " << value << " and "
                  << std::quoted(important) << "\n";
    } else {
        std::cout << "Failed to parse parse";
    }

    if (f != l) {
        auto bytes_remaining = std::distance(f,l);
        std::cout << "Remaining in buffer: " << bytes_remaining << " bytes\n";
        std::rotate(buf.begin(), f, l);      // put at front of buffer
        bytes_transferred = bytes_remaining; // just for example

        std::cout << "Buffer contents: "
                  << std::quoted(std::string(buf.begin(), bytes_remaining))
                  << "\n";
    }
}

Which prints

Sucessfully parsed message: 12345 and "SOMETHING IMPORTANT"
Remaining in buffer: 8 bytes
Buffer contents: "trailing"

Upvotes: 1

Related Questions