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 char
s. std::copy
is trying to copy-assign char
s 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
How to Swap Array-Elements to Transfer the Array from a Column-Like into a Row-Like Representation
Receiving Only Necessary Data with C++ Socket
How to Iterate Through Every Possible Combination of N Playing Cards
Why Is the Console Closing After I'Ve Included Cin.Get()
C++ Access Violation Reading Location 0Xcdcdcdcd Error on Calling a Function
Is Uninitialized Data Behavior Well Specified
Long VS. Int C/C++ - What's the Point
How to Declare Std::Unique_Ptr and What Is the Use of It
Read Func Interp of a Z3 Array from the Z3 Model
How to Store a Reference of a Singleton Class
Skipping Expected Characters Like Scanf() with Cin
How to Change Directshow Filter Properties C++
Why Does Rand() Return the Same Value Using Srand(Time(Null)) in This for Loop
Unary Plus (+) Against Literal String
Convert Hexadecimal String with Leading "0X" to Signed Short in C++
Vs: Unexpected Optimization Behavior with _Bitscanreverse64 Intrinsic