How to Construct a Std::String from a Std::Vector<Char>

How to construct a std::string from a std::vector char ?

Well, the best way is to use the following constructor:

template<class InputIterator> string (InputIterator begin, InputIterator end);

which would lead to something like:

std::vector<char> v;
std::string str(v.begin(), v.end());

std::vector char to std::string

Writing a null character at the end of a character vector will not magically create an std::string. To create an actual std::string, use something like:

std::string s = std::string(readBuffer.begin(), readBuffer.end());

You don't need to explicitly append the null character to the string, the std::string constructor will do it for you.

Initialization of std::string from std::vector unsigned char causes error

std::string has several constructors, some of which can be used to construct the string from a std::vector, eg:

// using a char* pointer and a size...
std::string tmp2( reinterpret_cast<char*>(&some_vector[i]), j-i );

// using char* pointers as iterators...
std::string tmp2( &some_vector[i], &some_vector[j] );

// using vector iterators...
std::string tmp2( some_vector.begin()+i, some_vector.begin()+j );

Live Demo

How to construct a std::string from a std::vector string ?

C++03

std::string s;
for (std::vector<std::string>::const_iterator i = v.begin(); i != v.end(); ++i)
s += *i;
return s;

C++11 (the MSVC 2010 subset)

std::string s;
std::for_each(v.begin(), v.end(), [&](const std::string &piece){ s += piece; });
return s;

C++11

std::string s;
for (const auto &piece : v) s += piece;
return s;

Don't use std::accumulate for string concatenation, it is a classic Schlemiel the Painter's algorithm, even worse than the usual example using strcat in C. Without C++11 move semantics, it incurs two unnecessary copies of the accumulator for each element of the vector. Even with move semantics, it still incurs one unnecessary copy of the accumulator for each element.

The three examples above are O(n).

std::accumulate is O(n²) for strings.

You could make std::accumulate O(n) for strings by supplying a
custom functor:

std::string s = std::accumulate(v.begin(), v.end(), std::string{},
[](std::string &s, const std::string &piece) -> decltype(auto) { return s += piece; });

Note that s must be a reference to non-const, the lambda return type
must be a reference (hence decltype(auto)), and the body must use
+= not +.

C++20

In the current draft of what is expected to become C++20, the definition of std::accumulate has been altered to use std::move when appending to the accumulator, so from C++20 onwards, accumulate will be O(n) for strings, and can be used as a one-liner:

std::string s = std::accumulate(v.begin(), v.end(), std::string{});

How to choose between `std::vector char ` and `std::string`?

What aspects need to be considered when making such a choice?

What is the input data and what is it going to be used for in the future? That would be a big consideration.

If the input data is not going to be used as a string in the future, it may be clearer in the future if you used a container as specified in the comments e.g. std::vector<std::byte>.

Interpret a std::string as a std::vector of char_type?

If you make your template just for type const T& and use the begin(), end(), etc, functions which both vector and string share then your code will work with both types.

How to push strings (char by char) into a vector of strings

It seems you need something like the following

#include <iostream>
#include <string>
#include <vector>

int main()
{
std::vector<std::vector<std::string>> v( 2 );

v[0].emplace_back( 1, 'z' );
v[1].emplace_back( 1, 'r' );
v[0][0].append( 1, ' ' );
v[1][0].append( 1, ' ' );
v[0][0].append( 1, 'x' );
v[1][0].append( 1, 'g' );

for ( const auto &item : v )
{
std::cout << item[0] << '\n';
}

return 0;
}

The program output is

z x
r g

Otherwise declare the vector like

std::vector<std::vector<char>> v;

For example

#include <iostream>
#include <string>
#include <vector>

int main()
{
std::vector<std::vector<char>> v( 2 );

v[0].emplace_back( 'z' );
v[1].emplace_back( 'r' );
v[0].emplace_back( 'x' );
v[1].emplace_back( 'g' );

for ( const auto &line : v )
{
for ( const auto &item : line )
{
std::cout << item << ' ';
}
std::cout << '\n';
}

return 0;
}


Related Topics



Leave a reply



Submit