I need add items to a vector who are created as std::vector<char*> Lista;
then i do:
char txt[10];
for (int x = 0; x <= 5; x )
{
sprintf(txt, "num%d", x);
printf("Add %s\n", txt);
Lista.push_back(txt);
}
but if i loop Lista items it show show:
for (int x = 0; x <= Lista.size() - 1; x )
{
printf("Items > [%d] %s\n", x, Lista[x]);
}
Items > [0] num5
Items > [1] num5
Items > [2] num5
Items > [3] num5
Items > [4] num5
Items > [5] num5
what i'm doing wrong? i need use char* not string.
CodePudding user response:
You're pushing five pointers to the same array into your vector, so when you print the contents of the array pointed to by each pointer they're all the same.
You only have a single array: txt
. Each time through your loop, you write new contents into that array and push a pointer to it into Lista
. So the first time through your loop you have this:
txt
┌─────┬─────┬─────┬─────┬──────┬─────┬─────┬─────┬─────┬─────┐
│ │ │ │ │ │ │ │ │ │ │
│ 'n' │ 'u' │ 'm' │ '0' │ '\0' │ ? │ ? │ ? │ ? │ ? │
│ │ │ │ │ │ │ │ │ │ │
└─────┴─────┴─────┴─────┴──────┴─────┴─────┴─────┴─────┴─────┘
▲
│
└───┐
│
┌───┼───┐
│ │ │
│ │ │
│ │
└───────┘
Lista
Then the second time through you modify txt
and add another pointer to it to Lista
, so you have this:
txt
┌─────┬─────┬─────┬─────┬──────┬─────┬─────┬─────┬─────┬─────┐
│ │ │ │ │ │ │ │ │ │ │
│ 'n' │ 'u' │ 'm' │ '1' │ '\0' │ ? │ ? │ ? │ ? │ ? │
│ │ │ │ │ │ │ │ │ │ │
└─────┴─────┴─────┴─────┴──────┴─────┴─────┴─────┴─────┴─────┘
▲ ▲
│ └─────────┐
└───┐ │
│ │
┌───┼───┬───┼───┐
│ │ │ │ │
│ │ │ │ │
│ │ │
└───────┴───────┘
Lista
And so on. Every element of Lista
contains a pointer to the same array, which you modify in each iteration of your loop. When you go back and print the contents of the array pointed to by each element of Lista
, they all point to the same array, so the same thing gets printed for each.
If you want to store different text in each element of Lista
, you will need to create a separate string for each. The easiest way to do that would be to change the type of Lista
to std::vector<std::string>
and let the std::string
class handle allocating space for each string:
for (int x = 0; x <= 5; x) {
std::string text = std::format(num{}, x); // Use std::ostringstream or sprintf if your compiler doesn't support std::format
Lista.push_back(text);
}
Then you can use std::string
's data
member function to get a pointer to the string's underlying char*
if you need to pass it to some interface that doesn't support std::string
. Keep in mind that the lifetime of the arrays pointed to by those pointers are tied to the lifetime of the std::string
object, so be careful not to use them after the std::string
(or the std::vector
that contains it) goes out of scope.
If you absolutely do not want to use std::string
to manage the lifetime of your arrays, you can allocate them yourself with new[]
, just remember that you must then remember to delete[]
them when you're done with them to avoid leaking memory:
for (int x = 0; x <= 5; x) {
char* txt = new char[5];
sprintf(txt, "num%d", x);
Lista.push_back(txt);
}
// ... stuff
for (char* txt : Lista) {
delete[] txt;
}
There are very few legitimate reasons to do this though. In 99.9% of cases you should use std::string
or some sort of smart pointer to manage your memory.
Note: Your program also exhibits undefined behavior because you access your array out of bounds with Lista[x 1] = txt
; you should get rid of that line.