How to elegantly initialize a <char *> vector with a string literal?
The problem arises from an exercise in C ++ Primer 5th Edition:
Write a program to assign items from a char * pointer list for C-style character strings to a string vector.
---------------- Another question ------------
First I try the following somewhat straightforward path:
vector<char *> vec = {"Hello", "World"}; vec[0][0] = 'h'; But compiling the code, I get a warning:
temp.cpp:11:43: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings] vector<char *> vec = {"Hello", "World"}; ^ And by running. /a.out, I get
Segmentation fault (core dumped) I think this is because I'm trying to write const char. So I try differently:
char s1[] = "Hello", s2[] = "World"; vector<char *> vec = {s1, s2}; vec[0][0] = 'h'; This time, everything is in order. But that seems a little tedious. Is there another elegant way to initialize a vector with a string literal?
Here is one way:
template <size_t N> void append_literal(std::vector<char*>& v, const char (&str)[N]) { char* p = new char[N]; memcpy(p, str, N); v.push_back(p); } std::vector<char*> v; append_literal(v, "Hello"); append_literal(v, "World"); Just remember:
void clear(std::vector<char*>& v) { for (auto p : v) delete[] p; } Although from the wording of the question, syntactically this is the same job anyway, if it was vector<const char*> , as if it were vector<char*> anyway (you don't change the source when you copy, so it doesn't matter , can you change the source), so I will stick to the exercise as if you just did:
std::vector<const char*> v{"Hello", "World!"}; I think the difference between char vs const char not a big deal in this task.
For the actual copy, use the pad constructor with iterator arguments:
vector<const char*> vc = {"hello","world"}; vector<string> vs(vc.begin(), vc.end()); See a working working example .
If the source needs editable characters, just use the second published version:
char s1[] = "Hello", s2[] = "World"; vector<char *> vec = {s1, s2}; Addition . The arguments main, argc and argv are a great example.
list of char * pointers to C-style character strings
See how argc and argv will be translated into a row vector .
You can try something like this:
// utility function to create char*'s template<std::size_t Size> char* make_rptr(const char (&s)[Size]) { char* rptr = new char[Size]; std::strcpy(rptr, s); return rptr; } int main() { // initialize vector std::vector<char*> v {make_rptr("hello"), make_rptr("world")}; // use vector for(auto&& s: v) std::cout << s << '\n'; // ... // remember to dealloacte for(auto&& s: v) delete[] s; }