Home > OS >  vector push_back add new items
vector push_back add new items

Time:06-12

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.

  •  Tags:  
  • c
  • Related