How to Copy Std::String into Std::Vector<Char>

How to copy std::string into std::vectorchar?

std::vector has a constructor that takes two iterators. You can use that:

std::string str = "hello";
std::vector<char> data(str.begin(), str.end());

If you already have a vector and want to add the characters at the end, you need a back inserter:

std::string str = "hello";
std::vector<char> data = /* ... */;
std::copy(str.begin(), str.end(), std::back_inserter(data));

How to efficiently copy a std::string into a vector

If you really need a vector (e.g. because your C function modifies the string content), then the following should give you what you want, in one line:

std::vector<char> v(s.c_str(), s.c_str() + s.length() + 1);

Since c_str() returns a null-terminated string, you can just copy it whole into the vector.

However, I’m not actually sure how optimised this constructor is. I do know that std::copy is as optimised as it gets, so perhaps (measure!) the following is faster:

std::vector<char> v(s.length() + 1);
std::copy(s.c_str(), s.c_str() + s.length() + 1, v.begin());

If the C function doesn’t modify the string, just pass c_str() directly, and cast away const-ness. This is safe, as long as the C function only reads from the string.

Converting std::string to std::vectorchar

Nope, that's the way to do it, directly initializing the vector with the data from the string.

As @ildjarn points out in his comment, if for whatever reason your data buffer needs to be null-terminated, you need to explicitly add it with charvect.push_back('\0').

Also note, if you want to reuse the buffer, use the assign member function which takes iterators.

A more elegant way to copy std::string into a vectorchar

Construct a range with an iterator like this:

std::vector<char> temp(s.begin(), s.end());

How to convert a vectorstring to a vectorchar*

A faster way of doing this is

std::vector<const char*> charVec(strVec.size(),nullptr);
for (int i=0; i<strVec.size();i++) {
charVec[i]= strVec[i].c_str();
}

and then using the resulting vector. This will save a lot of time on memory allocation for large sets of data.

How to efficiently copy a std::vectorchar to a std::string

std::string s( &v[ 0 ] );

generates less than half the number of lines of assembly code in Visual C++ 2005 as

std::string s( v.begin(), v.end() );

convert vectorstring into char** C++

It is possible to solve the problem without copying out all the std::strings as long as the function does not modify the passed in char**. Otherwise I can see no alternative but to copy out everything into a new char**` structure (see second example).

void old_func(char** carray, size_t size)
{
for(size_t i = 0; i < size; ++i)
std::cout << carray[i] << '\n';
}

int main()
{
std::vector<std::string> strings {"one", "two", "three"};
std::vector<char*> cstrings;
cstrings.reserve(strings.size());

for(size_t i = 0; i < strings.size(); ++i)
cstrings.push_back(const_cast<char*>(strings[i].c_str()));

// Do not change any of the strings here as that will
// invalidate the new data structure that relies on
// the returned values from `c_str()`
//
// This is not an issue after C++11 as long as you don't
// increase the length of a string (as that may cause reallocation)

if(!cstrings.empty())
old_func(&cstrings[0], cstrings.size());
}

EXAMPLE 2: If the function must modify the passed in data:

void old_func(char** carray, size_t size)
{
for(size_t i = 0; i < size; ++i)
std::cout << carray[i] << '\n';
}

int main()
{
{
// pre C++11
std::vector<std::string> strings {"one", "two", "three"};

// guarantee contiguous, null terminated strings
std::vector<std::vector<char>> vstrings;

// pointers to rhose strings
std::vector<char*> cstrings;

vstrings.reserve(strings.size());
cstrings.reserve(strings.size());

for(size_t i = 0; i < strings.size(); ++i)
{
vstrings.emplace_back(strings[i].begin(), strings[i].end());
vstrings.back().push_back('\0');
cstrings.push_back(vstrings.back().data());
}

old_func(cstrings.data(), cstrings.size());
}

{
// post C++11
std::vector<std::string> strings {"one", "two", "three"};

std::vector<char*> cstrings;
cstrings.reserve(strings.size());

for(auto& s: strings)
cstrings.push_back(&s[0]);

old_func(cstrings.data(), cstrings.size());
}
}

NOTE: Revised to provide better code.

Why cant I use std::copy with std::string to another std::string?

The problem is r is an empty std::string, it contains no chars. std::copy is trying to copy-assign chars since r.begin(), which leads to UB.

You can make r containing 5 elements in advance.

std::string r(5, '\0');

Or

std::string r;
r.resize(5);

Or use std::back_inserter.

std::string r;
std::copy(s.rbegin(),s.rend(), std::back_inserter(r));


Related Topics



Leave a reply



Submit