1

Is there an easy way to convert a std::vector<std::string> to a std::vector<unsigned char> (and back again to a std::vector<std::string>, without having to manually convert each string and add a delimiter, such as a comma?

5
  • Can you give an example? Commented Feb 22, 2012 at 5:46
  • Please clarify your question. The former is a sequence of strings and the latter is a single sequence of characters. You will need some sort of delimiter, I imagine. Before knowing how we need to understand what you want to do. An example would be of much help. Commented Feb 22, 2012 at 5:47
  • Basically, if I wanted to convert a std::string to a std::vector<unsigned char>, I could so something like std::vector<unsigned char> char_vec(myString.begin(), myString.end()), right? I was wondering if there was an easy way to convert from a std::vector<std::string> to a std::vector<unsigned char>` in a similar way. Commented Feb 22, 2012 at 5:48
  • So you really don't mean std::vector<std::vector<unsigned char> >? Commented Feb 22, 2012 at 8:58
  • This Q really needs clarification. A string wraps an array of chars, and a vector of chars wraps an array of chars, so a conversion is possible. But a vector of strings is acting as a 2 dimensional char array, and vector of chars is a 1 dimensional array; how can you possibly 'convert' one to the other? Commented Feb 22, 2012 at 12:18

4 Answers 4

1

The short answer is: no.

The way vectors and strings are implemented are as independant, heap-allocated arrays. Therefore, you could transform vector<string> into char** (a jagged array of arrays of char), and vector<unsigned char> into char* (an array of char) when thinking about internals. This turns your problem into: is there any way to concatenate arrays without having to copy them?

No. No there is not.

Sign up to request clarification or add additional context in comments.

Comments

0
std::vector<char> chars;
for (const std::string& s : strings)
{
    for (char c : s)
    {
        chars.push_back(c);
    }
    chars.push_back(',');
}

It's a little more clumsy without the new for loop syntax, but you get the idea.

1 Comment

C++ has iterators! You can write chars.insert(chars.end(), s.begin(), s.end());.
0

Boost Serialization should let you stuff a data structure into a sequence of unsigned char and reconstitute it again.

Comments

0

The first question is why, and what are you trying to do? What does the std::vector<std::string> represent, and what should the semantics of the conversion be? If you just want to concatenate, then the simplest solution would be something like:

std::vector<unsigned char> results;
for ( std::vector<std::string>::const_iterator iter = source.begin();
        iter != source.end();
        ++ iter ) {
    results.insert( results.end(), iter->begin(), iter->end() );
}

The implicit conversion of char to unsigned char will take care of the reslt.

If you need to insert some sort of separator or terminator for each string in the source, you can do that in the loop as well: for a terminator, just append it (push_back) after the insert; for a separator, I generally append it conditionally before the insert, e.g.:

std::vector<unsigned char> results;
for ( std::vector<std::string>::const_iterator iter = source.begin();
        iter != source.end();
        ++ iter ) {
    if ( iter != source.begin() ) {
        results.push_back( separator );
    }
    results.insert( results.end(), iter->begin(), iter->end() );
}

But the question is: why unsigned char? Presumably, because you are formatting into a buffer for some specific protocol. Is some additional formatting required? What is the format of a string in your protocol? (Typically, it will be either length + data, or '\0' terminated.) Does the protocol require some sort of alignment? (For XDR—one of the most widely used protocols—, you'd need something like:

std::vector<unsigned char> results;
for ( std::vector<std::string>::const_iterator iter = source.begin();
        iter != source.end();
        ++ iter ) {
    size_t len = iter->size();
    results.push_back( (len >> 24) & 0xFF );
    results.push_back( (len >> 16) & 0xFF );
    results.push_back( (len >>  8) & 0xFF );
    results.push_back( (len      ) & 0xFF );
    results.insert( results.end(), iter->begin(), iter->end() );
    while ( results.size() % 4 != 0 ) {
        results.push_back( '\0' );
    }
}

, for example.)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.